Wire the Buy direction to submit: AmmUiBackend gains a swapExactOutput slot
(guarded like swapExactInput), SwapCard.executeSwap branches on direction —
sell -> swapExactInput(minReceivedRaw), buy -> swapExactOutput(maxInRaw) — and
canSubmit/submitButtonText/buildSnapshot handle both. The confirmation dialog
switches wording by mode ("You pay at most" / "You receive exactly" for exact
output). The Buy field is now digitsOnly since its value is submitted as a raw
base-units integer.
With both directions priced and oriented by the module, the client no longer
needs any pool math. Remove the reserve-orientation chain (sellIsPoolA,
buy/sellReserveNum, poolReserveA/B, poolDefAHex) — resolvePool now reports only
existence and fee — and the now-dead helpers (formatBaseUnits/formatAmountValue,
DummySwapState.amountInFor/minReceived/priceImpactPercent/maxSent). The
impossible-swap guard moves from a client reserve compare to the module's
output_exceeds_liquidity error, surfaced as "Insufficient liquidity".
Wire the Sell direction of the swap card to the module's server-side quote
instead of the client-side DummySwapState estimate. AmmUiBackend gains a
swapExactInQuote(tokenIn, tokenOut, amountInDecimal, slippageBps) slot that
forwards to amm_module and returns { expectedOutRaw, minReceivedRaw,
priceImpactBps } (read-only, no wallet guard).
SwapCard debounces a swapExactInQuote call as the user types a Sell amount and
sources the expected output, min received, and price impact from it. The exact
figures shown (buy field, confirmation snapshot) and the submitted min_out come
straight from the quote's raw integer strings, so the preview can't drift from
execution and the client no longer orients reserves (fixes the #236 defAHex
bug) or recomputes min_out in double/BigInt. A retyped amount invalidates the
quote immediately and blocks submit until the re-quote lands.
The Buy direction is unchanged — still a local DummySwapState preview, pending
the exact-output wiring. resolvePool stays as the source of pool existence, the
fee row, and the Buy-side reserves.