@metamask/transaction-pay-controller 20.2.0 → 21.1.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 (83) hide show
  1. package/CHANGELOG.md +32 -1
  2. package/dist/TransactionPayController.cjs +25 -0
  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 +26 -1
  7. package/dist/TransactionPayController.mjs.map +1 -1
  8. package/dist/strategy/across/across-quotes.cjs +137 -41
  9. package/dist/strategy/across/across-quotes.cjs.map +1 -1
  10. package/dist/strategy/across/across-quotes.d.cts.map +1 -1
  11. package/dist/strategy/across/across-quotes.d.mts.map +1 -1
  12. package/dist/strategy/across/across-quotes.mjs +138 -42
  13. package/dist/strategy/across/across-quotes.mjs.map +1 -1
  14. package/dist/strategy/across/across-submit.cjs +5 -0
  15. package/dist/strategy/across/across-submit.cjs.map +1 -1
  16. package/dist/strategy/across/across-submit.mjs +5 -0
  17. package/dist/strategy/across/across-submit.mjs.map +1 -1
  18. package/dist/strategy/fiat/constants.cjs +2 -1
  19. package/dist/strategy/fiat/constants.cjs.map +1 -1
  20. package/dist/strategy/fiat/constants.d.cts +1 -0
  21. package/dist/strategy/fiat/constants.d.cts.map +1 -1
  22. package/dist/strategy/fiat/constants.d.mts +1 -0
  23. package/dist/strategy/fiat/constants.d.mts.map +1 -1
  24. package/dist/strategy/fiat/constants.mjs +1 -0
  25. package/dist/strategy/fiat/constants.mjs.map +1 -1
  26. package/dist/strategy/fiat/fiat-quotes.cjs +31 -9
  27. package/dist/strategy/fiat/fiat-quotes.cjs.map +1 -1
  28. package/dist/strategy/fiat/fiat-quotes.d.cts.map +1 -1
  29. package/dist/strategy/fiat/fiat-quotes.d.mts.map +1 -1
  30. package/dist/strategy/fiat/fiat-quotes.mjs +32 -10
  31. package/dist/strategy/fiat/fiat-quotes.mjs.map +1 -1
  32. package/dist/strategy/fiat/fiat-submit.cjs +264 -5
  33. package/dist/strategy/fiat/fiat-submit.cjs.map +1 -1
  34. package/dist/strategy/fiat/fiat-submit.d.cts +9 -4
  35. package/dist/strategy/fiat/fiat-submit.d.cts.map +1 -1
  36. package/dist/strategy/fiat/fiat-submit.d.mts +9 -4
  37. package/dist/strategy/fiat/fiat-submit.d.mts.map +1 -1
  38. package/dist/strategy/fiat/fiat-submit.mjs +264 -5
  39. package/dist/strategy/fiat/fiat-submit.mjs.map +1 -1
  40. package/dist/strategy/fiat/types.cjs.map +1 -1
  41. package/dist/strategy/fiat/types.d.cts +1 -2
  42. package/dist/strategy/fiat/types.d.cts.map +1 -1
  43. package/dist/strategy/fiat/types.d.mts +1 -2
  44. package/dist/strategy/fiat/types.d.mts.map +1 -1
  45. package/dist/strategy/fiat/types.mjs.map +1 -1
  46. package/dist/strategy/fiat/utils.cjs +1 -7
  47. package/dist/strategy/fiat/utils.cjs.map +1 -1
  48. package/dist/strategy/fiat/utils.d.cts +0 -2
  49. package/dist/strategy/fiat/utils.d.cts.map +1 -1
  50. package/dist/strategy/fiat/utils.d.mts +0 -2
  51. package/dist/strategy/fiat/utils.d.mts.map +1 -1
  52. package/dist/strategy/fiat/utils.mjs +0 -5
  53. package/dist/strategy/fiat/utils.mjs.map +1 -1
  54. package/dist/strategy/relay/relay-max-gas-station.cjs +1 -1
  55. package/dist/strategy/relay/relay-max-gas-station.cjs.map +1 -1
  56. package/dist/strategy/relay/relay-max-gas-station.mjs +1 -1
  57. package/dist/strategy/relay/relay-max-gas-station.mjs.map +1 -1
  58. package/dist/strategy/relay/relay-quotes.cjs +8 -5
  59. package/dist/strategy/relay/relay-quotes.cjs.map +1 -1
  60. package/dist/strategy/relay/relay-quotes.d.cts.map +1 -1
  61. package/dist/strategy/relay/relay-quotes.d.mts.map +1 -1
  62. package/dist/strategy/relay/relay-quotes.mjs +8 -5
  63. package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
  64. package/dist/types.cjs +2 -1
  65. package/dist/types.cjs.map +1 -1
  66. package/dist/types.d.cts +12 -7
  67. package/dist/types.d.cts.map +1 -1
  68. package/dist/types.d.mts +12 -7
  69. package/dist/types.d.mts.map +1 -1
  70. package/dist/types.mjs +2 -1
  71. package/dist/types.mjs.map +1 -1
  72. package/dist/{strategy/relay → utils}/gas-station.cjs +4 -4
  73. package/dist/{strategy/relay/gas-station.mjs.map → utils/gas-station.cjs.map} +1 -1
  74. package/dist/{strategy/relay → utils}/gas-station.d.cts +1 -1
  75. package/dist/utils/gas-station.d.cts.map +1 -0
  76. package/dist/{strategy/relay → utils}/gas-station.d.mts +1 -1
  77. package/dist/utils/gas-station.d.mts.map +1 -0
  78. package/dist/{strategy/relay → utils}/gas-station.mjs +4 -4
  79. package/dist/utils/gas-station.mjs.map +1 -0
  80. package/package.json +6 -6
  81. package/dist/strategy/relay/gas-station.cjs.map +0 -1
  82. package/dist/strategy/relay/gas-station.d.cts.map +0 -1
  83. package/dist/strategy/relay/gas-station.d.mts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"across-submit.cjs","sourceRoot":"","sources":["../../../src/strategy/across/across-submit.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ORIGIN_METAMASK,\n successfulFetch,\n toHex,\n} from '@metamask/controller-utils';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type {\n BatchTransactionParams,\n TransactionMeta,\n TransactionParams,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyExecuteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { getPayStrategiesConfig } from '../../utils/feature-flags';\nimport {\n collectTransactionIds,\n getTransaction,\n updateTransaction,\n waitForTransactionConfirmed,\n} from '../../utils/transaction';\nimport { getAcrossOrderedTransactions } from './transactions';\nimport type { AcrossQuote } from './types';\n\nconst log = createModuleLogger(projectLogger, 'across-strategy');\nconst ACROSS_STATUS_POLL_INTERVAL = 1000;\n\ntype PreparedAcrossTransaction = {\n params: TransactionParams;\n type: TransactionType;\n};\n\n/**\n * Submit Across quotes.\n *\n * @param request - Request object.\n * @returns An object containing the transaction hash if available.\n */\nexport async function submitAcrossQuotes(\n request: PayStrategyExecuteRequest<AcrossQuote>,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing quotes', request);\n\n const { quotes, messenger, transaction } = request;\n let transactionHash: Hex | undefined;\n\n for (const quote of quotes) {\n ({ transactionHash } = await executeSingleQuote(\n quote,\n messenger,\n transaction,\n ));\n }\n\n return { transactionHash };\n}\n\nasync function executeSingleQuote(\n quote: TransactionPayQuote<AcrossQuote>,\n messenger: TransactionPayControllerMessenger,\n transaction: TransactionMeta,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing single quote', quote);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Remove nonce from skipped transaction',\n },\n (tx) => {\n tx.txParams.nonce = undefined;\n },\n );\n\n const acrossDepositType = getAcrossDepositType(transaction.type);\n const transactionHash = await submitTransactions(\n quote,\n transaction.id,\n acrossDepositType,\n messenger,\n );\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Intent complete after Across submission',\n },\n (tx) => {\n tx.isIntentComplete = true;\n },\n );\n\n return { transactionHash };\n}\n\n/**\n * Submit transactions for an Across quote.\n *\n * @param quote - Across quote.\n * @param parentTransactionId - ID of the parent transaction.\n * @param acrossDepositType - Transaction type used for the swap/deposit step.\n * @param messenger - Controller messenger.\n * @returns Hash of the last submitted transaction, if available.\n */\nasync function submitTransactions(\n quote: TransactionPayQuote<AcrossQuote>,\n parentTransactionId: string,\n acrossDepositType: TransactionType,\n messenger: TransactionPayControllerMessenger,\n): Promise<Hex | undefined> {\n const { swapTx } = quote.original.quote;\n const { gasLimits: quoteGasLimits, is7702 } = quote.original.metamask;\n const { from } = quote.request;\n const chainId = toHex(swapTx.chainId);\n const orderedTransactions = getAcrossOrderedTransactions({\n quote: quote.original.quote,\n swapType: acrossDepositType,\n });\n\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n const batchGasLimit =\n is7702 && orderedTransactions.length > 1\n ? quoteGasLimits[0]?.max\n : undefined;\n\n if (is7702 && orderedTransactions.length > 1 && batchGasLimit === undefined) {\n throw new Error('Missing quote gas limit for Across 7702 batch');\n }\n\n const gasLimit7702 =\n batchGasLimit === undefined ? undefined : toHex(batchGasLimit);\n\n const transactions: PreparedAcrossTransaction[] = orderedTransactions.map(\n (transaction, index) => {\n const gasLimit = gasLimit7702 ? undefined : quoteGasLimits[index]?.max;\n\n if (gasLimit === undefined && !gasLimit7702) {\n const errorMessage =\n transaction.kind === 'approval'\n ? `Missing quote gas limit for Across approval transaction at index ${index}`\n : 'Missing quote gas limit for Across swap transaction';\n\n throw new Error(errorMessage);\n }\n\n return {\n params: buildTransactionParams(from, {\n chainId: transaction.chainId,\n data: transaction.data,\n gasLimit,\n maxFeePerGas: transaction.maxFeePerGas,\n maxPriorityFeePerGas: transaction.maxPriorityFeePerGas,\n to: transaction.to,\n value: transaction.value,\n }),\n type: transaction.type ?? acrossDepositType,\n };\n },\n );\n\n const transactionIds: string[] = [];\n\n const { end } = collectTransactionIds(\n chainId,\n from,\n messenger,\n (transactionId) => {\n transactionIds.push(transactionId);\n\n updateTransaction(\n {\n transactionId: parentTransactionId,\n messenger,\n note: 'Add required transaction ID from Across submission',\n },\n (tx) => {\n tx.requiredTransactionIds ??= [];\n tx.requiredTransactionIds.push(transactionId);\n },\n );\n },\n );\n\n let result: { result: Promise<string> } | undefined;\n\n try {\n if (transactions.length === 1) {\n result = await messenger.call(\n 'TransactionController:addTransaction',\n transactions[0].params,\n {\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n type: transactions[0].type,\n },\n );\n } else {\n const batchTransactions = transactions.map(({ params, type }) => ({\n params: toBatchTransactionParams(params),\n type,\n }));\n\n await messenger.call('TransactionController:addTransactionBatch', {\n disable7702: !gasLimit7702,\n disableHook: Boolean(gasLimit7702),\n disableSequential: Boolean(gasLimit7702),\n from,\n gasLimit7702,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n transactions: batchTransactions,\n });\n }\n } finally {\n end();\n }\n\n if (result) {\n const txHash = await result.result;\n log('Submitted transaction', txHash);\n }\n\n await Promise.all(\n transactionIds.map((txId) => waitForTransactionConfirmed(txId, messenger)),\n );\n\n const hash = transactionIds.length\n ? getTransaction(transactionIds.slice(-1)[0], messenger)?.hash\n : undefined;\n\n return await waitForAcrossCompletion(hash as Hex | undefined, messenger);\n}\n\ntype AcrossStatusResponse = {\n depositId?: number | string;\n depositTxnRef?: Hex;\n status?: string;\n destinationTxHash?: Hex;\n fillTxnRef?: Hex;\n fillTxHash?: Hex;\n txHash?: Hex;\n};\n\nasync function waitForAcrossCompletion(\n transactionHash: Hex | undefined,\n messenger: TransactionPayControllerMessenger,\n): Promise<Hex | undefined> {\n if (!transactionHash) {\n return transactionHash;\n }\n\n const config = getPayStrategiesConfig(messenger);\n const params = new URLSearchParams({\n depositTxnRef: transactionHash,\n });\n const url = `${config.across.apiBase}/deposit/status?${params.toString()}`;\n\n let attempt = 0;\n\n while (true) {\n attempt += 1;\n let status: AcrossStatusResponse;\n\n try {\n const response = await successfulFetch(url, {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n });\n status = (await response.json()) as AcrossStatusResponse;\n } catch (error) {\n log('Across status polling request failed', {\n attempt,\n error: String(error),\n transactionHash,\n });\n\n await new Promise((resolve) =>\n setTimeout(resolve, ACROSS_STATUS_POLL_INTERVAL),\n );\n continue;\n }\n\n const normalizedStatus = status.status?.toLowerCase();\n\n log('Polled Across status', {\n attempt,\n status: normalizedStatus,\n transactionHash,\n });\n\n if (\n normalizedStatus &&\n ['completed', 'filled', 'success'].includes(normalizedStatus)\n ) {\n return (\n status.destinationTxHash ??\n status.fillTxnRef ??\n status.fillTxHash ??\n status.txHash ??\n transactionHash\n );\n }\n\n if (\n normalizedStatus &&\n ['error', 'failed', 'refund', 'refunded'].includes(normalizedStatus)\n ) {\n throw new Error(`Across request failed with status: ${normalizedStatus}`);\n }\n\n await new Promise((resolve) =>\n setTimeout(resolve, ACROSS_STATUS_POLL_INTERVAL),\n );\n }\n}\n\nfunction getAcrossDepositType(\n transactionType?: TransactionType,\n): TransactionType {\n switch (transactionType) {\n case TransactionType.perpsDeposit:\n return TransactionType.perpsAcrossDeposit;\n case TransactionType.predictDeposit:\n return TransactionType.predictAcrossDeposit;\n case undefined:\n return TransactionType.perpsAcrossDeposit;\n default:\n return transactionType;\n }\n}\n\nfunction buildTransactionParams(\n from: Hex,\n params: {\n chainId: number;\n data: Hex;\n gasLimit?: number;\n to: Hex;\n value?: Hex;\n maxFeePerGas?: string;\n maxPriorityFeePerGas?: string;\n },\n): TransactionParams {\n const value = toHex(params.value ?? '0x0');\n\n return {\n data: params.data,\n from,\n gas: params.gasLimit === undefined ? undefined : toHex(params.gasLimit),\n maxFeePerGas: normalizeOptionalHex(params.maxFeePerGas),\n maxPriorityFeePerGas: normalizeOptionalHex(params.maxPriorityFeePerGas),\n to: params.to,\n value,\n };\n}\n\nfunction normalizeOptionalHex(value?: string): Hex | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n return toHex(value);\n}\n\nfunction toBatchTransactionParams(\n params: TransactionParams,\n): BatchTransactionParams {\n return {\n data: params.data as Hex | undefined,\n gas: params.gas as Hex | undefined,\n maxFeePerGas: params.maxFeePerGas as Hex | undefined,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas as Hex | undefined,\n to: params.to as Hex | undefined,\n value: params.value as Hex | undefined,\n };\n}\n"]}
1
+ {"version":3,"file":"across-submit.cjs","sourceRoot":"","sources":["../../../src/strategy/across/across-submit.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ORIGIN_METAMASK,\n successfulFetch,\n toHex,\n} from '@metamask/controller-utils';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type {\n BatchTransactionParams,\n TransactionMeta,\n TransactionParams,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyExecuteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { getPayStrategiesConfig } from '../../utils/feature-flags';\nimport {\n collectTransactionIds,\n getTransaction,\n updateTransaction,\n waitForTransactionConfirmed,\n} from '../../utils/transaction';\nimport { getAcrossOrderedTransactions } from './transactions';\nimport type { AcrossQuote } from './types';\n\nconst log = createModuleLogger(projectLogger, 'across-strategy');\nconst ACROSS_STATUS_POLL_INTERVAL = 1000;\n\ntype PreparedAcrossTransaction = {\n params: TransactionParams;\n type: TransactionType;\n};\n\n/**\n * Submit Across quotes.\n *\n * @param request - Request object.\n * @returns An object containing the transaction hash if available.\n */\nexport async function submitAcrossQuotes(\n request: PayStrategyExecuteRequest<AcrossQuote>,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing quotes', request);\n\n const { quotes, messenger, transaction } = request;\n let transactionHash: Hex | undefined;\n\n for (const quote of quotes) {\n ({ transactionHash } = await executeSingleQuote(\n quote,\n messenger,\n transaction,\n ));\n }\n\n return { transactionHash };\n}\n\nasync function executeSingleQuote(\n quote: TransactionPayQuote<AcrossQuote>,\n messenger: TransactionPayControllerMessenger,\n transaction: TransactionMeta,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing single quote', quote);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Remove nonce from skipped transaction',\n },\n (tx) => {\n tx.txParams.nonce = undefined;\n },\n );\n\n const acrossDepositType = getAcrossDepositType(transaction.type);\n const transactionHash = await submitTransactions(\n quote,\n transaction.id,\n acrossDepositType,\n messenger,\n );\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Intent complete after Across submission',\n },\n (tx) => {\n tx.isIntentComplete = true;\n },\n );\n\n return { transactionHash };\n}\n\n/**\n * Submit transactions for an Across quote.\n *\n * @param quote - Across quote.\n * @param parentTransactionId - ID of the parent transaction.\n * @param acrossDepositType - Transaction type used for the swap/deposit step.\n * @param messenger - Controller messenger.\n * @returns Hash of the last submitted transaction, if available.\n */\nasync function submitTransactions(\n quote: TransactionPayQuote<AcrossQuote>,\n parentTransactionId: string,\n acrossDepositType: TransactionType,\n messenger: TransactionPayControllerMessenger,\n): Promise<Hex | undefined> {\n const { swapTx } = quote.original.quote;\n const { gasLimits: quoteGasLimits, is7702 } = quote.original.metamask;\n const { from } = quote.request;\n const chainId = toHex(swapTx.chainId);\n const orderedTransactions = getAcrossOrderedTransactions({\n quote: quote.original.quote,\n swapType: acrossDepositType,\n });\n\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n const batchGasLimit =\n is7702 && orderedTransactions.length > 1\n ? quoteGasLimits[0]?.max\n : undefined;\n\n if (is7702 && orderedTransactions.length > 1 && batchGasLimit === undefined) {\n throw new Error('Missing quote gas limit for Across 7702 batch');\n }\n\n const gasLimit7702 =\n batchGasLimit === undefined ? undefined : toHex(batchGasLimit);\n\n const transactions: PreparedAcrossTransaction[] = orderedTransactions.map(\n (transaction, index) => {\n const gasLimit = gasLimit7702 ? undefined : quoteGasLimits[index]?.max;\n\n if (gasLimit === undefined && !gasLimit7702) {\n const errorMessage =\n transaction.kind === 'approval'\n ? `Missing quote gas limit for Across approval transaction at index ${index}`\n : 'Missing quote gas limit for Across swap transaction';\n\n throw new Error(errorMessage);\n }\n\n return {\n params: buildTransactionParams(from, {\n chainId: transaction.chainId,\n data: transaction.data,\n gasLimit,\n maxFeePerGas: transaction.maxFeePerGas,\n maxPriorityFeePerGas: transaction.maxPriorityFeePerGas,\n to: transaction.to,\n value: transaction.value,\n }),\n type: transaction.type ?? acrossDepositType,\n };\n },\n );\n\n const transactionIds: string[] = [];\n\n const { end } = collectTransactionIds(\n chainId,\n from,\n messenger,\n (transactionId) => {\n transactionIds.push(transactionId);\n\n updateTransaction(\n {\n transactionId: parentTransactionId,\n messenger,\n note: 'Add required transaction ID from Across submission',\n },\n (tx) => {\n tx.requiredTransactionIds ??= [];\n tx.requiredTransactionIds.push(transactionId);\n },\n );\n },\n );\n\n let result: { result: Promise<string> } | undefined;\n const gasFeeToken = quote.fees.isSourceGasFeeToken\n ? quote.request.sourceTokenAddress\n : undefined;\n\n try {\n if (transactions.length === 1) {\n result = await messenger.call(\n 'TransactionController:addTransaction',\n transactions[0].params,\n {\n gasFeeToken,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n type: transactions[0].type,\n },\n );\n } else {\n const batchTransactions = transactions.map(({ params, type }) => ({\n params: toBatchTransactionParams(params),\n type,\n }));\n\n await messenger.call('TransactionController:addTransactionBatch', {\n disable7702: !gasLimit7702,\n disableHook: Boolean(gasLimit7702),\n disableSequential: Boolean(gasLimit7702),\n from,\n gasFeeToken,\n gasLimit7702,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n transactions: batchTransactions,\n });\n }\n } finally {\n end();\n }\n\n if (result) {\n const txHash = await result.result;\n log('Submitted transaction', txHash);\n }\n\n await Promise.all(\n transactionIds.map((txId) => waitForTransactionConfirmed(txId, messenger)),\n );\n\n const hash = transactionIds.length\n ? getTransaction(transactionIds.slice(-1)[0], messenger)?.hash\n : undefined;\n\n return await waitForAcrossCompletion(hash as Hex | undefined, messenger);\n}\n\ntype AcrossStatusResponse = {\n depositId?: number | string;\n depositTxnRef?: Hex;\n status?: string;\n destinationTxHash?: Hex;\n fillTxnRef?: Hex;\n fillTxHash?: Hex;\n txHash?: Hex;\n};\n\nasync function waitForAcrossCompletion(\n transactionHash: Hex | undefined,\n messenger: TransactionPayControllerMessenger,\n): Promise<Hex | undefined> {\n if (!transactionHash) {\n return transactionHash;\n }\n\n const config = getPayStrategiesConfig(messenger);\n const params = new URLSearchParams({\n depositTxnRef: transactionHash,\n });\n const url = `${config.across.apiBase}/deposit/status?${params.toString()}`;\n\n let attempt = 0;\n\n while (true) {\n attempt += 1;\n let status: AcrossStatusResponse;\n\n try {\n const response = await successfulFetch(url, {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n });\n status = (await response.json()) as AcrossStatusResponse;\n } catch (error) {\n log('Across status polling request failed', {\n attempt,\n error: String(error),\n transactionHash,\n });\n\n await new Promise((resolve) =>\n setTimeout(resolve, ACROSS_STATUS_POLL_INTERVAL),\n );\n continue;\n }\n\n const normalizedStatus = status.status?.toLowerCase();\n\n log('Polled Across status', {\n attempt,\n status: normalizedStatus,\n transactionHash,\n });\n\n if (\n normalizedStatus &&\n ['completed', 'filled', 'success'].includes(normalizedStatus)\n ) {\n return (\n status.destinationTxHash ??\n status.fillTxnRef ??\n status.fillTxHash ??\n status.txHash ??\n transactionHash\n );\n }\n\n if (\n normalizedStatus &&\n ['error', 'failed', 'refund', 'refunded'].includes(normalizedStatus)\n ) {\n throw new Error(`Across request failed with status: ${normalizedStatus}`);\n }\n\n await new Promise((resolve) =>\n setTimeout(resolve, ACROSS_STATUS_POLL_INTERVAL),\n );\n }\n}\n\nfunction getAcrossDepositType(\n transactionType?: TransactionType,\n): TransactionType {\n switch (transactionType) {\n case TransactionType.perpsDeposit:\n return TransactionType.perpsAcrossDeposit;\n case TransactionType.predictDeposit:\n return TransactionType.predictAcrossDeposit;\n case undefined:\n return TransactionType.perpsAcrossDeposit;\n default:\n return transactionType;\n }\n}\n\nfunction buildTransactionParams(\n from: Hex,\n params: {\n chainId: number;\n data: Hex;\n gasLimit?: number;\n to: Hex;\n value?: Hex;\n maxFeePerGas?: string;\n maxPriorityFeePerGas?: string;\n },\n): TransactionParams {\n const value = toHex(params.value ?? '0x0');\n\n return {\n data: params.data,\n from,\n gas: params.gasLimit === undefined ? undefined : toHex(params.gasLimit),\n maxFeePerGas: normalizeOptionalHex(params.maxFeePerGas),\n maxPriorityFeePerGas: normalizeOptionalHex(params.maxPriorityFeePerGas),\n to: params.to,\n value,\n };\n}\n\nfunction normalizeOptionalHex(value?: string): Hex | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n return toHex(value);\n}\n\nfunction toBatchTransactionParams(\n params: TransactionParams,\n): BatchTransactionParams {\n return {\n data: params.data as Hex | undefined,\n gas: params.gas as Hex | undefined,\n maxFeePerGas: params.maxFeePerGas as Hex | undefined,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas as Hex | undefined,\n to: params.to as Hex | undefined,\n value: params.value as Hex | undefined,\n };\n}\n"]}
@@ -102,9 +102,13 @@ async function submitTransactions(quote, parentTransactionId, acrossDepositType,
102
102
  });
103
103
  });
104
104
  let result;
105
+ const gasFeeToken = quote.fees.isSourceGasFeeToken
106
+ ? quote.request.sourceTokenAddress
107
+ : undefined;
105
108
  try {
106
109
  if (transactions.length === 1) {
107
110
  result = await messenger.call('TransactionController:addTransaction', transactions[0].params, {
111
+ gasFeeToken,
108
112
  networkClientId,
109
113
  origin: ORIGIN_METAMASK,
110
114
  requireApproval: false,
@@ -121,6 +125,7 @@ async function submitTransactions(quote, parentTransactionId, acrossDepositType,
121
125
  disableHook: Boolean(gasLimit7702),
122
126
  disableSequential: Boolean(gasLimit7702),
123
127
  from,
128
+ gasFeeToken,
124
129
  gasLimit7702,
125
130
  networkClientId,
126
131
  origin: ORIGIN_METAMASK,
@@ -1 +1 @@
1
- {"version":3,"file":"across-submit.mjs","sourceRoot":"","sources":["../../../src/strategy/across/across-submit.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ORIGIN_METAMASK,\n successfulFetch,\n toHex,\n} from '@metamask/controller-utils';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type {\n BatchTransactionParams,\n TransactionMeta,\n TransactionParams,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyExecuteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { getPayStrategiesConfig } from '../../utils/feature-flags';\nimport {\n collectTransactionIds,\n getTransaction,\n updateTransaction,\n waitForTransactionConfirmed,\n} from '../../utils/transaction';\nimport { getAcrossOrderedTransactions } from './transactions';\nimport type { AcrossQuote } from './types';\n\nconst log = createModuleLogger(projectLogger, 'across-strategy');\nconst ACROSS_STATUS_POLL_INTERVAL = 1000;\n\ntype PreparedAcrossTransaction = {\n params: TransactionParams;\n type: TransactionType;\n};\n\n/**\n * Submit Across quotes.\n *\n * @param request - Request object.\n * @returns An object containing the transaction hash if available.\n */\nexport async function submitAcrossQuotes(\n request: PayStrategyExecuteRequest<AcrossQuote>,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing quotes', request);\n\n const { quotes, messenger, transaction } = request;\n let transactionHash: Hex | undefined;\n\n for (const quote of quotes) {\n ({ transactionHash } = await executeSingleQuote(\n quote,\n messenger,\n transaction,\n ));\n }\n\n return { transactionHash };\n}\n\nasync function executeSingleQuote(\n quote: TransactionPayQuote<AcrossQuote>,\n messenger: TransactionPayControllerMessenger,\n transaction: TransactionMeta,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing single quote', quote);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Remove nonce from skipped transaction',\n },\n (tx) => {\n tx.txParams.nonce = undefined;\n },\n );\n\n const acrossDepositType = getAcrossDepositType(transaction.type);\n const transactionHash = await submitTransactions(\n quote,\n transaction.id,\n acrossDepositType,\n messenger,\n );\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Intent complete after Across submission',\n },\n (tx) => {\n tx.isIntentComplete = true;\n },\n );\n\n return { transactionHash };\n}\n\n/**\n * Submit transactions for an Across quote.\n *\n * @param quote - Across quote.\n * @param parentTransactionId - ID of the parent transaction.\n * @param acrossDepositType - Transaction type used for the swap/deposit step.\n * @param messenger - Controller messenger.\n * @returns Hash of the last submitted transaction, if available.\n */\nasync function submitTransactions(\n quote: TransactionPayQuote<AcrossQuote>,\n parentTransactionId: string,\n acrossDepositType: TransactionType,\n messenger: TransactionPayControllerMessenger,\n): Promise<Hex | undefined> {\n const { swapTx } = quote.original.quote;\n const { gasLimits: quoteGasLimits, is7702 } = quote.original.metamask;\n const { from } = quote.request;\n const chainId = toHex(swapTx.chainId);\n const orderedTransactions = getAcrossOrderedTransactions({\n quote: quote.original.quote,\n swapType: acrossDepositType,\n });\n\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n const batchGasLimit =\n is7702 && orderedTransactions.length > 1\n ? quoteGasLimits[0]?.max\n : undefined;\n\n if (is7702 && orderedTransactions.length > 1 && batchGasLimit === undefined) {\n throw new Error('Missing quote gas limit for Across 7702 batch');\n }\n\n const gasLimit7702 =\n batchGasLimit === undefined ? undefined : toHex(batchGasLimit);\n\n const transactions: PreparedAcrossTransaction[] = orderedTransactions.map(\n (transaction, index) => {\n const gasLimit = gasLimit7702 ? undefined : quoteGasLimits[index]?.max;\n\n if (gasLimit === undefined && !gasLimit7702) {\n const errorMessage =\n transaction.kind === 'approval'\n ? `Missing quote gas limit for Across approval transaction at index ${index}`\n : 'Missing quote gas limit for Across swap transaction';\n\n throw new Error(errorMessage);\n }\n\n return {\n params: buildTransactionParams(from, {\n chainId: transaction.chainId,\n data: transaction.data,\n gasLimit,\n maxFeePerGas: transaction.maxFeePerGas,\n maxPriorityFeePerGas: transaction.maxPriorityFeePerGas,\n to: transaction.to,\n value: transaction.value,\n }),\n type: transaction.type ?? acrossDepositType,\n };\n },\n );\n\n const transactionIds: string[] = [];\n\n const { end } = collectTransactionIds(\n chainId,\n from,\n messenger,\n (transactionId) => {\n transactionIds.push(transactionId);\n\n updateTransaction(\n {\n transactionId: parentTransactionId,\n messenger,\n note: 'Add required transaction ID from Across submission',\n },\n (tx) => {\n tx.requiredTransactionIds ??= [];\n tx.requiredTransactionIds.push(transactionId);\n },\n );\n },\n );\n\n let result: { result: Promise<string> } | undefined;\n\n try {\n if (transactions.length === 1) {\n result = await messenger.call(\n 'TransactionController:addTransaction',\n transactions[0].params,\n {\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n type: transactions[0].type,\n },\n );\n } else {\n const batchTransactions = transactions.map(({ params, type }) => ({\n params: toBatchTransactionParams(params),\n type,\n }));\n\n await messenger.call('TransactionController:addTransactionBatch', {\n disable7702: !gasLimit7702,\n disableHook: Boolean(gasLimit7702),\n disableSequential: Boolean(gasLimit7702),\n from,\n gasLimit7702,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n transactions: batchTransactions,\n });\n }\n } finally {\n end();\n }\n\n if (result) {\n const txHash = await result.result;\n log('Submitted transaction', txHash);\n }\n\n await Promise.all(\n transactionIds.map((txId) => waitForTransactionConfirmed(txId, messenger)),\n );\n\n const hash = transactionIds.length\n ? getTransaction(transactionIds.slice(-1)[0], messenger)?.hash\n : undefined;\n\n return await waitForAcrossCompletion(hash as Hex | undefined, messenger);\n}\n\ntype AcrossStatusResponse = {\n depositId?: number | string;\n depositTxnRef?: Hex;\n status?: string;\n destinationTxHash?: Hex;\n fillTxnRef?: Hex;\n fillTxHash?: Hex;\n txHash?: Hex;\n};\n\nasync function waitForAcrossCompletion(\n transactionHash: Hex | undefined,\n messenger: TransactionPayControllerMessenger,\n): Promise<Hex | undefined> {\n if (!transactionHash) {\n return transactionHash;\n }\n\n const config = getPayStrategiesConfig(messenger);\n const params = new URLSearchParams({\n depositTxnRef: transactionHash,\n });\n const url = `${config.across.apiBase}/deposit/status?${params.toString()}`;\n\n let attempt = 0;\n\n while (true) {\n attempt += 1;\n let status: AcrossStatusResponse;\n\n try {\n const response = await successfulFetch(url, {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n });\n status = (await response.json()) as AcrossStatusResponse;\n } catch (error) {\n log('Across status polling request failed', {\n attempt,\n error: String(error),\n transactionHash,\n });\n\n await new Promise((resolve) =>\n setTimeout(resolve, ACROSS_STATUS_POLL_INTERVAL),\n );\n continue;\n }\n\n const normalizedStatus = status.status?.toLowerCase();\n\n log('Polled Across status', {\n attempt,\n status: normalizedStatus,\n transactionHash,\n });\n\n if (\n normalizedStatus &&\n ['completed', 'filled', 'success'].includes(normalizedStatus)\n ) {\n return (\n status.destinationTxHash ??\n status.fillTxnRef ??\n status.fillTxHash ??\n status.txHash ??\n transactionHash\n );\n }\n\n if (\n normalizedStatus &&\n ['error', 'failed', 'refund', 'refunded'].includes(normalizedStatus)\n ) {\n throw new Error(`Across request failed with status: ${normalizedStatus}`);\n }\n\n await new Promise((resolve) =>\n setTimeout(resolve, ACROSS_STATUS_POLL_INTERVAL),\n );\n }\n}\n\nfunction getAcrossDepositType(\n transactionType?: TransactionType,\n): TransactionType {\n switch (transactionType) {\n case TransactionType.perpsDeposit:\n return TransactionType.perpsAcrossDeposit;\n case TransactionType.predictDeposit:\n return TransactionType.predictAcrossDeposit;\n case undefined:\n return TransactionType.perpsAcrossDeposit;\n default:\n return transactionType;\n }\n}\n\nfunction buildTransactionParams(\n from: Hex,\n params: {\n chainId: number;\n data: Hex;\n gasLimit?: number;\n to: Hex;\n value?: Hex;\n maxFeePerGas?: string;\n maxPriorityFeePerGas?: string;\n },\n): TransactionParams {\n const value = toHex(params.value ?? '0x0');\n\n return {\n data: params.data,\n from,\n gas: params.gasLimit === undefined ? undefined : toHex(params.gasLimit),\n maxFeePerGas: normalizeOptionalHex(params.maxFeePerGas),\n maxPriorityFeePerGas: normalizeOptionalHex(params.maxPriorityFeePerGas),\n to: params.to,\n value,\n };\n}\n\nfunction normalizeOptionalHex(value?: string): Hex | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n return toHex(value);\n}\n\nfunction toBatchTransactionParams(\n params: TransactionParams,\n): BatchTransactionParams {\n return {\n data: params.data as Hex | undefined,\n gas: params.gas as Hex | undefined,\n maxFeePerGas: params.maxFeePerGas as Hex | undefined,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas as Hex | undefined,\n to: params.to as Hex | undefined,\n value: params.value as Hex | undefined,\n };\n}\n"]}
1
+ {"version":3,"file":"across-submit.mjs","sourceRoot":"","sources":["../../../src/strategy/across/across-submit.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ORIGIN_METAMASK,\n successfulFetch,\n toHex,\n} from '@metamask/controller-utils';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type {\n BatchTransactionParams,\n TransactionMeta,\n TransactionParams,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyExecuteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { getPayStrategiesConfig } from '../../utils/feature-flags';\nimport {\n collectTransactionIds,\n getTransaction,\n updateTransaction,\n waitForTransactionConfirmed,\n} from '../../utils/transaction';\nimport { getAcrossOrderedTransactions } from './transactions';\nimport type { AcrossQuote } from './types';\n\nconst log = createModuleLogger(projectLogger, 'across-strategy');\nconst ACROSS_STATUS_POLL_INTERVAL = 1000;\n\ntype PreparedAcrossTransaction = {\n params: TransactionParams;\n type: TransactionType;\n};\n\n/**\n * Submit Across quotes.\n *\n * @param request - Request object.\n * @returns An object containing the transaction hash if available.\n */\nexport async function submitAcrossQuotes(\n request: PayStrategyExecuteRequest<AcrossQuote>,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing quotes', request);\n\n const { quotes, messenger, transaction } = request;\n let transactionHash: Hex | undefined;\n\n for (const quote of quotes) {\n ({ transactionHash } = await executeSingleQuote(\n quote,\n messenger,\n transaction,\n ));\n }\n\n return { transactionHash };\n}\n\nasync function executeSingleQuote(\n quote: TransactionPayQuote<AcrossQuote>,\n messenger: TransactionPayControllerMessenger,\n transaction: TransactionMeta,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing single quote', quote);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Remove nonce from skipped transaction',\n },\n (tx) => {\n tx.txParams.nonce = undefined;\n },\n );\n\n const acrossDepositType = getAcrossDepositType(transaction.type);\n const transactionHash = await submitTransactions(\n quote,\n transaction.id,\n acrossDepositType,\n messenger,\n );\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Intent complete after Across submission',\n },\n (tx) => {\n tx.isIntentComplete = true;\n },\n );\n\n return { transactionHash };\n}\n\n/**\n * Submit transactions for an Across quote.\n *\n * @param quote - Across quote.\n * @param parentTransactionId - ID of the parent transaction.\n * @param acrossDepositType - Transaction type used for the swap/deposit step.\n * @param messenger - Controller messenger.\n * @returns Hash of the last submitted transaction, if available.\n */\nasync function submitTransactions(\n quote: TransactionPayQuote<AcrossQuote>,\n parentTransactionId: string,\n acrossDepositType: TransactionType,\n messenger: TransactionPayControllerMessenger,\n): Promise<Hex | undefined> {\n const { swapTx } = quote.original.quote;\n const { gasLimits: quoteGasLimits, is7702 } = quote.original.metamask;\n const { from } = quote.request;\n const chainId = toHex(swapTx.chainId);\n const orderedTransactions = getAcrossOrderedTransactions({\n quote: quote.original.quote,\n swapType: acrossDepositType,\n });\n\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n const batchGasLimit =\n is7702 && orderedTransactions.length > 1\n ? quoteGasLimits[0]?.max\n : undefined;\n\n if (is7702 && orderedTransactions.length > 1 && batchGasLimit === undefined) {\n throw new Error('Missing quote gas limit for Across 7702 batch');\n }\n\n const gasLimit7702 =\n batchGasLimit === undefined ? undefined : toHex(batchGasLimit);\n\n const transactions: PreparedAcrossTransaction[] = orderedTransactions.map(\n (transaction, index) => {\n const gasLimit = gasLimit7702 ? undefined : quoteGasLimits[index]?.max;\n\n if (gasLimit === undefined && !gasLimit7702) {\n const errorMessage =\n transaction.kind === 'approval'\n ? `Missing quote gas limit for Across approval transaction at index ${index}`\n : 'Missing quote gas limit for Across swap transaction';\n\n throw new Error(errorMessage);\n }\n\n return {\n params: buildTransactionParams(from, {\n chainId: transaction.chainId,\n data: transaction.data,\n gasLimit,\n maxFeePerGas: transaction.maxFeePerGas,\n maxPriorityFeePerGas: transaction.maxPriorityFeePerGas,\n to: transaction.to,\n value: transaction.value,\n }),\n type: transaction.type ?? acrossDepositType,\n };\n },\n );\n\n const transactionIds: string[] = [];\n\n const { end } = collectTransactionIds(\n chainId,\n from,\n messenger,\n (transactionId) => {\n transactionIds.push(transactionId);\n\n updateTransaction(\n {\n transactionId: parentTransactionId,\n messenger,\n note: 'Add required transaction ID from Across submission',\n },\n (tx) => {\n tx.requiredTransactionIds ??= [];\n tx.requiredTransactionIds.push(transactionId);\n },\n );\n },\n );\n\n let result: { result: Promise<string> } | undefined;\n const gasFeeToken = quote.fees.isSourceGasFeeToken\n ? quote.request.sourceTokenAddress\n : undefined;\n\n try {\n if (transactions.length === 1) {\n result = await messenger.call(\n 'TransactionController:addTransaction',\n transactions[0].params,\n {\n gasFeeToken,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n type: transactions[0].type,\n },\n );\n } else {\n const batchTransactions = transactions.map(({ params, type }) => ({\n params: toBatchTransactionParams(params),\n type,\n }));\n\n await messenger.call('TransactionController:addTransactionBatch', {\n disable7702: !gasLimit7702,\n disableHook: Boolean(gasLimit7702),\n disableSequential: Boolean(gasLimit7702),\n from,\n gasFeeToken,\n gasLimit7702,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n transactions: batchTransactions,\n });\n }\n } finally {\n end();\n }\n\n if (result) {\n const txHash = await result.result;\n log('Submitted transaction', txHash);\n }\n\n await Promise.all(\n transactionIds.map((txId) => waitForTransactionConfirmed(txId, messenger)),\n );\n\n const hash = transactionIds.length\n ? getTransaction(transactionIds.slice(-1)[0], messenger)?.hash\n : undefined;\n\n return await waitForAcrossCompletion(hash as Hex | undefined, messenger);\n}\n\ntype AcrossStatusResponse = {\n depositId?: number | string;\n depositTxnRef?: Hex;\n status?: string;\n destinationTxHash?: Hex;\n fillTxnRef?: Hex;\n fillTxHash?: Hex;\n txHash?: Hex;\n};\n\nasync function waitForAcrossCompletion(\n transactionHash: Hex | undefined,\n messenger: TransactionPayControllerMessenger,\n): Promise<Hex | undefined> {\n if (!transactionHash) {\n return transactionHash;\n }\n\n const config = getPayStrategiesConfig(messenger);\n const params = new URLSearchParams({\n depositTxnRef: transactionHash,\n });\n const url = `${config.across.apiBase}/deposit/status?${params.toString()}`;\n\n let attempt = 0;\n\n while (true) {\n attempt += 1;\n let status: AcrossStatusResponse;\n\n try {\n const response = await successfulFetch(url, {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n });\n status = (await response.json()) as AcrossStatusResponse;\n } catch (error) {\n log('Across status polling request failed', {\n attempt,\n error: String(error),\n transactionHash,\n });\n\n await new Promise((resolve) =>\n setTimeout(resolve, ACROSS_STATUS_POLL_INTERVAL),\n );\n continue;\n }\n\n const normalizedStatus = status.status?.toLowerCase();\n\n log('Polled Across status', {\n attempt,\n status: normalizedStatus,\n transactionHash,\n });\n\n if (\n normalizedStatus &&\n ['completed', 'filled', 'success'].includes(normalizedStatus)\n ) {\n return (\n status.destinationTxHash ??\n status.fillTxnRef ??\n status.fillTxHash ??\n status.txHash ??\n transactionHash\n );\n }\n\n if (\n normalizedStatus &&\n ['error', 'failed', 'refund', 'refunded'].includes(normalizedStatus)\n ) {\n throw new Error(`Across request failed with status: ${normalizedStatus}`);\n }\n\n await new Promise((resolve) =>\n setTimeout(resolve, ACROSS_STATUS_POLL_INTERVAL),\n );\n }\n}\n\nfunction getAcrossDepositType(\n transactionType?: TransactionType,\n): TransactionType {\n switch (transactionType) {\n case TransactionType.perpsDeposit:\n return TransactionType.perpsAcrossDeposit;\n case TransactionType.predictDeposit:\n return TransactionType.predictAcrossDeposit;\n case undefined:\n return TransactionType.perpsAcrossDeposit;\n default:\n return transactionType;\n }\n}\n\nfunction buildTransactionParams(\n from: Hex,\n params: {\n chainId: number;\n data: Hex;\n gasLimit?: number;\n to: Hex;\n value?: Hex;\n maxFeePerGas?: string;\n maxPriorityFeePerGas?: string;\n },\n): TransactionParams {\n const value = toHex(params.value ?? '0x0');\n\n return {\n data: params.data,\n from,\n gas: params.gasLimit === undefined ? undefined : toHex(params.gasLimit),\n maxFeePerGas: normalizeOptionalHex(params.maxFeePerGas),\n maxPriorityFeePerGas: normalizeOptionalHex(params.maxPriorityFeePerGas),\n to: params.to,\n value,\n };\n}\n\nfunction normalizeOptionalHex(value?: string): Hex | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n return toHex(value);\n}\n\nfunction toBatchTransactionParams(\n params: TransactionParams,\n): BatchTransactionParams {\n return {\n data: params.data as Hex | undefined,\n gas: params.gas as Hex | undefined,\n maxFeePerGas: params.maxFeePerGas as Hex | undefined,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas as Hex | undefined,\n to: params.to as Hex | undefined,\n value: params.value as Hex | undefined,\n };\n}\n"]}
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FIAT_ASSET_ID_BY_TX_TYPE = void 0;
3
+ exports.FIAT_ASSET_ID_BY_TX_TYPE = exports.DEFAULT_FIAT_CURRENCY = void 0;
4
4
  const transaction_controller_1 = require("@metamask/transaction-controller");
5
5
  const constants_1 = require("../../constants.cjs");
6
+ exports.DEFAULT_FIAT_CURRENCY = 'USD';
6
7
  const POLYGON_POL_FIAT_ASSET = {
7
8
  address: '0x0000000000000000000000000000000000001010',
8
9
  caipAssetId: 'eip155:137/slip44:966',
@@ -1 +1 @@
1
- {"version":3,"file":"constants.cjs","sourceRoot":"","sources":["../../../src/strategy/fiat/constants.ts"],"names":[],"mappings":";;;AAAA,6EAAmE;AAGnE,mDAIyB;AASzB,MAAM,sBAAsB,GAA4B;IACtD,OAAO,EAAE,4CAA4C;IACrD,WAAW,EAAE,uBAAuB;IACpC,OAAO,EAAE,4BAAgB;IACzB,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,MAAM,uBAAuB,GAA4B;IACvD,OAAO,EAAE,gCAAoB;IAC7B,WAAW,EAAE,wBAAwB;IACrC,OAAO,EAAE,6BAAiB;IAC1B,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,uDAAuD;AAC1C,QAAA,wBAAwB,GAEjC;IACF,CAAC,wCAAe,CAAC,cAAc,CAAC,EAAE,sBAAsB;IACxD,CAAC,wCAAe,CAAC,YAAY,CAAC,EAAE,uBAAuB;IACvD,CAAC,wCAAe,CAAC,oBAAoB,CAAC,EAAE,uBAAuB;CAChE,CAAC","sourcesContent":["import { TransactionType } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n} from '../../constants';\n\nexport type TransactionPayFiatAsset = {\n address: Hex;\n caipAssetId: string;\n chainId: Hex;\n decimals: number;\n};\n\nconst POLYGON_POL_FIAT_ASSET: TransactionPayFiatAsset = {\n address: '0x0000000000000000000000000000000000001010',\n caipAssetId: 'eip155:137/slip44:966',\n chainId: CHAIN_ID_POLYGON,\n decimals: 18,\n};\n\nconst ARBITRUM_ETH_FIAT_ASSET: TransactionPayFiatAsset = {\n address: NATIVE_TOKEN_ADDRESS,\n caipAssetId: 'eip155:42161/slip44:60',\n chainId: CHAIN_ID_ARBITRUM,\n decimals: 18,\n};\n\n// We might use feature flags to determine these later.\nexport const FIAT_ASSET_ID_BY_TX_TYPE: Partial<\n Record<TransactionType, TransactionPayFiatAsset>\n> = {\n [TransactionType.predictDeposit]: POLYGON_POL_FIAT_ASSET,\n [TransactionType.perpsDeposit]: ARBITRUM_ETH_FIAT_ASSET,\n [TransactionType.perpsDepositAndOrder]: ARBITRUM_ETH_FIAT_ASSET,\n};\n"]}
1
+ {"version":3,"file":"constants.cjs","sourceRoot":"","sources":["../../../src/strategy/fiat/constants.ts"],"names":[],"mappings":";;;AAAA,6EAAmE;AAGnE,mDAIyB;AAEZ,QAAA,qBAAqB,GAAG,KAAK,CAAC;AAS3C,MAAM,sBAAsB,GAA4B;IACtD,OAAO,EAAE,4CAA4C;IACrD,WAAW,EAAE,uBAAuB;IACpC,OAAO,EAAE,4BAAgB;IACzB,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,MAAM,uBAAuB,GAA4B;IACvD,OAAO,EAAE,gCAAoB;IAC7B,WAAW,EAAE,wBAAwB;IACrC,OAAO,EAAE,6BAAiB;IAC1B,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,uDAAuD;AAC1C,QAAA,wBAAwB,GAEjC;IACF,CAAC,wCAAe,CAAC,cAAc,CAAC,EAAE,sBAAsB;IACxD,CAAC,wCAAe,CAAC,YAAY,CAAC,EAAE,uBAAuB;IACvD,CAAC,wCAAe,CAAC,oBAAoB,CAAC,EAAE,uBAAuB;CAChE,CAAC","sourcesContent":["import { TransactionType } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n} from '../../constants';\n\nexport const DEFAULT_FIAT_CURRENCY = 'USD';\n\nexport type TransactionPayFiatAsset = {\n address: Hex;\n caipAssetId: string;\n chainId: Hex;\n decimals: number;\n};\n\nconst POLYGON_POL_FIAT_ASSET: TransactionPayFiatAsset = {\n address: '0x0000000000000000000000000000000000001010',\n caipAssetId: 'eip155:137/slip44:966',\n chainId: CHAIN_ID_POLYGON,\n decimals: 18,\n};\n\nconst ARBITRUM_ETH_FIAT_ASSET: TransactionPayFiatAsset = {\n address: NATIVE_TOKEN_ADDRESS,\n caipAssetId: 'eip155:42161/slip44:60',\n chainId: CHAIN_ID_ARBITRUM,\n decimals: 18,\n};\n\n// We might use feature flags to determine these later.\nexport const FIAT_ASSET_ID_BY_TX_TYPE: Partial<\n Record<TransactionType, TransactionPayFiatAsset>\n> = {\n [TransactionType.predictDeposit]: POLYGON_POL_FIAT_ASSET,\n [TransactionType.perpsDeposit]: ARBITRUM_ETH_FIAT_ASSET,\n [TransactionType.perpsDepositAndOrder]: ARBITRUM_ETH_FIAT_ASSET,\n};\n"]}
@@ -1,5 +1,6 @@
1
1
  import { TransactionType } from "@metamask/transaction-controller";
2
2
  import type { Hex } from "@metamask/utils";
3
+ export declare const DEFAULT_FIAT_CURRENCY = "USD";
3
4
  export type TransactionPayFiatAsset = {
4
5
  address: Hex;
5
6
  caipAssetId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.cts","sourceRoot":"","sources":["../../../src/strategy/fiat/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AACnE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAQ3C,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,GAAG,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,GAAG,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAiBF,eAAO,MAAM,wBAAwB,EAAE,OAAO,CAC5C,MAAM,CAAC,eAAe,EAAE,uBAAuB,CAAC,CAKjD,CAAC"}
1
+ {"version":3,"file":"constants.d.cts","sourceRoot":"","sources":["../../../src/strategy/fiat/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AACnE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAQ3C,eAAO,MAAM,qBAAqB,QAAQ,CAAC;AAE3C,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,GAAG,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,GAAG,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAiBF,eAAO,MAAM,wBAAwB,EAAE,OAAO,CAC5C,MAAM,CAAC,eAAe,EAAE,uBAAuB,CAAC,CAKjD,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { TransactionType } from "@metamask/transaction-controller";
2
2
  import type { Hex } from "@metamask/utils";
3
+ export declare const DEFAULT_FIAT_CURRENCY = "USD";
3
4
  export type TransactionPayFiatAsset = {
4
5
  address: Hex;
5
6
  caipAssetId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../../src/strategy/fiat/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AACnE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAQ3C,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,GAAG,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,GAAG,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAiBF,eAAO,MAAM,wBAAwB,EAAE,OAAO,CAC5C,MAAM,CAAC,eAAe,EAAE,uBAAuB,CAAC,CAKjD,CAAC"}
1
+ {"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../../src/strategy/fiat/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AACnE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAQ3C,eAAO,MAAM,qBAAqB,QAAQ,CAAC;AAE3C,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,GAAG,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,GAAG,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAiBF,eAAO,MAAM,wBAAwB,EAAE,OAAO,CAC5C,MAAM,CAAC,eAAe,EAAE,uBAAuB,CAAC,CAKjD,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { TransactionType } from "@metamask/transaction-controller";
2
2
  import { CHAIN_ID_ARBITRUM, CHAIN_ID_POLYGON, NATIVE_TOKEN_ADDRESS } from "../../constants.mjs";
3
+ export const DEFAULT_FIAT_CURRENCY = 'USD';
3
4
  const POLYGON_POL_FIAT_ASSET = {
4
5
  address: '0x0000000000000000000000000000000000001010',
5
6
  caipAssetId: 'eip155:137/slip44:966',
@@ -1 +1 @@
1
- {"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AAGnE,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACrB,4BAAwB;AASzB,MAAM,sBAAsB,GAA4B;IACtD,OAAO,EAAE,4CAA4C;IACrD,WAAW,EAAE,uBAAuB;IACpC,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,MAAM,uBAAuB,GAA4B;IACvD,OAAO,EAAE,oBAAoB;IAC7B,WAAW,EAAE,wBAAwB;IACrC,OAAO,EAAE,iBAAiB;IAC1B,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,uDAAuD;AACvD,MAAM,CAAC,MAAM,wBAAwB,GAEjC;IACF,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,sBAAsB;IACxD,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,uBAAuB;IACvD,CAAC,eAAe,CAAC,oBAAoB,CAAC,EAAE,uBAAuB;CAChE,CAAC","sourcesContent":["import { TransactionType } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n} from '../../constants';\n\nexport type TransactionPayFiatAsset = {\n address: Hex;\n caipAssetId: string;\n chainId: Hex;\n decimals: number;\n};\n\nconst POLYGON_POL_FIAT_ASSET: TransactionPayFiatAsset = {\n address: '0x0000000000000000000000000000000000001010',\n caipAssetId: 'eip155:137/slip44:966',\n chainId: CHAIN_ID_POLYGON,\n decimals: 18,\n};\n\nconst ARBITRUM_ETH_FIAT_ASSET: TransactionPayFiatAsset = {\n address: NATIVE_TOKEN_ADDRESS,\n caipAssetId: 'eip155:42161/slip44:60',\n chainId: CHAIN_ID_ARBITRUM,\n decimals: 18,\n};\n\n// We might use feature flags to determine these later.\nexport const FIAT_ASSET_ID_BY_TX_TYPE: Partial<\n Record<TransactionType, TransactionPayFiatAsset>\n> = {\n [TransactionType.predictDeposit]: POLYGON_POL_FIAT_ASSET,\n [TransactionType.perpsDeposit]: ARBITRUM_ETH_FIAT_ASSET,\n [TransactionType.perpsDepositAndOrder]: ARBITRUM_ETH_FIAT_ASSET,\n};\n"]}
1
+ {"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,yCAAyC;AAGnE,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACrB,4BAAwB;AAEzB,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAS3C,MAAM,sBAAsB,GAA4B;IACtD,OAAO,EAAE,4CAA4C;IACrD,WAAW,EAAE,uBAAuB;IACpC,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,MAAM,uBAAuB,GAA4B;IACvD,OAAO,EAAE,oBAAoB;IAC7B,WAAW,EAAE,wBAAwB;IACrC,OAAO,EAAE,iBAAiB;IAC1B,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,uDAAuD;AACvD,MAAM,CAAC,MAAM,wBAAwB,GAEjC;IACF,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,sBAAsB;IACxD,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,uBAAuB;IACvD,CAAC,eAAe,CAAC,oBAAoB,CAAC,EAAE,uBAAuB;CAChE,CAAC","sourcesContent":["import { TransactionType } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n} from '../../constants';\n\nexport const DEFAULT_FIAT_CURRENCY = 'USD';\n\nexport type TransactionPayFiatAsset = {\n address: Hex;\n caipAssetId: string;\n chainId: Hex;\n decimals: number;\n};\n\nconst POLYGON_POL_FIAT_ASSET: TransactionPayFiatAsset = {\n address: '0x0000000000000000000000000000000000001010',\n caipAssetId: 'eip155:137/slip44:966',\n chainId: CHAIN_ID_POLYGON,\n decimals: 18,\n};\n\nconst ARBITRUM_ETH_FIAT_ASSET: TransactionPayFiatAsset = {\n address: NATIVE_TOKEN_ADDRESS,\n caipAssetId: 'eip155:42161/slip44:60',\n chainId: CHAIN_ID_ARBITRUM,\n decimals: 18,\n};\n\n// We might use feature flags to determine these later.\nexport const FIAT_ASSET_ID_BY_TX_TYPE: Partial<\n Record<TransactionType, TransactionPayFiatAsset>\n> = {\n [TransactionType.predictDeposit]: POLYGON_POL_FIAT_ASSET,\n [TransactionType.perpsDeposit]: ARBITRUM_ETH_FIAT_ASSET,\n [TransactionType.perpsDepositAndOrder]: ARBITRUM_ETH_FIAT_ASSET,\n};\n"]}
@@ -7,6 +7,7 @@ const constants_1 = require("../../constants.cjs");
7
7
  const logger_1 = require("../../logger.cjs");
8
8
  const token_1 = require("../../utils/token.cjs");
9
9
  const relay_quotes_1 = require("../relay/relay-quotes.cjs");
10
+ const constants_2 = require("./constants.cjs");
10
11
  const utils_2 = require("./utils.cjs");
11
12
  const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'fiat-strategy');
12
13
  /**
@@ -82,19 +83,19 @@ async function getFiatQuotes(request) {
82
83
  sourceAmountRaw: relayRequest.sourceTokenAmount,
83
84
  transactionId,
84
85
  });
85
- const quotes = await messenger.call('RampsController:getQuotes', {
86
- amount: adjustedAmount,
87
- paymentMethods: [fiatPaymentMethod],
86
+ const fiatQuote = await getRampsQuote({
87
+ adjustedAmount,
88
+ fiatAsset,
89
+ fiatPaymentMethod,
90
+ messenger,
88
91
  walletAddress,
89
92
  });
90
- log('Fetched ramps quotes', {
91
- rampsQuotesCount: quotes.success?.length ?? 0,
93
+ messenger.call('TransactionPayController:updateFiatPayment', {
94
+ callback: (fiatPayment) => {
95
+ fiatPayment.rampsQuote = fiatQuote;
96
+ },
92
97
  transactionId,
93
98
  });
94
- const fiatQuote = (0, utils_2.pickBestFiatQuote)(quotes);
95
- if (!fiatQuote) {
96
- throw new Error('No matching ramps quote found for selected provider');
97
- }
98
99
  return [
99
100
  combineQuotes({
100
101
  adjustedAmountFiat: adjustedAmountFiat.toString(10),
@@ -113,6 +114,27 @@ exports.getFiatQuotes = getFiatQuotes;
113
114
  function getRequiredTokens(tokens) {
114
115
  return tokens?.filter((token) => !token.skipIfBalance) ?? [];
115
116
  }
117
+ async function getRampsQuote({ adjustedAmount, fiatAsset, fiatPaymentMethod, messenger, walletAddress, }) {
118
+ const rampsState = messenger.call('RampsController:getState');
119
+ const selectedProviderId = rampsState.providers.selected?.id;
120
+ const quotes = await messenger.call('RampsController:getQuotes', {
121
+ amount: adjustedAmount,
122
+ assetId: fiatAsset.caipAssetId,
123
+ fiat: constants_2.DEFAULT_FIAT_CURRENCY,
124
+ paymentMethods: [fiatPaymentMethod],
125
+ providers: selectedProviderId ? [selectedProviderId] : undefined,
126
+ walletAddress,
127
+ });
128
+ log('Fetched ramps quotes', {
129
+ quotesCount: quotes.success?.length ?? 0,
130
+ selectedProviderId,
131
+ });
132
+ const quote = quotes.success?.[0];
133
+ if (!quote) {
134
+ throw new Error('No matching ramps quote found for selected provider');
135
+ }
136
+ return quote;
137
+ }
116
138
  function buildRelayRequestFromAmountFiat({ amountFiat, fiatAsset, messenger, requiredToken, walletAddress, }) {
117
139
  const sourceFiatRate = (0, token_1.getTokenFiatRate)(messenger, fiatAsset.address, fiatAsset.chainId);
118
140
  if (!sourceFiatRate) {
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-quotes.cjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Quote as RampsQuote } from '@metamask/ramps-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TransactionPayStrategy } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayRequiredToken,\n TransactionPayQuote,\n} from '../../types';\nimport { computeRawFromFiatAmount, getTokenFiatRate } from '../../utils/token';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport type { RelayQuote } from '../relay/types';\nimport type { FiatQuote } from './types';\nimport { deriveFiatAssetForFiatPayment, pickBestFiatQuote } from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-strategy');\n\n/**\n * Fetches MM Pay fiat strategy quotes using a relay-first estimation flow.\n *\n * @param request - Strategy quotes request.\n * @returns A single combined fiat strategy quote, or an empty array when inputs/quotes are unavailable.\n * @remarks\n * Flow summary:\n * 1. Read `amountFiat` and selected payment method from transaction pay state.\n * 2. Build a synthetic relay request from `amountFiat` using source token USD rate.\n * 3. Fetch relay quote and compute total relay fee (`provider + source network + target network + MetaMask`).\n * 4. Call ramps quotes with `adjustedAmountFiat = amountFiat + relayTotalFeeUsd`.\n * 5. Pick the configured ramps provider quote and combine it with relay quote into one fiat strategy quote.\n */\nexport async function getFiatQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<FiatQuote>[]> {\n const { accountSupports7702, fiatPaymentMethod, messenger, transaction } =\n request;\n const transactionId = transaction.id;\n\n const state = messenger.call('TransactionPayController:getState');\n const transactionData = state.transactionData[transactionId];\n const amountFiat = transactionData?.fiatPayment?.amountFiat;\n const walletAddress = transaction.txParams.from as Hex;\n const requiredTokens = getRequiredTokens(transactionData?.tokens);\n const fiatAsset = deriveFiatAssetForFiatPayment(transaction);\n\n if (\n !amountFiat ||\n !fiatPaymentMethod ||\n !requiredTokens.length ||\n !fiatAsset\n ) {\n return [];\n }\n\n try {\n if (requiredTokens.length > 1) {\n throw new Error(\n 'Multiple required tokens not supported for fiat strategy',\n );\n }\n\n const requiredToken = requiredTokens[0];\n\n const relayRequest = buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n });\n\n if (!relayRequest) {\n throw new Error('Failed to build relay request from fiat amount');\n }\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702,\n messenger,\n requests: [relayRequest],\n transaction,\n });\n\n const relayQuote = relayQuotes[0];\n if (!relayQuote) {\n throw new Error('No relay quote available for fiat estimation');\n }\n\n const relayTotalFeeUsd = getRelayTotalFeeUsd(relayQuote);\n const adjustedAmountFiat = new BigNumber(amountFiat).plus(relayTotalFeeUsd);\n\n if (\n !adjustedAmountFiat.isFinite() ||\n !adjustedAmountFiat.gt(0) ||\n !relayTotalFeeUsd.isFinite() ||\n !relayTotalFeeUsd.gte(0)\n ) {\n throw new Error('Invalid fiat amount after relay fee adjustment');\n }\n\n const adjustedAmount = adjustedAmountFiat.toNumber();\n\n if (!Number.isFinite(adjustedAmount) || adjustedAmount <= 0) {\n throw new Error('Invalid fiat amount after relay fee adjustment');\n }\n\n log('Fiat quote flow', {\n adjustedAmountFiat: adjustedAmountFiat.toString(10),\n amountFiat,\n paymentMethods: [fiatPaymentMethod],\n relayTotalFeeUsd: relayTotalFeeUsd.toString(10),\n sourceAmountRaw: relayRequest.sourceTokenAmount,\n transactionId,\n });\n\n const quotes = await messenger.call('RampsController:getQuotes', {\n amount: adjustedAmount,\n paymentMethods: [fiatPaymentMethod],\n walletAddress,\n });\n\n log('Fetched ramps quotes', {\n rampsQuotesCount: quotes.success?.length ?? 0,\n transactionId,\n });\n\n const fiatQuote = pickBestFiatQuote(quotes);\n\n if (!fiatQuote) {\n throw new Error('No matching ramps quote found for selected provider');\n }\n\n return [\n combineQuotes({\n adjustedAmountFiat: adjustedAmountFiat.toString(10),\n amountFiat,\n fiatQuote,\n relayQuote,\n }),\n ];\n } catch (error) {\n log('Failed to fetch fiat quotes', { error, transactionId });\n }\n\n return [];\n}\n\nfunction getRequiredTokens(\n tokens?: TransactionPayRequiredToken[],\n): TransactionPayRequiredToken[] {\n return tokens?.filter((token) => !token.skipIfBalance) ?? [];\n}\n\nfunction buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n}: {\n amountFiat: string;\n fiatAsset: {\n address: Hex;\n chainId: Hex;\n decimals: number;\n };\n messenger: PayStrategyGetQuotesRequest['messenger'];\n requiredToken: TransactionPayRequiredToken;\n walletAddress: Hex;\n}): QuoteRequest | undefined {\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n fiatAsset.address,\n fiatAsset.chainId,\n );\n\n if (!sourceFiatRate) {\n return undefined;\n }\n\n const sourceAmountRaw = computeRawFromFiatAmount(\n amountFiat,\n fiatAsset.decimals,\n sourceFiatRate.usdRate,\n );\n\n if (!sourceAmountRaw) {\n return undefined;\n }\n\n return {\n from: walletAddress,\n // Force EXACT_INPUT mode: source amount is pre-calculated from the fiat\n // amount, so the relay should treat it as a fixed input rather than\n // computing it from the target.\n isPostQuote: true,\n sourceBalanceRaw: sourceAmountRaw,\n sourceChainId: fiatAsset.chainId,\n sourceTokenAddress: fiatAsset.address,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: requiredToken.amountRaw,\n targetChainId: requiredToken.chainId,\n targetTokenAddress: requiredToken.address,\n };\n}\n\n/**\n * Combines fiat and relay legs into a single MM Pay fiat strategy quote.\n *\n * @param params - Combined quote inputs.\n * @param params.adjustedAmountFiat - Fiat amount sent to ramps after adding relay fee estimate.\n * @param params.amountFiat - User-entered fiat amount.\n * @param params.fiatQuote - Selected ramps quote.\n * @param params.relayQuote - Estimated relay quote.\n * @returns A single fiat strategy quote with split fee buckets.\n * @remarks\n * Fee mapping contract for MM Pay Fiat strategy:\n * - `fees.provider`: Total provider fee (relay provider/swap fee + ramps provider/network fee).\n * Consumed by UI transaction fee row and tooltip provider fee.\n * - `fees.providerFiat`: Fiat on-ramp provider fees only (`providerFee + networkFee` from ramps quote).\n * Optional breakdown; client can derive relay portion via `provider - providerFiat`.\n * - `fees.sourceNetwork` / `fees.targetNetwork`: Relay settlement network fees.\n * Consumed by UI transaction fee row and tooltip network fee.\n * - `fees.metaMask`: MM Pay fee (currently 100 bps over `amountFiat + adjustedAmountFiat`).\n * Consumed by UI transaction fee row and tooltip MetaMask fee.\n * - `totals.total` should represent Amount + Transaction Fee using the totals pipeline.\n */\nfunction combineQuotes({\n adjustedAmountFiat,\n amountFiat,\n fiatQuote,\n relayQuote,\n}: {\n adjustedAmountFiat: string;\n amountFiat: string;\n fiatQuote: RampsQuote;\n relayQuote: TransactionPayQuote<RelayQuote>;\n}): TransactionPayQuote<FiatQuote> {\n const rampsProviderFee = getRampsProviderFee(fiatQuote);\n const totalProviderFee = new BigNumber(relayQuote.fees.provider.usd)\n .plus(rampsProviderFee)\n .toString(10);\n const rampsProviderFeeStr = rampsProviderFee.toString(10);\n const metaMaskFee = getMetaMaskFee({\n adjustedAmountFiat,\n amountFiat,\n }).toString(10);\n\n return {\n ...relayQuote,\n fees: {\n ...relayQuote.fees,\n metaMask: {\n fiat: metaMaskFee,\n usd: metaMaskFee,\n },\n provider: {\n fiat: totalProviderFee,\n usd: totalProviderFee,\n },\n providerFiat: {\n fiat: rampsProviderFeeStr,\n usd: rampsProviderFeeStr,\n },\n },\n original: {\n rampsQuote: fiatQuote,\n relayQuote: relayQuote.original,\n },\n strategy: TransactionPayStrategy.Fiat,\n };\n}\n\n/**\n * Ramps providers handle network gas fees themselves but report them separately\n * as `networkFee` alongside their `providerFee`. We combine both into a single\n * ramps provider fee for the `providerFiat` breakdown.\n *\n * @param fiatQuote - The ramps quote containing provider and network fees.\n * @returns Combined ramps provider fee as a BigNumber.\n */\nfunction getRampsProviderFee(fiatQuote: RampsQuote): BigNumber {\n return new BigNumber(fiatQuote.quote.providerFee ?? 0).plus(\n fiatQuote.quote.networkFee ?? 0,\n );\n}\n\nfunction getRelayTotalFeeUsd(\n relayQuote: TransactionPayQuote<RelayQuote>,\n): BigNumber {\n return new BigNumber(relayQuote.fees.provider.usd)\n .plus(relayQuote.fees.sourceNetwork.estimate.usd)\n .plus(relayQuote.fees.targetNetwork.usd)\n .plus(relayQuote.fees.metaMask.usd);\n}\n\nfunction getMetaMaskFee({\n adjustedAmountFiat,\n amountFiat,\n}: {\n adjustedAmountFiat: BigNumber.Value;\n amountFiat: BigNumber.Value;\n}): BigNumber {\n return new BigNumber(amountFiat).plus(adjustedAmountFiat).dividedBy(100);\n}\n"]}
1
+ {"version":3,"file":"fiat-quotes.cjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Quote as RampsQuote } from '@metamask/ramps-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TransactionPayStrategy } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayRequiredToken,\n TransactionPayQuote,\n} from '../../types';\nimport { computeRawFromFiatAmount, getTokenFiatRate } from '../../utils/token';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport type { RelayQuote } from '../relay/types';\nimport { DEFAULT_FIAT_CURRENCY } from './constants';\nimport type { TransactionPayFiatAsset } from './constants';\nimport type { FiatQuote } from './types';\nimport { deriveFiatAssetForFiatPayment } from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-strategy');\n\n/**\n * Fetches MM Pay fiat strategy quotes using a relay-first estimation flow.\n *\n * @param request - Strategy quotes request.\n * @returns A single combined fiat strategy quote, or an empty array when inputs/quotes are unavailable.\n * @remarks\n * Flow summary:\n * 1. Read `amountFiat` and selected payment method from transaction pay state.\n * 2. Build a synthetic relay request from `amountFiat` using source token USD rate.\n * 3. Fetch relay quote and compute total relay fee (`provider + source network + target network + MetaMask`).\n * 4. Call ramps quotes with `adjustedAmountFiat = amountFiat + relayTotalFeeUsd`.\n * 5. Pick the configured ramps provider quote and combine it with relay quote into one fiat strategy quote.\n */\nexport async function getFiatQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<FiatQuote>[]> {\n const { accountSupports7702, fiatPaymentMethod, messenger, transaction } =\n request;\n const transactionId = transaction.id;\n\n const state = messenger.call('TransactionPayController:getState');\n const transactionData = state.transactionData[transactionId];\n const amountFiat = transactionData?.fiatPayment?.amountFiat;\n const walletAddress = transaction.txParams.from as Hex;\n const requiredTokens = getRequiredTokens(transactionData?.tokens);\n const fiatAsset = deriveFiatAssetForFiatPayment(transaction);\n\n if (\n !amountFiat ||\n !fiatPaymentMethod ||\n !requiredTokens.length ||\n !fiatAsset\n ) {\n return [];\n }\n\n try {\n if (requiredTokens.length > 1) {\n throw new Error(\n 'Multiple required tokens not supported for fiat strategy',\n );\n }\n\n const requiredToken = requiredTokens[0];\n\n const relayRequest = buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n });\n\n if (!relayRequest) {\n throw new Error('Failed to build relay request from fiat amount');\n }\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702,\n messenger,\n requests: [relayRequest],\n transaction,\n });\n\n const relayQuote = relayQuotes[0];\n if (!relayQuote) {\n throw new Error('No relay quote available for fiat estimation');\n }\n\n const relayTotalFeeUsd = getRelayTotalFeeUsd(relayQuote);\n const adjustedAmountFiat = new BigNumber(amountFiat).plus(relayTotalFeeUsd);\n\n if (\n !adjustedAmountFiat.isFinite() ||\n !adjustedAmountFiat.gt(0) ||\n !relayTotalFeeUsd.isFinite() ||\n !relayTotalFeeUsd.gte(0)\n ) {\n throw new Error('Invalid fiat amount after relay fee adjustment');\n }\n\n const adjustedAmount = adjustedAmountFiat.toNumber();\n\n if (!Number.isFinite(adjustedAmount) || adjustedAmount <= 0) {\n throw new Error('Invalid fiat amount after relay fee adjustment');\n }\n\n log('Fiat quote flow', {\n adjustedAmountFiat: adjustedAmountFiat.toString(10),\n amountFiat,\n paymentMethods: [fiatPaymentMethod],\n relayTotalFeeUsd: relayTotalFeeUsd.toString(10),\n sourceAmountRaw: relayRequest.sourceTokenAmount,\n transactionId,\n });\n\n const fiatQuote = await getRampsQuote({\n adjustedAmount,\n fiatAsset,\n fiatPaymentMethod,\n messenger,\n walletAddress,\n });\n\n messenger.call('TransactionPayController:updateFiatPayment', {\n callback: (fiatPayment) => {\n fiatPayment.rampsQuote = fiatQuote;\n },\n transactionId,\n });\n\n return [\n combineQuotes({\n adjustedAmountFiat: adjustedAmountFiat.toString(10),\n amountFiat,\n fiatQuote,\n relayQuote,\n }),\n ];\n } catch (error) {\n log('Failed to fetch fiat quotes', { error, transactionId });\n }\n\n return [];\n}\n\nfunction getRequiredTokens(\n tokens?: TransactionPayRequiredToken[],\n): TransactionPayRequiredToken[] {\n return tokens?.filter((token) => !token.skipIfBalance) ?? [];\n}\n\nasync function getRampsQuote({\n adjustedAmount,\n fiatAsset,\n fiatPaymentMethod,\n messenger,\n walletAddress,\n}: {\n adjustedAmount: number;\n fiatAsset: TransactionPayFiatAsset;\n fiatPaymentMethod: string;\n messenger: PayStrategyGetQuotesRequest['messenger'];\n walletAddress: string;\n}): Promise<RampsQuote> {\n const rampsState = messenger.call('RampsController:getState');\n const selectedProviderId = rampsState.providers.selected?.id;\n\n const quotes = await messenger.call('RampsController:getQuotes', {\n amount: adjustedAmount,\n assetId: fiatAsset.caipAssetId,\n fiat: DEFAULT_FIAT_CURRENCY,\n paymentMethods: [fiatPaymentMethod],\n providers: selectedProviderId ? [selectedProviderId] : undefined,\n walletAddress,\n });\n\n log('Fetched ramps quotes', {\n quotesCount: quotes.success?.length ?? 0,\n selectedProviderId,\n });\n\n const quote = quotes.success?.[0];\n\n if (!quote) {\n throw new Error('No matching ramps quote found for selected provider');\n }\n\n return quote;\n}\n\nfunction buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n}: {\n amountFiat: string;\n fiatAsset: {\n address: Hex;\n chainId: Hex;\n decimals: number;\n };\n messenger: PayStrategyGetQuotesRequest['messenger'];\n requiredToken: TransactionPayRequiredToken;\n walletAddress: Hex;\n}): QuoteRequest | undefined {\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n fiatAsset.address,\n fiatAsset.chainId,\n );\n\n if (!sourceFiatRate) {\n return undefined;\n }\n\n const sourceAmountRaw = computeRawFromFiatAmount(\n amountFiat,\n fiatAsset.decimals,\n sourceFiatRate.usdRate,\n );\n\n if (!sourceAmountRaw) {\n return undefined;\n }\n\n return {\n from: walletAddress,\n // Force EXACT_INPUT mode: source amount is pre-calculated from the fiat\n // amount, so the relay should treat it as a fixed input rather than\n // computing it from the target.\n isPostQuote: true,\n sourceBalanceRaw: sourceAmountRaw,\n sourceChainId: fiatAsset.chainId,\n sourceTokenAddress: fiatAsset.address,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: requiredToken.amountRaw,\n targetChainId: requiredToken.chainId,\n targetTokenAddress: requiredToken.address,\n };\n}\n\n/**\n * Combines fiat and relay legs into a single MM Pay fiat strategy quote.\n *\n * @param params - Combined quote inputs.\n * @param params.adjustedAmountFiat - Fiat amount sent to ramps after adding relay fee estimate.\n * @param params.amountFiat - User-entered fiat amount.\n * @param params.fiatQuote - Selected ramps quote.\n * @param params.relayQuote - Estimated relay quote.\n * @returns A single fiat strategy quote with split fee buckets.\n * @remarks\n * Fee mapping contract for MM Pay Fiat strategy:\n * - `fees.provider`: Total provider fee (relay provider/swap fee + ramps provider/network fee).\n * Consumed by UI transaction fee row and tooltip provider fee.\n * - `fees.providerFiat`: Fiat on-ramp provider fees only (`providerFee + networkFee` from ramps quote).\n * Optional breakdown; client can derive relay portion via `provider - providerFiat`.\n * - `fees.sourceNetwork` / `fees.targetNetwork`: Relay settlement network fees.\n * Consumed by UI transaction fee row and tooltip network fee.\n * - `fees.metaMask`: MM Pay fee (currently 100 bps over `amountFiat + adjustedAmountFiat`).\n * Consumed by UI transaction fee row and tooltip MetaMask fee.\n * - `totals.total` should represent Amount + Transaction Fee using the totals pipeline.\n */\nfunction combineQuotes({\n adjustedAmountFiat,\n amountFiat,\n fiatQuote,\n relayQuote,\n}: {\n adjustedAmountFiat: string;\n amountFiat: string;\n fiatQuote: RampsQuote;\n relayQuote: TransactionPayQuote<RelayQuote>;\n}): TransactionPayQuote<FiatQuote> {\n const rampsProviderFee = getRampsProviderFee(fiatQuote);\n const totalProviderFee = new BigNumber(relayQuote.fees.provider.usd)\n .plus(rampsProviderFee)\n .toString(10);\n const rampsProviderFeeStr = rampsProviderFee.toString(10);\n const metaMaskFee = getMetaMaskFee({\n adjustedAmountFiat,\n amountFiat,\n }).toString(10);\n\n return {\n ...relayQuote,\n fees: {\n ...relayQuote.fees,\n metaMask: {\n fiat: metaMaskFee,\n usd: metaMaskFee,\n },\n provider: {\n fiat: totalProviderFee,\n usd: totalProviderFee,\n },\n providerFiat: {\n fiat: rampsProviderFeeStr,\n usd: rampsProviderFeeStr,\n },\n },\n original: {\n rampsQuote: fiatQuote,\n relayQuote: relayQuote.original,\n },\n strategy: TransactionPayStrategy.Fiat,\n };\n}\n\n/**\n * Ramps providers handle network gas fees themselves but report them separately\n * as `networkFee` alongside their `providerFee`. We combine both into a single\n * ramps provider fee for the `providerFiat` breakdown.\n *\n * @param fiatQuote - The ramps quote containing provider and network fees.\n * @returns Combined ramps provider fee as a BigNumber.\n */\nfunction getRampsProviderFee(fiatQuote: RampsQuote): BigNumber {\n return new BigNumber(fiatQuote.quote.providerFee ?? 0).plus(\n fiatQuote.quote.networkFee ?? 0,\n );\n}\n\nfunction getRelayTotalFeeUsd(\n relayQuote: TransactionPayQuote<RelayQuote>,\n): BigNumber {\n return new BigNumber(relayQuote.fees.provider.usd)\n .plus(relayQuote.fees.sourceNetwork.estimate.usd)\n .plus(relayQuote.fees.targetNetwork.usd)\n .plus(relayQuote.fees.metaMask.usd);\n}\n\nfunction getMetaMaskFee({\n adjustedAmountFiat,\n amountFiat,\n}: {\n adjustedAmountFiat: BigNumber.Value;\n amountFiat: BigNumber.Value;\n}): BigNumber {\n return new BigNumber(amountFiat).plus(adjustedAmountFiat).dividedBy(100);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-quotes.d.cts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-quotes.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,2BAA2B,EAG3B,mBAAmB,EACpB,wBAAoB;AAIrB,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC,CA+G3C"}
1
+ {"version":3,"file":"fiat-quotes.d.cts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-quotes.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,2BAA2B,EAG3B,mBAAmB,EACpB,wBAAoB;AAMrB,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC,CA6G3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-quotes.d.mts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-quotes.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,2BAA2B,EAG3B,mBAAmB,EACpB,wBAAoB;AAIrB,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC,CA+G3C"}
1
+ {"version":3,"file":"fiat-quotes.d.mts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-quotes.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,2BAA2B,EAG3B,mBAAmB,EACpB,wBAAoB;AAMrB,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC,CA6G3C"}
@@ -4,7 +4,8 @@ import { TransactionPayStrategy } from "../../constants.mjs";
4
4
  import { projectLogger } from "../../logger.mjs";
5
5
  import { computeRawFromFiatAmount, getTokenFiatRate } from "../../utils/token.mjs";
6
6
  import { getRelayQuotes } from "../relay/relay-quotes.mjs";
7
- import { deriveFiatAssetForFiatPayment, pickBestFiatQuote } from "./utils.mjs";
7
+ import { DEFAULT_FIAT_CURRENCY } from "./constants.mjs";
8
+ import { deriveFiatAssetForFiatPayment } from "./utils.mjs";
8
9
  const log = createModuleLogger(projectLogger, 'fiat-strategy');
9
10
  /**
10
11
  * Fetches MM Pay fiat strategy quotes using a relay-first estimation flow.
@@ -79,19 +80,19 @@ export async function getFiatQuotes(request) {
79
80
  sourceAmountRaw: relayRequest.sourceTokenAmount,
80
81
  transactionId,
81
82
  });
82
- const quotes = await messenger.call('RampsController:getQuotes', {
83
- amount: adjustedAmount,
84
- paymentMethods: [fiatPaymentMethod],
83
+ const fiatQuote = await getRampsQuote({
84
+ adjustedAmount,
85
+ fiatAsset,
86
+ fiatPaymentMethod,
87
+ messenger,
85
88
  walletAddress,
86
89
  });
87
- log('Fetched ramps quotes', {
88
- rampsQuotesCount: quotes.success?.length ?? 0,
90
+ messenger.call('TransactionPayController:updateFiatPayment', {
91
+ callback: (fiatPayment) => {
92
+ fiatPayment.rampsQuote = fiatQuote;
93
+ },
89
94
  transactionId,
90
95
  });
91
- const fiatQuote = pickBestFiatQuote(quotes);
92
- if (!fiatQuote) {
93
- throw new Error('No matching ramps quote found for selected provider');
94
- }
95
96
  return [
96
97
  combineQuotes({
97
98
  adjustedAmountFiat: adjustedAmountFiat.toString(10),
@@ -109,6 +110,27 @@ export async function getFiatQuotes(request) {
109
110
  function getRequiredTokens(tokens) {
110
111
  return tokens?.filter((token) => !token.skipIfBalance) ?? [];
111
112
  }
113
+ async function getRampsQuote({ adjustedAmount, fiatAsset, fiatPaymentMethod, messenger, walletAddress, }) {
114
+ const rampsState = messenger.call('RampsController:getState');
115
+ const selectedProviderId = rampsState.providers.selected?.id;
116
+ const quotes = await messenger.call('RampsController:getQuotes', {
117
+ amount: adjustedAmount,
118
+ assetId: fiatAsset.caipAssetId,
119
+ fiat: DEFAULT_FIAT_CURRENCY,
120
+ paymentMethods: [fiatPaymentMethod],
121
+ providers: selectedProviderId ? [selectedProviderId] : undefined,
122
+ walletAddress,
123
+ });
124
+ log('Fetched ramps quotes', {
125
+ quotesCount: quotes.success?.length ?? 0,
126
+ selectedProviderId,
127
+ });
128
+ const quote = quotes.success?.[0];
129
+ if (!quote) {
130
+ throw new Error('No matching ramps quote found for selected provider');
131
+ }
132
+ return quote;
133
+ }
112
134
  function buildRelayRequestFromAmountFiat({ amountFiat, fiatAsset, messenger, requiredToken, walletAddress, }) {
113
135
  const sourceFiatRate = getTokenFiatRate(messenger, fiatAsset.address, fiatAsset.chainId);
114
136
  if (!sourceFiatRate) {
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-quotes.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Quote as RampsQuote } from '@metamask/ramps-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TransactionPayStrategy } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayRequiredToken,\n TransactionPayQuote,\n} from '../../types';\nimport { computeRawFromFiatAmount, getTokenFiatRate } from '../../utils/token';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport type { RelayQuote } from '../relay/types';\nimport type { FiatQuote } from './types';\nimport { deriveFiatAssetForFiatPayment, pickBestFiatQuote } from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-strategy');\n\n/**\n * Fetches MM Pay fiat strategy quotes using a relay-first estimation flow.\n *\n * @param request - Strategy quotes request.\n * @returns A single combined fiat strategy quote, or an empty array when inputs/quotes are unavailable.\n * @remarks\n * Flow summary:\n * 1. Read `amountFiat` and selected payment method from transaction pay state.\n * 2. Build a synthetic relay request from `amountFiat` using source token USD rate.\n * 3. Fetch relay quote and compute total relay fee (`provider + source network + target network + MetaMask`).\n * 4. Call ramps quotes with `adjustedAmountFiat = amountFiat + relayTotalFeeUsd`.\n * 5. Pick the configured ramps provider quote and combine it with relay quote into one fiat strategy quote.\n */\nexport async function getFiatQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<FiatQuote>[]> {\n const { accountSupports7702, fiatPaymentMethod, messenger, transaction } =\n request;\n const transactionId = transaction.id;\n\n const state = messenger.call('TransactionPayController:getState');\n const transactionData = state.transactionData[transactionId];\n const amountFiat = transactionData?.fiatPayment?.amountFiat;\n const walletAddress = transaction.txParams.from as Hex;\n const requiredTokens = getRequiredTokens(transactionData?.tokens);\n const fiatAsset = deriveFiatAssetForFiatPayment(transaction);\n\n if (\n !amountFiat ||\n !fiatPaymentMethod ||\n !requiredTokens.length ||\n !fiatAsset\n ) {\n return [];\n }\n\n try {\n if (requiredTokens.length > 1) {\n throw new Error(\n 'Multiple required tokens not supported for fiat strategy',\n );\n }\n\n const requiredToken = requiredTokens[0];\n\n const relayRequest = buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n });\n\n if (!relayRequest) {\n throw new Error('Failed to build relay request from fiat amount');\n }\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702,\n messenger,\n requests: [relayRequest],\n transaction,\n });\n\n const relayQuote = relayQuotes[0];\n if (!relayQuote) {\n throw new Error('No relay quote available for fiat estimation');\n }\n\n const relayTotalFeeUsd = getRelayTotalFeeUsd(relayQuote);\n const adjustedAmountFiat = new BigNumber(amountFiat).plus(relayTotalFeeUsd);\n\n if (\n !adjustedAmountFiat.isFinite() ||\n !adjustedAmountFiat.gt(0) ||\n !relayTotalFeeUsd.isFinite() ||\n !relayTotalFeeUsd.gte(0)\n ) {\n throw new Error('Invalid fiat amount after relay fee adjustment');\n }\n\n const adjustedAmount = adjustedAmountFiat.toNumber();\n\n if (!Number.isFinite(adjustedAmount) || adjustedAmount <= 0) {\n throw new Error('Invalid fiat amount after relay fee adjustment');\n }\n\n log('Fiat quote flow', {\n adjustedAmountFiat: adjustedAmountFiat.toString(10),\n amountFiat,\n paymentMethods: [fiatPaymentMethod],\n relayTotalFeeUsd: relayTotalFeeUsd.toString(10),\n sourceAmountRaw: relayRequest.sourceTokenAmount,\n transactionId,\n });\n\n const quotes = await messenger.call('RampsController:getQuotes', {\n amount: adjustedAmount,\n paymentMethods: [fiatPaymentMethod],\n walletAddress,\n });\n\n log('Fetched ramps quotes', {\n rampsQuotesCount: quotes.success?.length ?? 0,\n transactionId,\n });\n\n const fiatQuote = pickBestFiatQuote(quotes);\n\n if (!fiatQuote) {\n throw new Error('No matching ramps quote found for selected provider');\n }\n\n return [\n combineQuotes({\n adjustedAmountFiat: adjustedAmountFiat.toString(10),\n amountFiat,\n fiatQuote,\n relayQuote,\n }),\n ];\n } catch (error) {\n log('Failed to fetch fiat quotes', { error, transactionId });\n }\n\n return [];\n}\n\nfunction getRequiredTokens(\n tokens?: TransactionPayRequiredToken[],\n): TransactionPayRequiredToken[] {\n return tokens?.filter((token) => !token.skipIfBalance) ?? [];\n}\n\nfunction buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n}: {\n amountFiat: string;\n fiatAsset: {\n address: Hex;\n chainId: Hex;\n decimals: number;\n };\n messenger: PayStrategyGetQuotesRequest['messenger'];\n requiredToken: TransactionPayRequiredToken;\n walletAddress: Hex;\n}): QuoteRequest | undefined {\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n fiatAsset.address,\n fiatAsset.chainId,\n );\n\n if (!sourceFiatRate) {\n return undefined;\n }\n\n const sourceAmountRaw = computeRawFromFiatAmount(\n amountFiat,\n fiatAsset.decimals,\n sourceFiatRate.usdRate,\n );\n\n if (!sourceAmountRaw) {\n return undefined;\n }\n\n return {\n from: walletAddress,\n // Force EXACT_INPUT mode: source amount is pre-calculated from the fiat\n // amount, so the relay should treat it as a fixed input rather than\n // computing it from the target.\n isPostQuote: true,\n sourceBalanceRaw: sourceAmountRaw,\n sourceChainId: fiatAsset.chainId,\n sourceTokenAddress: fiatAsset.address,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: requiredToken.amountRaw,\n targetChainId: requiredToken.chainId,\n targetTokenAddress: requiredToken.address,\n };\n}\n\n/**\n * Combines fiat and relay legs into a single MM Pay fiat strategy quote.\n *\n * @param params - Combined quote inputs.\n * @param params.adjustedAmountFiat - Fiat amount sent to ramps after adding relay fee estimate.\n * @param params.amountFiat - User-entered fiat amount.\n * @param params.fiatQuote - Selected ramps quote.\n * @param params.relayQuote - Estimated relay quote.\n * @returns A single fiat strategy quote with split fee buckets.\n * @remarks\n * Fee mapping contract for MM Pay Fiat strategy:\n * - `fees.provider`: Total provider fee (relay provider/swap fee + ramps provider/network fee).\n * Consumed by UI transaction fee row and tooltip provider fee.\n * - `fees.providerFiat`: Fiat on-ramp provider fees only (`providerFee + networkFee` from ramps quote).\n * Optional breakdown; client can derive relay portion via `provider - providerFiat`.\n * - `fees.sourceNetwork` / `fees.targetNetwork`: Relay settlement network fees.\n * Consumed by UI transaction fee row and tooltip network fee.\n * - `fees.metaMask`: MM Pay fee (currently 100 bps over `amountFiat + adjustedAmountFiat`).\n * Consumed by UI transaction fee row and tooltip MetaMask fee.\n * - `totals.total` should represent Amount + Transaction Fee using the totals pipeline.\n */\nfunction combineQuotes({\n adjustedAmountFiat,\n amountFiat,\n fiatQuote,\n relayQuote,\n}: {\n adjustedAmountFiat: string;\n amountFiat: string;\n fiatQuote: RampsQuote;\n relayQuote: TransactionPayQuote<RelayQuote>;\n}): TransactionPayQuote<FiatQuote> {\n const rampsProviderFee = getRampsProviderFee(fiatQuote);\n const totalProviderFee = new BigNumber(relayQuote.fees.provider.usd)\n .plus(rampsProviderFee)\n .toString(10);\n const rampsProviderFeeStr = rampsProviderFee.toString(10);\n const metaMaskFee = getMetaMaskFee({\n adjustedAmountFiat,\n amountFiat,\n }).toString(10);\n\n return {\n ...relayQuote,\n fees: {\n ...relayQuote.fees,\n metaMask: {\n fiat: metaMaskFee,\n usd: metaMaskFee,\n },\n provider: {\n fiat: totalProviderFee,\n usd: totalProviderFee,\n },\n providerFiat: {\n fiat: rampsProviderFeeStr,\n usd: rampsProviderFeeStr,\n },\n },\n original: {\n rampsQuote: fiatQuote,\n relayQuote: relayQuote.original,\n },\n strategy: TransactionPayStrategy.Fiat,\n };\n}\n\n/**\n * Ramps providers handle network gas fees themselves but report them separately\n * as `networkFee` alongside their `providerFee`. We combine both into a single\n * ramps provider fee for the `providerFiat` breakdown.\n *\n * @param fiatQuote - The ramps quote containing provider and network fees.\n * @returns Combined ramps provider fee as a BigNumber.\n */\nfunction getRampsProviderFee(fiatQuote: RampsQuote): BigNumber {\n return new BigNumber(fiatQuote.quote.providerFee ?? 0).plus(\n fiatQuote.quote.networkFee ?? 0,\n );\n}\n\nfunction getRelayTotalFeeUsd(\n relayQuote: TransactionPayQuote<RelayQuote>,\n): BigNumber {\n return new BigNumber(relayQuote.fees.provider.usd)\n .plus(relayQuote.fees.sourceNetwork.estimate.usd)\n .plus(relayQuote.fees.targetNetwork.usd)\n .plus(relayQuote.fees.metaMask.usd);\n}\n\nfunction getMetaMaskFee({\n adjustedAmountFiat,\n amountFiat,\n}: {\n adjustedAmountFiat: BigNumber.Value;\n amountFiat: BigNumber.Value;\n}): BigNumber {\n return new BigNumber(amountFiat).plus(adjustedAmountFiat).dividedBy(100);\n}\n"]}
1
+ {"version":3,"file":"fiat-quotes.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Quote as RampsQuote } from '@metamask/ramps-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TransactionPayStrategy } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayRequiredToken,\n TransactionPayQuote,\n} from '../../types';\nimport { computeRawFromFiatAmount, getTokenFiatRate } from '../../utils/token';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport type { RelayQuote } from '../relay/types';\nimport { DEFAULT_FIAT_CURRENCY } from './constants';\nimport type { TransactionPayFiatAsset } from './constants';\nimport type { FiatQuote } from './types';\nimport { deriveFiatAssetForFiatPayment } from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-strategy');\n\n/**\n * Fetches MM Pay fiat strategy quotes using a relay-first estimation flow.\n *\n * @param request - Strategy quotes request.\n * @returns A single combined fiat strategy quote, or an empty array when inputs/quotes are unavailable.\n * @remarks\n * Flow summary:\n * 1. Read `amountFiat` and selected payment method from transaction pay state.\n * 2. Build a synthetic relay request from `amountFiat` using source token USD rate.\n * 3. Fetch relay quote and compute total relay fee (`provider + source network + target network + MetaMask`).\n * 4. Call ramps quotes with `adjustedAmountFiat = amountFiat + relayTotalFeeUsd`.\n * 5. Pick the configured ramps provider quote and combine it with relay quote into one fiat strategy quote.\n */\nexport async function getFiatQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<FiatQuote>[]> {\n const { accountSupports7702, fiatPaymentMethod, messenger, transaction } =\n request;\n const transactionId = transaction.id;\n\n const state = messenger.call('TransactionPayController:getState');\n const transactionData = state.transactionData[transactionId];\n const amountFiat = transactionData?.fiatPayment?.amountFiat;\n const walletAddress = transaction.txParams.from as Hex;\n const requiredTokens = getRequiredTokens(transactionData?.tokens);\n const fiatAsset = deriveFiatAssetForFiatPayment(transaction);\n\n if (\n !amountFiat ||\n !fiatPaymentMethod ||\n !requiredTokens.length ||\n !fiatAsset\n ) {\n return [];\n }\n\n try {\n if (requiredTokens.length > 1) {\n throw new Error(\n 'Multiple required tokens not supported for fiat strategy',\n );\n }\n\n const requiredToken = requiredTokens[0];\n\n const relayRequest = buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n });\n\n if (!relayRequest) {\n throw new Error('Failed to build relay request from fiat amount');\n }\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702,\n messenger,\n requests: [relayRequest],\n transaction,\n });\n\n const relayQuote = relayQuotes[0];\n if (!relayQuote) {\n throw new Error('No relay quote available for fiat estimation');\n }\n\n const relayTotalFeeUsd = getRelayTotalFeeUsd(relayQuote);\n const adjustedAmountFiat = new BigNumber(amountFiat).plus(relayTotalFeeUsd);\n\n if (\n !adjustedAmountFiat.isFinite() ||\n !adjustedAmountFiat.gt(0) ||\n !relayTotalFeeUsd.isFinite() ||\n !relayTotalFeeUsd.gte(0)\n ) {\n throw new Error('Invalid fiat amount after relay fee adjustment');\n }\n\n const adjustedAmount = adjustedAmountFiat.toNumber();\n\n if (!Number.isFinite(adjustedAmount) || adjustedAmount <= 0) {\n throw new Error('Invalid fiat amount after relay fee adjustment');\n }\n\n log('Fiat quote flow', {\n adjustedAmountFiat: adjustedAmountFiat.toString(10),\n amountFiat,\n paymentMethods: [fiatPaymentMethod],\n relayTotalFeeUsd: relayTotalFeeUsd.toString(10),\n sourceAmountRaw: relayRequest.sourceTokenAmount,\n transactionId,\n });\n\n const fiatQuote = await getRampsQuote({\n adjustedAmount,\n fiatAsset,\n fiatPaymentMethod,\n messenger,\n walletAddress,\n });\n\n messenger.call('TransactionPayController:updateFiatPayment', {\n callback: (fiatPayment) => {\n fiatPayment.rampsQuote = fiatQuote;\n },\n transactionId,\n });\n\n return [\n combineQuotes({\n adjustedAmountFiat: adjustedAmountFiat.toString(10),\n amountFiat,\n fiatQuote,\n relayQuote,\n }),\n ];\n } catch (error) {\n log('Failed to fetch fiat quotes', { error, transactionId });\n }\n\n return [];\n}\n\nfunction getRequiredTokens(\n tokens?: TransactionPayRequiredToken[],\n): TransactionPayRequiredToken[] {\n return tokens?.filter((token) => !token.skipIfBalance) ?? [];\n}\n\nasync function getRampsQuote({\n adjustedAmount,\n fiatAsset,\n fiatPaymentMethod,\n messenger,\n walletAddress,\n}: {\n adjustedAmount: number;\n fiatAsset: TransactionPayFiatAsset;\n fiatPaymentMethod: string;\n messenger: PayStrategyGetQuotesRequest['messenger'];\n walletAddress: string;\n}): Promise<RampsQuote> {\n const rampsState = messenger.call('RampsController:getState');\n const selectedProviderId = rampsState.providers.selected?.id;\n\n const quotes = await messenger.call('RampsController:getQuotes', {\n amount: adjustedAmount,\n assetId: fiatAsset.caipAssetId,\n fiat: DEFAULT_FIAT_CURRENCY,\n paymentMethods: [fiatPaymentMethod],\n providers: selectedProviderId ? [selectedProviderId] : undefined,\n walletAddress,\n });\n\n log('Fetched ramps quotes', {\n quotesCount: quotes.success?.length ?? 0,\n selectedProviderId,\n });\n\n const quote = quotes.success?.[0];\n\n if (!quote) {\n throw new Error('No matching ramps quote found for selected provider');\n }\n\n return quote;\n}\n\nfunction buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n}: {\n amountFiat: string;\n fiatAsset: {\n address: Hex;\n chainId: Hex;\n decimals: number;\n };\n messenger: PayStrategyGetQuotesRequest['messenger'];\n requiredToken: TransactionPayRequiredToken;\n walletAddress: Hex;\n}): QuoteRequest | undefined {\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n fiatAsset.address,\n fiatAsset.chainId,\n );\n\n if (!sourceFiatRate) {\n return undefined;\n }\n\n const sourceAmountRaw = computeRawFromFiatAmount(\n amountFiat,\n fiatAsset.decimals,\n sourceFiatRate.usdRate,\n );\n\n if (!sourceAmountRaw) {\n return undefined;\n }\n\n return {\n from: walletAddress,\n // Force EXACT_INPUT mode: source amount is pre-calculated from the fiat\n // amount, so the relay should treat it as a fixed input rather than\n // computing it from the target.\n isPostQuote: true,\n sourceBalanceRaw: sourceAmountRaw,\n sourceChainId: fiatAsset.chainId,\n sourceTokenAddress: fiatAsset.address,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: requiredToken.amountRaw,\n targetChainId: requiredToken.chainId,\n targetTokenAddress: requiredToken.address,\n };\n}\n\n/**\n * Combines fiat and relay legs into a single MM Pay fiat strategy quote.\n *\n * @param params - Combined quote inputs.\n * @param params.adjustedAmountFiat - Fiat amount sent to ramps after adding relay fee estimate.\n * @param params.amountFiat - User-entered fiat amount.\n * @param params.fiatQuote - Selected ramps quote.\n * @param params.relayQuote - Estimated relay quote.\n * @returns A single fiat strategy quote with split fee buckets.\n * @remarks\n * Fee mapping contract for MM Pay Fiat strategy:\n * - `fees.provider`: Total provider fee (relay provider/swap fee + ramps provider/network fee).\n * Consumed by UI transaction fee row and tooltip provider fee.\n * - `fees.providerFiat`: Fiat on-ramp provider fees only (`providerFee + networkFee` from ramps quote).\n * Optional breakdown; client can derive relay portion via `provider - providerFiat`.\n * - `fees.sourceNetwork` / `fees.targetNetwork`: Relay settlement network fees.\n * Consumed by UI transaction fee row and tooltip network fee.\n * - `fees.metaMask`: MM Pay fee (currently 100 bps over `amountFiat + adjustedAmountFiat`).\n * Consumed by UI transaction fee row and tooltip MetaMask fee.\n * - `totals.total` should represent Amount + Transaction Fee using the totals pipeline.\n */\nfunction combineQuotes({\n adjustedAmountFiat,\n amountFiat,\n fiatQuote,\n relayQuote,\n}: {\n adjustedAmountFiat: string;\n amountFiat: string;\n fiatQuote: RampsQuote;\n relayQuote: TransactionPayQuote<RelayQuote>;\n}): TransactionPayQuote<FiatQuote> {\n const rampsProviderFee = getRampsProviderFee(fiatQuote);\n const totalProviderFee = new BigNumber(relayQuote.fees.provider.usd)\n .plus(rampsProviderFee)\n .toString(10);\n const rampsProviderFeeStr = rampsProviderFee.toString(10);\n const metaMaskFee = getMetaMaskFee({\n adjustedAmountFiat,\n amountFiat,\n }).toString(10);\n\n return {\n ...relayQuote,\n fees: {\n ...relayQuote.fees,\n metaMask: {\n fiat: metaMaskFee,\n usd: metaMaskFee,\n },\n provider: {\n fiat: totalProviderFee,\n usd: totalProviderFee,\n },\n providerFiat: {\n fiat: rampsProviderFeeStr,\n usd: rampsProviderFeeStr,\n },\n },\n original: {\n rampsQuote: fiatQuote,\n relayQuote: relayQuote.original,\n },\n strategy: TransactionPayStrategy.Fiat,\n };\n}\n\n/**\n * Ramps providers handle network gas fees themselves but report them separately\n * as `networkFee` alongside their `providerFee`. We combine both into a single\n * ramps provider fee for the `providerFiat` breakdown.\n *\n * @param fiatQuote - The ramps quote containing provider and network fees.\n * @returns Combined ramps provider fee as a BigNumber.\n */\nfunction getRampsProviderFee(fiatQuote: RampsQuote): BigNumber {\n return new BigNumber(fiatQuote.quote.providerFee ?? 0).plus(\n fiatQuote.quote.networkFee ?? 0,\n );\n}\n\nfunction getRelayTotalFeeUsd(\n relayQuote: TransactionPayQuote<RelayQuote>,\n): BigNumber {\n return new BigNumber(relayQuote.fees.provider.usd)\n .plus(relayQuote.fees.sourceNetwork.estimate.usd)\n .plus(relayQuote.fees.targetNetwork.usd)\n .plus(relayQuote.fees.metaMask.usd);\n}\n\nfunction getMetaMaskFee({\n adjustedAmountFiat,\n amountFiat,\n}: {\n adjustedAmountFiat: BigNumber.Value;\n amountFiat: BigNumber.Value;\n}): BigNumber {\n return new BigNumber(amountFiat).plus(adjustedAmountFiat).dividedBy(100);\n}\n"]}