Mechanisms

mechanisms/svm

github.com/x402-foundation/x402/go/v2/mechanisms/svm

import "github.com/x402-foundation/x402/go/v2/mechanisms/svm"

Constants

Source: mechanisms/svm/constants.go:11

const (
	// SchemeExact is the scheme identifier for exact payments
	SchemeExact = "exact"

	// DefaultDecimals is the default token decimals for USDC
	DefaultDecimals = 6

	// DefaultComputeUnitPriceMicrolamports is the default compute unit price in microlamports
	DefaultComputeUnitPriceMicrolamports = 1

	// MaxComputeUnitPriceMicrolamports is the maximum compute unit price in microlamports (facilitator validation limit)
	// 5 lamports = 5,000,000 microlamports
	MaxComputeUnitPriceMicrolamports = 5_000_000

	// DefaultComputeUnitLimit is the default compute unit limit for transactions
	// Set to 20000 to accommodate: transfer (~6200 CUs) + memo (~8500 CUs without signer) + budget instructions (~300 CUs) + headroom
	DefaultComputeUnitLimit uint32 = 20000

	// MaxMemoBytes is the maximum byte length for seller-defined memo data (extra.memo)
	MaxMemoBytes = 256

	// LighthouseProgramAddress is the Phantom/Solflare Lighthouse program address
	// Phantom and Solflare wallets inject Lighthouse instructions for user protection on mainnet transactions.
	// - Phantom adds 1 Lighthouse instruction (4th instruction)
	// - Solflare adds 2 Lighthouse instructions (4th and 5th instructions)
	// We allow these as optional instructions to support these wallets.
	// See: https://github.com/x402-foundation/x402/issues/828
	LighthouseProgramAddress = "L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95"

	// MemoProgramAddress is the SPL Memo program address
	MemoProgramAddress = "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"

	// DefaultCommitment is the default commitment level for transactions
	DefaultCommitment = rpc.CommitmentConfirmed

	// MaxConfirmAttempts is the maximum number of confirmation attempts
	MaxConfirmAttempts = 30

	// ConfirmRetryDelay is the base delay between confirmation attempts
	ConfirmRetryDelay = 1 * time.Second

	// SettlementTTL is how long a transaction is held in the duplicate settlement cache.
	// Covers the Solana blockhash lifetime (~60-90s) with margin.
	SettlementTTL = 120 * time.Second

	// CAIP-2 network identifiers (V2)
	SolanaMainnetCAIP2 = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
	SolanaDevnetCAIP2  = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"
	SolanaTestnetCAIP2 = "solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z"

	// V1 network names
	SolanaMainnetV1 = "solana"
	SolanaDevnetV1  = "solana-devnet"
	SolanaTestnetV1 = "solana-testnet"

	// USDC mint addresses
	USDCMainnetAddress = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
	USDCDevnetAddress  = "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU"
	USDCTestnetAddress = "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU" // Same as devnet
)

Variables

Source: mechanisms/svm/constants.go:73

var (
	// NetworkConfigs maps CAIP-2 identifiers to network configurations
	// See DEFAULT_ASSETS.md for guidelines on adding new networks
	NetworkConfigs = map[string]NetworkConfig{
		SolanaMainnetCAIP2: {
			Name:   "Solana Mainnet",
			CAIP2:  SolanaMainnetCAIP2,
			RPCURL: "https://api.mainnet-beta.solana.com",
			DefaultAsset: AssetInfo{
				Address:  USDCMainnetAddress,
				Symbol:   "USDC",
				Decimals: DefaultDecimals,
			},
		},
		SolanaDevnetCAIP2: {
			Name:   "Solana Devnet",
			CAIP2:  SolanaDevnetCAIP2,
			RPCURL: "https://api.devnet.solana.com",
			DefaultAsset: AssetInfo{
				Address:  USDCDevnetAddress,
				Symbol:   "USDC",
				Decimals: DefaultDecimals,
			},
		},
		SolanaTestnetCAIP2: {
			Name:   "Solana Testnet",
			CAIP2:  SolanaTestnetCAIP2,
			RPCURL: "https://api.testnet.solana.com",
			DefaultAsset: AssetInfo{
				Address:  USDCTestnetAddress,
				Symbol:   "USDC",
				Decimals: DefaultDecimals,
			},
		},
	}

	// V1ToV2NetworkMap maps V1 network names to CAIP-2 identifiers
	V1ToV2NetworkMap = map[string]string{
		SolanaMainnetV1: SolanaMainnetCAIP2,
		SolanaDevnetV1:  SolanaDevnetCAIP2,
		SolanaTestnetV1: SolanaTestnetCAIP2,
	}
)

Source: mechanisms/svm/mint_cache.go:16

var (
	ErrMintAccountNotFound     = errors.New("mint account not found")
	ErrUnknownMintTokenProgram = errors.New("unknown token program")
	ErrFailedToDecodeMintData  = errors.New("failed to decode mint data")
)

Functions

func DecodeTransaction(base64Tx string) (*solana.Transaction, error)

Source: mechanisms/svm/utils.go:173

DecodeTransaction decodes a base64 encoded Solana transaction

func EncodeTransaction(tx *solana.Transaction) (string, error)

Source: mechanisms/svm/utils.go:227

EncodeTransaction encodes a Solana transaction to base64

func FormatAmount(amount uint64, decimals int) string

Source: mechanisms/svm/utils.go:136

FormatAmount converts an amount in smallest units to a decimal string

func GetAssetInfo(network string, assetSymbolOrAddress string) (*AssetInfo, error)

Source: mechanisms/svm/utils.go:58

GetAssetInfo returns information about an asset on a network

func GetNetworkConfig(network string) (*NetworkConfig, error)

Source: mechanisms/svm/utils.go:42

GetNetworkConfig returns the configuration for a network

func GetTokenPayerFromTransaction(tx *solana.Transaction) (string, error)

Source: mechanisms/svm/utils.go:191

GetTokenPayerFromTransaction extracts the token payer (owner) address from a transaction This looks for the TransferChecked instruction and returns the owner/authority address

func IsValidNetwork(network string) bool

Source: mechanisms/svm/types.go:111

IsValidNetwork checks if the network is supported for Solana

func MessageHash(tx *solana.Transaction) (string, error)

Source: mechanisms/svm/utils.go:163

MessageHash returns a stable, immutable cache key for a transaction by hashing its message bytes. The fee-payer signature (slot 0) is mutable - the facilitator overwrites it before broadcast - so keying on the full wire bytes would let an attacker bypass deduplication by randomizing those bytes. The message is what every signer commits to, so its hash uniquely and immutably identifies a payment.

func NewMintMetadataCache() *MintMetadataCache

Source: mechanisms/svm/mint_cache.go:38

func NewSettlementCache() *SettlementCache

Source: mechanisms/svm/settlement_cache.go:18

NewSettlementCache creates a new, empty SettlementCache.

func NormalizeNetwork(network string) (string, error)

Source: mechanisms/svm/utils.go:23

NormalizeNetwork converts V1 network names to CAIP-2 format

func ParseAmount(amount string, decimals int) (uint64, error)

Source: mechanisms/svm/utils.go:95

ParseAmount converts a decimal string amount to token smallest units

func PayloadFromMap(data map[string]interface{}) (*ExactSvmPayload, error)

Source: mechanisms/svm/types.go:91

PayloadFromMap creates an ExactSvmPayload from a map

func ValidateSolanaAddress(address string) bool

Source: mechanisms/svm/utils.go:84

ValidateSolanaAddress checks if a string is a valid Solana address

Types

type AssetInfo

Source: mechanisms/svm/types.go:58

AssetInfo contains information about a SPL token

type AssetInfo struct {
	Address  string // Mint address
	Symbol   string // Token symbol (e.g., "USDC")
	Decimals int    // Token decimals
}
Fields
  • Address string

    Mint address

  • Symbol string

    Token symbol (e.g., "USDC")

  • Decimals int

    Token decimals

type ClientConfig

Source: mechanisms/svm/types.go:74

ClientConfig contains optional client configuration

type ClientConfig struct {
	RPCURL string // Custom RPC URL
}
Fields
  • RPCURL string

    Custom RPC URL

type ClientSvmSigner

Source: mechanisms/svm/types.go:23

ClientSvmSigner defines client-side operations

type ClientSvmSigner interface {
	// Address returns the signer's Solana address (base58)
	Address() solana.PublicKey

	// SignTransaction signs a Solana transaction
	SignTransaction(ctx context.Context, tx *solana.Transaction) error
}
Methods
  • Address func() solana.PublicKey

    Address returns the signer's Solana address (base58)

  • SignTransaction func(ctx context.Context, tx *solana.Transaction) error

    SignTransaction signs a Solana transaction

type ExactSvmPayload

Source: mechanisms/svm/types.go:12

ExactSvmPayload represents a SVM (Solana) payment payload

type ExactSvmPayload struct {
	Transaction string `json:"transaction"` // Base64 encoded Solana transaction
}
Fields
  • Transaction string `json:"transaction"`

    Base64 encoded Solana transaction

func ToMap() map[string]interface{}

Source: mechanisms/svm/types.go:84

ToMap converts an ExactSvmPayload to a map for JSON marshaling

type ExactSvmPayloadV1

Source: mechanisms/svm/types.go:17

ExactSvmPayloadV1 - alias for v1 compatibility

type ExactSvmPayloadV1 = ExactSvmPayload

type ExactSvmPayloadV2

Source: mechanisms/svm/types.go:20

ExactSvmPayloadV2 - alias for v2 (currently identical, reserved for future)

type ExactSvmPayloadV2 = ExactSvmPayload

type FacilitatorSvmSigner

Source: mechanisms/svm/types.go:34

FacilitatorSvmSigner defines facilitator operations for SVM Supports multiple signers for load balancing, key rotation, and high availability All implementation details (RPC clients, key management) are hidden

type FacilitatorSvmSigner interface {
	// GetAddresses returns all addresses this facilitator can use as fee payers for a network
	// Enables dynamic address selection for load balancing and key rotation
	GetAddresses(ctx context.Context, network string) []solana.PublicKey

	// SignTransaction signs a transaction with the signer matching feePayer
	// Transaction is modified in-place to add the facilitator's signature
	// Returns error if no signer exists for feePayer or signing fails
	SignTransaction(ctx context.Context, tx *solana.Transaction, feePayer solana.PublicKey, network string) error

	// SimulateTransaction simulates a signed transaction to verify it would succeed
	// Returns error if simulation fails
	SimulateTransaction(ctx context.Context, tx *solana.Transaction, network string) error

	// SendTransaction sends a signed transaction to the network
	// Returns transaction signature or error if send fails
	SendTransaction(ctx context.Context, tx *solana.Transaction, network string) (solana.Signature, error)

	// ConfirmTransaction waits for transaction confirmation
	// Returns error if confirmation fails or times out
	ConfirmTransaction(ctx context.Context, signature solana.Signature, network string) error
}
Methods
  • GetAddresses func(ctx context.Context, network string) []solana.PublicKey

    GetAddresses returns all addresses this facilitator can use as fee payers for a network Enables dynamic address selection for load balancing and key rotation

  • SignTransaction func(ctx context.Context, tx *solana.Transaction, feePayer solana.PublicKey, network string) error

    SignTransaction signs a transaction with the signer matching feePayer Transaction is modified in-place to add the facilitator's signature Returns error if no signer exists for feePayer or signing fails

  • SimulateTransaction func(ctx context.Context, tx *solana.Transaction, network string) error

    SimulateTransaction simulates a signed transaction to verify it would succeed Returns error if simulation fails

  • SendTransaction func(ctx context.Context, tx *solana.Transaction, network string) (solana.Signature, error)

    SendTransaction sends a signed transaction to the network Returns transaction signature or error if send fails

  • ConfirmTransaction func(ctx context.Context, signature solana.Signature, network string) error

    ConfirmTransaction waits for transaction confirmation Returns error if confirmation fails or times out

type MintMetadata

Source: mechanisms/svm/mint_cache.go:22

MintMetadata contains the stable fields clients need to build SPL transfers.

type MintMetadata struct {
	TokenProgramID solana.PublicKey
	Decimals       uint8
}
Fields
  • TokenProgramID solana.PublicKey
  • Decimals uint8

type MintMetadataCache

Source: mechanisms/svm/mint_cache.go:28

MintMetadataCache caches mint owner and decimals for one client instance.

type MintMetadataCache struct {
	// contains filtered or unexported fields
}

func GetOrFetch( ctx context.Context, rpcClient *rpc.Client, network string, mint solana.PublicKey, ) (MintMetadata, error)

Source: mechanisms/svm/mint_cache.go:44

type NetworkConfig

Source: mechanisms/svm/types.go:66

NetworkConfig contains network-specific configuration See DEFAULT_ASSETS.md for guidelines on adding new chains

type NetworkConfig struct {
	Name         string    // Network name
	CAIP2        string    // CAIP-2 identifier
	RPCURL       string    // Default RPC URL
	DefaultAsset AssetInfo // Default stablecoin
}
Fields
  • Name string

    Network name

  • CAIP2 string

    CAIP-2 identifier

  • RPCURL string

    Default RPC URL

  • DefaultAsset AssetInfo

    Default stablecoin

type ServerConfig

Source: mechanisms/svm/types.go:79

ServerConfig contains optional server configuration.

type ServerConfig struct {
	RPCURL string // Custom RPC URL for challenge enrichment
}
Fields
  • RPCURL string

    Custom RPC URL for challenge enrichment

type SettlementCache

Source: mechanisms/svm/settlement_cache.go:12

SettlementCache is a thread-safe in-memory cache for deduplicating concurrent settlement requests. A single instance should be shared across V1 and V2 facilitator scheme instances so that a transaction submitted through one protocol version is also blocked on the other.

type SettlementCache struct {
	// contains filtered or unexported fields
}

func Entries() map[string]time.Time

Source: mechanisms/svm/settlement_cache.go:41

Entries returns a snapshot of the underlying map - use only in tests.

func IsDuplicate(key string) bool

Source: mechanisms/svm/settlement_cache.go:27

IsDuplicate returns true if key is already pending settlement (duplicate). Otherwise it records the key as newly pending and returns false. Callers should reject the settlement when this returns true.

func Mu() *sync.Mutex

Source: mechanisms/svm/settlement_cache.go:46

Mu returns the mutex - use only in tests.