This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Root (pnpm workspace + Turbo)
pnpm build # Build all packages
pnpm typecheck # Type-check all packages
pnpm test # Run all tests
# packages/mpp
pnpm build # tsc compile → dist/
pnpm dev # tsc --watch
pnpm typecheck # tsc --noEmit
# packages/contracts (Foundry)
forge build # Standard compile
forge build --zksync # ZKsync VM compile (requires foundry-zksync)
forge test -v # Run 17 contract tests
forge soldeer install # Install Solidity deps (solady, forge-std)
# examples
pnpm dev # tsx src/index.ts or tsx src/agent.ts
pnpm typecheck # tsc --noEmitLinting/formatting uses Biome (biome.json at root). Solidity files are excluded from Biome.
This is a Machine Payments Protocol (MPP) plugin for the Abstract blockchain, enabling paid API access via two settlement mechanisms.
packages/contracts/ Solidity — AbstractStreamChannel.sol
packages/mpp/ TypeScript plugin (npm: @abstract-foundation/mpp)
examples/hono-server/ Server example using the plugin
examples/agent-client/ Autonomous client that pays via 402 flow
Both payment intents follow the same HTTP protocol:
- Client requests a resource → server responds
402 Payment RequiredwithWWW-Authenticate: Payment method="abstract" - Client signs and retries with
Authorization: Payment <base64url> - Server verifies, settles on-chain, responds
200 OKwithPayment-Receipt
The mppx framework (peer dep ^0.4.9) handles this 402 negotiation loop. @abstract-foundation/mpp implements the Abstract-specific signing and settlement logic on top.
charge (ERC-3009 TransferWithAuthorization)
- Client signs typed data only — no transaction from client
- Server calls
transferWithAuthorization()on USDC.e, paying gas (or via Abstract paymaster) - One signature per request; replay-protected by nonce +
validBeforeexpiry - Implementation:
packages/mpp/src/client/charge.ts+server/charge.ts
session (AbstractStreamChannel payment channels)
- Client opens a channel on-chain once (approve +
open()), depositing USDC.e into escrow - Each subsequent request exchanges a signed EIP-712 voucher with a cumulative amount
- Server accumulates the highest accepted voucher; calls
settle()orclose()to finalize - Payer escape hatch:
requestClose()→ 15-minute grace period →withdraw() - Implementation:
packages/mpp/src/client/session.ts+server/session.ts
AbstractStreamChannel.sol is a direct port of Tempo's TempoStreamChannel.sol with three changes:
ITIP20→IERC20TempoUtilities.isTIP20()→require(token != address(0))- EIP-712 domain →
"Abstract Stream Channel"
All business logic is identical to Tempo's implementation.
- Abstract uses the ZKsync VM — on-chain deployment requires
foundry-zksyncorhardhat-zksync - Standard
forge testworks withoutfoundry-zksync(tests run against a fork-std EVM) - Gas sponsorship uses native ZKsync paymasters (
customData.paymasterParams) — no separate fee-payer service needed - Chain IDs:
11124(testnet),2741(mainnet) - Token: USDC.e (6 decimals); constants in
packages/mpp/src/constants.ts
packages/mpp exports three entry points: @abstract-foundation/mpp, @abstract-foundation/mpp/client, @abstract-foundation/mpp/server (see package.json exports map).
Examples use path mappings in tsconfig.json to resolve these from local source during development — no need to build the package first when working in examples.
- Charge (ERC-3009): domain
{name: 'USD Coin', version: '2', chainId, verifyingContract: tokenAddr} - Session vouchers: domain
{name: 'Abstract Stream Channel', version: '1', chainId, verifyingContract: escrowAddr}
- TypeScript: ESM (
"type": "module"), ES2023 target, NodeNext resolution, strict mode. Explicit.jsextensions on imports. - Solidity: Solc 0.8.26, 200 optimizer runs. Dependencies via Soldeer (forge-std, solady).
- Formatting: Biome with recommended rules, single quotes, space indentation.
.solfiles excluded from linting. - Foundry tests:
setUp()+test_*naming. Payer key0xA11CEwith helper functions_openChannel(),_signVoucher().
| Testnet (11124) | Mainnet (2741) | |
|---|---|---|
| USDC.e | 0xbd28Bd5A3Ef540d1582828CE2A1a657353008C61 |
0x84A71ccD554Cc1b02749b35d22F684CC8ec987e1 |
| AbstractStreamChannel | 0x29635C384f451a72ED2e2a312BCeb8b0bDC0923c |
0x29635C384f451a72ED2e2a312BCeb8b0bDC0923c |
| RPC | https://api.testnet.abs.xyz |
https://api.mainnet.abs.xyz |