venice_ai.auth.x402_solana
x402 Solana ("exact" scheme, SVM) settlement for Venice's /x402/top-up
endpoint.
Venice's live 402 challenge (x402Version 2) advertises a Solana payment
requirement whose network is the bare string "solana" (NOT a
CAIP-2 id). The settlement envelope mirrors the EVM one in
:mod:venice_ai.auth.x402 but carries a base64-encoded, partially-signed
Solana :class:~solders.transaction.VersionedTransaction instead of an
EIP-712 authorization:
{ "x402Version": 2, "scheme": "exact", "network": "solana",
"payload": { "transaction": "<base64 serialized VersionedTransaction>" } }
The transaction implements the upstream x402 "exact" scheme for SVM:
* message ``payer`` = the requirement's ``extra.feePayer`` (the facilitator
pays gas; the client only signs the SPL transfer it authorizes), and
* exactly four instructions: ComputeBudget set-unit-limit, ComputeBudget
set-unit-price, SPL ``TransferChecked``, SPL Memo.
The client signs only its own slot; the feePayer slot (index 0) is left as a
64-zero-byte placeholder for the facilitator to fill in before submission.
Usage:
from venice_ai.auth.x402_solana import SolanaX402Auth
auth = SolanaX402Auth(private_key="<base58 secret>")
# auth.wallet_address — base58 pubkey derived from the key
header = auth.build_payment_header(
requirement=req, # the network=="solana" accepts entry
recent_blockhash=blockhash,
mint_decimals=6,
token_program="Tokenkeg...",
)
This module is optional and requires ``pip install venice-ai[x402-solana]``.
SolanaX402Auth Objects
class SolanaX402Auth()
Builds base64 X-402-Payment envelopes for Venice's Solana x402 flow.
Arguments:
private_key: A base58-encoded Solana secret key (the 64-byte keypair, as produced bysolana-keygen/ wallet exports). Never share or commit this.
SolanaX402Auth.wallet_address
@property
def wallet_address() -> str
Base58 public key (wallet address) derived from the secret key.
SolanaX402Auth.build_header
def build_header(*,
nonce: str | None = None,
now: datetime | None = None) -> str
Build the base64-encoded X-Sign-In-With-X (SIGN-IN-WITH-X) header value.
Signs a Solana SIWX (Sign-In-With-X) message with the wallet's Ed25519
key so wallet-authenticated reads (client.x402.balance /
transactions) work for Solana, mirroring
Arguments:
nonce: Optional 16-character hex nonce; a random one is generated if omitted.now: Override theissuedAttimestamp (UTC), for testing.
SolanaX402Auth.build_payment_header
def build_payment_header(*,
requirement: dict[str, Any],
recent_blockhash: str,
mint_decimals: int,
token_program: str,
max_amount_units: int | None = None) -> str
Build the base64 X-402-Payment v2 envelope (PURE, no I/O).
Constructs the four-instruction Solana VersionedTransaction for the
x402 "exact" SVM scheme, partial-signs the client's slot, and base64
encodes the v2 payment envelope. Performs no network I/O — the caller
supplies recent_blockhash, mint_decimals and token_program
(fetched live via :func:fetch_solana_tx_context).
Validates network/asset/amount BEFORE signing — refuses to
sign payloads that deviate from expectations. This is a security
control: a misbehaving server could otherwise ask you to authorize a
transfer to an attacker-controlled address.
Arguments:
requirement: A singleacceptsentry withnetwork == "solana"(bare string, echoed back exactly). Expected keys:asset(mint),amount(string base units),payTo(recipient owner), andextra.feePayer(the facilitator). Optionalextra.memo(UTF-8, <=256 bytes) — a random 16-byte hex memo is generated when absent. Optionalscheme(defaults"exact").recent_blockhash: Base58 recent blockhash for the message.mint_decimals: The mint's decimals (byte 44 of the mint account data), encoded into theTransferCheckedinstruction.token_program: The mint's owning token program id (base58).max_amount_units: Optional cap in token base units; refuses to sign ifint(requirement["amount"])exceeds it.Nonedisables the cap (not recommended in production).
Raises:
ValueError: On validation mismatch (network/asset/amount) or a malformed requirement.
Returns:
Base64-encoded v2 X-402-Payment envelope string.
fetch_solana_tx_context
async def fetch_solana_tx_context(rpc_url: str, mint: str, *,
http: Any) -> tuple[str, int, str]
Fetch the live transaction context needed to build a Solana payment.
Performs two raw JSON-RPC calls over the supplied aiohttp session:
getLatestBlockhash→ recent blockhash (base58 str) for the message.getAccountInfo(mint, {encoding:"base64"})→ the mint account'sowner(the token program id) anddata;decimalsis byte 44 of the base64-decoded mint account data.
Arguments:
rpc_url: Solana JSON-RPC endpoint.mint: The mint (asset) base58 address from the 402 requirement.http: Anaiohttp.ClientSessionto issue the POSTs with.
Raises:
RuntimeError: If the RPC returns an error or unexpected shape.
Returns:
(recent_blockhash, mint_decimals, token_program).