Skip to main content
Glama

ERC-8183 Agentic Commerce Demo

A complete learning application for the minimal ERC-8183 job lifecycle. It uses test-only mUSDC, MetaMask, Solidity, Hardhat, React, FastAPI, SQLAlchemy, and SQLite. The backend never holds private keys and no real funds should be used.

ERC-8183 is still an Ethereum Draft as of August 3, 2026. The lifecycle and hook interface may change before the proposal becomes final. This project uses Solidity 0.8.24, a non-upgradeable core, and two optional policy hooks for learning.

Official source: https://eips.ethereum.org/EIPS/eip-8183

What is included

  • contracts/: MockUSDC, hook-enabled AgenticCommerce, separate Allowlist/Bidding hooks, tests, deployment, ABI export

  • backend/: FastAPI metadata API, persistent ERC-8004 agent profiles, SQLAlchemy models, SQLite, Alembic migrations, tests

  • frontend/: React/Vite dark UI, MetaMask, role-aware actions, ERC-8004 identity/reputation, bidding, delivery, evaluation

  • scripts/: Linux/macOS shell and Windows PowerShell native setup/run/binary build scripts

  • HOOKS_GUIDE.md: deployment, architecture, EIP-712 bidding, and manual/automated test instructions

  • No Docker configuration. This package uses native Node.js and Python setup as requested.

Related MCP server: Etherscan MCP Python

Architecture

flowchart TD
    U["Client / Provider / Evaluator"] -->|MetaMask transactions| C["AgenticCommerce"]
    C -->|escrow transfers| T["MockUSDC"]
    C -->|trusted callbacks| H["Allowlist or Bidding Hook"]
    U -->|metadata and bids| F["React UI"]
    F -->|REST| B["FastAPI"]
    B --> D["SQLite"]
    F -->|ethers.js reads and writes| C

The blockchain is authoritative for lifecycle, role permissions, escrow, hashes, and settlement. SQLite stores only searchable off-chain data such as bids, URLs, descriptive metadata, and full reason text. A user signs every state-changing blockchain transaction in MetaMask.

Exact state machine

From

To

Caller

Function

Open

Funded

Client

fund(jobId, expectedBudget)

Open

Rejected

Client

reject(jobId, reason)

Funded

Submitted

Provider

submit(jobId, deliverable)

Funded

Rejected

Evaluator

reject(jobId, reason)

Funded

Expired

Anyone after deadline

claimRefund(jobId)

Submitted

Completed

Evaluator

complete(jobId, reason)

Submitted

Rejected

Evaluator

reject(jobId, reason)

Submitted

Expired

Anyone after deadline

claimRefund(jobId)

Every other transition reverts. Completed, Rejected, and Expired are terminal.

Lifecycle sequences

Completed

sequenceDiagram
    participant C as Client
    participant A as AgenticCommerce
    participant P as Provider
    participant E as Evaluator
    C->>A: createJob + setBudget
    C->>A: approve token + fund(expectedBudget)
    P->>A: submit(deliverableHash)
    E->>A: complete(reasonHash)
    A-->>P: release escrow

Rejected

sequenceDiagram
    participant C as Client
    participant A as AgenticCommerce
    participant E as Evaluator
    C->>A: fund job
    E->>A: reject(reasonHash)
    A-->>C: refund full escrow

Expired

sequenceDiagram
    participant C as Client
    participant A as AgenticCommerce
    participant X as Any wallet
    C->>A: fund job
    Note over A: expiredAt reached
    X->>A: claimRefund(jobId)
    A-->>C: refund full escrow

Optional provider and bidding

sequenceDiagram
    participant C as Client
    participant B as FastAPI bids
    participant P as Provider
    participant A as AgenticCommerce
    C->>A: createJob(provider=0)
    P->>B: submit off-chain bid
    C->>B: select bid
    C->>A: setProvider(winner)
    C->>A: setBudget + fund

Bids remain off-chain, but the Bidding hook now verifies the winning provider's EIP-712 signature and committed amount before the provider is written on-chain. See HOOKS_GUIDE.md for the exact flow.

Prerequisites

  • Node.js 20 or 22 LTS recommended

  • npm 10+

  • Python 3.11 or 3.12

  • MetaMask

  • Sepolia test ETH for transaction gas

Node 24 may work but Hardhat 2 officially targets LTS Node releases; use Node 20/22 if you see a runtime warning.

Fast native setup

Windows PowerShell

Set-ExecutionPolicy -Scope Process Bypass
.\scripts\setup-native.ps1
Copy-Item contracts\.env.example contracts\.env
Copy-Item backend\.env.example backend\.env
Copy-Item frontend\.env.example frontend\.env

Linux or macOS

chmod +x scripts/*.sh
./scripts/setup-native.sh
cp contracts/.env.example contracts/.env
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env

Run locally with a Hardhat chain

Open three terminals:

# Terminal 1
./scripts/run-local-chain.sh

# Terminal 2: deploy and note the two addresses
npm --prefix contracts run deploy:local

# Put the core, token, and two hook addresses into frontend/.env, then:
./scripts/run-backend.sh

# Terminal 3
./scripts/run-frontend.sh

Windows users can run the matching .ps1 scripts. Set VITE_CHAIN_ID=31337 for the Hardhat network and import one of Hardhat's displayed test-only private keys into MetaMask. Add a local MetaMask network with RPC http://127.0.0.1:8545 and chain ID 31337.

Run the tests

npm --prefix contracts test

cd backend
.venv/bin/pytest
cd ..

npm --prefix frontend run build

Also run npm --prefix frontend run lint. Existing pre-hook databases need migration 0002; see HOOKS_GUIDE.md before starting the backend.

Existing databases also need the ERC-8004 profile and job-provenance migration:

cd backend
.venv/bin/alembic upgrade head

On Windows, use .venv\Scripts\alembic.exe upgrade head.

On Windows, replace .venv/bin/pytest with .venv\Scripts\pytest.exe.

Sepolia deployment

  1. Copy contracts/.env.example to contracts/.env.

  2. Add a Sepolia RPC URL, a test-only deployer key, and optional Etherscan API key.

  3. Deploy:

npm --prefix contracts run deploy:sepolia
  1. Copy the printed token, core, Allowlist hook, and Bidding hook addresses into frontend/.env.

  2. Set VITE_CHAIN_ID=11155111.

  3. Set the same contract address and chain ID in backend/.env.

  4. Rebuild/restart the frontend and backend.

Verify contracts:

cd contracts
npx hardhat verify --network sepolia MOCK_USDC_ADDRESS
npx hardhat verify --network sepolia AGENTIC_COMMERCE_ADDRESS MOCK_USDC_ADDRESS
npx hardhat verify --network sepolia ALLOWLIST_HOOK_ADDRESS AGENTIC_COMMERCE_ADDRESS OWNER_ADDRESS
npx hardhat verify --network sepolia BIDDING_HOOK_ADDRESS AGENTIC_COMMERCE_ADDRESS

Never commit .env or a private key. Use a wallet created only for Sepolia.

Add MockUSDC to MetaMask

In MetaMask, choose Import tokens, select Custom token, paste the deployed MockUSDC address, use symbol mUSDC, and use 6 decimals. The UI's mint button calls the permissionless test faucet for 100 mUSDC.

Deliverable hash

Both React and FastAPI calculate:

keccak256(
  abi.encode(
    uint256 jobId,
    address provider,
    string deliverableUrl,
    bytes32 fileHash,
    uint256 submissionTimestamp
  )
)

The exact ABI types, value order, URL bytes, provider address, file hash, and Unix timestamp must match. React uses AbiCoder.defaultAbiCoder().encode; Python uses eth_abi.encode. FastAPI recomputes the commitment and rejects mismatches. Only the bytes32 commitment is submitted on-chain.

The UI saves the off-chain deliverable record before asking MetaMask to submit the commitment. This prevents a confirmed blockchain transaction from losing its URL/file metadata when SQLite is busy. Repeated clicks are guarded in the UI, and the backend treats the same deliverable commitment as an idempotent request. Uploaded files use relative /uploads/... URLs so Vite can proxy them during development and the bundled backend can serve them from the same origin in production.

Do not leave DB Browser for SQLite in an uncommitted edit transaction while the backend is running. Choose Write Changes or Revert Changes before returning to the app; otherwise SQLite may lock backend writes. The API waits briefly for transient locks and returns a descriptive HTTP 503 if the database remains busy.

Reason text is stored in SQLite. The on-chain commitment is keccak256(UTF-8 reason) or bytes32(0) for an empty reason.

API examples

Create a bid:

curl -X POST http://127.0.0.1:8000/api/jobs/1/bids \
  -H "Content-Type: application/json" \
  -d '{"provider_address":"0x2222222222222222222222222222222222222222","proposed_budget":"20","message":"I can deliver this job"}'

List bids and metadata:

curl http://127.0.0.1:8000/api/jobs/1/bids
curl http://127.0.0.1:8000/api/jobs/1/metadata

Interactive API documentation is available at http://127.0.0.1:8000/docs.

Streamable HTTP MCP endpoint

The backend also mounts a Streamable HTTP MCP server at /mcp/ (/mcp redirects there). In a local run it is available at http://127.0.0.1:8000/mcp/. In a public deployment, serve the same FastAPI app over HTTPS and set:

CORS_ORIGINS=https://your-domain.example
MCP_ALLOWED_HOSTS=your-domain.example,your-domain.example:443
MCP_ALLOWED_ORIGINS=https://your-domain.example

The MCP wrapper exposes read-only ERC-8004/ ERC-8183 resources plus preparation tools for deliverable hashes, evaluation reason hashes, and ERC-8004 feedback payloads. It does not hold private keys or submit blockchain transactions.

See docs/DEPLOY_STREAMABLE_HTTP_MCP.md for public deployment steps and ERC-8004 registration metadata.

For Railway-specific deployment, see docs/DEPLOY_RAILWAY.md. The root railway.json builds the React frontend, installs backend dependencies, runs Alembic, and starts FastAPI with /mcp/ exposed.

ERC-8004 provider identity

The Sepolia integration uses these official registry deployments:

  • Identity Registry: 0x8004A818BFB912233c491871b3d84c89A494BD9e

  • Reputation Registry: 0x8004B663056A597Dffe9eCcC1965A193B7388713

Open Agents, select Ethereum Sepolia, enter an agent ID, and import it. The frontend reads getAgentWallet, tokenURI, and ownerOf directly from the Identity Registry, decodes the registration file, then persists the normalized profile through FastAPI. Base64 JSON data URIs, URL-encoded JSON data URIs, HTTP(S) JSON, and basic ipfs:// resolution through ipfs.io are supported. HTTP and IPFS gateways must allow browser CORS requests.

On Create Job, choosing an ERC-8004 provider sends the imported agentWallet to the unchanged ERC-8183 createJob(address provider, ...) call. The numeric agentId, registry, wallet, and name are stored only as off-chain job provenance. Manual EOA providers and bidding jobs continue to use their existing paths.

After an agent-backed job reaches Completed or Rejected, the recorded client or evaluator can post ERC-8004 feedback. Completed jobs submit value 100; rejected jobs submit value 0; both use zero decimals and tags erc8183-job plus the final status. The feedback hash commits to the job ID, status, deliverable evidence, and evaluation reason. The UI blocks the agent owner and agentWallet from posting self-feedback, and the Reputation Registry independently enforces its own restrictions.

End-to-end Sepolia test with agent 9406

  1. Run Alembic migration 0003, then start the backend and frontend.

  2. Connect MetaMask to Ethereum Sepolia as the client.

  3. Open Agents, keep chain Ethereum Sepolia, enter 9406, and click Import from Identity Registry.

  4. Verify the imported card shows ERC8183 Escrow Provider Agent, agent ID 9406, agent wallet 0x85aC164b4A81eb9bFbE75b995f0D4e5F0fF0B35A, owner, image, and the metadata active status.

  5. Open Create job, select ERC-8004 registered agent provider, choose agent 9406, enter an evaluator, and create the job.

  6. On Job Details, verify the on-chain Provider equals the agent wallet and the provider identity card links to 8004scan.

  7. As the client, set the budget, approve mUSDC, and fund escrow.

  8. Switch MetaMask to the agentWallet account and submit a URL or file deliverable.

  9. Switch to the evaluator and complete or reject the job with an optional reason.

  10. While still connected as evaluator (or as a non-self client), click Post ERC-8004 Feedback and confirm the Reputation Registry transaction.

  11. Open the agent’s 8004scan feedback tab and allow time for the indexer to refresh.

The current agent metadata reports active: false; the demo displays that registry metadata as-is and does not treat it as evidence that a backend service is running.

Contract interaction example

const usdc = new ethers.Contract(mockUsdcAddress, mockUsdcAbi, clientSigner);
const commerce = new ethers.Contract(commerceAddress, commerceAbi, clientSigner);
const budget = ethers.parseUnits("20", 6);

await (await commerce.setBudget(jobId, budget)).wait();
await (await usdc.approve(commerceAddress, budget)).wait();
await (await commerce.fund(jobId, budget)).wait();

If the provider changes the budget to 30 mUSDC before the last line, fund(jobId, 20 mUSDC) reverts with BudgetMismatch.

Single executable build

The binary build first creates the React static production bundle, then embeds it into a PyInstaller FastAPI executable.

Linux/macOS:

./scripts/build-backend-binary.sh
./backend/dist/erc8183-demo

Windows:

.\scripts\build-backend-binary.ps1
.\backend\dist\erc8183-demo.exe

Open http://127.0.0.1:8000. The executable serves both the frontend and API. Build the binary on the same operating system on which it will run; PyInstaller is not a cross-compiler. Keep .env beside the working directory used to launch it.

Manual Sepolia checklist

  • Deploy MockUSDC, then deploy AgenticCommerce with its address.

  • Update frontend/backend environment files and verify chain 11155111.

  • Connect the client wallet and mint 100 test mUSDC.

  • Create a plain job with a provider, evaluator, future deadline, and zero hook.

  • Set 20 mUSDC budget; approve; fund; confirm 80/20 client/escrow balances.

  • Connect provider; submit URL/file commitment; confirm Submitted.

  • Connect evaluator; complete; confirm provider receives 20 mUSDC.

  • Repeat Open rejection, Funded rejection, and Submitted rejection.

  • Create short-deadline Funded and Submitted jobs; claim refunds after expiry.

  • Test Allowlist creation, assignment, funding, and an unapproved participant failure.

  • Test Bidding with two provider-signed bids, wait for the deadline, accept one, set the signed budget, and fund.

  • Attempt forbidden actions and confirm the transaction reverts.

Security and scope

The contracts use SafeERC20, ReentrancyGuard, checks-effects-interactions, custom errors, immutable payment-token selection, strict roles, exact state checks, deadline validation, expected-budget verification, ERC-165 hook validation, owner-controlled hook registration, onlyACP callbacks, and bounded hook gas. ERC-8004 is integrated as an external identity and reputation layer; it does not change ERC-8183 authorization or prove that an agent service is online. This demo has no platform fee, upgradeable proxy, ERC-4337, ERC-2771, EIP-7702, TEE, milestones, partial payments, or real-fund support.

The bid-accept endpoint checks the recorded client address supplied by the UI, but it does not provide cryptographic API authentication. On-chain setProvider is the authoritative protected action. Add signed API challenges before using the metadata service outside a learning environment.

F
license - not found
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Read-only ProofRelay MCP verifier for non-confidential evidence bundles. Exposes 22 public-safe tools, 11 resources, and 11 prompts for bundle integrity checks, receipt-chain review, checkpoint recommendations, MCP risk metadata review, and real-estate closing proof-pack readiness.
    Last updated
    5
    MIT
  • A
    license
    -
    quality
    B
    maintenance
    Enables submitting claims and receiving Ed25519-signed, hash-chained verdicts resolved against real external ground truth, supporting resolvers like GitHub PRs, on-chain transactions, URL JSON, HTTP status, and Kalshi markets.
    Last updated
    296
    MIT

View all related MCP servers

Related MCP Connectors

  • Read-only discovery for exact-commit Agent Skill validation, x402 payment, and signed receipts.

  • Read-only crypto safety: token honeypot checks, EIP-712 signature decode, approval scans.

  • Pay-per-call x402 gateway: agent tools, OpenAI-compatible LLM, market data, RPC, security audits.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/winminthant1404/erc-8183-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server