
基于 EIP-3009 与 Permit2 的 EVM 支付实现深入解读 x402/evm 包【免费下载链接】x402A payments protocol for the internet. Built on HTTP.项目地址: https://gitcode.com/GitHub_Trending/x4/x402x402/evm是 x402 支付协议在 EVM以太坊虚拟机链上的官方实现采用Exact支付方案核心基于 EIP-3009TransferWithAuthorization签名授权并支持以 Permit2 作为通用兜底。本文以 typescript/packages/mechanisms/evm/README.md 为主体结合仓库源码与测试完整梳理该包的客户端Client、Facilitator、资源服务器Server三种角色、V1/V2 协议差异、注册与 RPC 配置方式、签名者抽象、资产转移方法与支持网络清单帮助你直接把这套免 gas 的 HTTP 支付能力接入自己的 TypeScript 应用。包定位与三大组件x402/evm的目标是在 EVM 兼容链上让买家客户端通过链下签名完成支付授权让 Facilitator支付处理方负责链上验证与结算让资源服务器Service构建支付需求Payment Requirements从而把传统 HTTP 资源访问改造成先支付、后访问的按次计费接口。从源码结构看该包提供三类角色对应的实现三者共享同一套 EVM 签名与 EIP-712 基础设施Client付款方为需要发起支付的应用程序设计持有钱包/签名者负责根据服务端返回的支付需求生成 EIP-3009 或 Permit2 支付载荷。对应实现见 client/scheme.ts 中的ExactEvmScheme。Facilitator支付处理方为验证并执行链上交易的支付处理器设计负责verify离线验证签名与需求与settle链上结算。对应实现见 facilitator/scheme.ts。Service资源服务器为接受支付并构建支付需求的资源服务器设计负责生成PaymentRequirements并校验支付结果。命名说明README 中习惯称ExactEvmClient/ExactEvmFacilitator/ExactEvmServer而当前源码中三个角色的实际类名统一为ExactEvmScheme分别实现SchemeNetworkClient/SchemeNetworkFacilitator接口通过不同的注册入口暴露。安装与包导出结构在任意 TypeScript 项目中安装npm install x402/evm该包依赖x402/core核心协议类型与客户端、viemEVM 交互与zod载荷校验依赖声明可查看 package.json。包的导出被划分为多个子路径便于按需引入导出路径内容x402/evmV2 协议CAIP-2 网络标识ExactEvmScheme、toClientEvmSigner、toFacilitatorEvmSigner、ClientEvmSigner/FacilitatorEvmSigner类型、Permit2 辅助函数createPermit2ApprovalTx、getPermit2AllowanceReadParams、EIP-3009/Permit2 载荷类型与常量x402/evm/v1V1 协议简单网络名ExactEvmSchemeV1与NETWORKS常量x402/evm/exact/client客户端专用导出ExactEvmScheme、registerExactEvmScheme、EvmClientConfig类型x402/evm/exact/facilitatorFacilitator 专用导出ExactEvmScheme、registerExactEvmScheme、EvmFacilitatorConfig类型x402/evm/exact/server服务器专用导出ExactEvmScheme、registerExactEvmScheme、EvmResourceServerConfig类型x402/evm/exact/v1/client、x402/evm/exact/v1/facilitatorV1 客户端与 Facilitator 单独入口x402/evm/upto/*Upto 方案按需支付的 client/server/facilitator 实现主入口 src/index.ts 还会额外导出PERMIT2_ADDRESS、x402ExactPermit2ProxyAddress、x402UptoPermit2ProxyAddress、permit2WitnessTypes、eip3009ABI等链上常量以及isPermit2Payload/isEIP3009Payload等类型守卫。V2 与 V1 协议差异该包同时维护 V2现代 x402 协议CAIP-2 网络标识与 V1旧协议简单网络名两套实现差异对照如下维度V2主包V1x402/evm/v1网络格式CAIP-2如eip155:8453简单名称如base-sepolia通配符支持支持如eip155:*不支持固定网络列表载荷结构部分载荷核心层包裹元数据完整载荷扩展支持完整支持有限支持默认有效期1 小时10 分钟含缓冲V1 支持网络由 src/v1/index.ts 中的EVM_NETWORK_CHAIN_ID_MAP定义即NETWORKS常量的来源[ ethereum, sepolia, abstract, abstract-testnet, base-sepolia, base, avalanche-fuji, avalanche, iotex, sei, sei-testnet, polygon, polygon-amoy, peaq, story, educhain, skale-base-sepolia, megaeth, monad, stable, stable-testnet ]注意README 中给出的 V1 网络清单是核心列表当前源码EVM_NETWORK_CHAIN_ID_MAP还额外包含了ethereum、sepolia、megaeth、monad、stable、stable-testnet并以getEvmChainIdV1(network)提供网络名 → 链 ID的映射能力遇到未知网络名会抛出Unsupported v1 network错误。用法一直接注册全控制最直接的方式是显式注册 scheme 到x402Client实例。README 示例中同时注册了 V2 通配符与 V1 网络import { x402Client } from x402/core/client; import { ExactEvmScheme } from x402/evm; import { ExactEvmSchemeV1 } from x402/evm/v1; const client new x402Client() .register(eip155:*, new ExactEvmScheme(signer)) .registerSchemeV1(base-sepolia, new ExactEvmSchemeV1(signer)) .registerSchemeV1(base, new ExactEvmSchemeV1(signer));对于希望一步到位的场景可以使用registerExactEvmScheme见 client/register.ts它一次性完成注册 V2 scheme未传networks时注册eip155:*通配符否则逐网络注册注册全部 V1 网络遍历NETWORKS常量为每个网络注册ExactEvmSchemeV1应用客户端策略policies。其配置对象EvmClientConfig支持字段signer必填用于创建支付载荷的 EVM 签名者paymentRequirementsSelector可选的支付需求选择函数缺省使用默认选择器取第一个可用选项policies可选PaymentPolicy[]schemeOptions可选 RPC 配置支持单配置{ rpcUrl }或按链 ID 键控的多配置{ 8453: { rpcUrl } }networks可选指定要注册的网络缺省注册eip155:*。import { registerExactEvmScheme } from x402/evm/exact/client/register; import { x402Client } from x402/core/client; import { privateKeyToAccount } from viem/accounts; const account privateKeyToAccount(0x...); const client new x402Client(); registerExactEvmScheme(client, { signer: account });Extension RPC 配置可选ExactEvmScheme的基础流程只需要签名者支持addresssignTypedData。当服务端声明了EIP-2612 / ERC-20 Approval 的 gas sponsoring 扩展时客户端还需要链上读取与交易签名能力readContract、getTransactionCount、estimateFeesPerGas、signTransaction。这些能力可以显式通过 RPC URL 配置补齐——SDK不会应用任何链默认 RPC兜底// 按网络显式注册 const client new x402Client() .register(eip155:137, new ExactEvmScheme(signer, { rpcUrl: polygonRpcUrl })) .register(eip155:8453, new ExactEvmScheme(signer, { rpcUrl: baseRpcUrl })); // 通配符注册 按链 ID 键控的配置映射 const wildcardClient new x402Client().register( eip155:*, new ExactEvmScheme(signer, { 137: { rpcUrl: polygonRpcUrl }, 8453: { rpcUrl: baseRpcUrl }, }), );底层逻辑在 shared/rpc.ts 中EvmSchemeOptions是扁平配置{ rpcUrl }与按链 ID 键控映射Recordnumber, { rpcUrl }的联合类型isConfigByChainId通过所有键均为数字判断属于哪种形态resolveRpcUrl(network, options)从 CAIP-2 网络标识解析出链 IDgetEvmChainId再查表得到对应 RPC URLresolveExtensionRpcCapabilities(network, signer, options)会在签名者缺少readContract/getTransactionCount/estimateFeesPerGas时用createPublicClient创建的 viem 公共客户端按需回填这些能力RPC 客户端按 URL 缓存复用。用法二基于 Config更灵活不逐个手写注册时可以直接从配置对象构建客户端import { x402Client } from x402/core/client; import { ExactEvmScheme } from x402/evm; const client x402Client.fromConfig({ schemes: [ { network: eip155:*, client: new ExactEvmScheme(signer) }, { network: base-sepolia, client: new ExactEvmSchemeV1(signer), x402Version: 1 } ], policies: [myCustomPolicy] });签名者抽象ClientEvmSigner 与 FacilitatorEvmSigner客户端与 Facilitator 对签名者的能力要求不同定义集中在 src/signer.tsClientEvmSigner付款方核心能力address签名者地址signTypedData(message)签署 EIP-712 结构化数据基础流程唯一必需的能力可选readContract链上读取仅扩展富化EIP-2612 / ERC-20 Approval需要可选signTransaction/getTransactionCount/estimateFeesPerGasERC-20 Approval gas sponsoring 需要。典型构造方式是用 viem 的WalletClient扩展publicActions或通过toClientEvmSigner(account, publicClient)组合import { createWalletClient, http } from viem; import { privateKeyToAccount } from viem/accounts; import { baseSepolia } from viem/chains; import { publicActions } from viem/actions; const client createWalletClient({ account: privateKeyToAccount(0x...), chain: baseSepolia, transport: http(), }).extend(publicActions);toClientEvmSigner(signer, publicClient)会把签名者自身的可选能力与 publicClient 的能力合并优先取签名者自带实现缺失时回退到 publicClient 的readContract/getTransactionCount/estimateFeesPerGas。FacilitatorEvmSigner结算方要求更完整getAddresses()支持多地址轮换、密钥轮换与高可用、readContract、verifyTypedData、writeContract、sendTransaction、waitForTransactionReceipt、getCode。toFacilitatorEvmSigner(wallet)会将单地址钱包包装为getAddresses() [address]以兼容多地址接口。客户端如何路由EIP-3009 还是 Permit2ExactEvmScheme.createPaymentPayload见 client/scheme.ts依据支付需求中的requirements.extra.assetTransferMethod决定走哪条路径缺省回退到eip3009兼容旧版 Facilitatoreip3009直接生成 EIP-3009 载荷createEIP3009Payload。permit2先生成 Permit2 载荷再按优先级尝试附加扩展若服务端声明eip2612GasSponsoring且签名者支持readContract当 Permit2 授权额度不足时自动签署 EIP-2612 permittrySignEip2612PermitExtension实现免 gas 的首次授权否则尝试 ERC-20 Approval 扩展trySignErc20ApprovalExtension为不支持 EIP-2612 的代币签署approve交易都不适用时直接返回 Permit2 载荷。Facilitator 侧则通过isPermit2Payload类型守卫区分两种载荷分别路由到verifyPermit2/settlePermit2或verifyEIP3009/settleEIP3009见 facilitator/scheme.ts。Facilitator 构造时还支持两个开关均默认falsedeployERC4337WithEIP6492遇到未部署合约账户如 ERC-4337 智能钱包的签名时通过 EIP-6492 部署并验证simulateInSettle结算的二次校验阶段是否执行链上模拟。链上结算Permit2 代理合约Permit2 路径的链上结算由 x402 自部署的代理合约完成相关常量见 src/constants.tsPERMIT2_ADDRESS 0x000000000022D473030F116dDEE9F6B43aC78BA3Uniswap Permit2 的规范地址所有 EVM 链通过 CREATE2 部署为同一地址x402ExactPermit2ProxyAddress 0x402085c248EeA27D92E8b30b2C58ed07f9E20001Exact 方案代理vanity 地址0x4020...0001基于 Arachnid 确定性部署器与 vanity-miner 挖掘的盐前缀0x4020、后缀0001确定性部署x402UptoPermit2ProxyAddress 0x4020A4f3b7b90ccA423B9fabCc0CE57C6C240002Upto 方案代理0x4020...0002。EIP-712 结构化类型同样定义在 constants 中。Exact 方案的 Permit2 witness 为Witness(address to, uint256 validAfter)且类型必须按字母序排列TokenPermissions Witness以匹配 Permit2 合约的 typehash 计算Upto 方案的 witness 额外包含facilitator字段确保只有被授权的 Facilitator 才能结算。EIP-3009 侧eip3009ABI提供了transferWithAuthorization含v,r,s与 bytes 签名两种重载、balanceOf、version、name、authorizationState等接口定义authorizationTypes定义了TransferWithAuthorization的 EIP-712 字段from、to、value、validAfter、validBefore、nonce。资产转移方式与默认资产该包支持两种资产转移方法详见 docs/core-concepts/network-and-token-support.mdxEIP-3009适用于原生支持transferWithAuthorization()的代币如 USDC、EURC。最简单、真正免 gas——一次链下签名即可完成授权无需前置授权步骤是首选路径。Permit2适用于任意 ERC-20 代币。作为通用兜底需要一次性链上授权可通过上文提到的 EIP-2612 / ERC-20 Approval gas sponsoring 扩展把这次授权也做成免 gas。两种方式都由 Facilitator 赞助 gas、以签名授权、保证支付安全。当服务器使用美元字符串定价如$0.01时需要知道使用哪个稳定币。默认资产表在 shared/defaultAssets.ts 的DEFAULT_STABLECOINS中按 CAIP-2 网络标识索引例如eip155:8453Base 主网USDC0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913EIP-712 nameUSD Coin、version2、6 位小数eip155:84532Base SepoliaUSDCUSDC/2/ 6 位小数eip155:4326MegaETHMegaUSDMegaUSD/1/ 18 位小数。ExactDefaultAssetInfo还包含两个客户端行为提示字段assetTransferMethod对不支持 EIP-3009 的代币标记为permit2与supportsEip2612标记代币是否实现 EIP-2612permit()决定是否在extra中附带 name/version 供客户端签署免 gas permit。当前默认资产链的完整清单与新增链的接入方式参见 网络与代币支持文档。对于未配置默认资产的链应使用registerMoneyParser()或直接以TokenAmountamountInAtomicUnits 资产地址指定价格。支持的网络V2 网络CAIP-2 标识eip155:chainId覆盖任意 EVM 链eip155:1— Ethereum 主网eip155:8453— Base 主网eip155:84532— Base Sepoliaeip155:*— 通配符匹配所有 EVM 链任意eip155:chainId网络V1 网络简单名称见上文NETWORKS常量清单。开发与测试命令仓库内对该包提供了完整的开发脚本见 package.json# 构建tsup 打包 CJS ESM 类型声明 npm run build # 单元测试vitest npm run test # 集成测试独立配置 vitest.integration.config.ts npm run test:integration # Lint 与格式检查 npm run lint npm run format测试覆盖集中在 test 目录unit/exact/下有针对客户端 RPC 回填、载荷创建与 Facilitator 验证/结算的测试unit/v1/覆盖 V1 客户端与 Facilitatorintegrations/exact-evm.test.ts则提供 Exact 方案的端到端集成验证。相关包与进一步阅读x402/core核心协议类型与客户端x402Client、策略、支付需求选择器x402/fetch带自动支付处理的 HTTP 封装x402/svmSolana/SVM 实现x402/stellarStellar 实现钱包端与服务器端完整接入流程可参考 docs/getting-started/quickstart-for-buyers.mdx 与 docs/getting-started/quickstart-for-sellers.mdx链上结算合约本体位于 contracts/evm/src/x402ExactPermit2Proxy.sol其测试见 contracts/evm/test/x402ExactPermit2Proxy.t.sol可作为理解settle/settleWithPermit语义的补充材料。【免费下载链接】x402A payments protocol for the internet. Built on HTTP.项目地址: https://gitcode.com/GitHub_Trending/x4/x402创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考