End-to-end demo of a personalized AI stock analyst bought and paid for on BNB Chain.
The agent aggregates 5 independent data sources (yfinance, FRED macro, SEC EDGAR insider trades, Alpha Vantage AI sentiment, GNews headlines), computes 10 technical indicators (RSI, MACD, Bollinger, MA50/200 golden/death cross, ADX trend strength, OBV, ATR, VaR 95%), and writes a structured report with explicit bull/bear thesis, portfolio P&L vs your actual cost basis, and a hard recommendation with target price.
x402 payments use BSC Mainnet (chain ID 56). Every accepted analysis costs exactly 100000000000000000 atomic units (0.1 of the selected 18-decimal token).
| Token | BSC address | Method | Price |
|---|---|---|---|
| U | 0xcE24439F2D9C6a2289F741120FE202248B666666 |
eip3009 |
0.1 U |
| USD1 | 0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d |
eip3009 |
0.1 USD1 |
| USDC | 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d |
permit2-exact |
0.1 USDC |
| USDT | 0x55d398326f99059fF775485246999027B3197955 |
permit2-exact |
0.1 USDT |
B402 capabilities may be partial; choose one live supported requirement. U and USD1 use EIP-3009; USDC and USDT use permit2-exact. extra.signerAddress is facilitator EOA metadata; it is not the Permit2 spender and is not part of permit2-exact typed data. extra.spenderAddress is the live B402 proxy and the permit2-exact typed-data spender; the ERC-20 approval target remains canonical Permit2 0x000000000022D473030F116dDEE9F6B43aC78BA3.
BSC_RPC_URL is used only for USDC/USDT allowance reads, approval/revoke, and paid preflight. Use npm run x402:allowance, npm run x402:approve, and npm run x402:revoke; both approve and revoke require confirmation and --yes is an explicit noninteractive bypass. npm run x402:async never approves or revokes. Only a freshly created Permit2 reservation in the same request uses verify-and-settle. Every pre-existing stale Permit2 reservation is recovered settle-only with the identical persisted proof, regardless of pendingSettlementReference or deadline; recovery does not call /verify.
After local cryptographic payment-proof verification identifies the wallet, admission allows 30 accepted new jobs per rolling hour. The 31st request returns HTTP 429 and Retry-After before B402 verification or settlement. An exact retry does not consume another slot or settle twice. Competition reporting occurs once after terminal settlement or queued state using settledAt.
ERC-8183 is a separate on-chain escrow flow, not x402; its fixed price remains 0.21 U and its settlement and delivery behavior are unchanged.
Two payment channels are available:
| Tier | Command | Cost | Settlement | Speed |
|---|---|---|---|---|
| Paid full analysis via x402 | npm run x402:async |
0.1 U, USD1, USDC, or USDT | Binance Pay facilitator | async job |
| Paid full analysis via ERC-8183 | npm run dev |
0.21 U | on-chain escrow (trustless) | 5–15 min |
- Seller (
stockanalyst/) — stock analysis agent deployed on BNB Chain platform; serves both x402 (durable private jobs, EIP-3009 or Permit2 exact) and ERC-8183 (on-chain escrow, A2A + Cognito) in parallel. LLM: kimi-k2.6 with extended thinking. - Buyer (
buyer-client/) — TypeScript client that reads the user's portfolio and cost basis from a local UOMP Guard and supports both payment channels.
LOCAL (buyer machine) CLOUD / CHAIN
────────────────────── ─────────────
UOMP Guard (localhost:9374)
├─ portfolio: AAPL ×50, NVDA ×20
└─ profile: moderate / 12mo
│
│ [1] read context
▼
buyer-client (Node.js)
│
│
├─── x402 paid async ─────────────► public x402 API Gateway
│ sign exact 0.1-token proof └─ seller agent → Binance Pay facilitator
│ POST /x402/analyze/async kimi-k2.6 background analysis
│◄── jobId + private token ────────
│ poll status → presigned URL ──► private S3 report
│
├─[2]─ A2A negotiate ─────────────► seller agent (BNB Chain Platform :9000)
│ OAuth2 token └─ ERC-8183 sign quote → 0.21 U
│◄─────────────────────────────────── signed quote
│
├─[3]─ createJob ─────────────────► BSC Testnet (chain 97)
│ registerJob AgenticCommerce
│ setBudget U token locked in escrow
│ approve + fund
│
├─ start relay (localhost:9444)
│ Cloudflare Tunnel ──────────────► https://xxx.trycloudflare.com
│ │
├─[4]─ notify_funded ────────────► seller agent
│ EIP-712 signed context ├─ kimi-k2.6 extended thinking (~5-15min)
│ ├─[5]─ submit_result ─► BSC Testnet
│ └─[6]─ POST report ───► Cloudflare Tunnel
│ │
│◄────────────────────────────────────────────────────────────────┘
│
├─[5]─ poll getJob() ─────────────► BSC Testnet → SUBMITTED
├─[6]─ fetch report via tunnel URL
└─[7]─ settle (after 24h) ────────► BSC Testnet (escrow released)
| x402 Paid | ERC-8183 | |
|---|---|---|
| Cost | 0.1 U, USD1, USDC, or USDT | ERC-8183: 0.21 U |
| Signing | EIP-3009 or Permit2 exact | EIP-191 quote + on-chain txs |
| On-chain settlement | Binance Pay facilitator | escrow contract (trustless) |
| Report | full analysis | full analysis |
| LLM | kimi-k2.6 | kimi-k2.6 |
| Time | asynchronous | 5–15 min |
| Rate limit | 30 accepted jobs per wallet per rolling hour | none |
# Terminal 1 — start the agent locally
cd stockanalyst/app/agent
OPENAI_API_KEY=<kimi-key> WALLET_PASSWORD=<pw> python main.py
# Terminal 2 — seed UOMP portfolio context
node guard-mock.mjs
# Terminal 3 — buyer (pick one)
cd buyer-client
npm run x402:async # paid: exact 0.1 selected token, durable async analysis
npm run dev # paid: 0.21 U, full analysis, ERC-8183 trustless| Step | Who | Action |
|---|---|---|
| 1 | Buyer | Read UOMP Guard → AAPL/NVDA holdings + risk profile |
| 2 | Buyer→Seller | ERC-8183 A2A negotiate (OAuth2) → signed quote 0.21 U |
| 3 | Buyer→Chain | createJob → registerJob → setBudget → approve → fund |
| 4 | Buyer→Seller | notify_funded with EIP-712 authorization from the job-client wallet |
| 5 | Seller | kimi-k2.6 extended thinking + report (~5–15 min) → submit_result → POST to tunnel |
| 6 | Buyer | Poll chain → SUBMITTED → fetch report from local relay |
| 7 | Buyer→Chain | settle (after 24h dispute window) |
Named notify_funded calls are authenticated separately from OAuth2. The buyer
client serializes the complete delivery context once (gateway URL and token,
portfolio, and risk profile), then its existing job-creation wallet signs that
exact string as EIP-712 typed data. The request carries the decimal job_id
and that authorization envelope; the seller recovers the signer against its own
chain/Commerce domain and requires it to be the on-chain job client. The
TypeScript notifyFunded helper is the supported
way to make this request.
For remote delivery, the production default accepts public HTTPS
*.trycloudflare.com relay origins. Local loopback development is intentionally
off by default: set ALLOW_PRIVATE_DELIVERY_GATEWAY=true only for an HTTP
loopback relay. Deployments that use another approved public relay origin must
configure DELIVERY_GATEWAY_ALLOWED_HOSTS (a comma-separated exact host or
.suffix allowlist). These controls do not replace the buyer signature.
cd stockanalyst/app/agent
export WALLET_PASSWORD='<your-keystore-password>'
bag deploy agentRecord agent_id from studio.toml [deploy.platform] and create an OAuth2 client in the platform console.
The deployed agent exposes two ports:
:9000— A2A (ERC-8183, requires Cognito Bearer token):9001— x402 (public,Payment-Signatureauth only) — enabled byX402_PORT=9001env var
The public x402 V2 exchange is 402 PAYMENT-REQUIRED: base64(PaymentRequired),
followed by a retry carrying PAYMENT-SIGNATURE: base64(PaymentPayload), then
202 PAYMENT-RESPONSE: base64(SettlementResponse).
brew install cloudflare/cloudflare/cloudflared # macOS; required for ERC-8183 remote
cd buyer-client
npm install
cp .env.example .envEdit buyer-client/.env:
KEYSTORE_PATH=../stockanalyst/.studio/wallets/<address>.json
WALLET_PASSWORD=<your-keystore-password>
# ERC-8183 (cloud seller, requires OAuth2)
AGENT_ENDPOINT=https://bnbagent-api.bnbchain.world/v1/rt/<agent_id>/a2a
AGENT_CLIENT_ID=<client_id>
AGENT_CLIENT_SECRET=<client_secret>
PROVIDER_ADDRESS=<seller wallet address>
# x402 — defaults to localhost:9000; deployed value is the public mainnet gateway
X402_ENDPOINT=https://stock-agent.bnbchain.org
# Append /x402/price, /x402/analyze/async, or private job paths to this base.
# It contains neither /mainnet nor a trailing /x402. The old execute-api endpoint remains enabled during certificate/DNS/custom-domain validation and is disabled only after successful final cutover verification.
UOMP_GUARD_URL=http://127.0.0.1:9374
UOMP_GUARD_TOKEN=demo-guard-tokenBuyer wallet needs: ≥ 0.01 tBNB (gas) + ≥ 0.21 U for ERC-8183. Paid x402 accepts exactly 0.1 U, USD1, USDC, or USDT when its live capability is available.
Terminal 1 — UOMP Guard mock:
node guard-mock.mjsTerminal 2 — buyer (pick one):
cd buyer-client
npm run x402:async # paid: exact 0.1 selected token, durable async analysis
npm run dev # paid: 0.21 U, full analysis, ERC-8183 trustless (~5–15min)After the 24-hour ERC-8183 dispute window:
cd stockanalyst/app/agent && bag erc8183 settle <job_id>agent-demo/
├── guard-mock.mjs UOMP Guard mock (portfolio + risk profile)
├── stockanalyst/ Seller agent
│ ├── app/agent/
│ │ ├── main.py A2A entrypoint + x402 dual-port mode
│ │ ├── x402_handler.py x402 routes: /price /analyze/async /jobs
│ │ ├── x402_verify.py EIP-712 EIP-3009 verification (FIXED code, never LLM)
│ │ ├── seller_core.py ERC-8183 negotiate / notify_funded / fulfill
│ │ ├── signing.py Deterministic signing (never LLM tools)
│ │ ├── analysis.py yfinance data engine + technical indicators
│ │ └── tools.py LLM-callable read-only tools
│ └── README.md
└── buyer-client/ TypeScript buyer client
├── src/
│ ├── x402-async.ts Paid x402 buyer (npm run x402:async)
│ ├── index.ts ERC-8183 buyer (npm run dev)
│ ├── uomp.ts UOMP memory layer
│ ├── gateway.ts Cloudflare Tunnel relay
│ ├── negotiate.ts A2A + OAuth2
│ └── erc8183.ts On-chain buyer ops
└── README.md
| Contract | Address |
|---|---|
| AgenticCommerce | 0xa206c0517b6371c6638cd9e4a42cc9f02a33b0de |
| EvaluatorRouter | 0xd7d36d66d2f1b608a0f943f722d27e3744f66f25 |
| OptimisticPolicy | 0x4f4678d4439fec812ac7674bb3efb4c8f5fb78a6 |
| U Token (ERC-20) | 0xc70B8741B8B07A6d61E54fd4B20f22Fa648E5565 |
| Resource | Link |
|---|---|
| tBNB faucet (gas) | https://testnet.bnbchain.org/faucet-smart |
| U token faucet | https://united-coin-u.github.io/u-faucet/ |
| BSC testnet explorer | https://testnet.bscscan.com |