Engineering case study · Vinay Nair
Making a payment useful to an application.
I built Lycoris to explore what it takes for a person or an AI agent to buy a paid API response with USDC: permission, confirmation, delivery, and evidence.
A deliberately small product
Both paths buy Melbourne’s next 1 PM forecast for 0.1 test USDC. Weather makes the delivery visible; it stands in for any read-only paid API. The playground’s default rail is a sponsored smart account, so the first click needs no wallet. The other rail is a Coinbase Wallet or injected EOA paying the same merchant.
Settle Kit is the reusable TypeScript SDK; Lycoris is its host application. The live demo runs on Base Sepolia. It is an independent engineering project with no claim of production payment volume.
What I built
I built the checkout state machine, React integration and replaceable UI, agent and paid-route adapters, facilitator policy checks, sponsored checkout, decision records, and this demo. The packages separate wallet access, payment state, rendering, and agent tooling so a host can adopt the part it needs.
Person: React checkout → sponsored 4337 smart account or injected EOA → USDC transfer → receipt → report.
Agent: paid API request → HTTP 402 → signed retry → facilitator verification and settlement → report and decision evidence.
Coinbase CDP supplies wallet, bundler, and paymaster services; viem supplies chain and account primitives; x402 supplies the payment protocol; Eve runs the agent; Neon and Drizzle store records; Open-Meteo supplies the forecast. My work connects those building blocks and defines the application’s behavior around them.
Three decisions that shaped it
1. An uncertain payment stays pending
A timeout cannot tell a buyer whether money moved. Once the SDK has a submitted hash, it retains that payment and offers another receipt lookup. It refuses a new payment or reset while settlement is unresolved. The core session is in memory; the sponsored host separately persists purchase IDs and hashes for recovery.
Read the payment safety tests ↗2. Confirm the operation that actually paid
A smart-account operation can revert inside a successful bundle transaction. The demo confirms the operation’s own success, then the report endpoint independently checks its sender and the USDC transfer’s token, merchant, amount, and age. A unique operation claim prevents reusing one payment for another purchase.
Read the report verification ↗3. Payment authority belongs to the host
The agent can request a report, but its authenticated session determines the wallet and allowed resource. A signed mandate is the grant: payer, merchant, per-payment ceiling, and expiry. The facilitator enforces that grant, plus identity and balance, when it verifies and settles. Identity proves a registry binding, not KYC.
Read the agent payment tool ↗How I check the work
Bun tests exercise payment states, refusal paths, intent validation, sponsorship policy, and receipt verification. CI also packs the SDK and installs it in a separate Next.js consumer. Browser fixtures use mocked payment services; live testnet runs provide separate integration evidence. The decision feed lets a reviewer inspect recorded attempts.
Where the demo ends
One testnet confirmation is the demo’s release threshold. Production would need durable reconciliation, reorg and replacement handling, stronger abuse controls, operational monitoring, and a funding policy. The mandate ceiling applies per payment; it is not an aggregate spending budget. The feed’s viewer roles demonstrate disclosure shapes, not authenticated access control.
The paid handler runs after verification but before settlement, so it must remain read-only or independently idempotent. The SDK is experimental, not published to npm, and carries no granted open-source license. Those limits are part of the design scope.