@metamask-previews/transaction-pay-controller 30.4.2-preview-77efa7863 → 30.4.3-preview-6ebaf4e52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"quote-recipient.js","sourceRoot":"","sources":["../../src/utils/quote-recipient.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,+BAA+B,EAAE,MAAM,kCAAkC,CAAC;AAEnF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAC1C,SAAS,EACT,OAAO,EACP,WAAW,GAKZ;IACC,MAAM,gBAAgB,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAW,CAAC;IAE1D,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACpD,0EAA0E;QAC1E,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,+BAA+B,CAAC;YAC1D,SAAS;YACT,WAAW;SACZ,CAAC,CAAC;QAEH,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC7B,wEAAwE;QACxE,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,4EAA4E;QAC5E,OAAO,OAAO,CAAC,SAAS,CAAC;IAC3B,CAAC;IAED,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,4EAA4E;QAC5E,oDAAoD;QACpD,OAAO,OAAO,CAAC,IAAI,CAAC;IACtB,CAAC;IAED,8EAA8E;IAC9E,OAAO,gBAAgB,CAAC;AAC1B,CAAC","sourcesContent":["import type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport type {\n QuoteRequest,\n TransactionPayControllerMessenger,\n} from '../types.js';\nimport { getPostQuotePaymentOverrideData } from './post-quote-payment-override.js';\n\n/**\n * Resolve the quote recipient used by both Relay and Server.\n *\n * Non-atomic execution must be funded on its execution account. Ordinary\n * post-quote withdrawals pay the selected receiving account in `request.from`.\n * Deposits default to the original transaction's execution account.\n *\n * @param options - Recipient resolution options.\n * @param options.messenger - Controller messenger.\n * @param options.request - Quote request.\n * @param options.transaction - Original transaction metadata.\n * @returns The recipient to use for the quote body.\n */\nexport async function resolveQuoteRecipient({\n messenger,\n request,\n transaction,\n}: {\n messenger: TransactionPayControllerMessenger;\n request: QuoteRequest;\n transaction: TransactionMeta;\n}): Promise<Hex> {\n const executionAccount = transaction.txParams.from as Hex;\n\n if (request.atomic === false && request.isPostQuote) {\n // The client identifies the account executing target-side override calls.\n const { recipient } = await getPostQuotePaymentOverrideData({\n messenger,\n transaction,\n });\n\n return recipient;\n }\n\n if (request.atomic === false) {\n // Fund the original execution account before submitting its second leg.\n return executionAccount;\n }\n\n if (request.recipient) {\n // Preserve an explicit payout recipient once second-leg funding is handled.\n return request.recipient;\n }\n\n if (request.isPostQuote) {\n // Ordinary withdrawals pay the selected receiving account, which can differ\n // from the account executing the source withdrawal.\n return request.from;\n }\n\n // Deposits default to the execution account, which can differ from the payer.\n return executionAccount;\n}\n"]}
1
+ {"version":3,"file":"quote-recipient.js","sourceRoot":"","sources":["../../src/utils/quote-recipient.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,+BAA+B,EAAE,MAAM,kCAAkC,CAAC;AAEnF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAC1C,SAAS,EACT,OAAO,EACP,WAAW,GAKZ;IACC,MAAM,gBAAgB,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAW,CAAC;IAE1D,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACpD,0EAA0E;QAC1E,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,+BAA+B,CAAC;YAC1D,SAAS;YACT,WAAW;SACZ,CAAC,CAAC;QAEH,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC7B,wEAAwE;QACxE,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,4EAA4E;QAC5E,OAAO,OAAO,CAAC,SAAS,CAAC;IAC3B,CAAC;IAED,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,4EAA4E;QAC5E,oDAAoD;QACpD,OAAO,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IACjD,CAAC;IAED,8EAA8E;IAC9E,OAAO,gBAAgB,CAAC;AAC1B,CAAC","sourcesContent":["import type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport type {\n QuoteRequest,\n TransactionPayControllerMessenger,\n} from '../types.js';\nimport { getPostQuotePaymentOverrideData } from './post-quote-payment-override.js';\n\n/**\n * Resolve the quote recipient used by both Relay and Server.\n *\n * Non-atomic execution must be funded on its execution account. Ordinary\n * post-quote withdrawals pay the selected receiving account in\n * `request.accountOverride`, falling back to `request.from`.\n * Deposits default to the original transaction's execution account.\n *\n * @param options - Recipient resolution options.\n * @param options.messenger - Controller messenger.\n * @param options.request - Quote request.\n * @param options.transaction - Original transaction metadata.\n * @returns The recipient to use for the quote body.\n */\nexport async function resolveQuoteRecipient({\n messenger,\n request,\n transaction,\n}: {\n messenger: TransactionPayControllerMessenger;\n request: QuoteRequest;\n transaction: TransactionMeta;\n}): Promise<Hex> {\n const executionAccount = transaction.txParams.from as Hex;\n\n if (request.atomic === false && request.isPostQuote) {\n // The client identifies the account executing target-side override calls.\n const { recipient } = await getPostQuotePaymentOverrideData({\n messenger,\n transaction,\n });\n\n return recipient;\n }\n\n if (request.atomic === false) {\n // Fund the original execution account before submitting its second leg.\n return executionAccount;\n }\n\n if (request.recipient) {\n // Preserve an explicit payout recipient once second-leg funding is handled.\n return request.recipient;\n }\n\n if (request.isPostQuote) {\n // Ordinary withdrawals pay the selected receiving account, which can differ\n // from the account executing the source withdrawal.\n return request.accountOverride ?? request.from;\n }\n\n // Deposits default to the execution account, which can differ from the payer.\n return executionAccount;\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import type { TransactionMeta } from '@metamask/transaction-controller';
2
2
  import { TransactionPayStrategy } from '../constants.js';
3
- import type { TransactionData, TransactionPayControllerMessenger, UpdateTransactionDataCallback } from '../types.js';
3
+ import type { TransactionData, GetBalanceCallback, TransactionPayControllerMessenger, UpdateTransactionDataCallback } from '../types.js';
4
4
  export type UpdateQuotesRequest = {
5
5
  getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[];
6
6
  messenger: TransactionPayControllerMessenger;
@@ -21,11 +21,12 @@ export type UpdateQuotesRequest = {
21
21
  */
22
22
  export declare function updateQuotes(request: UpdateQuotesRequest): Promise<boolean>;
23
23
  /**
24
- * Refresh quotes for all transactions if expired.
24
+ * Refresh source amounts and quotes for all transactions if expired.
25
25
  *
26
26
  * @param messenger - Messenger instance.
27
27
  * @param updateTransactionData - Callback to update transaction data.
28
28
  * @param getStrategies - Callback to get ordered strategy names for a transaction.
29
+ * @param getBalance - Optional callback to override the source balance used for max-amount calculation.
29
30
  */
30
- export declare function refreshQuotes(messenger: TransactionPayControllerMessenger, updateTransactionData: UpdateTransactionDataCallback, getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[]): Promise<void>;
31
+ export declare function refreshQuotes(messenger: TransactionPayControllerMessenger, updateTransactionData: UpdateTransactionDataCallback, getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[], getBalance?: GetBalanceCallback): Promise<void>;
31
32
  //# sourceMappingURL=quotes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"quotes.d.ts","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAIxE,OAAO,EAAmB,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAE1E,OAAO,KAAK,EAGV,eAAe,EACf,iCAAiC,EAMjC,6BAA6B,EAC9B,MAAM,aAAa,CAAC;AAwBrB,MAAM,MAAM,mBAAmB,GAAG;IAChC,aAAa,EAAE,CAAC,WAAW,EAAE,eAAe,KAAK,sBAAsB,EAAE,CAAC;IAC1E,SAAS,EAAE,iCAAiC,CAAC;IAC7C,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,6BAA6B,CAAC;CACtD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CA6JlB;AAgFD;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,iCAAiC,EAC5C,qBAAqB,EAAE,6BAA6B,EACpD,aAAa,EAAE,CAAC,WAAW,EAAE,eAAe,KAAK,sBAAsB,EAAE,GACxE,OAAO,CAAC,IAAI,CAAC,CA+Cf"}
1
+ {"version":3,"file":"quotes.d.ts","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAIxE,OAAO,EAAmB,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAE1E,OAAO,KAAK,EAGV,eAAe,EACf,kBAAkB,EAClB,iCAAiC,EAMjC,6BAA6B,EAC9B,MAAM,aAAa,CAAC;AAyBrB,MAAM,MAAM,mBAAmB,GAAG;IAChC,aAAa,EAAE,CAAC,WAAW,EAAE,eAAe,KAAK,sBAAsB,EAAE,CAAC;IAC1E,SAAS,EAAE,iCAAiC,CAAC;IAC7C,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,6BAA6B,CAAC;CACtD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CA+JlB;AAqGD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,iCAAiC,EAC5C,qBAAqB,EAAE,6BAA6B,EACpD,aAAa,EAAE,CAAC,WAAW,EAAE,eAAe,KAAK,sBAAsB,EAAE,EACzE,UAAU,CAAC,EAAE,kBAAkB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA+Df"}
@@ -4,6 +4,7 @@ import { TransactionPayStrategy } from '../constants.js';
4
4
  import { projectLogger } from '../logger.js';
5
5
  import { accountSupports7702 } from './7702.js';
6
6
  import { buildNoOpQuote } from './no-op-quote.js';
7
+ import { updateSourceAmounts } from './source-amounts.js';
7
8
  import { checkStrategyQuoteSupport, checkStrategySupport, getStrategiesByName, getStrategyByName, } from './strategy.js';
8
9
  import { computeTokenAmounts, getLiveTokenBalance, getTokenFiatRate, } from './token.js';
9
10
  import { calculateTotals } from './totals.js';
@@ -34,7 +35,7 @@ export async function updateQuotes(request) {
34
35
  }
35
36
  log('Updating quotes', { transactionId });
36
37
  const { accountOverride, atomic, fiatPayment, isHyperliquidSource, isMaxAmount, isPolymarketDepositWallet, isPostQuote, isQuoteRequired, paymentOverride, paymentToken: originalPaymentToken, refundTo, sourceAmounts, tokens, } = transactionData;
37
- const from = accountOverride ?? transaction.txParams.from;
38
+ const from = getFrom(transaction, transactionData);
38
39
  const controller = abortPreviousAndCreateController(transactionId);
39
40
  const { signal } = controller;
40
41
  updateTransactionData(transactionId, (data) => {
@@ -43,7 +44,8 @@ export async function updateQuotes(request) {
43
44
  });
44
45
  try {
45
46
  const paymentToken = await refreshPaymentTokenBalance({
46
- from,
47
+ // Post-quote payment tokens are received by `accountOverride`.
48
+ from: accountOverride ?? transaction.txParams.from,
47
49
  messenger,
48
50
  paymentToken: originalPaymentToken,
49
51
  signal,
@@ -61,6 +63,7 @@ export async function updateQuotes(request) {
61
63
  // loaded.
62
64
  const latestSourceAmounts = getSourceAmounts(messenger, transactionId) ?? sourceAmounts;
63
65
  const requests = buildQuoteRequests({
66
+ accountOverride,
64
67
  atomic,
65
68
  from,
66
69
  isHyperliquidSource,
@@ -128,6 +131,21 @@ export async function updateQuotes(request) {
128
131
  }
129
132
  return true;
130
133
  }
134
+ /**
135
+ * Get the account that sends quotes for a transaction.
136
+ *
137
+ * @param transaction - Transaction metadata.
138
+ * @param transactionData - Transaction pay data.
139
+ * @returns The quote sender address.
140
+ */
141
+ function getFrom(transaction, transactionData) {
142
+ const transactionFrom = transaction.txParams.from;
143
+ // Post-quote output goes to `accountOverride`, so the funds holder sends.
144
+ if (transactionData.isPostQuote) {
145
+ return transactionFrom;
146
+ }
147
+ return transactionData.accountOverride ?? transactionFrom;
148
+ }
131
149
  /**
132
150
  * Sync batch transactions to the transaction meta.
133
151
  *
@@ -180,13 +198,14 @@ function syncTransaction({ batchTransactions, hasQuotes, isPostQuote, messenger,
180
198
  });
181
199
  }
182
200
  /**
183
- * Refresh quotes for all transactions if expired.
201
+ * Refresh source amounts and quotes for all transactions if expired.
184
202
  *
185
203
  * @param messenger - Messenger instance.
186
204
  * @param updateTransactionData - Callback to update transaction data.
187
205
  * @param getStrategies - Callback to get ordered strategy names for a transaction.
206
+ * @param getBalance - Optional callback to override the source balance used for max-amount calculation.
188
207
  */
189
- export async function refreshQuotes(messenger, updateTransactionData, getStrategies) {
208
+ export async function refreshQuotes(messenger, updateTransactionData, getStrategies, getBalance) {
190
209
  const state = messenger.call('TransactionPayController:getState');
191
210
  const transactionIds = Object.keys(state.transactionData);
192
211
  for (const transactionId of transactionIds) {
@@ -205,15 +224,22 @@ export async function refreshQuotes(messenger, updateTransactionData, getStrateg
205
224
  const refreshInterval = (await strategy.getRefreshInterval?.({
206
225
  chainId: quotes[0].request.sourceChainId,
207
226
  messenger,
227
+ transactionId,
208
228
  })) ?? DEFAULT_REFRESH_INTERVAL;
209
229
  const isExpired = Date.now() - (quotesLastUpdated ?? 0) > refreshInterval;
210
230
  if (!isExpired) {
211
231
  continue;
212
232
  }
233
+ updateTransactionData(transactionId, (data) => updateSourceAmounts(transactionId,
234
+ /* oxlint-disable typescript/no-unnecessary-type-assertion */
235
+ data,
236
+ /* oxlint-enable typescript/no-unnecessary-type-assertion */
237
+ messenger, getBalance));
238
+ const latestTransactionData = messenger.call('TransactionPayController:getState').transactionData[transactionId];
213
239
  const isUpdated = await updateQuotes({
214
240
  getStrategies,
215
241
  messenger,
216
- transactionData,
242
+ transactionData: latestTransactionData,
217
243
  transactionId,
218
244
  updateTransactionData,
219
245
  });
@@ -251,6 +277,7 @@ function getSourceAmounts(messenger, transactionId) {
251
277
  * Build quote requests required to retrieve quotes.
252
278
  *
253
279
  * @param request - Request parameters.
280
+ * @param request.accountOverride - Optional account receiving post-quote output.
254
281
  * @param request.atomic - Whether the target transaction is executed atomically with the Relay quote.
255
282
  * @param request.from - Address from which the transaction is sent.
256
283
  * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.
@@ -265,12 +292,13 @@ function getSourceAmounts(messenger, transactionId) {
265
292
  * @param request.transactionId - ID of the transaction.
266
293
  * @returns Array of quote requests.
267
294
  */
268
- function buildQuoteRequests({ atomic, from, isHyperliquidSource, isMaxAmount, isPolymarketDepositWallet, isPostQuote, paymentOverride, paymentToken, refundTo, sourceAmounts, tokens, transactionId, }) {
295
+ function buildQuoteRequests({ accountOverride, atomic, from, isHyperliquidSource, isMaxAmount, isPolymarketDepositWallet, isPostQuote, paymentOverride, paymentToken, refundTo, sourceAmounts, tokens, transactionId, }) {
269
296
  if (!paymentToken) {
270
297
  return [];
271
298
  }
272
299
  if (isPostQuote) {
273
300
  return buildPostQuoteRequests({
301
+ accountOverride,
274
302
  atomic,
275
303
  destinationToken: paymentToken,
276
304
  from,
@@ -312,6 +340,7 @@ function buildQuoteRequests({ atomic, from, isHyperliquidSource, isMaxAmount, is
312
340
  * and the target is the user's selected destination token (paymentToken).
313
341
  *
314
342
  * @param request - Request parameters.
343
+ * @param request.accountOverride - Optional account receiving the output.
315
344
  * @param request.atomic - Whether the target transaction is executed atomically with the Relay quote.
316
345
  * @param request.destinationToken - Destination token (paymentToken in post-quote mode).
317
346
  * @param request.from - Address from which the transaction is sent.
@@ -324,7 +353,7 @@ function buildQuoteRequests({ atomic, from, isHyperliquidSource, isMaxAmount, is
324
353
  * @param request.transactionId - ID of the transaction.
325
354
  * @returns Array of quote requests for post-quote flow.
326
355
  */
327
- function buildPostQuoteRequests({ atomic, destinationToken, from, isHyperliquidSource, isMaxAmount, isPolymarketDepositWallet, paymentOverride, refundTo, sourceAmounts, transactionId, }) {
356
+ function buildPostQuoteRequests({ accountOverride, atomic, destinationToken, from, isHyperliquidSource, isMaxAmount, isPolymarketDepositWallet, paymentOverride, refundTo, sourceAmounts, transactionId, }) {
328
357
  // Find the source amount where targetTokenAddress matches the destination token
329
358
  const sourceAmount = sourceAmounts?.find((amount) => amount.targetTokenAddress.toLowerCase() ===
330
359
  destinationToken.address.toLowerCase());
@@ -338,6 +367,7 @@ function buildPostQuoteRequests({ atomic, destinationToken, from, isHyperliquidS
338
367
  return [];
339
368
  }
340
369
  const request = {
370
+ accountOverride,
341
371
  atomic,
342
372
  from,
343
373
  isHyperliquidSource,
@@ -396,7 +426,7 @@ async function refreshPaymentTokenBalance({ from, messenger, paymentToken, signa
396
426
  * Retrieve quotes for a transaction.
397
427
  *
398
428
  * @param transaction - Transaction metadata.
399
- * @param from - Resolved wallet address (`accountOverride ?? txParams.from`).
429
+ * @param from - Sending wallet address (`txParams.from` for post-quote, otherwise `accountOverride ?? txParams.from`).
400
430
  * @param requests - Quote requests.
401
431
  * @param paymentToken - Selected payment token, if any.
402
432
  * @param isQuoteRequired - Whether a quote is always required for the transaction.
@@ -1 +1 @@
1
- {"version":3,"file":"quotes.js","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { TransactionStatus } from '@metamask/transaction-controller';\nimport type { BatchTransaction } from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex, Json } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { PaymentOverride, TransactionPayStrategy } from '../constants.js';\nimport { projectLogger } from '../logger.js';\nimport type {\n QuoteRequest,\n QuoteErrorInfo,\n TransactionData,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n TransactionPayRequiredToken,\n TransactionPaySourceAmount,\n TransactionPayTotals,\n TransactionPaymentToken,\n UpdateTransactionDataCallback,\n} from '../types.js';\nimport { accountSupports7702 } from './7702.js';\nimport { buildNoOpQuote } from './no-op-quote.js';\nimport {\n checkStrategyQuoteSupport,\n checkStrategySupport,\n getStrategiesByName,\n getStrategyByName,\n} from './strategy.js';\nimport {\n computeTokenAmounts,\n getLiveTokenBalance,\n getTokenFiatRate,\n} from './token.js';\nimport { calculateTotals } from './totals.js';\nimport { getTransaction, updateTransaction } from './transaction.js';\nimport { isQuoteError } from './validation.js';\n\nconst DEFAULT_REFRESH_INTERVAL = 30 * 1000; // 30 Seconds\n\nconst log = createModuleLogger(projectLogger, 'quotes');\n\nconst inFlightQuoteRequests = new Map<string, AbortController>();\n\nexport type UpdateQuotesRequest = {\n getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[];\n messenger: TransactionPayControllerMessenger;\n transactionData: TransactionData | undefined;\n transactionId: string;\n updateTransactionData: UpdateTransactionDataCallback;\n};\n\n/**\n * Update the quotes for a specific transaction.\n *\n * Calls for the same `transactionId` are serialised: a fresh call aborts any\n * previous in-flight call so a slower stale response cannot overwrite a newer\n * one in state.\n *\n * @param request - Request parameters.\n * @returns Boolean indicating if the quotes were updated. Returns `false` when\n * the call was aborted by a subsequent call for the same transaction.\n */\nexport async function updateQuotes(\n request: UpdateQuotesRequest,\n): Promise<boolean> {\n const {\n getStrategies,\n messenger,\n transactionData,\n transactionId,\n updateTransactionData,\n } = request;\n\n const transaction = getTransaction(transactionId, messenger);\n\n if (!transaction || !transactionData) {\n throw new Error('Transaction not found');\n }\n\n if (transaction?.status !== TransactionStatus.unapproved) {\n return false;\n }\n\n log('Updating quotes', { transactionId });\n\n const {\n accountOverride,\n atomic,\n fiatPayment,\n isHyperliquidSource,\n isMaxAmount,\n isPolymarketDepositWallet,\n isPostQuote,\n isQuoteRequired,\n paymentOverride,\n paymentToken: originalPaymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n } = transactionData;\n\n const from = accountOverride ?? (transaction.txParams.from as Hex);\n\n const controller = abortPreviousAndCreateController(transactionId);\n const { signal } = controller;\n\n updateTransactionData(transactionId, (data) => {\n data.isLoading = true;\n data.quoteError = undefined;\n });\n\n try {\n const paymentToken = await refreshPaymentTokenBalance({\n from,\n messenger,\n paymentToken: originalPaymentToken,\n signal,\n transactionId,\n updateTransactionData,\n });\n\n if (signal.aborted) {\n log('Quote request aborted before building requests', { transactionId });\n return false;\n }\n\n // Refreshing the balance above re-derives max source amounts, so read the\n // latest values instead of the snapshot taken before the refresh. Using\n // the snapshot quotes a max amount against a stale balance, which requests\n // a zero source amount when the token was selected before its balance\n // loaded.\n const latestSourceAmounts =\n getSourceAmounts(messenger, transactionId) ?? sourceAmounts;\n\n const requests = buildQuoteRequests({\n atomic,\n from,\n isHyperliquidSource,\n isMaxAmount: isMaxAmount ?? false,\n isPolymarketDepositWallet,\n isPostQuote,\n paymentOverride,\n paymentToken,\n refundTo,\n sourceAmounts: latestSourceAmounts,\n tokens,\n transactionId,\n });\n\n const supports7702 = accountSupports7702(messenger, from);\n\n const { batchTransactions, error, quotes } = await getQuotes(\n transaction,\n from,\n requests,\n paymentToken,\n isQuoteRequired ?? false,\n supports7702,\n getStrategies,\n messenger,\n fiatPayment?.selectedPaymentMethodId,\n signal,\n );\n\n if (signal.aborted) {\n log('Quote request aborted before persisting results', { transactionId });\n return false;\n }\n\n // No-op quotes mark direct routes. They have no fees or amounts and the\n // transaction is signed and submitted locally, so totals and transaction\n // sync must treat them as \"no quotes\".\n const executableQuotes = quotes.filter(\n (quote) => quote.strategy !== TransactionPayStrategy.None,\n );\n\n const totals = calculateTotals({\n fiatPaymentAmount: fiatPayment?.amountFiat,\n messenger,\n quotes: executableQuotes,\n tokens,\n transaction,\n });\n\n log('Calculated totals', { transactionId, totals });\n\n syncTransaction({\n batchTransactions,\n selectedFiatPayment: fiatPayment?.selectedPaymentMethodId,\n hasQuotes: executableQuotes.length > 0,\n isPostQuote,\n messenger,\n paymentToken,\n strategy: executableQuotes[0]?.strategy,\n totals,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n // oxlint-disable-next-line typescript/no-unnecessary-type-assertion\n data.quotes = quotes as never;\n data.quoteError = error;\n data.quotesLastUpdated = Date.now();\n data.totals = totals;\n });\n } catch (error) {\n if (signal.aborted) {\n log('Quote request aborted', { transactionId, reason: signal.reason });\n return false;\n }\n throw error;\n } finally {\n if (!signal.aborted) {\n updateTransactionData(transactionId, (data) => {\n data.isLoading = false;\n });\n }\n clearControllerIfCurrent(transactionId, controller);\n }\n\n return true;\n}\n\n/**\n * Sync batch transactions to the transaction meta.\n *\n * @param request - Request object.\n * @param request.batchTransactions - Batch transactions to sync.\n * @param request.hasQuotes - Whether MM Pay produced any quotes for this transaction.\n * @param request.isPostQuote - Whether this is a post-quote flow.\n * @param request.messenger - Messenger instance.\n * @param request.paymentToken - Payment token (source for standard flows, destination for post-quote).\n * @param request.selectedFiatPayment - Selected fiat payment method ID.\n * @param request.strategy - Strategy of the executable quotes.\n * @param request.totals - Calculated totals.\n * @param request.transactionId - ID of the transaction to sync.\n */\nfunction syncTransaction({\n batchTransactions,\n hasQuotes,\n isPostQuote,\n messenger,\n paymentToken,\n selectedFiatPayment,\n strategy,\n totals,\n transactionId,\n}: {\n batchTransactions: BatchTransaction[];\n selectedFiatPayment?: string;\n hasQuotes: boolean;\n isPostQuote?: boolean;\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\n strategy?: TransactionPayStrategy;\n totals: TransactionPayTotals;\n transactionId: string;\n}): void {\n if (!paymentToken && !selectedFiatPayment) {\n return;\n }\n\n updateTransaction(\n {\n transactionId,\n messenger,\n note: 'Update transaction pay data',\n },\n (tx: TransactionMeta) => {\n tx.batchTransactions = batchTransactions;\n tx.batchTransactionsOptions = {};\n\n // When MM Pay has produced quotes, it owns submission of this transaction\n // via its strategy publish hook, so the parent must be marked externally\n // signed to skip the local `KeyringController:signTransaction` call.\n // When there are no quotes (e.g. user selected the target token as the\n // payment token in a Predict flow), the transaction falls back to normal\n // local signing, so the flag is cleared to allow that.\n // If gas is sponsored, TC owns this field — it is set based on the\n // Sentinel simulation result and must not be cleared here. Same-token\n // flows (e.g. Monad mUSD withdrawal via a Money Account) produce no\n // quotes but still need external sign because the account cannot sign\n // locally.\n if (!tx.isGasFeeSponsored) {\n tx.isExternalSign = hasQuotes;\n }\n\n tx.metamaskPay = {\n bridgeFeeFiat: totals.fees.provider.usd,\n chainId: paymentToken?.chainId,\n isPostQuote,\n networkFeeFiat: totals.fees.sourceNetwork.estimate.usd,\n strategy,\n targetFiat: totals.targetAmount.usd,\n tokenAddress: paymentToken?.address,\n totalFiat: totals.total.usd,\n };\n },\n );\n}\n\n/**\n * Refresh quotes for all transactions if expired.\n *\n * @param messenger - Messenger instance.\n * @param updateTransactionData - Callback to update transaction data.\n * @param getStrategies - Callback to get ordered strategy names for a transaction.\n */\nexport async function refreshQuotes(\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[],\n): Promise<void> {\n const state = messenger.call('TransactionPayController:getState');\n const transactionIds = Object.keys(state.transactionData);\n\n for (const transactionId of transactionIds) {\n const transactionData = state.transactionData[transactionId];\n const { isLoading, quotes, quotesLastUpdated } = transactionData;\n\n if (isLoading || !quotes?.length) {\n continue;\n }\n\n // No-op quotes mark direct routes and have nothing to refresh. They are\n // regenerated whenever the transaction data changes.\n if (\n quotes.every((quote) => quote.strategy === TransactionPayStrategy.None)\n ) {\n continue;\n }\n\n const strategyName = quotes[0].strategy;\n const strategy = getStrategyByName(strategyName);\n\n const refreshInterval =\n (await strategy.getRefreshInterval?.({\n chainId: quotes[0].request.sourceChainId,\n messenger,\n })) ?? DEFAULT_REFRESH_INTERVAL;\n\n const isExpired = Date.now() - (quotesLastUpdated ?? 0) > refreshInterval;\n\n if (!isExpired) {\n continue;\n }\n\n const isUpdated = await updateQuotes({\n getStrategies,\n messenger,\n transactionData,\n transactionId,\n updateTransactionData,\n });\n\n if (isUpdated) {\n log('Refreshed quotes', { transactionId, strategy: strategyName });\n }\n }\n}\n\nfunction abortPreviousAndCreateController(\n transactionId: string,\n): AbortController {\n const previous = inFlightQuoteRequests.get(transactionId);\n\n if (previous && !previous.signal.aborted) {\n log('Aborting previous quote request', { transactionId });\n previous.abort(new Error('Superseded by newer quote request'));\n }\n\n const controller = new AbortController();\n inFlightQuoteRequests.set(transactionId, controller);\n return controller;\n}\n\nfunction clearControllerIfCurrent(\n transactionId: string,\n controller: AbortController,\n): void {\n if (inFlightQuoteRequests.get(transactionId) === controller) {\n inFlightQuoteRequests.delete(transactionId);\n }\n}\n\n/**\n * Read the current source amounts for a transaction from controller state.\n *\n * @param messenger - Messenger instance.\n * @param transactionId - ID of the transaction.\n * @returns The source amounts, or `undefined` if the transaction has none.\n */\nfunction getSourceAmounts(\n messenger: TransactionPayControllerMessenger,\n transactionId: string,\n): TransactionPaySourceAmount[] | undefined {\n return messenger.call('TransactionPayController:getState').transactionData[\n transactionId\n ]?.sourceAmounts;\n}\n\n/**\n * Build quote requests required to retrieve quotes.\n *\n * @param request - Request parameters.\n * @param request.atomic - Whether the target transaction is executed atomically with the Relay quote.\n * @param request.from - Address from which the transaction is sent.\n * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.\n * @param request.isMaxAmount - Whether the transaction is a maximum amount transaction.\n * @param request.isPolymarketDepositWallet - Whether the source of funds is a Polymarket deposit wallet.\n * @param request.isPostQuote - Whether this is a post-quote flow.\n * @param request.paymentOverride - Optional payment override type for the transaction.\n * @param request.paymentToken - Payment token (source for standard flows, destination for post-quote).\n * @param request.refundTo - Optional address to receive refunds if the Relay transaction fails.\n * @param request.sourceAmounts - Source amounts for the transaction.\n * @param request.tokens - Required tokens for the transaction.\n * @param request.transactionId - ID of the transaction.\n * @returns Array of quote requests.\n */\nfunction buildQuoteRequests({\n atomic,\n from,\n isHyperliquidSource,\n isMaxAmount,\n isPolymarketDepositWallet,\n isPostQuote,\n paymentOverride,\n paymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n transactionId,\n}: {\n atomic?: boolean;\n from: Hex;\n isHyperliquidSource?: boolean;\n isMaxAmount: boolean;\n isPolymarketDepositWallet?: boolean;\n isPostQuote?: boolean;\n paymentOverride?: PaymentOverride;\n paymentToken: TransactionPaymentToken | undefined;\n refundTo?: Hex;\n sourceAmounts: TransactionPaySourceAmount[] | undefined;\n tokens: TransactionPayRequiredToken[];\n transactionId: string;\n}): QuoteRequest[] {\n if (!paymentToken) {\n return [];\n }\n\n if (isPostQuote) {\n return buildPostQuoteRequests({\n atomic,\n destinationToken: paymentToken,\n from,\n isHyperliquidSource,\n isMaxAmount,\n isPolymarketDepositWallet,\n paymentOverride,\n refundTo,\n sourceAmounts,\n transactionId,\n });\n }\n\n // Standard flow: source = paymentToken, target = required tokens\n const requests = (sourceAmounts ?? []).map((sourceAmount) => {\n const token = tokens.find(\n (singleToken) => singleToken.address === sourceAmount.targetTokenAddress,\n ) as TransactionPayRequiredToken;\n\n return {\n atomic,\n from,\n isMaxAmount,\n paymentOverride,\n refundTo,\n sourceBalanceRaw: paymentToken.balanceRaw,\n sourceChainId: paymentToken.chainId,\n sourceTokenAddress: paymentToken.address,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n targetAmountMinimum: token.allowUnderMinimum ? '0' : token.amountRaw,\n targetChainId: token.chainId,\n targetTokenAddress: token.address,\n };\n });\n\n if (!requests.length) {\n log('No quote requests', { transactionId });\n }\n\n return requests;\n}\n\n/**\n * Build quote requests for post-quote flows.\n * In this flow, the source is the transaction's required token,\n * and the target is the user's selected destination token (paymentToken).\n *\n * @param request - Request parameters.\n * @param request.atomic - Whether the target transaction is executed atomically with the Relay quote.\n * @param request.destinationToken - Destination token (paymentToken in post-quote mode).\n * @param request.from - Address from which the transaction is sent.\n * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.\n * @param request.isMaxAmount - Whether the transaction is a maximum amount transaction.\n * @param request.isPolymarketDepositWallet - Whether the source of funds is a Polymarket deposit wallet.\n * @param request.paymentOverride - Optional payment override type for the transaction.\n * @param request.refundTo - Optional address to receive refunds if the Relay transaction fails.\n * @param request.sourceAmounts - Source amounts for the transaction (includes source token info).\n * @param request.transactionId - ID of the transaction.\n * @returns Array of quote requests for post-quote flow.\n */\nfunction buildPostQuoteRequests({\n atomic,\n destinationToken,\n from,\n isHyperliquidSource,\n isMaxAmount,\n isPolymarketDepositWallet,\n paymentOverride,\n refundTo,\n sourceAmounts,\n transactionId,\n}: {\n atomic?: boolean;\n destinationToken: TransactionPaymentToken;\n from: Hex;\n isHyperliquidSource?: boolean;\n isMaxAmount: boolean;\n isPolymarketDepositWallet?: boolean;\n paymentOverride?: PaymentOverride;\n refundTo?: Hex;\n sourceAmounts: TransactionPaySourceAmount[] | undefined;\n transactionId: string;\n}): QuoteRequest[] {\n // Find the source amount where targetTokenAddress matches the destination token\n const sourceAmount = sourceAmounts?.find(\n (amount) =>\n amount.targetTokenAddress.toLowerCase() ===\n destinationToken.address.toLowerCase(),\n );\n\n // Same-token-same-chain cases are already filtered in source-amounts.ts\n if (\n !sourceAmount?.sourceBalanceRaw ||\n !sourceAmount.sourceChainId ||\n !sourceAmount.sourceTokenAddress\n ) {\n log('No valid source amount found for post-quote request', {\n transactionId,\n });\n return [];\n }\n\n const request: QuoteRequest = {\n atomic,\n from,\n isHyperliquidSource,\n isMaxAmount,\n isPolymarketDepositWallet,\n isPostQuote: true,\n paymentOverride,\n refundTo,\n sourceBalanceRaw: sourceAmount.sourceBalanceRaw,\n sourceChainId: sourceAmount.sourceChainId,\n sourceTokenAddress: sourceAmount.sourceTokenAddress,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n targetAmountMinimum: '0',\n targetChainId: destinationToken.chainId,\n targetTokenAddress: destinationToken.address,\n };\n\n log('Post-quote request built', { transactionId, request });\n\n // Currently only single token post-quote flows are supported.\n // Multiple token support would require multiple quotes for each required token.\n return [request];\n}\n\nasync function refreshPaymentTokenBalance({\n from,\n messenger,\n paymentToken,\n signal,\n transactionId,\n updateTransactionData,\n}: {\n from: Hex;\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\n signal: AbortSignal;\n transactionId: string;\n updateTransactionData: UpdateTransactionDataCallback;\n}): Promise<TransactionPaymentToken | undefined> {\n if (!paymentToken) {\n return undefined;\n }\n\n try {\n const fiatRates = getTokenFiatRate(\n messenger,\n paymentToken.address,\n paymentToken.chainId,\n );\n\n if (!fiatRates) {\n return paymentToken;\n }\n\n const liveBalance = await getLiveTokenBalance(\n messenger,\n from,\n paymentToken.chainId,\n paymentToken.address,\n );\n\n if (signal.aborted) {\n log('Payment token balance refresh aborted', { transactionId });\n return paymentToken;\n }\n\n const {\n raw: balanceRaw,\n human: balanceHuman,\n usd: balanceUsd,\n fiat: balanceFiat,\n } = computeTokenAmounts(liveBalance, paymentToken.decimals, fiatRates);\n\n const updatedToken = {\n ...paymentToken,\n balanceFiat,\n balanceHuman,\n balanceRaw,\n balanceUsd,\n };\n\n updateTransactionData(transactionId, (data) => {\n data.paymentToken = updatedToken;\n });\n\n log('Refreshed payment token balance', { transactionId, balanceRaw });\n\n return updatedToken;\n } catch (error) {\n log('Failed to refresh payment token balance', { transactionId, error });\n return paymentToken;\n }\n}\n\n/**\n * Retrieve quotes for a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param from - Resolved wallet address (`accountOverride ?? txParams.from`).\n * @param requests - Quote requests.\n * @param paymentToken - Selected payment token, if any.\n * @param isQuoteRequired - Whether a quote is always required for the transaction.\n * @param isAccountEIP7702Compatible - Whether the account supports EIP-7702.\n * @param getStrategies - Callback to get ordered strategy names for a transaction.\n * @param messenger - Controller messenger.\n * @param fiatPaymentMethod - Selected fiat payment method ID, if applicable.\n * @param signal - Signal that aborts when the quote request is superseded.\n * @returns An object containing batch transactions and quotes.\n */\nasync function getQuotes(\n transaction: TransactionMeta,\n from: Hex,\n requests: QuoteRequest[],\n paymentToken: TransactionPaymentToken | undefined,\n isQuoteRequired: boolean,\n isAccountEIP7702Compatible: boolean,\n getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[],\n messenger: TransactionPayControllerMessenger,\n fiatPaymentMethod?: string,\n signal?: AbortSignal,\n): Promise<{\n batchTransactions: BatchTransaction[];\n error?: QuoteErrorInfo;\n quotes: TransactionPayQuote<Json>[];\n}> {\n const { id: transactionId } = transaction;\n const strategies = getStrategiesByName(\n getStrategies(transaction),\n (strategyName) => {\n log('Skipping unknown strategy', {\n strategy: strategyName,\n transactionId,\n });\n },\n );\n\n if (!requests?.length && !fiatPaymentMethod) {\n // A selected payment token with no conversion requests means the route is\n // direct. Return an explicit no-op quote so clients and the publish hook\n // can distinguish \"no conversion needed\" from \"quote needed but missing\".\n // Not applicable when a quote is always required, as an empty requests\n // list then means the source amounts could not be calculated.\n const noOpQuote =\n paymentToken && !isQuoteRequired\n ? buildNoOpQuote(from, paymentToken)\n : undefined;\n\n if (noOpQuote) {\n log('Built no-op quote for direct route', { transactionId });\n }\n\n return {\n batchTransactions: [],\n quotes: noOpQuote ? [noOpQuote] : [],\n };\n }\n\n const request = {\n accountSupports7702: isAccountEIP7702Compatible,\n fiatPaymentMethod,\n from,\n messenger,\n requests,\n signal,\n transaction,\n };\n\n let error: QuoteErrorInfo | undefined;\n\n for (const { name, strategy } of strategies) {\n try {\n const support = await checkStrategySupport(strategy, request);\n\n if (!support) {\n log('Strategy does not support request', {\n strategy: name,\n transactionId,\n });\n continue;\n }\n\n const quotes = (await strategy.getQuotes(\n request,\n )) as TransactionPayQuote<Json>[];\n\n if (!quotes.length) {\n log('Strategy returned no quotes', { strategy: name, transactionId });\n continue;\n }\n\n const isQuoteSupported = await checkStrategyQuoteSupport(strategy, {\n messenger,\n quotes,\n signal,\n transaction,\n });\n\n if (!isQuoteSupported) {\n log('Strategy does not support quotes', {\n strategy: name,\n transactionId,\n });\n continue;\n }\n\n log('Updated', { transactionId, quotes });\n\n const batchTransactions = strategy.getBatchTransactions\n ? await strategy.getBatchTransactions({\n messenger,\n quotes,\n signal,\n })\n : [];\n\n log('Batch transactions', { transactionId, batchTransactions });\n\n return {\n batchTransactions,\n quotes,\n };\n } catch (caughtError) {\n if (signal?.aborted) {\n throw caughtError;\n }\n\n error ??= isQuoteError(caughtError)\n ? caughtError.info\n : { message: (caughtError as Error).message, reason: 'no-quotes' };\n\n if (\n isQuoteError(caughtError) &&\n caughtError.info.reason === 'insufficient-source-balance' &&\n caughtError.quotes?.length\n ) {\n log('Keeping quotes despite insufficient source balance', {\n strategy: name,\n transactionId,\n });\n return {\n batchTransactions: [],\n error: caughtError.info,\n quotes: caughtError.quotes as TransactionPayQuote<Json>[],\n };\n }\n\n log('Strategy failed, trying next', {\n error: caughtError,\n strategy: name,\n transactionId,\n });\n continue;\n }\n }\n\n log('No quotes available', { transactionId });\n\n return {\n batchTransactions: [],\n error,\n quotes: [],\n };\n}\n"]}
1
+ {"version":3,"file":"quotes.js","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { TransactionStatus } from '@metamask/transaction-controller';\nimport type { BatchTransaction } from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex, Json } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { PaymentOverride, TransactionPayStrategy } from '../constants.js';\nimport { projectLogger } from '../logger.js';\nimport type {\n QuoteRequest,\n QuoteErrorInfo,\n TransactionData,\n GetBalanceCallback,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n TransactionPayRequiredToken,\n TransactionPaySourceAmount,\n TransactionPayTotals,\n TransactionPaymentToken,\n UpdateTransactionDataCallback,\n} from '../types.js';\nimport { accountSupports7702 } from './7702.js';\nimport { buildNoOpQuote } from './no-op-quote.js';\nimport { updateSourceAmounts } from './source-amounts.js';\nimport {\n checkStrategyQuoteSupport,\n checkStrategySupport,\n getStrategiesByName,\n getStrategyByName,\n} from './strategy.js';\nimport {\n computeTokenAmounts,\n getLiveTokenBalance,\n getTokenFiatRate,\n} from './token.js';\nimport { calculateTotals } from './totals.js';\nimport { getTransaction, updateTransaction } from './transaction.js';\nimport { isQuoteError } from './validation.js';\n\nconst DEFAULT_REFRESH_INTERVAL = 30 * 1000; // 30 Seconds\n\nconst log = createModuleLogger(projectLogger, 'quotes');\n\nconst inFlightQuoteRequests = new Map<string, AbortController>();\n\nexport type UpdateQuotesRequest = {\n getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[];\n messenger: TransactionPayControllerMessenger;\n transactionData: TransactionData | undefined;\n transactionId: string;\n updateTransactionData: UpdateTransactionDataCallback;\n};\n\n/**\n * Update the quotes for a specific transaction.\n *\n * Calls for the same `transactionId` are serialised: a fresh call aborts any\n * previous in-flight call so a slower stale response cannot overwrite a newer\n * one in state.\n *\n * @param request - Request parameters.\n * @returns Boolean indicating if the quotes were updated. Returns `false` when\n * the call was aborted by a subsequent call for the same transaction.\n */\nexport async function updateQuotes(\n request: UpdateQuotesRequest,\n): Promise<boolean> {\n const {\n getStrategies,\n messenger,\n transactionData,\n transactionId,\n updateTransactionData,\n } = request;\n\n const transaction = getTransaction(transactionId, messenger);\n\n if (!transaction || !transactionData) {\n throw new Error('Transaction not found');\n }\n\n if (transaction?.status !== TransactionStatus.unapproved) {\n return false;\n }\n\n log('Updating quotes', { transactionId });\n\n const {\n accountOverride,\n atomic,\n fiatPayment,\n isHyperliquidSource,\n isMaxAmount,\n isPolymarketDepositWallet,\n isPostQuote,\n isQuoteRequired,\n paymentOverride,\n paymentToken: originalPaymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n } = transactionData;\n\n const from = getFrom(transaction, transactionData);\n\n const controller = abortPreviousAndCreateController(transactionId);\n const { signal } = controller;\n\n updateTransactionData(transactionId, (data) => {\n data.isLoading = true;\n data.quoteError = undefined;\n });\n\n try {\n const paymentToken = await refreshPaymentTokenBalance({\n // Post-quote payment tokens are received by `accountOverride`.\n from: accountOverride ?? (transaction.txParams.from as Hex),\n messenger,\n paymentToken: originalPaymentToken,\n signal,\n transactionId,\n updateTransactionData,\n });\n\n if (signal.aborted) {\n log('Quote request aborted before building requests', { transactionId });\n return false;\n }\n\n // Refreshing the balance above re-derives max source amounts, so read the\n // latest values instead of the snapshot taken before the refresh. Using\n // the snapshot quotes a max amount against a stale balance, which requests\n // a zero source amount when the token was selected before its balance\n // loaded.\n const latestSourceAmounts =\n getSourceAmounts(messenger, transactionId) ?? sourceAmounts;\n\n const requests = buildQuoteRequests({\n accountOverride,\n atomic,\n from,\n isHyperliquidSource,\n isMaxAmount: isMaxAmount ?? false,\n isPolymarketDepositWallet,\n isPostQuote,\n paymentOverride,\n paymentToken,\n refundTo,\n sourceAmounts: latestSourceAmounts,\n tokens,\n transactionId,\n });\n\n const supports7702 = accountSupports7702(messenger, from);\n\n const { batchTransactions, error, quotes } = await getQuotes(\n transaction,\n from,\n requests,\n paymentToken,\n isQuoteRequired ?? false,\n supports7702,\n getStrategies,\n messenger,\n fiatPayment?.selectedPaymentMethodId,\n signal,\n );\n\n if (signal.aborted) {\n log('Quote request aborted before persisting results', { transactionId });\n return false;\n }\n\n // No-op quotes mark direct routes. They have no fees or amounts and the\n // transaction is signed and submitted locally, so totals and transaction\n // sync must treat them as \"no quotes\".\n const executableQuotes = quotes.filter(\n (quote) => quote.strategy !== TransactionPayStrategy.None,\n );\n\n const totals = calculateTotals({\n fiatPaymentAmount: fiatPayment?.amountFiat,\n messenger,\n quotes: executableQuotes,\n tokens,\n transaction,\n });\n\n log('Calculated totals', { transactionId, totals });\n\n syncTransaction({\n batchTransactions,\n selectedFiatPayment: fiatPayment?.selectedPaymentMethodId,\n hasQuotes: executableQuotes.length > 0,\n isPostQuote,\n messenger,\n paymentToken,\n strategy: executableQuotes[0]?.strategy,\n totals,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n // oxlint-disable-next-line typescript/no-unnecessary-type-assertion\n data.quotes = quotes as never;\n data.quoteError = error;\n data.quotesLastUpdated = Date.now();\n data.totals = totals;\n });\n } catch (error) {\n if (signal.aborted) {\n log('Quote request aborted', { transactionId, reason: signal.reason });\n return false;\n }\n throw error;\n } finally {\n if (!signal.aborted) {\n updateTransactionData(transactionId, (data) => {\n data.isLoading = false;\n });\n }\n clearControllerIfCurrent(transactionId, controller);\n }\n\n return true;\n}\n\n/**\n * Get the account that sends quotes for a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param transactionData - Transaction pay data.\n * @returns The quote sender address.\n */\nfunction getFrom(\n transaction: TransactionMeta,\n transactionData: TransactionData,\n): Hex {\n const transactionFrom = transaction.txParams.from as Hex;\n\n // Post-quote output goes to `accountOverride`, so the funds holder sends.\n if (transactionData.isPostQuote) {\n return transactionFrom;\n }\n\n return transactionData.accountOverride ?? transactionFrom;\n}\n\n/**\n * Sync batch transactions to the transaction meta.\n *\n * @param request - Request object.\n * @param request.batchTransactions - Batch transactions to sync.\n * @param request.hasQuotes - Whether MM Pay produced any quotes for this transaction.\n * @param request.isPostQuote - Whether this is a post-quote flow.\n * @param request.messenger - Messenger instance.\n * @param request.paymentToken - Payment token (source for standard flows, destination for post-quote).\n * @param request.selectedFiatPayment - Selected fiat payment method ID.\n * @param request.strategy - Strategy of the executable quotes.\n * @param request.totals - Calculated totals.\n * @param request.transactionId - ID of the transaction to sync.\n */\nfunction syncTransaction({\n batchTransactions,\n hasQuotes,\n isPostQuote,\n messenger,\n paymentToken,\n selectedFiatPayment,\n strategy,\n totals,\n transactionId,\n}: {\n batchTransactions: BatchTransaction[];\n selectedFiatPayment?: string;\n hasQuotes: boolean;\n isPostQuote?: boolean;\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\n strategy?: TransactionPayStrategy;\n totals: TransactionPayTotals;\n transactionId: string;\n}): void {\n if (!paymentToken && !selectedFiatPayment) {\n return;\n }\n\n updateTransaction(\n {\n transactionId,\n messenger,\n note: 'Update transaction pay data',\n },\n (tx: TransactionMeta) => {\n tx.batchTransactions = batchTransactions;\n tx.batchTransactionsOptions = {};\n\n // When MM Pay has produced quotes, it owns submission of this transaction\n // via its strategy publish hook, so the parent must be marked externally\n // signed to skip the local `KeyringController:signTransaction` call.\n // When there are no quotes (e.g. user selected the target token as the\n // payment token in a Predict flow), the transaction falls back to normal\n // local signing, so the flag is cleared to allow that.\n // If gas is sponsored, TC owns this field — it is set based on the\n // Sentinel simulation result and must not be cleared here. Same-token\n // flows (e.g. Monad mUSD withdrawal via a Money Account) produce no\n // quotes but still need external sign because the account cannot sign\n // locally.\n if (!tx.isGasFeeSponsored) {\n tx.isExternalSign = hasQuotes;\n }\n\n tx.metamaskPay = {\n bridgeFeeFiat: totals.fees.provider.usd,\n chainId: paymentToken?.chainId,\n isPostQuote,\n networkFeeFiat: totals.fees.sourceNetwork.estimate.usd,\n strategy,\n targetFiat: totals.targetAmount.usd,\n tokenAddress: paymentToken?.address,\n totalFiat: totals.total.usd,\n };\n },\n );\n}\n\n/**\n * Refresh source amounts and quotes for all transactions if expired.\n *\n * @param messenger - Messenger instance.\n * @param updateTransactionData - Callback to update transaction data.\n * @param getStrategies - Callback to get ordered strategy names for a transaction.\n * @param getBalance - Optional callback to override the source balance used for max-amount calculation.\n */\nexport async function refreshQuotes(\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[],\n getBalance?: GetBalanceCallback,\n): Promise<void> {\n const state = messenger.call('TransactionPayController:getState');\n const transactionIds = Object.keys(state.transactionData);\n\n for (const transactionId of transactionIds) {\n const transactionData = state.transactionData[transactionId];\n const { isLoading, quotes, quotesLastUpdated } = transactionData;\n\n if (isLoading || !quotes?.length) {\n continue;\n }\n\n // No-op quotes mark direct routes and have nothing to refresh. They are\n // regenerated whenever the transaction data changes.\n if (\n quotes.every((quote) => quote.strategy === TransactionPayStrategy.None)\n ) {\n continue;\n }\n\n const strategyName = quotes[0].strategy;\n const strategy = getStrategyByName(strategyName);\n\n const refreshInterval =\n (await strategy.getRefreshInterval?.({\n chainId: quotes[0].request.sourceChainId,\n messenger,\n transactionId,\n })) ?? DEFAULT_REFRESH_INTERVAL;\n\n const isExpired = Date.now() - (quotesLastUpdated ?? 0) > refreshInterval;\n\n if (!isExpired) {\n continue;\n }\n\n updateTransactionData(transactionId, (data) =>\n updateSourceAmounts(\n transactionId,\n /* oxlint-disable typescript/no-unnecessary-type-assertion */\n data as never,\n /* oxlint-enable typescript/no-unnecessary-type-assertion */\n messenger,\n getBalance,\n ),\n );\n\n const latestTransactionData = messenger.call(\n 'TransactionPayController:getState',\n ).transactionData[transactionId];\n\n const isUpdated = await updateQuotes({\n getStrategies,\n messenger,\n transactionData: latestTransactionData,\n transactionId,\n updateTransactionData,\n });\n\n if (isUpdated) {\n log('Refreshed quotes', { transactionId, strategy: strategyName });\n }\n }\n}\n\nfunction abortPreviousAndCreateController(\n transactionId: string,\n): AbortController {\n const previous = inFlightQuoteRequests.get(transactionId);\n\n if (previous && !previous.signal.aborted) {\n log('Aborting previous quote request', { transactionId });\n previous.abort(new Error('Superseded by newer quote request'));\n }\n\n const controller = new AbortController();\n inFlightQuoteRequests.set(transactionId, controller);\n return controller;\n}\n\nfunction clearControllerIfCurrent(\n transactionId: string,\n controller: AbortController,\n): void {\n if (inFlightQuoteRequests.get(transactionId) === controller) {\n inFlightQuoteRequests.delete(transactionId);\n }\n}\n\n/**\n * Read the current source amounts for a transaction from controller state.\n *\n * @param messenger - Messenger instance.\n * @param transactionId - ID of the transaction.\n * @returns The source amounts, or `undefined` if the transaction has none.\n */\nfunction getSourceAmounts(\n messenger: TransactionPayControllerMessenger,\n transactionId: string,\n): TransactionPaySourceAmount[] | undefined {\n return messenger.call('TransactionPayController:getState').transactionData[\n transactionId\n ]?.sourceAmounts;\n}\n\n/**\n * Build quote requests required to retrieve quotes.\n *\n * @param request - Request parameters.\n * @param request.accountOverride - Optional account receiving post-quote output.\n * @param request.atomic - Whether the target transaction is executed atomically with the Relay quote.\n * @param request.from - Address from which the transaction is sent.\n * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.\n * @param request.isMaxAmount - Whether the transaction is a maximum amount transaction.\n * @param request.isPolymarketDepositWallet - Whether the source of funds is a Polymarket deposit wallet.\n * @param request.isPostQuote - Whether this is a post-quote flow.\n * @param request.paymentOverride - Optional payment override type for the transaction.\n * @param request.paymentToken - Payment token (source for standard flows, destination for post-quote).\n * @param request.refundTo - Optional address to receive refunds if the Relay transaction fails.\n * @param request.sourceAmounts - Source amounts for the transaction.\n * @param request.tokens - Required tokens for the transaction.\n * @param request.transactionId - ID of the transaction.\n * @returns Array of quote requests.\n */\nfunction buildQuoteRequests({\n accountOverride,\n atomic,\n from,\n isHyperliquidSource,\n isMaxAmount,\n isPolymarketDepositWallet,\n isPostQuote,\n paymentOverride,\n paymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n transactionId,\n}: {\n accountOverride?: Hex;\n atomic?: boolean;\n from: Hex;\n isHyperliquidSource?: boolean;\n isMaxAmount: boolean;\n isPolymarketDepositWallet?: boolean;\n isPostQuote?: boolean;\n paymentOverride?: PaymentOverride;\n paymentToken: TransactionPaymentToken | undefined;\n refundTo?: Hex;\n sourceAmounts: TransactionPaySourceAmount[] | undefined;\n tokens: TransactionPayRequiredToken[];\n transactionId: string;\n}): QuoteRequest[] {\n if (!paymentToken) {\n return [];\n }\n\n if (isPostQuote) {\n return buildPostQuoteRequests({\n accountOverride,\n atomic,\n destinationToken: paymentToken,\n from,\n isHyperliquidSource,\n isMaxAmount,\n isPolymarketDepositWallet,\n paymentOverride,\n refundTo,\n sourceAmounts,\n transactionId,\n });\n }\n\n // Standard flow: source = paymentToken, target = required tokens\n const requests = (sourceAmounts ?? []).map((sourceAmount) => {\n const token = tokens.find(\n (singleToken) => singleToken.address === sourceAmount.targetTokenAddress,\n ) as TransactionPayRequiredToken;\n\n return {\n atomic,\n from,\n isMaxAmount,\n paymentOverride,\n refundTo,\n sourceBalanceRaw: paymentToken.balanceRaw,\n sourceChainId: paymentToken.chainId,\n sourceTokenAddress: paymentToken.address,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n targetAmountMinimum: token.allowUnderMinimum ? '0' : token.amountRaw,\n targetChainId: token.chainId,\n targetTokenAddress: token.address,\n };\n });\n\n if (!requests.length) {\n log('No quote requests', { transactionId });\n }\n\n return requests;\n}\n\n/**\n * Build quote requests for post-quote flows.\n * In this flow, the source is the transaction's required token,\n * and the target is the user's selected destination token (paymentToken).\n *\n * @param request - Request parameters.\n * @param request.accountOverride - Optional account receiving the output.\n * @param request.atomic - Whether the target transaction is executed atomically with the Relay quote.\n * @param request.destinationToken - Destination token (paymentToken in post-quote mode).\n * @param request.from - Address from which the transaction is sent.\n * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.\n * @param request.isMaxAmount - Whether the transaction is a maximum amount transaction.\n * @param request.isPolymarketDepositWallet - Whether the source of funds is a Polymarket deposit wallet.\n * @param request.paymentOverride - Optional payment override type for the transaction.\n * @param request.refundTo - Optional address to receive refunds if the Relay transaction fails.\n * @param request.sourceAmounts - Source amounts for the transaction (includes source token info).\n * @param request.transactionId - ID of the transaction.\n * @returns Array of quote requests for post-quote flow.\n */\nfunction buildPostQuoteRequests({\n accountOverride,\n atomic,\n destinationToken,\n from,\n isHyperliquidSource,\n isMaxAmount,\n isPolymarketDepositWallet,\n paymentOverride,\n refundTo,\n sourceAmounts,\n transactionId,\n}: {\n accountOverride?: Hex;\n atomic?: boolean;\n destinationToken: TransactionPaymentToken;\n from: Hex;\n isHyperliquidSource?: boolean;\n isMaxAmount: boolean;\n isPolymarketDepositWallet?: boolean;\n paymentOverride?: PaymentOverride;\n refundTo?: Hex;\n sourceAmounts: TransactionPaySourceAmount[] | undefined;\n transactionId: string;\n}): QuoteRequest[] {\n // Find the source amount where targetTokenAddress matches the destination token\n const sourceAmount = sourceAmounts?.find(\n (amount) =>\n amount.targetTokenAddress.toLowerCase() ===\n destinationToken.address.toLowerCase(),\n );\n\n // Same-token-same-chain cases are already filtered in source-amounts.ts\n if (\n !sourceAmount?.sourceBalanceRaw ||\n !sourceAmount.sourceChainId ||\n !sourceAmount.sourceTokenAddress\n ) {\n log('No valid source amount found for post-quote request', {\n transactionId,\n });\n return [];\n }\n\n const request: QuoteRequest = {\n accountOverride,\n atomic,\n from,\n isHyperliquidSource,\n isMaxAmount,\n isPolymarketDepositWallet,\n isPostQuote: true,\n paymentOverride,\n refundTo,\n sourceBalanceRaw: sourceAmount.sourceBalanceRaw,\n sourceChainId: sourceAmount.sourceChainId,\n sourceTokenAddress: sourceAmount.sourceTokenAddress,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n targetAmountMinimum: '0',\n targetChainId: destinationToken.chainId,\n targetTokenAddress: destinationToken.address,\n };\n\n log('Post-quote request built', { transactionId, request });\n\n // Currently only single token post-quote flows are supported.\n // Multiple token support would require multiple quotes for each required token.\n return [request];\n}\n\nasync function refreshPaymentTokenBalance({\n from,\n messenger,\n paymentToken,\n signal,\n transactionId,\n updateTransactionData,\n}: {\n from: Hex;\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\n signal: AbortSignal;\n transactionId: string;\n updateTransactionData: UpdateTransactionDataCallback;\n}): Promise<TransactionPaymentToken | undefined> {\n if (!paymentToken) {\n return undefined;\n }\n\n try {\n const fiatRates = getTokenFiatRate(\n messenger,\n paymentToken.address,\n paymentToken.chainId,\n );\n\n if (!fiatRates) {\n return paymentToken;\n }\n\n const liveBalance = await getLiveTokenBalance(\n messenger,\n from,\n paymentToken.chainId,\n paymentToken.address,\n );\n\n if (signal.aborted) {\n log('Payment token balance refresh aborted', { transactionId });\n return paymentToken;\n }\n\n const {\n raw: balanceRaw,\n human: balanceHuman,\n usd: balanceUsd,\n fiat: balanceFiat,\n } = computeTokenAmounts(liveBalance, paymentToken.decimals, fiatRates);\n\n const updatedToken = {\n ...paymentToken,\n balanceFiat,\n balanceHuman,\n balanceRaw,\n balanceUsd,\n };\n\n updateTransactionData(transactionId, (data) => {\n data.paymentToken = updatedToken;\n });\n\n log('Refreshed payment token balance', { transactionId, balanceRaw });\n\n return updatedToken;\n } catch (error) {\n log('Failed to refresh payment token balance', { transactionId, error });\n return paymentToken;\n }\n}\n\n/**\n * Retrieve quotes for a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param from - Sending wallet address (`txParams.from` for post-quote, otherwise `accountOverride ?? txParams.from`).\n * @param requests - Quote requests.\n * @param paymentToken - Selected payment token, if any.\n * @param isQuoteRequired - Whether a quote is always required for the transaction.\n * @param isAccountEIP7702Compatible - Whether the account supports EIP-7702.\n * @param getStrategies - Callback to get ordered strategy names for a transaction.\n * @param messenger - Controller messenger.\n * @param fiatPaymentMethod - Selected fiat payment method ID, if applicable.\n * @param signal - Signal that aborts when the quote request is superseded.\n * @returns An object containing batch transactions and quotes.\n */\nasync function getQuotes(\n transaction: TransactionMeta,\n from: Hex,\n requests: QuoteRequest[],\n paymentToken: TransactionPaymentToken | undefined,\n isQuoteRequired: boolean,\n isAccountEIP7702Compatible: boolean,\n getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[],\n messenger: TransactionPayControllerMessenger,\n fiatPaymentMethod?: string,\n signal?: AbortSignal,\n): Promise<{\n batchTransactions: BatchTransaction[];\n error?: QuoteErrorInfo;\n quotes: TransactionPayQuote<Json>[];\n}> {\n const { id: transactionId } = transaction;\n const strategies = getStrategiesByName(\n getStrategies(transaction),\n (strategyName) => {\n log('Skipping unknown strategy', {\n strategy: strategyName,\n transactionId,\n });\n },\n );\n\n if (!requests?.length && !fiatPaymentMethod) {\n // A selected payment token with no conversion requests means the route is\n // direct. Return an explicit no-op quote so clients and the publish hook\n // can distinguish \"no conversion needed\" from \"quote needed but missing\".\n // Not applicable when a quote is always required, as an empty requests\n // list then means the source amounts could not be calculated.\n const noOpQuote =\n paymentToken && !isQuoteRequired\n ? buildNoOpQuote(from, paymentToken)\n : undefined;\n\n if (noOpQuote) {\n log('Built no-op quote for direct route', { transactionId });\n }\n\n return {\n batchTransactions: [],\n quotes: noOpQuote ? [noOpQuote] : [],\n };\n }\n\n const request = {\n accountSupports7702: isAccountEIP7702Compatible,\n fiatPaymentMethod,\n from,\n messenger,\n requests,\n signal,\n transaction,\n };\n\n let error: QuoteErrorInfo | undefined;\n\n for (const { name, strategy } of strategies) {\n try {\n const support = await checkStrategySupport(strategy, request);\n\n if (!support) {\n log('Strategy does not support request', {\n strategy: name,\n transactionId,\n });\n continue;\n }\n\n const quotes = (await strategy.getQuotes(\n request,\n )) as TransactionPayQuote<Json>[];\n\n if (!quotes.length) {\n log('Strategy returned no quotes', { strategy: name, transactionId });\n continue;\n }\n\n const isQuoteSupported = await checkStrategyQuoteSupport(strategy, {\n messenger,\n quotes,\n signal,\n transaction,\n });\n\n if (!isQuoteSupported) {\n log('Strategy does not support quotes', {\n strategy: name,\n transactionId,\n });\n continue;\n }\n\n log('Updated', { transactionId, quotes });\n\n const batchTransactions = strategy.getBatchTransactions\n ? await strategy.getBatchTransactions({\n messenger,\n quotes,\n signal,\n })\n : [];\n\n log('Batch transactions', { transactionId, batchTransactions });\n\n return {\n batchTransactions,\n quotes,\n };\n } catch (caughtError) {\n if (signal?.aborted) {\n throw caughtError;\n }\n\n error ??= isQuoteError(caughtError)\n ? caughtError.info\n : { message: (caughtError as Error).message, reason: 'no-quotes' };\n\n if (\n isQuoteError(caughtError) &&\n caughtError.info.reason === 'insufficient-source-balance' &&\n caughtError.quotes?.length\n ) {\n log('Keeping quotes despite insufficient source balance', {\n strategy: name,\n transactionId,\n });\n return {\n batchTransactions: [],\n error: caughtError.info,\n quotes: caughtError.quotes as TransactionPayQuote<Json>[],\n };\n }\n\n log('Strategy failed, trying next', {\n error: caughtError,\n strategy: name,\n transactionId,\n });\n continue;\n }\n }\n\n log('No quotes available', { transactionId });\n\n return {\n batchTransactions: [],\n error,\n quotes: [],\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/transaction-pay-controller",
3
- "version": "30.4.2-preview-77efa7863",
3
+ "version": "30.4.3-preview-6ebaf4e52",
4
4
  "description": "Manages alternate payment strategies to provide required funds for transactions in MetaMask",
5
5
  "keywords": [
6
6
  "Ethereum",