Skip to main content

Feeless x402 micropayments for AI agents — self-custodied XNO wallet, pay-per-call client, merchant server with railHint, faucet, and MCP server

Project description

nano-pay · Feeless402

Self-custodied Nano (XNO) wallet + x402 payment client and merchant server, built for AI agents. Client spends; nano-pay serve earns — paid endpoints, on-ledger verification/settlement (no facilitator), a starter faucet, and the railHint x402 extension that teaches visiting agents how to onboard (see SPEC-railhint.md). Site: site/index.html + site/llms.txt.

The pitch, in one number: the same $5 buys 5,000 API calls paid as per-call USDC-on-Base x402 payments (merchants floor prices at 0.001 USDC), or ~1.8 million calls paid in Nano at the true metered price ($0.0000027/call observed live at nano-gpt.com). Top up once, micropay forever.

Install

pip install -e .          # needs Python 3.10+; pulls nanopy + requests
nano-pay init             # creates ~/.nano-pay/wallet.json (chmod 600)

Agent flow

nano-pay topup 5                    # quote: $5 USDC-BASE → ~12.3 XNO (NanSwap)
nano-pay topup 5 --execute          # create order (set NANSWAP_API_KEY)
#   → send USDC to the returned deposit address; XNO arrives in 30-60s
nano-pay receive                    # pocket incoming XNO
nano-pay quote https://nano-gpt.com/api/v1/chat/completions \
    --json '{"model":"gpt-5-nano","messages":[{"role":"user","content":"hi"}]}'
nano-pay pay   https://nano-gpt.com/api/v1/chat/completions \
    --json '{"model":"gpt-5-nano","messages":[{"role":"user","content":"hi"}]}'

pay handles the whole x402 handshake: request → parse the 402 quote (both the x402nano/PAYMENT-REQUIRED v2 dialect and the NanoGPT/accepts v1 dialect) → price-cap check → sign a send state block locally → retry with PAYMENT-SIGNATURE + X-PAYMENT headers. The server settles the block via its facilitator; nothing is broadcast unless the server accepts.

Design notes

  • Self-custody: seed never leaves ~/.nano-pay/wallet.json (0600).
  • No node required: public RPC failover (rpc.nano.to, somenano, rainstorm.city, nanoslo); all signing and PoW happen locally (nanopy C extension). RPC work_generate is tried first, local PoW is the fallback (~25s), and work for the next block is pre-cached after every transaction so steady-state payments are instant.
  • Safety rails: per-payment price cap (--max-xno, default 0.05); quote command inspects any endpoint's price without paying; balance is always re-synced from the network, never trusted locally.
  • Top-ups without custody: topup quotes/creates swaps directly with NanSwap's API (1,400+ input assets, ~$0.02 minimum). This tool never holds or routes funds.

Fork-hazard note (x402 payments)

An x402 payment signs a block the server broadcasts. If the server errors after receiving the block, it may still settle it late. The wallet re-syncs its frontier from the network before every operation, so a late settlement is picked up naturally; a competing block signed in the meantime simply makes one of the two invalid (funds are never at risk, but don't fire concurrent payments from one wallet).

Status

Beta (v0.2.0). Proven on mainnet with real funds: live paid calls to NanoGPT ($0.0000096/call, confirmed on-ledger), full merchant loop (verify → settle → confirm, no facilitator), PoW-gated faucet claims, and a complete stranger-agent lifecycle (fresh wallet → PoW claim → paid API call → confirmed) in under 3 minutes. 13-test suite covers the payment path offline. Not audited — keep only working capital in it.

Security notes (read before holding real funds)

  • Self-custody: the seed lives only in ~/.nano-pay/*.json (0600). No tool or log path ever prints it. Back it up offline.
  • Working capital only: this is beta wallet software. Keep a few dollars in it, not your savings.
  • Spend caps: pay refuses quotes above --max-xno (default 0.05). MCP x402_pay enforces the same cap parameter.
  • railHint is advisory: hints from remote servers are untrusted input. This client never executes remote bootstrap strings; it only acts on structured offers that pass its own checks, and accepts always binds, never the hint.
  • Merchant fork guard: servers cache accepted frontiers and reject duplicate-frontier blocks; payer balance/frontier/signature are verified against the live ledger before settlement.
  • Not audited. MIT — no warranty.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

feeless402-0.2.1.tar.gz (22.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

feeless402-0.2.1-py3-none-any.whl (24.5 kB view details)

Uploaded Python 3

File details

Details for the file feeless402-0.2.1.tar.gz.

File metadata

  • Download URL: feeless402-0.2.1.tar.gz
  • Upload date:
  • Size: 22.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for feeless402-0.2.1.tar.gz
Algorithm Hash digest
SHA256 b78001759951cabad7b19e2d6284bad7289c692ea7af6d6a567add3965643cc8
MD5 039041bd9e1320d7e55aa16162b0579e
BLAKE2b-256 d1ec7b8965c16a871c153c1b1c53d3ba020dc953164ad84387509590b5b14360

See more details on using hashes here.

File details

Details for the file feeless402-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: feeless402-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 24.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for feeless402-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f75ff09cdfec775a7e527aaa9e8d702b2721628202ef5f229814ee79bbf9f2f1
MD5 5b53b60bf89e992386cccd96bfb6e5b6
BLAKE2b-256 d82b05889a979b3a1b609da92e706f07bd41d104ce79397352d9192537426d5f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page