Skip to content

alexbelij/AgentEscrow402

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

208 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

AgentEscrow402

HTTP 402 Γ— Casper Network: autonomous escrow for AI-to-AI micropayments

Agents pay agents. On-chain. No humans in the loop.

CI Python 3.11+ Casper Network License: MIT Live Demo Hackathon

Try it β€” ae402.xyz

πŸš€ Live Demo Β· πŸ“ Architecture Β· πŸ“‘ API Reference Β· SDK Docs


Important

What this is: A deployed Casper testnet escrow console for AI-agent payments: signed x402 payment intent, Casper deploys for escrow lifecycle calls, Neon-backed hosted records, IsolationForest risk scoring, ML-KEM metadata encryption, and VRF-assisted arbitration. Console live at ae402.xyz; API live at agentescrow402-api.onrender.com.

Table of contents

✨ What makes it unique

The x402 protocol defines machine-to-machine payments via HTTP 402 headers. Existing implementations assume Ethereum facilitators. AgentEscrow402 brings the pattern to Casper Network with live testnet escrow calls plus a hosted console that labels what is on-chain, what is Neon-backed API state, and what is demo-signer convenience for browsers.

Feature AgentEscrow402 Coinbase x402 Manual invoicing
Trustless on-chain escrow βœ… Time-locked WASM contract ❌ Facilitator holds funds ❌ N/A
Reputation tracking βœ… Exponential decay, per-agent ❌ None ❌ None
Multi-sig dispute resolution βœ… 3-of-5 arbiter vote ⚠️ Facilitator decides ⚠️ Manual
Zero human facilitation βœ… Fully agentic ⚠️ Needs setup ❌ Always human
Casper Network native βœ… WASM contract ❌ EVM only β€”
Multi-asset escrow βœ… CSPR, CEP-18, CEP-78 (real on-chain) ❌ Single asset β€”
Atomic secret-for-payment swap βœ… SHA-256 HTLC commit/reveal ❌ Not supported β€”
AI-assisted dispute triage βœ… Evidence scoring feeds the arbiter vote ❌ None ❌ None
Sybil-resistant agent identity βœ… DID registry, staking + slashing ❌ None β€”
Post-quantum metadata confidentiality βœ… ML-KEM-768 hybrid encryption ❌ None β€”
Production maturity / ecosystem adoption ⚠️ Hackathon-stage, testnet only βœ… Live, mainnet, adopted by real facilitators βœ… Universally understood

See what's real vs. simulated for exactly which of these are live on-chain today versus API-level.


βš™οΈ How it works

Four steps, no human signature required mid-flow (see verified on-chain transactions and what's real vs. simulated for the exact scope of that claim).

  1. Agent A creates escrow β€” locks funds in a time-locked Casper contract with a TTL and service hash
  2. Agent B verifies payment β€” checks the x402 header against the on-chain escrow before serving work
  3. Agent A releases β€” confirms delivery; funds transfer to Agent B; reputation score updates
  4. Timeout protection β€” if Agent B never delivers, Agent A reclaims funds after TTL expires; no arbiter needed
Agent A                    Payment Server                 Casper Network
  β”‚                            β”‚                              β”‚
  β”œβ”€ POST /escrow ────────────▢│                              β”‚
  β”‚  {receiver, amount, ttl}   │── create_escrow() ─────────▢│
  β”‚                            β”‚                              β”‚ funds locked
  │◀── 201 {service_hash} ─────                              β”‚
  β”‚                            β”‚                              β”‚
  β”œβ”€ GET /api/compute ────────▢│                              β”‚
  β”‚  X-Payment: x402-v1;...    │── verify header ───────────▢│
  β”‚                            │◀─ ok ───────────────────────
  │◀── 200 result ─────────────                              β”‚
  β”‚                            β”‚                              β”‚
  β”œβ”€ POST /release ───────────▢│── release() ───────────────▢│
  β”‚  {service_hash}            β”‚                              β”‚ funds β†’ Agent B
  │◀── 200 ────────────────────  reputation updated on-chain β”‚

x402 header format: X-Payment: x402-v1;<escrow_hash>;<amount>;<sender>;<timestamp>;<nonce>;<signature>

Protected endpoints return 402 Payment Required with machine-readable terms when the header is missing.

This is the base happy-path lifecycle. The dispute-resolution vote, HTLC atomic-swap commit/reveal, and multi-asset (CEP-18/CEP-78) flows each have their own diagram in docs/ARCHITECTURE.md rather than being crammed into this one.

Every escrow moves through the same on-chain states regardless of which exit path it takes β€” created, then released, refunded, or disputed β†’ resolved:

stateDiagram-v2
  [*] --> Pending: create_escrow()\nfunds locked, TTL set
  Pending --> Released: release()\n(sender confirms delivery)
  Pending --> Refunded: refund()\n(caller, after TTL expiry)
  Pending --> Disputed: dispute()\n(sender or receiver)
  Disputed --> Released: resolve()\n3-of-5 arbiter vote β†’ payee
  Disputed --> Refunded: resolve()\n3-of-5 arbiter vote β†’ sender
  Released --> [*]
  Refunded --> [*]
Loading

Text fallback: an escrow starts Pending; it exits via release (seller paid), refund (TTL expired, nobody delivered), or dispute β†’ 3-of-5 arbiter resolve, which routes funds to either side. commit_swap/reveal_swap is a variant exit on the same Pending state β€” see the HTLC atomic-swap flow below.

Full product scope

All escrow types share the same on-chain core but add specialised flows on top:

flowchart LR
    subgraph Escrow Types
        A["πŸ”’ Standard\nCSPR escrow"]
        B["πŸͺ™ Multi-Asset\nCEP-18 / CEP-78"]
        C["🌊 Streaming\nLinear vesting"]
        D["πŸ”— Atomic Swap\nHTLC commit-reveal"]
        E["πŸ“¦ Batch\nBulk create/release"]
    end

    subgraph On-Chain Core
        F["Smart Contract v9\n(8 entry points)"]
    end

    subgraph Security Layer
        G["πŸ›‘οΈ Release Cap\n+ Arbiter Quorum"]
        H["🎲 VRF Election\nOn-chain randomness"]
        I["🏦 Insurance Pool\nRisk-scaled premiums"]
        J["πŸ†” Identity Registry\nDID + reputation"]
    end

    A & B & C & D & E --> F
    F --> G & H & I & J
Loading

πŸ›‘οΈ No-unilateral-withdraw guard: release cap + arbiter quorum

The escrow contract's sender key is not, by itself, sufficient authorization to move funds above a configurable cap. This is enforced on-chain in contracts/escrow/src/main.rs, not in the API layer:

  • A release_cap named key (RELEASE_CAP_KEY) defaults to 1_000_000_000_000 motes = 1,000 CSPR (DEFAULT_RELEASE_CAP_MOTES) and is retunable on-chain via set_release_cap (installer-only) with no redeploy needed.
  • Both fund-releasing entry points β€” release() and reveal_swap() (the HTLC path below) β€” call read_release_cap() and compare it against the escrow amount. Below the cap, the sender's own signed call is enough, exactly like today's happy path.
  • Above the cap, the sender's signature alone is rejected. The caller must additionally supply arbiter_pubkeys/arbiter_signatures covering a canonical "release:<service_hash>:cap_approval" (or "reveal_swap:...") message. require_arbiter_cap_approval() β†’ verify_arbiter_quorum() checks that at least threshold (default 3, same registered-arbiter list resolve() uses) distinct, registered arbiters produced valid Ed25519 signatures over that exact message β€” dedup'd, so one arbiter can't sign twice to fake a quorum. Fail the quorum check and the call reverts with ERR_CAP_EXCEEDED; no funds move.
  • In other words: propose β†’ arbiter-quorum approve β†’ release, not agent key β†’ release, for anything above the cap. A compromised or malicious agent key can drain at most the cap amount unilaterally; anything larger requires collusion or compromise of a majority of the independently-held arbiter keys.
  • Confirmed on the deployed v9 contract: the resolve (3-of-5 multisig) gas-benchmark entry in docs/GAS_BENCHMARK.md measures the same signature-verification code path this guard reuses (~7.5 CSPR gas for 3 on-chain Ed25519 verifications vs. ~3.2 CSPR for a plain release).
flowchart TD
  A["release() / reveal_swap() called\namount known"] --> B{"amount > release_cap?"}
  B -- "no (below cap)" --> C["Direct release\nsender signature only"]
  C --> D["funds β†’ receiver"]
  B -- "yes (above cap)" --> E["Sender proposes:\nsubmit arbiter_pubkeys +\narbiter_signatures"]
  E --> F{"verify_arbiter_quorum()\n>= threshold distinct,\nregistered, valid sigs?"}
  F -- "no" --> G["revert ERR_CAP_EXCEEDED\nno funds move"]
  F -- "yes" --> D
Loading

Text fallback: below the configurable cap, the sender's own call releases funds directly; above it, the sender's call is rejected unless it also carries a quorum of registered-arbiter Ed25519 signatures over the exact release/service-hash message β€” otherwise the transaction reverts and no funds move.

This is a structural safety property, not a policy promise: it's enforced by the contract bytecode itself for release/reveal_swap. The escrow-manager's batch_release/batch_cancel entry points are wired to API endpoints with a server-side cap/quorum guard β€” see docs/STATUS_AND_ROADMAP.md.


πŸš€ Quickstart

Under 5 minutes for local development. No Casper node needed β€” sandbox mode is default locally.

Prerequisites: Python 3.11+

git clone https://github.com/alexbelij/AgentEscrow402.git
cd AgentEscrow402
pip install -r requirements.txt
cp .env.example .env
python -m uvicorn server.app:app --host 0.0.0.0 --port 8000

Verify:

curl http://localhost:8000/health
# {"status":"ok","sandbox":true,"db":"disconnected",...}

Create your first escrow

curl -X POST http://localhost:8000/escrow \
  -H "Content-Type: application/json" \
  -H "X-Payment: x402-v1;<service_hash>;5000000;<sender>;<timestamp>;<nonce>;<signature>" \
  -d '{"receiver":"agent-B","amount":5000000,"service_hash":"<64-hex>","ttl":300}'
# {"service_hash":"<64-hex>","status":"pending",...}

Check status

curl http://localhost:8000/escrow/<service_hash>
# {"service_hash":"<64-hex>","status":"pending","amount":5000000,...}

Release after delivery

curl -X POST http://localhost:8000/release \
  -H "Content-Type: application/json" \
  -H "X-Payment: x402-v1;<service_hash>;5000000;<sender>;<timestamp>;<nonce>;<signature>" \
  -d '{"service_hash":"<64-hex>"}'
# {"status":"released",...}

Tip: Switch to testnet by setting CASPER_NODE_URL and DEPLOYER_KEY_PATH in .env.


πŸ” What is real vs. simulated

Judging a hackathon project means separating "works in a demo" from "works on-chain." Here's the honest breakdown, verified against the current deployment (contract package d3ca33d1...c8eeb, version 9, updated 2026-07-07):

Component Status Evidence
Escrow create / release / refund / dispute / resolve βœ… Real on-chain Real Casper testnet transactions in live mode (SANDBOX=false, what production runs); see Verified on-chain
Release cap + arbiter-quorum guard on release/reveal_swap βœ… Real on-chain Enforced in contract bytecode, not the API; see No-unilateral-withdraw guard
HTLC atomic-swap (commit_swap / reveal_swap) βœ… Real on-chain SHA-256 commit/reveal entry points, live round-trip with cross-account reveal
CEP-18 (fungible token) transfers βœ… Real on-chain Deployed test token AETUSD, transfer + balance read against live contract state
CEP-2612-inspired gasless permit (CEP-18) βœ… Real on-chain Custom permit()/permit_nonce() entry points added to a forked CEP-18 contract (Ed25519-signature-gated allowance, no session-wasm needed); live-verified: owner signs an off-chain message only, relayer submits permit()+transfer_from() and pays gas, real balance moves
CEP-78 (NFT) mint/transfer βœ… Real on-chain Deployed test collection AETNFT, mint + transfer + ownership read against live contract state
ID-1 Agent Identity Registry (DID + stake + reputation) βœ… Real on-chain, separate contract Standalone deployed contract, not the escrow contracts; see ID-1 registry and docs/AGENT_IDENTITY_REGISTRY.md
x402 signature verification βœ… Real crypto Ed25519 verify (cryptography lib) + nonce replay protection, not a stub
Reputation scoring, staking, slashing (off-chain API) βœ… Real logic Exponential decay + stake-weighted slashing in identity_registry_api.py β€” separate from the on-chain ID-1 registry above
Arbiter multisig resolution (resolve) βœ… Real crypto Real Ed25519 3-of-5 quorum check over the escrow/verdict payload, replay-proof
VRF-assisted arbiter election (/vrf/elect) βœ… Real on-chain election Submits select_arbiters to the deployed vrf-arbiter contract, waits for finalization, and reads the result back; falls back to a reputation-weighted local CSPRNG only when the contract is unavailable/unconfigured or every on-chain candidate for a draw is a dispute party β€” see VRF-assisted arbiter election below
Payment streaming (/escrow/stream) ⚠️ API-level simulation Streamed/remaining amount computed from wall-clock time in the backend; not an on-chain per-tick release yet
Hosted console demo-signer ⚠️ Explicit, labelled bypass One fixed public demo identity + signature, gated by ALLOW_HOSTED_DEMO_IDENTITY, so browser visitors without a wallet can try the console β€” never used in the signature-verification code path for real requests
TEE-attested proofs, on-chain ZK-KYC, cross-chain bridge ❌ Not implemented Roadmap ideas only β€” would need real TEE hardware or a ZK circuit; out of scope for the hackathon deadline, see ROADMAP.md

VRF-assisted arbiter election

POST /vrf/elect (server/vrf_election.py) picks a dispute's arbiter via a real on-chain call to the deployed vrf-arbiter contract instead of a purely off-chain choice: it submits select_arbiters(dispute_id, count), polls until the transaction finalizes, and reads the elected candidates back from elections_dict. Because the contract's select_arbiters has no notion of dispute parties, INVARIANT 5 (arbiter must not be either dispute party) is enforced by the backend over the returned candidate list β€” requesting more than one candidate per election leaves room to drop any that are also parties. 4 arbiters are currently registered on-chain via register_arbiter (staked purses). The API response's method field is genuinely "onchain_vrf" when this succeeds, and only falls back to "local_csprng" (a reputation-weighted local pseudo-random choice) when the contract is unavailable/unconfigured, or β€” as verified live β€” when every on-chain candidate returned for a given draw happens to be a dispute party. Real testnet deploy hashes and both a normal election and that exclusion stress case are in docs/evidence/VRF_ONCHAIN_ELECTION.md.

Full architecture details and roadmap in docs/STATUS_AND_ROADMAP.md β€” kept current, not a one-time snapshot.


🧩 Use cases

Concrete scenarios this unlocks today, not hypotheticals:

  1. Autonomous data-provider agents β€” an AI agent buys a single API call, dataset row, or model inference from another agent, pays through escrow, and the seller only gets funds once the buyer confirms receipt. No invoicing, no manual reconciliation, no trusted intermediary holding the money.
  2. Multi-agent pipelines with built-in recourse β€” a chain of agents (scraper β†’ summarizer β†’ translator) each escrow-pay the next step; if any step fails to deliver, the TTL-based refund or the 3-of-5 arbiter dispute path returns funds automatically instead of the payer eating the loss.
  3. Reputation-gated marketplaces β€” buyers can filter sellers by on-chain reputation score (exponential decay + slashing) before ever escrowing funds, so bad actors lose standing automatically rather than needing a human moderator.
  4. Cross-asset agent payments β€” an agent can be paid in native CSPR, a fungible token (CEP-18), or even receive an NFT (CEP-78) as proof-of-service, all through the same escrow lifecycle and the same x402 header.
  5. Atomic secret-for-payment swaps β€” the HTLC commit_swap/reveal_swap flow lets a seller release a secret (an API key, a decryption key, a proof) only in the same transaction that pays them β€” either both happen or neither does.

HTLC atomic swap, step by step

Real hash-time-lock contract flow (commit_swap/reveal_swap in contracts/escrow/src/main.rs), not a simulated swap:

sequenceDiagram
  participant Sender
  participant Contract as escrow contract
  participant Receiver

  Sender->>Contract: commit_swap(service_hash, sha256(preimage))
  Note over Contract: hash-lock stored,\nnot revealed yet
  Note over Sender,Receiver: off-chain: external condition met\n(e.g. secret handed over once paid elsewhere)
  Receiver->>Contract: reveal_swap(service_hash, preimage,\narbiter_pubkeys, arbiter_signatures)
  Contract->>Contract: sha256(preimage) == commit_hash?
  alt hash matches AND (amount <= cap OR quorum verified)
    Contract->>Receiver: funds released
  else hash mismatch or above-cap quorum missing
    Contract-->>Receiver: revert (ERR_INVALID_PREIMAGE / ERR_CAP_EXCEEDED)
  end
Loading

Text fallback: the sender locks a SHA-256 hash on-chain with commit_swap; funds only move once someone calls reveal_swap with the exact preimage β€” verified on-chain, not by a trusted party β€” and, above the release cap, also with a valid arbiter-quorum signature set. Live-verified on testnet with a different account revealing than the one that committed (see Verified on-chain).


🧱 Architecture

flowchart LR
  A["Agent A\n(Payer)"] -->|"POST /escrow\nfunds + TTL"| MW

  subgraph Server ["Payment Server β€” FastAPI"]
    MW["x402 Middleware\nheader parse + verify"]
    API["REST API"]
    MW --> API
  end

  API -->|"create_escrow()"| ESC

  subgraph Chain ["Casper Network"]
    ESC["escrow.wasm\nTime-locked contract"]
    REP["Reputation Store\nExp. decay scoring"]
    ARB["Arbiter Pool\n3-of-5 multi-sig"]
    ESC --> REP
    ESC --> ARB
  end

  ESC -->|"funds locked"| B
  B["Agent B\n(Payee)"] -->|"X-Payment header\nservice delivery"| MW
  A -->|"POST /release"| API
  API -->|"release() β†’ funds β†’ B\nreputation++"| ESC
Loading

The payment server mediates between agent SDKs and the Casper contract. In sandbox mode the Casper client is replaced by an in-memory store. In the hosted demo, API records are persisted in Neon while the console clearly labels the hosted demo signer versus production x402 signatures.

Detailed diagrams β†’ docs/ARCHITECTURE.md


πŸ“Έ Screenshots

Real screenshots of the live deployment (captured 2026-07-05, not mockups):

Homepage Console overview
Homepage Console overview
Escrows table Escrow detail Arbitration (AI dispute analysis)
Escrows Escrow detail Arbitration

Live at ae402.xyz Β· ae402.xyz/console/overview


πŸ“œ Smart contract

Deployed on Casper Testnet:

Contract Hash Explorer
Core Escrow 612cead2226329fafec492042fd96a999df06d1e88c476913a167f44d3ddd9ec (package: d3ca33d192dda5ece798db91811ec1259d2197ca0e8d3ea4de043b977d3c8eeb, v9) view
Escrow Manager bfa8c02cb3ab0f9d7bf03335f324973675200a597162e1e5fa4cb5a77dff675d view
Insurance Pool e128780fd7e41159df4ca14d8584c7ef0cea2d75e6d5ba4166d94ca41f2d8929 (hardened redeploy β€” the old e36b958d... had a fully public claim()/withdraw(), superseded) view
VRF Arbiter 78ae28702deeb2eadec573d95b870f68b928a82a3566e292ff33a9ae2c779c93 (package: 53805f7866cd158ff091ab93efe2f19bd2e803414a5ef1badc7a46d759f36611) β€” real on-chain election write path wired and live-verified, 4 arbiters registered (see VRF section) view
Agent Identity Registry (ID-1) 1f29271d986818254d42e5551dd8fbb2e2b7f7295bdfcd6558639584ad311cae (package: 0b760bb7bf9be5a74ee4ed5626bcc74a8154f221a059e29fc9d768d45fb4a2ba, v2) β€” standalone DID/stake/reputation registry, separate from the escrow contracts view
MultiAssetEscrow (CEP-18) 52db09a146158ba2a07b5da07587046985ce8ca3be094fca9ad63cb6b9ecd12a (package: a3207e9bb29f6cec6c5017e6c7538626f92f001d35cda22585dff9f76a488044) β€” real contract-custody escrow for CEP-18 tokens, full lifecycle verified on-chain view
CEP-18 test token (AETUSD) 177ca5d88f72e1ca72fbe94a24ba34b03830dd1fe63d90d3d719cd6e6d4de754 view
CEP-18 test token (AEMAT) 8ba7df6fd9a12c71de903a915717537eeff4f04adf33f4ed8abf16c254e300a5 (package: 5caa324c3073a8b9fc05076a01e9d4d658cb08a1b4839fa0aa93dac39213e3fd) β€” custody-compatible token (uses get_immediate_caller) view
Entry point Description
create_escrow Lock funds with TTL and service hash
release Confirm delivery β†’ funds to receiver (arbiter-quorum-gated above the release cap)
refund Reclaim after TTL expiry
dispute Open a contested payment
resolve 3-of-5 arbiter vote β†’ auto-payout
commit_swap HTLC atomic-swap: sender locks a SHA-256 hash of a secret
reveal_swap HTLC atomic-swap: anyone who knows the secret releases funds
configure_fee Set insurance pool fee (basis points)
set_release_cap Update the amount above which an arbiter-quorum approval is required
set_arbiters Rotate the 5-account arbiter pool (no redeploy needed)
emergency_freeze Pause all state changes (installer-only)
unfreeze Resume operations after emergency_freeze (installer-only)

Security status: latest changed code was reviewed through NVIDIA API and no concrete HIGH blockers were reported for the console/Neon patch. Architecture decisions and roadmap are documented in docs/STATUS_AND_ROADMAP.md.


πŸ“‘ API reference

Base URL (production): https://agentescrow402-api.onrender.com

Full OpenAPI spec β†’ docs/openapi.yaml

All 62 endpoints β€” click to expand
Method Path Description
Core escrow
GET /health Server health + mode
GET /stats Console statistics and data-source label
GET /contracts Deployed contract hashes and roles
GET /escrows List escrows (filter by status, paged)
GET /escrow/{hash} Look up escrow by service hash
GET /escrow/{hash}/history Full state-change history of an escrow
POST /escrow Create escrow β€” lock funds
POST /release Release funds to receiver
POST /refund Refund sender after TTL
POST /dispute Open dispute (sender or receiver)
POST /resolve Arbiter vote (3-of-5)
POST /compute-hash Derive service hash from params
GET /reputation/{agent} Agent trust score
GET /agents List all known agents with reputation
GET /estimate Fee + insurance estimate for an amount
GET /events SSE stream of escrow events
GET /wasm/escrow_funder Download escrow_funder.wasm binary
Batch operations
POST /escrows/batch Create multiple escrows in one call
POST /escrows/batch-release Release multiple escrows atomically
POST /escrows/batch-cancel Cancel (refund) multiple escrows
Multi-asset & streaming
GET /escrow/cep18-permit-nonce CEP-18 gasless permit nonce lookup
POST /escrow/multi-asset Create CEP-18/CEP-78 token escrow
POST /escrow/multi-asset/{hash}/release Release multi-asset escrow
POST /escrow/multi-asset/{hash}/refund Refund multi-asset escrow
POST /escrow/multi-asset/{hash}/dispute Dispute multi-asset escrow
POST /escrow/multi-asset/{hash}/resolve Resolve multi-asset escrow
POST /escrow/stream Create linear-vesting streaming escrow
GET /escrow/{hash}/stream-status Streaming escrow vesting status
POST /escrow/{hash}/stream-claim Claim fully-vested streaming escrow
Atomic swap (HTLC)
POST /escrow/atomic-swap/commit Commit SHA-256 hash-lock
POST /escrow/atomic-swap/reveal Reveal preimage to release funds
AI arbitration
POST /arbitration/analyze AI-assisted dispute evidence analysis
GET /arbitration/history Recent arbitration recommendations
VRF arbiter election
POST /vrf/elect VRF-assisted on-chain arbiter election
GET /vrf/election/{dispute_id} Look up election result
GET /vrf/arbiters List registered arbiters
POST /vrf/arbiters/register Register an agent as arbiter
Insurance pool
POST /insurance/deposit Deposit into insurance pool
POST /insurance/claim Claim from insurance pool
GET /insurance/pool-stats Pool balance and accounting
GET /insurance/premium-quote Risk-scaled premium quote
Agent identity (on-chain)
POST /identity/register Register identity with on-chain deploy
GET /identity/{agent_id} Look up on-chain agent identity
POST /identity/delegate Delegate capability to sub-agent
GET /identity/capabilities/{agent_id} Own + delegated capabilities
Identity registry (hosted)
POST /identity-registry/register Register DID + stake + capabilities
GET /identity-registry/{did} Look up by DID
GET /identity-registry/by-account/{hash} Look up by account hash
POST /identity-registry/{did}/reputation Update reputation counters
POST /identity-registry/{did}/decay Apply time-based reputation decay
POST /identity-registry/{did}/slash Slash stake for misbehaviour
POST /identity-registry/{did}/verify Advance verification level
POST /identity-registry/{did}/capabilities Update agent capabilities
GET /identity-registry/search/agents Search agents by capability/score
GET /identity-registry/stats/summary Registry-wide summary stats
Risk scoring
GET /risk/score/{agent} IsolationForest agent risk score
GET /risk/dashboard Aggregated risk dashboard
Admin (API-key gated)
POST /admin/configure-fee Set insurance fee (basis points)
POST /admin/set-release-cap Update arbiter-quorum release cap
POST /admin/set-arbiters Rotate 5-account arbiter pool
POST /admin/emergency-freeze Pause all state changes
POST /admin/unfreeze Resume after freeze

402 response format:

{
  "error": "payment_required",
  "accepts": "x402-v1",
  "price": 1000000,
  "receiver": "account-hash-74c9..."
}

πŸ”Œ SDK and integrations

Python SDK

The real, live deployment (sandbox=false) requires a genuine Ed25519-signed X-Payment header on every request β€” EscrowClient.generate(...) handles that for you, deriving your agent's identity from a fresh keypair:

from sdk import EscrowClient

async with EscrowClient.generate("https://agentescrow402-api.onrender.com") as client:
    receiver = "ab" * 32  # counterparty's 64-hex Casper account hash / Ed25519 public key
    escrow = await client.create_escrow(receiver=receiver, amount=5_000_000, ttl=300)
    await client.release(escrow["service_hash"])

Running against your own local sandbox instance (SANDBOX=true) still works with a plain string identity and no signing:

client = EscrowClient("http://localhost:8000", sender="my-agent", sandbox=True)

See examples/quickstart.py (minimal) and examples/escrow_agent.py (full autonomous buyer/seller lifecycle with a real dispute + AI arbitration call) for runnable end-to-end examples. escrow_agent.py signs real Ed25519 arbiter votes and resolves the dispute on-chain out of the box, using the throwaway, never-funded testnet keypairs committed under demo/test-arbiter-keys/ (see that folder's README for why it's safe to ship these particular private keys) β€” clone and run it, no credentials needed, to watch create β†’ dispute β†’ resolve happen for real on Casper Testnet.

LangChain tool

from sdk.langchain_tool import EscrowPaymentTool
tool = EscrowPaymentTool(base_url="http://localhost:8000", sender="my-agent")  # sandbox mode
result = await tool.run(action="create", receiver="ab" * 32, amount=1_000_000)

MCP server (26 tools via stdio/SSE)

python sdk/mcp_server.py

Full SDK reference β†’ docs/SDK.md Β· Standalone JSON-Schema for all 26 tools (no server needed to browse) β†’ docs/mcp_tools_schema.json


πŸ›  Tech stack

Layer Technology
Smart contract Rust β†’ WASM, Casper 2.x CEP-88
Payment server Python 3.11, FastAPI, Uvicorn
x402 middleware Custom header parser + validator
Persistence Neon PostgreSQL-compatible serverless database for hosted API records
Sandbox / testing In-memory fallback for local/demo development
SDK Python async SDK, LangChain tool, MCP server
CI GitHub Actions β€” lint β†’ pytest β†’ WASM build β†’ cargo test
Frontend React + Vite console, Vercel
Backend hosting Render (always-on)

πŸ§ͺ Testing

python -m compileall -q server
npm --prefix frontend run build
uv run --active python -m pytest -q          # 450 tests (server logic, x402, identity, risk, multi-asset)
cargo test --manifest-path contracts/escrow/Cargo.toml   # 40 tests (escrow, HTLC, arbitration)
ALLOW_HOSTED_DEMO_IDENTITY=true uv run python tests/test_business_logic.py   # live smoke: health/stats/escrow create+release/risk/VRF/insurance

Current status: 450/450 Python + 40/40 Rust tests passing (incl. Hypothesis/proptest property-based invariant tests added for fee/insurance/TTL/quorum/reputation logic). (One test, test_delegate_expired_timestamp_rejected, has an occasional cross-module flake tied to in-memory identity-registry state sharing between test files β€” not a production code bug, tracked in docs/STATUS_AND_ROADMAP.md.) NVIDIA API-assisted security review reported no concrete HIGH blockers for the latest console/Neon/contract patch.

Verified on-chain (this is not simulated β€” real testnet transactions)

Flow Deploy/tx hash Result
Escrow create (CSPR) a3c5da80...f6f40a8ad βœ… processed
release() on the current (v8, fixed) contract 0184cc2b...06c3ee53 βœ… processed, no error
HTLC atomic-swap upgrade deploy 2211685a...29c7aaa2 βœ… processed
HTLC commit_swap β†’ reveal_swap, revealed by a different account than the committer live round-trip on testnet, same session βœ… funds transferred (2.94 CSPR), cross-account reveal confirmed
CEP-18 token transfer (AETUSD) 2139b49e...07a82c387 βœ… balance confirmed via state_get_dictionary_item
CEP-78 NFT mint (AETNFT) 3a298259...f39d441 βœ… ownership confirmed via token_owners dict
CEP-78 NFT transfer (AETNFT) c4046eaa...d599bc9d βœ… ownership confirmed via token_owners dict

All hashes are independently verifiable on testnet.cspr.live or via https://api.testnet.cspr.cloud/deploys/{hash}.

Bulk on-chain volume: beyond the curated flows above, 349/349 additional deploys were submitted and confirmed on testnet with zero failures (same escrow contract as above) β€” not just create_escrow spam, but the full escrow lifecycle: 173 create_escrow, 166 release, 4 sender-initiated refund, and 3 full dispute β†’ 3-of-5 arbiter-multisig resolve cycles (signed live with the same demo/test-arbiter-keys/ used by examples/escrow_agent.py, confirming the arbiter set survived the v8β†’v9 in-place contract upgrade). 20 of the 349 (10 create/release pairs) use the 10 pre-generated agent_01..agent_10 accounts as the counterparty receiver, so the log also demonstrates multi-agent-wallet participation, not just a single sender/receiver pair. Full deploy-hash-by-deploy-hash log: docs/evidence/bulk_escrow_tx_log.jsonl.


πŸ“š All documentation

Doc What's in it
docs/ARCHITECTURE.md Detailed component/sequence diagrams
docs/SDK.md Python SDK, LangChain tool, MCP server (26 tools) reference
docs/openapi.yaml Full OpenAPI schema for the REST API
docs/GAS_BENCHMARK.md Real testnet gas costs per escrow entry point
docs/AGENT_IDENTITY_REGISTRY.md On-chain DID/stake/reputation registry contract (ID-1), separate from the escrow contracts
docs/STATUS_AND_ROADMAP.md Architecture decisions, roadmap, and production status
ROADMAP.md Shipped vs. planned, phase by phase
CHANGELOG.md Version history

| CONTRIBUTING.md | Dev setup, PR conventions | | SECURITY.md | Vulnerability disclosure, key-handling policy |

πŸ“ License

MIT

Security: testnet keys only β€” never commit real deployer keys. See docs/STATUS_AND_ROADMAP.md for architecture decisions and roadmap.


Built for Casper Agentic Buildathon 2026 Β· Deployed on Casper Testnet

ae402.xyz Β· API Docs Β· Architecture

Last verified against commit 5cdd4a8 / contract package d3ca33d1...c8eeb v9 (612cead2...ddd9ec), 2026-07-07.

About

x402-compatible payment middleware for autonomous AI agents on Casper Network

Topics

Resources

License

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors