middleware-ISO-and-x402 is an early-stage Python project in the AI payments / x402 ecosystem. It currently has 1 GitHub stars and 1 forks.
Production-ready middleware for ISO 20022 payment processing with blockchain anchoring, x402 micropayments, and autonomous AI agents
Transform blockchain transactions into compliant ISO 20022 XML messages with cryptographic evidence bundles anchored on EVM chains. Enable pay-per-use API access with USDC micropayments and deploy autonomous XMTP agents.
Quick Start | Core Features | Projects | Receipts | Dashboard | API | SDK | Agents
The ISO 20022 Middleware provides a complete solution for payment processing:
Production-ready middleware for ISO 20022 payment processing with blockchain anchoring, x402 micropayments, and autonomous AI agents
Transform blockchain transactions into compliant ISO 20022 XML messages with cryptographic evidence bundles anchored on EVM chains. Enable pay-per-use API access with USDC micropayments and deploy autonomous XMTP agents.
Quick Start | Core Features | Projects | Receipts | Dashboard | API | SDK | Agents
The ISO 20022 Middleware provides a complete solution for payment processing:
# Clone repository
git clone https://github.com/alfre97x/middleware-ISO-and-x402.git
cd middleware-ISO-and-x402
# Install Python dependencies
pip install -r requirements.txt
# Run database migrations
alembic upgrade head
# Start API server
uvicorn app.main:app --reload --port 8000
# In a new terminal, start UI
cd web-alt
npm install
npm run dev
Access the dashboard at: http://localhost:3000
Create isolated projects for multi-tenant deployments with independent configurations.
Navigate to: http://localhost:3000
Connect Wallet: Click "Connect Wallet" → Sign with MetaMask
Create Project:
Configure Project:
import IsoMiddlewareClient from 'iso-middleware-sdk';
const client = new IsoMiddlewareClient({
baseUrl: 'http://localhost:8000'
});
// Create project (requires SIWE authentication)
const project = await client.createProject({
name: 'My Payment Project',
config: {
anchoring: {
execution_mode: 'platform', // or 'tenant'
chains: [
{ name: 'flare', contract: '0x...', rpc_url: 'https://...' }
]
}
}
});
// Get project details
const details = await client.getProjectConfig(project.id);
# Create project
curl -X POST http://localhost:8000/v1/projects \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <siwe_token>" \
-d '{
"name": "My Project",
"config": {
"anchoring": {
"execution_mode": "platform"
}
}
}'
# List projects
curl http://localhost:8000/v1/projects \
-H "Authorization: Bearer <siwe_token>"
# Get project config
curl http://localhost:8000/v1/projects/{project_id}/config \
-H "Authorization: Bearer <siwe_token>"
Generate ISO 20022 receipts from blockchain transactions and verify evidence bundles.
Using the UI:
Using the SDK:
import IsoMiddlewareClient from 'iso-middleware-sdk';
const client = new IsoMiddlewareClient({ baseUrl: 'http://localhost:8000' });
// Record a tip transaction
const receipt = await client.recordTip({
tip_tx_hash: '0xabc123...',
chain: 'flare',
amount: '100.50',
currency: 'FLR',
sender_wallet: '0xSender...',
receiver_wallet: '0xReceiver...',
reference: 'invoice-2026-001'
});
console.log('Receipt ID:', receipt.receipt_id);
console.log('Status:', receipt.status);
// Output: Status: pending → bundling → anchored
Using the API:
curl -X POST http://localhost:8000/v1/iso/record-tip \
-H "Content-Type: application/json" \
-d '{
"tip_tx_hash": "0xabc123...",
"chain": "flare",
"amount": "100.50",
"currency": "FLR",
"sender_wallet": "0xSender...",
"receiver_wallet": "0xReceiver...",
"reference": "invoice-2026-001"
}'
Using the UI:
Using the SDK:
// Verify by URL
const result = await client.verifyBundle({
bundle_url: 'https://ipfs.io/ipfs/Qm...'
});
// Verify by hash
const result = await client.verifyBundle({
bundle_hash: '0x1234...'
});
console.log('Valid:', result.valid);
console.log('Chains:', result.chains);
console.log('Messages:', result.iso_messages);
Using the API:
curl -X POST http://localhost:8000/v1/iso/verify \
-H "Content-Type: application/json" \
-d '{
"bundle_url": "https://ipfs.io/ipfs/Qm..."
}'
Using the UI:
Using the SDK:
// List receipts with pagination
const page = await client.listReceipts({
page: 1,
page_size: 20,
scope: 'mine' // or 'all' for admin
});
console.log('Total:', page.total);
page.receipts.forEach(r => {
console.log(`${r.reference}: ${r.amount} ${r.currency} - ${r.status}`);
});
// Get specific receipt
const receipt = await client.getReceipt('receipt-id');
console.log('Bundle URL:', receipt.bundle_url);
console.log('ISO Messages:', receipt.iso_messages);
Full-featured Next.js dashboard for managing all operations.
1. Home (/)
2. Operations (/operations)
3. Settings (/settings)
4. Agents (/agents)
Connect Wallet:
Create Receipt:
Verify Bundle:
Manage Projects:
Agent Anchoring allows AI agents to automatically or manually anchor payment data to the blockchain, creating cryptographically verifiable audit trails. This is particularly useful for:
Choose your preferred method:
# 1. Start the middleware
uvicorn app.main:app --port 8000
# 2. Start the UI
cd web-alt && npm run dev
# 3. Open browser
open http://localhost:3000/agents
Result: Configure anchoring with toggles and buttons
import IsoMiddlewareClient from 'iso-middleware-sdk';
const client = new IsoMiddlewareClient({ baseUrl: 'http://localhost:8000' });
await client.updateAgentAnchoringConfig('agent-id', {
auto_anchor_enabled: true,
anchor_on_payment: true
});
Result: Anchoring enabled programmatically
# 1. Configure agent
cd agents/iso-x402-agent
cp .env.example .env
# Set: ANCHOR_ENABLED=true, ANCHOR_ON_PAYMENT=true
# 2. Deploy
npm install && npm start
Result: Agent auto-anchors on every x402 payment
Before starting, ensure:
http://localhost:8000http://localhost:3000Open your browser to: http://localhost:3000/agents
Expected view:
┌─────────────────────────────────────────┐
│ ISO Middleware - Agents │
├─────────────┬───────────────────────────┤
│ Left Panel │ Right Panel │
│ │ │
│ [+ New │ (Agent details will │
│ Agent] │ appear here) │
│ │ │
│ Agent List: │ │
│ • My Agent │ │
│ • Bot 2 │ │
└─────────────┴───────────────────────────┘
If no agents exist:
Click on agent name in left sidebar (e.g., "My Agent")
Right panel opens showing agent details
Tabs visible:
[Details] [AI Settings] [Activity] [Analytics] [Anchoring] [Pricing] [Revenue]
↑
(Click this tab)
Click the "Anchoring" tab (⚓ icon, 5th from left)
Wait for panel to load (~500ms)
Locate the configuration panel at the top:
┌─────────────────────────────────────────┐
│ Anchoring Configuration │
├─────────────────────────────────────────┤
│ │
│ [○] Enable Automatic Anchoring │
│ │
│ [○] Anchor on x402 Payment │
│ │
│ Anchor Wallet (optional) │
│ [_________________________________] │
│ │
│ [Save Configuration] │
└─────────────────────────────────────────┘
Enable auto-anchoring:
○ gray (off) to ● blue (on)Enable payment-triggered anchoring (optional):
Set dedicated wallet (optional):
0x1234567890123456789012345678901234567890Save your configuration:
Scroll down to "Manual Anchoring" section:
┌─────────────────────────────────────────┐
│ Manual Anchoring │
├─────────────────────────────────────────┤
│ Data to Anchor (JSON) │
│ ┌─────────────────────────────────────┐ │
│ │ { │ │
│ │ "payment_id": "pay-001", │ │
│ │ "amount": 100.50 │ │
│ │ } │ │
│ └─────────────────────────────────────┘ │
│ │
│ Description │
│ [_________________________________] │
│ │
│ [Anchor Data] │
└─────────────────────────────────────────┘
Enter JSON data:
{
"payment_id": "pay-001",
"amount": 100.50,
"currency": "USD",
"timestamp": "2026-01-20T20:00:00Z"
}
Add description:
Payment verification for order #001Submit anchoring:
View the created anchor:
Locate the history table:
┌────────────────────────────────────────────────────────────────┐
│ Anchor History │
├──────────────┬─────────────┬────────────┬──────────┬──────────┤
│ Timestamp │ Data Hash │ TX Hash │ Contract │ Status │
├──────────────┼─────────────┼────────────┼──────────┼──────────┤
│ 1/20 8:30 PM │ 0x1234... │ 0xabcd... │ 0x5678.. │ ✅ Conf. │
│ 1/20 8:25 PM │ 0x2345... │ 0xbcde... │ 0x5678.. │ ⏳ Pend. │
└──────────────┴─────────────┴────────────┴──────────┴──────────┘
Understanding the columns:
Copy data hash:
0x1234...)View on blockchain:
Symptoms: Only 6 tabs visible, no "Anchoring" tab
Solution:
curl http://localhost:8000/healthSymptoms: Error message or no response
Solution:
# Check last 50 lines of API logs
tail -f -n 50 api.log
Symptoms: Error: "Invalid JSON" or "Anchoring failed"
Solution:
{...}// commentsnpm install iso-middleware-sdk
import IsoMiddlewareClient from 'iso-middleware-sdk';
// Initialize client
const client = new IsoMiddlewareClient({
baseUrl: 'http://localhost:8000',
apiKey: process.env.ISO_MW_API_KEY // Optional
});
// 1. Get current anchoring configuration
async function getConfig(agentId: string) {
const config = await client.getAgentAnchoringConfig(agentId);
console.log('Current configuration:', config);
// Expected output:
// {
// auto_anchor_enabled: false,
// anchor_on_payment: false,
// anchor_wallet: null
// }
return config;
}
// 2. Enable automatic anchoring
async function enableAnchoring(agentId: string) {
const updated = await client.updateAgentAnchoringConfig(agentId, {
auto_anchor_enabled: true,
anchor_on_payment: true,
anchor_wallet: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'
});
console.log('✅ Anchoring enabled!', updated);
// Expected output:
// {
// auto_anchor_enabled: true,
// anchor_on_payment: true,
// anchor_wallet: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'
// }
}
// 3. Manually anchor data
async function anchorData(agentId: string) {
const anchor = await client.anchorAgentData(agentId, {
data: {
payment_id: 'pay-001',
amount: 100.50,
currency: 'USD',
debtor: 'John Doe',
creditor: 'Jane Smith'
},
description: 'Payment verification for order #001'
});
console.log('✅ Data anchored!');
console.log('Anchor ID:', anchor.id);
console.log('Hash:', anchor.anchor_hash);
console.log('Status:', anchor.status);
// Expected output:
// Anchor ID: 550e8400-e29b-41d4-a716-446655440000
// Hash: 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
// Status: pending
return anchor;
}
// 4. List all anchors for an agent
async function listAnchors(agentId: string) {
const anchors = await client.listAgentAnchors(agentId);
console.log(`Found ${anchors.length} anchors:`);
anchors.forEach((anchor, index) => {
console.log(`\n${index + 1}. Anchor ${anchor.id}`);
console.log(` Hash: ${anchor.anchor_hash}`);
console.log(` Status: ${anchor.status}`);
console.log(` Created: ${anchor.created_at}`);
if (anchor.anchor_tx_hash) {
console.log(` TX: ${anchor.anchor_tx_hash}`);
}
});
// Expected output:
// Found 3 anchors:
//
// 1. Anchor 550e8400-...
// Hash: 0x1234...
// Status: confirmed
// Created: 2026-01-20T20:00:00Z
// TX: 0xabcd...
// ...
}
// 5. Complete workflow
async function main() {
const agentId = 'agent-550e8400-e29b-41d4-a716-446655440000';
// Get current config
await getConfig(agentId);
// Enable anchoring
await enableAnchoring(agentId);
// Anchor some data
await anchorData(agentId);
// List all anchors
await listAnchors(agentId);
}
main().catch(console.error);
import IsoMiddlewareClient from 'iso-middleware-sdk';
const client = new IsoMiddlewareClient({
baseUrl: 'http://localhost:8000',
apiKey: process.env.ISO_MW_API_KEY
});
async function anchorWithErrorHandling(agentId: string, data: any) {
try {
const anchor = await client.anchorAgentData(agentId, {
data: data,
description: 'Payment verification'
});
console.log('✅ Success:', anchor.id);
return anchor;
} catch (error: any) {
// Handle specific error cases
if (error.status === 404) {
console.error('❌ Agent not found:', agentId);
} else if (error.status === 422) {
console.error('❌ Invalid data format:', error.message);
} else if (error.status === 500) {
console.error('❌ Server error:', error.message);
} else {
console.error('❌ Unknown error:', error);
}
throw error;
}
}
pip install iso-middleware-sdk
from iso_middleware_sdk import Client
import os
from datetime import datetime
# Initialize client
client = Client(
base_url='http://localhost:8000',
api_key=os.getenv('ISO_MW_API_KEY') # Optional
)
# 1. Get current anchoring configuration
def get_config(agent_id: str):
config = client.get_agent_anchoring_config(agent_id)
print('Current configuration:', config)
# Expected output:
# {
# 'auto_anchor_enabled': False,
# 'anchor_on_payment': False,
# 'anchor_wallet': None
# }
return config
# 2. Enable automatic anchoring
def enable_anchoring(agent_id: str):
updated = client.update_agent_anchoring_config(
agent_id=agent_id,
auto_anchor_enabled=True,
anchor_on_payment=True,
anchor_wallet='0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'
)
print('✅ Anchoring enabled!', updated)
return updated
# 3. Manually anchor data
def anchor_data(agent_id: str):
anchor = client.anchor_agent_data(
agent_id=agent_id,
data={
'payment_id': 'pay-001',
'amount': 100.50,
'currency': 'USD',
'debtor': 'John Doe',
'creditor': 'Jane Smith',
'timestamp': datetime.utcnow().isoformat()
},
description='Payment verification for order #001'
)
print('✅ Data anchored!')
print(f'Anchor ID: {anchor["id"]}')
print(f'Hash: {anchor["anchor_hash"]}')
print(f'Status: {anchor["status"]}')
return anchor
# 4. List all anchors for an agent
def list_anchors(agent_id: str):
anchors = client.list_agent_anchors(agent_id)
print(f'Found {len(anchors)} anchors:')
for i, anchor in enumerate(anchors, 1):
print(f'\n{i}. Anchor {anchor["id"]}')
print(f' Hash: {anchor["anchor_hash"]}')
print(f' Status: {anchor["status"]}')
print(f' Created: {anchor["created_at"]}')
if anchor.get('anchor_tx_hash'):
print(f' TX: {anchor["anchor_tx_hash"]}')
# 5. Error handling
def anchor_with_error_handling(agent_id: str, data: dict):
try:
anchor = client.anchor_agent_data(
agent_id=agent_id,
data=data,
description='Payment verification'
)
print(f'✅ Success: {anchor["id"]}')
return anchor
except client.NotFoundError:
print(f'❌ Agent not found: {agent_id}')
except client.ValidationError as e:
print(f'❌ Invalid data format: {e}')
except client.ServerError as e:
print(f'❌ Server error: {e}')
except Exception as e:
print(f'❌ Unknown error: {e}')
raise
# 6. Complete workflow
def main():
agent_id = 'agent-550e8400-e29b-41d4-a716-446655440000'
# Get current config
get_config(agent_id)
# Enable anchoring
enable_anchoring(agent_id)
# Anchor some data
anchor_data(agent_id)
# List all anchors
list_anchors(agent_id)
if __name__ == '__main__':
main()
Deploy an autonomous XMTP agent that automatically anchors payment data on x402 micropayments.
cd agents/iso-x402-agent
npm install
Expected output:
added 245 packages in 12s
# Copy template
cp .env.example .env
# Edit configuration
nano .env # or use your preferred editor
Required configuration:
# Anchoring Configuration
ANCHOR_ENABLED=true # Enable anchoring feature
ANCHOR_ON_PAYMENT=true # Auto-anchor on x402 payments
ANCHOR_WALLET=0x1234... # Wallet for gas fees (optional)
# XMTP Configuration
XMTP_ENV=production # or 'dev' for testing
WALLET_PRIVATE_KEY=0x... # Agent's wallet private key
# ISO Middleware API
ISO_MW_API_URL=http://localhost:8000
ISO_MW_API_KEY=your_api_key # Optional
# x402 Payment Configuration
X402_RECIPIENT=0x0690d8cFb1897c12B2C0b34660edBDE4E20ff4d8
CHAIN_RPC_URL=https://mainnet.base.org
USDC_CONTRACT=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
# Agent Settings
AGENT_NAME=ISO Anchoring Agent
LOG_LEVEL=info # debug, info, warn, error
# Build TypeScript
npm run build
# Start agent
npm start
Expected output:
🤖 ISO Middleware XMTP Agent Starting...
✅ Environment: production
✅ XMTP client initialized
✅ Connected to ISO Middleware at http://localhost:8000
✅ Agent anchoring: ENABLED
✅ Auto-anchor on payment: ENABLED
✅ Anchor wallet: 0x1234...5678
✅ Listening for messages on XMTP...
User: status
Agent: 🔗 Agent Status
Anchoring: ✅ Enabled
Auto-anchor: ✅ Enabled
Anchor wallet: 0x1234...5678
Total anchors: 42
Last anchor: 2 hours ago
Last TX: 0xabcd...
User: anchor {"payment_id": "pay-123", "amount": 100.50}
Agent: ⏳ Creating anchor...
✅ Data anchored successfully!
Anchor ID: 550e8400-e29b-41d4-a716-446655440000
Hash: 0x1234567890abcdef...
Status: pending
View on Etherscan: https://etherscan.io/tx/0x...
User: list anchors
Agent: 📋 Recent Anchors (5)
1. 2 hours ago
Hash: 0x1234...
Status: ✅ Confirmed
TX: 0xabcd...
2. 4 hours ago
Hash: 0x2345...
Status: ✅ Confirmed
TX: 0xbcde...
3. 6 hours ago
Hash: 0x3456...
Status: ⏳ Pending
User: verify 0x1234567890abcdef...
Agent: 🔍 Verifying anchor...
✅ Anchor verified!
Status: Confirmed
Block: 12345678
Timestamp: 2026-01-20 20:00:00 UTC
Chain: ethereum
Contract: 0x5678...
When ANCHOR_ON_PAYMENT=true, the agent automatically anchors data on every x402 payment:
User: verify https://ipfs.io/ipfs/Qm...
Agent: ⏳ Verifying bundle (paying 0.001 USDC)...
💳 Payment processed: 0.001 USDC
🔗 Auto-anchoring payment data...
✅ Bundle verified!
✅ Data anchored!
Verification:
Valid: ✓ Yes
Bundle hash: 0x1234...
Anchor:
Anchor hash: 0x5678...
TX: 0xabcd...
Status: pending
💰 Payment: 0.001 USDC paid
# Install PM2
npm install -g pm2
# Start agent with PM2
pm2 start dist/index.js --name iso-anchor-agent
# Monitor
pm2 status
pm2 logs iso-anchor-agent
# Auto-restart on system reboot
pm2 startup
pm2 save
# Build image
docker build -t iso-anchor-agent .
# Run container
docker run -d \
--name iso-anchor-agent \
--env-file .env \
--restart unless-stopped \
iso-anchor-agent
# View logs
docker logs -f iso-anchor-agent
Heroku:
heroku create iso-anchor-agent
heroku config:set ANCHOR_ENABLED=true
heroku config:set WALLET_PRIVATE_KEY=0x...
git push heroku main
Railway:
# Use railway.json configuration
railway up
Google Cloud Run:
gcloud run deploy iso-anchor-agent \
--source . \
--region us-central1 \
--set-env-vars ANCHOR_ENABLED=true
The agent exposes health metrics:
# Check agent health
curl http://localhost:3001/health
# Response:
{
"status": "healthy",
"uptime": 86400,
"anchoring": {
"enabled": true,
"auto_on_payment": true,
"total_anchors": 42,
"last_anchor": "2026-01-20T20:00:00Z"
}
}
Enable detailed logging:
LOG_LEVEL=debug npm start
Debug output example:
[2026-01-20T20:00:00.000Z] DEBUG: Received message from 0x1234...
[2026-01-20T20:00:00.100Z] DEBUG: Parsed command: { action: 'anchor', data: {...} }
[2026-01-20T20:00:00.200Z] DEBUG: Making payment of 0.001 USDC...
[2026-01-20T20:00:01.000Z] DEBUG: Payment successful: 0xabcd...
[2026-01-20T20:00:01.200Z] DEBUG: Creating anchor...
[2026-01-20T20:00:02.000Z] DEBUG: Anchor created: 0x1234...
[2026-01-20T20:00:02.100Z] DEBUG: Sent reply to 0x1234...
GET /v1/agents/{agent_id}/anchoring-config
Response:
{
"auto_anchor_enabled": false,
"anchor_on_payment": false,
"anchor_wallet": null
}
PUT /v1/agents/{agent_id}/anchoring-config
Request:
{
"auto_anchor_enabled": true,
"anchor_on_payment": true,
"anchor_wallet": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
}
Response:
{
"auto_anchor_enabled": true,
"anchor_on_payment": true,
"anchor_wallet": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
}
POST /v1/agents/{agent_id}/anchor-data
Request:
{
"data": {
"payment_id": "pay-001",
"amount": 100.50,
"currency": "USD"
},
"description": "Payment verification"
}
Response:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"agent_id": "agent-550e8400-e29b-41d4-a716-446655440000",
"anchor_hash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"anchor_tx_hash": null,
"anchor_contract": null,
"status": "pending",
"created_at": "2026-01-20T20:00:00Z"
}
GET /v1/agents/{agent_id}/anchors
Response:
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"agent_id": "agent-550e8400-e29b-41d4-a716-446655440000",
"anchor_hash": "0x1234...",
"anchor_tx_hash": "0xabcd...",
"anchor_contract": "0x5678...",
"status": "confirmed",
"created_at": "2026-01-20T20:00:00Z"
}
]
| Code | Description | Solution |
|---|---|---|
| 404 | Agent not found | Verify agent ID |
| 422 | Invalid data | Check JSON format |
| 500 | Server error | Check API logs |
| 503 | Blockchain unavailable | Check RPC endpoint |
Symptoms: Anchor shows "pending" for > 10 minutes
Causes:
Solutions:
# Check wallet balance
cast balance 0xYourAnchorWallet --rpc-url https://mainnet.base.org
# Increase gas price in agent config
# Edit .env:
GAS_PRICE_GWEI=50 # Increase if network is congested
# Check RPC endpoint
curl https://mainnet.base.org \
-X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
Symptoms: Error: connect ETIMEDOUT or Error: Network request failed
Solutions:
// Increase timeout
const client = new IsoMiddlewareClient({
baseUrl: 'http://localhost:8000',
timeout: 30000 // 30 seconds
});
// Check API is running
// curl http://localhost:8000/health
// Check firewall/network
// ping localhost
Symptoms: 422 Unprocessable Entity: Invalid JSON
Solutions:
// ❌ Invalid (has trailing comma)
{
"payment_id": "pay-001",
"amount": 100.50,
}
// ✅ Valid
{
"payment_id": "pay-001",
"amount": 100.50
}
// Validate at: https://jsonlint.com/
Symptoms: Agent running but no response to messages
Solutions:
# Check XMTP environment
# Ensure sender and agent are on same network (dev/production)
# Check wallet has XMTP identity
# Visit: https://converse.xyz to initialize if needed
# Verify agent logs
tail -f agent.log | grep XMTP
# Check XMTP_ENV matches sender's network
XMTP_ENV=production # or 'dev'
┌─────────────┐
│ User/AI │
│ Agent │
└──────┬──────┘
│ 1. Configure anchoring
▼
┌─────────────────────────────────┐
│ ISO Middleware API │
│ - Stores configuration │
│ - Manages anchor records │
└──────┬──────────────────────────┘
│ 2. On payment/manual trigger
▼
┌─────────────────────────────────┐
│ Anchoring Service │
│ - Hash data (SHA-256) │
│ - Create anchor record │
│ - Submit to blockchain │
└──────┬──────────────────────────┘
│ 3. Blockchain transaction
▼
┌─────────────────────────────────┐
│ EVM Chain (Ethereum/Base/etc) │
│ - EvidenceAnchor contract │
│ - Stores hash on-chain │
│ - Emits event │
└──────┬──────────────────────────┘
│ 4. Confirmation
▼
┌─────────────────────────────────┐
│ Anchor Record Updated │
│ - Status: confirmed │
│ - TX hash stored │
│ - Block number recorded │
└─────────────────────────────────┘
// EvidenceAnchorBasic.sol (simplified)
contract EvidenceAnchorBasic {
event EvidenceAnchored(
bytes32 indexed dataHash,
address indexed submitter,
uint256 timestamp
);
function anchorEvidence(bytes32 dataHash) external {
emit EvidenceAnchored(dataHash, msg.sender, block.timestamp);
}
}
Anchor the same data to multiple chains:
// Configure multi-chain anchoring
await client.updateAgentAnchoringConfig(agentId, {
auto_anchor_enabled: true,
chains: ['ethereum', 'base', 'optimism']
});
// Each chain gets its own anchor record
const anchors = await client.listAgentAnchors(agentId);
// Returns anchors for all configured chains
Deploy your own anchor contract:
# Deploy contract
cd contracts
npx hardhat run scripts/deploy.js --network base
# Configure agent to use custom contract
await client.updateAgentAnchoringConfig(agentId, {
anchor_contract: '0xYourContractAddress'
});
Anchor multiple data points efficiently:
// Batch anchor (coming soon)
const anchors = await client.batchAnchorAgentData(agentId, [
{ data: { payment_id: 'pay-001' }, description: 'Payment 1' },
{ data: { payment_id: 'pay-002' }, description: 'Payment 2' },
{ data: { payment_id: 'pay-003' }, description: 'Payment 3' }
]);
// More efficient: single transaction, multiple hashes
Tips for reducing gas costs:
Wallet Security
Data Privacy
Access Control
Gas Management
Every anchor creates an immutable audit trail:
Data → Hash (SHA-256) → Blockchain → Permanent Record
Anyone can verify:
Q: How much does anchoring cost? A: Gas fees vary by network. Base: ~$0.01, Ethereum: ~$1-5, Optimism: ~$0.05
Q: Can I anchor private data? A: Yes, only the hash goes on-chain. Original data stays private in your database.
Q: How long until anchor is confirmed? A: 15 seconds on Base, 12 seconds on Ethereum, 2 seconds on Optimism (average).
Q: What if anchoring fails? A: Anchor record shows "failed" status. Check logs for details. Common causes: insufficient gas, invalid data.
Q: Can I delete an anchor? A: No, blockchain records are immutable. You can mark as inactive in your database.
Q: Do I need my own blockchain node? A: No, uses public RPC endpoints by default. You can configure custom RPC if desired.
Built with ❤️ for ISO 20022 compliance and blockchain immutability
An open SDK for agentic payments. Let AI agents make payments, hold funds, and move money across chains with policy enforcement and human approval built in.
Golang SDK for A2A Protocol
Client SDK for the Vybe x402 API. Pay-per-call USDC over HTTP and prepaid-credit WebSocket streaming for Vybe's Solana analytics API. Built for AI agents.
Rust SDK for the Machine Payments Protocol
Building blocks for Agentic payments (x402, MPP, AP2) for TypeScript, Rust, Go, Python, Ruby, PHP, Lua, Kotlin and Swift.
Opinionated React Native crypto x AI chat app boilerplate with embedded wallet support, conversational AI, and dynamic UI component injection