Split price quote from swap quote#505
Draft
its-everdred wants to merge 2 commits into
Draft
Conversation
✅ Deploy Preview for actions-ui ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #435
Problem
actions.swap.getQuote(...)(no wallet bound) returned aSwapQuotewhoserecipient: Addresswas the Universal Routermsg.sendersentinel(
0x0000000000000000000000000000000000000001) when no recipient was supplied.The type said "ready to execute" while the value was un-executable — a footgun
for any consumer reading
quote.recipientfor display, accounting, or analytics.Change (Option B — split the type)
PriceQuotetype: pricing, amounts, route, metadata only — norecipient, noexecution. Structurally un-executable.SwapQuotenowextends PriceQuoteand addsexecution,recipient,approvalMode.actions.swap.getQuote/getQuotesreturnPriceQuote(stripped at thenamespace boundary via
toPriceQuote).wallet.swap.getQuote/getQuotesstill return the full
SwapQuote;wallet.swap.executeis unchanged.BaseSwapNamespace.getQuote/getQuotesbecameprotected resolveQuote/ resolveQuotes(a covariant override can't widen the return type), with eachnamespace exposing its own public method.
actions swap quote(s)commands, demobackend
getQuote, demo frontendEarnOperations/useSwap/SwapAction/actionsApi.Providers are untouched — the sentinel remains a valid internal Universal
Router encoding detail; it's simply never exposed.
Why B
The demo's
executeSwapre-quotes from raw params viawallet.swap.executeand never executes an actions-level quote, so the
execution/recipienton aprice quote were already dead weight (and un-executable post-#434). Dropping
them breaks no execution path and gives price-display consumers a smaller,
honest surface.
Note: passing a
PriceQuotetoexecuteis structurally accepted as rawparams, but it carries
quotedAt, so it routes to the pre-built-quote path andthrows on the missing
recipient— a fail-loud runtime guard (regression-tested).Testing
actions.swap.getQuotestripsrecipient/execution/approvalMode(the leak fix);
executerejects a price-only quote.actions swap quote(live, base-sepolia) JSON outputcontains no
recipient/execution/sentinel; human output renders cleanly.pnpm typecheck && pnpm lint && pnpm testclean (zero new warnings).minor; breaking type change documented).Plan:
docs/plans/2026-06-16-001-refactor-split-price-quote-from-swap-quote-plan.md.