Developers
Working on Intent Pay
How the repository is organised, how to run it, and how the pieces fit together.
Commands
npm install # install dependencies npm run dev # dev server on http://localhost:3000 npm test # vitest (unit + component tests) npm run build # production build + typecheck npx tsc --noEmit --noUnusedLocals --noUnusedParameters # strict typecheck
Build vs dev
next dev and next build share the .next/ directory. Running a build while the dev server is live can break its module cache; restart the dev server (or remove .next) afterwards.Repository layout
lib/domain/*— pure domain logic: intent, validation, canonical state, readiness, source selection, freshness, protection, token state and risk, partial-balance split, diagnostics.lib/nlp/*— the natural-language intent engine (parser, schema, engine, question, handoff, optional LLM).lib/providers/*— the routing provider interface and the live Uniswap V3 engine.lib/server/*— server-only concerns: quote orchestration, balances/discovery, pricing, diagnostics, optimizer.lib/execution/*— plan construction, ABIs, execution, the signing guard and delivery verification.lib/hooks/*— React hooks for wallet, payment flow, optimizer and capabilities.app/api/*— HTTP routes (quote, balances, tokens, optimize, nlp, partial, capabilities, diagnostics, health).components/*— the UI: composer, review sheet, wallet bar, landing, docs.
HTTP routes
POST /api/quote— price a payment without a wallet (fastest way to exercise routing).GET /api/balances— real, on-chain-confirmed balances for an account, with source status.GET /api/tokens— token catalog / search / single-address resolution with state and routability.POST /api/optimize— rank the wallet's assets for the current intent.POST /api/nlp— parse a natural-language payment request.POST /api/partial— build a partial-balance split plan.GET /api/capabilitiesandGET /api/diagnostics— provider configuration and reachability.
Example — exercise routing directly:
curl -s -X POST http://localhost:3000/api/quote \
-H 'Content-Type: application/json' \
-d '{
"recipient": "0x7A91c4b8E2d9F04aB3c6E81d5F72a0C9e4Bd92F4",
"receiveToken": "USDC", "receiveAmount": "5",
"amountMode": "recipient_receives",
"payToken": "USDT", "mode": "live", "network": "mainnet"
}'Configuration
Everything token, chain and provider related is configuration-driven. .env.example documents every key; every value is optional and the app degrades honestly when a provider is absent. Gas is always paid in MON by the standard EOA path — there is no paymaster or account-abstraction configuration.
MONAD_RPC_URL/NEXT_PUBLIC_MONAD_RPC_URL— RPC transport.ALCHEMY_API_KEY— Alchemy RPC and the Alchemy Prices source (not gas abstraction).ZERION_API_KEY— wallet asset discovery and USD valuation.NEXT_PUBLIC_SLIPPAGE_BPS/NEXT_PUBLIC_MAX_PRICE_IMPACT_BPS— execution-protection thresholds.INTENT_LLM_*— optional gap-filling for the natural-language parser.
Testing conventions
- Prefer testing real code paths; avoid mocks.
- Tests that touch the token registry or a cached provider must use unique addresses/keys per test, or they leak state between cases.
- Live-network tests are gated behind environment flags and mirror production setup in
beforeAll.
Design principles
- The provider is behind an interface; the UI never branches on it beyond the demo/live label.
- Never hardcode a token symbol in a component or route.
- Live mode must fail honestly (
route_unavailable,unsupported_token) rather than fabricate a quote. - Demo mode is always labelled and never produces a transaction hash.
- One canonical intent; no second payment store.