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/capabilities and GET /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.