x402 TypeScript SDK @x402/paywall 版本演进深度解析:从多链支付墙 HTML 生成到 Algorand 支持的完整路线图 📅 发布时间:2026/9/17 8:34:22 👁 浏览次数: x402 TypeScript SDK x402/paywall 版本演进深度解析从多链支付墙 HTML 生成到 Algorand 支持的完整路线图【免费下载链接】x402A payments protocol for the internet. Built on HTTP.项目地址: https://gitcode.com/GitHub_Trending/x4/x402本文以typescript/packages/http/paywall/CHANGELOG.md为骨架梳理x402/paywall包从 1.0.0 到 2.10.0 的完整版本演进x402 协议 v1/v2 的双轨适配、与x402/core的版本联动、v2 规范字段对齐、字符编码修复以及 2.10.0 引入的 AlgorandAVM链支持与令牌名称动态化。读完本文你将掌握这个支付墙PaywallUI 生成器在每个版本中的能力边界并能结合仓库源码理解 Builder 模式、first-match 网络选择、CAIP-2 网络标识与 HTML 模板注入机制的实现细节。上图正是x402/paywall在客户端命中 HTTP 402 后生成的支付墙页面用户在浏览器中看到金额$0.01 Base Sepolia USDC、收款钱包与网络信息点击 Pay now 后由钱包完成签名支付。这正是本文所追踪的包的全部使命——把402 Payment Required响应渲染成可用的支付页面。1. x402/paywall 是什么x402 协议中的支付墙生成器在 x402 协议的完整流程中客户端请求受保护资源时服务端返回402 PAYMENT-REQUIRED客户端据此创建支付负载并携带PAYMENT-SIGNATURE重新请求Facilitator 完成 verify 与 settle 后返回 200而x402/paywall就运行在客户端收到 402 之后这个节点它不处理链上逻辑而是根据服务端accepts数组中声明的支付方式选择对应网络的处理器并生成一段可自包含运行的 HTML 页面内嵌钱包连接、余额查询与支付提交逻辑。从 package.json 可以确认其当前状态包名x402/paywall版本2.10.0作者 x402 Foundation提供四个子路径导出根入口.、./evm、./svm、./avm分别对应 EVM、Solana、Algorand 三套网络处理器与聚合入口核心依赖为x402/coreworkspace 内部依赖、viem/wagmiEVM 侧、solana/kit等Solana 侧以及 Algorand 钱包相关库txnlab/use-wallet、walletconnect/sign-client等react/react-dom^19为 peerDependency因为支付墙 UI 是 React 应用构建脚本build:paywall会依次执行 EVM/SVM/AVM 三套模板的生成详见第 5 节。README 给出的定位是Modular paywall UI for the x402 payment protocol开箱即用的支付墙 UI、多钱包连接MetaMask、Coinbase Wallet、Phantom 等、余额查询、多网络支持、可 tree-shake、完全可通过 Builder 模式定制。2. 版本时间线1.0.0 → 2.10.0 全景完整记录见 CHANGELOG.md按时间线归纳如下版本核心变更性质1.0.0Implements x402 1.0.0 for the TypeScript SDK协议 v1 首发2.0.0Implements x402 2.0.0 for the TypeScript SDK协议 v2 升级2.3.0Bumped x402/core dependency to 2.3.0commit51b8445依赖联动2.4.0 / 2.5.0跟随x402/core2.4.0 / 2.5.0 的依赖更新依赖联动2.6.0将ResourceInfo.description、ResourceInfo.mimeType与PaymentPayload.resource改为可选对齐 v2 规范commit29fe09a规范对齐2.7.0修复 Latin1 范围之外字符的编码问题commit34d2442Bug 修复2.8.0跟随x402/core2.8.0 的依赖更新依赖联动2.9.0项目从 coinbase/x402 迁移至 x402-foundation/x402 组织commit2250cae组织迁移2.10.0① 新增 AlgorandAVM链支持exact 支付方案 支付墙 UI② viem lockfile 升级至 2.47.12③ 令牌名称改为从支付要求的extra.name读取而非硬编码 USDC功能扩展从这份时间线可以读出x402/paywall的演进节奏版本号与x402/core严格同步2.3.0~2.9.0 的多个版本条目中大量出现 Updated dependencies - x402/corex.y.z说明支付墙是核心协议的展示层必须跟随核心 SDK 的规范变更走真正的功能增量集中在 2.6.0规范对齐、2.7.0编码修复与 2.10.0AVM 支持三个版本上。下面逐一展开。3. 2.6.0对齐 x402 v2 规范的字段可选化2.6.0 的变更条目是Make ResourceInfo.description, ResourceInfo.mimeType, and PaymentPayload.resource optional to match v2 spec这在当前源码中有直接对应。src/types.ts 中的PaymentRequired结构体export interface PaymentRequired { x402Version: number; error?: string; resource?: { url: string; description?: string; // 可选 mimeType?: string; // 可选 }; accepts: PaymentRequirements[]; extensions?: Recordstring, unknown; }resource整体、description与mimeType均为可选——这正是 2.6.0 的规范对齐落点。同时PaymentRequirements接口types.ts刻意同时容纳了 v1 与 v2 两套字段v1 的maxAmountRequired、description、resource、mimeType以及 v2 的amount。这个双轨结构解释了为何 1.0.0 与 2.0.0 两个大版本都能在同一个包内演进处理器层通过字段存在性来兼容两代协议。在 src/evm/index.ts 中可以看到这种兼容的直接体现优先读取 v2 的amount不存在时回退到 v1 的maxAmountRequiredconst amount requirement.amount ? parseFloat(requirement.amount) / 1000000 : requirement.maxAmountRequired ? parseFloat(requirement.maxAmountRequired) / 1000000 : 0;注意金额统一按 6 位小数微单位换算为美元数额——这是 x402 结算资产USDC 等 6 位精度稳定币的约定精度。4. 2.7.0Latin1 范围外字符的编码修复2.7.0 仅有一条变更34d2442: Fixed encoding of characters outside of the Latin1 range支付墙 HTML 的生成方式是服务端把运行时配置序列化进一个script标签再注入模板。以 src/evm/paywall.ts 为例getEvmPaywallHtml会把currentUrl、appName、appLogo等字符串拼进window.x402配置脚本const configScript script window.x402 { amount: ${amount}, paymentRequired: ${JSON.stringify(paymentRequired)}, testnet: ${testnet}, currentUrl: ${escapeString(currentUrl)}, config: { chainConfig: ${JSON.stringify(config)}, }, appName: ${escapeString(appName || )}, appLogo: ${escapeString(appLogo || )}, }; ... /script; return EVM_PAYWALL_TEMPLATE.replace(/head, ${configScript}\n/head);这里的关键是escapeString工具函数evm/paywall.ts#L10-L18它对反斜杠、单双引号、换行、回车、制表符做逐字符转义。从源码结构看currentUrl这类用户可控字符串在注入 JS 字面量时是编码风险的主要面——当 URL 或应用名包含 Latin1 之外的字符如中日韩文本时若转义或编码处理不当会破坏注入脚本的可解析性。2.7.0 的修复正是针对这一注入路径的加固EVM 与 AVM 两套paywall.ts中均保留了同款escapeString实现avm/paywall.ts#L10-L18属于该修复后的统一形态。5. 2.9.0 → 2.10.0组织迁移与 Algorand 支持5.1 2.9.0组织迁移2.9.0 的条目是项目从 coinbase/x402 迁移至 x402-foundation/x402 组织。当前 package.json 的元数据可以印证这一状态author: x402 Foundation、repository指向 x402-foundation 仓库。对使用者而言这是一个零行为变更的版本但决定了此后所有发布的维护主体。5.2 2.10.0三条变更逐条落到源码变更一新增 AlgorandAVM链支持exact 支付方案 支付墙 UI这条变更在仓库中留下了四层痕迹目录结构src/avm/与src/evm/、src/svm/并列包含AvmPaywall.tsx、entry.tsx、paywall.ts、index.ts、template-loader.ts以及完整的algorand/适配层useAlgorandWalletOptions、useAlgorandBalance、useAlgorandSigner、useAlgorandWalletEvents等 hook导出入口package.json 新增./avm子路径导出src/index.ts 同时 re-exportavmPaywall因此根入口x402/paywall聚合了evmPaywall、svmPaywall、avmPaywall三个处理器构建脚本build:paywall从两模板扩展为三模板tsx src/evm/build.ts tsx src/svm/build.ts tsx src/avm/build.ts网络工具函数src/paywallUtils.ts 新增 Algorand 网络常量并新增isAvmNetwork前缀algorand:// Algorand Network References (CAIP-2 format: algorand:genesisHash) export const ALGORAND_NETWORK_REFS { MAINNET: wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8, TESTNET: SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI, } as const; export function isAvmNetwork(network: string): boolean { return network.startsWith(algorand:); }AVM 处理器avmPaywall的实现形态与 EVM 版完全同构supports判断network.startsWith(algorand:)generateHtml同样做 1e6 精度换算与testnet ?? true默认值avm/index.ts#L19-L49最终通过getAvmPaywallHtml注入模板avm/paywall.ts。这说明 2.10.0 的 AVM 支持是严格按既有网络处理器扩展点落地的没有改动任何核心机制——这正是 Builder 架构的可扩展性红利。变更二viem lockfile 升级至 2.47.12CHANGELOG 说明此举added chain definitions for Mezo Testnet, MegaETH, Stable, and Stable Testnet that were missing from previously locked versions。这条变更的意义要结合 paywallUtils.ts 中的getNetworkDisplayName来看export function getNetworkDisplayName(network: string): string { if (network.startsWith(eip155:)) { const chainId parseInt(network.split(:)[1]); const chain Object.values(allChains).find(c c.id chainId); if (chain) { return chain.name; } return Chain ${chainId}; } // solana: / algorand: 分支分别映射 Devnet/Testnet 与 Mainnet 名称 ... }支付墙 UI 上的网络名称如截图中的 Base Sepolia完全依赖viem/chains的链定义表来解析。viem 版本升级意味着这些新链Mezo Testnet、MegaETH、Stable 等能被正确解析出人类可读名称而不是回退为Chain id同理isTestnetNetwork也依赖 viem 的testnet属性来判定 EVM 链的网络属性paywallUtils.ts#L151-L169。这是依赖升级与UI 正确性之间的直接耦合。变更三令牌名称从支付要求读取不再硬编码 USDCCHANGELOG 原文The EVM paywall now reads the token name fromextra.namein payment requirements and uses it for all display text. Falls back to Token (generic) whenextra.nameis absent. This fixes mislabeled token names for non-USDC chains (MegaUSD, USDT0, Mezo USD, etc.)对应PaymentRequirements中的extra?: Recordstring, unknown字段types.ts#L20。在 2.10.0 之前服务端即使要求用 MegaUSD 或 Mezo USD 结算支付墙文案也可能显示为 USDC修复后展示文案以服务端在extra.name中声明的令牌名称为准缺省时回退为通用的 Token。值得注意的是evm/paywall.ts 中的getChainConfig仍保留了 Base / Base Sepolia 的 USDC 合约地址作为基础链配置注入模板——两者分工明确chainConfig提供结算所需的合约地址extra.name提供展示层文案。6. 机制深潜Builder、First-Match 与模板生成以下机制贯穿所有版本是理解上述每条 CHANGELOG 变更的运行语境。6.1 Builder 模式与配置合并核心实现在 src/builder.ts。createPaywall()返回PaywallBuilder链式调用withNetwork(handler)注册处理器、withConfig(config)设置配置最后build()产出一个PaywallProviderbuild(): PaywallProvider { const builderConfig this.config; const handlers this.handlers; return { generateHtml: (paymentRequired, runtimeConfig) { // Merge builder config with runtime config (runtime takes precedence) const finalConfig { ...builderConfig, ...runtimeConfig }; // ... }, }; }两个细节值得注意配置双源合并build()时传入的 builder 配置是静态的而generateHtml的第二个参数是运行时配置后者优先{ ...builderConfig, ...runtimeConfig }。这使得同一 paywall 实例可以在多次 402 响应中接受不同的运行时覆盖两个明确的失败路径未注册任何处理器时抛出No paywall handlers registered...遍历完accepts后没有任何处理器支持时抛出携带所有网络名的错误No paywall handler supports networks: ...便于定位注册了处理器但 CAIP-2 前缀不匹配这类配置问题。6.2 First-Match 选择builder.ts#L57-L62 的选择逻辑是对paymentRequired.accepts顺序遍历返回第一个supports()为真的处理器for (const requirement of paymentRequired.accepts) { const handler handlers.find(h h.supports(requirement)); if (handler) { return handler.generateHtml(requirement, paymentRequired, finalConfig); } }README 明确指出这是以服务端accepts数组顺序为准的 first-match即使先注册 EVM 处理器、后注册 Solana 处理器只要服务端把 Solana 放在accepts首位就选 Solana。换言之用户看到哪个链的支付墙由服务端的报价顺序决定withNetwork的注册顺序只影响有没有不影响选谁。每个内置处理器都是一个符合PaywallNetworkHandler接口types.ts#L62-L84的对象supports(requirement)按 CAIP-2 网络前缀判定eip155:/solana:/algorand:generateHtml(requirement, paymentRequired, config)产出完整 HTML。这套接口同时也是自定义网络的扩展点——例如为 Sui 写一个supports: (req) req.network.startsWith(sui:)的处理器再withNetwork注册即可README 给出了示例。6.3 模板生成与注入管线支付墙是 React 应用但交付物是一个字符串 HTML。仓库用两阶段管线完成模板预构建pnpm build:paywall分别运行 EVM/SVM/AVM 三套build.ts用 esbuild配合 HTML 插件把 React 入口如src/evm/entry.tsx打包成完整 HTML落盘到各自的gen/template.ts中运行时注入getEvmTemplate()/getAvmTemplate()等 template-loader 读取生成物getEvmPaywallHtml/getAvmPaywallHtml在/head前注入window.x402配置脚本。模板未生成时有防御性降级返回提示页EVM Paywall (run pnpm build:paywall to generate full template)evm/paywall.ts#L62-L64提醒开发者先执行模板构建。这也解释了 README 的 Development 部分要求先pnpm build:paywall再pnpm build的顺序约束。6.4 客户端侧的选择工具函数src/paywallUtils.ts 还维护了一组客户端/通用工具getPreferredNetworks(testnet)返回首选网络testnet 模式为 Base Sepoliaeip155:84532 Solana Devnet主网模式为 Baseeip155:8453 Solana MainnetchoosePaymentRequirement先尝试匹配首选网络、否则回退到数组首项。这些工具服务于客户端在多个报价中挑一个的场景与 Builder 的服务端报价驱动的 first-match 互补。7. 实战使用指南继承自 README 并对照源码7.1 安装与入口选择pnpm add x402/paywall按 README 的 Bundle Sizes 表选择入口ImportSizeNetworksUse Casex402/paywall3.5MBEVM SolanaMulti-network appsx402/paywall/evm3.4MBEVM onlyBase, Ethereum, Polygon, etc.x402/paywall/svm1.0MBSolana onlySolana apps2.10.0 起package.json的 exports 中另有./avm子路径见 package.json#L117-L126Algorand-only 应用可按需从该入口导入。7.2 三种构建方式// Option 1: EVM Only import { createPaywall } from x402/paywall; import { evmPaywall } from x402/paywall/evm; const paywall createPaywall() .withNetwork(evmPaywall) .withConfig({ appName: My App, testnet: true }) .build(); // Use with Express app.use(paymentMiddleware(routes, facilitators, schemes, undefined, paywall)); // Option 2: Solana Only —— .withNetwork(svmPaywall) // Option 3: Multi-Network —— .withNetwork(evmPaywall).withNetwork(svmPaywall)PaywallConfig四个字段与 types.ts#L4-L9 完全一致interface PaywallConfig { appName?: string; // 钱包连接弹窗中显示的应用名 appLogo?: string; // 应用 Logo URL currentUrl?: string;// 受保护资源的 URL testnet?: boolean; // 是否使用 testnet }源码层面testnet的默认值是true处理器中config.testnet ?? true未显式设置时支付墙按测试网运行——生产环境务必显式传testnet: false。7.3 与 HTTP 中间件集成import express from express; import { paymentMiddleware } from x402/express; import { createPaywall } from x402/paywall; import { evmPaywall } from x402/paywall/evm; const app express(); const paywall createPaywall() .withNetwork(evmPaywall) .withConfig({ appName: My API }) .build(); app.use(paymentMiddleware( { /api/premium: { price: $0.10, network: eip155:84532, payTo: 0x... } }, facilitators, schemes, undefined, paywall ));若不提供自定义 paywall 实例而仅传paywallConfigx402/core会自动探测已安装的x402/paywall未安装时降级为基础 HTML 页——这是 README Automatic Detection 一节描述的集成路径。7.4 开发与测试pnpm build:paywall # 生成 EVM/SVM/AVM 三套 HTML 模板 pnpm build # 构建 TypeScripttsup pnpm test # 运行 vitest 单元测试本包内置了四组测试文件覆盖上述机制builder.test.tsBuilder 行为、index.test.ts入口导出、network-handlers.test.ts各处理器supports判定、paywallUtils.test.ts网络工具函数位于 src/ 目录下。2.10.0 新增 AVM 后src/avm/下的处理器与模板加载即为对应的被测对象。8. 小结以 CHANGELOG 为主线的回顾给出了三条可复用的经验展示层跟随核心层走版本号2.3.0~2.9.0 的大量条目是与x402/core的联动更新x402/paywall的类型结构PaymentRequired/PaymentRequirements双轨字段必须与协议规范同频演进规范对齐是静默但关键的版本2.6.0 的字段可选化、2.7.0 的编码修复都不改变主流程却直接决定多语言字符场景下支付墙 HTML 是否可用新链支持走既定扩展点2.10.0 的 Algorand 支持没有重构核心而是复用PaywallNetworkHandler接口 模板生成管线新增目录、导出子路径与build:paywall步骤三处即可。如需继续深入建议从 src/builder.ts 的选择逻辑、src/paywallUtils.ts 的 CAIP-2 工具函数以及 CHANGELOG.md 的完整提交记录入手。【免费下载链接】x402A payments protocol for the internet. Built on HTTP.项目地址: https://gitcode.com/GitHub_Trending/x4/x402创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考