@metamask/transaction-pay-controller 19.2.2 → 20.0.0

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.
Files changed (104) hide show
  1. package/CHANGELOG.md +30 -1
  2. package/dist/TransactionPayController.cjs +10 -1
  3. package/dist/TransactionPayController.cjs.map +1 -1
  4. package/dist/TransactionPayController.d.cts.map +1 -1
  5. package/dist/TransactionPayController.d.mts.map +1 -1
  6. package/dist/TransactionPayController.mjs +10 -1
  7. package/dist/TransactionPayController.mjs.map +1 -1
  8. package/dist/actions/update-payment-token.cjs +3 -1
  9. package/dist/actions/update-payment-token.cjs.map +1 -1
  10. package/dist/actions/update-payment-token.d.cts.map +1 -1
  11. package/dist/actions/update-payment-token.d.mts.map +1 -1
  12. package/dist/actions/update-payment-token.mjs +3 -1
  13. package/dist/actions/update-payment-token.mjs.map +1 -1
  14. package/dist/helpers/TransactionPayPublishHook.cjs +3 -0
  15. package/dist/helpers/TransactionPayPublishHook.cjs.map +1 -1
  16. package/dist/helpers/TransactionPayPublishHook.d.cts.map +1 -1
  17. package/dist/helpers/TransactionPayPublishHook.d.mts.map +1 -1
  18. package/dist/helpers/TransactionPayPublishHook.mjs +3 -0
  19. package/dist/helpers/TransactionPayPublishHook.mjs.map +1 -1
  20. package/dist/strategy/across/AcrossStrategy.cjs +34 -3
  21. package/dist/strategy/across/AcrossStrategy.cjs.map +1 -1
  22. package/dist/strategy/across/AcrossStrategy.d.cts +2 -1
  23. package/dist/strategy/across/AcrossStrategy.d.cts.map +1 -1
  24. package/dist/strategy/across/AcrossStrategy.d.mts +2 -1
  25. package/dist/strategy/across/AcrossStrategy.d.mts.map +1 -1
  26. package/dist/strategy/across/AcrossStrategy.mjs +34 -3
  27. package/dist/strategy/across/AcrossStrategy.mjs.map +1 -1
  28. package/dist/strategy/across/across-quotes.cjs +4 -2
  29. package/dist/strategy/across/across-quotes.cjs.map +1 -1
  30. package/dist/strategy/across/across-quotes.mjs +4 -2
  31. package/dist/strategy/across/across-quotes.mjs.map +1 -1
  32. package/dist/strategy/across/types.cjs.map +1 -1
  33. package/dist/strategy/across/types.d.cts +1 -0
  34. package/dist/strategy/across/types.d.cts.map +1 -1
  35. package/dist/strategy/across/types.d.mts +1 -0
  36. package/dist/strategy/across/types.d.mts.map +1 -1
  37. package/dist/strategy/across/types.mjs.map +1 -1
  38. package/dist/strategy/fiat/fiat-quotes.cjs +2 -1
  39. package/dist/strategy/fiat/fiat-quotes.cjs.map +1 -1
  40. package/dist/strategy/fiat/fiat-quotes.d.cts.map +1 -1
  41. package/dist/strategy/fiat/fiat-quotes.d.mts.map +1 -1
  42. package/dist/strategy/fiat/fiat-quotes.mjs +2 -1
  43. package/dist/strategy/fiat/fiat-quotes.mjs.map +1 -1
  44. package/dist/strategy/relay/relay-quotes.cjs +3 -1
  45. package/dist/strategy/relay/relay-quotes.cjs.map +1 -1
  46. package/dist/strategy/relay/relay-quotes.mjs +3 -1
  47. package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
  48. package/dist/strategy/relay/relay-submit.cjs +5 -2
  49. package/dist/strategy/relay/relay-submit.cjs.map +1 -1
  50. package/dist/strategy/relay/relay-submit.mjs +5 -2
  51. package/dist/strategy/relay/relay-submit.mjs.map +1 -1
  52. package/dist/tests/messenger-mock.cjs +12 -0
  53. package/dist/tests/messenger-mock.cjs.map +1 -1
  54. package/dist/tests/messenger-mock.d.cts +2 -4
  55. package/dist/tests/messenger-mock.d.cts.map +1 -1
  56. package/dist/tests/messenger-mock.d.mts +2 -4
  57. package/dist/tests/messenger-mock.d.mts.map +1 -1
  58. package/dist/tests/messenger-mock.mjs +12 -0
  59. package/dist/tests/messenger-mock.mjs.map +1 -1
  60. package/dist/types.cjs +9 -0
  61. package/dist/types.cjs.map +1 -1
  62. package/dist/types.d.cts +42 -3
  63. package/dist/types.d.cts.map +1 -1
  64. package/dist/types.d.mts +42 -3
  65. package/dist/types.d.mts.map +1 -1
  66. package/dist/types.mjs +8 -1
  67. package/dist/types.mjs.map +1 -1
  68. package/dist/utils/7702.cjs +23 -0
  69. package/dist/utils/7702.cjs.map +1 -0
  70. package/dist/utils/7702.d.cts +15 -0
  71. package/dist/utils/7702.d.cts.map +1 -0
  72. package/dist/utils/7702.d.mts +15 -0
  73. package/dist/utils/7702.d.mts.map +1 -0
  74. package/dist/utils/7702.mjs +19 -0
  75. package/dist/utils/7702.mjs.map +1 -0
  76. package/dist/utils/feature-flags.cjs +1 -1
  77. package/dist/utils/feature-flags.cjs.map +1 -1
  78. package/dist/utils/feature-flags.d.cts +1 -1
  79. package/dist/utils/feature-flags.d.mts +1 -1
  80. package/dist/utils/feature-flags.mjs +1 -1
  81. package/dist/utils/feature-flags.mjs.map +1 -1
  82. package/dist/utils/quote-gas.cjs +2 -1
  83. package/dist/utils/quote-gas.cjs.map +1 -1
  84. package/dist/utils/quote-gas.d.cts +1 -0
  85. package/dist/utils/quote-gas.d.cts.map +1 -1
  86. package/dist/utils/quote-gas.d.mts +1 -0
  87. package/dist/utils/quote-gas.d.mts.map +1 -1
  88. package/dist/utils/quote-gas.mjs +2 -1
  89. package/dist/utils/quote-gas.mjs.map +1 -1
  90. package/dist/utils/quotes.cjs +22 -5
  91. package/dist/utils/quotes.cjs.map +1 -1
  92. package/dist/utils/quotes.d.cts.map +1 -1
  93. package/dist/utils/quotes.d.mts.map +1 -1
  94. package/dist/utils/quotes.mjs +23 -6
  95. package/dist/utils/quotes.mjs.map +1 -1
  96. package/dist/utils/strategy.cjs +30 -1
  97. package/dist/utils/strategy.cjs.map +1 -1
  98. package/dist/utils/strategy.d.cts +21 -1
  99. package/dist/utils/strategy.d.cts.map +1 -1
  100. package/dist/utils/strategy.d.mts +21 -1
  101. package/dist/utils/strategy.d.mts.map +1 -1
  102. package/dist/utils/strategy.mjs +27 -0
  103. package/dist/utils/strategy.mjs.map +1 -1
  104. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"quote-gas.cjs","sourceRoot":"","sources":["../../src/utils/quote-gas.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { BatchTransactionParams } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport type { TransactionPayControllerMessenger } from '..';\nimport { projectLogger } from '../logger';\nimport { getGasBuffer } from './feature-flags';\nimport { estimateGasLimit } from './gas';\n\nconst log = createModuleLogger(projectLogger, 'quote-gas');\n\nexport type QuoteGasTransaction = {\n chainId: Hex;\n data: Hex;\n from: Hex;\n gas?: number | string;\n to: Hex;\n value?: number | string | Hex;\n};\n\nexport type QuoteGasLimit = {\n estimate: number;\n max: number;\n};\n\nexport async function estimateQuoteGasLimits({\n fallbackGas,\n fallbackOnSimulationFailure = false,\n messenger,\n transactions,\n}: {\n fallbackGas?: {\n estimate: number;\n max: number;\n };\n fallbackOnSimulationFailure?: boolean;\n messenger: TransactionPayControllerMessenger;\n transactions: QuoteGasTransaction[];\n}): Promise<{\n batchGasLimit?: QuoteGasLimit;\n gasLimits: QuoteGasLimit[];\n is7702: boolean;\n totalGasEstimate: number;\n totalGasLimit: number;\n usedBatch: boolean;\n}> {\n if (transactions.length === 0) {\n throw new Error('Quote gas estimation requires at least one transaction');\n }\n\n const useBatch = transactions.length > 1;\n\n if (useBatch) {\n return {\n ...(await estimateQuoteGasLimitsBatch(transactions, messenger)),\n usedBatch: true,\n };\n }\n\n return {\n ...(await estimateQuoteGasLimitSingle({\n fallbackGas,\n fallbackOnSimulationFailure,\n messenger,\n transaction: transactions[0],\n })),\n is7702: false,\n usedBatch: false,\n };\n}\n\nasync function estimateQuoteGasLimitsBatch(\n transactions: QuoteGasTransaction[],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n batchGasLimit?: QuoteGasLimit;\n gasLimits: QuoteGasLimit[];\n is7702: boolean;\n totalGasEstimate: number;\n totalGasLimit: number;\n}> {\n const [firstTransaction] = transactions;\n const gasBuffer = getGasBuffer(messenger, firstTransaction.chainId);\n\n const paramGasLimits = transactions.map((transaction) =>\n parseGasLimit(transaction.gas),\n );\n\n const { gasLimits } = await messenger.call(\n 'TransactionController:estimateGasBatch',\n {\n chainId: firstTransaction.chainId,\n from: firstTransaction.from,\n transactions: transactions.map(toBatchTransactionParams),\n },\n );\n\n if (gasLimits.length !== 1 && gasLimits.length !== transactions.length) {\n throw new Error('Unexpected batch gas limit count');\n }\n\n const bufferedGasLimits = gasLimits.map((gasLimit, index) => {\n const providedGasLimit = paramGasLimits[index];\n const providedGasWasPreserved =\n providedGasLimit !== undefined && providedGasLimit === gasLimit;\n\n // Per-entry batch results currently preserve validated input gas values\n // for transactions that already provided gas. If that contract changes\n // and batch estimation returns a different value, treat it as a fresh\n // estimate and apply the buffer. A single combined 7702 result is always\n // buffered because it is a fresh batch estimate.\n const useBuffer = gasLimits.length === 1 || !providedGasWasPreserved;\n const bufferedGas = Math.ceil(gasLimit * (useBuffer ? gasBuffer : 1));\n\n return {\n estimate: bufferedGas,\n max: bufferedGas,\n };\n });\n\n const totalGasLimit = bufferedGasLimits.reduce(\n (acc, gasLimit) => acc + gasLimit.max,\n 0,\n );\n const is7702 = bufferedGasLimits.length === 1;\n const batchGasLimit = is7702 ? bufferedGasLimits[0] : undefined;\n\n return {\n ...(batchGasLimit ? { batchGasLimit } : {}),\n gasLimits: bufferedGasLimits,\n is7702,\n totalGasEstimate: totalGasLimit,\n totalGasLimit,\n };\n}\n\nasync function estimateQuoteGasLimitSingle({\n fallbackGas,\n fallbackOnSimulationFailure,\n messenger,\n transaction,\n}: {\n fallbackGas?: {\n estimate: number;\n max: number;\n };\n fallbackOnSimulationFailure: boolean;\n messenger: TransactionPayControllerMessenger;\n transaction: QuoteGasTransaction;\n}): Promise<{\n gasLimits: QuoteGasLimit[];\n totalGasEstimate: number;\n totalGasLimit: number;\n}> {\n const providedGasLimit = parseGasLimit(transaction.gas);\n\n if (providedGasLimit !== undefined) {\n log('Using provided gas limit', {\n chainId: transaction.chainId,\n gas: providedGasLimit,\n index: 0,\n to: transaction.to,\n });\n\n return {\n gasLimits: [\n {\n estimate: providedGasLimit,\n max: providedGasLimit,\n },\n ],\n totalGasEstimate: providedGasLimit,\n totalGasLimit: providedGasLimit,\n };\n }\n\n const gasLimitResult = await estimateGasLimit({\n chainId: transaction.chainId,\n data: transaction.data,\n fallbackGas,\n fallbackOnSimulationFailure,\n from: transaction.from,\n messenger,\n to: transaction.to,\n value: toHex(transaction.value ?? '0'),\n });\n\n if (gasLimitResult.usedFallback) {\n log('Gas estimate failed, using fallback', {\n chainId: transaction.chainId,\n error: gasLimitResult.error,\n index: 0,\n to: transaction.to,\n });\n }\n\n const gasLimit = {\n estimate: gasLimitResult.estimate,\n max: gasLimitResult.max,\n };\n\n return {\n gasLimits: [gasLimit],\n totalGasEstimate: gasLimit.estimate,\n totalGasLimit: gasLimit.max,\n };\n}\n\nfunction toBatchTransactionParams(\n transaction: QuoteGasTransaction,\n): BatchTransactionParams {\n return {\n data: transaction.data,\n gas: transaction.gas === undefined ? undefined : toHex(transaction.gas),\n maxFeePerGas: undefined,\n maxPriorityFeePerGas: undefined,\n to: transaction.to,\n value: toHex(transaction.value ?? '0'),\n };\n}\n\nfunction parseGasLimit(gas?: number | string): number | undefined {\n if (gas === undefined) {\n return undefined;\n }\n\n const parsedGas = new BigNumber(gas);\n\n if (\n !parsedGas.isFinite() ||\n parsedGas.isNaN() ||\n !parsedGas.isInteger() ||\n parsedGas.lte(0)\n ) {\n return undefined;\n }\n\n return parsedGas.toNumber();\n}\n"]}
1
+ {"version":3,"file":"quote-gas.cjs","sourceRoot":"","sources":["../../src/utils/quote-gas.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { BatchTransactionParams } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport type { TransactionPayControllerMessenger } from '..';\nimport { projectLogger } from '../logger';\nimport { getGasBuffer } from './feature-flags';\nimport { estimateGasLimit } from './gas';\n\nconst log = createModuleLogger(projectLogger, 'quote-gas');\n\nexport type QuoteGasTransaction = {\n chainId: Hex;\n data: Hex;\n from: Hex;\n gas?: number | string;\n to: Hex;\n value?: number | string | Hex;\n};\n\nexport type QuoteGasLimit = {\n estimate: number;\n max: number;\n};\n\nexport async function estimateQuoteGasLimits({\n fallbackGas,\n fallbackOnSimulationFailure = false,\n messenger,\n transactions,\n}: {\n fallbackGas?: {\n estimate: number;\n max: number;\n };\n fallbackOnSimulationFailure?: boolean;\n messenger: TransactionPayControllerMessenger;\n transactions: QuoteGasTransaction[];\n}): Promise<{\n batchGasLimit?: QuoteGasLimit;\n gasLimits: QuoteGasLimit[];\n is7702: boolean;\n requiresAuthorizationList?: true;\n totalGasEstimate: number;\n totalGasLimit: number;\n usedBatch: boolean;\n}> {\n if (transactions.length === 0) {\n throw new Error('Quote gas estimation requires at least one transaction');\n }\n\n const useBatch = transactions.length > 1;\n\n if (useBatch) {\n return {\n ...(await estimateQuoteGasLimitsBatch(transactions, messenger)),\n usedBatch: true,\n };\n }\n\n return {\n ...(await estimateQuoteGasLimitSingle({\n fallbackGas,\n fallbackOnSimulationFailure,\n messenger,\n transaction: transactions[0],\n })),\n is7702: false,\n usedBatch: false,\n };\n}\n\nasync function estimateQuoteGasLimitsBatch(\n transactions: QuoteGasTransaction[],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n batchGasLimit?: QuoteGasLimit;\n gasLimits: QuoteGasLimit[];\n is7702: boolean;\n requiresAuthorizationList?: true;\n totalGasEstimate: number;\n totalGasLimit: number;\n}> {\n const [firstTransaction] = transactions;\n const gasBuffer = getGasBuffer(messenger, firstTransaction.chainId);\n\n const paramGasLimits = transactions.map((transaction) =>\n parseGasLimit(transaction.gas),\n );\n\n const { gasLimits, requiresAuthorizationList } = await messenger.call(\n 'TransactionController:estimateGasBatch',\n {\n chainId: firstTransaction.chainId,\n from: firstTransaction.from,\n transactions: transactions.map(toBatchTransactionParams),\n },\n );\n\n if (gasLimits.length !== 1 && gasLimits.length !== transactions.length) {\n throw new Error('Unexpected batch gas limit count');\n }\n\n const bufferedGasLimits = gasLimits.map((gasLimit, index) => {\n const providedGasLimit = paramGasLimits[index];\n const providedGasWasPreserved =\n providedGasLimit !== undefined && providedGasLimit === gasLimit;\n\n // Per-entry batch results currently preserve validated input gas values\n // for transactions that already provided gas. If that contract changes\n // and batch estimation returns a different value, treat it as a fresh\n // estimate and apply the buffer. A single combined 7702 result is always\n // buffered because it is a fresh batch estimate.\n const useBuffer = gasLimits.length === 1 || !providedGasWasPreserved;\n const bufferedGas = Math.ceil(gasLimit * (useBuffer ? gasBuffer : 1));\n\n return {\n estimate: bufferedGas,\n max: bufferedGas,\n };\n });\n\n const totalGasLimit = bufferedGasLimits.reduce(\n (acc, gasLimit) => acc + gasLimit.max,\n 0,\n );\n const is7702 = bufferedGasLimits.length === 1;\n const batchGasLimit = is7702 ? bufferedGasLimits[0] : undefined;\n\n return {\n ...(batchGasLimit ? { batchGasLimit } : {}),\n gasLimits: bufferedGasLimits,\n is7702,\n ...(requiresAuthorizationList ? { requiresAuthorizationList } : {}),\n totalGasEstimate: totalGasLimit,\n totalGasLimit,\n };\n}\n\nasync function estimateQuoteGasLimitSingle({\n fallbackGas,\n fallbackOnSimulationFailure,\n messenger,\n transaction,\n}: {\n fallbackGas?: {\n estimate: number;\n max: number;\n };\n fallbackOnSimulationFailure: boolean;\n messenger: TransactionPayControllerMessenger;\n transaction: QuoteGasTransaction;\n}): Promise<{\n gasLimits: QuoteGasLimit[];\n totalGasEstimate: number;\n totalGasLimit: number;\n}> {\n const providedGasLimit = parseGasLimit(transaction.gas);\n\n if (providedGasLimit !== undefined) {\n log('Using provided gas limit', {\n chainId: transaction.chainId,\n gas: providedGasLimit,\n index: 0,\n to: transaction.to,\n });\n\n return {\n gasLimits: [\n {\n estimate: providedGasLimit,\n max: providedGasLimit,\n },\n ],\n totalGasEstimate: providedGasLimit,\n totalGasLimit: providedGasLimit,\n };\n }\n\n const gasLimitResult = await estimateGasLimit({\n chainId: transaction.chainId,\n data: transaction.data,\n fallbackGas,\n fallbackOnSimulationFailure,\n from: transaction.from,\n messenger,\n to: transaction.to,\n value: toHex(transaction.value ?? '0'),\n });\n\n if (gasLimitResult.usedFallback) {\n log('Gas estimate failed, using fallback', {\n chainId: transaction.chainId,\n error: gasLimitResult.error,\n index: 0,\n to: transaction.to,\n });\n }\n\n const gasLimit = {\n estimate: gasLimitResult.estimate,\n max: gasLimitResult.max,\n };\n\n return {\n gasLimits: [gasLimit],\n totalGasEstimate: gasLimit.estimate,\n totalGasLimit: gasLimit.max,\n };\n}\n\nfunction toBatchTransactionParams(\n transaction: QuoteGasTransaction,\n): BatchTransactionParams {\n return {\n data: transaction.data,\n gas: transaction.gas === undefined ? undefined : toHex(transaction.gas),\n maxFeePerGas: undefined,\n maxPriorityFeePerGas: undefined,\n to: transaction.to,\n value: toHex(transaction.value ?? '0'),\n };\n}\n\nfunction parseGasLimit(gas?: number | string): number | undefined {\n if (gas === undefined) {\n return undefined;\n }\n\n const parsedGas = new BigNumber(gas);\n\n if (\n !parsedGas.isFinite() ||\n parsedGas.isNaN() ||\n !parsedGas.isInteger() ||\n parsedGas.lte(0)\n ) {\n return undefined;\n }\n\n return parsedGas.toNumber();\n}\n"]}
@@ -24,6 +24,7 @@ export declare function estimateQuoteGasLimits({ fallbackGas, fallbackOnSimulati
24
24
  batchGasLimit?: QuoteGasLimit;
25
25
  gasLimits: QuoteGasLimit[];
26
26
  is7702: boolean;
27
+ requiresAuthorizationList?: true;
27
28
  totalGasEstimate: number;
28
29
  totalGasLimit: number;
29
30
  usedBatch: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"quote-gas.d.cts","sourceRoot":"","sources":["../../src/utils/quote-gas.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAW;AAO5D,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,GAAG,CAAC;IACb,IAAI,EAAE,GAAG,CAAC;IACV,IAAI,EAAE,GAAG,CAAC;IACV,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,EAAE,EAAE,GAAG,CAAC;IACR,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,wBAAsB,sBAAsB,CAAC,EAC3C,WAAW,EACX,2BAAmC,EACnC,SAAS,EACT,YAAY,GACb,EAAE;IACD,WAAW,CAAC,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,YAAY,EAAE,mBAAmB,EAAE,CAAC;CACrC,GAAG,OAAO,CAAC;IACV,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC,CAwBD"}
1
+ {"version":3,"file":"quote-gas.d.cts","sourceRoot":"","sources":["../../src/utils/quote-gas.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAW;AAO5D,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,GAAG,CAAC;IACb,IAAI,EAAE,GAAG,CAAC;IACV,IAAI,EAAE,GAAG,CAAC;IACV,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,EAAE,EAAE,GAAG,CAAC;IACR,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,wBAAsB,sBAAsB,CAAC,EAC3C,WAAW,EACX,2BAAmC,EACnC,SAAS,EACT,YAAY,GACb,EAAE;IACD,WAAW,CAAC,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,YAAY,EAAE,mBAAmB,EAAE,CAAC;CACrC,GAAG,OAAO,CAAC;IACV,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,yBAAyB,CAAC,EAAE,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC,CAwBD"}
@@ -24,6 +24,7 @@ export declare function estimateQuoteGasLimits({ fallbackGas, fallbackOnSimulati
24
24
  batchGasLimit?: QuoteGasLimit;
25
25
  gasLimits: QuoteGasLimit[];
26
26
  is7702: boolean;
27
+ requiresAuthorizationList?: true;
27
28
  totalGasEstimate: number;
28
29
  totalGasLimit: number;
29
30
  usedBatch: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"quote-gas.d.mts","sourceRoot":"","sources":["../../src/utils/quote-gas.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAW;AAO5D,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,GAAG,CAAC;IACb,IAAI,EAAE,GAAG,CAAC;IACV,IAAI,EAAE,GAAG,CAAC;IACV,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,EAAE,EAAE,GAAG,CAAC;IACR,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,wBAAsB,sBAAsB,CAAC,EAC3C,WAAW,EACX,2BAAmC,EACnC,SAAS,EACT,YAAY,GACb,EAAE;IACD,WAAW,CAAC,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,YAAY,EAAE,mBAAmB,EAAE,CAAC;CACrC,GAAG,OAAO,CAAC;IACV,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC,CAwBD"}
1
+ {"version":3,"file":"quote-gas.d.mts","sourceRoot":"","sources":["../../src/utils/quote-gas.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAW;AAO5D,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,GAAG,CAAC;IACb,IAAI,EAAE,GAAG,CAAC;IACV,IAAI,EAAE,GAAG,CAAC;IACV,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,EAAE,EAAE,GAAG,CAAC;IACR,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,wBAAsB,sBAAsB,CAAC,EAC3C,WAAW,EACX,2BAAmC,EACnC,SAAS,EACT,YAAY,GACb,EAAE;IACD,WAAW,CAAC,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,YAAY,EAAE,mBAAmB,EAAE,CAAC;CACrC,GAAG,OAAO,CAAC;IACV,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,yBAAyB,CAAC,EAAE,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC,CAwBD"}
@@ -31,7 +31,7 @@ async function estimateQuoteGasLimitsBatch(transactions, messenger) {
31
31
  const [firstTransaction] = transactions;
32
32
  const gasBuffer = getGasBuffer(messenger, firstTransaction.chainId);
33
33
  const paramGasLimits = transactions.map((transaction) => parseGasLimit(transaction.gas));
34
- const { gasLimits } = await messenger.call('TransactionController:estimateGasBatch', {
34
+ const { gasLimits, requiresAuthorizationList } = await messenger.call('TransactionController:estimateGasBatch', {
35
35
  chainId: firstTransaction.chainId,
36
36
  from: firstTransaction.from,
37
37
  transactions: transactions.map(toBatchTransactionParams),
@@ -61,6 +61,7 @@ async function estimateQuoteGasLimitsBatch(transactions, messenger) {
61
61
  ...(batchGasLimit ? { batchGasLimit } : {}),
62
62
  gasLimits: bufferedGasLimits,
63
63
  is7702,
64
+ ...(requiresAuthorizationList ? { requiresAuthorizationList } : {}),
64
65
  totalGasEstimate: totalGasLimit,
65
66
  totalGasLimit,
66
67
  };
@@ -1 +1 @@
1
- {"version":3,"file":"quote-gas.mjs","sourceRoot":"","sources":["../../src/utils/quote-gas.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { BatchTransactionParams } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport type { TransactionPayControllerMessenger } from '..';\nimport { projectLogger } from '../logger';\nimport { getGasBuffer } from './feature-flags';\nimport { estimateGasLimit } from './gas';\n\nconst log = createModuleLogger(projectLogger, 'quote-gas');\n\nexport type QuoteGasTransaction = {\n chainId: Hex;\n data: Hex;\n from: Hex;\n gas?: number | string;\n to: Hex;\n value?: number | string | Hex;\n};\n\nexport type QuoteGasLimit = {\n estimate: number;\n max: number;\n};\n\nexport async function estimateQuoteGasLimits({\n fallbackGas,\n fallbackOnSimulationFailure = false,\n messenger,\n transactions,\n}: {\n fallbackGas?: {\n estimate: number;\n max: number;\n };\n fallbackOnSimulationFailure?: boolean;\n messenger: TransactionPayControllerMessenger;\n transactions: QuoteGasTransaction[];\n}): Promise<{\n batchGasLimit?: QuoteGasLimit;\n gasLimits: QuoteGasLimit[];\n is7702: boolean;\n totalGasEstimate: number;\n totalGasLimit: number;\n usedBatch: boolean;\n}> {\n if (transactions.length === 0) {\n throw new Error('Quote gas estimation requires at least one transaction');\n }\n\n const useBatch = transactions.length > 1;\n\n if (useBatch) {\n return {\n ...(await estimateQuoteGasLimitsBatch(transactions, messenger)),\n usedBatch: true,\n };\n }\n\n return {\n ...(await estimateQuoteGasLimitSingle({\n fallbackGas,\n fallbackOnSimulationFailure,\n messenger,\n transaction: transactions[0],\n })),\n is7702: false,\n usedBatch: false,\n };\n}\n\nasync function estimateQuoteGasLimitsBatch(\n transactions: QuoteGasTransaction[],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n batchGasLimit?: QuoteGasLimit;\n gasLimits: QuoteGasLimit[];\n is7702: boolean;\n totalGasEstimate: number;\n totalGasLimit: number;\n}> {\n const [firstTransaction] = transactions;\n const gasBuffer = getGasBuffer(messenger, firstTransaction.chainId);\n\n const paramGasLimits = transactions.map((transaction) =>\n parseGasLimit(transaction.gas),\n );\n\n const { gasLimits } = await messenger.call(\n 'TransactionController:estimateGasBatch',\n {\n chainId: firstTransaction.chainId,\n from: firstTransaction.from,\n transactions: transactions.map(toBatchTransactionParams),\n },\n );\n\n if (gasLimits.length !== 1 && gasLimits.length !== transactions.length) {\n throw new Error('Unexpected batch gas limit count');\n }\n\n const bufferedGasLimits = gasLimits.map((gasLimit, index) => {\n const providedGasLimit = paramGasLimits[index];\n const providedGasWasPreserved =\n providedGasLimit !== undefined && providedGasLimit === gasLimit;\n\n // Per-entry batch results currently preserve validated input gas values\n // for transactions that already provided gas. If that contract changes\n // and batch estimation returns a different value, treat it as a fresh\n // estimate and apply the buffer. A single combined 7702 result is always\n // buffered because it is a fresh batch estimate.\n const useBuffer = gasLimits.length === 1 || !providedGasWasPreserved;\n const bufferedGas = Math.ceil(gasLimit * (useBuffer ? gasBuffer : 1));\n\n return {\n estimate: bufferedGas,\n max: bufferedGas,\n };\n });\n\n const totalGasLimit = bufferedGasLimits.reduce(\n (acc, gasLimit) => acc + gasLimit.max,\n 0,\n );\n const is7702 = bufferedGasLimits.length === 1;\n const batchGasLimit = is7702 ? bufferedGasLimits[0] : undefined;\n\n return {\n ...(batchGasLimit ? { batchGasLimit } : {}),\n gasLimits: bufferedGasLimits,\n is7702,\n totalGasEstimate: totalGasLimit,\n totalGasLimit,\n };\n}\n\nasync function estimateQuoteGasLimitSingle({\n fallbackGas,\n fallbackOnSimulationFailure,\n messenger,\n transaction,\n}: {\n fallbackGas?: {\n estimate: number;\n max: number;\n };\n fallbackOnSimulationFailure: boolean;\n messenger: TransactionPayControllerMessenger;\n transaction: QuoteGasTransaction;\n}): Promise<{\n gasLimits: QuoteGasLimit[];\n totalGasEstimate: number;\n totalGasLimit: number;\n}> {\n const providedGasLimit = parseGasLimit(transaction.gas);\n\n if (providedGasLimit !== undefined) {\n log('Using provided gas limit', {\n chainId: transaction.chainId,\n gas: providedGasLimit,\n index: 0,\n to: transaction.to,\n });\n\n return {\n gasLimits: [\n {\n estimate: providedGasLimit,\n max: providedGasLimit,\n },\n ],\n totalGasEstimate: providedGasLimit,\n totalGasLimit: providedGasLimit,\n };\n }\n\n const gasLimitResult = await estimateGasLimit({\n chainId: transaction.chainId,\n data: transaction.data,\n fallbackGas,\n fallbackOnSimulationFailure,\n from: transaction.from,\n messenger,\n to: transaction.to,\n value: toHex(transaction.value ?? '0'),\n });\n\n if (gasLimitResult.usedFallback) {\n log('Gas estimate failed, using fallback', {\n chainId: transaction.chainId,\n error: gasLimitResult.error,\n index: 0,\n to: transaction.to,\n });\n }\n\n const gasLimit = {\n estimate: gasLimitResult.estimate,\n max: gasLimitResult.max,\n };\n\n return {\n gasLimits: [gasLimit],\n totalGasEstimate: gasLimit.estimate,\n totalGasLimit: gasLimit.max,\n };\n}\n\nfunction toBatchTransactionParams(\n transaction: QuoteGasTransaction,\n): BatchTransactionParams {\n return {\n data: transaction.data,\n gas: transaction.gas === undefined ? undefined : toHex(transaction.gas),\n maxFeePerGas: undefined,\n maxPriorityFeePerGas: undefined,\n to: transaction.to,\n value: toHex(transaction.value ?? '0'),\n };\n}\n\nfunction parseGasLimit(gas?: number | string): number | undefined {\n if (gas === undefined) {\n return undefined;\n }\n\n const parsedGas = new BigNumber(gas);\n\n if (\n !parsedGas.isFinite() ||\n parsedGas.isNaN() ||\n !parsedGas.isInteger() ||\n parsedGas.lte(0)\n ) {\n return undefined;\n }\n\n return parsedGas.toNumber();\n}\n"]}
1
+ {"version":3,"file":"quote-gas.mjs","sourceRoot":"","sources":["../../src/utils/quote-gas.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { BatchTransactionParams } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport type { TransactionPayControllerMessenger } from '..';\nimport { projectLogger } from '../logger';\nimport { getGasBuffer } from './feature-flags';\nimport { estimateGasLimit } from './gas';\n\nconst log = createModuleLogger(projectLogger, 'quote-gas');\n\nexport type QuoteGasTransaction = {\n chainId: Hex;\n data: Hex;\n from: Hex;\n gas?: number | string;\n to: Hex;\n value?: number | string | Hex;\n};\n\nexport type QuoteGasLimit = {\n estimate: number;\n max: number;\n};\n\nexport async function estimateQuoteGasLimits({\n fallbackGas,\n fallbackOnSimulationFailure = false,\n messenger,\n transactions,\n}: {\n fallbackGas?: {\n estimate: number;\n max: number;\n };\n fallbackOnSimulationFailure?: boolean;\n messenger: TransactionPayControllerMessenger;\n transactions: QuoteGasTransaction[];\n}): Promise<{\n batchGasLimit?: QuoteGasLimit;\n gasLimits: QuoteGasLimit[];\n is7702: boolean;\n requiresAuthorizationList?: true;\n totalGasEstimate: number;\n totalGasLimit: number;\n usedBatch: boolean;\n}> {\n if (transactions.length === 0) {\n throw new Error('Quote gas estimation requires at least one transaction');\n }\n\n const useBatch = transactions.length > 1;\n\n if (useBatch) {\n return {\n ...(await estimateQuoteGasLimitsBatch(transactions, messenger)),\n usedBatch: true,\n };\n }\n\n return {\n ...(await estimateQuoteGasLimitSingle({\n fallbackGas,\n fallbackOnSimulationFailure,\n messenger,\n transaction: transactions[0],\n })),\n is7702: false,\n usedBatch: false,\n };\n}\n\nasync function estimateQuoteGasLimitsBatch(\n transactions: QuoteGasTransaction[],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n batchGasLimit?: QuoteGasLimit;\n gasLimits: QuoteGasLimit[];\n is7702: boolean;\n requiresAuthorizationList?: true;\n totalGasEstimate: number;\n totalGasLimit: number;\n}> {\n const [firstTransaction] = transactions;\n const gasBuffer = getGasBuffer(messenger, firstTransaction.chainId);\n\n const paramGasLimits = transactions.map((transaction) =>\n parseGasLimit(transaction.gas),\n );\n\n const { gasLimits, requiresAuthorizationList } = await messenger.call(\n 'TransactionController:estimateGasBatch',\n {\n chainId: firstTransaction.chainId,\n from: firstTransaction.from,\n transactions: transactions.map(toBatchTransactionParams),\n },\n );\n\n if (gasLimits.length !== 1 && gasLimits.length !== transactions.length) {\n throw new Error('Unexpected batch gas limit count');\n }\n\n const bufferedGasLimits = gasLimits.map((gasLimit, index) => {\n const providedGasLimit = paramGasLimits[index];\n const providedGasWasPreserved =\n providedGasLimit !== undefined && providedGasLimit === gasLimit;\n\n // Per-entry batch results currently preserve validated input gas values\n // for transactions that already provided gas. If that contract changes\n // and batch estimation returns a different value, treat it as a fresh\n // estimate and apply the buffer. A single combined 7702 result is always\n // buffered because it is a fresh batch estimate.\n const useBuffer = gasLimits.length === 1 || !providedGasWasPreserved;\n const bufferedGas = Math.ceil(gasLimit * (useBuffer ? gasBuffer : 1));\n\n return {\n estimate: bufferedGas,\n max: bufferedGas,\n };\n });\n\n const totalGasLimit = bufferedGasLimits.reduce(\n (acc, gasLimit) => acc + gasLimit.max,\n 0,\n );\n const is7702 = bufferedGasLimits.length === 1;\n const batchGasLimit = is7702 ? bufferedGasLimits[0] : undefined;\n\n return {\n ...(batchGasLimit ? { batchGasLimit } : {}),\n gasLimits: bufferedGasLimits,\n is7702,\n ...(requiresAuthorizationList ? { requiresAuthorizationList } : {}),\n totalGasEstimate: totalGasLimit,\n totalGasLimit,\n };\n}\n\nasync function estimateQuoteGasLimitSingle({\n fallbackGas,\n fallbackOnSimulationFailure,\n messenger,\n transaction,\n}: {\n fallbackGas?: {\n estimate: number;\n max: number;\n };\n fallbackOnSimulationFailure: boolean;\n messenger: TransactionPayControllerMessenger;\n transaction: QuoteGasTransaction;\n}): Promise<{\n gasLimits: QuoteGasLimit[];\n totalGasEstimate: number;\n totalGasLimit: number;\n}> {\n const providedGasLimit = parseGasLimit(transaction.gas);\n\n if (providedGasLimit !== undefined) {\n log('Using provided gas limit', {\n chainId: transaction.chainId,\n gas: providedGasLimit,\n index: 0,\n to: transaction.to,\n });\n\n return {\n gasLimits: [\n {\n estimate: providedGasLimit,\n max: providedGasLimit,\n },\n ],\n totalGasEstimate: providedGasLimit,\n totalGasLimit: providedGasLimit,\n };\n }\n\n const gasLimitResult = await estimateGasLimit({\n chainId: transaction.chainId,\n data: transaction.data,\n fallbackGas,\n fallbackOnSimulationFailure,\n from: transaction.from,\n messenger,\n to: transaction.to,\n value: toHex(transaction.value ?? '0'),\n });\n\n if (gasLimitResult.usedFallback) {\n log('Gas estimate failed, using fallback', {\n chainId: transaction.chainId,\n error: gasLimitResult.error,\n index: 0,\n to: transaction.to,\n });\n }\n\n const gasLimit = {\n estimate: gasLimitResult.estimate,\n max: gasLimitResult.max,\n };\n\n return {\n gasLimits: [gasLimit],\n totalGasEstimate: gasLimit.estimate,\n totalGasLimit: gasLimit.max,\n };\n}\n\nfunction toBatchTransactionParams(\n transaction: QuoteGasTransaction,\n): BatchTransactionParams {\n return {\n data: transaction.data,\n gas: transaction.gas === undefined ? undefined : toHex(transaction.gas),\n maxFeePerGas: undefined,\n maxPriorityFeePerGas: undefined,\n to: transaction.to,\n value: toHex(transaction.value ?? '0'),\n };\n}\n\nfunction parseGasLimit(gas?: number | string): number | undefined {\n if (gas === undefined) {\n return undefined;\n }\n\n const parsedGas = new BigNumber(gas);\n\n if (\n !parsedGas.isFinite() ||\n parsedGas.isNaN() ||\n !parsedGas.isInteger() ||\n parsedGas.lte(0)\n ) {\n return undefined;\n }\n\n return parsedGas.toNumber();\n}\n"]}
@@ -5,6 +5,7 @@ const transaction_controller_1 = require("@metamask/transaction-controller");
5
5
  const utils_1 = require("@metamask/utils");
6
6
  const constants_1 = require("../constants.cjs");
7
7
  const logger_1 = require("../logger.cjs");
8
+ const _7702_1 = require("./7702.cjs");
8
9
  const strategy_1 = require("./strategy.cjs");
9
10
  const token_1 = require("./token.cjs");
10
11
  const totals_1 = require("./totals.cjs");
@@ -27,8 +28,8 @@ async function updateQuotes(request) {
27
28
  return false;
28
29
  }
29
30
  log('Updating quotes', { transactionId });
30
- const { isMaxAmount, isPostQuote, isHyperliquidSource, paymentToken: originalPaymentToken, refundTo, sourceAmounts, tokens, } = transactionData;
31
- const from = transaction.txParams.from;
31
+ const { accountOverride, isMaxAmount, isPostQuote, isHyperliquidSource, paymentToken: originalPaymentToken, refundTo, sourceAmounts, tokens, } = transactionData;
32
+ const from = accountOverride ?? transaction.txParams.from;
32
33
  updateTransactionData(transactionId, (data) => {
33
34
  data.isLoading = true;
34
35
  });
@@ -51,7 +52,8 @@ async function updateQuotes(request) {
51
52
  tokens,
52
53
  transactionId,
53
54
  });
54
- const { batchTransactions, quotes } = await getQuotes(transaction, requests, getStrategies, messenger, transactionData.fiatPayment?.selectedPaymentMethodId);
55
+ const supports7702 = (0, _7702_1.accountSupports7702)(messenger, from);
56
+ const { batchTransactions, quotes } = await getQuotes(transaction, requests, supports7702, getStrategies, messenger, transactionData.fiatPayment?.selectedPaymentMethodId);
55
57
  const totals = (0, totals_1.calculateTotals)({
56
58
  isMaxAmount,
57
59
  messenger,
@@ -285,12 +287,13 @@ async function refreshPaymentTokenBalance({ from, messenger, paymentToken, trans
285
287
  *
286
288
  * @param transaction - Transaction metadata.
287
289
  * @param requests - Quote requests.
290
+ * @param isAccountEIP7702Compatible - Whether the account supports EIP-7702.
288
291
  * @param getStrategies - Callback to get ordered strategy names for a transaction.
289
292
  * @param messenger - Controller messenger.
290
293
  * @param fiatPaymentMethod - Selected fiat payment method ID, if applicable.
291
294
  * @returns An object containing batch transactions and quotes.
292
295
  */
293
- async function getQuotes(transaction, requests, getStrategies, messenger, fiatPaymentMethod) {
296
+ async function getQuotes(transaction, requests, isAccountEIP7702Compatible, getStrategies, messenger, fiatPaymentMethod) {
294
297
  const { id: transactionId } = transaction;
295
298
  const strategies = (0, strategy_1.getStrategiesByName)(getStrategies(transaction), (strategyName) => {
296
299
  log('Skipping unknown strategy', {
@@ -305,6 +308,7 @@ async function getQuotes(transaction, requests, getStrategies, messenger, fiatPa
305
308
  };
306
309
  }
307
310
  const request = {
311
+ accountSupports7702: isAccountEIP7702Compatible,
308
312
  fiatPaymentMethod,
309
313
  messenger,
310
314
  requests,
@@ -312,7 +316,8 @@ async function getQuotes(transaction, requests, getStrategies, messenger, fiatPa
312
316
  };
313
317
  for (const { name, strategy } of strategies) {
314
318
  try {
315
- if (strategy.supports && !strategy.supports(request)) {
319
+ const support = await (0, strategy_1.checkStrategySupport)(strategy, request);
320
+ if (!support) {
316
321
  log('Strategy does not support request', {
317
322
  strategy: name,
318
323
  transactionId,
@@ -324,6 +329,18 @@ async function getQuotes(transaction, requests, getStrategies, messenger, fiatPa
324
329
  log('Strategy returned no quotes', { strategy: name, transactionId });
325
330
  continue;
326
331
  }
332
+ const quoteSupport = await (0, strategy_1.checkStrategyQuoteSupport)(strategy, {
333
+ messenger,
334
+ quotes,
335
+ transaction,
336
+ });
337
+ if (!quoteSupport) {
338
+ log('Strategy does not support quotes', {
339
+ strategy: name,
340
+ transactionId,
341
+ });
342
+ continue;
343
+ }
327
344
  log('Updated', { transactionId, quotes });
328
345
  const batchTransactions = strategy.getBatchTransactions
329
346
  ? await strategy.getBatchTransactions({
@@ -1 +1 @@
1
- {"version":3,"file":"quotes.cjs","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 { TransactionPayStrategy } from '../constants';\nimport { projectLogger } from '../logger';\nimport type {\n QuoteRequest,\n TransactionData,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n TransactionPayRequiredToken,\n TransactionPaySourceAmount,\n TransactionPayTotals,\n TransactionPaymentToken,\n UpdateTransactionDataCallback,\n} from '../types';\nimport { getStrategiesByName, getStrategyByName } from './strategy';\nimport {\n computeTokenAmounts,\n getLiveTokenBalance,\n getTokenFiatRate,\n} from './token';\nimport { calculateTotals } from './totals';\nimport { getTransaction, updateTransaction } from './transaction';\n\nconst DEFAULT_REFRESH_INTERVAL = 30 * 1000; // 30 Seconds\n\nconst log = createModuleLogger(projectLogger, 'quotes');\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 * @param request - Request parameters.\n * @returns Boolean indicating if the quotes were updated.\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 isMaxAmount,\n isPostQuote,\n isHyperliquidSource,\n paymentToken: originalPaymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n } = transactionData;\n\n const from = transaction.txParams.from as Hex;\n\n updateTransactionData(transactionId, (data) => {\n data.isLoading = true;\n });\n\n try {\n const paymentToken = await refreshPaymentTokenBalance({\n from,\n messenger,\n paymentToken: originalPaymentToken,\n transactionId,\n updateTransactionData,\n });\n\n const requests = buildQuoteRequests({\n from,\n isMaxAmount: isMaxAmount ?? false,\n isPostQuote,\n isHyperliquidSource,\n paymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n transactionId,\n });\n\n const { batchTransactions, quotes } = await getQuotes(\n transaction,\n requests,\n getStrategies,\n messenger,\n transactionData.fiatPayment?.selectedPaymentMethodId,\n );\n\n const totals = calculateTotals({\n isMaxAmount,\n messenger,\n quotes: quotes as TransactionPayQuote<unknown>[],\n tokens,\n transaction,\n });\n\n log('Calculated totals', { transactionId, totals });\n\n syncTransaction({\n batchTransactions,\n isPostQuote,\n messenger: messenger as never,\n paymentToken,\n totals,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n data.quotes = quotes as never;\n data.quotesLastUpdated = Date.now();\n data.totals = totals;\n });\n } finally {\n updateTransactionData(transactionId, (data) => {\n data.isLoading = false;\n });\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.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.totals - Calculated totals.\n * @param request.transactionId - ID of the transaction to sync.\n */\nfunction syncTransaction({\n batchTransactions,\n isPostQuote,\n messenger,\n paymentToken,\n totals,\n transactionId,\n}: {\n batchTransactions: BatchTransaction[];\n isPostQuote?: boolean;\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\n totals: TransactionPayTotals;\n transactionId: string;\n}): void {\n if (!paymentToken) {\n return;\n }\n\n updateTransaction(\n {\n transactionId,\n messenger: messenger as never,\n note: 'Update transaction pay data',\n },\n (tx: TransactionMeta) => {\n tx.batchTransactions = batchTransactions;\n tx.batchTransactionsOptions = {};\n\n tx.metamaskPay = {\n bridgeFeeFiat: totals.fees.provider.usd,\n chainId: paymentToken.chainId,\n isPostQuote,\n networkFeeFiat: totals.fees.sourceNetwork.estimate.usd,\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 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\n/**\n * Build quote requests required to retrieve quotes.\n *\n * @param request - Request parameters.\n * @param request.from - Address from which the transaction is sent.\n * @param request.isMaxAmount - Whether the transaction is a maximum amount transaction.\n * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.\n * @param request.isPostQuote - Whether this is a post-quote flow.\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 from,\n isMaxAmount,\n isPostQuote,\n isHyperliquidSource,\n paymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n transactionId,\n}: {\n from: Hex;\n isMaxAmount: boolean;\n isPostQuote?: boolean;\n isHyperliquidSource?: boolean;\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 from,\n isMaxAmount,\n isHyperliquidSource,\n destinationToken: paymentToken,\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 from,\n isMaxAmount,\n sourceBalanceRaw: paymentToken.balanceRaw,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n sourceChainId: paymentToken.chainId,\n sourceTokenAddress: paymentToken.address,\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.from - Address from which the transaction is sent.\n * @param request.isMaxAmount - Whether the transaction is a maximum amount transaction.\n * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.\n * @param request.destinationToken - Destination token (paymentToken in post-quote mode).\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 from,\n isMaxAmount,\n isHyperliquidSource,\n destinationToken,\n refundTo,\n sourceAmounts,\n transactionId,\n}: {\n from: Hex;\n isMaxAmount: boolean;\n isHyperliquidSource?: boolean;\n destinationToken: TransactionPaymentToken;\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 from,\n isMaxAmount,\n isPostQuote: true,\n isHyperliquidSource,\n refundTo,\n sourceBalanceRaw: sourceAmount.sourceBalanceRaw,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n sourceChainId: sourceAmount.sourceChainId,\n sourceTokenAddress: sourceAmount.sourceTokenAddress,\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 transactionId,\n updateTransactionData,\n}: {\n from: Hex;\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\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 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 requests - Quote requests.\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 * @returns An object containing batch transactions and quotes.\n */\nasync function getQuotes(\n transaction: TransactionMeta,\n requests: QuoteRequest[],\n getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[],\n messenger: TransactionPayControllerMessenger,\n fiatPaymentMethod?: string,\n): Promise<{\n batchTransactions: BatchTransaction[];\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) {\n return {\n batchTransactions: [],\n quotes: [],\n };\n }\n\n const request = {\n fiatPaymentMethod,\n messenger,\n requests,\n transaction,\n };\n\n for (const { name, strategy } of strategies) {\n try {\n if (strategy.supports && !strategy.supports(request)) {\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 log('Updated', { transactionId, quotes });\n\n const batchTransactions = strategy.getBatchTransactions\n ? await strategy.getBatchTransactions({\n messenger,\n quotes,\n })\n : [];\n\n log('Batch transactions', { transactionId, batchTransactions });\n\n return {\n batchTransactions,\n quotes,\n };\n } catch (error) {\n log('Strategy failed, trying next', {\n error,\n strategy: name,\n transactionId,\n });\n continue;\n }\n }\n\n log('No quotes available', { transactionId });\n\n return {\n batchTransactions: [],\n quotes: [],\n };\n}\n"]}
1
+ {"version":3,"file":"quotes.cjs","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 { TransactionPayStrategy } from '../constants';\nimport { projectLogger } from '../logger';\nimport type {\n QuoteRequest,\n TransactionData,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n TransactionPayRequiredToken,\n TransactionPaySourceAmount,\n TransactionPayTotals,\n TransactionPaymentToken,\n UpdateTransactionDataCallback,\n} from '../types';\nimport { accountSupports7702 } from './7702';\nimport {\n checkStrategyQuoteSupport,\n checkStrategySupport,\n getStrategiesByName,\n getStrategyByName,\n} from './strategy';\nimport {\n computeTokenAmounts,\n getLiveTokenBalance,\n getTokenFiatRate,\n} from './token';\nimport { calculateTotals } from './totals';\nimport { getTransaction, updateTransaction } from './transaction';\n\nconst DEFAULT_REFRESH_INTERVAL = 30 * 1000; // 30 Seconds\n\nconst log = createModuleLogger(projectLogger, 'quotes');\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 * @param request - Request parameters.\n * @returns Boolean indicating if the quotes were updated.\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 isMaxAmount,\n isPostQuote,\n isHyperliquidSource,\n paymentToken: originalPaymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n } = transactionData;\n\n const from = accountOverride ?? (transaction.txParams.from as Hex);\n\n updateTransactionData(transactionId, (data) => {\n data.isLoading = true;\n });\n\n try {\n const paymentToken = await refreshPaymentTokenBalance({\n from,\n messenger,\n paymentToken: originalPaymentToken,\n transactionId,\n updateTransactionData,\n });\n\n const requests = buildQuoteRequests({\n from,\n isMaxAmount: isMaxAmount ?? false,\n isPostQuote,\n isHyperliquidSource,\n paymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n transactionId,\n });\n\n const supports7702 = accountSupports7702(messenger, from);\n\n const { batchTransactions, quotes } = await getQuotes(\n transaction,\n requests,\n supports7702,\n getStrategies,\n messenger,\n transactionData.fiatPayment?.selectedPaymentMethodId,\n );\n\n const totals = calculateTotals({\n isMaxAmount,\n messenger,\n quotes: quotes as TransactionPayQuote<unknown>[],\n tokens,\n transaction,\n });\n\n log('Calculated totals', { transactionId, totals });\n\n syncTransaction({\n batchTransactions,\n isPostQuote,\n messenger: messenger as never,\n paymentToken,\n totals,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n data.quotes = quotes as never;\n data.quotesLastUpdated = Date.now();\n data.totals = totals;\n });\n } finally {\n updateTransactionData(transactionId, (data) => {\n data.isLoading = false;\n });\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.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.totals - Calculated totals.\n * @param request.transactionId - ID of the transaction to sync.\n */\nfunction syncTransaction({\n batchTransactions,\n isPostQuote,\n messenger,\n paymentToken,\n totals,\n transactionId,\n}: {\n batchTransactions: BatchTransaction[];\n isPostQuote?: boolean;\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\n totals: TransactionPayTotals;\n transactionId: string;\n}): void {\n if (!paymentToken) {\n return;\n }\n\n updateTransaction(\n {\n transactionId,\n messenger: messenger as never,\n note: 'Update transaction pay data',\n },\n (tx: TransactionMeta) => {\n tx.batchTransactions = batchTransactions;\n tx.batchTransactionsOptions = {};\n\n tx.metamaskPay = {\n bridgeFeeFiat: totals.fees.provider.usd,\n chainId: paymentToken.chainId,\n isPostQuote,\n networkFeeFiat: totals.fees.sourceNetwork.estimate.usd,\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 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\n/**\n * Build quote requests required to retrieve quotes.\n *\n * @param request - Request parameters.\n * @param request.from - Address from which the transaction is sent.\n * @param request.isMaxAmount - Whether the transaction is a maximum amount transaction.\n * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.\n * @param request.isPostQuote - Whether this is a post-quote flow.\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 from,\n isMaxAmount,\n isPostQuote,\n isHyperliquidSource,\n paymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n transactionId,\n}: {\n from: Hex;\n isMaxAmount: boolean;\n isPostQuote?: boolean;\n isHyperliquidSource?: boolean;\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 from,\n isMaxAmount,\n isHyperliquidSource,\n destinationToken: paymentToken,\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 from,\n isMaxAmount,\n sourceBalanceRaw: paymentToken.balanceRaw,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n sourceChainId: paymentToken.chainId,\n sourceTokenAddress: paymentToken.address,\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.from - Address from which the transaction is sent.\n * @param request.isMaxAmount - Whether the transaction is a maximum amount transaction.\n * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.\n * @param request.destinationToken - Destination token (paymentToken in post-quote mode).\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 from,\n isMaxAmount,\n isHyperliquidSource,\n destinationToken,\n refundTo,\n sourceAmounts,\n transactionId,\n}: {\n from: Hex;\n isMaxAmount: boolean;\n isHyperliquidSource?: boolean;\n destinationToken: TransactionPaymentToken;\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 from,\n isMaxAmount,\n isPostQuote: true,\n isHyperliquidSource,\n refundTo,\n sourceBalanceRaw: sourceAmount.sourceBalanceRaw,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n sourceChainId: sourceAmount.sourceChainId,\n sourceTokenAddress: sourceAmount.sourceTokenAddress,\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 transactionId,\n updateTransactionData,\n}: {\n from: Hex;\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\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 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 requests - Quote requests.\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 * @returns An object containing batch transactions and quotes.\n */\nasync function getQuotes(\n transaction: TransactionMeta,\n requests: QuoteRequest[],\n isAccountEIP7702Compatible: boolean,\n getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[],\n messenger: TransactionPayControllerMessenger,\n fiatPaymentMethod?: string,\n): Promise<{\n batchTransactions: BatchTransaction[];\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) {\n return {\n batchTransactions: [],\n quotes: [],\n };\n }\n\n const request = {\n accountSupports7702: isAccountEIP7702Compatible,\n fiatPaymentMethod,\n messenger,\n requests,\n transaction,\n };\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 quoteSupport = await checkStrategyQuoteSupport(strategy, {\n messenger,\n quotes,\n transaction,\n });\n\n if (!quoteSupport) {\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 })\n : [];\n\n log('Batch transactions', { transactionId, batchTransactions });\n\n return {\n batchTransactions,\n quotes,\n };\n } catch (error) {\n log('Strategy failed, trying next', {\n error,\n strategy: name,\n transactionId,\n });\n continue;\n }\n }\n\n log('No quotes available', { transactionId });\n\n return {\n batchTransactions: [],\n quotes: [],\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"quotes.d.cts","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AAIxE,OAAO,EAAE,sBAAsB,EAAE,yBAAqB;AAEtD,OAAO,KAAK,EAEV,eAAe,EACf,iCAAiC,EAMjC,6BAA6B,EAC9B,qBAAiB;AAclB,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;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAiGlB;AAuDD;;;;;;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,CAuCf"}
1
+ {"version":3,"file":"quotes.d.cts","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AAIxE,OAAO,EAAE,sBAAsB,EAAE,yBAAqB;AAEtD,OAAO,KAAK,EAEV,eAAe,EACf,iCAAiC,EAMjC,6BAA6B,EAC9B,qBAAiB;AAoBlB,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;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAqGlB;AAuDD;;;;;;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,CAuCf"}
@@ -1 +1 @@
1
- {"version":3,"file":"quotes.d.mts","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AAIxE,OAAO,EAAE,sBAAsB,EAAE,yBAAqB;AAEtD,OAAO,KAAK,EAEV,eAAe,EACf,iCAAiC,EAMjC,6BAA6B,EAC9B,qBAAiB;AAclB,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;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAiGlB;AAuDD;;;;;;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,CAuCf"}
1
+ {"version":3,"file":"quotes.d.mts","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AAIxE,OAAO,EAAE,sBAAsB,EAAE,yBAAqB;AAEtD,OAAO,KAAK,EAEV,eAAe,EACf,iCAAiC,EAMjC,6BAA6B,EAC9B,qBAAiB;AAoBlB,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;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAqGlB;AAuDD;;;;;;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,CAuCf"}
@@ -2,7 +2,8 @@ import { TransactionStatus } from "@metamask/transaction-controller";
2
2
  import { createModuleLogger } from "@metamask/utils";
3
3
  import { TransactionPayStrategy } from "../constants.mjs";
4
4
  import { projectLogger } from "../logger.mjs";
5
- import { getStrategiesByName, getStrategyByName } from "./strategy.mjs";
5
+ import { accountSupports7702 } from "./7702.mjs";
6
+ import { checkStrategyQuoteSupport, checkStrategySupport, getStrategiesByName, getStrategyByName } from "./strategy.mjs";
6
7
  import { computeTokenAmounts, getLiveTokenBalance, getTokenFiatRate } from "./token.mjs";
7
8
  import { calculateTotals } from "./totals.mjs";
8
9
  import { getTransaction, updateTransaction } from "./transaction.mjs";
@@ -24,8 +25,8 @@ export async function updateQuotes(request) {
24
25
  return false;
25
26
  }
26
27
  log('Updating quotes', { transactionId });
27
- const { isMaxAmount, isPostQuote, isHyperliquidSource, paymentToken: originalPaymentToken, refundTo, sourceAmounts, tokens, } = transactionData;
28
- const from = transaction.txParams.from;
28
+ const { accountOverride, isMaxAmount, isPostQuote, isHyperliquidSource, paymentToken: originalPaymentToken, refundTo, sourceAmounts, tokens, } = transactionData;
29
+ const from = accountOverride ?? transaction.txParams.from;
29
30
  updateTransactionData(transactionId, (data) => {
30
31
  data.isLoading = true;
31
32
  });
@@ -48,7 +49,8 @@ export async function updateQuotes(request) {
48
49
  tokens,
49
50
  transactionId,
50
51
  });
51
- const { batchTransactions, quotes } = await getQuotes(transaction, requests, getStrategies, messenger, transactionData.fiatPayment?.selectedPaymentMethodId);
52
+ const supports7702 = accountSupports7702(messenger, from);
53
+ const { batchTransactions, quotes } = await getQuotes(transaction, requests, supports7702, getStrategies, messenger, transactionData.fiatPayment?.selectedPaymentMethodId);
52
54
  const totals = calculateTotals({
53
55
  isMaxAmount,
54
56
  messenger,
@@ -280,12 +282,13 @@ async function refreshPaymentTokenBalance({ from, messenger, paymentToken, trans
280
282
  *
281
283
  * @param transaction - Transaction metadata.
282
284
  * @param requests - Quote requests.
285
+ * @param isAccountEIP7702Compatible - Whether the account supports EIP-7702.
283
286
  * @param getStrategies - Callback to get ordered strategy names for a transaction.
284
287
  * @param messenger - Controller messenger.
285
288
  * @param fiatPaymentMethod - Selected fiat payment method ID, if applicable.
286
289
  * @returns An object containing batch transactions and quotes.
287
290
  */
288
- async function getQuotes(transaction, requests, getStrategies, messenger, fiatPaymentMethod) {
291
+ async function getQuotes(transaction, requests, isAccountEIP7702Compatible, getStrategies, messenger, fiatPaymentMethod) {
289
292
  const { id: transactionId } = transaction;
290
293
  const strategies = getStrategiesByName(getStrategies(transaction), (strategyName) => {
291
294
  log('Skipping unknown strategy', {
@@ -300,6 +303,7 @@ async function getQuotes(transaction, requests, getStrategies, messenger, fiatPa
300
303
  };
301
304
  }
302
305
  const request = {
306
+ accountSupports7702: isAccountEIP7702Compatible,
303
307
  fiatPaymentMethod,
304
308
  messenger,
305
309
  requests,
@@ -307,7 +311,8 @@ async function getQuotes(transaction, requests, getStrategies, messenger, fiatPa
307
311
  };
308
312
  for (const { name, strategy } of strategies) {
309
313
  try {
310
- if (strategy.supports && !strategy.supports(request)) {
314
+ const support = await checkStrategySupport(strategy, request);
315
+ if (!support) {
311
316
  log('Strategy does not support request', {
312
317
  strategy: name,
313
318
  transactionId,
@@ -319,6 +324,18 @@ async function getQuotes(transaction, requests, getStrategies, messenger, fiatPa
319
324
  log('Strategy returned no quotes', { strategy: name, transactionId });
320
325
  continue;
321
326
  }
327
+ const quoteSupport = await checkStrategyQuoteSupport(strategy, {
328
+ messenger,
329
+ quotes,
330
+ transaction,
331
+ });
332
+ if (!quoteSupport) {
333
+ log('Strategy does not support quotes', {
334
+ strategy: name,
335
+ transactionId,
336
+ });
337
+ continue;
338
+ }
322
339
  log('Updated', { transactionId, quotes });
323
340
  const batchTransactions = strategy.getBatchTransactions
324
341
  ? await strategy.getBatchTransactions({
@@ -1 +1 @@
1
- {"version":3,"file":"quotes.mjs","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 { TransactionPayStrategy } from '../constants';\nimport { projectLogger } from '../logger';\nimport type {\n QuoteRequest,\n TransactionData,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n TransactionPayRequiredToken,\n TransactionPaySourceAmount,\n TransactionPayTotals,\n TransactionPaymentToken,\n UpdateTransactionDataCallback,\n} from '../types';\nimport { getStrategiesByName, getStrategyByName } from './strategy';\nimport {\n computeTokenAmounts,\n getLiveTokenBalance,\n getTokenFiatRate,\n} from './token';\nimport { calculateTotals } from './totals';\nimport { getTransaction, updateTransaction } from './transaction';\n\nconst DEFAULT_REFRESH_INTERVAL = 30 * 1000; // 30 Seconds\n\nconst log = createModuleLogger(projectLogger, 'quotes');\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 * @param request - Request parameters.\n * @returns Boolean indicating if the quotes were updated.\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 isMaxAmount,\n isPostQuote,\n isHyperliquidSource,\n paymentToken: originalPaymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n } = transactionData;\n\n const from = transaction.txParams.from as Hex;\n\n updateTransactionData(transactionId, (data) => {\n data.isLoading = true;\n });\n\n try {\n const paymentToken = await refreshPaymentTokenBalance({\n from,\n messenger,\n paymentToken: originalPaymentToken,\n transactionId,\n updateTransactionData,\n });\n\n const requests = buildQuoteRequests({\n from,\n isMaxAmount: isMaxAmount ?? false,\n isPostQuote,\n isHyperliquidSource,\n paymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n transactionId,\n });\n\n const { batchTransactions, quotes } = await getQuotes(\n transaction,\n requests,\n getStrategies,\n messenger,\n transactionData.fiatPayment?.selectedPaymentMethodId,\n );\n\n const totals = calculateTotals({\n isMaxAmount,\n messenger,\n quotes: quotes as TransactionPayQuote<unknown>[],\n tokens,\n transaction,\n });\n\n log('Calculated totals', { transactionId, totals });\n\n syncTransaction({\n batchTransactions,\n isPostQuote,\n messenger: messenger as never,\n paymentToken,\n totals,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n data.quotes = quotes as never;\n data.quotesLastUpdated = Date.now();\n data.totals = totals;\n });\n } finally {\n updateTransactionData(transactionId, (data) => {\n data.isLoading = false;\n });\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.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.totals - Calculated totals.\n * @param request.transactionId - ID of the transaction to sync.\n */\nfunction syncTransaction({\n batchTransactions,\n isPostQuote,\n messenger,\n paymentToken,\n totals,\n transactionId,\n}: {\n batchTransactions: BatchTransaction[];\n isPostQuote?: boolean;\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\n totals: TransactionPayTotals;\n transactionId: string;\n}): void {\n if (!paymentToken) {\n return;\n }\n\n updateTransaction(\n {\n transactionId,\n messenger: messenger as never,\n note: 'Update transaction pay data',\n },\n (tx: TransactionMeta) => {\n tx.batchTransactions = batchTransactions;\n tx.batchTransactionsOptions = {};\n\n tx.metamaskPay = {\n bridgeFeeFiat: totals.fees.provider.usd,\n chainId: paymentToken.chainId,\n isPostQuote,\n networkFeeFiat: totals.fees.sourceNetwork.estimate.usd,\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 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\n/**\n * Build quote requests required to retrieve quotes.\n *\n * @param request - Request parameters.\n * @param request.from - Address from which the transaction is sent.\n * @param request.isMaxAmount - Whether the transaction is a maximum amount transaction.\n * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.\n * @param request.isPostQuote - Whether this is a post-quote flow.\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 from,\n isMaxAmount,\n isPostQuote,\n isHyperliquidSource,\n paymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n transactionId,\n}: {\n from: Hex;\n isMaxAmount: boolean;\n isPostQuote?: boolean;\n isHyperliquidSource?: boolean;\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 from,\n isMaxAmount,\n isHyperliquidSource,\n destinationToken: paymentToken,\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 from,\n isMaxAmount,\n sourceBalanceRaw: paymentToken.balanceRaw,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n sourceChainId: paymentToken.chainId,\n sourceTokenAddress: paymentToken.address,\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.from - Address from which the transaction is sent.\n * @param request.isMaxAmount - Whether the transaction is a maximum amount transaction.\n * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.\n * @param request.destinationToken - Destination token (paymentToken in post-quote mode).\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 from,\n isMaxAmount,\n isHyperliquidSource,\n destinationToken,\n refundTo,\n sourceAmounts,\n transactionId,\n}: {\n from: Hex;\n isMaxAmount: boolean;\n isHyperliquidSource?: boolean;\n destinationToken: TransactionPaymentToken;\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 from,\n isMaxAmount,\n isPostQuote: true,\n isHyperliquidSource,\n refundTo,\n sourceBalanceRaw: sourceAmount.sourceBalanceRaw,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n sourceChainId: sourceAmount.sourceChainId,\n sourceTokenAddress: sourceAmount.sourceTokenAddress,\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 transactionId,\n updateTransactionData,\n}: {\n from: Hex;\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\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 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 requests - Quote requests.\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 * @returns An object containing batch transactions and quotes.\n */\nasync function getQuotes(\n transaction: TransactionMeta,\n requests: QuoteRequest[],\n getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[],\n messenger: TransactionPayControllerMessenger,\n fiatPaymentMethod?: string,\n): Promise<{\n batchTransactions: BatchTransaction[];\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) {\n return {\n batchTransactions: [],\n quotes: [],\n };\n }\n\n const request = {\n fiatPaymentMethod,\n messenger,\n requests,\n transaction,\n };\n\n for (const { name, strategy } of strategies) {\n try {\n if (strategy.supports && !strategy.supports(request)) {\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 log('Updated', { transactionId, quotes });\n\n const batchTransactions = strategy.getBatchTransactions\n ? await strategy.getBatchTransactions({\n messenger,\n quotes,\n })\n : [];\n\n log('Batch transactions', { transactionId, batchTransactions });\n\n return {\n batchTransactions,\n quotes,\n };\n } catch (error) {\n log('Strategy failed, trying next', {\n error,\n strategy: name,\n transactionId,\n });\n continue;\n }\n }\n\n log('No quotes available', { transactionId });\n\n return {\n batchTransactions: [],\n quotes: [],\n };\n}\n"]}
1
+ {"version":3,"file":"quotes.mjs","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 { TransactionPayStrategy } from '../constants';\nimport { projectLogger } from '../logger';\nimport type {\n QuoteRequest,\n TransactionData,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n TransactionPayRequiredToken,\n TransactionPaySourceAmount,\n TransactionPayTotals,\n TransactionPaymentToken,\n UpdateTransactionDataCallback,\n} from '../types';\nimport { accountSupports7702 } from './7702';\nimport {\n checkStrategyQuoteSupport,\n checkStrategySupport,\n getStrategiesByName,\n getStrategyByName,\n} from './strategy';\nimport {\n computeTokenAmounts,\n getLiveTokenBalance,\n getTokenFiatRate,\n} from './token';\nimport { calculateTotals } from './totals';\nimport { getTransaction, updateTransaction } from './transaction';\n\nconst DEFAULT_REFRESH_INTERVAL = 30 * 1000; // 30 Seconds\n\nconst log = createModuleLogger(projectLogger, 'quotes');\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 * @param request - Request parameters.\n * @returns Boolean indicating if the quotes were updated.\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 isMaxAmount,\n isPostQuote,\n isHyperliquidSource,\n paymentToken: originalPaymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n } = transactionData;\n\n const from = accountOverride ?? (transaction.txParams.from as Hex);\n\n updateTransactionData(transactionId, (data) => {\n data.isLoading = true;\n });\n\n try {\n const paymentToken = await refreshPaymentTokenBalance({\n from,\n messenger,\n paymentToken: originalPaymentToken,\n transactionId,\n updateTransactionData,\n });\n\n const requests = buildQuoteRequests({\n from,\n isMaxAmount: isMaxAmount ?? false,\n isPostQuote,\n isHyperliquidSource,\n paymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n transactionId,\n });\n\n const supports7702 = accountSupports7702(messenger, from);\n\n const { batchTransactions, quotes } = await getQuotes(\n transaction,\n requests,\n supports7702,\n getStrategies,\n messenger,\n transactionData.fiatPayment?.selectedPaymentMethodId,\n );\n\n const totals = calculateTotals({\n isMaxAmount,\n messenger,\n quotes: quotes as TransactionPayQuote<unknown>[],\n tokens,\n transaction,\n });\n\n log('Calculated totals', { transactionId, totals });\n\n syncTransaction({\n batchTransactions,\n isPostQuote,\n messenger: messenger as never,\n paymentToken,\n totals,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n data.quotes = quotes as never;\n data.quotesLastUpdated = Date.now();\n data.totals = totals;\n });\n } finally {\n updateTransactionData(transactionId, (data) => {\n data.isLoading = false;\n });\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.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.totals - Calculated totals.\n * @param request.transactionId - ID of the transaction to sync.\n */\nfunction syncTransaction({\n batchTransactions,\n isPostQuote,\n messenger,\n paymentToken,\n totals,\n transactionId,\n}: {\n batchTransactions: BatchTransaction[];\n isPostQuote?: boolean;\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\n totals: TransactionPayTotals;\n transactionId: string;\n}): void {\n if (!paymentToken) {\n return;\n }\n\n updateTransaction(\n {\n transactionId,\n messenger: messenger as never,\n note: 'Update transaction pay data',\n },\n (tx: TransactionMeta) => {\n tx.batchTransactions = batchTransactions;\n tx.batchTransactionsOptions = {};\n\n tx.metamaskPay = {\n bridgeFeeFiat: totals.fees.provider.usd,\n chainId: paymentToken.chainId,\n isPostQuote,\n networkFeeFiat: totals.fees.sourceNetwork.estimate.usd,\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 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\n/**\n * Build quote requests required to retrieve quotes.\n *\n * @param request - Request parameters.\n * @param request.from - Address from which the transaction is sent.\n * @param request.isMaxAmount - Whether the transaction is a maximum amount transaction.\n * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.\n * @param request.isPostQuote - Whether this is a post-quote flow.\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 from,\n isMaxAmount,\n isPostQuote,\n isHyperliquidSource,\n paymentToken,\n refundTo,\n sourceAmounts,\n tokens,\n transactionId,\n}: {\n from: Hex;\n isMaxAmount: boolean;\n isPostQuote?: boolean;\n isHyperliquidSource?: boolean;\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 from,\n isMaxAmount,\n isHyperliquidSource,\n destinationToken: paymentToken,\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 from,\n isMaxAmount,\n sourceBalanceRaw: paymentToken.balanceRaw,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n sourceChainId: paymentToken.chainId,\n sourceTokenAddress: paymentToken.address,\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.from - Address from which the transaction is sent.\n * @param request.isMaxAmount - Whether the transaction is a maximum amount transaction.\n * @param request.isHyperliquidSource - Whether the source of funds is HyperLiquid.\n * @param request.destinationToken - Destination token (paymentToken in post-quote mode).\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 from,\n isMaxAmount,\n isHyperliquidSource,\n destinationToken,\n refundTo,\n sourceAmounts,\n transactionId,\n}: {\n from: Hex;\n isMaxAmount: boolean;\n isHyperliquidSource?: boolean;\n destinationToken: TransactionPaymentToken;\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 from,\n isMaxAmount,\n isPostQuote: true,\n isHyperliquidSource,\n refundTo,\n sourceBalanceRaw: sourceAmount.sourceBalanceRaw,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n sourceChainId: sourceAmount.sourceChainId,\n sourceTokenAddress: sourceAmount.sourceTokenAddress,\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 transactionId,\n updateTransactionData,\n}: {\n from: Hex;\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\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 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 requests - Quote requests.\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 * @returns An object containing batch transactions and quotes.\n */\nasync function getQuotes(\n transaction: TransactionMeta,\n requests: QuoteRequest[],\n isAccountEIP7702Compatible: boolean,\n getStrategies: (transaction: TransactionMeta) => TransactionPayStrategy[],\n messenger: TransactionPayControllerMessenger,\n fiatPaymentMethod?: string,\n): Promise<{\n batchTransactions: BatchTransaction[];\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) {\n return {\n batchTransactions: [],\n quotes: [],\n };\n }\n\n const request = {\n accountSupports7702: isAccountEIP7702Compatible,\n fiatPaymentMethod,\n messenger,\n requests,\n transaction,\n };\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 quoteSupport = await checkStrategyQuoteSupport(strategy, {\n messenger,\n quotes,\n transaction,\n });\n\n if (!quoteSupport) {\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 })\n : [];\n\n log('Batch transactions', { transactionId, batchTransactions });\n\n return {\n batchTransactions,\n quotes,\n };\n } catch (error) {\n log('Strategy failed, trying next', {\n error,\n strategy: name,\n transactionId,\n });\n continue;\n }\n }\n\n log('No quotes available', { transactionId });\n\n return {\n batchTransactions: [],\n quotes: [],\n };\n}\n"]}