chore(e2e): make the harness portable to any EVM chain in DEFAULT_STABLECOINS#2250
Open
ryanRfox wants to merge 1 commit intox402-foundation:mainfrom
Open
chore(e2e): make the harness portable to any EVM chain in DEFAULT_STABLECOINS#2250ryanRfox wants to merge 1 commit intox402-foundation:mainfrom
ryanRfox wants to merge 1 commit intox402-foundation:mainfrom
Conversation
|
@ryanRfox is attempting to deploy a commit to the Coinbase Team on Vercel. A member of the Team first needs to authorize it. |
0387732 to
26c331b
Compare
4 tasks
…BLECOINS
Makes the e2e harness portable to any EVM chain in the SDK's
DEFAULT_STABLECOINS catalog. The visible knob is --evm-network=<caip2>;
the rest is the plumbing that makes the knob actually work.
Four interlocking pieces:
1. CLI override - --evm-network=<caip2> selects the EVM chain for a run.
Mode-default behavior preserved when the flag is omitted.
2. SDK-imported chain registry - EVM_NETWORK_CONFIGS is derived from
DEFAULT_STABLECOINS at module load via Object.fromEntries(...), replacing
the prior 10-entry hand-curated table. New SDK chains propagate after
pnpm install with no harness edit.
3. Removes Base Sepolia hardcodes - EIP-712 token names in the four EVM
resource servers (express, fastify, hono, next/proxy) move to a per-server
EVM_PERMIT2_ASSET_NAMES lookup keyed by EVM_NETWORK. The Permit2 approval
script reads its target from the resolved network config. The mock
facilitator advertises the full scheme set (exact, upto, batch-settlement)
and gates non-EVM kinds on env presence.
4. EVM-only credential gating - an EVM-only run (--families=evm) no longer
requires Solana, Aptos, Hedera, or Stellar wallets. The harness's
existing requiredEnvByFamily post-filter check (test.ts line ~660)
handles this uniformly across all five families; the unconditional
EVM+SVM gate that fired before scenario filtering and over-required both
families is removed.
resolveViemChain(caip2) looks up viem's chain database; for chains viem
hasn't packaged it falls through to defineChain({ name: 'EVM <id>',
rpcUrls: { default: { http: [] } } }) and the caller supplies EVM_RPC_URL.
With the viem floor at ^2.48.11, every chain currently in DEFAULT_STABLECOINS
is in viem's catalog, so the fallback is for forward-compatibility with
future SDK chains that out-pace viem.
evmRpcUrl(caip2) resolves in three tiers: EVM_RPC_URL env override -> viem
chain default -> ''. getNetworkSet(mode, evmCaip2?) accepts an optional
CAIP-2 EVM override that overlays the mode default's EVM slot from
EVM_NETWORK_CONFIGS.
Migration: CI configurations that set per-chain RPC URL env vars (e.g.,
BASE_SEPOLIA_RPC_URL) must migrate to the unified EVM_RPC_URL. The harness
selects the chain via --evm-network=<caip2> (or the mode default) and reads
RPC override from EVM_RPC_URL only. No impact on SDK consumers using the
published packages.
The complementary monorepo-wide viem floor bump is in x402-foundation#2242.
26c331b to
72d1195
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2249
Summary
Makes the e2e harness portable to any EVM chain in the SDK's
DEFAULT_STABLECOINScatalog. The visible knob is--evm-network=<caip2>; the rest of the PR is the plumbing that makes the knob actually work.Four interlocking pieces:
--evm-network=<caip2>selects the EVM chain for a run. Mode-default behavior preserved when the flag is omitted.EVM_NETWORK_CONFIGSis derived fromDEFAULT_STABLECOINSat module load, replacing the prior 10-entry hand-curated table. New SDK chains propagate afterpnpm installwith no harness edit.EVM_NETWORK. The Permit2 approval script reads its target from the resolved network config. The mock facilitator advertises the full scheme set (exact,upto,batch-settlement) and gates non-EVM kinds on env presence.--families=evm) no longer requires Solana, Aptos, Hedera, or Stellar wallets. The harness's existingrequiredEnvByFamilypost-filter check (test.tsline ~660) handles this uniformly across all five families; we removed an unconditional EVM+SVM gate that fired before scenario filtering and over-required both families regardless of--families.Why
Without (2), the override in (1) has nothing to resolve to. Without (3), selecting a non-Base chain produces wrong EIP-712 signatures, wrong Permit2 setup targets, and incomplete scheme advertisement. Without (4), an EVM-only contributor must set up a Solana wallet they may never use, which raises the entry bar for chain-specific testing.
Concrete consequences this addresses:
permit2personalities — chains whose default asset specifiesassetTransferMethod === "permit2"(tokens that ship without EIP-3009) — are unreachable today. Their unique EIP-712 domains, permit signatures, and contract behaviors get no runtime signal. (Note: the harness'spermit2endpoints are exercised on Base Sepolia today because USDC supports both methods; what's missing is the chain-specific personality.)assetTransferMethodbut not Base Sepolia passes the harness without signal.After this PR, the harness exercises any chain in
DEFAULT_STABLECOINS(including new additions like Radius Network from #2038) through one--evm-network=<caip2>flag, with no harness source edits.What's in this PR
1. Networks core (
e2e/src/networks/networks.ts)The centerpiece. The hand-curated
EVM_NETWORK_CONFIGStable is replaced withObject.fromEntries(Object.keys(DEFAULT_STABLECOINS).map(...))— a runtime view of the SDK's chain catalog.permit2Assetfor any caip2 lookup flows fromDEFAULT_STABLECOINS[caip2].address.EVM_NETWORK_CONFIGSis exported so callers can introspect the supported chains.resolveViemChain(caip2)looks up viem's chain database; for chains viem hasn't packaged it falls through todefineChain({ name: 'EVM <id>', rpcUrls: { default: { http: [] } } })and the caller suppliesEVM_RPC_URL. With the viem floor at^2.48.11, every chain currently inDEFAULT_STABLECOINSis in viem's catalog, so the fallback is for forward-compatibility with future SDK chains that out-pace viem.evmRpcUrl(caip2)resolves in three tiers:EVM_RPC_URLenv override → viem chain default →''.getNetworkSet(mode, evmCaip2?)accepts an optional CAIP-2 EVM override that overlays the mode default's EVM slot fromEVM_NETWORK_CONFIGS. The mode-defaultNETWORK_SETSrows for Base / Base Sepolia retain their inline addresses — out-of-scope consolidation candidate.2. CLI + harness wiring (
e2e/src/cli/args.ts,e2e/test.ts)--evm-network=<caip2>parsed inparseArgs()asevmNetwork?: string.runTest()passesparsedArgs.evmNetworkintogetNetworkSet(mode, ...).getEvmClients()replacesevmNetwork === 'eip155:8453' ? base : baseSepoliawith
resolveViemChain(evmNetwork).filtering and over-required both families regardless of
--families. Theexisting
requiredEnvByFamilytable-driven check (same file, line ~660)already handles family-conditional credentials uniformly across all five
protocol families —
--families=evmruns no longer require Solana wallets.3. EVM resource servers
Each EVM-payable server constructs an EIP-712 payment domain. All four sites
previously embedded the binary
EVM_NETWORK == "eip155:84532" ? "USDC" : "USD Coin"ternary at multiple call points. Replaced with a per-server
EVM_PERMIT2_ASSET_NAMES: Record<string, string>lookup keyed byEVM_NETWORK,with comments indicating where to add entries when new chains land.
e2e/servers/express/index.tse2e/servers/fastify/index.tse2e/servers/hono/index.tse2e/servers/next/proxy.tse2e/servers/mcp-typescript/index.ts— eip155:* network-prefix widening onlyThe exported
resolveViemChainfromnetworks.tsis consumed bye2e/test.ts.The clients, the facilitator, and the Permit2 script keep their own local
chain-resolution helpers (each spawned process is its own pnpm sub-package and
imports from
e2e/src/...cross workspace boundaries). All local helpersmirror
resolveViemChain's viem-DB lookup with a minimaldefineChainfallback.4. EVM clients
Each client previously selected
viem/chainsbasevsbaseSepoliaviaevmNetwork === 'eip155:8453' ? base : baseSepolia. Replaced with a localresolveEvmChain(network)helper that walks viem's chain database and fallsback to a minimal
defineChainfor chains viem hasn't yet packaged, so any EVMchain in
DEFAULT_STABLECOINSworks.e2e/clients/fetch/index.tse2e/clients/axios/index.tse2e/clients/mcp-typescript/index.ts— eip155:* network-prefix widening only5. Facilitator + Permit2 + mock + generic-server
e2e/facilitators/typescript/index.ts— localgetEvmChain(network)helperfor
createPublicClient(mirrorsresolveViemChain's lookup pattern). SVMsigner initialization is now lazy, gated on
SVM_PRIVATE_KEYpresence soEVM-only runs don't require it. Scheme registration is family-conditional.
e2e/scripts/permit2-approval.ts— reads target token fromEVM_PERMIT2_ASSET(set bygeneric-server.tsfrom the resolvednetwork config) with
[tokenAddress]CLI override. Works on any chainin
DEFAULT_STABLECOINS.e2e/mock-facilitator/index.ts— advertisesbatch-settlementalongsideexact/upto. Non-EVM kinds are gated on env presence so EVM-only runssee a coherent
/supportedresponse (matches the real TS facilitator).e2e/src/servers/generic-server.ts— wiresEVM_NETWORK,EVM_RPC_URL,and
EVM_PERMIT2_ASSETinto spawned server processes from the resolvedNetworkConfig.6. Package wiring + README
e2e/package.json— adds"@x402/evm": "workspace:*"(was reachabletransitively via the workspace, now declared at the e2e top-level package).
e2e/pnpm-lock.yaml— workspace link side-effect.e2e/README.md— documents--evm-network=<caip2>, theEVM_RPC_URLsingle-override env var, the SDK-import auto-propagation, and the
EVM-only credential gating.
Tests
pnpm install --frozen-lockfileclean acrosstypescript/,examples/typescript/, ande2e/.tsc --noEmitfrome2e/(afterpnpm -C typescript build) introduces zero new errors vsupstream/main; the 51 pre-existing top-level-await / missing-route-import / implicit-any errors are unchanged.EVM_NETWORK_CONFIGS: 12 keys, names sourced from viem's chain database, RPC URLs populated for every chain inDEFAULT_STABLECOINS. New SDK chains propagate afterpnpm installwith no harness source edit.--testnet --families=evm --facilitators=typescript --servers=express --clients=fetch --min): 11/11 scenarios pass, exit 0, 28 settlement tx hashes status=0x1 via paced JSON-RPC (1.2 s sleep, sequential, no sampling). Run with no SVM env vars set — confirmsrequiredEnvByFamilycorrectly skips SVM credentials on--families=evm.--evm-network=<caip2> --families=evm: the chain-pluggable path exercises end-to-end with EVM-only credentials. ZeroMissing required environmenterrors reference any SVM variable.^2.48.11;e2e/lockfile resolves direct viem to2.48.11. The complementary monorepo-wide floor bump is in chore: bump viem floor to ^2.48.11 across monorepo + refresh lockfiles #2242.Migration
CI configurations that set per-chain RPC URL env vars (e.g.,
BASE_SEPOLIA_RPC_URL) must migrate to the unifiedEVM_RPC_URL. The harnessselects the chain via
--evm-network=<caip2>(or the mode default) and readsRPC override from
EVM_RPC_URLonly.No impact on SDK consumers using the published packages.
Follow-up (not in this PR)
NETWORK_SETSto derive fromEVM_NETWORK_CONFIGSfor full SDK-import symmetry.Checklist
@x402/*runtime API surface changesAI disclosure
This PR used an agentic coding workflow and was reviewed by Ryan R. Fox (an actual human) before posting.