x402-avm 对 TypeScript 开发者的介绍
了解 @x402-avm/* TypeScript 包生态系统,签名者接口,注册模式,以及如何将 Algorand 支付集成到 TypeScript 应用程序中。
前提条件
在 TypeScript 中使用 x402-avm 之前:
- Node.js 18+ 或现代浏览器运行时
- 推荐 TypeScript 5+(JavaScript 也可以)
- npm 或 yarn 用于包管理
- algosdk – Algorand JavaScript SDK(签名者实现的对等依赖)
核心工作流程:注册,配置,使用
每个 x402-avm TypeScript 应用程序都遵循相同的模式:
1. 创建组件实例(客户端/服务器/促进者)
2. 通过 registerExactAvmScheme() 注册 AVM 方案
3. 使用组件(获取,中间件,验证/结算)
registerExactAvmScheme 函数是通用 x402 核心和 Algorand 特定逻辑之间的桥梁。
如何进行
第 1 步:安装包
包生态系统是模块化的。只安装你需要的:
# 核心 + AVM 机制(总是需要)
npm install @x402-avm/core @x402-avm/avm algosdk
# 对于客户端应用程序(选择一个)
npm install @x402-avm/fetch # Fetch API 包装器
npm install @x402-avm/axios # Axios 拦截器
# 对于服务器应用程序(选择一个)
npm install @x402-avm/express # Express.js 中间件
npm install @x402-avm/hono # Hono 中间件
npm install @x402-avm/next # Next.js 中间件
# 对于浏览器钱包集成
npm install @txnlab/use-wallet
# 可选
npm install @x402-avm/paywall # 浏览器支付墙 UI
npm install @x402-avm/extensions # 协议扩展
第 2 步:了解包结构
| 包 | 角色 | 关键导出 |
|---|---|---|
@x402-avm/core |
基础协议 | x402Client, x402ResourceServer, x402Facilitator, HTTPFacilitatorClient |
@x402-avm/avm |
AVM 机制 | ClientAvmSigner, FacilitatorAvmSigner, 常量,工具 |
@x402-avm/express |
Express 中间件 | paymentMiddleware, paymentMiddlewareFromConfig |
@x402-avm/hono |
Hono 中间件 | paymentMiddleware, paymentMiddlewareFromConfig |
@x402-avm/next |
Next.js 中间件 | paymentMiddleware |
@x402-avm/fetch |
Fetch 客户端 | wrapFetch |
@x402-avm/axios |
Axios 客户端 | wrapAxios |
@x402-avm/paywall |
支付墙 UI | PaywallProvider |
@x402-avm/extensions |
扩展 | Bazaar, 自定义方案 |
第 3 步:实现签名者
签名者是唯一直接接触 algosdk 的组件。SDK 定义接口;你提供实现。
对于客户端(浏览器带钱包):
import type { ClientAvmSigner } from "@x402-avm/avm";
import { useWallet } from "@txnlab/use-wallet";
const { activeAccount, signTransactions } = useWallet();
const signer: ClientAvmSigner = {
address: activeAccount.address,
signTransactions: async (txns, indexesToSign) => {
return signTransactions(txns, indexesToSign);
},
};
对于客户端(服务器端带私钥):
import type { ClientAvmSigner } from "@x402-avm/avm";
import algosdk from "algosdk";
const secretKey = Buffer.from(process.env.AVM_PRIVATE_KEY!, "base64");
const address = algosdk.encodeAddress(secretKey.slice(32));
const signer: ClientAvmSigner = {
address,
signTransactions: async (txns, indexesToSign) => {
return txns.map((txn, i) => {
if (indexesToSign && !indexesToSign.includes(i)) return null;
const decoded = algosdk.decodeUnsignedTransaction(txn);
return algosdk.signTransaction(decoded, secretKey).blob;
});
},
};
对于促进者:
import type { FacilitatorAvmSigner } from "@x402-avm/avm";
import algosdk from "algosdk";
const secretKey = Buffer.from(process.env.AVM_PRIVATE_KEY!, "base64");
const address = algosdk.encodeAddress(secretKey.slice(32));
const algodClient = new algosdk.Algodv2("", "https://testnet-api.algonode.cloud", "");
const signer: FacilitatorAvmSigner = {
getAddresses: () => [address],
signTransaction: async (txn, _addr) => {
const decoded = algosdk.decodeUnsignedTransaction(txn);
return algosdk.signTransaction(decoded, secretKey).blob;
},
getAlgodClient: () => algodClient,
simulateTransactions: async (txns) => { /* ... */ },
sendTransactions: async (signedTxns) => { /* ... */ },
waitForConfirmation: async (txId, _net, rounds) => { /* ... */ },
};
第 4 步:注册 AVM 方案
注册将 AVM 机制连接到核心组件。每个角色都有自己的注册函数,来自不同的子路径:
// 客户端
import { registerExactAvmScheme } from "@x402-avm/avm/exact/client";
registerExactAvmScheme(client, { signer });
// 服务器
import { registerExactAvmScheme } from "@x402-avm/avm/exact/server";
registerExactAvmScheme(server);
// 促进者
import { registerExactAvmScheme } from "@x402-avm/avm/exact/facilitator";
registerExactAvmScheme(facilitator, { signer, networks: ALGORAND_TESTNET_CAIP2 });
第 5 步:使用常量和工具
import {
ALGORAND_TESTNET_CAIP2,
ALGORAND_MAINNET_CAIP2,
USDC_TESTNET_ASA_ID,
USDC_MAINNET_ASA_ID,
isAlgorandNetwork,
isValidAlgorandAddress,
convertToTokenAmount,
createAlgodClient,
} from "@x402-avm/avm";
签名者接口
ClientAvmSigner
interface ClientAvmSigner {
address: string;
signTransactions(
txns: Uint8Array[],
indexesToSign?: number[],
): Promise<(Uint8Array | null)[]>;
}
address: 58 字符的 Algorand 支付者地址signTransactions: 签署一个或多个交易。返回null表示客户端不应签署的交易(例如,费用支付者交易)txns: 作为原始 msgpackUint8Array的未签名交易数组indexesToSign: 可选的要签名的索引数组。如果没有提供,签署所有
这个接口与 @txnlab/use-wallet 的 signTransactions 直接兼容。
FacilitatorAvmSigner
interface FacilitatorAvmSigner {
getAddresses(): readonly string[];
signTransaction(txn: Uint8Array, senderAddress: string): Promise<Uint8Array>;
getAlgodClient(network: Network): unknown;
simulateTransactions(txns: Uint8Array[], network: Network): Promise<unknown>;
sendTransactions(signedTxns: Uint8Array[], network: Network): Promise<string>;
waitForConfirmation(txId: string, network: Network, waitRounds?: number): Promise<unknown>;
}
getAddresses: 返回促进者管理的所有费用支付者地址signTransaction: 为给定的发送者地址签署单个交易getAlgodClient: 返回指定网络的 Algod 客户端simulateTransactions: 在提交前模拟交易组sendTransactions: 提交签名的交易到网络,返回 txIdwaitForConfirmation: 等待交易确认
重要规则 / 指南
- 导入路径很重要 –
registerExactAvmScheme来自客户端、服务器和促进者的不同的子路径 - 签名者是边界 – 只有签名者实现导入
algosdk。SDK 核心从未直接接触algosdk - 到处都是原始字节 – SDK 传递
Uint8Arraymsgpack 字节。SDK 内部不需要 base64 转换(与 Python 不同) - 注册是无条件的 – 永远不要将
registerExactAvmScheme()包装在if (env.AVM_*)检查中 - 类型导入 – 使用
import type { ... }用于接口,以避免捆绑问题 - 网络常量 – 总是在 SDK 代码中从
@x402-avm/avm导入ALGORAND_TESTNET_CAIP2/ALGORAND_MAINNET_CAIP2
常见错误 / 故障排除
| 错误 | 原因 | 解决方案 |
|---|---|---|
Cannot find module '@x402-avm/avm/exact/client' |
包未安装或版本错误 | 运行 npm install @x402-avm/avm |
signTransactions is not a function |
签名者对象缺少方法 | 确保签名者实现 ClientAvmSigner 接口 |
Invalid key length: expected 64 |
私钥格式错误 | 密钥必须是 64 字节 Base64 编码 |
No scheme registered for network |
未注册 AVM 方案 | 在使用前调用 registerExactAvmScheme() |
getAddresses is not a function |
错误的签名者类型 | 对于促进者使用 FacilitatorAvmSigner,对于客户端使用 ClientAvmSigner |
Simulation failed |
交易在链上会失败 | 检查余额,ASA 选择加入,正确的网络 |
global is not defined |
algosdk 在浏览器中引用 global |
在 vite.config.ts 中添加 define: { global: 'globalThis' } |
| 钱包集成中的类型错误 | @txnlab/use-wallet 版本不匹配 |
确保兼容版本的 @txnlab/use-wallet |
参考资料 / 进一步阅读
- REFERENCE.md - 详细的包 API 参考
- EXAMPLES.md - 完整的 TypeScript 代码示例
- @x402-avm/core 在 npm 上
- @x402-avm/avm 在 npm 上
- GoPlausible x402-avm 示例
- GoPlausible x402-avm 文档
- @txnlab/use-wallet 文档