-
-
Notifications
You must be signed in to change notification settings - Fork 270
feat: Withdrawal to any token (Predict) #7783
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| .filter((singleRequest) => singleRequest.targetAmountMinimum !== '0') | ||
| // Ignore gas fee token requests (which have both target=0 and source=0) | ||
| // but keep post-quote requests (which have target=0 but source>0) | ||
| .filter( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new logic keeps requests where either target > 0 (normal deposit flows) or source > 0 (withdrawal/post-quote flows). Only requests with both at zero (gas fee token placeholders) get filtered out.
| * @param messenger - Controller messenger. | ||
| * @returns Submit context with normalized params and metadata. | ||
| */ | ||
| export function getSubmitContext( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've abstracted shared code between submitPostQuoteTransactions and submitTransactions functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
| ### Added | ||
|
|
||
| - Add `isPostQuote` field to `TransactionData` type for withdrawal flows ([#7773](https://github.com/MetaMask/core/pull/7773)) | ||
| - Add `setIsPostQuote` action type ([#7773](https://github.com/MetaMask/core/pull/7773)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can nest changes here, so could we have a high level summary like Support quote execution after transaction in Relay strategy with details in nested lines?
| }); | ||
| } | ||
|
|
||
| setIsPostQuote(transactionId: string, isPostQuote: boolean): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than adding more individual setters and actions, could we define a new TransactionConfig type and a single setTransactionConfig that uses a callback to allow custom changes to the config without defining it each time?
| return { decimals: Number(token.decimals), symbol: token.symbol }; | ||
| } | ||
|
|
||
| if (!token && !isNative) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we remove the changes to this file as they seem identical?
| .map((token) => ({ | ||
| sourceAmountHuman: token.amountHuman, | ||
| sourceAmountRaw: token.amountRaw, | ||
| targetTokenAddress: token.address, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be the payment token?
| }): QuoteRequest[] { | ||
| // For withdrawals, the required token (e.g., Polygon USDC.e) becomes the SOURCE | ||
| // and the destinationToken (paymentToken) becomes the TARGET/destination | ||
| const sourceToken = tokens.find((token) => !token.skipIfBalance); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we've already done this to generate the source amounts, should we instead just look for a source amount with targetTokenAddress matching the payment token / destinationToken?
| ): Promise<{ transactionHash?: Hex }> { | ||
| log('Executing single quote', quote); | ||
|
|
||
| const isPostQuote = transaction.metamaskPay?.isPostQuote; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to determine this via the strategy request directly, rather than the transaction where the properties are just used for transaction details.
| if (isPostQuote) { | ||
| await submitPostQuoteTransactions(quote, transaction, messenger); | ||
| } else { | ||
| await submitTransactions(quote, transaction.id, messenger); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than branching here, would it not be much simpler to keep the original flow and code, but just add a tiny branch in submitTransactions to include the original transaction data as the first entry in normalizedParams if isPostQuote is true?
|
|
||
| // Add original transaction (e.g., Safe execTransaction call) | ||
| // Note: We use txParams (the outer call) not nestedTransactions (internal calls) | ||
| // because nestedTransactions are executed BY the Safe, not by the user's EOA |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only use nestedTransactions for batch transactions to user EOAs, meaning it should be empty anyway?
| log('Fetched relay quote', quote); | ||
|
|
||
| return normalizeQuote(quote, request, fullRequest); | ||
| return await normalizeQuote(quote, request, fullRequest); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't have to be this PR, but since we're adding a transaction to the Relay deposit transaction, we'll need to update the source gas fees in the normalized quote to include the gas fee of the original transaction.
Technically, we may also need to move the fee to the target property, and set source to zero.
Depends if we consider the fees relative to the transaction or the quote 😅
|
|
||
| const body: RelayQuoteRequest = { | ||
| amount: isMaxAmount ? sourceTokenAmount : targetAmountMinimum, | ||
| amount: useExactInput ? sourceTokenAmount : targetAmountMinimum, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we also need to update processTransactions to skip changing the quote at all, since we never want to also execute the same transaction data on the target chain of the quote.
I assume it is skipping now since it's just a token transfer for the Predict withdraw.
Signed-off-by: dan437 <80175477+dan437@users.noreply.github.com>
5b8062c to
8b20558
Compare
Explanation
Adds support for "post-quote" withdrawal flows, enabling users to withdraw funds to any token/chain (e.g., Predict withdrawals).
Changes:
References
Checklist
Note
Medium Risk
Medium risk because it changes quote construction and Relay submission behavior, including creating EIP-7702 atomic batches that affect transaction execution ordering and required-transaction tracking.
Overview
Adds post-quote (withdrawal-first) flow support by introducing an optional
isPostQuoteflag onTransactionDataandMetamaskPayMetadata, plus a newTransactionPayController:setIsPostQuoteaction.Updates quote generation to invert source/target semantics when
isPostQuoteis true (target minimum forced to0/ EXACT_INPUT), skip same-token/same-chain withdrawals, and compute source amounts directly from required tokens (excludingskipIfBalance).Updates the Relay strategy to treat
targetAmountMinimum=0as a valid post-quote request (only filtering out target=0+source=0 gas-fee-token requests) and to submit post-quote withdrawals as an atomic batch that combines the original transaction with Relay deposit transactions; refactors Relay submit logic into reusable helpers and tightens required-token detection for nested transfers.Written by Cursor Bugbot for commit 8b20558. This will update automatically on new commits. Configure here.