npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

trust-escrow

v0.1.0

Published

Escrow primitive for the Machine Economy — CLI and library for AI agent escrow on Base

Readme

trust-escrow

x402 for payments. Trust for escrow.

Escrow primitive for AI agent transactions on Base. AI agents lock USDC in escrow, an evaluator agent verifies delivery quality, funds are released or split based on the outcome. 0.3% protocol fee.

What it does

  • Agent A (buyer) locks USDC in escrow before work starts
  • Agent B (seller) delivers the work and marks it complete
  • Agent A approves and releases funds — or opens a dispute
  • Agent C (arbiter/evaluator) resolves disputes by splitting funds (0–100%)
  • Automatic refund if seller doesn't deliver by deadline
  • Automatic release if buyer doesn't act after delivery

Install

# Library (import in your agent code)
npm install trust-escrow

# CLI (use from terminal or agent shell)
npx trust-escrow --help

Quick Start — CLI

# Create escrow: Agent A locks 10 USDC for Agent B, Agent C arbitrates
npx trust-escrow create \
  --buyer 0xAGENT_A \
  --seller 0xAGENT_B \
  --arbiter 0xAGENT_C \
  --amount 10 \
  --delivery-time-limit 7d \
  --payment-time-limit 14d \
  --arbiter-time-limit 30d \
  --private-key $BUYER_PRIVATE_KEY

# Fund escrow (auto-approves USDC allowance)
npx trust-escrow fund 12 --private-key $BUYER_PRIVATE_KEY

# Seller marks delivery complete
npx trust-escrow deliver 12 --private-key $SELLER_PRIVATE_KEY

# Buyer releases funds (happy path)
npx trust-escrow release 12 --private-key $BUYER_PRIVATE_KEY

# OR: Buyer opens dispute (quality not satisfactory)
npx trust-escrow dispute 12 --private-key $BUYER_PRIVATE_KEY

# Arbiter resolves: 70% to seller, 30% to buyer
npx trust-escrow resolve 12 --split 70 --private-key $ARBITER_PRIVATE_KEY

# Check status (no private key needed)
npx trust-escrow status 12

Quick Start — Library

import { createPublicClient, createWalletClient, http } from 'viem'
import { baseSepolia } from 'viem/chains'
import { privateKeyToAccount } from 'viem/accounts'
import {
  createEscrow,
  fundEscrow,
  markDelivered,
  releaseFunds,
  openDispute,
  resolveDispute,
  getEscrow,
  parseUSDC,
  formatUSDC,
  type TrustConfig,
} from 'trust-escrow'

// Build config for an agent wallet
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)
const config: TrustConfig = {
  contractAddress: '0x2aCEa5D1F1e562F7D4040e0003A4bf46030f2ac0',
  tokenAddress: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // USDC on Base Sepolia
  chain: baseSepolia,
  publicClient: createPublicClient({ chain: baseSepolia, transport: http() }),
  walletClient: createWalletClient({ account, chain: baseSepolia, transport: http() }),
}

// Create escrow: 10 USDC with default time limits
const txHash = await createEscrow(config, {
  buyer:  '0xAGENT_A',
  seller: '0xAGENT_B',
  arbiter: '0xAGENT_C',
  amount: parseUSDC('10'),
  deliveryTimeLimit: 0n,  // 0 = contract default (30 days)
  paymentTimeLimit:  0n,  // 0 = contract default (14 days)
  arbiterTimeLimit:  0n,  // 0 = contract default (30 days)
})

// Fund, deliver, release
await fundEscrow(config, escrowId)
await markDelivered(sellerConfig, escrowId)
await releaseFunds(config, escrowId)

// OR open dispute and resolve
await openDispute(config, escrowId)
await resolveDispute(arbiterConfig, { escrowId, percentageToSeller: 7000n }) // 70%

// Read escrow state
const escrow = await getEscrow(config, escrowId)
console.log(escrow.state, formatUSDC(escrow.amount))

CLI Commands

| Command | Description | |---------|-------------| | create | Create a new escrow (7 params: buyer, seller, arbiter, amount, 3 time limits) | | fund <id> | Fund escrow (auto-approves USDC allowance if needed) | | deliver <id> | Seller marks delivery complete | | release <id> | Buyer releases funds to seller (after delivery) | | dispute <id> | Buyer or seller opens a dispute (after delivery) | | resolve <id> --split <0-100> | Arbiter resolves dispute with split percentage to seller | | settle <id> | Propose (--propose <pct>) or approve a settlement (during dispute) | | cancel <id> | Request (--request) or approve mutual cancellation | | refund <id> | Buyer claims refund after delivery deadline expired | | timeout <id> --type payment | Seller claims after buyer payment timeout (v1.2) | | timeout <id> --type arbiter | Claim after arbiter resolution timeout (v1.2) | | status <id> | View all 15 escrow fields (read-only, no key needed) | | next-id | View next escrow ID (read-only, no key needed) |

Global options (available on all commands):

--private-key <key>    Private key for signing (or set PRIVATE_KEY env var)
--contract <address>   TrustEscrow contract address (default: Base Sepolia v1.2)
--token <address>      USDC token address (default: Base Sepolia)
--rpc <url>            Custom RPC URL (default: https://sepolia.base.org)

Library API

Write functions (require walletClient)

| Function | Signature | Description | |----------|-----------|-------------| | createEscrow | (config, CreateEscrowParams) => Promise<Hash> | Create escrow with 7 params | | fundEscrow | (config, escrowId: bigint) => Promise<Hash> | Atomic approve + fund | | markDelivered | (config, escrowId: bigint) => Promise<Hash> | Seller marks delivery | | releaseFunds | (config, escrowId: bigint) => Promise<Hash> | Buyer releases to seller | | openDispute | (config, escrowId: bigint) => Promise<Hash> | Open dispute after delivery | | resolveDispute | (config, ResolveDisputeParams) => Promise<Hash> | Arbiter resolves with split | | proposeSettlement | (config, ProposeSettlementParams) => Promise<Hash> | Propose settlement during dispute | | approveSettlement | (config, ApproveSettlementParams) => Promise<Hash> | Approve settlement (L-02 safe) | | requestCancel | (config, escrowId: bigint) => Promise<Hash> | Request mutual cancellation | | approveCancel | (config, escrowId: bigint) => Promise<Hash> | Approve cancellation request | | claimRefund | (config, escrowId: bigint) => Promise<Hash> | Buyer refund after deadline | | claimAfterPaymentTimeLimit | (config, escrowId: bigint) => Promise<Hash> | Seller claims after buyer timeout | | claimAfterArbiterTimeLimit | (config, escrowId: bigint) => Promise<Hash> | Claim after arbiter timeout | | approveUSDC | (config, amount: bigint) => Promise<Hash> | Standalone USDC approval |

Read functions (publicClient only)

| Function | Signature | Description | |----------|-----------|-------------| | getEscrow | (config, escrowId: bigint) => Promise<EscrowData> | Read all 15 escrow fields | | getNextEscrowId | (config) => Promise<bigint> | Next escrow ID to be assigned |

Utility functions

| Function | Signature | Description | |----------|-----------|-------------| | formatUSDC | (amount: bigint) => string | 6-decimal bigint to "10.50" | | parseUSDC | (amount: string) => bigint | "10.50" to 6-decimal bigint |

Time Limits (v1.2)

TrustEscrow v1.2 introduced three independent configurable time limits per escrow:

| Parameter | CLI flag | Default | Description | |-----------|----------|---------|-------------| | deliveryTimeLimit | --delivery-time-limit | 30 days | Seller must mark delivery within this window (starts at funding) | | paymentTimeLimit | --payment-time-limit | 14 days | Buyer must release/dispute within this window (starts after delivery) | | arbiterTimeLimit | --arbiter-time-limit | 30 days | Arbiter must resolve within this window (starts when dispute opened) |

Duration format: 7d, 24h, 30m, or plain seconds. Pass 0 for contract default.

Bounds: Minimum 1 hour, maximum 90 days per time limit.

When a time limit expires:

  • Delivery deadline: buyer can call claimRefund to recover USDC
  • Payment deadline: seller can call timeout --type payment to claim payment
  • Arbiter deadline: either party can call timeout --type arbiter to recover USDC

Use Case: Agent Service Escrow

The canonical trust-escrow use case for AI agents:

1. Agent A (client) identifies Agent B (service provider) via agent marketplace
2. They agree on terms: task, payment (10 USDC), evaluation criteria
3. Agent A creates and funds escrow — payment locked, not yet sent
4. Agent B executes the task and calls markDelivered
5a. If quality is good: Agent A calls releaseFunds — Agent B gets 9.97 USDC (0.3% fee)
5b. If quality is partial: Agent A opens dispute, Agent C evaluates
    Agent C resolves: e.g., 70% to Agent B (6.97 USDC), 30% refunded to Agent A (2.9 USDC)
    Agent C receives 1.5% dispute fee (0.15 USDC)

See examples/agent-escrow-demo.ts for a full runnable demo with 3 wallets on Base Sepolia.

Trust in the Agent Stack

Agent A ──[wants service]──► Agent B
   │                              │
   ▼                              ▼
x402                          trust-escrow
(micropayments:              (escrow: lock funds,
 pay per API call)            verify delivery, split)
  • x402 (Coinbase) — HTTP 402 payment required. Instant pay-then-get. For API calls, data access, streaming services.
  • trust-escrow — Escrow with delivery verification. For tasks with uncertain outcomes, multi-step work, or quality that requires evaluation.

Use x402 when you trust the service. Use trust-escrow when you need protection.

Contract

  • Network: Base (Base Sepolia for testnet)
  • Version: v1.2 (7-param createEscrow, 3 independent time limits, L-02 settlement fix)
  • Protocol fee: 0.3% on releaseFunds and resolveDispute
  • Dispute fee: 1.5% paid to arbiter on resolveDispute
  • No fee: on cancel, claimRefund, claimAfterPaymentTimeLimit, claimAfterArbiterTimeLimit
  • Security: Audited, 99.35% test coverage (107 tests including fuzz + invariant)

Running the Demo

# 1. Set up wallets and environment
cp packages/trust-escrow/examples/.env.example packages/trust-escrow/examples/.env
# Edit .env: fill in BUYER_PRIVATE_KEY, SELLER_PRIVATE_KEY, ARBITER_PRIVATE_KEY, CONTRACT_ADDRESS

# 2. Fund wallets with testnet ETH: https://faucet.coinbase.com (Base Sepolia)
# 3. Fund buyer with testnet USDC: at least 5 USDC

# 4. Run demo
cd packages/trust-escrow
npm run demo

Expected output: 9 transactions across 2 paths (happy + dispute), all confirmed on Base Sepolia.

License

MIT