A layered payment system
Each layer has a single responsibility and is testable in isolation. Network access is confined to the server or the wallet client; the domain logic is pure.
Layer map
Defines the payment intent, validates it, and holds the single canonical payment state shared by every surface.
A deterministic offline parser (the authority), a state machine derived only from the structured draft, a one-question-at-a-time clarifier, an optional gap-filling LLM, and a handoff to the composer.
Reads the connected account and its real, on-chain-confirmed balances plus discovered holdings.
Behind getRoutingProvider: a demo provider and the live Uniswap V3 provider share one interface. The UI never branches on the provider beyond the demo/live label.
Turns a quote into explicit steps that carry real on-chain bounds and the correct router selectors.
Submits the plan through the user's wallet and tracks per-step results.
Proves the recipient's on-chain transfer from the confirmed receipt against the enforced minimum.
The only path to a signature; re-validates everything from fresh data immediately before signing.
Configuration-driven, never hardcoded
Tokens, chains and Uniswap deployments all come from configuration — lib/config/tokens.ts, lib/config/chains.ts and lib/providers/constants.ts. No component or route hardcodes a token symbol, so a token that is not shipped in source can still flow through exactly like a seed token.
Server and client boundaries
- Server: RPC reads, market pricing, provider probes, token discovery and metadata reads. Secrets stay server-side.
- Client: the composer, the review sheet, the signing guard and the wallet client. The client never holds a key or a provider secret.
- Shared, pure: intent math, freshness, source-selection rules, the plan builder, the pricing state machine and the risk classifier are pure so the same rules run in the browser, on the server and in tests.
Routing engine
The live routing engine discovers Uniswap V3 pools across all fee tiers on Monad and supports both exact-output and exact-input modes. Notable properties the implementation enforces:
- every fee tier is quoted — a token can have a low-fee pool that reverts while a higher-fee pool holds the real liquidity;
- graph reuse is keyed on probed basis tokens, so a freshly discovered token is genuinely probed rather than assumed;
- the native MON is a basis token (pooled as WMON) and is the usual intermediate for multi-hop routes;
- the reported rate is a human rate, decimal-adjusted, never raw base units;
- an unavailable route fails honestly with
route_unavailablerather than a fabricated quote.
Execution protection, in code
- every swap step carries a real on-chain
amountOutMinimum/amountInMaximum; - the Monad SwapRouter02 has no
deadlineparameter, and the implementation does not add one; - a route above the price-impact ceiling is blocked before signing;
- quote freshness is enforced off-chain, and the guard refuses a stale quote and rebuilds the calldata.
Testing
vitest. Pure domain logic (math, validation, path, pricing, token state/risk, source selection, plan economics, diagnostics, freshness) is unit-tested. Component flows (the composer and review) are tested with @testing-library/react. A small set of live-network tests are opt-in behind environment flags, because they require real Monad access.