breeze-x402-payment-api
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBreeze x402 Payment API
Breeze x402 支付API
Interact with Breeze through its x402 payment-gated HTTP API. Each protected request pays a small USDC micropayment, then returns API data or an unsigned Solana transaction.
通过Breeze的x402支付网关HTTP API与Breeze进行交互。每个受保护的请求需要支付少量USDC小额费用,之后会返回API数据或未签名的Solana交易。
Quick Start: Minimum Viable Flow
快速入门:最简流程
This is the fastest path from zero to a working deposit. Read this before anything else.
What you need:
- A Solana wallet funded with USDC and ~0.01 SOL (for transaction fees)
- Node.js installed
这是从零基础到完成一笔存款的最快路径。请先阅读这部分内容。
所需准备:
- 一个已充值USDC和约0.01 SOL的Solana钱包(用于支付交易手续费)
- 已安装Node.js
Step 0: Generate a wallet (skip if you already have one)
步骤0:生成钱包(已有钱包可跳过)
Run once to create and save a keypair:
js
// generate-wallet.js
const { Keypair } = require('@solana/web3.js');
const fs = require('fs');
// Install first: npm install @solana/web3.js --legacy-peer-deps
const bs58Module = require('bs58');
const bs58 = bs58Module.default || bs58Module;
const keypair = Keypair.generate();
const secretKeyBase58 = bs58.encode(keypair.secretKey);
console.log('Public key (fund this address):', keypair.publicKey.toBase58());
console.log('Private key (set as WALLET_PRIVATE_KEY):', secretKeyBase58);
// Save secret key as array backup
fs.writeFileSync('wallet-backup.json', JSON.stringify(Array.from(keypair.secretKey)));
console.log('Backup saved to wallet-backup.json — keep this file secret and out of git!');bash
node generate-wallet.jsFund the printed public key with USDC and at least 0.01 SOL before continuing.
运行一次即可创建并保存密钥对:
js
// generate-wallet.js
const { Keypair } = require('@solana/web3.js');
const fs = require('fs');
// 先安装依赖:npm install @solana/web3.js --legacy-peer-deps
const bs58Module = require('bs58');
const bs58 = bs58Module.default || bs58Module;
const keypair = Keypair.generate();
const secretKeyBase58 = bs58.encode(keypair.secretKey);
console.log('公钥(请向此地址充值):', keypair.publicKey.toBase58());
console.log('私钥(设置为WALLET_PRIVATE_KEY环境变量):', secretKeyBase58);
// 将密钥保存为数组备份
fs.writeFileSync('wallet-backup.json', JSON.stringify(Array.from(keypair.secretKey)));
console.log('备份已保存至wallet-backup.json — 请妥善保管此文件,不要提交到git!');bash
node generate-wallet.js继续操作前,请向打印出的公钥地址充值USDC和至少0.01 SOL。
Step 1: Preflight checks
步骤1:预检检查
Verify everything is reachable before writing code:
bash
undefined在编写代码前,先验证所有服务是否可访问:
bash
undefinedx402 server health
x402服务器健康检查
Breeze strategy info (no auth needed)
Breeze策略信息(无需授权)
Wallet USDC balance (replace YOUR_WALLET_ADDRESS)
钱包USDC余额(替换为你的钱包地址)
curl https://api.mainnet-beta.solana.com
-X POST -H "Content-Type: application/json"
-d '{"jsonrpc":"2.0","id":1,"method":"getTokenAccountsByOwner","params":["YOUR_WALLET_ADDRESS",{"mint":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"},{"encoding":"jsonParsed"}]}'
-X POST -H "Content-Type: application/json"
-d '{"jsonrpc":"2.0","id":1,"method":"getTokenAccountsByOwner","params":["YOUR_WALLET_ADDRESS",{"mint":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"},{"encoding":"jsonParsed"}]}'
Expected: healthz returns `{"status":"ok"}`, strategy-info returns strategy data, token query shows your USDC balance. If any of these fail, fix the connectivity issue before proceeding.curl https://api.mainnet-beta.solana.com
-X POST -H "Content-Type: application/json"
-d '{"jsonrpc":"2.0","id":1,"method":"getTokenAccountsByOwner","params":["YOUR_WALLET_ADDRESS",{"mint":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"},{"encoding":"jsonParsed"}]}'
-X POST -H "Content-Type: application/json"
-d '{"jsonrpc":"2.0","id":1,"method":"getTokenAccountsByOwner","params":["YOUR_WALLET_ADDRESS",{"mint":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"},{"encoding":"jsonParsed"}]}'
预期结果:healthz返回`{"status":"ok"}`,strategy-info返回策略数据,代币查询显示你的USDC余额。如果任何一项失败,请先解决连接问题再继续。Step 2: Install
步骤2:安装依赖
bash
npm install @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58 --legacy-peer-depsis required for npm. Without it,--legacy-peer-depspeer dependency conflicts cause npm to silently remove@faremeter/*.@solana/web3.js
bash
npm install @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58 --legacy-peer-deps对npm是必需的。 没有它,--legacy-peer-deps的 peer 依赖冲突会导致npm自动移除@faremeter/*。@solana/web3.js
Step 3: Run the deposit script
步骤3:运行存款脚本
Save as and run with :
deposit.jsnode deposit.jsjs
// deposit.js — CommonJS, no TypeScript needed
'use strict';
const { wrap } = require('@faremeter/fetch');
const { createPaymentHandler } = require('@faremeter/payment-solana/exact');
const { createLocalWallet } = require('@faremeter/wallet-solana');
const { Connection, Keypair, PublicKey, VersionedTransaction, Transaction } = require('@solana/web3.js');
// bs58 exports .default in some CJS environments
const bs58Module = require('bs58');
const bs58 = bs58Module.default || bs58Module;
async function main() {
const WALLET_PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY;
if (!WALLET_PRIVATE_KEY) throw new Error('Set WALLET_PRIVATE_KEY env var');
const API_URL = 'https://x402.breeze.baby';
const STRATEGY_ID = '43620ba3-354c-456b-aa3c-5bf7fa46a6d4';
const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
const DEPOSIT_AMOUNT = 1_000_000; // 1 USDC (6 decimals)
// Setup
const keypair = Keypair.fromSecretKey(bs58.decode(WALLET_PRIVATE_KEY));
const connection = new Connection('https://api.mainnet-beta.solana.com');
const wallet = await createLocalWallet('mainnet-beta', keypair);
const paymentHandler = createPaymentHandler(wallet, new PublicKey(USDC_MINT), connection);
const fetchWithPayment = wrap(fetch, { handlers: [paymentHandler] });
console.log('Wallet:', keypair.publicKey.toBase58());
// Build deposit transaction
const res = await fetchWithPayment(`${API_URL}/deposit`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
amount: DEPOSIT_AMOUNT,
user_key: keypair.publicKey.toBase58(),
strategy_id: STRATEGY_ID,
base_asset: USDC_MINT,
}),
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Deposit failed (${res.status}): ${text}`);
}
// Parse transaction string (may be bare or JSON-wrapped)
const raw = (await res.text()).trim();
const txString = raw.startsWith('"') ? JSON.parse(raw) : raw;
// Sign and send (try versioned tx first, fall back to legacy)
const bytes = Buffer.from(txString, 'base64');
let sig;
try {
const tx = VersionedTransaction.deserialize(bytes);
tx.sign([keypair]);
sig = await connection.sendRawTransaction(tx.serialize());
} catch {
const tx = Transaction.from(bytes);
tx.partialSign(keypair);
sig = await connection.sendRawTransaction(tx.serialize());
}
await connection.confirmTransaction(sig, 'confirmed');
console.log('Done! View transaction:', `https://solscan.io/tx/${sig}`);
}
main().catch(console.error);bash
WALLET_PRIVATE_KEY=your_base58_key node deposit.js将以下代码保存为,然后运行:
deposit.jsnode deposit.jsjs
// deposit.js — CommonJS,无需TypeScript
'use strict';
const { wrap } = require('@faremeter/fetch');
const { createPaymentHandler } = require('@faremeter/payment-solana/exact');
const { createLocalWallet } = require('@faremeter/wallet-solana');
const { Connection, Keypair, PublicKey, VersionedTransaction, Transaction } = require('@solana/web3.js');
// 在某些CJS环境中bs58导出.default
const bs58Module = require('bs58');
const bs58 = bs58Module.default || bs58Module;
async function main() {
const WALLET_PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY;
if (!WALLET_PRIVATE_KEY) throw new Error('请设置WALLET_PRIVATE_KEY环境变量');
const API_URL = 'https://x402.breeze.baby';
const STRATEGY_ID = '43620ba3-354c-456b-aa3c-5bf7fa46a6d4';
const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
const DEPOSIT_AMOUNT = 1_000_000; // 1 USDC(6位小数)
// 初始化设置
const keypair = Keypair.fromSecretKey(bs58.decode(WALLET_PRIVATE_KEY));
const connection = new Connection('https://api.mainnet-beta.solana.com');
const wallet = await createLocalWallet('mainnet-beta', keypair);
const paymentHandler = createPaymentHandler(wallet, new PublicKey(USDC_MINT), connection);
const fetchWithPayment = wrap(fetch, { handlers: [paymentHandler] });
console.log('钱包地址:', keypair.publicKey.toBase58());
// 构建存款交易
const res = await fetchWithPayment(`${API_URL}/deposit`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
amount: DEPOSIT_AMOUNT,
user_key: keypair.publicKey.toBase58(),
strategy_id: STRATEGY_ID,
base_asset: USDC_MINT,
}),
});
if (!res.ok) {
const text = await res.text();
throw new Error(`存款失败 (${res.status}): ${text}`);
}
// 解析交易字符串(可能是纯字符串或JSON包裹的)
const raw = (await res.text()).trim();
const txString = raw.startsWith('"') ? JSON.parse(raw) : raw;
// 签名并发送交易(优先尝试版本化交易,失败则回退到旧版)
const bytes = Buffer.from(txString, 'base64');
let sig;
try {
const tx = VersionedTransaction.deserialize(bytes);
tx.sign([keypair]);
sig = await connection.sendRawTransaction(tx.serialize());
} catch {
const tx = Transaction.from(bytes);
tx.partialSign(keypair);
sig = await connection.sendRawTransaction(tx.serialize());
}
await connection.confirmTransaction(sig, 'confirmed');
console.log('操作完成!查看交易:', `https://solscan.io/tx/${sig}`);
}
main().catch(console.error);bash
WALLET_PRIVATE_KEY=你的base58密钥 node deposit.jsEndpoint Paths: x402 API vs Direct REST API
端点路径:x402 API vs 直接REST API
These are different APIs with different paths. Do not mix them up.
| API | Base URL | Endpoints | Auth method |
|---|---|---|---|
| x402 (this skill) | | | USDC micropayment via x402 protocol |
| Direct REST API | | | |
This skill uses the x402 API. The direct REST API uses different paths and API key auth — do not mix them.
这是两个不同的API,路径不同。请勿混淆。
| API | 基础URL | 端点 | 认证方式 |
|---|---|---|---|
| x402(本技能使用) | | | 通过x402协议支付USDC小额费用 |
| 直接REST API | | | |
本技能使用x402 API。直接REST API使用不同的路径和API密钥认证——请勿混淆两者。
When to use this skill
何时使用本技能
- "check my Breeze balance" or "show positions/yield"
- "deposit X token into Breeze strategy"
- "withdraw X token from Breeze strategy"
- "sign and send the transaction built by the API"
- "查询我的Breeze余额" 或 "查看持仓/收益"
- "将X代币存入Breeze策略"
- "从Breeze策略中取出X代币"
- "签名并发送由API构建的交易"
Required inputs
必需输入
- (base58 secret key — see Step 0 to generate one)
WALLET_PRIVATE_KEY - Optional (defaults to
STRATEGY_ID— you can use any Breeze strategy ID)43620ba3-354c-456b-aa3c-5bf7fa46a6d4 - Optional (default
X402_API_URL)https://x402.breeze.baby - Optional (default
SOLANA_RPC_URL)https://api.mainnet-beta.solana.com - Optional mint (default USDC mint)
BASE_ASSET
- (base58格式的密钥——见步骤0生成)
WALLET_PRIVATE_KEY - 可选(默认值为
STRATEGY_ID——你可以使用任何Breeze策略ID)43620ba3-354c-456b-aa3c-5bf7fa46a6d4 - 可选(默认
X402_API_URL)https://x402.breeze.baby - 可选(默认
SOLANA_RPC_URL)https://api.mainnet-beta.solana.com - 可选代币地址(默认USDC地址)
BASE_ASSET
Security rules
安全规则
- Never print or echo .
WALLET_PRIVATE_KEY - Never return raw secret values in tool output.
- If a command fails, redact secrets before showing logs.
- Add to
wallet-backup.jsonimmediately..gitignore
- 永远不要打印或输出。
WALLET_PRIVATE_KEY - 永远不要在工具输出中返回原始密钥值。
- 如果命令失败,在显示日志前先隐藏密钥信息。
- 立即将添加到
wallet-backup.json中。.gitignore
Dependencies and install
依赖与安装
bash
undefinedbash
undefinednpm (--legacy-peer-deps required)
npm(必须添加--legacy-peer-deps)
npm install @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58 --legacy-peer-deps
```bashnpm install @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58 --legacy-peer-deps
```bashpnpm
pnpm
pnpm add @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58
```bashpnpm add @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58
```bashbun
bun
bun add @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58
undefinedbun add @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58
undefinedSetup: Payment-Wrapped Fetch (TypeScript)
初始化:带支付功能的Fetch(TypeScript)
Use this setup once per runtime. It automatically handles x402 challenges ( → build payment proof → retry request):
402typescript
import { wrap } from "@faremeter/fetch";
import { createPaymentHandler } from "@faremeter/payment-solana/exact";
import { createLocalWallet } from "@faremeter/wallet-solana";
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import bs58 from "bs58";
const API_URL = (process.env.X402_API_URL ?? "https://x402.breeze.baby").replace(/\/$/, "");
const SOLANA_RPC_URL = process.env.SOLANA_RPC_URL ?? "https://api.mainnet-beta.solana.com";
const STRATEGY_ID = process.env.STRATEGY_ID || "43620ba3-354c-456b-aa3c-5bf7fa46a6d4";
const BASE_ASSET = process.env.BASE_ASSET ?? "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
const WALLET_PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY!;
const keypair = Keypair.fromSecretKey(bs58.decode(WALLET_PRIVATE_KEY));
const connection = new Connection(SOLANA_RPC_URL);
const wallet = await createLocalWallet("mainnet-beta", keypair);
const walletPublicKey = keypair.publicKey.toBase58();
const USDC_MINT = new PublicKey(BASE_ASSET);
const paymentHandler = createPaymentHandler(wallet, USDC_MINT, connection);
const fetchWithPayment = wrap(fetch, { handlers: [paymentHandler] });每个运行环境只需设置一次。它会自动处理x402挑战( → 构建支付凭证 → 重试请求):
402typescript
import { wrap } from "@faremeter/fetch";
import { createPaymentHandler } from "@faremeter/payment-solana/exact";
import { createLocalWallet } from "@faremeter/wallet-solana";
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import bs58 from "bs58";
const API_URL = (process.env.X402_API_URL ?? "https://x402.breeze.baby").replace(/\/$/, "");
const SOLANA_RPC_URL = process.env.SOLANA_RPC_URL ?? "https://api.mainnet-beta.solana.com";
const STRATEGY_ID = process.env.STRATEGY_ID || "43620ba3-354c-456b-aa3c-5bf7fa46a6d4";
const BASE_ASSET = process.env.BASE_ASSET ?? "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
const WALLET_PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY!;
const keypair = Keypair.fromSecretKey(bs58.decode(WALLET_PRIVATE_KEY));
const connection = new Connection(SOLANA_RPC_URL);
const wallet = await createLocalWallet("mainnet-beta", keypair);
const walletPublicKey = keypair.publicKey.toBase58();
const USDC_MINT = new PublicKey(BASE_ASSET);
const paymentHandler = createPaymentHandler(wallet, USDC_MINT, connection);
const fetchWithPayment = wrap(fetch, { handlers: [paymentHandler] });API endpoint contract
API端点约定
Check Balance
查询余额
GET /balance/:fund_userReturns JSON with positions, deposited amounts, yield earned, and APY.
Values are in base units. Convert to human amounts with token decimals.
typescript
const response = await fetchWithPayment(
`${API_URL}/balance/${encodeURIComponent(walletPublicKey)}`,
{ method: "GET" },
);
const balances = await response.json();GET /balance/:fund_user返回包含持仓、存款金额、已赚取收益和APY的JSON数据。
数值为基础单位,需通过代币小数位数转换为可读金额。
typescript
const response = await fetchWithPayment(
`${API_URL}/balance/${encodeURIComponent(walletPublicKey)}`,
{ method: "GET" },
);
const balances = await response.json();Deposit
存款
POST /deposit
Content-Type: application/jsonBuilds an unsigned deposit transaction.
must be base units (example: = 10 USDC).
amount10_000_000typescript
const response = await fetchWithPayment(`${API_URL}/deposit`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
amount: 10_000_000, // 10 USDC (6 decimals)
user_key: walletPublicKey,
strategy_id: STRATEGY_ID,
base_asset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
}),
});
const txString = await response.text(); // encoded unsigned transactionPOST /deposit
Content-Type: application/json构建未签名的存款交易。
必须为基础单位(示例: = 10 USDC)。
amount10_000_000typescript
const response = await fetchWithPayment(`${API_URL}/deposit`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
amount: 10_000_000, // 10 USDC(6位小数)
user_key: walletPublicKey,
strategy_id: STRATEGY_ID,
base_asset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
}),
});
const txString = await response.text(); // 编码后的未签名交易Withdraw
取款
POST /withdraw
Content-Type: application/jsonBuilds an unsigned withdrawal transaction. Supports optional WSOL handling flags.
must be base units.
amounttypescript
const response = await fetchWithPayment(`${API_URL}/withdraw`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
amount: 5_000_000,
user_key: walletPublicKey,
strategy_id: STRATEGY_ID,
base_asset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
all: false,
exclude_fees: true, // always recommended
// For wrapped SOL withdrawals only:
// unwrap_wsol_ata: true, // unwrap WSOL to native SOL
// create_wsol_ata: true, // create WSOL ATA if needed
// detect_wsol_ata: true, // auto-detect WSOL ATA existence
}),
});
const txString = await response.text();Withdraw parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| number | yes | Amount in base units |
| string | yes | User's Solana public key |
| string | yes | Breeze strategy ID (default: |
| string | yes | Token mint address |
| boolean | no | Withdraw entire position |
| boolean | no | Exclude fees from amount (recommended: |
| boolean | no | Unwrap WSOL to native SOL after withdraw |
| boolean | no | Create WSOL ATA if it doesn't exist |
| boolean | no | Auto-detect WSOL ATA and set flags accordingly |
WSOL handling: when withdrawing WSOL (), pass to receive native SOL.
So11111111111111111111111111111111111111112unwrap_wsol_ata: truePOST /withdraw
Content-Type: application/json构建未签名的取款交易。支持可选的WSOL处理标志。
必须为基础单位。
amounttypescript
const response = await fetchWithPayment(`${API_URL}/withdraw`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
amount: 5_000_000,
user_key: walletPublicKey,
strategy_id: STRATEGY_ID,
base_asset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
all: false,
exclude_fees: true, // 推荐设置为true
// 仅在提取WSOL时使用:
// unwrap_wsol_ata: true, // 将WSOL解包为原生SOL
// create_wsol_ata: true, // 如果不存在则创建WSOL关联账户
// detect_wsol_ata: true, // 自动检测WSOL关联账户是否存在
}),
});
const txString = await response.text();取款参数:
| 参数 | 类型 | 是否必需 | 描述 |
|---|---|---|---|
| 数字 | 是 | 基础单位的金额 |
| 字符串 | 是 | 用户的Solana公钥 |
| 字符串 | 是 | Breeze策略ID(默认值: |
| 字符串 | 是 | 代币地址 |
| 布尔值 | 否 | 提取全部持仓 |
| 布尔值 | 否 | 从金额中扣除手续费(推荐设置为 |
| 布尔值 | 否 | 取款后将WSOL解包为原生SOL |
| 布尔值 | 否 | 如果WSOL关联账户不存在则创建 |
| 布尔值 | 否 | 自动检测WSOL关联账户并相应设置标志 |
WSOL处理:当提取WSOL()时,设置即可接收原生SOL。
So11111111111111111111111111111111111111112unwrap_wsol_ata: trueHealth Check
健康检查
GET /healthzFree endpoint (no x402 payment required). Returns when the service is running. Use this to verify connectivity before making paid requests.
{"status":"ok"}GET /healthz免费端点(无需x402支付)。服务运行正常时返回。在发起付费请求前,可使用此端点验证连接性。
{"status":"ok"}Workflow checklists
工作流检查清单
Copy a checklist into your working notes and mark each step complete.
将检查清单复制到你的工作笔记中,完成一项标记一项。
Balance workflow
余额查询工作流
Task Progress:
- Read input
wallet public key - Call with URL-encoded wallet key
GET /balance/:fund_user - Verify ; if not, capture status/body and stop
response.ok - Parse JSON response
- Convert base units to human-readable values using token decimals
- Return balances, yield, and APY clearly
任务进度:
- 读取输入
钱包公钥 - 调用,对钱包密钥进行URL编码
GET /balance/:fund_user - 验证;如果失败,记录状态/响应体并停止
response.ok - 解析JSON响应
- 使用代币小数位数将基础单位转换为可读金额
- 清晰返回余额、收益和APY信息
Deposit workflow
存款工作流
Task Progress:
- Confirm token mint and decimals
- Convert user amount to base units ()
floor(amount * 10^decimals) - Call with validated payload
POST /deposit - Verify ; if not, capture status/body and stop
response.ok - Extract transaction string from response text
- Sign and broadcast transaction on Solana
- Confirm transaction and return explorer link
任务进度:
- 确认代币地址和小数位数
- 将用户输入的金额转换为基础单位()
floor(amount * 10^decimals) - 使用验证后的请求体调用
POST /deposit - 验证;如果失败,记录状态/响应体并停止
response.ok - 从响应文本中提取交易字符串
- 在Solana上签名并广播交易
- 确认交易并返回浏览器链接
Withdraw workflow
取款工作流
Task Progress:
- Confirm token mint and decimals
- Convert user amount to base units unless
all=true - Set unless user asks otherwise
exclude_fees: true - For WSOL + native SOL output, set
unwrap_wsol_ata: true - Call with validated payload
POST /withdraw - Verify ; if not, capture status/body and stop
response.ok - Extract transaction string from response text
- Sign and broadcast transaction on Solana
- Confirm transaction and return explorer link
任务进度:
- 确认代币地址和小数位数
- 将用户输入的金额转换为基础单位(时除外)
all=true - 设置(除非用户要求其他设置)
exclude_fees: true - 如果是提取WSOL并需要原生SOL,设置
unwrap_wsol_ata: true - 使用验证后的请求体调用
POST /withdraw - 验证;如果失败,记录状态/响应体并停止
response.ok - 从响应文本中提取交易字符串
- 在Solana上签名并广播交易
- 确认交易并返回浏览器链接
Signing and Sending Transactions
签名与发送交易
Deposit and withdraw return encoded unsigned transactions. Normalize then sign/send:
typescript
import { VersionedTransaction, Transaction } from "@solana/web3.js";
function extractTransactionString(responseText: string): string {
const trimmed = responseText.trim();
try {
const parsed = JSON.parse(trimmed);
if (typeof parsed === "string") return parsed;
throw new Error("expected transaction string");
} catch (e) {
if (e instanceof SyntaxError) return trimmed;
throw e;
}
}
async function signAndSend(txString: string) {
const bytes = Uint8Array.from(Buffer.from(txString, "base64"));
// Try versioned transaction first, then legacy
try {
const tx = VersionedTransaction.deserialize(bytes);
tx.sign([keypair]);
const sig = await connection.sendRawTransaction(tx.serialize());
await connection.confirmTransaction(sig, "confirmed");
return sig;
} catch {
const tx = Transaction.from(bytes);
tx.partialSign(keypair);
const sig = await connection.sendRawTransaction(tx.serialize());
await connection.confirmTransaction(sig, "confirmed");
return sig;
}
}Validation loop:
- Build/parse transaction string.
- Try path.
VersionedTransaction - If it fails, try legacy path.
Transaction - Confirm transaction.
- If both deserializations fail, return a clear decoding error and do not continue.
存款和取款会返回编码后的未签名交易。先标准化处理,再签名/发送:
typescript
import { VersionedTransaction, Transaction } from "@solana/web3.js";
function extractTransactionString(responseText: string): string {
const trimmed = responseText.trim();
try {
const parsed = JSON.parse(trimmed);
if (typeof parsed === "string") return parsed;
throw new Error("预期为交易字符串");
} catch (e) {
if (e instanceof SyntaxError) return trimmed;
throw e;
}
}
async function signAndSend(txString: string) {
const bytes = Uint8Array.from(Buffer.from(txString, "base64"));
// 优先尝试VersionedTransaction,失败则回退到旧版Transaction
try {
const tx = VersionedTransaction.deserialize(bytes);
tx.sign([keypair]);
const sig = await connection.sendRawTransaction(tx.serialize());
await connection.confirmTransaction(sig, "confirmed");
return sig;
} catch {
const tx = Transaction.from(bytes);
tx.partialSign(keypair);
const sig = await connection.sendRawTransaction(tx.serialize());
await connection.confirmTransaction(sig, "confirmed");
return sig;
}
}验证流程:
- 构建/解析交易字符串。
- 尝试路径。
VersionedTransaction - 如果失败,尝试旧版路径。
Transaction - 确认交易。
- 如果两种反序列化都失败,返回清晰的解码错误,不要继续执行。
Failure handling
错误处理
- errors: payload issue. Re-check required fields and amount positivity.
400 - : wallet/payment authorization issue. Verify wallet and x402 payment capability.
401/403 - : payment challenge not satisfied. Re-run request through wrapped fetch and do not bypass payment handler.
402 - : upstream or proxy issue. Retry once with short backoff, then report failure.
500+ - Transaction send failure: return explicit error with stage (,
deserialize,sign, orsend).confirm
- 错误:请求体问题。重新检查必填字段和金额是否为正数。
400 - :钱包/支付授权问题。验证钱包和x402支付能力。
401/403 - :支付挑战未通过。通过包装后的fetch重新发起请求,不要绕过支付处理器。
402 - :上游或代理问题。重试一次(短时间间隔),然后报告失败。
500+ - 交易发送失败:返回明确的错误信息,包含失败阶段(、
deserialize、sign或send)。confirm
Response format to user
向用户返回的格式
For successful deposit/withdraw, return:
- Action (or
deposit)withdraw - Token + human amount
- Base-unit amount used in request
- Solana transaction signature
- Explorer URL ()
https://solscan.io/tx/{sig}
For balance, return:
- Per-token deposited amount
- Yield earned
- APY details when present
- Note that raw API values are base units and were converted
存款/取款成功时,返回:
- 操作类型(或
deposit)withdraw - 代币+可读金额
- 请求中使用的基础单位金额
- Solana交易签名
- 浏览器链接()
https://solscan.io/tx/{sig}
余额查询成功时,返回:
- 各代币的存款金额
- 已赚取的收益
- 可用的APY详情
- 备注:原始API返回的是基础单位,已转换为可读金额
Supported Tokens
支持的代币
| Token | Mint | Decimals |
|---|---|---|
| USDC | | 6 |
| USDT | | 6 |
| USDS | | 6 |
| SOL | | 9 |
| JitoSOL | | 9 |
| mSOL | | 9 |
| JupSOL | | 9 |
| JLP | | 6 |
| 代币 | 地址 | 小数位数 |
|---|---|---|
| USDC | | 6 |
| USDT | | 6 |
| USDS | | 6 |
| SOL | | 9 |
| JitoSOL | | 9 |
| mSOL | | 9 |
| JupSOL | | 9 |
| JLP | | 6 |
Environment Variables
环境变量
| Variable | Required | Default | Description |
|---|---|---|---|
| yes | — | Base58-encoded Solana private key |
| no | | Breeze strategy ID — any valid strategy ID works |
| no | | x402 payment API URL |
| no | | Solana RPC endpoint |
| no | USDC mint | Default token mint for operations |
| 变量 | 是否必需 | 默认值 | 描述 |
|---|---|---|---|
| 是 | — | Base58编码的Solana私钥 |
| 否 | | Breeze策略ID — 任何有效的策略ID都可使用 |
| 否 | | x402支付API地址 |
| 否 | | Solana RPC端点 |
| 否 | USDC地址 | 操作的默认代币地址 |
Additional reference
额外参考
See agent-using-x402 for a full TypeScript implementation.
完整的TypeScript实现请查看agent-using-x402。