Agentscanspend.Theycan'toverspend.
One signed AP2 mandate. A contract on Stellar, Solana or Base that re-checks scope, amount, expiry and replay on every call. x402 turns the 402 into a 200 only after settlement clears.
Three settle.
The fourth gets rejected.
That is the reference run: npm run agents:testnet creates fresh funded actors, drives real agent.fetch() purchases, verifies each one independently — and the fourth purchase is refused by the contract-enforced budget, not by the client.
Not a diagram. A dependency.
Drop the SDK in front of any HTTP call your agent already makes. The contract does the arguing.
1npm i @reapp-sdk/core2npx ackrate init --chain stellar,solana,base
402 to 200.
A protected GET returns 402 Payment Required with a bound challenge. The agent submits the exact contract payment, the on-chain registry verifies authority and settles, and the retry returns 200 with the paid result. An old settlement re-signed for a fresh request is rejected.
Limits they can't talk past.
MandateRegistry checks merchant scope, amount, expiry, replay state and remaining authority before any paid work is delivered. execute_payment validates, consumes, then transfers — atomically. Prompt injection, a rogue model or a patched client all hit the same wall.
Deployed from attested artifacts.
Releases are built from reproducible, hash-checked workflows, attested on GitHub, then deployed and re-verified on every chain we ship to — Stellar, Solana and Base. Upgrades run through a timelock and land at the original program address.
Every call leaves a receipt.
This is what npm run agents:testnet does, in order. Three calls clear. The fourth is refused on-chain — and the run prints the explorer link for every one of them, so you check them, not us.
reference run · fresh funded testnet actors · ~48s end to end
Agents can already pay.
Nothing proves they were allowed to.
Handing an agent a key hands it everything.
Most agent payment stacks fund a hot wallet or a custodial balance the agent controls. ackrate never does: the user approves a SEP-41 allowance for the MandateRegistry contract — never for the agent, the SDK, or the CLI.
An SDK-side limit is a suggestion.
Client-side checks can be edited out. In ackrate the SDK only prepares a request; MandateRegistry.execute_payment re-validates auth, scope, asset, expiry, budget and sequence, then consumes and transfers atomically in one transaction.
Agents loop. Payments shouldn't.
Every spend supplies the current mandate sequence, so stale and out-of-order calls are rejected. Bound-v2 challenges tie each payment to an exact origin, an agent signature and an immutable result — public-transaction reuse is closed.
One enforced payment path.
Click through the stack.
MandateRegistry (multichain)
Money moves only through execute_payment (solo) and clear_pool (composite capture), with the same boundary deployed on Stellar, Solana and Base. Each validates and consumes atomically before any transfer — a failed transfer reverts the state change.
- Re-checks caller auth, merchant scope, asset, budget, expiry and sequence on every payment
- Consumes mandate (spent + sequence) then calls SEP-41 transfer_from in the same transaction
- Replay-resistant: stale and out-of-order sequences are rejected
- Rust · wasm32v1-none · reproducible build, SHA-256 hash attested on GitHub and matched on chain
execute_payment(mandate_id, amount, merchant, seq) ↳ validate → consume → transfer_from
Six runnable surfaces —
all of them settle on testnet.
Tap any surface to see what it proves.
Starter library
Each starter ships as a ZIP verified against its published SHA-256 before extraction, or can be run straight from the public source clone. Recorded clean-room run: about 48 seconds from empty folder to testnet evidence.
Configure the policy.
Watch the chain enforce it.
Every choice writes to the on-chain MandateRegistry. Fire calls at it — the contract accepts what fits and reverts what doesn't.
{
"cap": "$10",
"period": "day",
"maxPerTx": "$2.00",
"merchants": ["openai.com","anthropic.com","replicate.com"],
"expiresIn": "24h",
"signature": "0x10daycompute24…"
}How ackrate Works
A live trace of consent — from the human signature to merchant settlement. It plays itself. Touch anything to take the wheel.
One call. Three protocols.
The SDK composes AP2 authorization, multichain policy enforcement, and x402 HTTP settlement into a single TypeScript primitive. You write fetch(); we handle the rest.
- TypeScript-first, framework-agnostic
- Round-trip bound-v2 challenge before signing
- Deterministic — same inputs, same outcome, always
Why Multichain
One mandate spec. Three enforcement targets. The same gate checks compile down to each chain's native execution environment.
Fixed-fee rails built for micropayments.
- Native USDC through the Stellar Asset Contract — no ERC-20 wrapper overhead.
- Smart accounts with __check_auth run a per-invocation authorization check.
- Native fee-bump sponsorship: agents transact without ever holding XLM.
Every claim is a build artifact
Straight from the contracts repo gate check and the tagged, attested multichain releases. Click any tile to flip it.
Who's Building ackrate
Alex Astrum
Agentic AI expert with 20+ years of full-stack engineering experience, currently at Google on the Antigravity team within the Gemini ecosystem. Contributor to Firebase. Leads ackrate's spec design, SDK architecture, and technical strategy.
Drew Raines
Shipped smart contracts and production systems across eight chains including Ethereum, Solana, Bitcoin, and Cosmos. Built an NFT marketplace engine, a decentralized social network on Polygon, and a Bitcoin ordinal inscription engine on ICP. Leads ackrate's multichain contract implementation and x402 integration across Stellar, Solana and Base.
Max Shama
Led the development of agentic blockchain products across NEAR and Avalanche, including DeFi agents and custom AI agent frameworks. Previously a chair in NEAR NDC overseeing ecosystem grant allocation. Leads ackrate's product direction and ecosystem partnerships.
Run it in an empty folder.
No wallet, no repository, no mainnet keys. Disposable testnet actors, clickable explorer evidence, and a rejection you can reproduce.
then run npm run agents:testnet to watch the fourth call get refused