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

allowance-kit

v0.7.1

Published

The missing buyer-side runtime for x402: fund your AI agent once; it pays any x402 API autonomously inside hard policy rails — budgets, per-call caps, velocity circuit breakers, host allowlists, kill switch, audit ledger.

Readme

AllowanceKit

CI

A spending allowance for your AI agent. Fund it once. It pays supported x402-priced APIs on its own — inside hard limits you set, with a kill switch and a receipt for every cent.

Landing page: onewallie.com · Follow-along tutorial: onewallie.com/docs.html

npx allowance-kit demo          # watch the whole thing work, end to end (30 seconds)
npx allowance-kit init          # create the agent's wallet
npx allowance-kit topup 5.00    # fund the allowance
npx allowance-kit dashboard     # live spending, kill switch, approval queue

The AllowanceKit dashboard: $2.14 left of a $5.00 allowance, $2.86 spent across 156 payments with 6 stopped, one $0.42 payment waiting on a human decision, and every payment and block listed in plain English.

The dashboard. One payment is parked for a human — nothing moves until someone decides.

What this does and does not cap

It caps payments your agent makes through AllowanceKit to x402-priced APIs — every call routed through payingFetch.

It does not cap your existing OpenAI, Anthropic, or cloud bill. Those are metered on an account, not paid per call over x402, and nothing here can stop them. If a surprise invoice from a metered API is the problem you're solving, this is not yet the tool for it.

Is this for you?

  • Yes if you're building an agent that calls paid APIs and you want a hard ceiling on what it can spend, plus an audit trail of every payment.
  • Yes if you're selling an x402 API and want drop-in middleware — see paymentGate.
  • Not yet if you want a cap on a credit card or on metered API accounts.

Requires Node ≥ 20.11 to use the npm package. ESM only — import, not require. Zero runtime dependencies. Running this repo's TypeScript sources directly needs Node ≥ 24; on older versions run npm install && npm run build first.


Practice money by default

Out of the box, settlement runs on a local simulated ledger. Every dollar in the CLI, the demo and the dashboard is practice money, and the tool says so at every money touchpoint. Nothing real can move until you deliberately wire a real rail (sellers via CdpFacilitator, buyers via createLiveAgent).

That is the point: you can prove the rails hold before any real funds are at risk.


The one-import SDK

import { createAgent, topUp, payingFetch } from "allowance-kit";

const agent = createAgent(".allowance");        // same default agent the CLI manages
topUp(agent, 5);                                // fund the allowance (practice money)

// The host allowlist is default-deny. Allow the destination first:
agent.policyStore.save({ allowHostSuffixes: ["api.example.com"] });

const res = await payingFetch(agent.ctx, "https://api.example.com/weather?city=lisbon");
if (res.ok) console.log(res.body, res.costMicro, res.txHash);
else console.log(res.blockedBy);  // { rule, detail, recoverable, quotedMicro, capMicro, retryAfterMs?, requestId? }

createAgent(stateDir, agentName) files spend, top-ups and the remaining allowance under agentName. The CLI uses DEFAULT_AGENT_NAME ("research-agent"); pass the same name in code or the agent will look unfunded.

Agents can act on a block, not just log it

blockedBy carries enough to self-correct:

| Field | Use | |---|---| | rule | a closed union — switch on it exhaustively | | recoverable | false means retrying will never help; stop | | quotedMicro / capMicro | how far over the limit the price was → retry a cheaper tier | | retryAfterMs | how long until the velocity window clears → back off | | requestId | the queued approval to escalate to a human |

const res = await payingFetch(agent.ctx, url);
switch (res.blockedBy?.rule) {
  case "velocity_circuit_breaker": await sleep(res.blockedBy.retryAfterMs!); break;
  case "per_call_cap":             return tryCheaperTier(res.blockedBy.quotedMicro!, res.blockedBy.capMicro!);
  case "human_approval_required":  return askHuman(res.blockedBy.requestId!);
  case "insufficient_funds":       return askHumanToFundWallet(res.blockedBy!.capMicro!);
  case "budget_exhausted":         return giveUp("out of allowance");
}

Why spending allowances

A payment facilitator verifies and settles a payment. Wallie checks the configured spending policy before signing it: total allowance, per-payment cap, approved destinations, and spending-rate limits. A local ledger records payments and policy decisions so operators can investigate what happened.

Try the practice-money tutorial before funding a live wallet. Controls apply to payments routed through Wallie; they do not cap existing metered LLM API bills or spending that bypasses the runtime.

The rails

The agent calls payingFetch(ctx, url) instead of fetch(url). That handles the whole protocol — 402 challenge → price discovery → two-phase authorization → signed payment → settle → receipt — while the policy engine enforces:

| Rail | Rule | Blocked pre-payment | |---|---|---| | killSwitch | human freeze, instant | ✅ | | host_not_allowlisted / blockedHosts | default-deny destinations | ✅ | | per_call_cap | max price per single call | ✅ | | velocity_circuit_breaker | rolling-window spend limit (kills retry loops) | ✅ | | budget_exhausted | hard total: the agent can spend min(totalBudgetUsd, amount funded) | ✅ | | insufficient_funds | live rails only: the wallet's real USDC balance cannot cover the price | ✅ | | human_approval_required | escalation gate above threshold | ⏸ blocked & queued until you approve | | settlement_rejected | the seller refused the payment; nothing was spent | ✅ logged |

Two properties worth stating plainly:

  • Authorization is atomic. Deciding and reserving happen inside one state-dir lock, and in-flight payments count as spent until they settle. Twenty parallel payingFetch calls against a $1.00/60s velocity limit settle exactly $1.00 — a retry storm cannot fan out past the breaker.
  • totalBudgetUsd is enforced, not decorative. The spendable ceiling is the smaller of what you configured and what you funded.
  • On a live rail, the wallet is checked too. The allowance says what a human permitted; the chain says what is actually there. A payment the allowance allows but the wallet cannot cover is refused as insufficient_funds before anything is signed — not discovered at the facilitator. If the RPC is unreachable the rails fall back to the allowance rather than freezing the agent over someone else's outage.

Approvals are real, and they are not permanent. An above-threshold call is blocked and queued (allowance-kit approvals or the dashboard). Approving creates a grant that expires in 24 hours and covers exactly the amount that was approved — one yes is one payment, not a standing licence. Widen it deliberately:

npx allowance-kit approve a1b2c3d4                        # that payment, for 24 hours
npx allowance-kit approve a1b2c3d4 --budget 2.00          # up to $2.00 of spend to that host
npx allowance-kit approve a1b2c3d4 --expires 2h           # or 30m, 7d, never

Grants draw down as payments authorize against them, and a payment that never settles hands its budget back. Approving does not execute the payment; the agent completes it on its next attempt. Every step is in the ledger.

The kill switch and approval queue are token-gated: mutating dashboard endpoints require the local control token (auto-generated into .allowance/dashboard-token, injected into the served UI).

Every decision — paid or blocked, with rule, reason and tx hash — lands in an append-only JSONL ledger (.allowance/ledger.jsonl) for reviewing the runtime’s decisions. Read it as a table with allowance-kit audit, or as raw JSONL with allowance-kit audit --json.

CLI

init                            provision the agent wallet in ./.allowance
topup <usd>                     add to the allowance
status                          what is left, what the limits are, what needs you
policy [field value]            show or change one limit
approvals                       payments waiting for your decision, and live grants
approve <id> | deny <id>        decide one (--budget <usd>, --expires <30m|2h|7d|never>)
audit [--json]                  the full spending history
notify [webhook|email|sms|push|heartbeat|test|off]   where alerts are sent, and on what
agents                          every agent sharing this state directory
dashboard [--port <n>]          live dashboard (default http://localhost:4030)
demo                            run the built-in demo into ./.allowance-demo

--state <dir>                   state directory (default ./.allowance, or $ALLOWANCE_STATE_DIR)
--agent <name>                  which agent in that directory (default research-agent, or $ALLOWANCE_AGENT)

More than one agent in one directory

Every command takes --agent. Limits, allowances, approvals and alert settings are per agent; the audit ledger is shared and every row is tagged.

npx allowance-kit topup 3.00 --agent writer-agent
npx allowance-kit policy perCallMaxUsd 0.02 --agent writer-agent
npx allowance-kit agents        # what is in this directory, and what each has left

The first agent keeps the original file names (config.json, agent.json), so a directory written by an earlier version reads back unchanged.

Limits: totalBudgetUsd, perCallMaxUsd, windowLimitUsd, windowSeconds, requireApprovalAboveUsd, allowHostSuffixes, blockedHosts, killSwitch. Unknown fields are rejected, not silently written, and combinations where one rail shadows another produce a warning.

npx allowance-kit policy perCallMaxUsd 0.10
npx allowance-kit policy allowHostSuffixes api.weather.com,api.search.com
npx allowance-kit policy killSwitch true      # freeze everything, right now

Alerts, so nobody has to watch a screen

A dashboard only helps someone who is looking at it. The runs that hurt happen overnight.

npx allowance-kit notify webhook https://hooks.slack.com/services/...   # Slack, Discord, Zapier, your own server
npx allowance-kit notify email [email protected] --from [email protected]    # needs a provider key, below
npx allowance-kit notify sms +31612345678                               # needs Twilio keys, below
npx allowance-kit notify push my-agent-alerts                           # ntfy.sh — no account, no key
npx allowance-kit notify heartbeat https://hc-ping.com/<uuid>           # a dead-man's switch, see below
npx allowance-kit notify test                                           # send one of each now, report delivery
npx allowance-kit notify                                                # show what is set up
npx allowance-kit notify off                                            # stop sending anything

You get told about three things:

  • Spending, at 50%, 80% and 100% of the allowance. Once per threshold, not once per payment. Topping up rearms them.
  • Every block — which rail refused, what it tried to pay, and that nothing moved.
  • Every payment waiting on you, with the approve and deny commands to settle it.

Every channel is an HTTP POST made with the platform's own fetch — email and SMS go through a provider's REST API rather than SMTP or a vendor SDK, so the package keeps its zero-dependency promise. Keys live in your environment, never in a config file:

export RESEND_API_KEY=...        # for --via resend (the default)
export POSTMARK_API_TOKEN=...    # for --via postmark
export TWILIO_ACCOUNT_SID=... TWILIO_AUTH_TOKEN=... TWILIO_FROM=+1...   # for notify sms

Push needs nothing at all: pick a topic, install the ntfy app, subscribe. Anyone who knows the topic name can read it, so pick something unguessable.

notifications.json in the state dir holds addresses and providers. It never holds a key, so it is safe to read, copy, or paste into a bug report.

Delivery is retried, and failures are written down. A timeout, a 429 or a 5xx is tried three times with backoff; a 401 is not retried, because a wrong key is wrong three times too. Anything that still never arrived lands in notify-failures.jsonl and is surfaced by notify and status. Alerts remain best-effort by construction — never awaited inside the ledger lock, so a webhook that hangs cannot slow a payment down and one that errors cannot fail one. The ledger, not your inbox, is the record of what happened.

When the machine itself goes quiet

Nothing running on your laptop can tell you that your laptop is off. Something outside it can:

npx allowance-kit notify heartbeat https://hc-ping.com/<uuid>
npx allowance-kit dashboard        # pings that URL every 60s while it runs

Point healthchecks.io, Cronitor or your own monitor at that URL and it alerts you when the pings stop. That is the honest shape of the guarantee: the free channels fire while the agent is running somewhere you control, and a dead-man's switch covers the case where it is not.

Architecture

src/
  index.ts          public API — `import { payingFetch, createAgent, topUp } from "allowance-kit"`
  types.ts          x402 wire types (PaymentRequired, PaymentPayload, receipts)
  money.ts          integer micro-dollar math (no float drift)
  chain.ts          settlement + Facilitator interface {verify, settle}
                    MockChain = deterministic local ledger w/ replay protection,
                    snapshots to disk. Swap for a real facilitator by
                    implementing 2 methods — nothing else changes.
  facilitator-cdp.ts Coinbase CDP facilitator: verify/settle over the x402 v1
                    facilitator contract with ES256 request-signed JWTs
                    (node:crypto only). For sellers settling real USDC on Base.
  live.ts           live-network agent runtime: real x402 v1 EVM payloads
                    (EIP-3009 TransferWithAuthorization, EIP-712 signed via
                    optional viem) against any live x402 endpoint.
  seller.ts         paymentGate(): drop-in x402 middleware for any node:http route
  payer.ts          payingFetch(): the agent-side client (two-phase authorization)
  policy.ts         PolicyStore (hot-reloaded JSON) + evaluatePolicy() + field validation
  lock.ts           state-dir mutex (in-process + cross-process, stale-safe)
  reservations.ts   authorized-but-unsettled spend, so parallel calls can't overspend
  approvals.ts      human-approval queue (request → decide → standing grant)
  wallet.ts         agent runtime: stable wallet identity, funding, authorization gate
  ledger.ts         append-only audit log (parse-cached, single-pass totals)
  demo-servers.ts   five x402-priced APIs used by the demo
  demo-run.ts       the demo story, shipped in the package as `allowance-kit demo`
  dashboard-server.ts + public/dashboard.html   live UI; kill switch & approvals
                    are token-gated (.allowance/dashboard-token)
test/               zero-dependency node --test suite

The buyer supports exact USDC payments on Base, Base Sepolia, Solana, and Solana devnet, plus Solana upto payment channels. See the compatibility guide for supported wire shapes and validation limits.

Sellers

import { paymentGate, CdpFacilitator } from "allowance-kit";

paymentGate(
  {
    priceMicro: 10_000n,               // $0.01 == 10k atomic USDC units
    description: "Weather lookup",
    payTo: "0xYourMerchantAddress",
    network: "base-sepolia",
    facilitator: new CdpFacilitator(), // reads CDP_API_KEY_ID / CDP_API_KEY_SECRET
  },
  handler,
);

Live networks

Real money in five commands — no code, straight from the shell. Base Sepolia is free testnet USDC, so prove it there first:

export AGENT_PRIVATE_KEY=0x...                     # your wallet key — read from the env, never written to disk
npx allowance-kit init --live                      # mark the directory live, print the wallet address
# 1. send USDC to that address (a Base Sepolia faucet, for testnet)
npx allowance-kit topup 5.00                       # 2. set the ceiling the agent may spend
npx allowance-kit policy perCallMaxUsd 0.10        # 3. tighten the rails
npx allowance-kit pay https://some-live-x402-api.com/data   # 4. make a real payment
npx allowance-kit doctor                           # checks node, viem, the key, RPC, permissions

Mainnet is one flag and a confirmation: npx allowance-kit init --live --network base (it asks you to type base back, or takes --yes in a script), and top-ups over $50 then need --yes too. status shows the wallet's real balance; pay exits 0 on a paid call, 2 on a policy block, 1 on error.

Or from the SDK:

import { payingFetch, createLiveAgent, topUp } from "allowance-kit";

const live = await createLiveAgent({
  stateDir: ".allowance",
  privateKey: process.env.AGENT_PRIVATE_KEY!,
  network: "base-sepolia",              // "base" is mainnet — ask for it explicitly
});

topUp(live, 5);                         // the ceiling you allow out of that wallet
live.policyStore.save({ allowHostSuffixes: ["some-live-x402-api.com"] });

const res = await payingFetch(live.ctx, "https://some-live-x402-api.com/data");

The allowance and the wallet are two different numbers, and both are enforced. topUp records what you are willing to let the agent spend; the USDC itself arrives by being sent to live.address. A payment inside the allowance that the wallet cannot cover is refused as insufficient_funds before anything is signed. Check both at once with allowance-kit status, which prints the wallet's real balance on a live directory.

The directory is marked live the moment createLiveAgent touches it. The CLI and dashboard show live USDC payments and the configured network. In the example above that network is base-sepolia; Solana directories show their selected Solana network. Funding from the CLI on a live directory raises the spending ceiling and moves no funds.

network is a hard constraint, not a hint: a seller quoting a chain the agent was not configured for is refused before signing, so a testnet agent can never be talked into signing a mainnet authorization.

Signing needs the optional peer dependency viem (npm i viem); everything else stays zero-dep. Policy, approvals, kill switch and the audit ledger apply identically to simulated and live spending.

Prove the whole path before trusting it with anything:

node --env-file=.env scripts/canary.ts --buyer                  # Base Sepolia, free faucet USDC
node --env-file=.env scripts/canary.ts --buyer --network base   # mainnet, real money

It funds a $0.20 allowance with a $0.05 per-call cap, settles a real $0.01 payment through a CDP facilitator, then tightens the cap and checks the next payment is refused — and fails loudly if the audit ledger does not show exactly one payment and one block.

Solana

Version 0.6.0 adds Solana exact and upto payments. The recorded public devnet canary deposited $0.10, paid $0.03, and refunded $0.07 in a finalized transaction. Inspect the canary record. This is devnet evidence; it does not establish Solana mainnet production readiness.

For a repeatable demo with no keys or funded accounts, use Node 24 or later. The commands below use the published 0.6.0 release. Before publication, run npm ci and npm run demo:mcp in the prepared checkout:

git clone --branch v0.6.0 --depth 1 https://github.com/fskroes/AllowanceKit.git
cd AllowanceKit
npm ci
npm run demo:mcp

The exact phase uses the local practice rail. The Solana metered phase builds the channel transaction and uses an offline seller operator. The public devnet canary is separate. The stock monitor uses this runtime to buy AAPLx, NVDAx and SPYx reports within a simulated USDC budget. It offers scenario or live DEX data and stock-specific alerts. See the Stocklana submission pack; videos are deferred to the project owner.

For a live Solana project, install the optional chain libraries:

npm install [email protected] @solana/kit@^5.5.1 @x402/[email protected] @solana-program/token@^0.9.0
export AGENT_PRIVATE_KEY='your Solana secret key'
npx allowance-kit init --live --network solana-devnet
npx allowance-kit doctor
# Send devnet USDC to the displayed address before making a live payment.
npx allowance-kit topup 1.00
npx allowance-kit policy perCallMaxUsd 0.10
npx allowance-kit policy allowHostSuffixes your-seller.example
npx allowance-kit channels list

The key accepts a base58 secret or a solana-keygen JSON array. It stays in the environment. topup changes the permitted allowance; it does not transfer tokens. The seller sponsors the normal payment path. Buyer reclaim requires SOL.

Channel accounting survives missing receipts and process restarts. A resolved payment enters the ledger before its escrow is released, and repeated recovery does not count the same payment or grant refund twice. Missing account data alone does not prove a refund: the runtime checks finalized channel history. If evidence is unavailable, the deposit remains held. Corrupt channel state blocks new authorization instead of silently resetting spending limits.

npx allowance-kit channels reconcile
npx allowance-kit channels reclaim CHANNEL_ID

Solana sellers start the library cleanup worker automatically. Its public channel index is persisted in .allowance-seller/seller-channels.json, or the directory set by ALLOWANCE_SELLER_STATE_DIR. Keys are excluded from this file. An explicit recovery sweep is also available:

npx allowance-kit channels sweep --seller --network solana-devnet \
  --seller-state-dir .allowance-seller

Configure the seller keys through SELLER_FEE_PAYER_KEY and SELLER_AUTHORIZER_KEY. The library submits settleAndSeal and distribute atomically. A failed transaction can leave the channel open; cleanup follows the library's abandon-close rules after expiry and its 120 second grace period. It does not replay a failed charge. Await gate.ready() before listening and gate.stop() after closing the HTTP server. Direct operator users must await operator.stop() too.

Seller cleanup uses a compatibility adapter for the pinned @x402/[email protected]: the library reverses the program's Sealed and Closing state values. Only cleanup reads use the corrected mapping; payment verification receives original data. The index records each signed openSlot before broadcast. An absent channel is removed only when a finalized RPC response proves absence after openSlot + 1500. RPC errors and old records without an open slot remain indexed for retry. Do not delete these records to clear a pending count. Upgrade the library only with the cleanup integration tests and adapter changes together.

MCP server

Give an MCP client — Claude Desktop, an agent framework, anything that speaks the Model Context Protocol — a spending allowance. wallie-mcp serves the same runtime the CLI uses over stdio, so the agent pays x402 APIs (Base or Solana, exact or upto) inside the same policy rails, ledger and escrow book.

export AGENT_PRIVATE_KEY=0x...          # only for a live directory; a fresh one is practice money
export ALLOWANCE_STATE_DIR=.allowance  # optional, this is the default
npx [email protected]                    # speaks MCP over stdio; includes chain libraries

Point a client at it, e.g. in Claude Desktop's claude_desktop_config.json:

{
  "mcpServers": {
    "wallie": { "command": "npx", "args": ["wallie-mcp"], "env": { "ALLOWANCE_STATE_DIR": ".allowance" } }
  }
}

Five tools, over stdio:

| Tool | Does | |---|---| | pay_fetch(url, method?, body?, headers?) | Fetch an x402 URL, paying inside the rails. Returns the response, what was spent, and — on a refusal — a blocked reason in plain language, never an exception. | | get_budget() | Funded ceiling, spent, reserved, escrowed (open channels), remaining, and the velocity-window state. | | list_channels() | The buyer's book of Solana upto payment channels — each deposit's status, settled and refunded amounts. | | decide_approval(id, approve) | Approve or deny a payment the rails queued for a human; approving mints a time-boxed, budget-limited grant. | | reclaim_channel(id) | Sweep an orphaned Solana channel's deposit back to the wallet after its grace period. |

Approval tools are administrative authority. A client that receives decide_approval can approve queued requests; do not give that authority to an untrusted agent and call it a separate human approval boundary. Wallet keys and state-directory write access also require a trusted process.

The server binds one runtime, resolved from the state directory exactly as the CLI resolves it: mode.json says whether it is live, AGENT_PRIVATE_KEY supplies the key. The runtime is chosen once, so pay_fetch transparently settles exact on Base or exact/upto on Solana without the caller choosing a scheme.

The MCP surface is also importable from the SDK:

import { createMcpServer, runMcpStdio } from "allowance-kit/mcp"; // or from "wallie-mcp"

@modelcontextprotocol/sdk is an optional peer, loaded lazily — importing allowance-kit never pulls the MCP stack in, only allowance-kit/mcp does.

The example agent drives the server end to end, offline:

npm run demo:mcp    # node demo/mcp-agent/agent.ts

It lists the tools, buys an exact API, hits a per-call cap (a block named in RULE_LABELS language), then buys a metered Solana upto API for less than its ceiling and watches the rest refund.

Demo output (abridged)

npx allowance-kit demo:

PHASE 1 · fine-grained pay-per-use
  PAID    weather?city=lisbon            $0.001000  0xcddcb9a6…
  PAID    research?topic=agent-payments  $0.250000  0x4e5bc352…

PHASE 2 · runaway loop
  PAID    loop #1…#149                   $0.010000 each
  BLOCKED loop #150  Too much, too fast  rolling 12s spend would exceed $2.00

PHASE 3 · attack, mispricing & approval gate
  BLOCKED evil-api.example.com  Site not on your approved list
  BLOCKED report?id=q3-2026     Waiting for your approval ($0.45 ≥ $0.30 → queued)
  PAID    report?id=q3-2026 (retry)      $0.450000 (approved grant)
  BLOCKED feed?key=pro          Over your per-payment limit ($5 > $0.50)

PHASE 4 · kill switch
  BLOCKED weather?city=berlin   Spending paused by you

spent $2.443 across 155 settled payments; 5 policy blocks enforced
remaining allowance: $2.557 of $5.00 practice money

Business model

See BUSINESS.md.

Honest limitations

  • Default settlement is a local mock ledger — all funds are simulated until you deliberately wire a real rail. Sellers settle real USDC via CdpFacilitator; buyers sign real x402 payments via createLiveAgent (needs optional viem).
  • The buyer speaks x402 v1 and v2, and has settled against a live third-party seller. The live ecosystem has moved to v2 (CAIP-2 networks, PAYMENT-* headers — see docs/x402-compat.md); the buyer detects the version and answers in kind. On 2026-09-07 it paid a real third-party v2 seller — Mart402's PDF parser on Base Sepolia — end to end: negotiated the multi-offer 402, selected the payable offer, signed a real EIP-3009 authorization, and the seller's facilitator settled it on-chain (tx 0xf53b18b0…d817e, $0.004 USDC), returning the parsed document. Recorded in docs/canary-runs/2026-09-07-base-sepolia-mart402.md. (An earlier attempt against QuickNode reached the settlement boundary but 404'd on the testnet it advertised — docs/x402-compat.md §8.) The CdpFacilitator v2 body follows the spec but has not been round-tripped against real CDP.
  • The live buyer path is proven on Base Sepolia and on Base mainnet. scripts/canary.ts --buyer settles a real testnet USDC payment through a CDP facilitator inside real rails and checks the ledger afterwards; --network base ran the same on mainnet on 2026-09-07 — a real $0.01 USDC settlement, tx 0x044245…2648e, recorded in docs/canary-runs/2026-09-07-base.md. It is a single canary run, not sustained production traffic — treat early mainnet use as canary.
  • Alerts are best-effort, not guaranteed. Retried three times with backoff, then recorded in notify-failures.jsonl — but never awaited inside the ledger lock, so a payment is never delayed or failed by a broken channel. The ledger, not your inbox, is the record of what happened.
  • Local alerts require your infrastructure to be running. Wallie Cloud adds a hosted event feed, heartbeat monitoring, and email rules for connected agents.
  • SMS needs a Twilio account and costs money per message. Push over ntfy is unauthenticated by design: anyone who knows the topic name can read your alerts.
  • The on-chain balance check reads USDC over a public RPC and caches it for 15 seconds, so a payment can be authorized against a reading that is up to 15 seconds stale. Bring your own rpcUrl for anything busy.
  • Several agents can share a state dir, but they share one lock, so a very busy agent serialises the others' authorizations.
  • The dashboard binds to 127.0.0.1; reads and mutations require its token. Its agent switcher selects among agents in the state directory.
  • npm ships compiled dist/ (ESM + .d.ts, zero runtime deps).

Changes

See CHANGELOG.md for release history and current limitations, and npm for the currently published version.