What
Collapses the admin On/Off Ramp section (four pages: stuck orders, spreads, revenue, treasury) into one Convert page at /ramp. Convert is now only USD ⇄ USDC, so the operator needs a much smaller surface. Admin-only change, no backend or migration.
Sections, top to bottom:
-
Fees: two percent inputs, Deposit USD→USDC (
USD/USDC) and Withdraw USDC→USD (USDC/USD). Save PATCHes the corridor's band-less, tier-less rule, or POSTs one at priority 1 above the seeded catch-all (priority 0). Other rules that can affect the fee are listed read-only. When a higher-priority broader rule wins, the page shows "Overridden: users pay X%" and blocks Save, so it never creates a rule that cannot apply. Needsramp:pricing; without it the page shows a read-only note and does not call the spreads endpoint. -
Revenue: fees, volume, realised bps and orders for a date range (default 30 days). Legacy
CARD_USDrows are excluded. - Status: ON_RAMP corridor state, Fireblocks USDC balance, and open rebalances with the providerRef confirm.
- Stuck orders: shown only when PARTIALLY_SETTLED, SETTLING or FAILED has orders, or when loading fails. Complete and Reverse are unchanged.
Also:
- Deletes the unrouted wireframe (
ramp-page.tsx,sample-data.ts), the netting table and its store, and the dead locale keys. - Reversal block codes now match the backend:
RAMP_REVERSAL_INSUFFICIENT_WALLET,_INSUFFICIENT_CRYPTOand_LEGACY_CARD_ORDER. The balance refusals can be retried. -
RAILSnow matches the backend rail enum.
Not in scope
The USDC/USD rate and the order limits are still env-only (RAMP_*); the page does not edit them.
Verification
-
pnpm test: 48 suites, 518 tests.pnpm type-checkis clean,pnpm lint:checkhas 0 errors, and en/vi keys match. - Checked by hand against a local backend: the page renders, a fee save creates the priority-1 rule, and a second save PATCHes it.
- Opus review gate passed in 2 rounds. Five NITs remain (rare edge cases and test tightness).