breeze-x402-payment-api

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Breeze 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.js
Fund 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
undefined

x402 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"}]}'

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"}]}'

预期结果: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-deps
--legacy-peer-deps
is required for npm.
Without it,
@faremeter/*
peer dependency conflicts cause npm to silently remove
@solana/web3.js
.
bash
npm install @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58 --legacy-peer-deps
--legacy-peer-deps
对npm是必需的。
没有它,
@faremeter/*
的 peer 依赖冲突会导致npm自动移除
@solana/web3.js

Step 3: Run the deposit script

步骤3:运行存款脚本

Save as
deposit.js
and run with
node deposit.js
:
js
// 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.js
,然后运行
node deposit.js
js
// 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.js

Endpoint Paths: x402 API vs Direct REST API

端点路径:x402 API vs 直接REST API

These are different APIs with different paths. Do not mix them up.
APIBase URLEndpointsAuth method
x402 (this skill)
https://x402.breeze.baby
/balance/:fund_user
<br>
/deposit
<br>
/withdraw
<br>
/healthz
(free)
USDC micropayment via x402 protocol
Direct REST API
https://api.breeze.baby
/deposit/tx
<br>
/withdraw/tx
<br>
/strategy-info/:id
x-api-key
header
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(本技能使用)
https://x402.breeze.baby
/balance/:fund_user
<br>
/deposit
<br>
/withdraw
<br>
/healthz
(免费)
通过x402协议支付USDC小额费用
直接REST API
https://api.breeze.baby
/deposit/tx
<br>
/withdraw/tx
<br>
/strategy-info/:id
x-api-key
请求头
本技能使用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

必需输入

  • WALLET_PRIVATE_KEY
    (base58 secret key — see Step 0 to generate one)
  • Optional
    STRATEGY_ID
    (defaults to
    43620ba3-354c-456b-aa3c-5bf7fa46a6d4
    — you can use any Breeze strategy ID)
  • Optional
    X402_API_URL
    (default
    https://x402.breeze.baby
    )
  • Optional
    SOLANA_RPC_URL
    (default
    https://api.mainnet-beta.solana.com
    )
  • Optional
    BASE_ASSET
    mint (default USDC mint)
  • WALLET_PRIVATE_KEY
    (base58格式的密钥——见步骤0生成)
  • 可选
    STRATEGY_ID
    (默认值为
    43620ba3-354c-456b-aa3c-5bf7fa46a6d4
    ——你可以使用任何Breeze策略ID)
  • 可选
    X402_API_URL
    (默认
    https://x402.breeze.baby
  • 可选
    SOLANA_RPC_URL
    (默认
    https://api.mainnet-beta.solana.com
  • 可选
    BASE_ASSET
    代币地址(默认USDC地址)

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
    wallet-backup.json
    to
    .gitignore
    immediately.
  • 永远不要打印或输出
    WALLET_PRIVATE_KEY
  • 永远不要在工具输出中返回原始密钥值。
  • 如果命令失败,在显示日志前先隐藏密钥信息。
  • 立即将
    wallet-backup.json
    添加到
    .gitignore
    中。

Dependencies and install

依赖与安装

bash
undefined
bash
undefined

npm (--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

```bash
npm install @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58 --legacy-peer-deps

```bash

pnpm

pnpm

pnpm add @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58

```bash
pnpm add @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58

```bash

bun

bun

bun add @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58
undefined
bun add @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58
undefined

Setup: Payment-Wrapped Fetch (TypeScript)

初始化:带支付功能的Fetch(TypeScript)

Use this setup once per runtime. It automatically handles x402 challenges (
402
→ build payment proof → retry request):
typescript
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挑战(
402
→ 构建支付凭证 → 重试请求):
typescript
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_user
Returns 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/json
Builds an unsigned deposit transaction.
amount
must be base units (example:
10_000_000
= 10 USDC).
typescript
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 transaction
POST /deposit
Content-Type: application/json
构建未签名的存款交易。
amount
必须为基础单位(示例:
10_000_000
= 10 USDC)。
typescript
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/json
Builds an unsigned withdrawal transaction. Supports optional WSOL handling flags.
amount
must be base units.
typescript
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:
ParameterTypeRequiredDescription
amount
numberyesAmount in base units
user_key
stringyesUser's Solana public key
strategy_id
stringyesBreeze strategy ID (default:
43620ba3-354c-456b-aa3c-5bf7fa46a6d4
, or any valid strategy)
base_asset
stringyesToken mint address
all
booleannoWithdraw entire position
exclude_fees
booleannoExclude fees from amount (recommended:
true
)
unwrap_wsol_ata
booleannoUnwrap WSOL to native SOL after withdraw
create_wsol_ata
booleannoCreate WSOL ATA if it doesn't exist
detect_wsol_ata
booleannoAuto-detect WSOL ATA and set flags accordingly
WSOL handling: when withdrawing WSOL (
So11111111111111111111111111111111111111112
), pass
unwrap_wsol_ata: true
to receive native SOL.
POST /withdraw
Content-Type: application/json
构建未签名的取款交易。支持可选的WSOL处理标志。
amount
必须为基础单位。
typescript
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();
取款参数:
参数类型是否必需描述
amount
数字基础单位的金额
user_key
字符串用户的Solana公钥
strategy_id
字符串Breeze策略ID(默认值:
43620ba3-354c-456b-aa3c-5bf7fa46a6d4
,或任何有效策略ID)
base_asset
字符串代币地址
all
布尔值提取全部持仓
exclude_fees
布尔值从金额中扣除手续费(推荐设置为
true
unwrap_wsol_ata
布尔值取款后将WSOL解包为原生SOL
create_wsol_ata
布尔值如果WSOL关联账户不存在则创建
detect_wsol_ata
布尔值自动检测WSOL关联账户并相应设置标志
WSOL处理:当提取WSOL(
So11111111111111111111111111111111111111112
)时,设置
unwrap_wsol_ata: true
即可接收原生SOL。

Health Check

健康检查

GET /healthz
Free endpoint (no x402 payment required). Returns
{"status":"ok"}
when the service is running. Use this to verify connectivity before making paid requests.
GET /healthz
免费端点(无需x402支付)。服务运行正常时返回
{"status":"ok"}
。在发起付费请求前,可使用此端点验证连接性。

Workflow checklists

工作流检查清单

Copy a checklist into your working notes and mark each step complete.
将检查清单复制到你的工作笔记中,完成一项标记一项。

Balance workflow

余额查询工作流

Task Progress:
  • Read
    wallet public key
    input
  • Call
    GET /balance/:fund_user
    with URL-encoded wallet key
  • Verify
    response.ok
    ; if not, capture status/body and stop
  • Parse JSON response
  • Convert base units to human-readable values using token decimals
  • Return balances, yield, and APY clearly
任务进度:
  • 读取
    钱包公钥
    输入
  • 调用
    GET /balance/:fund_user
    ,对钱包密钥进行URL编码
  • 验证
    response.ok
    ;如果失败,记录状态/响应体并停止
  • 解析JSON响应
  • 使用代币小数位数将基础单位转换为可读金额
  • 清晰返回余额、收益和APY信息

Deposit workflow

存款工作流

Task Progress:
  • Confirm token mint and decimals
  • Convert user amount to base units (
    floor(amount * 10^decimals)
    )
  • Call
    POST /deposit
    with validated payload
  • Verify
    response.ok
    ; if not, capture status/body and stop
  • 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
    exclude_fees: true
    unless user asks otherwise
  • For WSOL + native SOL output, set
    unwrap_wsol_ata: true
  • Call
    POST /withdraw
    with validated payload
  • Verify
    response.ok
    ; if not, capture status/body and stop
  • 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:
  1. Build/parse transaction string.
  2. Try
    VersionedTransaction
    path.
  3. If it fails, try legacy
    Transaction
    path.
  4. Confirm transaction.
  5. 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;
	}
}
验证流程:
  1. 构建/解析交易字符串。
  2. 尝试
    VersionedTransaction
    路径。
  3. 如果失败,尝试旧版
    Transaction
    路径。
  4. 确认交易。
  5. 如果两种反序列化都失败,返回清晰的解码错误,不要继续执行。

Failure handling

错误处理

  • 400
    errors: payload issue. Re-check required fields and amount positivity.
  • 401/403
    : wallet/payment authorization issue. Verify wallet and x402 payment capability.
  • 402
    : payment challenge not satisfied. Re-run request through wrapped fetch and do not bypass payment handler.
  • 500+
    : upstream or proxy issue. Retry once with short backoff, then report failure.
  • Transaction send failure: return explicit error with stage (
    deserialize
    ,
    sign
    ,
    send
    , or
    confirm
    ).
  • 400
    错误:请求体问题。重新检查必填字段和金额是否为正数。
  • 401/403
    :钱包/支付授权问题。验证钱包和x402支付能力。
  • 402
    :支付挑战未通过。通过包装后的fetch重新发起请求,不要绕过支付处理器。
  • 500+
    :上游或代理问题。重试一次(短时间间隔),然后报告失败。
  • 交易发送失败:返回明确的错误信息,包含失败阶段(
    deserialize
    sign
    send
    confirm
    )。

Response format to user

向用户返回的格式

For successful deposit/withdraw, return:
  • Action (
    deposit
    or
    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

支持的代币

TokenMintDecimals
USDC
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
6
USDT
Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB
6
USDS
USDSwr9ApdHk5bvJKMjzff41FfuX8bSxdKcR81vTwcA
6
SOL
So11111111111111111111111111111111111111112
9
JitoSOL
J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn
9
mSOL
mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So
9
JupSOL
jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v
9
JLP
27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4
6
代币地址小数位数
USDC
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
6
USDT
Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB
6
USDS
USDSwr9ApdHk5bvJKMjzff41FfuX8bSxdKcR81vTwcA
6
SOL
So11111111111111111111111111111111111111112
9
JitoSOL
J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn
9
mSOL
mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So
9
JupSOL
jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v
9
JLP
27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4
6

Environment Variables

环境变量

VariableRequiredDefaultDescription
WALLET_PRIVATE_KEY
yesBase58-encoded Solana private key
STRATEGY_ID
no
43620ba3-354c-456b-aa3c-5bf7fa46a6d4
Breeze strategy ID — any valid strategy ID works
X402_API_URL
no
https://x402.breeze.baby
x402 payment API URL
SOLANA_RPC_URL
no
https://api.mainnet-beta.solana.com
Solana RPC endpoint
BASE_ASSET
noUSDC mintDefault token mint for operations
变量是否必需默认值描述
WALLET_PRIVATE_KEY
Base58编码的Solana私钥
STRATEGY_ID
43620ba3-354c-456b-aa3c-5bf7fa46a6d4
Breeze策略ID — 任何有效的策略ID都可使用
X402_API_URL
https://x402.breeze.baby
x402支付API地址
SOLANA_RPC_URL
https://api.mainnet-beta.solana.com
Solana RPC端点
BASE_ASSET
USDC地址操作的默认代币地址

Additional reference

额外参考

See agent-using-x402 for a full TypeScript implementation.
完整的TypeScript实现请查看agent-using-x402