Skip to content

feat(x402): register @x402/svm alongside @x402/evm in Agents MCP integration - #3

Merged
twzrd-sol merged 1 commit into
mainfrom
spike/svm-scheme-1863-clean
Aug 12, 2026
Merged

twzrd-sol merged 1 commit into
mainfrom
spike/svm-scheme-1863-clean

Conversation

@twzrd-sol

Copy link
Copy Markdown
Owner

Summary

Test plan

  • 38/38 tests pass (33 existing unchanged + 5 new: server registers both schemes, svmRpcUrl passthrough, client branches to SVM for an SVM-shaped signer, client branches to EVM for an EVM-shaped signer, regression test for the TransactionSendingSigner-only shape)
  • tsc --noEmit clean on packages/agents/src/mcp/x402.ts
  • Branched directly off main (single commit, no unrelated changes)

Context

This is scoped for cloudflare#1863's own framing — same fix shape as its proposed Stellar patch, applied to Solana. Not yet opened against cloudflare/agents upstream; parking here first as a reviewable, durable artifact.

Related upstream issues: cloudflare#1863, cloudflare#1989 (integration deprecation risk), cloudflare#793 (v2 migration explicitly named future @x402/svm support), cloudflare#596 (closed NOT_PLANNED — different framing, not reopened here).

…gration

Fixes the gap in cloudflare#1863: docs claim Solana support, but withX402()/withX402Client()
only ever registered the EVM exact scheme. @x402/svm@2.21.0 mirrors @x402/evm's
export shape exactly (registerExactSvmScheme on both exact/server and
exact/client), so this follows cloudflare#1863's own Stellar pattern verbatim:

- Server: registerServerSvmScheme() registers additively alongside the existing
  EVM registration — inert for EVM-network configs, since scheme selection
  happens per-request against the requested network.
- Client: isSvmSigner() branches between SVM and EVM client registration,
  using @solana/kit's own isTransactionSigner() as the discriminator rather
  than a hand-rolled method check — @x402/svm doesn't currently export an
  isClientSvmSigner the way @x402/stellar exports isClientStellarSigner for
  the same purpose (cloudflare#1863), and @solana/kit's TransactionSigner is itself a
  union of three shapes (TransactionModifyingSigner, TransactionPartialSigner,
  TransactionSendingSigner). An earlier draft of this guard checked only
  signTransactions/modifyAndSignTransactions and missed the third
  (signAndSendTransactions-only) shape, which would have silently fallen
  through to the EVM branch and failed at runtime the first time it tried to
  sign. Using the canonical isTransactionSigner() closes that gap correctly
  instead of hand-checking method names.
- Types: X402Config.recipient and X402ClientConfig.account both widen from
  EVM-only literals to unions, matching cloudflare#1863's proposed non-breaking approach.
- New X402Config.svmRpcUrl (optional) lets the challenge embed a recent
  blockhash server-side, same as the x402-hono Solana path already does.

Bumped @x402/core and @x402/evm devDeps 2.17.0 -> 2.21.0 to match @x402/svm's
peer requirement — the version skew otherwise produces structurally-
incompatible private-field types between two @x402/core copies (verified via
tsc, not assumed).

38/38 tests pass (33 existing unchanged + 5 new: server registers both
schemes, svmRpcUrl passthrough, client branches to SVM for an SVM-shaped
signer, client branches to EVM for an EVM-shaped signer, and a regression
test for the TransactionSendingSigner shape the method-name-only guard
would have missed). tsc --noEmit clean on this file.

Unlike the Stellar patch in cloudflare#1863, no test-mock scaffolding was needed:
@x402/svm ships the same registerExactSvmScheme convenience-function shape
as @x402/evm, so the existing no-op-function mock pattern extends directly.

Branched directly from cloudflare/agents:main equivalent (single commit,
no unrelated product-lane commits) — CF-mergeable topology.

Local spike only — not opened upstream. See cloudflare#1863, cloudflare#1989 (integration
deprecation risk), cloudflare#793 (v2 migration explicitly named future @x402/svm
support), cloudflare#596 (closed NOT_PLANNED — different framing, not reopened).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant