Sign In

@arbitova/sdk

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@arbitova/sdk

Non-custodial USDC escrow for agent-to-agent payments on Base. v3 is a rewrite — see MIGRATION.md.

latest
Source
npmnpm
Version
3.0.1
Version published
Maintainers
1
Created
Source

@arbitova/sdk

Non-custodial USDC escrow for agent-to-agent payments on Base.

Two agents lock USDC into a contract, one delivers, the other confirms or disputes, and a neutral arbiter resolves. Arbitova never holds the money — the contract does.

No API keys. No registration. No custody. Your Ethereum address is your identity.

npm install @arbitova/sdk ethers

Contract: 0xA8a031bcaD2f840b451c19db8e43CEAF86a088fC on Base Sepolia (mainnet launching after audit) Spec: A2A-ESCROW-RFC-v0.1 Live UI: arbitova.com/pay

Why this exists

Every A2A / agent-commerce spec in the wild — MCP, Google's A2A, ERC-7683, Coinbase's Agent Commerce — defines how agents talk. None of them define how money moves when the agents don't trust each other.

Arbitova is the missing settlement primitive:

  • Deterministic state machine. createEscrow → markDelivered → {confirmDelivery | dispute → resolve | cancel}. No hidden branches, no admin override.
  • No auto-release after timeout. Review windows expire into DISPUTED, not into seller payout. Silence is safer than a wrong confirmation.
  • Content-hash pinned on-chain. Sellers can't swap the delivery file after the buyer inspects.
  • Verdict transparency. Every arbiter decision is a signed JSON blob; its keccak256 is stored on-chain. Anyone can audit.

This is not a marketplace. There is no Arbitova account, no listing fee, no Arbitova Pro tier. The protocol is the whole product.

30-second quickstart

Two terminals. Both need a Base Sepolia private key with some test USDC + a pinch of ETH for gas. Faucet: https://faucet.circle.com/ (Base Sepolia USDC) · gas: https://www.alchemy.com/faucets/base-sepolia

Buyer

// buyer.mjs
import { Arbitova } from '@arbitova/sdk';

const buyer = await Arbitova.fromPrivateKey({ privateKey: process.env.BUYER_PK });

const { escrowId, txHash } = await buyer.createEscrow({
  seller: process.env.SELLER_ADDRESS,
  amount: '5.00',                         // USDC
  deliveryHours: 24,
  reviewHours: 24,
  verificationURI: 'https://example.com/spec.json',
});

console.log(`Escrow #${escrowId} locked — ${buyer.explorerTx(txHash)}`);

Seller

// seller.mjs
import { Arbitova } from '@arbitova/sdk';

const seller = await Arbitova.fromPrivateKey({ privateKey: process.env.SELLER_PK });

seller.onEscrowCreated(async (ev) => {
  if (ev.seller.toLowerCase() !== (await seller.address()).toLowerCase()) return;

  console.log(`New escrow #${ev.id}: ${ev.amount} USDC from ${ev.buyer}`);

  // ...do the work, then:
  const deliveryContent = Buffer.from('hello, buyer');
  await seller.markDelivered({
    escrowId: ev.id,
    deliveryPayloadURI: 'https://example.com/receipt.json',
    deliveryContentBytes: deliveryContent,   // content-hash pinned on-chain
  });
});

Buyer confirms (happy path)

await buyer.confirmDelivery(escrowId);   // seller gets 4.975 USDC, fee 0.025 USDC

Buyer disputes (sad path)

await buyer.dispute(escrowId, 'Delivery incomplete — criterion #2 failed');
// arbiter picks it up, signs a verdict, calls resolve(buyerBps, sellerBps, verdictHash)

That's the whole thing.

Lifecycle

                      ┌──────────────────┐
                      │     CREATED      │ buyer locked USDC
                      └────────┬─────────┘
                               │
                               ▼ seller.markDelivered()
                      ┌──────────────────┐
                      │    DELIVERED     │ deliveryHash on-chain
                      └────────┬─────────┘
                               │
        buyer.confirmDelivery()│        │ buyer.dispute()
                               │        │ or seller.dispute()
                               ▼        ▼
                   ┌─────────────┐  ┌──────────┐
                   │  RELEASED   │  │ DISPUTED │ waiting for arbiter
                   └─────────────┘  └────┬─────┘
                                         │ arbiter.resolve(bps split + verdictHash)
                                         ▼
                                   ┌──────────┐
                                   │ RESOLVED │
                                   └──────────┘

Two terminal states not drawn: CANCELLED (buyer calls cancelIfNotDelivered after delivery window) and auto-escalation into DISPUTED if the review window expires without confirmation.

Browser wallet

import { Arbitova } from '@arbitova/sdk';

const client = await Arbitova.fromWallet(window.ethereum);
await client.confirmDelivery('17');

Works with any EIP-1193 wallet (MetaMask, Coinbase Wallet, Rainbow, Rabby, etc.).

Framework integrations

Three reference A2A demos, all end-to-end on Base Sepolia with a live AI arbiter:

Python agents: pip install arbitova[path_b], then from arbitova import path_b. Same contract surface, same verdicts.

MCP server: npm install @arbitova/mcp-server — six on-chain tools (same contract surface) for any MCP client.

Networks

KeyDescription
base-sepolia (default)Production contract, real Circle USDC
base-sepolia-testTest contract with mock USDC for CI
const client = await Arbitova.fromPrivateKey({
  privateKey: process.env.PK,
  network: 'base-sepolia-test',
});

Base mainnet launches after external audit + multisig arbiter migration. Watch Dev Log for the announcement.

Fees

WhenFeePaid by
confirmDelivery / escalateIfExpired0.5%deducted from seller payout
Arbiter resolves a dispute2%split per arbiter verdict

Fees accrue in the contract. The protocol runs on them; there is no subscription.

API

All methods async. Write methods require a signer (private key or browser wallet).

MethodRoleDescription
Arbitova.fromPrivateKey({ privateKey, network? })Client signed by private key
Arbitova.fromWallet(window.ethereum)Client using an EIP-1193 wallet
Arbitova.fromReadOnly({ network? })Read-only (no signing)
createEscrow({ seller, amount, deliveryHours, reviewHours, verificationURI })buyerLock USDC (auto-approves). Returns { escrowId, txHash, receipt }
markDelivered({ escrowId, deliveryPayloadURI, deliveryContentBytes? })sellerCommits keccak256(content) (or URI) on-chain
confirmDelivery(escrowId)buyerHappy path — pays seller (minus 0.5%)
dispute(escrowId, reason)buyer or sellerOpens dispute; reason emitted in event
cancelIfNotDelivered(escrowId)buyerAfter delivery deadline if seller no-showed
escalateIfExpired(escrowId)anyoneAfter review deadline — forces DISPUTED, not auto-release
getEscrow(escrowId)Full on-chain state
getUsdcBalance(addr?)USDC balance
listEscrowsForAddress(role, addr?)Scan escrows where address is buyer or seller
onEscrowCreated / onDelivered / onReleased / onDisputed / onResolved / onCancelledEvent subscriptions
explorerTx(hash) / explorerAddr(addr)Basescan URL helpers
Arbitova.keccakURI(uri)staticCompute deliveryHash for an off-chain URI
subscribeEvents({ address, onEvent })Server-sent events push stream (alternative to polling)

Verification specs

Your verificationURI should link to a JSON document defining what "done" means. Two modes:

  • manual — human-readable prose for buyer, seller, and arbiter
  • programmatic — an HTTPS endpoint an arbiter can hit to get a pass/fail

Schema: arbitova.com/schemas/ · Reference: RFC v0.1

Security

Migrating from v2 (custodial)

v3 is a rewrite. If you have working v2 code, pin to @arbitova/sdk@^2.3.1 until you're ready — v3 doesn't share any API surface with v2. Migration guide: MIGRATION.md.

License

MIT · github.com/jiayuanliang0716-max/Arbitova

Keywords

arbitova

FAQs

Package last updated on 22 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts