news 2026/9/17 8:34:20

x402 TypeScript SDK @x402/paywall 版本演进深度解析:从多链支付墙 HTML 生成到 Algorand 支持的完整路线图

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
x402 TypeScript SDK @x402/paywall 版本演进深度解析:从多链支付墙 HTML 生成到 Algorand 支持的完整路线图

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 引入的 Algorand(AVM)链支持与令牌名称动态化。读完本文,你将掌握这个"支付墙(Paywall)UI 生成器"在每个版本中的能力边界,并能结合仓库源码理解 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/core(workspace 内部依赖)、viem/wagmi(EVM 侧)、@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.0(commit51b8445依赖联动
2.4.0 / 2.5.0跟随@x402/core2.4.0 / 2.5.0 的依赖更新依赖联动
2.6.0ResourceInfo.descriptionResourceInfo.mimeTypePaymentPayload.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① 新增 Algorand(AVM)链支持(exact 支付方案 + 支付墙 UI);② viem lockfile 升级至 2.47.12;③ 令牌名称改为从支付要求的extra.name读取而非硬编码 "USDC"功能扩展

从这份时间线可以读出@x402/paywall的演进节奏:版本号与@x402/core严格同步(2.3.0~2.9.0 的多个版本条目中大量出现 "Updated dependencies - @x402/core@x.y.z"),说明支付墙是核心协议的"展示层",必须跟随核心 SDK 的规范变更走;真正的功能增量集中在 2.6.0(规范对齐)、2.7.0(编码修复)与 2.10.0(AVM 支持)三个版本上。下面逐一展开。

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?: Record<string, unknown>; }

resource整体、descriptionmimeType均为可选——这正是 2.6.0 的规范对齐落点。同时PaymentRequirements接口(types.ts)刻意同时容纳了 v1 与 v2 两套字段:v1 的maxAmountRequireddescriptionresourcemimeType,以及 v2 的amount。这个"双轨结构"解释了为何 1.0.0 与 2.0.0 两个大版本都能在同一个包内演进:处理器层通过字段存在性来兼容两代协议。

在 src/evm/index.ts 中可以看到这种兼容的直接体现:优先读取 v2 的amount,不存在时回退到 v1 的maxAmountRequired

const amount = requirement.amount ? parseFloat(requirement.amount) / 1000000 : requirement.maxAmountRequired ? parseFloat(requirement.maxAmountRequired) / 1000000 : 0;

注意金额统一按 6 位小数(微单位)换算为美元数额——这是 x402 结算资产(USDC 等 6 位精度稳定币)的约定精度。

4. 2.7.0:Latin1 范围外字符的编码修复

2.7.0 仅有一条变更:

34d2442: Fixed encoding of characters outside of the Latin1 range

支付墙 HTML 的生成方式是服务端把运行时配置序列化进一个<script>标签再注入模板。以 src/evm/paywall.ts 为例,getEvmPaywallHtml会把currentUrlappNameappLogo等字符串拼进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:三条变更逐条落到源码

变更一:新增 Algorand(AVM)链支持(exact 支付方案 + 支付墙 UI)

这条变更在仓库中留下了四层痕迹:

  1. 目录结构src/avm/src/evm/src/svm/并列,包含AvmPaywall.tsxentry.tsxpaywall.tsindex.tstemplate-loader.ts,以及完整的algorand/适配层(useAlgorandWalletOptionsuseAlgorandBalanceuseAlgorandSigneruseAlgorandWalletEvents等 hook);
  2. 导出入口:package.json 新增"./avm"子路径导出,src/index.ts 同时 re-exportavmPaywall,因此根入口@x402/paywall聚合了evmPaywallsvmPaywallavmPaywall三个处理器;
  3. 构建脚本build:paywall从两模板扩展为三模板:tsx src/evm/build.ts && tsx src/svm/build.ts && tsx src/avm/build.ts
  4. 网络工具函数: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.12

CHANGELOG 说明此举"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 正确性"之间的直接耦合。

变更三:令牌名称从支付要求读取,不再硬编码 "USDC"

CHANGELOG 原文:

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?: Record<string, 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()产出一个PaywallProvider

build(): 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。仓库用两阶段管线完成:

  1. 模板预构建pnpm build:paywall分别运行 EVM/SVM/AVM 三套build.ts,用 esbuild(配合 HTML 插件)把 React 入口(如src/evm/entry.tsx)打包成完整 HTML,落盘到各自的gen/template.ts中;
  2. 运行时注入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:paywallpnpm build的顺序约束。

6.4 客户端侧的选择工具函数

src/paywallUtils.ts 还维护了一组客户端/通用工具:getPreferredNetworks(testnet)返回首选网络(testnet 模式为 Base Sepoliaeip155:84532+ Solana Devnet,主网模式为 Baseeip155:8453+ Solana Mainnet),choosePaymentRequirement先尝试匹配首选网络、否则回退到数组首项。这些工具服务于"客户端在多个报价中挑一个"的场景,与 Builder 的"服务端报价驱动"的 first-match 互补。

7. 实战使用指南(继承自 README 并对照源码)

7.1 安装与入口选择

pnpm add @x402/paywall

按 README 的 Bundle Sizes 表选择入口:

ImportSizeNetworksUse Case
@x402/paywall3.5MBEVM + SolanaMulti-network apps
@x402/paywall/evm3.4MBEVM onlyBase, Ethereum, Polygon, etc.
@x402/paywall/svm1.0MBSolana onlySolana apps

2.10.0 起package.json的 exports 中另有./avm子路径(见 package.json#L117-L126),Algorand-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 实例而仅传paywallConfig@x402/core会自动探测已安装的@x402/paywall,未安装时降级为基础 HTML 页——这是 README "Automatic Detection" 一节描述的集成路径。

7.4 开发与测试

pnpm build:paywall # 生成 EVM/SVM/AVM 三套 HTML 模板 pnpm build # 构建 TypeScript(tsup) pnpm test # 运行 vitest 单元测试

本包内置了四组测试文件覆盖上述机制:builder.test.ts(Builder 行为)、index.test.ts(入口导出)、network-handlers.test.ts(各处理器supports判定)、paywallUtils.test.ts(网络工具函数),位于 src/ 目录下。2.10.0 新增 AVM 后,src/avm/下的处理器与模板加载即为对应的被测对象。

8. 小结

以 CHANGELOG 为主线的回顾给出了三条可复用的经验:

  1. 展示层跟随核心层走版本号:2.3.0~2.9.0 的大量条目是与@x402/core的联动更新,@x402/paywall的类型结构(PaymentRequired/PaymentRequirements双轨字段)必须与协议规范同频演进;
  2. 规范对齐是静默但关键的版本:2.6.0 的字段可选化、2.7.0 的编码修复,都不改变"主流程",却直接决定多语言字符场景下支付墙 HTML 是否可用;
  3. 新链支持走既定扩展点: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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 8:33:18

拆解智能换电站:62.88亿美元市场预测背后的技术与运营逻辑

新能源补能圈子里&#xff0c;换电一直是个既热闹又拧巴的话题。前两天我看到一份行业预测数据&#xff1a;到2032年&#xff0c;全球智能换电站市场销售额预计会突破62.88亿美元。这个数字放在整个汽车产业链里不算夸张&#xff0c;但如果你知道当前这个市场才多大&#xff0c…

作者头像 李华
网站建设 2026/9/17 8:32:39

AR-NAR混合Transformer模型YuE2实战:兼顾速度与精度的序列生成方案

1. 项目概述&#xff1a;从“YuE”到可复现的AR–NAR MoT模型实践最近在Hugging Face上看到一个叫“YuE”的模型仓库&#xff0c;点进去发现它既不是常见的LLM微调项目&#xff0c;也不是图像生成类Pipeline&#xff0c;而是一个明确标注为AR–NAR Mixture-of-Transformers&…

作者头像 李华
网站建设 2026/9/17 8:32:36

甘氏矩阵图价格推算:螺旋数表、Python实现与回测标定

简介&#xff1a;这份资料是甘氏矩阵图价格推算的系统性汇编&#xff0c;面向股票、外汇、期货等领域的技术分析学习者与实战交易者&#xff0c;适合从入门到进阶的读者理解这一工具的原理与用法。资源共1个文件&#xff0c;为pdf格式&#xff0c;压缩包约4.01MB&#xff0c;方…

作者头像 李华
网站建设 2026/9/17 8:32:25

如何用 pypdf 完成 PDF 合并、拆分与文本提取?完整指南

如何用 pypdf 完成 PDF 合并、拆分与文本提取&#xff1f;完整指南 【免费下载链接】pypdf A pure-python PDF library capable of splitting, merging, cropping, and transforming the pages of PDF files 项目地址: https://gitcode.com/GitHub_Trending/py/pypdf py…

作者头像 李华
网站建设 2026/9/17 8:30:39

SpringBoot整合Neo4j实战:图数据库应用开发指南

1. 为什么选择SpringBoot整合Neo4j&#xff1f;在当今数据关系日益复杂的应用场景中&#xff0c;传统关系型数据库在处理多对多关系时往往显得力不从心。我去年接手的一个社交网络分析项目就遇到了这个问题——当需要频繁查询"朋友的朋友"这类多层关系时&#xff0c;…

作者头像 李华
网站建设 2026/9/17 8:30:20

智能电梯门禁系统架构设计与实战经验分享

1. 智能电梯门禁系统架构解析作为一名参与过多个大型商业综合体梯控系统部署的工程师&#xff0c;我想分享一套经过实战验证的智能电梯门禁系统设计方案。这套系统采用模块化架构&#xff0c;完美融合了人脸识别、刷卡验证和二维码技术&#xff0c;特别适合高端写字楼、医院和智…

作者头像 李华