{
  "schemaVersion": "1.0",
  "item": {
    "slug": "breeze-x402-payment-api",
    "name": "Breeze x402",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/keeganthomp/breeze-x402-payment-api",
    "canonicalUrl": "https://clawhub.ai/keeganthomp/breeze-x402-payment-api",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/breeze-x402-payment-api",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=breeze-x402-payment-api",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "README.md",
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/breeze-x402-payment-api"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/breeze-x402-payment-api",
    "agentPageUrl": "https://openagent3.xyz/skills/breeze-x402-payment-api/agent",
    "manifestUrl": "https://openagent3.xyz/skills/breeze-x402-payment-api/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/breeze-x402-payment-api/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Breeze x402 Payment API",
        "body": "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."
      },
      {
        "title": "Quick Start: Minimum Viable Flow",
        "body": "This is the fastest path from zero to a working deposit. Read this before anything else.\n\nWhat you need:\n\nA Solana wallet funded with USDC and ~0.01 SOL (for transaction fees)\nNode.js installed"
      },
      {
        "title": "Step 0: Generate a wallet (skip if you already have one)",
        "body": "Run once to create and save a keypair:\n\n// generate-wallet.js\nconst { Keypair } = require('@solana/web3.js');\nconst fs = require('fs');\n\n// Install first: npm install @solana/web3.js --legacy-peer-deps\nconst bs58Module = require('bs58');\nconst bs58 = bs58Module.default || bs58Module;\n\nconst keypair = Keypair.generate();\nconst secretKeyBase58 = bs58.encode(keypair.secretKey);\n\nconsole.log('Public key (fund this address):', keypair.publicKey.toBase58());\n\n// Save secret key to file — never print it to the console\nfs.writeFileSync('wallet-backup.json', JSON.stringify(Array.from(keypair.secretKey)));\nfs.writeFileSync('.env', `WALLET_PRIVATE_KEY=${secretKeyBase58}\\n`);\nconsole.log('Saved .env with WALLET_PRIVATE_KEY and wallet-backup.json — keep both secret and out of git!');\n\nnode generate-wallet.js\n\nFund the printed public key with USDC and at least 0.01 SOL before continuing. The .env file now contains your WALLET_PRIVATE_KEY."
      },
      {
        "title": "Step 1: Preflight checks",
        "body": "Verify everything is reachable before writing code:\n\n# x402 server health\ncurl https://x402.breeze.baby/healthz\n\n# Breeze strategy info (no auth needed)\ncurl https://api.breeze.baby/strategy-info/43620ba3-354c-456b-aa3c-5bf7fa46a6d4\n\n# Wallet USDC balance (replace YOUR_WALLET_ADDRESS)\ncurl https://api.mainnet-beta.solana.com \\\n  -X POST -H \"Content-Type: application/json\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"getTokenAccountsByOwner\",\"params\":[\"YOUR_WALLET_ADDRESS\",{\"mint\":\"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\"},{\"encoding\":\"jsonParsed\"}]}'\n\nExpected: 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."
      },
      {
        "title": "Step 2: Install",
        "body": "npm install @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58 --legacy-peer-deps\n\n--legacy-peer-deps is required for npm. Without it, @faremeter/* peer dependency conflicts cause npm to silently remove @solana/web3.js."
      },
      {
        "title": "Step 3: Run the deposit script",
        "body": "Save as deposit.js and run with node deposit.js:\n\n// deposit.js — CommonJS, no TypeScript needed\n'use strict';\n\nconst { wrap } = require('@faremeter/fetch');\nconst { createPaymentHandler } = require('@faremeter/payment-solana/exact');\nconst { createLocalWallet } = require('@faremeter/wallet-solana');\nconst { Connection, Keypair, PublicKey, VersionedTransaction, Transaction } = require('@solana/web3.js');\n\n// bs58 exports .default in some CJS environments\nconst bs58Module = require('bs58');\nconst bs58 = bs58Module.default || bs58Module;\n\nasync function main() {\n  const WALLET_PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY;\n  if (!WALLET_PRIVATE_KEY) throw new Error('Set WALLET_PRIVATE_KEY env var');\n\n  const API_URL = 'https://x402.breeze.baby';\n  const STRATEGY_ID = '43620ba3-354c-456b-aa3c-5bf7fa46a6d4';\n  const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';\n  const DEPOSIT_AMOUNT = 1_000_000; // 1 USDC (6 decimals)\n\n  // Setup\n  const keypair = Keypair.fromSecretKey(bs58.decode(WALLET_PRIVATE_KEY));\n  const connection = new Connection('https://api.mainnet-beta.solana.com');\n  const wallet = await createLocalWallet('mainnet-beta', keypair);\n  const paymentHandler = createPaymentHandler(wallet, new PublicKey(USDC_MINT), connection);\n  const fetchWithPayment = wrap(fetch, { handlers: [paymentHandler] });\n\n  console.log('Wallet:', keypair.publicKey.toBase58());\n\n  // Build deposit transaction\n  const res = await fetchWithPayment(`${API_URL}/deposit`, {\n    method: 'POST',\n    headers: { 'content-type': 'application/json' },\n    body: JSON.stringify({\n      amount: DEPOSIT_AMOUNT,\n      user_key: keypair.publicKey.toBase58(),\n      strategy_id: STRATEGY_ID,\n      base_asset: USDC_MINT,\n    }),\n  });\n\n  if (!res.ok) {\n    const text = await res.text();\n    throw new Error(`Deposit failed (${res.status}): ${text}`);\n  }\n\n  // Parse transaction string (may be bare or JSON-wrapped)\n  const raw = (await res.text()).trim();\n  const txString = raw.startsWith('\"') ? JSON.parse(raw) : raw;\n\n  // Sign and send (try versioned tx first, fall back to legacy)\n  const bytes = Buffer.from(txString, 'base64');\n  let sig;\n  try {\n    const tx = VersionedTransaction.deserialize(bytes);\n    tx.sign([keypair]);\n    sig = await connection.sendRawTransaction(tx.serialize());\n  } catch {\n    const tx = Transaction.from(bytes);\n    tx.partialSign(keypair);\n    sig = await connection.sendRawTransaction(tx.serialize());\n  }\n\n  await connection.confirmTransaction(sig, 'confirmed');\n  console.log('Done! View transaction:', `https://solscan.io/tx/${sig}`);\n}\n\nmain().catch(console.error);\n\n# Set WALLET_PRIVATE_KEY from the .env created in Step 0\nexport $(cat .env | xargs) && node deposit.js"
      },
      {
        "title": "Endpoint Paths: x402 API vs Direct REST API",
        "body": "These are different APIs with different paths. Do not mix them up.\n\nAPIBase URLEndpointsAuth methodx402 (this skill)https://x402.breeze.baby/balance/:fund_user<br>/deposit<br>/withdraw<br>/healthz (free)USDC micropayment via x402 protocolDirect REST APIhttps://api.breeze.baby/deposit/tx<br>/withdraw/tx<br>/strategy-info/:idx-api-key header\n\nThis skill uses the x402 API. The direct REST API uses different paths and API key auth — do not mix them."
      },
      {
        "title": "When to use this skill",
        "body": "\"check my Breeze balance\" or \"show positions/yield\"\n\"deposit X token into Breeze strategy\"\n\"withdraw X token from Breeze strategy\"\n\"sign and send the transaction built by the API\""
      },
      {
        "title": "Required inputs",
        "body": "WALLET_PRIVATE_KEY (base58 secret key — see Step 0 to generate one)\nOptional STRATEGY_ID (defaults to 43620ba3-354c-456b-aa3c-5bf7fa46a6d4 — you can use any Breeze strategy ID)\nOptional X402_API_URL (default https://x402.breeze.baby)\nOptional SOLANA_RPC_URL (default https://api.mainnet-beta.solana.com)\nOptional BASE_ASSET mint (default USDC mint)"
      },
      {
        "title": "Security rules",
        "body": "Never print or echo WALLET_PRIVATE_KEY.\nNever return raw secret values in tool output.\nIf a command fails, redact secrets before showing logs.\nAdd wallet-backup.json to .gitignore immediately."
      },
      {
        "title": "Dependencies and install",
        "body": "# npm (--legacy-peer-deps required)\nnpm install @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58 --legacy-peer-deps\n\n# pnpm\npnpm add @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58\n\n# bun\nbun add @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58"
      },
      {
        "title": "Setup: Payment-Wrapped Fetch (TypeScript)",
        "body": "Use this setup once per runtime. It automatically handles x402 challenges (402 → build payment proof → retry request):\n\nimport { wrap } from \"@faremeter/fetch\";\nimport { createPaymentHandler } from \"@faremeter/payment-solana/exact\";\nimport { createLocalWallet } from \"@faremeter/wallet-solana\";\nimport { Connection, Keypair, PublicKey } from \"@solana/web3.js\";\nimport bs58 from \"bs58\";\n\nconst API_URL = (process.env.X402_API_URL ?? \"https://x402.breeze.baby\").replace(/\\/$/, \"\");\nconst SOLANA_RPC_URL = process.env.SOLANA_RPC_URL ?? \"https://api.mainnet-beta.solana.com\";\nconst STRATEGY_ID = process.env.STRATEGY_ID || \"43620ba3-354c-456b-aa3c-5bf7fa46a6d4\";\nconst BASE_ASSET = process.env.BASE_ASSET ?? \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\nconst WALLET_PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY!;\n\nconst keypair = Keypair.fromSecretKey(bs58.decode(WALLET_PRIVATE_KEY));\nconst connection = new Connection(SOLANA_RPC_URL);\nconst wallet = await createLocalWallet(\"mainnet-beta\", keypair);\nconst walletPublicKey = keypair.publicKey.toBase58();\nconst USDC_MINT = new PublicKey(BASE_ASSET);\nconst paymentHandler = createPaymentHandler(wallet, USDC_MINT, connection);\n\nconst fetchWithPayment = wrap(fetch, { handlers: [paymentHandler] });"
      },
      {
        "title": "Check Balance",
        "body": "GET /balance/:fund_user\n\nReturns JSON with positions, deposited amounts, yield earned, and APY.\nValues are in base units. Convert to human amounts with token decimals.\n\nconst response = await fetchWithPayment(\n\t`${API_URL}/balance/${encodeURIComponent(walletPublicKey)}`,\n\t{ method: \"GET\" },\n);\nconst balances = await response.json();"
      },
      {
        "title": "Deposit",
        "body": "POST /deposit\nContent-Type: application/json\n\nBuilds an unsigned deposit transaction.\namount must be base units (example: 10_000_000 = 10 USDC).\n\nconst response = await fetchWithPayment(`${API_URL}/deposit`, {\n\tmethod: \"POST\",\n\theaders: { \"content-type\": \"application/json\" },\n\tbody: JSON.stringify({\n\t\tamount: 10_000_000, // 10 USDC (6 decimals)\n\t\tuser_key: walletPublicKey,\n\t\tstrategy_id: STRATEGY_ID,\n\t\tbase_asset: \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n\t}),\n});\nconst txString = await response.text(); // encoded unsigned transaction"
      },
      {
        "title": "Withdraw",
        "body": "POST /withdraw\nContent-Type: application/json\n\nBuilds an unsigned withdrawal transaction. Supports optional WSOL handling flags.\namount must be base units.\n\nconst response = await fetchWithPayment(`${API_URL}/withdraw`, {\n\tmethod: \"POST\",\n\theaders: { \"content-type\": \"application/json\" },\n\tbody: JSON.stringify({\n\t\tamount: 5_000_000,\n\t\tuser_key: walletPublicKey,\n\t\tstrategy_id: STRATEGY_ID,\n\t\tbase_asset: \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n\t\tall: false,\n\t\texclude_fees: true, // always recommended\n\t\t// For wrapped SOL withdrawals only:\n\t\t// unwrap_wsol_ata: true,     // unwrap WSOL to native SOL\n\t\t// create_wsol_ata: true,     // create WSOL ATA if needed\n\t\t// detect_wsol_ata: true,     // auto-detect WSOL ATA existence\n\t}),\n});\nconst txString = await response.text();\n\nWithdraw parameters:\n\nParameterTypeRequiredDescriptionamountnumberyesAmount in base unitsuser_keystringyesUser's Solana public keystrategy_idstringyesBreeze strategy ID (default: 43620ba3-354c-456b-aa3c-5bf7fa46a6d4, or any valid strategy)base_assetstringyesToken mint addressallbooleannoWithdraw entire positionexclude_feesbooleannoExclude fees from amount (recommended: true)unwrap_wsol_atabooleannoUnwrap WSOL to native SOL after withdrawcreate_wsol_atabooleannoCreate WSOL ATA if it doesn't existdetect_wsol_atabooleannoAuto-detect WSOL ATA and set flags accordingly\n\nWSOL handling: when withdrawing WSOL (So11111111111111111111111111111111111111112), pass unwrap_wsol_ata: true to receive native SOL."
      },
      {
        "title": "Health Check",
        "body": "GET /healthz\n\nFree endpoint (no x402 payment required). Returns {\"status\":\"ok\"} when the service is running. Use this to verify connectivity before making paid requests."
      },
      {
        "title": "Workflow checklists",
        "body": "Copy a checklist into your working notes and mark each step complete."
      },
      {
        "title": "Balance workflow",
        "body": "Task Progress:\n\nRead wallet public key input\n Call GET /balance/:fund_user with URL-encoded wallet key\n Verify response.ok; if not, capture status/body and stop\n Parse JSON response\n Convert base units to human-readable values using token decimals\n Return balances, yield, and APY clearly"
      },
      {
        "title": "Deposit workflow",
        "body": "Task Progress:\n\nConfirm token mint and decimals\n Convert user amount to base units (floor(amount * 10^decimals))\n Call POST /deposit with validated payload\n Verify response.ok; if not, capture status/body and stop\n Extract transaction string from response text\n Sign and broadcast transaction on Solana\n Confirm transaction and return explorer link"
      },
      {
        "title": "Withdraw workflow",
        "body": "Task Progress:\n\nConfirm token mint and decimals\n Convert user amount to base units unless all=true\n Set exclude_fees: true unless user asks otherwise\n For WSOL + native SOL output, set unwrap_wsol_ata: true\n Call POST /withdraw with validated payload\n Verify response.ok; if not, capture status/body and stop\n Extract transaction string from response text\n Sign and broadcast transaction on Solana\n Confirm transaction and return explorer link"
      },
      {
        "title": "Signing and Sending Transactions",
        "body": "Deposit and withdraw return encoded unsigned transactions. Normalize then sign/send:\n\nimport { VersionedTransaction, Transaction } from \"@solana/web3.js\";\n\nfunction extractTransactionString(responseText: string): string {\n\tconst trimmed = responseText.trim();\n\ttry {\n\t\tconst parsed = JSON.parse(trimmed);\n\t\tif (typeof parsed === \"string\") return parsed;\n\t\tthrow new Error(\"expected transaction string\");\n\t} catch (e) {\n\t\tif (e instanceof SyntaxError) return trimmed;\n\t\tthrow e;\n\t}\n}\n\nasync function signAndSend(txString: string) {\n\tconst bytes = Uint8Array.from(Buffer.from(txString, \"base64\"));\n\n\t// Try versioned transaction first, then legacy\n\ttry {\n\t\tconst tx = VersionedTransaction.deserialize(bytes);\n\t\ttx.sign([keypair]);\n\t\tconst sig = await connection.sendRawTransaction(tx.serialize());\n\t\tawait connection.confirmTransaction(sig, \"confirmed\");\n\t\treturn sig;\n\t} catch {\n\t\tconst tx = Transaction.from(bytes);\n\t\ttx.partialSign(keypair);\n\t\tconst sig = await connection.sendRawTransaction(tx.serialize());\n\t\tawait connection.confirmTransaction(sig, \"confirmed\");\n\t\treturn sig;\n\t}\n}\n\nValidation loop:\n\nBuild/parse transaction string.\nTry VersionedTransaction path.\nIf it fails, try legacy Transaction path.\nConfirm transaction.\nIf both deserializations fail, return a clear decoding error and do not continue."
      },
      {
        "title": "Failure handling",
        "body": "400 errors: payload issue. Re-check required fields and amount positivity.\n401/403: wallet/payment authorization issue. Verify wallet and x402 payment capability.\n402: payment challenge not satisfied. Re-run request through wrapped fetch and do not bypass payment handler.\n500+: upstream or proxy issue. Retry once with short backoff, then report failure.\nTransaction send failure: return explicit error with stage (deserialize, sign, send, or confirm)."
      },
      {
        "title": "Response format to user",
        "body": "For successful deposit/withdraw, return:\n\nAction (deposit or withdraw)\nToken + human amount\nBase-unit amount used in request\nSolana transaction signature\nExplorer URL (https://solscan.io/tx/{sig})\n\nFor balance, return:\n\nPer-token deposited amount\nYield earned\nAPY details when present\nNote that raw API values are base units and were converted"
      },
      {
        "title": "Supported Tokens",
        "body": "TokenMintDecimalsUSDCEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v6USDTEs9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB6USDSUSDSwr9ApdHk5bvJKMjzff41FfuX8bSxdKcR81vTwcA6SOLSo111111111111111111111111111111111111111129JitoSOLJ1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn9mSOLmSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So9JupSOLjupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v9JLP27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD46"
      },
      {
        "title": "Environment Variables",
        "body": "VariableRequiredDefaultDescriptionWALLET_PRIVATE_KEYyes—Base58-encoded Solana private keySTRATEGY_IDno43620ba3-354c-456b-aa3c-5bf7fa46a6d4Breeze strategy ID — any valid strategy ID worksX402_API_URLnohttps://x402.breeze.babyx402 payment API URLSOLANA_RPC_URLnohttps://api.mainnet-beta.solana.comSolana RPC endpointBASE_ASSETnoUSDC mintDefault token mint for operations"
      },
      {
        "title": "External Endpoints",
        "body": "This skill sends requests to:\n\nhttps://x402.breeze.baby — Breeze x402 payment-gated API (deposits, withdrawals, balances)\nhttps://api.mainnet-beta.solana.com — Solana RPC (transaction signing and broadcasting)"
      },
      {
        "title": "Security & Privacy",
        "body": "This skill requires WALLET_PRIVATE_KEY as an environment variable for signing Solana transactions and x402 USDC micropayments. The key is read from the process environment at runtime and is never logged, printed, or returned in output. By using this skill, small USDC micropayments are sent from your wallet to gate API access. Only install this skill if you trust Breeze with your wallet's signing capability for USDC transactions."
      },
      {
        "title": "Additional reference",
        "body": "See agent-using-x402 for a full TypeScript implementation."
      }
    ],
    "body": "Breeze x402 Payment API\n\nInteract 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.\n\nQuick Start: Minimum Viable Flow\n\nThis is the fastest path from zero to a working deposit. Read this before anything else.\n\nWhat you need:\n\nA Solana wallet funded with USDC and ~0.01 SOL (for transaction fees)\nNode.js installed\nStep 0: Generate a wallet (skip if you already have one)\n\nRun once to create and save a keypair:\n\n// generate-wallet.js\nconst { Keypair } = require('@solana/web3.js');\nconst fs = require('fs');\n\n// Install first: npm install @solana/web3.js --legacy-peer-deps\nconst bs58Module = require('bs58');\nconst bs58 = bs58Module.default || bs58Module;\n\nconst keypair = Keypair.generate();\nconst secretKeyBase58 = bs58.encode(keypair.secretKey);\n\nconsole.log('Public key (fund this address):', keypair.publicKey.toBase58());\n\n// Save secret key to file — never print it to the console\nfs.writeFileSync('wallet-backup.json', JSON.stringify(Array.from(keypair.secretKey)));\nfs.writeFileSync('.env', `WALLET_PRIVATE_KEY=${secretKeyBase58}\\n`);\nconsole.log('Saved .env with WALLET_PRIVATE_KEY and wallet-backup.json — keep both secret and out of git!');\n\nnode generate-wallet.js\n\n\nFund the printed public key with USDC and at least 0.01 SOL before continuing. The .env file now contains your WALLET_PRIVATE_KEY.\n\nStep 1: Preflight checks\n\nVerify everything is reachable before writing code:\n\n# x402 server health\ncurl https://x402.breeze.baby/healthz\n\n# Breeze strategy info (no auth needed)\ncurl https://api.breeze.baby/strategy-info/43620ba3-354c-456b-aa3c-5bf7fa46a6d4\n\n# Wallet USDC balance (replace YOUR_WALLET_ADDRESS)\ncurl https://api.mainnet-beta.solana.com \\\n  -X POST -H \"Content-Type: application/json\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"getTokenAccountsByOwner\",\"params\":[\"YOUR_WALLET_ADDRESS\",{\"mint\":\"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\"},{\"encoding\":\"jsonParsed\"}]}'\n\n\nExpected: 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.\n\nStep 2: Install\nnpm install @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58 --legacy-peer-deps\n\n\n--legacy-peer-deps is required for npm. Without it, @faremeter/* peer dependency conflicts cause npm to silently remove @solana/web3.js.\n\nStep 3: Run the deposit script\n\nSave as deposit.js and run with node deposit.js:\n\n// deposit.js — CommonJS, no TypeScript needed\n'use strict';\n\nconst { wrap } = require('@faremeter/fetch');\nconst { createPaymentHandler } = require('@faremeter/payment-solana/exact');\nconst { createLocalWallet } = require('@faremeter/wallet-solana');\nconst { Connection, Keypair, PublicKey, VersionedTransaction, Transaction } = require('@solana/web3.js');\n\n// bs58 exports .default in some CJS environments\nconst bs58Module = require('bs58');\nconst bs58 = bs58Module.default || bs58Module;\n\nasync function main() {\n  const WALLET_PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY;\n  if (!WALLET_PRIVATE_KEY) throw new Error('Set WALLET_PRIVATE_KEY env var');\n\n  const API_URL = 'https://x402.breeze.baby';\n  const STRATEGY_ID = '43620ba3-354c-456b-aa3c-5bf7fa46a6d4';\n  const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';\n  const DEPOSIT_AMOUNT = 1_000_000; // 1 USDC (6 decimals)\n\n  // Setup\n  const keypair = Keypair.fromSecretKey(bs58.decode(WALLET_PRIVATE_KEY));\n  const connection = new Connection('https://api.mainnet-beta.solana.com');\n  const wallet = await createLocalWallet('mainnet-beta', keypair);\n  const paymentHandler = createPaymentHandler(wallet, new PublicKey(USDC_MINT), connection);\n  const fetchWithPayment = wrap(fetch, { handlers: [paymentHandler] });\n\n  console.log('Wallet:', keypair.publicKey.toBase58());\n\n  // Build deposit transaction\n  const res = await fetchWithPayment(`${API_URL}/deposit`, {\n    method: 'POST',\n    headers: { 'content-type': 'application/json' },\n    body: JSON.stringify({\n      amount: DEPOSIT_AMOUNT,\n      user_key: keypair.publicKey.toBase58(),\n      strategy_id: STRATEGY_ID,\n      base_asset: USDC_MINT,\n    }),\n  });\n\n  if (!res.ok) {\n    const text = await res.text();\n    throw new Error(`Deposit failed (${res.status}): ${text}`);\n  }\n\n  // Parse transaction string (may be bare or JSON-wrapped)\n  const raw = (await res.text()).trim();\n  const txString = raw.startsWith('\"') ? JSON.parse(raw) : raw;\n\n  // Sign and send (try versioned tx first, fall back to legacy)\n  const bytes = Buffer.from(txString, 'base64');\n  let sig;\n  try {\n    const tx = VersionedTransaction.deserialize(bytes);\n    tx.sign([keypair]);\n    sig = await connection.sendRawTransaction(tx.serialize());\n  } catch {\n    const tx = Transaction.from(bytes);\n    tx.partialSign(keypair);\n    sig = await connection.sendRawTransaction(tx.serialize());\n  }\n\n  await connection.confirmTransaction(sig, 'confirmed');\n  console.log('Done! View transaction:', `https://solscan.io/tx/${sig}`);\n}\n\nmain().catch(console.error);\n\n# Set WALLET_PRIVATE_KEY from the .env created in Step 0\nexport $(cat .env | xargs) && node deposit.js\n\nEndpoint Paths: x402 API vs Direct REST API\n\nThese are different APIs with different paths. Do not mix them up.\n\nAPI\tBase URL\tEndpoints\tAuth method\nx402 (this skill)\thttps://x402.breeze.baby\t/balance/:fund_user<br>/deposit<br>/withdraw<br>/healthz (free)\tUSDC micropayment via x402 protocol\nDirect REST API\thttps://api.breeze.baby\t/deposit/tx<br>/withdraw/tx<br>/strategy-info/:id\tx-api-key header\n\nThis skill uses the x402 API. The direct REST API uses different paths and API key auth — do not mix them.\n\nWhen to use this skill\n\"check my Breeze balance\" or \"show positions/yield\"\n\"deposit X token into Breeze strategy\"\n\"withdraw X token from Breeze strategy\"\n\"sign and send the transaction built by the API\"\nRequired inputs\nWALLET_PRIVATE_KEY (base58 secret key — see Step 0 to generate one)\nOptional STRATEGY_ID (defaults to 43620ba3-354c-456b-aa3c-5bf7fa46a6d4 — you can use any Breeze strategy ID)\nOptional X402_API_URL (default https://x402.breeze.baby)\nOptional SOLANA_RPC_URL (default https://api.mainnet-beta.solana.com)\nOptional BASE_ASSET mint (default USDC mint)\nSecurity rules\nNever print or echo WALLET_PRIVATE_KEY.\nNever return raw secret values in tool output.\nIf a command fails, redact secrets before showing logs.\nAdd wallet-backup.json to .gitignore immediately.\nDependencies and install\n# npm (--legacy-peer-deps required)\nnpm install @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58 --legacy-peer-deps\n\n# pnpm\npnpm add @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58\n\n# bun\nbun add @faremeter/fetch @faremeter/payment-solana @faremeter/wallet-solana @faremeter/info @solana/web3.js bs58\n\nSetup: Payment-Wrapped Fetch (TypeScript)\n\nUse this setup once per runtime. It automatically handles x402 challenges (402 → build payment proof → retry request):\n\nimport { wrap } from \"@faremeter/fetch\";\nimport { createPaymentHandler } from \"@faremeter/payment-solana/exact\";\nimport { createLocalWallet } from \"@faremeter/wallet-solana\";\nimport { Connection, Keypair, PublicKey } from \"@solana/web3.js\";\nimport bs58 from \"bs58\";\n\nconst API_URL = (process.env.X402_API_URL ?? \"https://x402.breeze.baby\").replace(/\\/$/, \"\");\nconst SOLANA_RPC_URL = process.env.SOLANA_RPC_URL ?? \"https://api.mainnet-beta.solana.com\";\nconst STRATEGY_ID = process.env.STRATEGY_ID || \"43620ba3-354c-456b-aa3c-5bf7fa46a6d4\";\nconst BASE_ASSET = process.env.BASE_ASSET ?? \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\nconst WALLET_PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY!;\n\nconst keypair = Keypair.fromSecretKey(bs58.decode(WALLET_PRIVATE_KEY));\nconst connection = new Connection(SOLANA_RPC_URL);\nconst wallet = await createLocalWallet(\"mainnet-beta\", keypair);\nconst walletPublicKey = keypair.publicKey.toBase58();\nconst USDC_MINT = new PublicKey(BASE_ASSET);\nconst paymentHandler = createPaymentHandler(wallet, USDC_MINT, connection);\n\nconst fetchWithPayment = wrap(fetch, { handlers: [paymentHandler] });\n\nAPI endpoint contract\nCheck Balance\nGET /balance/:fund_user\n\n\nReturns JSON with positions, deposited amounts, yield earned, and APY. Values are in base units. Convert to human amounts with token decimals.\n\nconst response = await fetchWithPayment(\n\t`${API_URL}/balance/${encodeURIComponent(walletPublicKey)}`,\n\t{ method: \"GET\" },\n);\nconst balances = await response.json();\n\nDeposit\nPOST /deposit\nContent-Type: application/json\n\n\nBuilds an unsigned deposit transaction. amount must be base units (example: 10_000_000 = 10 USDC).\n\nconst response = await fetchWithPayment(`${API_URL}/deposit`, {\n\tmethod: \"POST\",\n\theaders: { \"content-type\": \"application/json\" },\n\tbody: JSON.stringify({\n\t\tamount: 10_000_000, // 10 USDC (6 decimals)\n\t\tuser_key: walletPublicKey,\n\t\tstrategy_id: STRATEGY_ID,\n\t\tbase_asset: \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n\t}),\n});\nconst txString = await response.text(); // encoded unsigned transaction\n\nWithdraw\nPOST /withdraw\nContent-Type: application/json\n\n\nBuilds an unsigned withdrawal transaction. Supports optional WSOL handling flags. amount must be base units.\n\nconst response = await fetchWithPayment(`${API_URL}/withdraw`, {\n\tmethod: \"POST\",\n\theaders: { \"content-type\": \"application/json\" },\n\tbody: JSON.stringify({\n\t\tamount: 5_000_000,\n\t\tuser_key: walletPublicKey,\n\t\tstrategy_id: STRATEGY_ID,\n\t\tbase_asset: \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n\t\tall: false,\n\t\texclude_fees: true, // always recommended\n\t\t// For wrapped SOL withdrawals only:\n\t\t// unwrap_wsol_ata: true,     // unwrap WSOL to native SOL\n\t\t// create_wsol_ata: true,     // create WSOL ATA if needed\n\t\t// detect_wsol_ata: true,     // auto-detect WSOL ATA existence\n\t}),\n});\nconst txString = await response.text();\n\n\nWithdraw parameters:\n\nParameter\tType\tRequired\tDescription\namount\tnumber\tyes\tAmount in base units\nuser_key\tstring\tyes\tUser's Solana public key\nstrategy_id\tstring\tyes\tBreeze strategy ID (default: 43620ba3-354c-456b-aa3c-5bf7fa46a6d4, or any valid strategy)\nbase_asset\tstring\tyes\tToken mint address\nall\tboolean\tno\tWithdraw entire position\nexclude_fees\tboolean\tno\tExclude fees from amount (recommended: true)\nunwrap_wsol_ata\tboolean\tno\tUnwrap WSOL to native SOL after withdraw\ncreate_wsol_ata\tboolean\tno\tCreate WSOL ATA if it doesn't exist\ndetect_wsol_ata\tboolean\tno\tAuto-detect WSOL ATA and set flags accordingly\n\nWSOL handling: when withdrawing WSOL (So11111111111111111111111111111111111111112), pass unwrap_wsol_ata: true to receive native SOL.\n\nHealth Check\nGET /healthz\n\n\nFree endpoint (no x402 payment required). Returns {\"status\":\"ok\"} when the service is running. Use this to verify connectivity before making paid requests.\n\nWorkflow checklists\n\nCopy a checklist into your working notes and mark each step complete.\n\nBalance workflow\n\nTask Progress:\n\n Read wallet public key input\n Call GET /balance/:fund_user with URL-encoded wallet key\n Verify response.ok; if not, capture status/body and stop\n Parse JSON response\n Convert base units to human-readable values using token decimals\n Return balances, yield, and APY clearly\nDeposit workflow\n\nTask Progress:\n\n Confirm token mint and decimals\n Convert user amount to base units (floor(amount * 10^decimals))\n Call POST /deposit with validated payload\n Verify response.ok; if not, capture status/body and stop\n Extract transaction string from response text\n Sign and broadcast transaction on Solana\n Confirm transaction and return explorer link\nWithdraw workflow\n\nTask Progress:\n\n Confirm token mint and decimals\n Convert user amount to base units unless all=true\n Set exclude_fees: true unless user asks otherwise\n For WSOL + native SOL output, set unwrap_wsol_ata: true\n Call POST /withdraw with validated payload\n Verify response.ok; if not, capture status/body and stop\n Extract transaction string from response text\n Sign and broadcast transaction on Solana\n Confirm transaction and return explorer link\nSigning and Sending Transactions\n\nDeposit and withdraw return encoded unsigned transactions. Normalize then sign/send:\n\nimport { VersionedTransaction, Transaction } from \"@solana/web3.js\";\n\nfunction extractTransactionString(responseText: string): string {\n\tconst trimmed = responseText.trim();\n\ttry {\n\t\tconst parsed = JSON.parse(trimmed);\n\t\tif (typeof parsed === \"string\") return parsed;\n\t\tthrow new Error(\"expected transaction string\");\n\t} catch (e) {\n\t\tif (e instanceof SyntaxError) return trimmed;\n\t\tthrow e;\n\t}\n}\n\nasync function signAndSend(txString: string) {\n\tconst bytes = Uint8Array.from(Buffer.from(txString, \"base64\"));\n\n\t// Try versioned transaction first, then legacy\n\ttry {\n\t\tconst tx = VersionedTransaction.deserialize(bytes);\n\t\ttx.sign([keypair]);\n\t\tconst sig = await connection.sendRawTransaction(tx.serialize());\n\t\tawait connection.confirmTransaction(sig, \"confirmed\");\n\t\treturn sig;\n\t} catch {\n\t\tconst tx = Transaction.from(bytes);\n\t\ttx.partialSign(keypair);\n\t\tconst sig = await connection.sendRawTransaction(tx.serialize());\n\t\tawait connection.confirmTransaction(sig, \"confirmed\");\n\t\treturn sig;\n\t}\n}\n\n\nValidation loop:\n\nBuild/parse transaction string.\nTry VersionedTransaction path.\nIf it fails, try legacy Transaction path.\nConfirm transaction.\nIf both deserializations fail, return a clear decoding error and do not continue.\nFailure handling\n400 errors: payload issue. Re-check required fields and amount positivity.\n401/403: wallet/payment authorization issue. Verify wallet and x402 payment capability.\n402: payment challenge not satisfied. Re-run request through wrapped fetch and do not bypass payment handler.\n500+: upstream or proxy issue. Retry once with short backoff, then report failure.\nTransaction send failure: return explicit error with stage (deserialize, sign, send, or confirm).\nResponse format to user\n\nFor successful deposit/withdraw, return:\n\nAction (deposit or withdraw)\nToken + human amount\nBase-unit amount used in request\nSolana transaction signature\nExplorer URL (https://solscan.io/tx/{sig})\n\nFor balance, return:\n\nPer-token deposited amount\nYield earned\nAPY details when present\nNote that raw API values are base units and were converted\nSupported Tokens\nToken\tMint\tDecimals\nUSDC\tEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\t6\nUSDT\tEs9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB\t6\nUSDS\tUSDSwr9ApdHk5bvJKMjzff41FfuX8bSxdKcR81vTwcA\t6\nSOL\tSo11111111111111111111111111111111111111112\t9\nJitoSOL\tJ1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn\t9\nmSOL\tmSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So\t9\nJupSOL\tjupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v\t9\nJLP\t27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4\t6\nEnvironment Variables\nVariable\tRequired\tDefault\tDescription\nWALLET_PRIVATE_KEY\tyes\t—\tBase58-encoded Solana private key\nSTRATEGY_ID\tno\t43620ba3-354c-456b-aa3c-5bf7fa46a6d4\tBreeze strategy ID — any valid strategy ID works\nX402_API_URL\tno\thttps://x402.breeze.baby\tx402 payment API URL\nSOLANA_RPC_URL\tno\thttps://api.mainnet-beta.solana.com\tSolana RPC endpoint\nBASE_ASSET\tno\tUSDC mint\tDefault token mint for operations\nExternal Endpoints\n\nThis skill sends requests to:\n\nhttps://x402.breeze.baby — Breeze x402 payment-gated API (deposits, withdrawals, balances)\nhttps://api.mainnet-beta.solana.com — Solana RPC (transaction signing and broadcasting)\nSecurity & Privacy\n\nThis skill requires WALLET_PRIVATE_KEY as an environment variable for signing Solana transactions and x402 USDC micropayments. The key is read from the process environment at runtime and is never logged, printed, or returned in output. By using this skill, small USDC micropayments are sent from your wallet to gate API access. Only install this skill if you trust Breeze with your wallet's signing capability for USDC transactions.\n\nAdditional reference\n\nSee agent-using-x402 for a full TypeScript implementation."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/keeganthomp/breeze-x402-payment-api",
    "publisherUrl": "https://clawhub.ai/keeganthomp/breeze-x402-payment-api",
    "owner": "keeganthomp",
    "version": "1.0.7",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/breeze-x402-payment-api",
    "downloadUrl": "https://openagent3.xyz/downloads/breeze-x402-payment-api",
    "agentUrl": "https://openagent3.xyz/skills/breeze-x402-payment-api/agent",
    "manifestUrl": "https://openagent3.xyz/skills/breeze-x402-payment-api/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/breeze-x402-payment-api/agent.md"
  }
}