Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AEON x402 Payment Demo (V2)

中文文档

A minimal Node.js client that pays an AEON QR-code order over the x402 protocol (V2). It demonstrates the full machine-to-machine payment loop:

  1. Request the payment API without a payment header → receive HTTP 402 Payment Required with the x402 V2 payment requirements.
  2. Verify the wallet balance, sign an EIP-712 payment authorization locally (the private key never leaves your machine).
  3. Retry the request with the PAYMENT-SIGNATURE header → the server verifies and settles on-chain through the AEON facilitator and returns the settlement result in the PAYMENT-RESPONSE header.
┌────────┐  GET /payment (no header)                ┌────────────┐
│ Client │ ───────────────────────────────────────► │ AEON  API  │
│        │ ◄─────────────────────────────────────── │            │
│        │  402 { x402Version:2, resource, accepts }│            │
│        │                                          │            │
│        │  sign EIP-712 authorization locally      │            │
│        │                                          │            │
│        │  GET /payment + PAYMENT-SIGNATURE        │            │      ┌─────────────┐
│        │ ───────────────────────────────────────► │            │ ───► │ Facilitator │ ──► on-chain
│        │ ◄─────────────────────────────────────── │            │ ◄─── │ verify/settle│     transfer
└────────┘  200 + PAYMENT-RESPONSE (tx hash)        └────────────┘      └─────────────┘

Supported networks & tokens

The token is selected with the token parameter (CLI arg or TOKEN env); USDT is the default when not specified.

Mode Network USDT USDC USDG
base Base (eip155:8453) facilitator scheme EIP-3009 (gasless) –
x X Layer (eip155:196) – EIP-3009 (gasless) EIP-3009 (gasless)
bsc BSC (eip155:56) facilitator scheme facilitator scheme –
  • EIP-3009 (gasless): sign TransferWithAuthorization directly; no transaction is sent by the client.
  • Facilitator scheme: the token does not implement EIP-3009 (USDT on all chains, USDC on BSC). The client sends a one-time ERC-20 approve to the AEON facilitator contract (requires a small native-token balance for gas), then signs tokenTransferWithAuthorization. Settlement gas is sponsored by the facilitator. The server tells the client which scheme to use via accepts[].extra.eip3009.

Project structure

.
├── src/
│   ├── config/app.js         # Configuration (env-driven)
│   ├── sign/createX402Sign.js# EIP-712 signing (both schemes) + PAYMENT-SIGNATURE builder
│   └── main.js               # Payment flow: 402 → balance check → sign → settle
├── qrcode.txt                # Payment QR code string (sample included)
├── .env.example              # Configuration template
└── package.json

Quick start

Requires Node.js ≥ 18.

npm install
cp .env.example .env    # then edit .env

Set at least these two values in .env:

PRIVATE_KEY=0x...your wallet private key...
EMAIL=you@example.com

Put the QR code string you want to pay into qrcode.txt (or set QR_CODE in .env), then run:

npm run pay:base        # pay with USDT on Base (default token)
npm run pay:bsc         # pay with USDT on BSC
npm run pay:x           # pay with USDT on X Layer

Equivalent direct invocation: node src/main.js [base|bsc|x] [usdt|usdc], e.g.:

node src/main.js bsc          # USDT on BSC (token defaults to USDT)
node src/main.js bsc usdc     # USDC on BSC
node src/main.js base usdc    # USDC on Base (gasless EIP-3009)
node src/main.js x usdg       # USDG on X Layer (gasless EIP-3009)

Note: X Layer does not support USDT — pass usdc or usdg explicitly when using x mode.

Example output

Running in BSC mode (x402 V2)
{ address: '0x34B7...F510' }
Fetching x402 V2 payment requirements...
Accept: { amount: '550000000000000000', asset: '0x8ac7...580d', network: 'eip155:56', payTo: '0x043b...6669', ... }
Balance check on eip155:56: 9.90 USDC available, 0.55 USDC required
Generated PAYMENT-SIGNATURE header: eyJ4NDAyVmVyc2lvbiI6MiwicGF5bG9hZCI6...
Sending payment request with PAYMENT-SIGNATURE header...
Payment request status: 200
PAYMENT-RESPONSE header: { success: true, transaction: '0x…', network: 'eip155:56', payer: '0x34B7…F510' }

Configuration

All settings are read from .env (see .env.example):

Variable Required Default Description
PRIVATE_KEY yes – Payer wallet private key (signs locally only)
EMAIL yes – Email attached to the order
APP_ID no TEST000001 Merchant appId issued by AEON
PAYMENT_API_URL no https://ai-api.aeonpay.ai/open/ai/402/payment Payment API endpoint
QR_CODE no contents of qrcode.txt QR code string to pay
TOKEN no USDT Payment token (USDT / USDC / USDG); CLI arg wins
RPC_URL_BSC / RPC_URL_BASE / RPC_URL_XLAYER no public RPCs JSON-RPC endpoints for balance checks / approve

How the payment header is built

The PAYMENT-SIGNATURE header is the Base64 of:

{
  "x402Version": 2,
  "payload": {
    "authorization": {          // what the wallet authorizes
      "from": "0xPayer",
      "to": "0xPayTo",
      "value": "550000000000000000",
      "validAfter": "1786506621",
      "validBefore": "1786506981",
      "nonce": "0x…32 random bytes…"
    },
    "signature": "0x…EIP-712 signature…"
  },
  "resource": { "url": "…", "description": "…", "mimeType": "application/json" },
  "accepted": { /* the accepts[] entry being paid, echoed back */ }
}
  • For EIP-3009 tokens the EIP-712 domain is the token contract itself (name/version come from accepts[].extra), type TransferWithAuthorization.
  • For non-EIP-3009 tokens the domain is the AEON facilitator contract ({ name: "Facilitator", version: "1" }), type tokenTransferWithAuthorization with an extra needApprove: true field, and addresses are lowercased in the signed message.
  • The scheme is chosen by the accepts[].extra.eip3009 flag from the 402 response.

The authorization expires after maxTimeoutSeconds (from the 402 response), and the random nonce prevents replay.

Troubleshooting

Symptom Cause / fix
Insufficient USDC balance on eip155:56 … The wallet holds less than the required amount — top up the token shown in the message. Checked before signing, so no gas is wasted.
Server is not x402 V2 (x402Version=…) The endpoint is running the V1 protocol — check PAYMENT_API_URL.
Expected 402 Payment Required, got … with code 2102 Server-side order creation failed (e.g. the deposit-address channel for that network is not configured in this environment).
Settlement failed: …transfer amount exceeds balance… Balance changed between the check and settlement.
First BSC payment sends a transaction That is the one-time approve to the facilitator; it needs a small BNB balance for gas.

Security notes

  • Never commit .env — it contains your private key (.gitignore already excludes it).
  • The private key is used only to sign locally and to send the optional BSC approve transaction; it is never transmitted.
  • The signed authorization is bound to the exact recipient, amount and expiry returned by the server, and single-use via the nonce.
  • Use a dedicated hot wallet with a small balance for automated payments.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages