> ## Documentation Index
> Fetch the complete documentation index at: https://docs.x402x.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# x402x-fetch

> 扩展 fetch，自动处理 402 支付与重试

## 概述

`x402x-fetch` 扩展原生 `fetch`，当遇到 HTTP 402 (Payment Required) 时，自动解析服务端返回的支付要求、创建签名（Permit / EIP-3009 / Permit2），并携带 `X-Payment` 头重试原请求。

### 核心特性

* ✅ 无缝集成：兼容原生 fetch API
* 🔐 多种授权：EIP-3009 / EIP-2612 Permit / Permit2
* 🌐 多链支持：内置常见 EVM 链，支持自定义
* 🛡️ 安全保护：最大金额上限、签名校验

## 安装与依赖

```bash theme={null}
npm i x402x-fetch viem
```

依赖（版本示例）：

```json theme={null}
{
  "viem": "^2.21.26",
  "zod": "^3.24.2",
  "x402x": "workspace:^"
}
```

## 快速开始

### 一行包装

```ts theme={null}
import { wrapFetchWithPayment } from "x402x-fetch";
const fetchWithPay = wrapFetchWithPayment(fetch, walletClient, "1000000");
```

### 完整示例

```ts theme={null}
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { wrapFetchWithPayment } from "x402x-fetch";
import { bscTestnet } from "viem/chains";

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const client = createWalletClient({ account, transport: http(), chain: bscTestnet });

// 最多支付 10 USDC（6 位小数）
const fetchWithPay = wrapFetchWithPayment(fetch, client, "10000000");

const response = await fetchWithPay("https://api.example.com/premium", { method: "GET" });
const data = await response.json();
console.log("✅", data);
```

## 参数说明

* `walletClient`：用于签名
* `maxValue`：最大允许支付金额（强烈建议设置）
* `paymentRequirementsSelector`：多选项时自定义选择

## 工作流程

```
1) 请求付费资源
2) 收到 402 响应（包含 x402Version 与 accepts 列表）
3) 选择/校验支付要求（金额 ≤ maxValue）
4) 生成 X-Payment 头（签名）
5) 携带支付头自动重试原请求
6) 返回 200 与数据（服务端校验并结算）
```

## 典型用途

* 访问付费 API / 内容
* 多端一致体验（浏览器 / Node）

## API 参考（精简）

```ts theme={null}
function wrapFetchWithPayment(
  fetch: typeof globalThis.fetch,
  walletClient: WalletClient,
  maxValue?: string,
  paymentRequirementsSelector?: (response: Response402) => PaymentRequirements
): typeof globalThis.fetch
```

支持的 `paymentType`：`eip3009` | `permit` | `permit2`

## 多链支持

你可以直接使用链名称 / viem Chain 对象 / 自定义配置来创建签名器：

```ts theme={null}
import { createEvmSigner, wrapFetchWithPayment } from "x402x-fetch";
import { polygon } from "viem/chains";

// 链名称
const signer1 = createEvmSigner("bsc-testnet", "0xYourPrivateKey");

// viem Chain
const signer2 = createEvmSigner(polygon, "0xYourPrivateKey");

// 自定义
const signer3 = createEvmSigner({ chainId: 56, name: "BSC", rpcUrl: "https://rpc" }, "0xKey");

const fetchWithPay = wrapFetchWithPayment(fetch, signer1);
```

## 使用示例

### GET

```ts theme={null}
const res = await fetchWithPay("https://api.example.com/premium-data");
const data = await res.json();
```

### POST（带 body）

```ts theme={null}
const res = await fetchWithPay("https://api.example.com/compute", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ complexity: 10 }),
});
```

### 自定义 Headers

```ts theme={null}
await fetchWithPay("https://api.example.com/data", {
  headers: {
    Authorization: "Bearer token",
    "X-Custom": "value",
  },
});
```

### 错误处理与金额保护

```ts theme={null}
const fetchPay = wrapFetchWithPayment(fetch, client, "1000000");
try {
  const res = await fetchPay("https://api.example.com/data");
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  const data = await res.json();
} catch (e) {
  if (e instanceof Error && e.message.includes("exceeds maximum")) {
    // 服务器要求金额超过上限
  }
}
```

### 读取支付响应头

```ts theme={null}
const res = await fetchWithPay("https://api.example.com/premium");
const header = res.headers.get("X-Payment-Response");
if (header) {
  const info = JSON.parse(Buffer.from(header, "base64").toString());
  console.log(info.transactionHash, info.payer);
}
```

## 最佳实践

* 为生产设置合理的 `maxValue`
* 统一封装日志与错误分类，便于排障
* 浏览器环境请走钱包连接（不要暴露私钥）

## 相关资源

* 源代码：`https://github.com/WTFLabs-WTF/x402x/tree/main/typescript/packages/x402x-fetch`
* 问题反馈：`https://github.com/WTFLabs-WTF/x402x/issues`
