The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Xpay listing page.
Ships as the npm package
@xona-labs/xpay, thexpayCLI, and thexpay_*MCP tools. The package and command names are unchanged.
Agentic-commerce wallet. Multi-network USDC wallet, x402 payments, AgenC marketplace hires, and discovery across 20,000+ services - as a CLI, an SDK, and an MCP server.
Xona Wallet is the wallet and rail layer for agentic commerce. It hides x402, USDC, RPC, and multi-network routing behind a flat surface so agent builders (Claude / Codex / OpenAI / Gemini / your own) can find and pay for services without writing payment plumbing.
Fund the addresses with a few dollars of USDC on Solana mainnet, Base, or both. Then:
| Command | What it does |
|---|---|
xpay init [name] | Create a profile (Solana + EVM keys from one BIP-39 seed). --import to restore from a phrase, --no-encrypt for dev wallets, --workspace to store locally. |
xpay accounts list | show | use | List profiles, inspect one, or set the active profile. |
xpay balance | Token balances per network for the active profile, plus a stablecoin total. Covers Solana, Base and other EVM chains, Robinhood Chain, and Stable. --network. |
xpay discover [query] | Search 21k+ x402 services across chains (Solana, Base, BNB Chain, and other EVM networks), plus AgenC marketplace agent listings (cached on disk). --network, --limit, --json. |
xpay pay <url> | Pay an x402 endpoint. Works on catalog URLs and any URL that returns 402. --max-usd, --body, -y. |
xpay agenc hire <listingPda> | Hire an AgenC marketplace listing - escrows its SOL price on-chain; the provider works asynchronously. --max-usd, --review-window, -y. |
xpay agenc status <taskPda> | Check a hire's progress (read-only, no wallet). --json. |
xpay token find <query> | Find a Solana token by ticker, name, or mint address (Jupiter) - price, mcap, liquidity, verification. Read-only. --limit, --json. |
xpay token rwa [query] | List tradable RWA tokens on Solana: tokenized stocks/ETFs (xStocks, Ondo, Remora) + USDY. Read-only. --category, --limit, --json. |
xpay swap <amount> <from> <to> | Swap tokens in your wallet via Jupiter (Solana only), subject to the guardrail. --slippage-bps, -y. |
xpay trade <amount> <from> <to> | Trade tokens on Robinhood Chain via Uniswap V3 / NOXA Fun (ETH↔token), subject to the guardrail. --slippage-bps, --quote-only, -y. |
xpay trending | List tokens trending on Robinhood Chain (read-only, no wallet). --new, --limit. |
xpay x user | posts <handle> | Realtime X (Twitter) account data - profile ( |
xpay zauth reposcan <repoUrl> | Repository security scan via partner zauth - zauth score + provenance/vulnerability report (~$0.05 USDC via x402). --json, -y. |
xpay zauth status <sessionToken> | Check a running zauth scan (free, read-only, no wallet). --json. |
xpay shop search "<query>" | Product discovery across Google Shopping, Amazon, and eBay from one query (~$0.02 USDC via x402, less for fewer marketplaces). --marketplaces, --price-min/max, --condition, --sort, --json, -y. |
xpay shop quote "<query>" | Free preflight: exact search price + how the query parses (no wallet). --json. |
xpay transfer <amount> USDC <to> | Direct stablecoin transfer (USDC, or USDT0 on Stable), subject to the guardrail. --network, -y. |
xpay report | Comprehensive USDC activity report - totals, net flow, timeline, top counterparties, biggest txs. --period daily|weekly|monthly, --network, --json. |
xpay guardrail show | set | clear | Inspect or edit spending caps and allowed hosts. |
xpay biometric status | enable | disable | Touch ID unlock for the wallet passphrase (macOS). |
xpay sana link | unlink | status | Link a Sana API key to activate the agent card (optional). |
xpay mcp | Start the MCP server on stdio (for Claude Desktop / Cursor / Codex). |
All commands run from a single profile. Switch with xpay accounts use <name>.
The CLI is a thin shell over the SDK - every command has a direct programmatic equivalent.
Xona Wallet ships tool definitions for the three major LLM SDKs. Same handlers, different schema shapes.
forOpenAI(xpay) and forGemini(xpay) return the same handlers wrapped in vendor-specific schemas. See examples/claude-agent.ts for the full tool-use loop.
Xona Wallet is listed in the official MCP Registry
as io.github.xona-labs/xpay - registry-aware hosts can discover and
install it by that name. For everything else, drop Xona Wallet into the host's
config - no code, no keys, no xpay init. On first boot the agent is
given its own wallet automatically:
That's the whole setup. The generated wallet's Solana address is printed to
stderr on first run - fund it with USDC and the agent can pay. It persists
under ~/.xpay and is reused on every later boot, so the address is stable.
The host sees the core tools: xpay_discover, xpay_use, xpay_do, xpay_transfer, xpay_balance, xpay_report, xpay_guardrail, xpay_token_find, xpay_swap, xpay_trending_tokens, xpay_trade_quote, xpay_trade, xpay_x_user, xpay_x_posts, xpay_zauth_reposcan, xpay_zauth_scan_status, xpay_shop_search, xpay_shop_quote, xpay_shop_lens, xpay_shop_lens_quote, xpay_rwa_find, xpay_agenc_status, plus xpay_bento_status / xpay_bento_enable / xpay_bento_disable to manage the intent firewall. If you've linked a Sana key (see below), eight additional sana_* tools are also registered automatically.
Bring your own wallet instead - the wallet source order is existing profile → key env → auto-generate, so any of these overrides the generated wallet:
On macOS, with biometric unlock enabled on a profile, the server shows one Touch ID dialog at startup instead of keeping the passphrase in host config.
See SKILL.md for a framework-agnostic guide to driving these tools from any agent.
Each profile is a directory under ~/.xpay/ with:
Override with XPAY_HOME=/some/path or xpay init --workspace for project-local profiles.
Skip typing the passphrase on every command - unlock with Touch ID instead:
How it works: the wallet's scrypt + AES-256-GCM encryption is unchanged. enable places the
passphrase in your login keychain, and a small native helper (compiled on first use to
~/.xpay/bin/, requires the Xcode Command Line Tools) releases it only after a
LocalAuthentication check. Biometrics never replace the passphrase - they gate access to it.
The unlock order for every command is: --passphrase flag → $XPAY_PASSPHRASE → Touch ID →
interactive prompt. Your passphrase keeps working everywhere and remains the only recovery
path - if Touch ID is unavailable (or the stored copy goes stale after a re-encrypt), the CLI
falls back to asking for it.
macOS asks once to allow keychain access for the helper - choose "Always Allow". It will ask again after package upgrades, since the helper is recompiled.
The guardrail runs before any signer is touched, so a misbehaving agent (or compromised LLM) cannot bypass it.
maxPerTx / maxPerDay: apply to every paid call and direct transfers.allowedHosts: apply only to x402 calls (transfers go to addresses, not hosts).maxPerTx / maxPerDay: apply to every paid call and direct transfers.allowedHosts: apply only to x402 calls (transfers go to addresses, not hosts).requireApprovalAbove: calls ≥ threshold need explicit approval. In the CLI this is a
Touch ID prompt when biometric unlock is enabled, otherwise a y/n
confirm; in the MCP server it is Touch ID only (no terminal), so an agent's large payment
surfaces as a system dialog you physically approve. In the SDK, wire the
onApprovalRequired hook to whatever you like - push notification, biometric, webhook.Spend caps stop an agent spending too much - they can't tell a legitimate payment from a prompt-injected one. The optional Bento layer adds an AI intent firewall: every paid call and transfer is screened for malicious intent (prompt-injection, wallet-drain, intent-vs-execution mismatch) before signing. It runs inside the guardrail, right after the local caps pass.
There's no API key - Bento authenticates with the wallet's own key. The one manual step is a
one-time, on-chain registration of the agent wallet at
app.bentoguard.xyz (log in with your owner wallet; until the agent
wallet is registered, payments are rejected with Agent not found).
Each screened call returns a verdict:
ALLOW: cleared; Xona Wallet signs as normal.BLOCKED: flagged as a critical threat; Xona Wallet throws before signing, no funds move.ESCALATED: ambiguous; Xona Wallet defers to your onApprovalRequired hook, or fails closed.Agents can manage it over MCP too: xpay_bento_status, xpay_bento_enable, xpay_bento_disable
(disable is the escape hatch when the wallet isn't registered yet).
Xona Wallet supports an optional integration with Sana - an agent-native card that lets your AI spend at the point of sale, anywhere Visa is accepted.
Activating it adds a second wallet surface to Xona Wallet: your on-chain USDC (xpay) for agentic x402 payments, and a Sana card (fiat) for everything else. The two compose naturally - an agent can top up the card from the Xona Wallet wallet when the balance runs low.
sana.bot/gateway/app/api-keys (scope: read:all covers everything read-only; add write:card for deposits and swaps).sana_* tools appear automatically alongside the standard xpay_* tools.| Tool | What it does |
|---|---|
sana_card | Card metadata - type, status, last 4, expiry |
sana_card_balance | Available spending power on the card |
sana_card_deposit | Top up the card with USDC from the Sana wallet |
sana_card_transactions | Card spending history (paginated) |
sana_portfolio | Sana wallet net worth + token holdings with 24h changes |
sana_price | Live USD price and 24h change for any token |
sana_swap | Swap tokens inside the Sana wallet |
sana_notifications | Recent Sana wallet activity feed |
Pass the API key to forClaude / forOpenAI / forGemini to include Sana tools in your agent loop:
Or set SANABOT_API_KEY in the environment - the MCP server picks it up without any code change.
The sana_* tools disappear from the MCP server on next restart.
AgenC is a Solana-mainnet marketplace where registered agents sell services with on-chain escrow. Its hireable listings appear in xpay discover alongside x402 services - but they execute differently, and xpay routes them automatically:
| x402 service | AgenC listing | |
|---|---|---|
| Priced in | USDC | native SOL |
| Payment | HTTP X-Payment header | on-chain escrow (program HJsZ…w1xK) |
| Result | immediate HTTP response | hire receipt - the provider works asynchronously |
| Settlement | instant | after your review window (default 24h) |
The same smart routing works in the SDK and MCP - xpay.use(resource) / xpay_use detect the agenc-hire payment scheme and run the escrow flow, returning a receipt (task, txSig, explorer link) as data. Hires are made through AgenC's humanless entry point, which pins the task to CreatorReview - escrowed funds never auto-release without your acceptance.
Notes:
maxPerTx/maxPerDay before signing. If no price feed is reachable and caps are set, the hire fails closed.xpay agenc accept is planned.agenc: { rpcUrl, reviewWindowSecs, endpoint } in the profile, or XPAY_AGENC_ENDPOINT. Opt out of the discovery source with XPAY_DISCOVERY_SOURCES=orbitx402.Find any Solana token by ticker or mint address and swap into it from your own wallet - keyless, via Jupiter's meta-aggregator:
Notes:
xpay token find shows the flag.maxPerTx / maxPerDay before signing - fails closed if the token can't be priced while caps are set. Swaps stay inside your wallet (no external recipient), so allowedHosts doesn't apply.--slippage-bps) or per profile (swap.slippageBps).JUPITER_API_KEY (or profile swap.apiKey) for higher limits; XPAY_JUPITER_ENDPOINT overrides the API base.xpay sana swap swaps inside a Sana-hosted wallet and needs a Sana API key.List tradable real-world-asset tokens: RWA covers any tokenized off-chain asset, and what actually trades on Solana DEXes today is tokenized stocks/ETFs (Backed xStocks like TSLAx/SPYx, Ondo Global Markets like TSLAon/GLDon, Remora, Backpack Securities) plus the treasury-backed yieldcoin USDY. Free, read-only, no wallet:
Notes:
rwa/stocks/xstocks token tags (the tag endpoint itself doesn't accept these), so the list is Jupiter-verified and priced live. Results cache in-process for 5 minutes.xpay_rwa_find (free). Everything returned is swappable from USDC via xpay_swap / xpay swap.Trade the NOXA Fun memecoin scene on Robinhood Chain (Robinhood's Arbitrum L2, chain 4663) straight from your own wallet - no API key. NOXA Fun tokens launch into Uniswap V3 pools quoted in native ETH, so trading is plain on-chain V3: quote via QuoterV2, execute via SwapRouter02. Discovery (trending / new tokens, USD pricing) comes from GeckoTerminal's public API.
Notes:
maxPerTx / maxPerDay before signing - same boundary as xpay swap.unverified (memecoin tickers aren't unique - prefer passing the exact contract address). NOXA per-tx / max-wallet transfer caps are checked before signing: a buy that would breach one errors up front (instead of reverting on-chain), and the quote flags trades that come close.rpcs.robinhood.--slippage-bps) or per profile (trading.slippageBps).xpay balance lists your Robinhood Chain ETH plus every ERC-20 you hold (via the chain's Blockscout explorer), so tokens bought here show up automatically. Override the explorer with XPAY_ROBINHOOD_EXPLORER.xpay swap (Solana / Jupiter). GMGN was evaluated and skipped - it doesn't support Robinhood Chain.Agents can pull live X account data with zero setup - no X developer account, no API key. xpay pays xona's x402-gated proxy per call, which passes X's pay-per-use billing through at cost (no markup):
MCP: xpay_x_user / xpay_x_posts - the classic flow is token due diligence: xpay_token_find → check the project's X account → swap only if it holds up. Payments go through the normal x402 flow, so the guardrail caps apply. Endpoint override: XPAY_XDATA_ENDPOINT.
Scan any git repository for code provenance and vulnerabilities via zauth's x402-paywalled scanner (partner integration) - returns a zauth score (0–100) plus a markdown analysis. Only the scan kickoff is paid (~$0.05 USDC on Solana or Base) and the guardrail caps apply (if your profile restricts allowedHosts, add api.zauth.inc). Status checks are free and need no wallet:
A scan either returns a cached report immediately or { status: "scanning", scanId, sessionToken }; xpay polls the free status endpoint automatically and hands you the sessionToken if the scan outlives the wait window. Follow up with the sessionToken (the JWT, valid ~1 hour) - not the scanId.
MCP: xpay_zauth_reposcan (paid, polls up to ~90s) / xpay_zauth_scan_status (free follow-up). Endpoint override: XPAY_ZAUTH_ENDPOINT.
Search products across Google Shopping, Amazon, and eBay from a single free-text query via xona's x402-paywalled /shop/search endpoint (partner integration). The query parser picks up price ranges, condition, and sort straight from natural language; results come back normalized, deduped, and ranked in one schema. Price scales with the marketplaces searched: ~$0.02 USDC for all three, less for a subset (floor $0.005). Paid through the normal x402 flow, so guardrail caps apply (if your profile restricts allowedHosts, api.xona-agent.com must be on the list):
shop search runs the free quote automatically before asking for confirmation, and refuses to pay when the parser says the query is not a product search (a paid search for such a query charges but returns zero results).
MCP: xpay_shop_search (paid) / xpay_shop_quote (free preflight: agents should quote first when a query is ambiguous). MCP results are compacted for context (image/position/scoring fields dropped); xpay shop search --json keeps the full payload. Endpoint override: XPAY_SHOP_ENDPOINT.
The same partner also answers "what is this, and where do I buy it" from a photo. Give /shop/lens an image and Google Lens identifies the product and the retailers selling it, normalized into the same schema as /shop/search. Two modes: identify (default, $0.02 USDC) returns the visual matches plus a derived product name; $0.04 for all three marketplaces) additionally runs that name through Google Shopping, Amazon, and eBay for a price comparison.shop (
The lens engine itself only accepts a publicly reachable http(s) URL (SerpAPI fetches the image; data URIs are rejected), so the MCP tool takes the image as exactly one of three inputs: image_url (used as-is), image_path (local file), or image_base64 (raw or data URI). Local files and base64 are first uploaded, free, to xona's public image host (JPEG/PNG/GIF/WebP, type sniffed from magic bytes, 25MB cap) and the hosted URL is echoed back as hosted_image_url for reuse. This is what makes images from chat clients that upload attachments (Hermes and friends) work: bytes in, public URL bridged automatically.
MCP: xpay_shop_lens (paid) / xpay_shop_lens_quote (free preflight: validates an image URL is publicly reachable and reports the exact price, no wallet). Agents should quote first when passing image_url, since the paid door charges even when the URL turns out to be unusable; uploads need no preflight because the hosted URL is always reachable. If the response flags the image as not a product photo, a mode=shop retry will not help.
init configures Solana and Base by default. Add or change via ~/.xpay/<name>/config.json:
Public RPCs work for development but rate-limit hard. Production deployments should configure dedicated RPC endpoints.
Stable (chain 988, Tether/Bitfinex's payments L1) is supported as a first-class wallet network. It settles USDT0 (the LayerZero OFT at 0x779Ded0c9e1022225f8E0630b35a9b54bE713736, 6 decimals as an ERC-20), not USDC.
The same derived EVM key covers it, so a Stable signer is registered on every profile whether or not stable is in networks. You get it without re-running xpay init:
Notes:
transferWithAuthorization and the facilitator broadcasts, so the wallet needs USDT0 only - no native gas. Direct xpay transfer is broadcast from your wallet, so that path needs a little native USDT for gas.USDT0 / 1, not the USDC default. xpay never hardcodes it: the domain is read from extra on the live 402 challenge, which is the only reliable source (version() and eip712Domain() both revert on this contract).xpay balance lists them separately.eip155:988 resolves to the Stable signer, and use() compares USDT0 balance against the price when several chains are offered.rpcs.stable (default https://rpc.stable.xyz). Explorer: stablescan.xyz.m/44'/501'/0'/0', Phantom-compatible) and EVM (m/44'/60'/0'/0/0, MetaMask-compatible) keypairs. Encrypted at rest with scrypt + AES-256-GCM.Promise.allSettled, so one source failing never kills discovery). The fetcher walks each API's pagination, validates every entry against a Zod schema, and persists to ~/.xpay/cache/ so repeat lookups skip the cold-fetch tax. (Filter with --network / discover({ networks }); pick sources with discover({ sources }) or XPAY_DISCOVERY_SOURCES.)use() and useByUrl() both go: guardrail check → signer.pay(USDC) on the right network → X-Payment header → retry. The signer abstraction means the same code path works for Solana SPL transfers and EVM ERC-20 transfers. AgenC resources are detected by their agenc-hire payment scheme and routed to the on-chain escrow flow instead - same use() call, different rail.v0.2.14 (current):
xpay token find, xpay swap)xpay x user|posts)xpay zauth reposcan)xpay shop search), free quote preflightxpay token rwa): tokenized stocks/ETFs + USDY, swappable via xpay swapxpay sana link) - 8 additional sana_* toolsxpay agenc hire|status)Planned:
bridge, USDC EVM ↔ SVM via CCTP (Circle's native burn/mint)link / unlink, opt-in cloud sync (audit log, dashboard)xpay agenc accept|rate - review AgenC hire results without leaving the CLIMIT - see LICENSE.