-
Notifications
You must be signed in to change notification settings - Fork 1.4k
feat(svm): allow injecting RPC client into ExactSvmScheme #1832
Description
ExactSvmScheme creates its RPC client internally inside createPaymentPayload(), with no way to provide a custom one. This forces anyone who needs to customize the transport layer (failover, retry, rate-limit handling, custom RPC endpoint priorities) to reimplement the entire class.
Use case
We run an MCP server that handles concurrent Solana payments. Public Solana RPCs rate-limit at 100 req/10s (api.mainnet.solana.com), so under load we need a failover transport that tries a second RPC on 429. @solana/kit supports this via transport composition (createSolanaRpcFromTransport), but there's no way to pass a custom RPC client into ExactSvmScheme.
We ended up reimplementing the full class (~100 lines of transaction building, compute budget, memo instruction, signing) just to change how the RPC client is created:
https://github.com/cascade-protocol/x402-proxy/blob/main/packages/x402-proxy/src/lib/optimized-svm-scheme.ts
Suggestion
Accept an optional RPC client in the constructor, falling back to the current behavior when not provided:
constructor(
signer: TransactionSigner,
config?: { rpcUrl?: string; rpc?: SolanaRpc }
) {
this.rpc = config?.rpc ?? createSolanaRpc(mainnet(config?.rpcUrl ?? MAINNET_RPC_URL));
}This would let consumers compose their own transport (failover, retry, throttle, custom auth) without forking the scheme implementation.
A secondary benefit: moving RPC creation from createPaymentPayload() to the constructor also enables @solana/kit's built-in request coalescing, which merges identical RPC calls (like getLatestBlockhash) across concurrent payments into a single network request.
Environment
@x402/svm2.8.0@solana/kit6.5.0