Receipts Guard
ERC-8004 identity, x402 payments, and arbitration protocol for autonomous agent commerce. The three rails for the machine economy.
ERC-8004 identity, x402 payments, and arbitration protocol for autonomous agent commerce. The three rails for the machine economy.
Real data. Real impact.
Emerging
Developers
Per week
Open source
Skills give you superpowers. Install in 30 seconds.
"The rails for the machine economy."
ERC-8004 identity + x402 payments + arbitration protocol. The infrastructure for agent commerce.
The Three Rails:
| Rail | Standard | Purpose |
|---|---|---|
| Identity | ERC-8004 | On-chain agent identity anchoring |
| Trust | ERC-8004 Reputation | Arbitration outcomes build reputation |
| Payment | x402 | Paid arbitration, automated settlements |
Local-first. Chain-anchored. Cloud-deployable. Security-hardened.
# === ARBITRATION FLOW ===1. Create proposal
node capture.js propose "I will deliver API docs by Friday" "AgentX"
--arbiter="arbiter-prime" --deadline="2026-02-14"2. Accept proposal (as counterparty)
node capture.js accept --proposalId=prop_abc123
3. Fulfill agreement
node capture.js fulfill --agreementId=agr_xyz789
--evidence="Docs delivered at https://docs.example.com"--- OR if there's a dispute ---
4. Open arbitration
node capture.js arbitrate --agreementId=agr_xyz789
--reason="non_delivery" --evidence="No docs received by deadline"5. Submit evidence (both parties)
node capture.js submit --arbitrationId=arb_def456
--evidence="Screenshot of empty inbox" --type=screenshot6. Issue ruling (as arbiter)
node capture.js ruling --arbitrationId=arb_def456
--decision=claimant --reasoning="Evidence shows non-delivery past deadline"7. View timeline
node capture.js timeline --agreementId=agr_xyz789
identity init - Create Identitynode capture.js identity init --namespace=remaster_io --name=receipts-guard \ --controller-twitter=@Remaster_io
Creates:
did:agent:<namespace>:<name>identity show - Display Identitynode capture.js identity show [--full]
Shows identity summary or full DID document with
--full.
identity rotate - Rotate Keysnode capture.js identity rotate [--reason=scheduled|compromise|device_change]
identity verify - Verify Identity or Signature# Verify DID key chain node capture.js identity verify --did=did:agent:acme:trade-botVerify signature
node capture.js identity verify
--signature="ed25519:xxx:timestamp"
--termsHash="sha256:abc123..."
identity set-controller - Set Human Controllernode capture.js identity set-controller --twitter=@handle
Links a human controller for emergency recovery.
identity recover - Emergency Recoverynode capture.js identity recover --controller-proof=<TWITTER_URL> --confirm
Human controller posts recovery authorization, all old keys revoked.
identity publish - Publish DID Documentnode capture.js identity publish [--platform=moltbook|ipfs|local]
identity anchor - Anchor to ERC-8004 (v0.7.0)node capture.js identity anchor --chain=ethereum|base|sepolia
Registers identity on-chain to ERC-8004 Identity Registry:
RECEIPTS_WALLET_PRIVATE_KEY environment variableDeployed Registries:
| Chain | Identity Registry | Status |
|---|---|---|
| Ethereum | | Live |
| Sepolia | | Testnet |
| Base | Coming soon | TBD |
identity resolve - Resolve DID (v0.7.0)node capture.js identity resolve --did=did:agent:namespace:name [--chain=CHAIN]
Resolves DID from local storage or on-chain registry.
The ERC-8004 standard provides three registries for agent trust:
RECEIPTS integrates with existing registries while providing superior off-chain agreement lifecycle management.
Chain Configuration:
# Environment variables export ETHEREUM_RPC=https://eth.llamarpc.com export BASE_RPC=https://mainnet.base.org export RECEIPTS_WALLET_PRIVATE_KEY=0x... # Never commit this!
x402 enables paid arbitration - arbiters get compensated for their work.
node capture.js propose "Service agreement" "counterparty" \ --arbiter="arbiter-prime" \ --arbitration-cost="10" \ --payment-token="USDC" \ --payment-chain="base" \ --payment-address="0x..." # Arbiter's address
# Without payment proof (fails if x402 required) node capture.js arbitrate --agreementId=agr_xxx --reason="non_delivery" # Error: Payment required: 10 USDCWith payment proof
node capture.js arbitrate --agreementId=agr_xxx --reason="non_delivery"
--evidence="..." --payment-proof="0x123..."
x402 Schema:
{ "x402": { "arbitrationCost": "10", "arbitrationToken": "USDC", "arbitrationChain": 8453, "paymentAddress": "0x...", "paymentProtocol": "x402", "version": "1.0" } }
Run RECEIPTS Guard as a persistent cloud agent.
node capture.js serve [--port=3000]
Public Endpoints (no auth):
GET / - Service infoGET /health - Health checkGET /identity - DID documentGET /identity/chains - Chain statusProtected Endpoints (auth required):
GET /list - List all recordsGET /proposals - List proposalsGET /agreements - List agreementsPOST /propose - Create proposalPOST /accept - Accept proposal (counterparty only)The HTTP server implements multiple security layers:
Option 1: API Key
# Generate a secure API key export RECEIPTS_API_KEY=$(openssl rand -hex 32)Use in requests
curl -H "X-API-Key: $RECEIPTS_API_KEY" https://your-agent.fly.dev/list
Option 2: DID Request Signing
# Sign each request with your Ed25519 key # Headers required: # - X-DID: your DID (e.g., did:agent:namespace:name) # - X-DID-Timestamp: Unix timestamp in milliseconds # - X-DID-Signature: ed25519:BASE64URL_SIGNATURE:TIMESTAMPSigned message format: METHOD:PATH:TIMESTAMP
Example: POST:/propose:1707494400000
By default, cross-origin requests are blocked for security.
# Allow specific origins export RECEIPTS_ALLOWED_ORIGINS=https://app.example.com,https://dashboard.example.comAllow all origins (not recommended for production)
export RECEIPTS_ALLOWED_ORIGINS=*
Default: 100 requests per minute per IP.
# Customize rate limit export RECEIPTS_RATE_LIMIT=200
Response headers:
X-RateLimit-Limit - Max requests per windowX-RateLimit-Remaining - Remaining requestsX-RateLimit-Reset - Window reset timestampAll POST endpoints validate:
/accept endpoint verifies the requester is the designated counterparty (when using DID signing)# Security RECEIPTS_API_KEY= # API key for authentication (generate with: openssl rand -hex 32) RECEIPTS_ALLOWED_ORIGINS= # Comma-separated CORS origins (default: none/blocked) RECEIPTS_RATE_LIMIT= # Requests per minute (default: 100)Existing
RECEIPTS_WALLET_PRIVATE_KEY= # For on-chain transactions RECEIPTS_AGENT_ID= # Agent identifier ETHEREUM_RPC= # Ethereum RPC endpoint BASE_RPC= # Base RPC endpoint
# Deploy fly launch fly deployConfigure secrets
fly secrets set RECEIPTS_WALLET_PRIVATE_KEY=... fly secrets set ETHEREUM_RPC=...
Create persistent volume
fly volumes create receipts_data --size 1
docker build -t receipts-guard . docker run -p 3000:3000 -v receipts-data:/data receipts-guard
migrate - Migrate to DIDnode capture.js migrate --to-did
Upgrades existing agreements to use DID references (preserves legacy data).
propose - Create Agreement Proposalnode capture.js propose "TERMS" "COUNTERPARTY" --arbiter="ARBITER" [options]Options: --arbiter=AGENT Required: mutually agreed arbiter --deadline=ISO_DATE Fulfillment deadline --value=AMOUNT Agreement value (for reference) --channel=CHANNEL Communication channel
Creates a PAO (Programmable Agreement Object) with:
termsHash - SHA-256 of canonical terms + parties + deadlinepending_acceptanceaccept - Accept Proposalnode capture.js accept --proposalId=prop_xxx
agreements/reject - Reject Proposalnode capture.js reject --proposalId=prop_xxx --reason="REASON"
fulfill - Claim Fulfillmentnode capture.js fulfill --agreementId=agr_xxx --evidence="PROOF"
pending_confirmationarbitrate - Open Disputenode capture.js arbitrate --agreementId=agr_xxx --reason="BREACH_TYPE" --evidence="PROOF"Valid reasons: non_delivery - Counterparty didn't deliver partial_delivery - Delivery was incomplete quality - Delivery didn't meet specs deadline_breach - Missed deadline repudiation - Counterparty denies agreement other - Other breach
submit - Submit Evidencenode capture.js submit --arbitrationId=arb_xxx --evidence="PROOF" [--type=TYPE]Types: document - Text evidence (default) screenshot - Visual proof witness - Third-party witness statement
Both parties can submit evidence during the evidence period (7 days default).
ruling - Issue Ruling (Arbiter Only)node capture.js ruling --arbitrationId=arb_xxx --decision=DECISION --reasoning="EXPLANATION"Decisions: claimant - Rule in favor of claimant respondent - Rule in favor of respondent split - Split responsibility
timeline - Generate LPR (Legal Provenance Review)node capture.js timeline --agreementId=agr_xxx
Generates chronological timeline showing:
node capture.js capture "TERMS_TEXT" "SOURCE_URL" "MERCHANT_NAME" [options]Options: --consent-type=TYPE explicit | implicit | continued_use --element=SELECTOR DOM element that triggered consent --screenshot=BASE64 Screenshot at time of consent
node capture.js promise "COMMITMENT_TEXT" "COUNTERPARTY" [options]Options: --direction=outbound outbound (I promised) | inbound (they promised) --channel=email email | chat | moltbook | api
node capture.js list [--type=TYPE]Types: all - Everything (default) captures - ToS captures and promises proposals - Pending proposals agreements - Active/closed agreements arbitrations - Open/closed arbitrations rulings - Issued rulings
node capture.js query --merchant="Company" --risk-level=high
node capture.js diff --capture1=ID --capture2=ID
node capture.js dispute --captureId=local_xxx
node capture.js witness --captureId=ID [--anchor=moltbook|bitcoin|both]
node capture.js rules --list node capture.js rules --add="PATTERN" --flag="FLAG_NAME"
node capture.js export --format=json|csv|pdf [--captureId=ID]
PROPOSAL: pending_acceptance → accepted → (becomes agreement) → rejected → expiredAGREEMENT: active → pending_confirmation → fulfilled → closed → disputed → (becomes arbitration)
ARBITRATION: open → evidence_period → deliberation → ruled → closed
identity/did.json) - v0.6.0{ "@context": ["https://www.w3.org/ns/did/v1"], "id": "did:agent:remaster_io:receipts-guard","verificationMethod": [{ "id": "did:agent:remaster_io:receipts-guard#key-xxx", "type": "Ed25519VerificationKey2020", "controller": "did:agent:remaster_io:receipts-guard", "publicKeyMultibase": "z6Mkf5rGMoatrSj1f..." }],
"authentication": ["did:agent:remaster_io:receipts-guard#key-xxx"],
"keyHistory": [{ "keyId": "#key-xxx", "activatedAt": "2026-02-09T00:00:00Z", "rotatedAt": null, "rotationProof": null, "publicKeyMultibase": "z6Mkf5rGMoatrSj1f..." }],
"controller": { "type": "human", "platform": "twitter", "handle": "@Remaster_io" },
"created": "2026-02-09T00:00:00Z", "updated": "2026-02-09T00:00:00Z" }
# Ed25519 (v0.6.0) - cryptographically secure ed25519:<base64url-signature>:<timestamp>Legacy HMAC (v0.5.0 and earlier) - still supported for backward compatibility
sig:<hex-signature>:<timestamp>
proposals/prop_xxx.json){ "proposalId": "prop_xxx", "termsHash": "sha256:...", "terms": { "text": "...", "canonical": "..." }, "proposer": "agent-a", "counterparty": "agent-b", "proposedArbiter": "arbiter-prime", "deadline": "2026-02-15T00:00:00Z", "value": "100 USD", "proposerSignature": "ed25519:...", "status": "pending_acceptance", "createdAt": "...", "expiresAt": "..." }
agreements/agr_xxx.json){ "agreementId": "agr_xxx", "termsHash": "sha256:...", "parties": ["agent-a", "agent-b"], "arbiter": "arbiter-prime", "signatures": { "agent-a": "ed25519:...", "agent-b": "ed25519:..." }, "status": "active", "timeline": [ { "event": "proposed", "timestamp": "...", "actor": "agent-a" }, { "event": "accepted", "timestamp": "...", "actor": "agent-b" } ] }
arbitrations/arb_xxx.json){ "arbitrationId": "arb_xxx", "agreementId": "agr_xxx", "claimant": "agent-a", "respondent": "agent-b", "arbiter": "arbiter-prime", "reason": "non_delivery", "status": "evidence_period", "evidence": { "claimant": [...], "respondent": [...] }, "evidenceDeadline": "..." }
rulings/rul_xxx.json){ "rulingId": "rul_xxx", "arbitrationId": "arb_xxx", "arbiter": "arbiter-prime", "decision": "claimant", "reasoning": "...", "reasoningHash": "sha256:...", "issuedAt": "..." }
~/.openclaw/receipts/ ├── identity/ # v0.6.0 Self-Sovereign Identity │ ├── did.json # DID document (public) │ ├── private/ │ │ ├── key-current.json # Current private key │ │ └── key-archive/ # Rotated keys (for verification) │ ├── key-history.json # Rotation chain with proofs │ ├── controller.json # Human controller config │ └── recovery/ # Recovery records ├── index.json # Fast lookup index ├── proposals/ │ └── prop_xxx.json # Proposal metadata ├── agreements/ │ ├── agr_xxx.json # Agreement metadata │ └── agr_xxx.txt # Terms text ├── arbitrations/ │ └── arb_xxx.json # Arbitration record ├── rulings/ │ └── rul_xxx.json # Ruling record ├── witnesses/ │ └── witness_xxx.json # Witness anchors ├── local_xxx.json # ToS captures ├── promise_xxx.json # Promise captures └── custom-rules.json # Custom rulesets
node capture.js capture "TERMS" "URL" "MERCHANT"
node capture.js propose "I will deliver X by Y" "AgentZ" --arbiter="trusted-arbiter"
RECEIPTS_AGENT_ID # Your agent identifier RECEIPTS_MOLTBOOK_KEY # API key for Moltbook witnessing RECEIPTS_CUSTOM_RULES # Path to custom rules file
const receipts = require('./capture.js');// Generate terms hash for verification const hash = receipts.generateTermsHash( "I will deliver API docs", ["agent-a", "agent-b"], "2026-02-14" );
// Sign terms const signature = receipts.signTerms(hash, "my-agent-id");
// Verify signature const valid = receipts.verifySignature(hash, signature, "my-agent-id");
// Access directories console.log(receipts.PROPOSALS_DIR); console.log(receipts.AGREEMENTS_DIR); console.log(receipts.ARBITRATIONS_DIR); console.log(receipts.RULINGS_DIR);
RECEIPTS Guard provides evidence capture and arbitration workflow tooling. It is NOT a substitute for legal review. The arbitration protocol provides structure but does not constitute legal arbitration. Always consult with a qualified attorney for actual disputes.
No automatic installation available. Please visit the source repository for installation instructions.
View Installation Instructions1,500+ AI skills, agents & workflows. Install in 30 seconds. Part of the Torly.ai family.
© 2026 Torly.ai. All rights reserved.