@metamask/transaction-pay-controller 10.4.0 → 10.5.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 (118) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/dist/TransactionPayController.cjs +3 -1
  3. package/dist/TransactionPayController.cjs.map +1 -1
  4. package/dist/TransactionPayController.d.cts.map +1 -1
  5. package/dist/TransactionPayController.d.mts.map +1 -1
  6. package/dist/TransactionPayController.mjs +3 -1
  7. package/dist/TransactionPayController.mjs.map +1 -1
  8. package/dist/actions/update-payment-token.cjs.map +1 -1
  9. package/dist/actions/update-payment-token.d.cts.map +1 -1
  10. package/dist/actions/update-payment-token.d.mts.map +1 -1
  11. package/dist/actions/update-payment-token.mjs.map +1 -1
  12. package/dist/helpers/QuoteRefresher.cjs.map +1 -1
  13. package/dist/helpers/QuoteRefresher.mjs.map +1 -1
  14. package/dist/strategy/bridge/BridgeStrategy.cjs.map +1 -1
  15. package/dist/strategy/bridge/BridgeStrategy.d.cts +5 -6
  16. package/dist/strategy/bridge/BridgeStrategy.d.cts.map +1 -1
  17. package/dist/strategy/bridge/BridgeStrategy.d.mts +5 -6
  18. package/dist/strategy/bridge/BridgeStrategy.d.mts.map +1 -1
  19. package/dist/strategy/bridge/BridgeStrategy.mjs.map +1 -1
  20. package/dist/strategy/bridge/bridge-quotes.cjs +3 -3
  21. package/dist/strategy/bridge/bridge-quotes.cjs.map +1 -1
  22. package/dist/strategy/bridge/bridge-quotes.mjs +3 -3
  23. package/dist/strategy/bridge/bridge-quotes.mjs.map +1 -1
  24. package/dist/strategy/bridge/bridge-submit.cjs +1 -3
  25. package/dist/strategy/bridge/bridge-submit.cjs.map +1 -1
  26. package/dist/strategy/bridge/bridge-submit.mjs +1 -3
  27. package/dist/strategy/bridge/bridge-submit.mjs.map +1 -1
  28. package/dist/strategy/relay/RelayStrategy.cjs.map +1 -1
  29. package/dist/strategy/relay/RelayStrategy.d.cts +3 -5
  30. package/dist/strategy/relay/RelayStrategy.d.cts.map +1 -1
  31. package/dist/strategy/relay/RelayStrategy.d.mts +3 -5
  32. package/dist/strategy/relay/RelayStrategy.d.mts.map +1 -1
  33. package/dist/strategy/relay/RelayStrategy.mjs.map +1 -1
  34. package/dist/strategy/relay/relay-quotes.cjs +158 -40
  35. package/dist/strategy/relay/relay-quotes.cjs.map +1 -1
  36. package/dist/strategy/relay/relay-quotes.d.cts.map +1 -1
  37. package/dist/strategy/relay/relay-quotes.d.mts.map +1 -1
  38. package/dist/strategy/relay/relay-quotes.mjs +159 -41
  39. package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
  40. package/dist/strategy/relay/relay-submit.cjs +31 -18
  41. package/dist/strategy/relay/relay-submit.cjs.map +1 -1
  42. package/dist/strategy/relay/relay-submit.mjs +31 -18
  43. package/dist/strategy/relay/relay-submit.mjs.map +1 -1
  44. package/dist/strategy/relay/types.cjs.map +1 -1
  45. package/dist/strategy/relay/types.d.cts +4 -1
  46. package/dist/strategy/relay/types.d.cts.map +1 -1
  47. package/dist/strategy/relay/types.d.mts +4 -1
  48. package/dist/strategy/relay/types.d.mts.map +1 -1
  49. package/dist/strategy/relay/types.mjs.map +1 -1
  50. package/dist/strategy/test/TestStrategy.cjs.map +1 -1
  51. package/dist/strategy/test/TestStrategy.d.cts +1 -3
  52. package/dist/strategy/test/TestStrategy.d.cts.map +1 -1
  53. package/dist/strategy/test/TestStrategy.d.mts +1 -3
  54. package/dist/strategy/test/TestStrategy.d.mts.map +1 -1
  55. package/dist/strategy/test/TestStrategy.mjs.map +1 -1
  56. package/dist/tests/messenger-mock.cjs +7 -0
  57. package/dist/tests/messenger-mock.cjs.map +1 -1
  58. package/dist/tests/messenger-mock.d.cts +21 -0
  59. package/dist/tests/messenger-mock.d.cts.map +1 -1
  60. package/dist/tests/messenger-mock.d.mts +21 -0
  61. package/dist/tests/messenger-mock.d.mts.map +1 -1
  62. package/dist/tests/messenger-mock.mjs +7 -0
  63. package/dist/tests/messenger-mock.mjs.map +1 -1
  64. package/dist/types.cjs.map +1 -1
  65. package/dist/types.d.cts +2 -2
  66. package/dist/types.d.cts.map +1 -1
  67. package/dist/types.d.mts +2 -2
  68. package/dist/types.d.mts.map +1 -1
  69. package/dist/types.mjs.map +1 -1
  70. package/dist/utils/feature-flags.cjs +27 -3
  71. package/dist/utils/feature-flags.cjs.map +1 -1
  72. package/dist/utils/feature-flags.d.cts +9 -0
  73. package/dist/utils/feature-flags.d.cts.map +1 -1
  74. package/dist/utils/feature-flags.d.mts +9 -0
  75. package/dist/utils/feature-flags.d.mts.map +1 -1
  76. package/dist/utils/feature-flags.mjs +25 -2
  77. package/dist/utils/feature-flags.mjs.map +1 -1
  78. package/dist/utils/gas.cjs +6 -5
  79. package/dist/utils/gas.cjs.map +1 -1
  80. package/dist/utils/gas.mjs +6 -5
  81. package/dist/utils/gas.mjs.map +1 -1
  82. package/dist/utils/quotes.cjs +1 -1
  83. package/dist/utils/quotes.cjs.map +1 -1
  84. package/dist/utils/quotes.d.cts.map +1 -1
  85. package/dist/utils/quotes.d.mts.map +1 -1
  86. package/dist/utils/quotes.mjs +1 -1
  87. package/dist/utils/quotes.mjs.map +1 -1
  88. package/dist/utils/required-tokens.cjs +3 -3
  89. package/dist/utils/required-tokens.cjs.map +1 -1
  90. package/dist/utils/required-tokens.mjs +3 -3
  91. package/dist/utils/required-tokens.mjs.map +1 -1
  92. package/dist/utils/source-amounts.cjs +1 -1
  93. package/dist/utils/source-amounts.cjs.map +1 -1
  94. package/dist/utils/source-amounts.d.cts.map +1 -1
  95. package/dist/utils/source-amounts.d.mts.map +1 -1
  96. package/dist/utils/source-amounts.mjs +1 -1
  97. package/dist/utils/source-amounts.mjs.map +1 -1
  98. package/dist/utils/token.cjs +1 -1
  99. package/dist/utils/token.cjs.map +1 -1
  100. package/dist/utils/token.d.cts +3 -3
  101. package/dist/utils/token.d.cts.map +1 -1
  102. package/dist/utils/token.d.mts +3 -3
  103. package/dist/utils/token.d.mts.map +1 -1
  104. package/dist/utils/token.mjs +1 -1
  105. package/dist/utils/token.mjs.map +1 -1
  106. package/dist/utils/totals.cjs +2 -2
  107. package/dist/utils/totals.cjs.map +1 -1
  108. package/dist/utils/totals.d.cts.map +1 -1
  109. package/dist/utils/totals.d.mts.map +1 -1
  110. package/dist/utils/totals.mjs +2 -2
  111. package/dist/utils/totals.mjs.map +1 -1
  112. package/dist/utils/transaction.cjs +1 -1
  113. package/dist/utils/transaction.cjs.map +1 -1
  114. package/dist/utils/transaction.d.cts.map +1 -1
  115. package/dist/utils/transaction.d.mts.map +1 -1
  116. package/dist/utils/transaction.mjs +1 -1
  117. package/dist/utils/transaction.mjs.map +1 -1
  118. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"gas.cjs","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { GasFeeEstimates } from '@metamask/gas-fee-controller';\nimport type {\n GasFeeToken,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { getNativeToken, getTokenBalance, getTokenFiatRate } from './token';\nimport type { TransactionPayControllerMessenger } from '..';\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { Amount } from '../types';\n\nconst log = createModuleLogger(projectLogger, 'gas');\n\n/**\n *\n * Calculate the estimated gas cost for a given transaction in fiat.\n *\n * @param transaction - Transaction to calculate gas cost for\n * @param messenger - Controller messenger.\n * @param options - Calculation options.\n * @param options.isMax - Whether to calculate the maximum fee.\n * @returns Estimated gas cost for the transaction.\n */\nexport function calculateTransactionGasCost(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n { isMax }: { isMax?: boolean } = {},\n): Amount & { isGasFeeToken?: boolean } {\n const {\n chainId,\n gasUsed: gasUsedOriginal,\n gasLimitNoBuffer,\n txParams,\n } = transaction;\n\n const { from, gas, maxFeePerGas, maxPriorityFeePerGas } = txParams;\n const gasUsed = isMax ? undefined : gasUsedOriginal;\n const finalGas = gasUsed || gasLimitNoBuffer || gas || '0x0';\n\n const result = calculateGasCost({\n chainId,\n gas: finalGas,\n isMax,\n maxFeePerGas,\n maxPriorityFeePerGas,\n messenger,\n });\n\n const max = calculateGasCost({\n chainId,\n gas: finalGas,\n isMax: true,\n messenger,\n });\n\n const nativeBalance = getTokenBalance(\n messenger,\n from as Hex,\n chainId,\n getNativeToken(chainId),\n );\n\n const hasBalance = new BigNumber(nativeBalance).gte(max.raw);\n\n const gasFeeTokenCost = calculateTransactionGasFeeTokenCost({\n hasBalance,\n messenger,\n transaction,\n });\n\n if (gasFeeTokenCost) {\n return gasFeeTokenCost;\n }\n\n return result;\n}\n\n/**\n * Calculate the gas cost for the specified parameters.\n *\n * @param request - Gas cost calculation parameters.\n * @param request.chainId - ID of the chain.\n * @param request.gas - Amount of gas the transaction will use.\n * @param request.isMax - Whether to calculate the maximum fee.\n * @param request.maxFeePerGas - Max fee to pay per gas.\n * @param request.maxPriorityFeePerGas - Max priority fee to pay per gas.\n * @param request.messenger - Controller messenger.\n \n * @returns Estimated gas cost for the transaction.\n */\nexport function calculateGasCost(request: {\n chainId: number | Hex;\n gas: BigNumber.Value;\n isMax?: boolean;\n maxFeePerGas?: BigNumber.Value;\n maxPriorityFeePerGas?: BigNumber.Value;\n messenger: TransactionPayControllerMessenger;\n}): Amount {\n const {\n chainId: chainIdInput,\n gas,\n isMax,\n maxFeePerGas: maxFeePerGasInput,\n maxPriorityFeePerGas: maxPriorityFeePerGasInput,\n messenger,\n } = request;\n\n const chainId = toHex(chainIdInput);\n\n const {\n estimatedBaseFee,\n maxFeePerGas: maxFeePerGasEstimate,\n maxPriorityFeePerGas: maxPriorityFeePerGasEstimate,\n } = getGasFee(chainId, messenger);\n\n const maxFeePerGas = maxFeePerGasInput || maxFeePerGasEstimate;\n\n const maxPriorityFeePerGas =\n maxPriorityFeePerGasInput || maxPriorityFeePerGasEstimate;\n\n const feePerGas =\n estimatedBaseFee && maxPriorityFeePerGas && !isMax\n ? new BigNumber(estimatedBaseFee).plus(maxPriorityFeePerGas)\n : new BigNumber(maxFeePerGas || '0x0');\n\n const rawValue = new BigNumber(gas).multipliedBy(feePerGas);\n const raw = rawValue.toString(10);\n\n const humanValue = rawValue.shiftedBy(-18);\n const human = humanValue.toString(10);\n\n const fiatRate = getTokenFiatRate(\n messenger,\n getNativeToken(chainId),\n chainId,\n );\n\n if (!fiatRate) {\n throw new Error('Could not fetch fiat rate for native token');\n }\n\n const usd = humanValue.multipliedBy(fiatRate.usdRate).toString(10);\n const fiat = humanValue.multipliedBy(fiatRate.fiatRate).toString(10);\n\n return {\n fiat,\n human,\n raw,\n usd,\n };\n}\n\n/**\n * Calculate the cost of a gas fee token on a transaction.\n *\n * @param request - Request parameters.\n * @param request.chainId - Chain ID.\n * @param request.gasFeeToken - Gas fee token to calculate cost for.\n * @param request.messenger - Controller messenger.\n * @returns Cost of the gas fee token.\n */\nexport function calculateGasFeeTokenCost({\n chainId,\n gasFeeToken,\n messenger,\n}: {\n chainId: Hex;\n gasFeeToken: GasFeeToken;\n messenger: TransactionPayControllerMessenger;\n}): (Amount & { isGasFeeToken?: boolean }) | undefined {\n const { amount, decimals, tokenAddress } = gasFeeToken;\n\n const tokenFiatRate = getTokenFiatRate(messenger, tokenAddress, chainId);\n\n if (!tokenFiatRate) {\n log('Cannot get gas fee token info');\n return undefined;\n }\n\n const rawValue = new BigNumber(amount);\n const raw = rawValue.toString(10);\n\n const humanValue = rawValue.shiftedBy(-decimals);\n const human = humanValue.toString(10);\n\n const fiat = humanValue.multipliedBy(tokenFiatRate.fiatRate).toString(10);\n const usd = humanValue.multipliedBy(tokenFiatRate.usdRate).toString(10);\n\n return {\n isGasFeeToken: true,\n fiat,\n human,\n raw,\n usd,\n };\n}\n\n/**\n * Get gas fee estimates for a given chain.\n *\n * @param chainId - Chain ID.\n * @param messenger - Controller messenger.\n * @returns Gas fee estimates for the chain.\n */\nfunction getGasFee(chainId: Hex, messenger: TransactionPayControllerMessenger) {\n const gasFeeControllerState = messenger.call('GasFeeController:getState');\n\n const chainState = gasFeeControllerState?.gasFeeEstimatesByChainId?.[chainId];\n\n const { estimatedBaseFee: estimatedBaseFeeGwei, medium } =\n (chainState?.gasFeeEstimates as GasFeeEstimates | undefined) ?? {};\n\n const maxFeePerGasGwei = medium?.suggestedMaxFeePerGas;\n const maxPriorityFeePerGasGwei = medium?.suggestedMaxPriorityFeePerGas;\n\n const estimatedBaseFee = estimatedBaseFeeGwei\n ? new BigNumber(estimatedBaseFeeGwei).shiftedBy(9).toString(10)\n : undefined;\n\n const maxFeePerGas = maxFeePerGasGwei\n ? new BigNumber(maxFeePerGasGwei).shiftedBy(9).toString(10)\n : undefined;\n\n const maxPriorityFeePerGas = maxPriorityFeePerGasGwei\n ? new BigNumber(maxPriorityFeePerGasGwei).shiftedBy(9).toString(10)\n : undefined;\n\n return { estimatedBaseFee, maxFeePerGas, maxPriorityFeePerGas };\n}\n\n/**\n * Calculate the cost of a gas fee token on a transaction.\n *\n * @param request - Request parameters.\n * @param request.hasBalance - Whether the user has enough balance to cover the gas fee.\n * @param request.messenger - Controller messenger.\n * @param request.transaction - Transaction to calculate gas fee token cost for.\n * @returns Cost of the gas fee token.\n */\nfunction calculateTransactionGasFeeTokenCost({\n hasBalance,\n messenger,\n transaction,\n}: {\n hasBalance: boolean;\n messenger: TransactionPayControllerMessenger;\n transaction: TransactionMeta;\n}): (Amount & { isGasFeeToken?: boolean }) | undefined {\n const {\n chainId,\n gasFeeTokens,\n isGasFeeTokenIgnoredIfBalance,\n selectedGasFeeToken,\n } = transaction;\n\n if (\n !gasFeeTokens ||\n !selectedGasFeeToken ||\n (isGasFeeTokenIgnoredIfBalance && hasBalance)\n ) {\n return undefined;\n }\n\n log('Calculating gas fee token cost', { selectedGasFeeToken, chainId });\n\n const gasFeeToken = gasFeeTokens?.find(\n (t) => t.tokenAddress.toLowerCase() === selectedGasFeeToken.toLowerCase(),\n );\n\n if (!gasFeeToken) {\n log('Gas fee token not found', {\n gasFeeTokens,\n selectedGasFeeToken,\n });\n\n return undefined;\n }\n\n return calculateGasFeeTokenCost({\n chainId,\n gasFeeToken,\n messenger,\n });\n}\n"]}
1
+ {"version":3,"file":"gas.cjs","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { GasFeeEstimates } from '@metamask/gas-fee-controller';\nimport type {\n GasFeeToken,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { getNativeToken, getTokenBalance, getTokenFiatRate } from './token';\nimport type { TransactionPayControllerMessenger } from '..';\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { Amount } from '../types';\n\nconst log = createModuleLogger(projectLogger, 'gas');\n\n/**\n *\n * Calculate the estimated gas cost for a given transaction in fiat.\n *\n * @param transaction - Transaction to calculate gas cost for\n * @param messenger - Controller messenger.\n * @param options - Calculation options.\n * @param options.isMax - Whether to calculate the maximum fee.\n * @returns Estimated gas cost for the transaction.\n */\nexport function calculateTransactionGasCost(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n { isMax }: { isMax?: boolean } = {},\n): Amount & { isGasFeeToken?: boolean } {\n const {\n chainId,\n gasUsed: gasUsedOriginal,\n gasLimitNoBuffer,\n txParams,\n } = transaction;\n\n const { from, gas, maxFeePerGas, maxPriorityFeePerGas } = txParams;\n const gasUsed = isMax ? undefined : gasUsedOriginal;\n const finalGas = gasUsed ?? gasLimitNoBuffer ?? gas ?? '0x0';\n\n const result = calculateGasCost({\n chainId,\n gas: finalGas,\n isMax,\n maxFeePerGas,\n maxPriorityFeePerGas,\n messenger,\n });\n\n const max = calculateGasCost({\n chainId,\n gas: finalGas,\n isMax: true,\n messenger,\n });\n\n const nativeBalance = getTokenBalance(\n messenger,\n from as Hex,\n chainId,\n getNativeToken(chainId),\n );\n\n const hasBalance = new BigNumber(nativeBalance).gte(max.raw);\n\n const gasFeeTokenCost = calculateTransactionGasFeeTokenCost({\n hasBalance,\n messenger,\n transaction,\n });\n\n if (gasFeeTokenCost) {\n return gasFeeTokenCost;\n }\n\n return result;\n}\n\n/**\n * Calculate the gas cost for the specified parameters.\n *\n * @param request - Gas cost calculation parameters.\n * @param request.chainId - ID of the chain.\n * @param request.gas - Amount of gas the transaction will use.\n * @param request.isMax - Whether to calculate the maximum fee.\n * @param request.maxFeePerGas - Max fee to pay per gas.\n * @param request.maxPriorityFeePerGas - Max priority fee to pay per gas.\n * @param request.messenger - Controller messenger.\n \n * @returns Estimated gas cost for the transaction.\n */\nexport function calculateGasCost(request: {\n chainId: number | Hex;\n gas: BigNumber.Value;\n isMax?: boolean;\n maxFeePerGas?: BigNumber.Value;\n maxPriorityFeePerGas?: BigNumber.Value;\n messenger: TransactionPayControllerMessenger;\n}): Amount {\n const {\n chainId: chainIdInput,\n gas,\n isMax,\n maxFeePerGas: maxFeePerGasInput,\n maxPriorityFeePerGas: maxPriorityFeePerGasInput,\n messenger,\n } = request;\n\n const chainId = toHex(chainIdInput);\n\n const {\n estimatedBaseFee,\n maxFeePerGas: maxFeePerGasEstimate,\n maxPriorityFeePerGas: maxPriorityFeePerGasEstimate,\n } = getGasFee(chainId, messenger);\n\n const maxFeePerGas = maxFeePerGasInput ?? maxFeePerGasEstimate;\n\n const maxPriorityFeePerGas =\n maxPriorityFeePerGasInput ?? maxPriorityFeePerGasEstimate;\n\n const feePerGas =\n estimatedBaseFee && maxPriorityFeePerGas && !isMax\n ? new BigNumber(estimatedBaseFee).plus(maxPriorityFeePerGas)\n : new BigNumber(maxFeePerGas ?? '0x0');\n\n const rawValue = new BigNumber(gas).multipliedBy(feePerGas);\n const raw = rawValue.toString(10);\n\n const humanValue = rawValue.shiftedBy(-18);\n const human = humanValue.toString(10);\n\n const fiatRate = getTokenFiatRate(\n messenger,\n getNativeToken(chainId),\n chainId,\n );\n\n if (!fiatRate) {\n throw new Error('Could not fetch fiat rate for native token');\n }\n\n const usd = humanValue.multipliedBy(fiatRate.usdRate).toString(10);\n const fiat = humanValue.multipliedBy(fiatRate.fiatRate).toString(10);\n\n return {\n fiat,\n human,\n raw,\n usd,\n };\n}\n\n/**\n * Calculate the cost of a gas fee token on a transaction.\n *\n * @param request - Request parameters.\n * @param request.chainId - Chain ID.\n * @param request.gasFeeToken - Gas fee token to calculate cost for.\n * @param request.messenger - Controller messenger.\n * @returns Cost of the gas fee token.\n */\nexport function calculateGasFeeTokenCost({\n chainId,\n gasFeeToken,\n messenger,\n}: {\n chainId: Hex;\n gasFeeToken: GasFeeToken;\n messenger: TransactionPayControllerMessenger;\n}): (Amount & { isGasFeeToken?: boolean }) | undefined {\n const { amount, decimals, tokenAddress } = gasFeeToken;\n\n const tokenFiatRate = getTokenFiatRate(messenger, tokenAddress, chainId);\n\n if (!tokenFiatRate) {\n log('Cannot get gas fee token info');\n return undefined;\n }\n\n const rawValue = new BigNumber(amount);\n const raw = rawValue.toString(10);\n\n const humanValue = rawValue.shiftedBy(-decimals);\n const human = humanValue.toString(10);\n\n const fiat = humanValue.multipliedBy(tokenFiatRate.fiatRate).toString(10);\n const usd = humanValue.multipliedBy(tokenFiatRate.usdRate).toString(10);\n\n return {\n isGasFeeToken: true,\n fiat,\n human,\n raw,\n usd,\n };\n}\n\n/**\n * Get gas fee estimates for a given chain.\n *\n * @param chainId - Chain ID.\n * @param messenger - Controller messenger.\n * @returns Gas fee estimates for the chain.\n */\nfunction getGasFee(\n chainId: Hex,\n messenger: TransactionPayControllerMessenger,\n): {\n estimatedBaseFee: string | undefined;\n maxFeePerGas: string | undefined;\n maxPriorityFeePerGas: string | undefined;\n} {\n const gasFeeControllerState = messenger.call('GasFeeController:getState');\n\n const chainState = gasFeeControllerState?.gasFeeEstimatesByChainId?.[chainId];\n\n const { estimatedBaseFee: estimatedBaseFeeGwei, medium } =\n (chainState?.gasFeeEstimates as GasFeeEstimates | undefined) ?? {};\n\n const maxFeePerGasGwei = medium?.suggestedMaxFeePerGas;\n const maxPriorityFeePerGasGwei = medium?.suggestedMaxPriorityFeePerGas;\n\n const estimatedBaseFee = estimatedBaseFeeGwei\n ? new BigNumber(estimatedBaseFeeGwei).shiftedBy(9).toString(10)\n : undefined;\n\n const maxFeePerGas = maxFeePerGasGwei\n ? new BigNumber(maxFeePerGasGwei).shiftedBy(9).toString(10)\n : undefined;\n\n const maxPriorityFeePerGas = maxPriorityFeePerGasGwei\n ? new BigNumber(maxPriorityFeePerGasGwei).shiftedBy(9).toString(10)\n : undefined;\n\n return { estimatedBaseFee, maxFeePerGas, maxPriorityFeePerGas };\n}\n\n/**\n * Calculate the cost of a gas fee token on a transaction.\n *\n * @param request - Request parameters.\n * @param request.hasBalance - Whether the user has enough balance to cover the gas fee.\n * @param request.messenger - Controller messenger.\n * @param request.transaction - Transaction to calculate gas fee token cost for.\n * @returns Cost of the gas fee token.\n */\nfunction calculateTransactionGasFeeTokenCost({\n hasBalance,\n messenger,\n transaction,\n}: {\n hasBalance: boolean;\n messenger: TransactionPayControllerMessenger;\n transaction: TransactionMeta;\n}): (Amount & { isGasFeeToken?: boolean }) | undefined {\n const {\n chainId,\n gasFeeTokens,\n isGasFeeTokenIgnoredIfBalance,\n selectedGasFeeToken,\n } = transaction;\n\n if (\n !gasFeeTokens ||\n !selectedGasFeeToken ||\n (isGasFeeTokenIgnoredIfBalance && hasBalance)\n ) {\n return undefined;\n }\n\n log('Calculating gas fee token cost', { selectedGasFeeToken, chainId });\n\n const gasFeeToken = gasFeeTokens?.find(\n (singleGasFeeToken) =>\n singleGasFeeToken.tokenAddress.toLowerCase() ===\n selectedGasFeeToken.toLowerCase(),\n );\n\n if (!gasFeeToken) {\n log('Gas fee token not found', {\n gasFeeTokens,\n selectedGasFeeToken,\n });\n\n return undefined;\n }\n\n return calculateGasFeeTokenCost({\n chainId,\n gasFeeToken,\n messenger,\n });\n}\n"]}
@@ -17,7 +17,7 @@ export function calculateTransactionGasCost(transaction, messenger, { isMax } =
17
17
  const { chainId, gasUsed: gasUsedOriginal, gasLimitNoBuffer, txParams, } = transaction;
18
18
  const { from, gas, maxFeePerGas, maxPriorityFeePerGas } = txParams;
19
19
  const gasUsed = isMax ? undefined : gasUsedOriginal;
20
- const finalGas = gasUsed || gasLimitNoBuffer || gas || '0x0';
20
+ const finalGas = gasUsed ?? gasLimitNoBuffer ?? gas ?? '0x0';
21
21
  const result = calculateGasCost({
22
22
  chainId,
23
23
  gas: finalGas,
@@ -61,11 +61,11 @@ export function calculateGasCost(request) {
61
61
  const { chainId: chainIdInput, gas, isMax, maxFeePerGas: maxFeePerGasInput, maxPriorityFeePerGas: maxPriorityFeePerGasInput, messenger, } = request;
62
62
  const chainId = toHex(chainIdInput);
63
63
  const { estimatedBaseFee, maxFeePerGas: maxFeePerGasEstimate, maxPriorityFeePerGas: maxPriorityFeePerGasEstimate, } = getGasFee(chainId, messenger);
64
- const maxFeePerGas = maxFeePerGasInput || maxFeePerGasEstimate;
65
- const maxPriorityFeePerGas = maxPriorityFeePerGasInput || maxPriorityFeePerGasEstimate;
64
+ const maxFeePerGas = maxFeePerGasInput ?? maxFeePerGasEstimate;
65
+ const maxPriorityFeePerGas = maxPriorityFeePerGasInput ?? maxPriorityFeePerGasEstimate;
66
66
  const feePerGas = estimatedBaseFee && maxPriorityFeePerGas && !isMax
67
67
  ? new BigNumber(estimatedBaseFee).plus(maxPriorityFeePerGas)
68
- : new BigNumber(maxFeePerGas || '0x0');
68
+ : new BigNumber(maxFeePerGas ?? '0x0');
69
69
  const rawValue = new BigNumber(gas).multipliedBy(feePerGas);
70
70
  const raw = rawValue.toString(10);
71
71
  const humanValue = rawValue.shiftedBy(-18);
@@ -154,7 +154,8 @@ function calculateTransactionGasFeeTokenCost({ hasBalance, messenger, transactio
154
154
  return undefined;
155
155
  }
156
156
  log('Calculating gas fee token cost', { selectedGasFeeToken, chainId });
157
- const gasFeeToken = gasFeeTokens?.find((t) => t.tokenAddress.toLowerCase() === selectedGasFeeToken.toLowerCase());
157
+ const gasFeeToken = gasFeeTokens?.find((singleGasFeeToken) => singleGasFeeToken.tokenAddress.toLowerCase() ===
158
+ selectedGasFeeToken.toLowerCase());
158
159
  if (!gasFeeToken) {
159
160
  log('Gas fee token not found', {
160
161
  gasFeeTokens,
@@ -1 +1 @@
1
- {"version":3,"file":"gas.mjs","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { GasFeeEstimates } from '@metamask/gas-fee-controller';\nimport type {\n GasFeeToken,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { getNativeToken, getTokenBalance, getTokenFiatRate } from './token';\nimport type { TransactionPayControllerMessenger } from '..';\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { Amount } from '../types';\n\nconst log = createModuleLogger(projectLogger, 'gas');\n\n/**\n *\n * Calculate the estimated gas cost for a given transaction in fiat.\n *\n * @param transaction - Transaction to calculate gas cost for\n * @param messenger - Controller messenger.\n * @param options - Calculation options.\n * @param options.isMax - Whether to calculate the maximum fee.\n * @returns Estimated gas cost for the transaction.\n */\nexport function calculateTransactionGasCost(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n { isMax }: { isMax?: boolean } = {},\n): Amount & { isGasFeeToken?: boolean } {\n const {\n chainId,\n gasUsed: gasUsedOriginal,\n gasLimitNoBuffer,\n txParams,\n } = transaction;\n\n const { from, gas, maxFeePerGas, maxPriorityFeePerGas } = txParams;\n const gasUsed = isMax ? undefined : gasUsedOriginal;\n const finalGas = gasUsed || gasLimitNoBuffer || gas || '0x0';\n\n const result = calculateGasCost({\n chainId,\n gas: finalGas,\n isMax,\n maxFeePerGas,\n maxPriorityFeePerGas,\n messenger,\n });\n\n const max = calculateGasCost({\n chainId,\n gas: finalGas,\n isMax: true,\n messenger,\n });\n\n const nativeBalance = getTokenBalance(\n messenger,\n from as Hex,\n chainId,\n getNativeToken(chainId),\n );\n\n const hasBalance = new BigNumber(nativeBalance).gte(max.raw);\n\n const gasFeeTokenCost = calculateTransactionGasFeeTokenCost({\n hasBalance,\n messenger,\n transaction,\n });\n\n if (gasFeeTokenCost) {\n return gasFeeTokenCost;\n }\n\n return result;\n}\n\n/**\n * Calculate the gas cost for the specified parameters.\n *\n * @param request - Gas cost calculation parameters.\n * @param request.chainId - ID of the chain.\n * @param request.gas - Amount of gas the transaction will use.\n * @param request.isMax - Whether to calculate the maximum fee.\n * @param request.maxFeePerGas - Max fee to pay per gas.\n * @param request.maxPriorityFeePerGas - Max priority fee to pay per gas.\n * @param request.messenger - Controller messenger.\n \n * @returns Estimated gas cost for the transaction.\n */\nexport function calculateGasCost(request: {\n chainId: number | Hex;\n gas: BigNumber.Value;\n isMax?: boolean;\n maxFeePerGas?: BigNumber.Value;\n maxPriorityFeePerGas?: BigNumber.Value;\n messenger: TransactionPayControllerMessenger;\n}): Amount {\n const {\n chainId: chainIdInput,\n gas,\n isMax,\n maxFeePerGas: maxFeePerGasInput,\n maxPriorityFeePerGas: maxPriorityFeePerGasInput,\n messenger,\n } = request;\n\n const chainId = toHex(chainIdInput);\n\n const {\n estimatedBaseFee,\n maxFeePerGas: maxFeePerGasEstimate,\n maxPriorityFeePerGas: maxPriorityFeePerGasEstimate,\n } = getGasFee(chainId, messenger);\n\n const maxFeePerGas = maxFeePerGasInput || maxFeePerGasEstimate;\n\n const maxPriorityFeePerGas =\n maxPriorityFeePerGasInput || maxPriorityFeePerGasEstimate;\n\n const feePerGas =\n estimatedBaseFee && maxPriorityFeePerGas && !isMax\n ? new BigNumber(estimatedBaseFee).plus(maxPriorityFeePerGas)\n : new BigNumber(maxFeePerGas || '0x0');\n\n const rawValue = new BigNumber(gas).multipliedBy(feePerGas);\n const raw = rawValue.toString(10);\n\n const humanValue = rawValue.shiftedBy(-18);\n const human = humanValue.toString(10);\n\n const fiatRate = getTokenFiatRate(\n messenger,\n getNativeToken(chainId),\n chainId,\n );\n\n if (!fiatRate) {\n throw new Error('Could not fetch fiat rate for native token');\n }\n\n const usd = humanValue.multipliedBy(fiatRate.usdRate).toString(10);\n const fiat = humanValue.multipliedBy(fiatRate.fiatRate).toString(10);\n\n return {\n fiat,\n human,\n raw,\n usd,\n };\n}\n\n/**\n * Calculate the cost of a gas fee token on a transaction.\n *\n * @param request - Request parameters.\n * @param request.chainId - Chain ID.\n * @param request.gasFeeToken - Gas fee token to calculate cost for.\n * @param request.messenger - Controller messenger.\n * @returns Cost of the gas fee token.\n */\nexport function calculateGasFeeTokenCost({\n chainId,\n gasFeeToken,\n messenger,\n}: {\n chainId: Hex;\n gasFeeToken: GasFeeToken;\n messenger: TransactionPayControllerMessenger;\n}): (Amount & { isGasFeeToken?: boolean }) | undefined {\n const { amount, decimals, tokenAddress } = gasFeeToken;\n\n const tokenFiatRate = getTokenFiatRate(messenger, tokenAddress, chainId);\n\n if (!tokenFiatRate) {\n log('Cannot get gas fee token info');\n return undefined;\n }\n\n const rawValue = new BigNumber(amount);\n const raw = rawValue.toString(10);\n\n const humanValue = rawValue.shiftedBy(-decimals);\n const human = humanValue.toString(10);\n\n const fiat = humanValue.multipliedBy(tokenFiatRate.fiatRate).toString(10);\n const usd = humanValue.multipliedBy(tokenFiatRate.usdRate).toString(10);\n\n return {\n isGasFeeToken: true,\n fiat,\n human,\n raw,\n usd,\n };\n}\n\n/**\n * Get gas fee estimates for a given chain.\n *\n * @param chainId - Chain ID.\n * @param messenger - Controller messenger.\n * @returns Gas fee estimates for the chain.\n */\nfunction getGasFee(chainId: Hex, messenger: TransactionPayControllerMessenger) {\n const gasFeeControllerState = messenger.call('GasFeeController:getState');\n\n const chainState = gasFeeControllerState?.gasFeeEstimatesByChainId?.[chainId];\n\n const { estimatedBaseFee: estimatedBaseFeeGwei, medium } =\n (chainState?.gasFeeEstimates as GasFeeEstimates | undefined) ?? {};\n\n const maxFeePerGasGwei = medium?.suggestedMaxFeePerGas;\n const maxPriorityFeePerGasGwei = medium?.suggestedMaxPriorityFeePerGas;\n\n const estimatedBaseFee = estimatedBaseFeeGwei\n ? new BigNumber(estimatedBaseFeeGwei).shiftedBy(9).toString(10)\n : undefined;\n\n const maxFeePerGas = maxFeePerGasGwei\n ? new BigNumber(maxFeePerGasGwei).shiftedBy(9).toString(10)\n : undefined;\n\n const maxPriorityFeePerGas = maxPriorityFeePerGasGwei\n ? new BigNumber(maxPriorityFeePerGasGwei).shiftedBy(9).toString(10)\n : undefined;\n\n return { estimatedBaseFee, maxFeePerGas, maxPriorityFeePerGas };\n}\n\n/**\n * Calculate the cost of a gas fee token on a transaction.\n *\n * @param request - Request parameters.\n * @param request.hasBalance - Whether the user has enough balance to cover the gas fee.\n * @param request.messenger - Controller messenger.\n * @param request.transaction - Transaction to calculate gas fee token cost for.\n * @returns Cost of the gas fee token.\n */\nfunction calculateTransactionGasFeeTokenCost({\n hasBalance,\n messenger,\n transaction,\n}: {\n hasBalance: boolean;\n messenger: TransactionPayControllerMessenger;\n transaction: TransactionMeta;\n}): (Amount & { isGasFeeToken?: boolean }) | undefined {\n const {\n chainId,\n gasFeeTokens,\n isGasFeeTokenIgnoredIfBalance,\n selectedGasFeeToken,\n } = transaction;\n\n if (\n !gasFeeTokens ||\n !selectedGasFeeToken ||\n (isGasFeeTokenIgnoredIfBalance && hasBalance)\n ) {\n return undefined;\n }\n\n log('Calculating gas fee token cost', { selectedGasFeeToken, chainId });\n\n const gasFeeToken = gasFeeTokens?.find(\n (t) => t.tokenAddress.toLowerCase() === selectedGasFeeToken.toLowerCase(),\n );\n\n if (!gasFeeToken) {\n log('Gas fee token not found', {\n gasFeeTokens,\n selectedGasFeeToken,\n });\n\n return undefined;\n }\n\n return calculateGasFeeTokenCost({\n chainId,\n gasFeeToken,\n messenger,\n });\n}\n"]}
1
+ {"version":3,"file":"gas.mjs","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { GasFeeEstimates } from '@metamask/gas-fee-controller';\nimport type {\n GasFeeToken,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { getNativeToken, getTokenBalance, getTokenFiatRate } from './token';\nimport type { TransactionPayControllerMessenger } from '..';\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { Amount } from '../types';\n\nconst log = createModuleLogger(projectLogger, 'gas');\n\n/**\n *\n * Calculate the estimated gas cost for a given transaction in fiat.\n *\n * @param transaction - Transaction to calculate gas cost for\n * @param messenger - Controller messenger.\n * @param options - Calculation options.\n * @param options.isMax - Whether to calculate the maximum fee.\n * @returns Estimated gas cost for the transaction.\n */\nexport function calculateTransactionGasCost(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n { isMax }: { isMax?: boolean } = {},\n): Amount & { isGasFeeToken?: boolean } {\n const {\n chainId,\n gasUsed: gasUsedOriginal,\n gasLimitNoBuffer,\n txParams,\n } = transaction;\n\n const { from, gas, maxFeePerGas, maxPriorityFeePerGas } = txParams;\n const gasUsed = isMax ? undefined : gasUsedOriginal;\n const finalGas = gasUsed ?? gasLimitNoBuffer ?? gas ?? '0x0';\n\n const result = calculateGasCost({\n chainId,\n gas: finalGas,\n isMax,\n maxFeePerGas,\n maxPriorityFeePerGas,\n messenger,\n });\n\n const max = calculateGasCost({\n chainId,\n gas: finalGas,\n isMax: true,\n messenger,\n });\n\n const nativeBalance = getTokenBalance(\n messenger,\n from as Hex,\n chainId,\n getNativeToken(chainId),\n );\n\n const hasBalance = new BigNumber(nativeBalance).gte(max.raw);\n\n const gasFeeTokenCost = calculateTransactionGasFeeTokenCost({\n hasBalance,\n messenger,\n transaction,\n });\n\n if (gasFeeTokenCost) {\n return gasFeeTokenCost;\n }\n\n return result;\n}\n\n/**\n * Calculate the gas cost for the specified parameters.\n *\n * @param request - Gas cost calculation parameters.\n * @param request.chainId - ID of the chain.\n * @param request.gas - Amount of gas the transaction will use.\n * @param request.isMax - Whether to calculate the maximum fee.\n * @param request.maxFeePerGas - Max fee to pay per gas.\n * @param request.maxPriorityFeePerGas - Max priority fee to pay per gas.\n * @param request.messenger - Controller messenger.\n \n * @returns Estimated gas cost for the transaction.\n */\nexport function calculateGasCost(request: {\n chainId: number | Hex;\n gas: BigNumber.Value;\n isMax?: boolean;\n maxFeePerGas?: BigNumber.Value;\n maxPriorityFeePerGas?: BigNumber.Value;\n messenger: TransactionPayControllerMessenger;\n}): Amount {\n const {\n chainId: chainIdInput,\n gas,\n isMax,\n maxFeePerGas: maxFeePerGasInput,\n maxPriorityFeePerGas: maxPriorityFeePerGasInput,\n messenger,\n } = request;\n\n const chainId = toHex(chainIdInput);\n\n const {\n estimatedBaseFee,\n maxFeePerGas: maxFeePerGasEstimate,\n maxPriorityFeePerGas: maxPriorityFeePerGasEstimate,\n } = getGasFee(chainId, messenger);\n\n const maxFeePerGas = maxFeePerGasInput ?? maxFeePerGasEstimate;\n\n const maxPriorityFeePerGas =\n maxPriorityFeePerGasInput ?? maxPriorityFeePerGasEstimate;\n\n const feePerGas =\n estimatedBaseFee && maxPriorityFeePerGas && !isMax\n ? new BigNumber(estimatedBaseFee).plus(maxPriorityFeePerGas)\n : new BigNumber(maxFeePerGas ?? '0x0');\n\n const rawValue = new BigNumber(gas).multipliedBy(feePerGas);\n const raw = rawValue.toString(10);\n\n const humanValue = rawValue.shiftedBy(-18);\n const human = humanValue.toString(10);\n\n const fiatRate = getTokenFiatRate(\n messenger,\n getNativeToken(chainId),\n chainId,\n );\n\n if (!fiatRate) {\n throw new Error('Could not fetch fiat rate for native token');\n }\n\n const usd = humanValue.multipliedBy(fiatRate.usdRate).toString(10);\n const fiat = humanValue.multipliedBy(fiatRate.fiatRate).toString(10);\n\n return {\n fiat,\n human,\n raw,\n usd,\n };\n}\n\n/**\n * Calculate the cost of a gas fee token on a transaction.\n *\n * @param request - Request parameters.\n * @param request.chainId - Chain ID.\n * @param request.gasFeeToken - Gas fee token to calculate cost for.\n * @param request.messenger - Controller messenger.\n * @returns Cost of the gas fee token.\n */\nexport function calculateGasFeeTokenCost({\n chainId,\n gasFeeToken,\n messenger,\n}: {\n chainId: Hex;\n gasFeeToken: GasFeeToken;\n messenger: TransactionPayControllerMessenger;\n}): (Amount & { isGasFeeToken?: boolean }) | undefined {\n const { amount, decimals, tokenAddress } = gasFeeToken;\n\n const tokenFiatRate = getTokenFiatRate(messenger, tokenAddress, chainId);\n\n if (!tokenFiatRate) {\n log('Cannot get gas fee token info');\n return undefined;\n }\n\n const rawValue = new BigNumber(amount);\n const raw = rawValue.toString(10);\n\n const humanValue = rawValue.shiftedBy(-decimals);\n const human = humanValue.toString(10);\n\n const fiat = humanValue.multipliedBy(tokenFiatRate.fiatRate).toString(10);\n const usd = humanValue.multipliedBy(tokenFiatRate.usdRate).toString(10);\n\n return {\n isGasFeeToken: true,\n fiat,\n human,\n raw,\n usd,\n };\n}\n\n/**\n * Get gas fee estimates for a given chain.\n *\n * @param chainId - Chain ID.\n * @param messenger - Controller messenger.\n * @returns Gas fee estimates for the chain.\n */\nfunction getGasFee(\n chainId: Hex,\n messenger: TransactionPayControllerMessenger,\n): {\n estimatedBaseFee: string | undefined;\n maxFeePerGas: string | undefined;\n maxPriorityFeePerGas: string | undefined;\n} {\n const gasFeeControllerState = messenger.call('GasFeeController:getState');\n\n const chainState = gasFeeControllerState?.gasFeeEstimatesByChainId?.[chainId];\n\n const { estimatedBaseFee: estimatedBaseFeeGwei, medium } =\n (chainState?.gasFeeEstimates as GasFeeEstimates | undefined) ?? {};\n\n const maxFeePerGasGwei = medium?.suggestedMaxFeePerGas;\n const maxPriorityFeePerGasGwei = medium?.suggestedMaxPriorityFeePerGas;\n\n const estimatedBaseFee = estimatedBaseFeeGwei\n ? new BigNumber(estimatedBaseFeeGwei).shiftedBy(9).toString(10)\n : undefined;\n\n const maxFeePerGas = maxFeePerGasGwei\n ? new BigNumber(maxFeePerGasGwei).shiftedBy(9).toString(10)\n : undefined;\n\n const maxPriorityFeePerGas = maxPriorityFeePerGasGwei\n ? new BigNumber(maxPriorityFeePerGasGwei).shiftedBy(9).toString(10)\n : undefined;\n\n return { estimatedBaseFee, maxFeePerGas, maxPriorityFeePerGas };\n}\n\n/**\n * Calculate the cost of a gas fee token on a transaction.\n *\n * @param request - Request parameters.\n * @param request.hasBalance - Whether the user has enough balance to cover the gas fee.\n * @param request.messenger - Controller messenger.\n * @param request.transaction - Transaction to calculate gas fee token cost for.\n * @returns Cost of the gas fee token.\n */\nfunction calculateTransactionGasFeeTokenCost({\n hasBalance,\n messenger,\n transaction,\n}: {\n hasBalance: boolean;\n messenger: TransactionPayControllerMessenger;\n transaction: TransactionMeta;\n}): (Amount & { isGasFeeToken?: boolean }) | undefined {\n const {\n chainId,\n gasFeeTokens,\n isGasFeeTokenIgnoredIfBalance,\n selectedGasFeeToken,\n } = transaction;\n\n if (\n !gasFeeTokens ||\n !selectedGasFeeToken ||\n (isGasFeeTokenIgnoredIfBalance && hasBalance)\n ) {\n return undefined;\n }\n\n log('Calculating gas fee token cost', { selectedGasFeeToken, chainId });\n\n const gasFeeToken = gasFeeTokens?.find(\n (singleGasFeeToken) =>\n singleGasFeeToken.tokenAddress.toLowerCase() ===\n selectedGasFeeToken.toLowerCase(),\n );\n\n if (!gasFeeToken) {\n log('Gas fee token not found', {\n gasFeeTokens,\n selectedGasFeeToken,\n });\n\n return undefined;\n }\n\n return calculateGasFeeTokenCost({\n chainId,\n gasFeeToken,\n messenger,\n });\n}\n"]}
@@ -149,7 +149,7 @@ function buildQuoteRequests({ from, paymentToken, sourceAmounts, tokens, transac
149
149
  return [];
150
150
  }
151
151
  const requests = (sourceAmounts ?? []).map((sourceAmount) => {
152
- const token = tokens.find((t) => t.address === sourceAmount.targetTokenAddress);
152
+ const token = tokens.find((singleToken) => singleToken.address === sourceAmount.targetTokenAddress);
153
153
  return {
154
154
  from,
155
155
  sourceBalanceRaw: paymentToken.balanceRaw,
@@ -1 +1 @@
1
- {"version":3,"file":"quotes.cjs","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { TransactionStatus } from '@metamask/transaction-controller';\nimport type { BatchTransaction } from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex, Json } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { getStrategy, getStrategyByName } from './strategy';\nimport { calculateTotals } from './totals';\nimport { getTransaction, updateTransaction } from './transaction';\nimport { projectLogger } from '../logger';\nimport type {\n QuoteRequest,\n TransactionData,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n TransactionPayRequiredToken,\n TransactionPaySourceAmount,\n TransactionPayTotals,\n TransactionPaymentToken,\n UpdateTransactionDataCallback,\n} from '../types';\n\nconst DEFAULT_REFRESH_INTERVAL = 30 * 1000; // 30 Seconds\n\nconst log = createModuleLogger(projectLogger, 'quotes');\n\nexport type UpdateQuotesRequest = {\n messenger: TransactionPayControllerMessenger;\n transactionData: TransactionData | undefined;\n transactionId: string;\n updateTransactionData: UpdateTransactionDataCallback;\n};\n\n/**\n * Update the quotes for a specific transaction.\n *\n * @param request - Request parameters.\n * @returns Boolean indicating if the quotes were updated.\n */\nexport async function updateQuotes(\n request: UpdateQuotesRequest,\n): Promise<boolean> {\n const { messenger, transactionData, transactionId, updateTransactionData } =\n request;\n\n const transaction = getTransaction(transactionId, messenger);\n\n if (!transaction || !transactionData) {\n throw new Error('Transaction not found');\n }\n\n if (transaction?.status !== TransactionStatus.unapproved) {\n return false;\n }\n\n log('Updating quotes', { transactionId });\n\n const { paymentToken, sourceAmounts, tokens } = transactionData;\n\n const requests = buildQuoteRequests({\n from: transaction.txParams.from as Hex,\n paymentToken,\n sourceAmounts,\n tokens,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n data.isLoading = true;\n });\n\n try {\n const { batchTransactions, quotes } = await getQuotes(\n transaction,\n requests,\n messenger,\n );\n\n const totals = calculateTotals({\n quotes: quotes as TransactionPayQuote<unknown>[],\n messenger,\n tokens,\n transaction,\n });\n\n log('Calculated totals', { transactionId, totals });\n\n syncTransaction({\n batchTransactions,\n messenger: messenger as never,\n paymentToken,\n totals,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n data.quotes = quotes as never;\n data.quotesLastUpdated = Date.now();\n data.totals = totals;\n });\n } finally {\n updateTransactionData(transactionId, (data) => {\n data.isLoading = false;\n });\n }\n\n return true;\n}\n\n/**\n * Sync batch transactions to the transaction meta.\n *\n * @param request - Request object.\n * @param request.batchTransactions - Batch transactions to sync.\n * @param request.messenger - Messenger instance.\n * @param request.paymentToken - Payment token used.\n * @param request.totals - Calculated totals.\n * @param request.transactionId - ID of the transaction to sync.\n */\nfunction syncTransaction({\n batchTransactions,\n messenger,\n paymentToken,\n totals,\n transactionId,\n}: {\n batchTransactions: BatchTransaction[];\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\n totals: TransactionPayTotals;\n transactionId: string;\n}) {\n if (!paymentToken) {\n return;\n }\n\n updateTransaction(\n {\n transactionId,\n messenger: messenger as never,\n note: 'Update transaction pay data',\n },\n (tx: TransactionMeta) => {\n tx.batchTransactions = batchTransactions;\n tx.batchTransactionsOptions = {};\n\n tx.metamaskPay = {\n bridgeFeeFiat: totals.fees.provider.usd,\n chainId: paymentToken.chainId,\n networkFeeFiat: totals.fees.sourceNetwork.estimate.usd,\n tokenAddress: paymentToken.address,\n totalFiat: totals.total.usd,\n };\n },\n );\n}\n\n/**\n * Refresh quotes for all transactions if expired.\n *\n * @param messenger - Messenger instance.\n * @param updateTransactionData - Callback to update transaction data.\n */\nexport async function refreshQuotes(\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n) {\n const state = messenger.call('TransactionPayController:getState');\n const transactionIds = Object.keys(state.transactionData);\n\n for (const transactionId of transactionIds) {\n const transactionData = state.transactionData[transactionId];\n const { isLoading, quotes, quotesLastUpdated } = transactionData;\n\n if (isLoading || !quotes?.length) {\n continue;\n }\n\n const strategyName = quotes[0].strategy;\n const strategy = getStrategyByName(strategyName);\n\n const refreshInterval =\n (await strategy.getRefreshInterval?.({\n chainId: quotes[0].request.sourceChainId,\n messenger,\n })) ?? DEFAULT_REFRESH_INTERVAL;\n\n const isExpired = Date.now() - (quotesLastUpdated ?? 0) > refreshInterval;\n\n if (!isExpired) {\n continue;\n }\n\n const isUpdated = await updateQuotes({\n messenger,\n transactionData,\n transactionId,\n updateTransactionData,\n });\n\n if (isUpdated) {\n log('Refreshed quotes', { transactionId, strategy: strategyName });\n }\n }\n}\n\n/**\n * Build quote requests required to retrieve quotes.\n *\n * @param request - Request parameters.\n * @param request.from - Address from which the transaction is sent.\n * @param request.paymentToken - Payment token used for the transaction.\n * @param request.sourceAmounts - Source amounts for the transaction.\n * @param request.tokens - Required tokens for the transaction.\n * @param request.transactionId - ID of the transaction.\n * @returns Array of quote requests.\n */\nfunction buildQuoteRequests({\n from,\n paymentToken,\n sourceAmounts,\n tokens,\n transactionId,\n}: {\n from: Hex;\n paymentToken: TransactionPaymentToken | undefined;\n sourceAmounts: TransactionPaySourceAmount[] | undefined;\n tokens: TransactionPayRequiredToken[];\n transactionId: string;\n}): QuoteRequest[] {\n if (!paymentToken) {\n return [];\n }\n\n const requests = (sourceAmounts ?? []).map((sourceAmount) => {\n const token = tokens.find(\n (t) => t.address === sourceAmount.targetTokenAddress,\n ) as TransactionPayRequiredToken;\n\n return {\n from,\n sourceBalanceRaw: paymentToken.balanceRaw,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n sourceChainId: paymentToken.chainId,\n sourceTokenAddress: paymentToken.address,\n targetAmountMinimum: token.allowUnderMinimum ? '0' : token.amountRaw,\n targetChainId: token.chainId,\n targetTokenAddress: token.address,\n };\n });\n\n if (!requests.length) {\n log('No quote requests', { transactionId });\n }\n\n return requests;\n}\n\n/**\n * Retrieve quotes for a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param requests - Quote requests.\n * @param messenger - Controller messenger.\n * @returns An object containing batch transactions and quotes.\n */\nasync function getQuotes(\n transaction: TransactionMeta,\n requests: QuoteRequest[],\n messenger: TransactionPayControllerMessenger,\n) {\n const { id: transactionId } = transaction;\n const strategy = getStrategy(messenger as never, transaction);\n let quotes: TransactionPayQuote<Json>[] | undefined = [];\n\n try {\n quotes = requests?.length\n ? ((await strategy.getQuotes({\n messenger,\n requests,\n transaction,\n })) as TransactionPayQuote<Json>[])\n : [];\n } catch (error) {\n log('Error fetching quotes', { error, transactionId });\n }\n\n log('Updated', { transactionId, quotes });\n\n const batchTransactions =\n quotes?.length && strategy.getBatchTransactions\n ? await strategy.getBatchTransactions({\n messenger,\n quotes,\n })\n : [];\n\n log('Batch transactions', { transactionId, batchTransactions });\n\n return {\n batchTransactions,\n quotes,\n };\n}\n"]}
1
+ {"version":3,"file":"quotes.cjs","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { TransactionStatus } from '@metamask/transaction-controller';\nimport type { BatchTransaction } from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex, Json } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { getStrategy, getStrategyByName } from './strategy';\nimport { calculateTotals } from './totals';\nimport { getTransaction, updateTransaction } from './transaction';\nimport { projectLogger } from '../logger';\nimport type {\n QuoteRequest,\n TransactionData,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n TransactionPayRequiredToken,\n TransactionPaySourceAmount,\n TransactionPayTotals,\n TransactionPaymentToken,\n UpdateTransactionDataCallback,\n} from '../types';\n\nconst DEFAULT_REFRESH_INTERVAL = 30 * 1000; // 30 Seconds\n\nconst log = createModuleLogger(projectLogger, 'quotes');\n\nexport type UpdateQuotesRequest = {\n messenger: TransactionPayControllerMessenger;\n transactionData: TransactionData | undefined;\n transactionId: string;\n updateTransactionData: UpdateTransactionDataCallback;\n};\n\n/**\n * Update the quotes for a specific transaction.\n *\n * @param request - Request parameters.\n * @returns Boolean indicating if the quotes were updated.\n */\nexport async function updateQuotes(\n request: UpdateQuotesRequest,\n): Promise<boolean> {\n const { messenger, transactionData, transactionId, updateTransactionData } =\n request;\n\n const transaction = getTransaction(transactionId, messenger);\n\n if (!transaction || !transactionData) {\n throw new Error('Transaction not found');\n }\n\n if (transaction?.status !== TransactionStatus.unapproved) {\n return false;\n }\n\n log('Updating quotes', { transactionId });\n\n const { paymentToken, sourceAmounts, tokens } = transactionData;\n\n const requests = buildQuoteRequests({\n from: transaction.txParams.from as Hex,\n paymentToken,\n sourceAmounts,\n tokens,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n data.isLoading = true;\n });\n\n try {\n const { batchTransactions, quotes } = await getQuotes(\n transaction,\n requests,\n messenger,\n );\n\n const totals = calculateTotals({\n quotes: quotes as TransactionPayQuote<unknown>[],\n messenger,\n tokens,\n transaction,\n });\n\n log('Calculated totals', { transactionId, totals });\n\n syncTransaction({\n batchTransactions,\n messenger: messenger as never,\n paymentToken,\n totals,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n data.quotes = quotes as never;\n data.quotesLastUpdated = Date.now();\n data.totals = totals;\n });\n } finally {\n updateTransactionData(transactionId, (data) => {\n data.isLoading = false;\n });\n }\n\n return true;\n}\n\n/**\n * Sync batch transactions to the transaction meta.\n *\n * @param request - Request object.\n * @param request.batchTransactions - Batch transactions to sync.\n * @param request.messenger - Messenger instance.\n * @param request.paymentToken - Payment token used.\n * @param request.totals - Calculated totals.\n * @param request.transactionId - ID of the transaction to sync.\n */\nfunction syncTransaction({\n batchTransactions,\n messenger,\n paymentToken,\n totals,\n transactionId,\n}: {\n batchTransactions: BatchTransaction[];\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\n totals: TransactionPayTotals;\n transactionId: string;\n}): void {\n if (!paymentToken) {\n return;\n }\n\n updateTransaction(\n {\n transactionId,\n messenger: messenger as never,\n note: 'Update transaction pay data',\n },\n (tx: TransactionMeta) => {\n tx.batchTransactions = batchTransactions;\n tx.batchTransactionsOptions = {};\n\n tx.metamaskPay = {\n bridgeFeeFiat: totals.fees.provider.usd,\n chainId: paymentToken.chainId,\n networkFeeFiat: totals.fees.sourceNetwork.estimate.usd,\n tokenAddress: paymentToken.address,\n totalFiat: totals.total.usd,\n };\n },\n );\n}\n\n/**\n * Refresh quotes for all transactions if expired.\n *\n * @param messenger - Messenger instance.\n * @param updateTransactionData - Callback to update transaction data.\n */\nexport async function refreshQuotes(\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n): Promise<void> {\n const state = messenger.call('TransactionPayController:getState');\n const transactionIds = Object.keys(state.transactionData);\n\n for (const transactionId of transactionIds) {\n const transactionData = state.transactionData[transactionId];\n const { isLoading, quotes, quotesLastUpdated } = transactionData;\n\n if (isLoading || !quotes?.length) {\n continue;\n }\n\n const strategyName = quotes[0].strategy;\n const strategy = getStrategyByName(strategyName);\n\n const refreshInterval =\n (await strategy.getRefreshInterval?.({\n chainId: quotes[0].request.sourceChainId,\n messenger,\n })) ?? DEFAULT_REFRESH_INTERVAL;\n\n const isExpired = Date.now() - (quotesLastUpdated ?? 0) > refreshInterval;\n\n if (!isExpired) {\n continue;\n }\n\n const isUpdated = await updateQuotes({\n messenger,\n transactionData,\n transactionId,\n updateTransactionData,\n });\n\n if (isUpdated) {\n log('Refreshed quotes', { transactionId, strategy: strategyName });\n }\n }\n}\n\n/**\n * Build quote requests required to retrieve quotes.\n *\n * @param request - Request parameters.\n * @param request.from - Address from which the transaction is sent.\n * @param request.paymentToken - Payment token used for the transaction.\n * @param request.sourceAmounts - Source amounts for the transaction.\n * @param request.tokens - Required tokens for the transaction.\n * @param request.transactionId - ID of the transaction.\n * @returns Array of quote requests.\n */\nfunction buildQuoteRequests({\n from,\n paymentToken,\n sourceAmounts,\n tokens,\n transactionId,\n}: {\n from: Hex;\n paymentToken: TransactionPaymentToken | undefined;\n sourceAmounts: TransactionPaySourceAmount[] | undefined;\n tokens: TransactionPayRequiredToken[];\n transactionId: string;\n}): QuoteRequest[] {\n if (!paymentToken) {\n return [];\n }\n\n const requests = (sourceAmounts ?? []).map((sourceAmount) => {\n const token = tokens.find(\n (singleToken) => singleToken.address === sourceAmount.targetTokenAddress,\n ) as TransactionPayRequiredToken;\n\n return {\n from,\n sourceBalanceRaw: paymentToken.balanceRaw,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n sourceChainId: paymentToken.chainId,\n sourceTokenAddress: paymentToken.address,\n targetAmountMinimum: token.allowUnderMinimum ? '0' : token.amountRaw,\n targetChainId: token.chainId,\n targetTokenAddress: token.address,\n };\n });\n\n if (!requests.length) {\n log('No quote requests', { transactionId });\n }\n\n return requests;\n}\n\n/**\n * Retrieve quotes for a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param requests - Quote requests.\n * @param messenger - Controller messenger.\n * @returns An object containing batch transactions and quotes.\n */\nasync function getQuotes(\n transaction: TransactionMeta,\n requests: QuoteRequest[],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n batchTransactions: BatchTransaction[];\n quotes: TransactionPayQuote<Json>[];\n}> {\n const { id: transactionId } = transaction;\n const strategy = getStrategy(messenger as never, transaction);\n let quotes: TransactionPayQuote<Json>[] | undefined = [];\n\n try {\n quotes = requests?.length\n ? ((await strategy.getQuotes({\n messenger,\n requests,\n transaction,\n })) as TransactionPayQuote<Json>[])\n : [];\n } catch (error) {\n log('Error fetching quotes', { error, transactionId });\n }\n\n log('Updated', { transactionId, quotes });\n\n const batchTransactions =\n quotes?.length && strategy.getBatchTransactions\n ? await strategy.getBatchTransactions({\n messenger,\n quotes,\n })\n : [];\n\n log('Batch transactions', { transactionId, batchTransactions });\n\n return {\n batchTransactions,\n quotes,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"quotes.d.cts","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,eAAe,EACf,iCAAiC,EAMjC,6BAA6B,EAC9B,qBAAiB;AAMlB,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,6BAA6B,CAAC;CACtD,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAkElB;AAkDD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,iCAAiC,EAC5C,qBAAqB,EAAE,6BAA6B,iBAuCrD"}
1
+ {"version":3,"file":"quotes.d.cts","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,eAAe,EACf,iCAAiC,EAMjC,6BAA6B,EAC9B,qBAAiB;AAMlB,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,6BAA6B,CAAC;CACtD,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAkElB;AAkDD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,iCAAiC,EAC5C,qBAAqB,EAAE,6BAA6B,GACnD,OAAO,CAAC,IAAI,CAAC,CAsCf"}
@@ -1 +1 @@
1
- {"version":3,"file":"quotes.d.mts","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,eAAe,EACf,iCAAiC,EAMjC,6BAA6B,EAC9B,qBAAiB;AAMlB,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,6BAA6B,CAAC;CACtD,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAkElB;AAkDD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,iCAAiC,EAC5C,qBAAqB,EAAE,6BAA6B,iBAuCrD"}
1
+ {"version":3,"file":"quotes.d.mts","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,eAAe,EACf,iCAAiC,EAMjC,6BAA6B,EAC9B,qBAAiB;AAMlB,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,6BAA6B,CAAC;CACtD,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAkElB;AAkDD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,iCAAiC,EAC5C,qBAAqB,EAAE,6BAA6B,GACnD,OAAO,CAAC,IAAI,CAAC,CAsCf"}
@@ -144,7 +144,7 @@ function buildQuoteRequests({ from, paymentToken, sourceAmounts, tokens, transac
144
144
  return [];
145
145
  }
146
146
  const requests = (sourceAmounts ?? []).map((sourceAmount) => {
147
- const token = tokens.find((t) => t.address === sourceAmount.targetTokenAddress);
147
+ const token = tokens.find((singleToken) => singleToken.address === sourceAmount.targetTokenAddress);
148
148
  return {
149
149
  from,
150
150
  sourceBalanceRaw: paymentToken.balanceRaw,
@@ -1 +1 @@
1
- {"version":3,"file":"quotes.mjs","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { TransactionStatus } from '@metamask/transaction-controller';\nimport type { BatchTransaction } from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex, Json } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { getStrategy, getStrategyByName } from './strategy';\nimport { calculateTotals } from './totals';\nimport { getTransaction, updateTransaction } from './transaction';\nimport { projectLogger } from '../logger';\nimport type {\n QuoteRequest,\n TransactionData,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n TransactionPayRequiredToken,\n TransactionPaySourceAmount,\n TransactionPayTotals,\n TransactionPaymentToken,\n UpdateTransactionDataCallback,\n} from '../types';\n\nconst DEFAULT_REFRESH_INTERVAL = 30 * 1000; // 30 Seconds\n\nconst log = createModuleLogger(projectLogger, 'quotes');\n\nexport type UpdateQuotesRequest = {\n messenger: TransactionPayControllerMessenger;\n transactionData: TransactionData | undefined;\n transactionId: string;\n updateTransactionData: UpdateTransactionDataCallback;\n};\n\n/**\n * Update the quotes for a specific transaction.\n *\n * @param request - Request parameters.\n * @returns Boolean indicating if the quotes were updated.\n */\nexport async function updateQuotes(\n request: UpdateQuotesRequest,\n): Promise<boolean> {\n const { messenger, transactionData, transactionId, updateTransactionData } =\n request;\n\n const transaction = getTransaction(transactionId, messenger);\n\n if (!transaction || !transactionData) {\n throw new Error('Transaction not found');\n }\n\n if (transaction?.status !== TransactionStatus.unapproved) {\n return false;\n }\n\n log('Updating quotes', { transactionId });\n\n const { paymentToken, sourceAmounts, tokens } = transactionData;\n\n const requests = buildQuoteRequests({\n from: transaction.txParams.from as Hex,\n paymentToken,\n sourceAmounts,\n tokens,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n data.isLoading = true;\n });\n\n try {\n const { batchTransactions, quotes } = await getQuotes(\n transaction,\n requests,\n messenger,\n );\n\n const totals = calculateTotals({\n quotes: quotes as TransactionPayQuote<unknown>[],\n messenger,\n tokens,\n transaction,\n });\n\n log('Calculated totals', { transactionId, totals });\n\n syncTransaction({\n batchTransactions,\n messenger: messenger as never,\n paymentToken,\n totals,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n data.quotes = quotes as never;\n data.quotesLastUpdated = Date.now();\n data.totals = totals;\n });\n } finally {\n updateTransactionData(transactionId, (data) => {\n data.isLoading = false;\n });\n }\n\n return true;\n}\n\n/**\n * Sync batch transactions to the transaction meta.\n *\n * @param request - Request object.\n * @param request.batchTransactions - Batch transactions to sync.\n * @param request.messenger - Messenger instance.\n * @param request.paymentToken - Payment token used.\n * @param request.totals - Calculated totals.\n * @param request.transactionId - ID of the transaction to sync.\n */\nfunction syncTransaction({\n batchTransactions,\n messenger,\n paymentToken,\n totals,\n transactionId,\n}: {\n batchTransactions: BatchTransaction[];\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\n totals: TransactionPayTotals;\n transactionId: string;\n}) {\n if (!paymentToken) {\n return;\n }\n\n updateTransaction(\n {\n transactionId,\n messenger: messenger as never,\n note: 'Update transaction pay data',\n },\n (tx: TransactionMeta) => {\n tx.batchTransactions = batchTransactions;\n tx.batchTransactionsOptions = {};\n\n tx.metamaskPay = {\n bridgeFeeFiat: totals.fees.provider.usd,\n chainId: paymentToken.chainId,\n networkFeeFiat: totals.fees.sourceNetwork.estimate.usd,\n tokenAddress: paymentToken.address,\n totalFiat: totals.total.usd,\n };\n },\n );\n}\n\n/**\n * Refresh quotes for all transactions if expired.\n *\n * @param messenger - Messenger instance.\n * @param updateTransactionData - Callback to update transaction data.\n */\nexport async function refreshQuotes(\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n) {\n const state = messenger.call('TransactionPayController:getState');\n const transactionIds = Object.keys(state.transactionData);\n\n for (const transactionId of transactionIds) {\n const transactionData = state.transactionData[transactionId];\n const { isLoading, quotes, quotesLastUpdated } = transactionData;\n\n if (isLoading || !quotes?.length) {\n continue;\n }\n\n const strategyName = quotes[0].strategy;\n const strategy = getStrategyByName(strategyName);\n\n const refreshInterval =\n (await strategy.getRefreshInterval?.({\n chainId: quotes[0].request.sourceChainId,\n messenger,\n })) ?? DEFAULT_REFRESH_INTERVAL;\n\n const isExpired = Date.now() - (quotesLastUpdated ?? 0) > refreshInterval;\n\n if (!isExpired) {\n continue;\n }\n\n const isUpdated = await updateQuotes({\n messenger,\n transactionData,\n transactionId,\n updateTransactionData,\n });\n\n if (isUpdated) {\n log('Refreshed quotes', { transactionId, strategy: strategyName });\n }\n }\n}\n\n/**\n * Build quote requests required to retrieve quotes.\n *\n * @param request - Request parameters.\n * @param request.from - Address from which the transaction is sent.\n * @param request.paymentToken - Payment token used for the transaction.\n * @param request.sourceAmounts - Source amounts for the transaction.\n * @param request.tokens - Required tokens for the transaction.\n * @param request.transactionId - ID of the transaction.\n * @returns Array of quote requests.\n */\nfunction buildQuoteRequests({\n from,\n paymentToken,\n sourceAmounts,\n tokens,\n transactionId,\n}: {\n from: Hex;\n paymentToken: TransactionPaymentToken | undefined;\n sourceAmounts: TransactionPaySourceAmount[] | undefined;\n tokens: TransactionPayRequiredToken[];\n transactionId: string;\n}): QuoteRequest[] {\n if (!paymentToken) {\n return [];\n }\n\n const requests = (sourceAmounts ?? []).map((sourceAmount) => {\n const token = tokens.find(\n (t) => t.address === sourceAmount.targetTokenAddress,\n ) as TransactionPayRequiredToken;\n\n return {\n from,\n sourceBalanceRaw: paymentToken.balanceRaw,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n sourceChainId: paymentToken.chainId,\n sourceTokenAddress: paymentToken.address,\n targetAmountMinimum: token.allowUnderMinimum ? '0' : token.amountRaw,\n targetChainId: token.chainId,\n targetTokenAddress: token.address,\n };\n });\n\n if (!requests.length) {\n log('No quote requests', { transactionId });\n }\n\n return requests;\n}\n\n/**\n * Retrieve quotes for a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param requests - Quote requests.\n * @param messenger - Controller messenger.\n * @returns An object containing batch transactions and quotes.\n */\nasync function getQuotes(\n transaction: TransactionMeta,\n requests: QuoteRequest[],\n messenger: TransactionPayControllerMessenger,\n) {\n const { id: transactionId } = transaction;\n const strategy = getStrategy(messenger as never, transaction);\n let quotes: TransactionPayQuote<Json>[] | undefined = [];\n\n try {\n quotes = requests?.length\n ? ((await strategy.getQuotes({\n messenger,\n requests,\n transaction,\n })) as TransactionPayQuote<Json>[])\n : [];\n } catch (error) {\n log('Error fetching quotes', { error, transactionId });\n }\n\n log('Updated', { transactionId, quotes });\n\n const batchTransactions =\n quotes?.length && strategy.getBatchTransactions\n ? await strategy.getBatchTransactions({\n messenger,\n quotes,\n })\n : [];\n\n log('Batch transactions', { transactionId, batchTransactions });\n\n return {\n batchTransactions,\n quotes,\n };\n}\n"]}
1
+ {"version":3,"file":"quotes.mjs","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { TransactionStatus } from '@metamask/transaction-controller';\nimport type { BatchTransaction } from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex, Json } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { getStrategy, getStrategyByName } from './strategy';\nimport { calculateTotals } from './totals';\nimport { getTransaction, updateTransaction } from './transaction';\nimport { projectLogger } from '../logger';\nimport type {\n QuoteRequest,\n TransactionData,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n TransactionPayRequiredToken,\n TransactionPaySourceAmount,\n TransactionPayTotals,\n TransactionPaymentToken,\n UpdateTransactionDataCallback,\n} from '../types';\n\nconst DEFAULT_REFRESH_INTERVAL = 30 * 1000; // 30 Seconds\n\nconst log = createModuleLogger(projectLogger, 'quotes');\n\nexport type UpdateQuotesRequest = {\n messenger: TransactionPayControllerMessenger;\n transactionData: TransactionData | undefined;\n transactionId: string;\n updateTransactionData: UpdateTransactionDataCallback;\n};\n\n/**\n * Update the quotes for a specific transaction.\n *\n * @param request - Request parameters.\n * @returns Boolean indicating if the quotes were updated.\n */\nexport async function updateQuotes(\n request: UpdateQuotesRequest,\n): Promise<boolean> {\n const { messenger, transactionData, transactionId, updateTransactionData } =\n request;\n\n const transaction = getTransaction(transactionId, messenger);\n\n if (!transaction || !transactionData) {\n throw new Error('Transaction not found');\n }\n\n if (transaction?.status !== TransactionStatus.unapproved) {\n return false;\n }\n\n log('Updating quotes', { transactionId });\n\n const { paymentToken, sourceAmounts, tokens } = transactionData;\n\n const requests = buildQuoteRequests({\n from: transaction.txParams.from as Hex,\n paymentToken,\n sourceAmounts,\n tokens,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n data.isLoading = true;\n });\n\n try {\n const { batchTransactions, quotes } = await getQuotes(\n transaction,\n requests,\n messenger,\n );\n\n const totals = calculateTotals({\n quotes: quotes as TransactionPayQuote<unknown>[],\n messenger,\n tokens,\n transaction,\n });\n\n log('Calculated totals', { transactionId, totals });\n\n syncTransaction({\n batchTransactions,\n messenger: messenger as never,\n paymentToken,\n totals,\n transactionId,\n });\n\n updateTransactionData(transactionId, (data) => {\n data.quotes = quotes as never;\n data.quotesLastUpdated = Date.now();\n data.totals = totals;\n });\n } finally {\n updateTransactionData(transactionId, (data) => {\n data.isLoading = false;\n });\n }\n\n return true;\n}\n\n/**\n * Sync batch transactions to the transaction meta.\n *\n * @param request - Request object.\n * @param request.batchTransactions - Batch transactions to sync.\n * @param request.messenger - Messenger instance.\n * @param request.paymentToken - Payment token used.\n * @param request.totals - Calculated totals.\n * @param request.transactionId - ID of the transaction to sync.\n */\nfunction syncTransaction({\n batchTransactions,\n messenger,\n paymentToken,\n totals,\n transactionId,\n}: {\n batchTransactions: BatchTransaction[];\n messenger: TransactionPayControllerMessenger;\n paymentToken: TransactionPaymentToken | undefined;\n totals: TransactionPayTotals;\n transactionId: string;\n}): void {\n if (!paymentToken) {\n return;\n }\n\n updateTransaction(\n {\n transactionId,\n messenger: messenger as never,\n note: 'Update transaction pay data',\n },\n (tx: TransactionMeta) => {\n tx.batchTransactions = batchTransactions;\n tx.batchTransactionsOptions = {};\n\n tx.metamaskPay = {\n bridgeFeeFiat: totals.fees.provider.usd,\n chainId: paymentToken.chainId,\n networkFeeFiat: totals.fees.sourceNetwork.estimate.usd,\n tokenAddress: paymentToken.address,\n totalFiat: totals.total.usd,\n };\n },\n );\n}\n\n/**\n * Refresh quotes for all transactions if expired.\n *\n * @param messenger - Messenger instance.\n * @param updateTransactionData - Callback to update transaction data.\n */\nexport async function refreshQuotes(\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n): Promise<void> {\n const state = messenger.call('TransactionPayController:getState');\n const transactionIds = Object.keys(state.transactionData);\n\n for (const transactionId of transactionIds) {\n const transactionData = state.transactionData[transactionId];\n const { isLoading, quotes, quotesLastUpdated } = transactionData;\n\n if (isLoading || !quotes?.length) {\n continue;\n }\n\n const strategyName = quotes[0].strategy;\n const strategy = getStrategyByName(strategyName);\n\n const refreshInterval =\n (await strategy.getRefreshInterval?.({\n chainId: quotes[0].request.sourceChainId,\n messenger,\n })) ?? DEFAULT_REFRESH_INTERVAL;\n\n const isExpired = Date.now() - (quotesLastUpdated ?? 0) > refreshInterval;\n\n if (!isExpired) {\n continue;\n }\n\n const isUpdated = await updateQuotes({\n messenger,\n transactionData,\n transactionId,\n updateTransactionData,\n });\n\n if (isUpdated) {\n log('Refreshed quotes', { transactionId, strategy: strategyName });\n }\n }\n}\n\n/**\n * Build quote requests required to retrieve quotes.\n *\n * @param request - Request parameters.\n * @param request.from - Address from which the transaction is sent.\n * @param request.paymentToken - Payment token used for the transaction.\n * @param request.sourceAmounts - Source amounts for the transaction.\n * @param request.tokens - Required tokens for the transaction.\n * @param request.transactionId - ID of the transaction.\n * @returns Array of quote requests.\n */\nfunction buildQuoteRequests({\n from,\n paymentToken,\n sourceAmounts,\n tokens,\n transactionId,\n}: {\n from: Hex;\n paymentToken: TransactionPaymentToken | undefined;\n sourceAmounts: TransactionPaySourceAmount[] | undefined;\n tokens: TransactionPayRequiredToken[];\n transactionId: string;\n}): QuoteRequest[] {\n if (!paymentToken) {\n return [];\n }\n\n const requests = (sourceAmounts ?? []).map((sourceAmount) => {\n const token = tokens.find(\n (singleToken) => singleToken.address === sourceAmount.targetTokenAddress,\n ) as TransactionPayRequiredToken;\n\n return {\n from,\n sourceBalanceRaw: paymentToken.balanceRaw,\n sourceTokenAmount: sourceAmount.sourceAmountRaw,\n sourceChainId: paymentToken.chainId,\n sourceTokenAddress: paymentToken.address,\n targetAmountMinimum: token.allowUnderMinimum ? '0' : token.amountRaw,\n targetChainId: token.chainId,\n targetTokenAddress: token.address,\n };\n });\n\n if (!requests.length) {\n log('No quote requests', { transactionId });\n }\n\n return requests;\n}\n\n/**\n * Retrieve quotes for a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param requests - Quote requests.\n * @param messenger - Controller messenger.\n * @returns An object containing batch transactions and quotes.\n */\nasync function getQuotes(\n transaction: TransactionMeta,\n requests: QuoteRequest[],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n batchTransactions: BatchTransaction[];\n quotes: TransactionPayQuote<Json>[];\n}> {\n const { id: transactionId } = transaction;\n const strategy = getStrategy(messenger as never, transaction);\n let quotes: TransactionPayQuote<Json>[] | undefined = [];\n\n try {\n quotes = requests?.length\n ? ((await strategy.getQuotes({\n messenger,\n requests,\n transaction,\n })) as TransactionPayQuote<Json>[])\n : [];\n } catch (error) {\n log('Error fetching quotes', { error, transactionId });\n }\n\n log('Updated', { transactionId, quotes });\n\n const batchTransactions =\n quotes?.length && strategy.getBatchTransactions\n ? await strategy.getBatchTransactions({\n messenger,\n quotes,\n })\n : [];\n\n log('Batch transactions', { transactionId, batchTransactions });\n\n return {\n batchTransactions,\n quotes,\n };\n}\n"]}
@@ -164,9 +164,9 @@ function getTokenTransferData(transactionMeta) {
164
164
  return { data: singleData, to: singleTo, index: undefined };
165
165
  }
166
166
  const nestedCallIndex = nestedTransactions?.findIndex((call) => call.data?.startsWith(FOUR_BYTE_TOKEN_TRANSFER));
167
- const nestedCall = nestedCallIndex !== undefined
168
- ? nestedTransactions?.[nestedCallIndex]
169
- : undefined;
167
+ const nestedCall = nestedCallIndex === undefined
168
+ ? undefined
169
+ : nestedTransactions?.[nestedCallIndex];
170
170
  if (nestedCall?.data && nestedCall.to) {
171
171
  return {
172
172
  data: nestedCall.data,
@@ -1 +1 @@
1
- {"version":3,"file":"required-tokens.cjs","sourceRoot":"","sources":["../../src/utils/required-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { toHex } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport { add0x } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n getTokenInfo,\n} from './token';\nimport type {\n FiatRates,\n TransactionPayControllerMessenger,\n TransactionPayRequiredToken,\n} from '../types';\n\nconst FOUR_BYTE_TOKEN_TRANSFER = '0xa9059cbb';\n\n/**\n * Parse required tokens from a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @returns An array of required tokens.\n */\nexport function parseRequiredTokens(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken[] {\n return [\n getTokenTransferToken(transaction, messenger),\n getGasFeeToken(transaction, messenger),\n ].filter(Boolean) as TransactionPayRequiredToken[];\n}\n\n/**\n * Parse a required token from a token transfer.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @returns The required token or undefined if the transaction is not a token transfer.\n */\nfunction getTokenTransferToken(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken | undefined {\n const { data, to } = getTokenTransferData(transaction) ?? {};\n\n if (!to || !data) {\n return undefined;\n }\n\n let transferAmount: Hex | undefined;\n\n try {\n const result = new Interface(abiERC20).decodeFunctionData('transfer', data);\n transferAmount = toHex(result._value);\n } catch {\n // Intentionally empty\n }\n\n if (transferAmount === undefined) {\n return undefined;\n }\n\n return buildRequiredToken(transaction, to, transferAmount, messenger);\n}\n\n/**\n * Get the gas fee token required for a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @returns The gas fee token or undefined if it could not be determined.\n */\nfunction getGasFeeToken(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken | undefined {\n const { chainId, txParams } = transaction;\n const { gas, maxFeePerGas } = txParams;\n const nativeTokenAddress = getNativeToken(chainId);\n\n const maxGasCostRawHex = add0x(\n new BigNumber(gas ?? '0x0')\n .multipliedBy(new BigNumber(maxFeePerGas ?? '0x0'))\n .toString(16),\n );\n\n const token = buildRequiredToken(\n transaction,\n nativeTokenAddress,\n maxGasCostRawHex,\n messenger,\n );\n\n if (!token) {\n return undefined;\n }\n\n const amountUsdValue = new BigNumber(token.amountUsd);\n\n const hasBalance = new BigNumber(token.balanceRaw).isGreaterThanOrEqualTo(\n token.amountRaw,\n );\n\n if (hasBalance || amountUsdValue.isGreaterThanOrEqualTo(1)) {\n return {\n ...token,\n allowUnderMinimum: true,\n skipIfBalance: true,\n };\n }\n\n const fiatRates = getTokenFiatRate(\n messenger,\n nativeTokenAddress,\n chainId,\n ) as FiatRates;\n\n const oneDollarRawHex = add0x(\n new BigNumber(1).dividedBy(fiatRates.usdRate).shiftedBy(18).toString(16),\n );\n\n const oneDollarToken = buildRequiredToken(\n transaction,\n nativeTokenAddress,\n oneDollarRawHex,\n messenger,\n );\n\n /* istanbul ignore next */\n if (!oneDollarToken) {\n return undefined;\n }\n\n return {\n ...oneDollarToken,\n allowUnderMinimum: true,\n skipIfBalance: true,\n };\n}\n\n/**\n * Get the full token properties for a specific token and amount.\n *\n * @param transaction - Transaction metadata.\n * @param tokenAddress - Token address.\n * @param amountRawHex - Raw token amount in hexadecimal format.\n * @param messenger - Controller messenger.\n * @returns The full token properties or undefined if the token data could not be retrieved.\n */\nfunction buildRequiredToken(\n transaction: TransactionMeta,\n tokenAddress: Hex,\n amountRawHex: Hex,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken | undefined {\n const { chainId, txParams } = transaction;\n const from = txParams.from as Hex;\n\n const { decimals: tokenDecimals, symbol } =\n getTokenInfo(messenger, tokenAddress, chainId) ?? {};\n\n const fiatRates = getTokenFiatRate(messenger, tokenAddress, chainId);\n const tokenBalance = getTokenBalance(messenger, from, chainId, tokenAddress);\n\n if (tokenDecimals === undefined || !symbol || fiatRates === undefined) {\n return undefined;\n }\n\n const {\n amountHuman: balanceHuman,\n amountRaw: balanceRaw,\n amountFiat: balanceFiat,\n amountUsd: balanceUsd,\n } = calculateAmounts(tokenBalance, tokenDecimals, fiatRates);\n\n const { amountHuman, amountRaw, amountFiat, amountUsd } = calculateAmounts(\n amountRawHex,\n tokenDecimals,\n fiatRates,\n );\n\n return {\n address: tokenAddress,\n allowUnderMinimum: false,\n amountFiat,\n amountHuman,\n amountRaw,\n amountUsd,\n balanceFiat,\n balanceHuman,\n balanceRaw,\n balanceUsd,\n chainId,\n decimals: tokenDecimals,\n skipIfBalance: false,\n symbol,\n };\n}\n\n/**\n * Calculates the various amount representations for a token value.\n *\n * @param amountRawInput - Raw amount.\n * @param decimals - Number of decimals for the token.\n * @param fiatRates - Fiat rates for the token.\n * @returns Object containing amount in fiat, human-readable, raw, and USD formats.\n */\nfunction calculateAmounts(\n amountRawInput: BigNumber.Value,\n decimals: number,\n fiatRates: FiatRates,\n) {\n const amountRawValue = new BigNumber(amountRawInput);\n const amountHumanValue = amountRawValue.shiftedBy(-decimals);\n\n const amountFiat = amountHumanValue\n .multipliedBy(fiatRates.fiatRate)\n .toString(10);\n\n const amountUsd = amountHumanValue\n .multipliedBy(fiatRates.usdRate)\n .toString(10);\n\n const amountRaw = amountRawValue.toFixed(0);\n const amountHuman = amountHumanValue.toString(10);\n\n return {\n amountFiat,\n amountHuman,\n amountRaw,\n amountUsd,\n };\n}\n\n/**\n * Find token transfer data in a transaction.\n *\n * @param transactionMeta - Transaction metadata.\n * @returns - Token transfer data or undefined if not found.\n */\nfunction getTokenTransferData(transactionMeta: TransactionMeta):\n | {\n data: Hex;\n to: Hex;\n index?: number;\n }\n | undefined {\n const { nestedTransactions, txParams } = transactionMeta;\n const { data: singleData } = txParams;\n const singleTo = txParams?.to as Hex | undefined;\n\n if (singleData?.startsWith(FOUR_BYTE_TOKEN_TRANSFER) && singleTo) {\n return { data: singleData as Hex, to: singleTo, index: undefined };\n }\n\n const nestedCallIndex = nestedTransactions?.findIndex((call) =>\n call.data?.startsWith(FOUR_BYTE_TOKEN_TRANSFER),\n );\n\n const nestedCall =\n nestedCallIndex !== undefined\n ? nestedTransactions?.[nestedCallIndex]\n : undefined;\n\n if (nestedCall?.data && nestedCall.to) {\n return {\n data: nestedCall.data,\n to: nestedCall.to,\n index: nestedCallIndex,\n };\n }\n\n return undefined;\n}\n"]}
1
+ {"version":3,"file":"required-tokens.cjs","sourceRoot":"","sources":["../../src/utils/required-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { toHex } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport { add0x } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n getTokenInfo,\n} from './token';\nimport type {\n FiatRates,\n TransactionPayControllerMessenger,\n TransactionPayRequiredToken,\n} from '../types';\n\nconst FOUR_BYTE_TOKEN_TRANSFER = '0xa9059cbb';\n\n/**\n * Parse required tokens from a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @returns An array of required tokens.\n */\nexport function parseRequiredTokens(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken[] {\n return [\n getTokenTransferToken(transaction, messenger),\n getGasFeeToken(transaction, messenger),\n ].filter(Boolean) as TransactionPayRequiredToken[];\n}\n\n/**\n * Parse a required token from a token transfer.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @returns The required token or undefined if the transaction is not a token transfer.\n */\nfunction getTokenTransferToken(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken | undefined {\n const { data, to } = getTokenTransferData(transaction) ?? {};\n\n if (!to || !data) {\n return undefined;\n }\n\n let transferAmount: Hex | undefined;\n\n try {\n const result = new Interface(abiERC20).decodeFunctionData('transfer', data);\n transferAmount = toHex(result._value);\n } catch {\n // Intentionally empty\n }\n\n if (transferAmount === undefined) {\n return undefined;\n }\n\n return buildRequiredToken(transaction, to, transferAmount, messenger);\n}\n\n/**\n * Get the gas fee token required for a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @returns The gas fee token or undefined if it could not be determined.\n */\nfunction getGasFeeToken(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken | undefined {\n const { chainId, txParams } = transaction;\n const { gas, maxFeePerGas } = txParams;\n const nativeTokenAddress = getNativeToken(chainId);\n\n const maxGasCostRawHex = add0x(\n new BigNumber(gas ?? '0x0')\n .multipliedBy(new BigNumber(maxFeePerGas ?? '0x0'))\n .toString(16),\n );\n\n const token = buildRequiredToken(\n transaction,\n nativeTokenAddress,\n maxGasCostRawHex,\n messenger,\n );\n\n if (!token) {\n return undefined;\n }\n\n const amountUsdValue = new BigNumber(token.amountUsd);\n\n const hasBalance = new BigNumber(token.balanceRaw).isGreaterThanOrEqualTo(\n token.amountRaw,\n );\n\n if (hasBalance || amountUsdValue.isGreaterThanOrEqualTo(1)) {\n return {\n ...token,\n allowUnderMinimum: true,\n skipIfBalance: true,\n };\n }\n\n const fiatRates = getTokenFiatRate(\n messenger,\n nativeTokenAddress,\n chainId,\n ) as FiatRates;\n\n const oneDollarRawHex = add0x(\n new BigNumber(1).dividedBy(fiatRates.usdRate).shiftedBy(18).toString(16),\n );\n\n const oneDollarToken = buildRequiredToken(\n transaction,\n nativeTokenAddress,\n oneDollarRawHex,\n messenger,\n );\n\n /* istanbul ignore next */\n if (!oneDollarToken) {\n return undefined;\n }\n\n return {\n ...oneDollarToken,\n allowUnderMinimum: true,\n skipIfBalance: true,\n };\n}\n\n/**\n * Get the full token properties for a specific token and amount.\n *\n * @param transaction - Transaction metadata.\n * @param tokenAddress - Token address.\n * @param amountRawHex - Raw token amount in hexadecimal format.\n * @param messenger - Controller messenger.\n * @returns The full token properties or undefined if the token data could not be retrieved.\n */\nfunction buildRequiredToken(\n transaction: TransactionMeta,\n tokenAddress: Hex,\n amountRawHex: Hex,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken | undefined {\n const { chainId, txParams } = transaction;\n const from = txParams.from as Hex;\n\n const { decimals: tokenDecimals, symbol } =\n getTokenInfo(messenger, tokenAddress, chainId) ?? {};\n\n const fiatRates = getTokenFiatRate(messenger, tokenAddress, chainId);\n const tokenBalance = getTokenBalance(messenger, from, chainId, tokenAddress);\n\n if (tokenDecimals === undefined || !symbol || fiatRates === undefined) {\n return undefined;\n }\n\n const {\n amountHuman: balanceHuman,\n amountRaw: balanceRaw,\n amountFiat: balanceFiat,\n amountUsd: balanceUsd,\n } = calculateAmounts(tokenBalance, tokenDecimals, fiatRates);\n\n const { amountHuman, amountRaw, amountFiat, amountUsd } = calculateAmounts(\n amountRawHex,\n tokenDecimals,\n fiatRates,\n );\n\n return {\n address: tokenAddress,\n allowUnderMinimum: false,\n amountFiat,\n amountHuman,\n amountRaw,\n amountUsd,\n balanceFiat,\n balanceHuman,\n balanceRaw,\n balanceUsd,\n chainId,\n decimals: tokenDecimals,\n skipIfBalance: false,\n symbol,\n };\n}\n\n/**\n * Calculates the various amount representations for a token value.\n *\n * @param amountRawInput - Raw amount.\n * @param decimals - Number of decimals for the token.\n * @param fiatRates - Fiat rates for the token.\n * @returns Object containing amount in fiat, human-readable, raw, and USD formats.\n */\nfunction calculateAmounts(\n amountRawInput: BigNumber.Value,\n decimals: number,\n fiatRates: FiatRates,\n): {\n amountFiat: string;\n amountHuman: string;\n amountRaw: string;\n amountUsd: string;\n} {\n const amountRawValue = new BigNumber(amountRawInput);\n const amountHumanValue = amountRawValue.shiftedBy(-decimals);\n\n const amountFiat = amountHumanValue\n .multipliedBy(fiatRates.fiatRate)\n .toString(10);\n\n const amountUsd = amountHumanValue\n .multipliedBy(fiatRates.usdRate)\n .toString(10);\n\n const amountRaw = amountRawValue.toFixed(0);\n const amountHuman = amountHumanValue.toString(10);\n\n return {\n amountFiat,\n amountHuman,\n amountRaw,\n amountUsd,\n };\n}\n\n/**\n * Find token transfer data in a transaction.\n *\n * @param transactionMeta - Transaction metadata.\n * @returns - Token transfer data or undefined if not found.\n */\nfunction getTokenTransferData(transactionMeta: TransactionMeta):\n | {\n data: Hex;\n to: Hex;\n index?: number;\n }\n | undefined {\n const { nestedTransactions, txParams } = transactionMeta;\n const { data: singleData } = txParams;\n const singleTo = txParams?.to as Hex | undefined;\n\n if (singleData?.startsWith(FOUR_BYTE_TOKEN_TRANSFER) && singleTo) {\n return { data: singleData as Hex, to: singleTo, index: undefined };\n }\n\n const nestedCallIndex = nestedTransactions?.findIndex((call) =>\n call.data?.startsWith(FOUR_BYTE_TOKEN_TRANSFER),\n );\n\n const nestedCall =\n nestedCallIndex === undefined\n ? undefined\n : nestedTransactions?.[nestedCallIndex];\n\n if (nestedCall?.data && nestedCall.to) {\n return {\n data: nestedCall.data,\n to: nestedCall.to,\n index: nestedCallIndex,\n };\n }\n\n return undefined;\n}\n"]}
@@ -160,9 +160,9 @@ function getTokenTransferData(transactionMeta) {
160
160
  return { data: singleData, to: singleTo, index: undefined };
161
161
  }
162
162
  const nestedCallIndex = nestedTransactions?.findIndex((call) => call.data?.startsWith(FOUR_BYTE_TOKEN_TRANSFER));
163
- const nestedCall = nestedCallIndex !== undefined
164
- ? nestedTransactions?.[nestedCallIndex]
165
- : undefined;
163
+ const nestedCall = nestedCallIndex === undefined
164
+ ? undefined
165
+ : nestedTransactions?.[nestedCallIndex];
166
166
  if (nestedCall?.data && nestedCall.to) {
167
167
  return {
168
168
  data: nestedCall.data,
@@ -1 +1 @@
1
- {"version":3,"file":"required-tokens.mjs","sourceRoot":"","sources":["../../src/utils/required-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { toHex } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport { add0x } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n getTokenInfo,\n} from './token';\nimport type {\n FiatRates,\n TransactionPayControllerMessenger,\n TransactionPayRequiredToken,\n} from '../types';\n\nconst FOUR_BYTE_TOKEN_TRANSFER = '0xa9059cbb';\n\n/**\n * Parse required tokens from a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @returns An array of required tokens.\n */\nexport function parseRequiredTokens(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken[] {\n return [\n getTokenTransferToken(transaction, messenger),\n getGasFeeToken(transaction, messenger),\n ].filter(Boolean) as TransactionPayRequiredToken[];\n}\n\n/**\n * Parse a required token from a token transfer.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @returns The required token or undefined if the transaction is not a token transfer.\n */\nfunction getTokenTransferToken(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken | undefined {\n const { data, to } = getTokenTransferData(transaction) ?? {};\n\n if (!to || !data) {\n return undefined;\n }\n\n let transferAmount: Hex | undefined;\n\n try {\n const result = new Interface(abiERC20).decodeFunctionData('transfer', data);\n transferAmount = toHex(result._value);\n } catch {\n // Intentionally empty\n }\n\n if (transferAmount === undefined) {\n return undefined;\n }\n\n return buildRequiredToken(transaction, to, transferAmount, messenger);\n}\n\n/**\n * Get the gas fee token required for a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @returns The gas fee token or undefined if it could not be determined.\n */\nfunction getGasFeeToken(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken | undefined {\n const { chainId, txParams } = transaction;\n const { gas, maxFeePerGas } = txParams;\n const nativeTokenAddress = getNativeToken(chainId);\n\n const maxGasCostRawHex = add0x(\n new BigNumber(gas ?? '0x0')\n .multipliedBy(new BigNumber(maxFeePerGas ?? '0x0'))\n .toString(16),\n );\n\n const token = buildRequiredToken(\n transaction,\n nativeTokenAddress,\n maxGasCostRawHex,\n messenger,\n );\n\n if (!token) {\n return undefined;\n }\n\n const amountUsdValue = new BigNumber(token.amountUsd);\n\n const hasBalance = new BigNumber(token.balanceRaw).isGreaterThanOrEqualTo(\n token.amountRaw,\n );\n\n if (hasBalance || amountUsdValue.isGreaterThanOrEqualTo(1)) {\n return {\n ...token,\n allowUnderMinimum: true,\n skipIfBalance: true,\n };\n }\n\n const fiatRates = getTokenFiatRate(\n messenger,\n nativeTokenAddress,\n chainId,\n ) as FiatRates;\n\n const oneDollarRawHex = add0x(\n new BigNumber(1).dividedBy(fiatRates.usdRate).shiftedBy(18).toString(16),\n );\n\n const oneDollarToken = buildRequiredToken(\n transaction,\n nativeTokenAddress,\n oneDollarRawHex,\n messenger,\n );\n\n /* istanbul ignore next */\n if (!oneDollarToken) {\n return undefined;\n }\n\n return {\n ...oneDollarToken,\n allowUnderMinimum: true,\n skipIfBalance: true,\n };\n}\n\n/**\n * Get the full token properties for a specific token and amount.\n *\n * @param transaction - Transaction metadata.\n * @param tokenAddress - Token address.\n * @param amountRawHex - Raw token amount in hexadecimal format.\n * @param messenger - Controller messenger.\n * @returns The full token properties or undefined if the token data could not be retrieved.\n */\nfunction buildRequiredToken(\n transaction: TransactionMeta,\n tokenAddress: Hex,\n amountRawHex: Hex,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken | undefined {\n const { chainId, txParams } = transaction;\n const from = txParams.from as Hex;\n\n const { decimals: tokenDecimals, symbol } =\n getTokenInfo(messenger, tokenAddress, chainId) ?? {};\n\n const fiatRates = getTokenFiatRate(messenger, tokenAddress, chainId);\n const tokenBalance = getTokenBalance(messenger, from, chainId, tokenAddress);\n\n if (tokenDecimals === undefined || !symbol || fiatRates === undefined) {\n return undefined;\n }\n\n const {\n amountHuman: balanceHuman,\n amountRaw: balanceRaw,\n amountFiat: balanceFiat,\n amountUsd: balanceUsd,\n } = calculateAmounts(tokenBalance, tokenDecimals, fiatRates);\n\n const { amountHuman, amountRaw, amountFiat, amountUsd } = calculateAmounts(\n amountRawHex,\n tokenDecimals,\n fiatRates,\n );\n\n return {\n address: tokenAddress,\n allowUnderMinimum: false,\n amountFiat,\n amountHuman,\n amountRaw,\n amountUsd,\n balanceFiat,\n balanceHuman,\n balanceRaw,\n balanceUsd,\n chainId,\n decimals: tokenDecimals,\n skipIfBalance: false,\n symbol,\n };\n}\n\n/**\n * Calculates the various amount representations for a token value.\n *\n * @param amountRawInput - Raw amount.\n * @param decimals - Number of decimals for the token.\n * @param fiatRates - Fiat rates for the token.\n * @returns Object containing amount in fiat, human-readable, raw, and USD formats.\n */\nfunction calculateAmounts(\n amountRawInput: BigNumber.Value,\n decimals: number,\n fiatRates: FiatRates,\n) {\n const amountRawValue = new BigNumber(amountRawInput);\n const amountHumanValue = amountRawValue.shiftedBy(-decimals);\n\n const amountFiat = amountHumanValue\n .multipliedBy(fiatRates.fiatRate)\n .toString(10);\n\n const amountUsd = amountHumanValue\n .multipliedBy(fiatRates.usdRate)\n .toString(10);\n\n const amountRaw = amountRawValue.toFixed(0);\n const amountHuman = amountHumanValue.toString(10);\n\n return {\n amountFiat,\n amountHuman,\n amountRaw,\n amountUsd,\n };\n}\n\n/**\n * Find token transfer data in a transaction.\n *\n * @param transactionMeta - Transaction metadata.\n * @returns - Token transfer data or undefined if not found.\n */\nfunction getTokenTransferData(transactionMeta: TransactionMeta):\n | {\n data: Hex;\n to: Hex;\n index?: number;\n }\n | undefined {\n const { nestedTransactions, txParams } = transactionMeta;\n const { data: singleData } = txParams;\n const singleTo = txParams?.to as Hex | undefined;\n\n if (singleData?.startsWith(FOUR_BYTE_TOKEN_TRANSFER) && singleTo) {\n return { data: singleData as Hex, to: singleTo, index: undefined };\n }\n\n const nestedCallIndex = nestedTransactions?.findIndex((call) =>\n call.data?.startsWith(FOUR_BYTE_TOKEN_TRANSFER),\n );\n\n const nestedCall =\n nestedCallIndex !== undefined\n ? nestedTransactions?.[nestedCallIndex]\n : undefined;\n\n if (nestedCall?.data && nestedCall.to) {\n return {\n data: nestedCall.data,\n to: nestedCall.to,\n index: nestedCallIndex,\n };\n }\n\n return undefined;\n}\n"]}
1
+ {"version":3,"file":"required-tokens.mjs","sourceRoot":"","sources":["../../src/utils/required-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { toHex } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport { add0x } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n getTokenInfo,\n} from './token';\nimport type {\n FiatRates,\n TransactionPayControllerMessenger,\n TransactionPayRequiredToken,\n} from '../types';\n\nconst FOUR_BYTE_TOKEN_TRANSFER = '0xa9059cbb';\n\n/**\n * Parse required tokens from a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @returns An array of required tokens.\n */\nexport function parseRequiredTokens(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken[] {\n return [\n getTokenTransferToken(transaction, messenger),\n getGasFeeToken(transaction, messenger),\n ].filter(Boolean) as TransactionPayRequiredToken[];\n}\n\n/**\n * Parse a required token from a token transfer.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @returns The required token or undefined if the transaction is not a token transfer.\n */\nfunction getTokenTransferToken(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken | undefined {\n const { data, to } = getTokenTransferData(transaction) ?? {};\n\n if (!to || !data) {\n return undefined;\n }\n\n let transferAmount: Hex | undefined;\n\n try {\n const result = new Interface(abiERC20).decodeFunctionData('transfer', data);\n transferAmount = toHex(result._value);\n } catch {\n // Intentionally empty\n }\n\n if (transferAmount === undefined) {\n return undefined;\n }\n\n return buildRequiredToken(transaction, to, transferAmount, messenger);\n}\n\n/**\n * Get the gas fee token required for a transaction.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @returns The gas fee token or undefined if it could not be determined.\n */\nfunction getGasFeeToken(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken | undefined {\n const { chainId, txParams } = transaction;\n const { gas, maxFeePerGas } = txParams;\n const nativeTokenAddress = getNativeToken(chainId);\n\n const maxGasCostRawHex = add0x(\n new BigNumber(gas ?? '0x0')\n .multipliedBy(new BigNumber(maxFeePerGas ?? '0x0'))\n .toString(16),\n );\n\n const token = buildRequiredToken(\n transaction,\n nativeTokenAddress,\n maxGasCostRawHex,\n messenger,\n );\n\n if (!token) {\n return undefined;\n }\n\n const amountUsdValue = new BigNumber(token.amountUsd);\n\n const hasBalance = new BigNumber(token.balanceRaw).isGreaterThanOrEqualTo(\n token.amountRaw,\n );\n\n if (hasBalance || amountUsdValue.isGreaterThanOrEqualTo(1)) {\n return {\n ...token,\n allowUnderMinimum: true,\n skipIfBalance: true,\n };\n }\n\n const fiatRates = getTokenFiatRate(\n messenger,\n nativeTokenAddress,\n chainId,\n ) as FiatRates;\n\n const oneDollarRawHex = add0x(\n new BigNumber(1).dividedBy(fiatRates.usdRate).shiftedBy(18).toString(16),\n );\n\n const oneDollarToken = buildRequiredToken(\n transaction,\n nativeTokenAddress,\n oneDollarRawHex,\n messenger,\n );\n\n /* istanbul ignore next */\n if (!oneDollarToken) {\n return undefined;\n }\n\n return {\n ...oneDollarToken,\n allowUnderMinimum: true,\n skipIfBalance: true,\n };\n}\n\n/**\n * Get the full token properties for a specific token and amount.\n *\n * @param transaction - Transaction metadata.\n * @param tokenAddress - Token address.\n * @param amountRawHex - Raw token amount in hexadecimal format.\n * @param messenger - Controller messenger.\n * @returns The full token properties or undefined if the token data could not be retrieved.\n */\nfunction buildRequiredToken(\n transaction: TransactionMeta,\n tokenAddress: Hex,\n amountRawHex: Hex,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayRequiredToken | undefined {\n const { chainId, txParams } = transaction;\n const from = txParams.from as Hex;\n\n const { decimals: tokenDecimals, symbol } =\n getTokenInfo(messenger, tokenAddress, chainId) ?? {};\n\n const fiatRates = getTokenFiatRate(messenger, tokenAddress, chainId);\n const tokenBalance = getTokenBalance(messenger, from, chainId, tokenAddress);\n\n if (tokenDecimals === undefined || !symbol || fiatRates === undefined) {\n return undefined;\n }\n\n const {\n amountHuman: balanceHuman,\n amountRaw: balanceRaw,\n amountFiat: balanceFiat,\n amountUsd: balanceUsd,\n } = calculateAmounts(tokenBalance, tokenDecimals, fiatRates);\n\n const { amountHuman, amountRaw, amountFiat, amountUsd } = calculateAmounts(\n amountRawHex,\n tokenDecimals,\n fiatRates,\n );\n\n return {\n address: tokenAddress,\n allowUnderMinimum: false,\n amountFiat,\n amountHuman,\n amountRaw,\n amountUsd,\n balanceFiat,\n balanceHuman,\n balanceRaw,\n balanceUsd,\n chainId,\n decimals: tokenDecimals,\n skipIfBalance: false,\n symbol,\n };\n}\n\n/**\n * Calculates the various amount representations for a token value.\n *\n * @param amountRawInput - Raw amount.\n * @param decimals - Number of decimals for the token.\n * @param fiatRates - Fiat rates for the token.\n * @returns Object containing amount in fiat, human-readable, raw, and USD formats.\n */\nfunction calculateAmounts(\n amountRawInput: BigNumber.Value,\n decimals: number,\n fiatRates: FiatRates,\n): {\n amountFiat: string;\n amountHuman: string;\n amountRaw: string;\n amountUsd: string;\n} {\n const amountRawValue = new BigNumber(amountRawInput);\n const amountHumanValue = amountRawValue.shiftedBy(-decimals);\n\n const amountFiat = amountHumanValue\n .multipliedBy(fiatRates.fiatRate)\n .toString(10);\n\n const amountUsd = amountHumanValue\n .multipliedBy(fiatRates.usdRate)\n .toString(10);\n\n const amountRaw = amountRawValue.toFixed(0);\n const amountHuman = amountHumanValue.toString(10);\n\n return {\n amountFiat,\n amountHuman,\n amountRaw,\n amountUsd,\n };\n}\n\n/**\n * Find token transfer data in a transaction.\n *\n * @param transactionMeta - Transaction metadata.\n * @returns - Token transfer data or undefined if not found.\n */\nfunction getTokenTransferData(transactionMeta: TransactionMeta):\n | {\n data: Hex;\n to: Hex;\n index?: number;\n }\n | undefined {\n const { nestedTransactions, txParams } = transactionMeta;\n const { data: singleData } = txParams;\n const singleTo = txParams?.to as Hex | undefined;\n\n if (singleData?.startsWith(FOUR_BYTE_TOKEN_TRANSFER) && singleTo) {\n return { data: singleData as Hex, to: singleTo, index: undefined };\n }\n\n const nestedCallIndex = nestedTransactions?.findIndex((call) =>\n call.data?.startsWith(FOUR_BYTE_TOKEN_TRANSFER),\n );\n\n const nestedCall =\n nestedCallIndex === undefined\n ? undefined\n : nestedTransactions?.[nestedCallIndex];\n\n if (nestedCall?.data && nestedCall.to) {\n return {\n data: nestedCall.data,\n to: nestedCall.to,\n index: nestedCallIndex,\n };\n }\n\n return undefined;\n}\n"]}
@@ -25,7 +25,7 @@ function updateSourceAmounts(transactionId, transactionData, messenger) {
25
25
  return;
26
26
  }
27
27
  const sourceAmounts = tokens
28
- .map((t) => calculateSourceAmount(paymentToken, t, messenger, transactionId))
28
+ .map((singleToken) => calculateSourceAmount(paymentToken, singleToken, messenger, transactionId))
29
29
  .filter(Boolean);
30
30
  log('Updated source amounts', { transactionId, sourceAmounts });
31
31
  transactionData.sourceAmounts = sourceAmounts;
@@ -1 +1 @@
1
- {"version":3,"file":"source-amounts.cjs","sourceRoot":"","sources":["../../src/utils/source-amounts.ts"],"names":[],"mappings":"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","sourcesContent":["import { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { getTokenFiatRate } from './token';\nimport { getTransaction } from './transaction';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPaymentToken,\n} from '..';\nimport { TransactionPayStrategy } from '..';\nimport type { TransactionMeta } from '../../../transaction-controller/src';\nimport { ARBITRUM_USDC_ADDRESS, CHAIN_ID_ARBITRUM } from '../constants';\nimport { projectLogger } from '../logger';\nimport type {\n TransactionPaySourceAmount,\n TransactionData,\n TransactionPayRequiredToken,\n} from '../types';\n\nconst log = createModuleLogger(projectLogger, 'source-amounts');\n\n/**\n * Update the source amounts for a transaction.\n *\n * @param transactionId - ID of the transaction to update.\n * @param transactionData - Existing transaction data.\n * @param messenger - Controller messenger.\n */\nexport function updateSourceAmounts(\n transactionId: string,\n transactionData: TransactionData | undefined,\n messenger: TransactionPayControllerMessenger,\n) {\n if (!transactionData) {\n return;\n }\n\n const { paymentToken, tokens } = transactionData;\n\n if (!tokens.length || !paymentToken) {\n return;\n }\n\n const sourceAmounts = tokens\n .map((t) =>\n calculateSourceAmount(paymentToken, t, messenger, transactionId),\n )\n .filter(Boolean) as TransactionPaySourceAmount[];\n\n log('Updated source amounts', { transactionId, sourceAmounts });\n\n transactionData.sourceAmounts = sourceAmounts;\n}\n\n/**\n * Calculate the required source amount for a payment token to cover a target token.\n *\n * @param paymentToken - Selected payment token.\n * @param token - Target token to cover.\n * @param messenger - Controller messenger.\n * @param transactionId - ID of the transaction.\n * @returns The source amount or undefined if calculation failed.\n */\nfunction calculateSourceAmount(\n paymentToken: TransactionPaymentToken,\n token: TransactionPayRequiredToken,\n messenger: TransactionPayControllerMessenger,\n transactionId: string,\n): TransactionPaySourceAmount | undefined {\n const paymentTokenFiatRate = getTokenFiatRate(\n messenger,\n paymentToken.address,\n paymentToken.chainId,\n );\n\n if (!paymentTokenFiatRate) {\n return undefined;\n }\n\n const hasBalance = new BigNumber(token.balanceRaw).gte(token.amountRaw);\n\n if (token.skipIfBalance && hasBalance) {\n log('Skipping token as sufficient balance', {\n tokenAddress: token.address,\n });\n return undefined;\n }\n\n const strategy = getStrategyType(transactionId, messenger);\n\n const isSameTokenSelected =\n token.address.toLowerCase() === paymentToken.address.toLowerCase() &&\n token.chainId === paymentToken.chainId;\n\n const isAlwaysRequired = isQuoteAlwaysRequired(token, strategy);\n\n if (isSameTokenSelected && !isAlwaysRequired) {\n log('Skipping token as same as payment token');\n return undefined;\n }\n\n const sourceAmountHumanValue = new BigNumber(token.amountUsd).div(\n paymentTokenFiatRate.usdRate,\n );\n\n const sourceAmountHuman = sourceAmountHumanValue.toString(10);\n\n const sourceAmountRaw = sourceAmountHumanValue\n .shiftedBy(paymentToken.decimals)\n .toFixed(0);\n\n if (token.amountRaw === '0') {\n log('Skipping token as zero amount', { tokenAddress: token.address });\n return undefined;\n }\n\n return {\n sourceAmountHuman,\n sourceAmountRaw,\n targetTokenAddress: token.address,\n };\n}\n\n/**\n * Determine if a quote is always required for a token and strategy.\n *\n * @param token - Target token.\n * @param strategy - Payment strategy.\n * @returns True if a quote is always required, false otherwise.\n */\nfunction isQuoteAlwaysRequired(\n token: TransactionPayRequiredToken,\n strategy: TransactionPayStrategy,\n) {\n const isHyperliquidDeposit =\n token.chainId === CHAIN_ID_ARBITRUM &&\n token.address.toLowerCase() === ARBITRUM_USDC_ADDRESS.toLowerCase();\n\n return strategy === TransactionPayStrategy.Relay && isHyperliquidDeposit;\n}\n\n/**\n * Get the strategy type for a transaction.\n *\n * @param transactionId - ID of the transaction.\n * @param messenger - Controller messenger.\n * @returns Payment strategy type.\n */\nfunction getStrategyType(\n transactionId: string,\n messenger: TransactionPayControllerMessenger,\n) {\n const transaction = getTransaction(\n transactionId,\n messenger,\n ) as TransactionMeta;\n\n return messenger.call('TransactionPayController:getStrategy', transaction);\n}\n"]}
1
+ {"version":3,"file":"source-amounts.cjs","sourceRoot":"","sources":["../../src/utils/source-amounts.ts"],"names":[],"mappings":"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","sourcesContent":["import { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { getTokenFiatRate } from './token';\nimport { getTransaction } from './transaction';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPaymentToken,\n} from '..';\nimport { TransactionPayStrategy } from '..';\nimport type { TransactionMeta } from '../../../transaction-controller/src';\nimport { ARBITRUM_USDC_ADDRESS, CHAIN_ID_ARBITRUM } from '../constants';\nimport { projectLogger } from '../logger';\nimport type {\n TransactionPaySourceAmount,\n TransactionData,\n TransactionPayRequiredToken,\n} from '../types';\n\nconst log = createModuleLogger(projectLogger, 'source-amounts');\n\n/**\n * Update the source amounts for a transaction.\n *\n * @param transactionId - ID of the transaction to update.\n * @param transactionData - Existing transaction data.\n * @param messenger - Controller messenger.\n */\nexport function updateSourceAmounts(\n transactionId: string,\n transactionData: TransactionData | undefined,\n messenger: TransactionPayControllerMessenger,\n): void {\n if (!transactionData) {\n return;\n }\n\n const { paymentToken, tokens } = transactionData;\n\n if (!tokens.length || !paymentToken) {\n return;\n }\n\n const sourceAmounts = tokens\n .map((singleToken) =>\n calculateSourceAmount(\n paymentToken,\n singleToken,\n messenger,\n transactionId,\n ),\n )\n .filter(Boolean) as TransactionPaySourceAmount[];\n\n log('Updated source amounts', { transactionId, sourceAmounts });\n\n transactionData.sourceAmounts = sourceAmounts;\n}\n\n/**\n * Calculate the required source amount for a payment token to cover a target token.\n *\n * @param paymentToken - Selected payment token.\n * @param token - Target token to cover.\n * @param messenger - Controller messenger.\n * @param transactionId - ID of the transaction.\n * @returns The source amount or undefined if calculation failed.\n */\nfunction calculateSourceAmount(\n paymentToken: TransactionPaymentToken,\n token: TransactionPayRequiredToken,\n messenger: TransactionPayControllerMessenger,\n transactionId: string,\n): TransactionPaySourceAmount | undefined {\n const paymentTokenFiatRate = getTokenFiatRate(\n messenger,\n paymentToken.address,\n paymentToken.chainId,\n );\n\n if (!paymentTokenFiatRate) {\n return undefined;\n }\n\n const hasBalance = new BigNumber(token.balanceRaw).gte(token.amountRaw);\n\n if (token.skipIfBalance && hasBalance) {\n log('Skipping token as sufficient balance', {\n tokenAddress: token.address,\n });\n return undefined;\n }\n\n const strategy = getStrategyType(transactionId, messenger);\n\n const isSameTokenSelected =\n token.address.toLowerCase() === paymentToken.address.toLowerCase() &&\n token.chainId === paymentToken.chainId;\n\n const isAlwaysRequired = isQuoteAlwaysRequired(token, strategy);\n\n if (isSameTokenSelected && !isAlwaysRequired) {\n log('Skipping token as same as payment token');\n return undefined;\n }\n\n const sourceAmountHumanValue = new BigNumber(token.amountUsd).div(\n paymentTokenFiatRate.usdRate,\n );\n\n const sourceAmountHuman = sourceAmountHumanValue.toString(10);\n\n const sourceAmountRaw = sourceAmountHumanValue\n .shiftedBy(paymentToken.decimals)\n .toFixed(0);\n\n if (token.amountRaw === '0') {\n log('Skipping token as zero amount', { tokenAddress: token.address });\n return undefined;\n }\n\n return {\n sourceAmountHuman,\n sourceAmountRaw,\n targetTokenAddress: token.address,\n };\n}\n\n/**\n * Determine if a quote is always required for a token and strategy.\n *\n * @param token - Target token.\n * @param strategy - Payment strategy.\n * @returns True if a quote is always required, false otherwise.\n */\nfunction isQuoteAlwaysRequired(\n token: TransactionPayRequiredToken,\n strategy: TransactionPayStrategy,\n): boolean {\n const isHyperliquidDeposit =\n token.chainId === CHAIN_ID_ARBITRUM &&\n token.address.toLowerCase() === ARBITRUM_USDC_ADDRESS.toLowerCase();\n\n return strategy === TransactionPayStrategy.Relay && isHyperliquidDeposit;\n}\n\n/**\n * Get the strategy type for a transaction.\n *\n * @param transactionId - ID of the transaction.\n * @param messenger - Controller messenger.\n * @returns Payment strategy type.\n */\nfunction getStrategyType(\n transactionId: string,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayStrategy {\n const transaction = getTransaction(\n transactionId,\n messenger,\n ) as TransactionMeta;\n\n return messenger.call('TransactionPayController:getStrategy', transaction);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"source-amounts.d.cts","sourceRoot":"","sources":["../../src/utils/source-amounts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,iCAAiC,EAElC,qBAAW;AAKZ,OAAO,KAAK,EAEV,eAAe,EAEhB,qBAAiB;AAIlB;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,eAAe,GAAG,SAAS,EAC5C,SAAS,EAAE,iCAAiC,QAqB7C"}
1
+ {"version":3,"file":"source-amounts.d.cts","sourceRoot":"","sources":["../../src/utils/source-amounts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,iCAAiC,EAElC,qBAAW;AAKZ,OAAO,KAAK,EAEV,eAAe,EAEhB,qBAAiB;AAIlB;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,eAAe,GAAG,SAAS,EAC5C,SAAS,EAAE,iCAAiC,GAC3C,IAAI,CAyBN"}
@@ -1 +1 @@
1
- {"version":3,"file":"source-amounts.d.mts","sourceRoot":"","sources":["../../src/utils/source-amounts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,iCAAiC,EAElC,qBAAW;AAKZ,OAAO,KAAK,EAEV,eAAe,EAEhB,qBAAiB;AAIlB;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,eAAe,GAAG,SAAS,EAC5C,SAAS,EAAE,iCAAiC,QAqB7C"}
1
+ {"version":3,"file":"source-amounts.d.mts","sourceRoot":"","sources":["../../src/utils/source-amounts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,iCAAiC,EAElC,qBAAW;AAKZ,OAAO,KAAK,EAEV,eAAe,EAEhB,qBAAiB;AAIlB;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,eAAe,GAAG,SAAS,EAC5C,SAAS,EAAE,iCAAiC,GAC3C,IAAI,CAyBN"}
@@ -22,7 +22,7 @@ export function updateSourceAmounts(transactionId, transactionData, messenger) {
22
22
  return;
23
23
  }
24
24
  const sourceAmounts = tokens
25
- .map((t) => calculateSourceAmount(paymentToken, t, messenger, transactionId))
25
+ .map((singleToken) => calculateSourceAmount(paymentToken, singleToken, messenger, transactionId))
26
26
  .filter(Boolean);
27
27
  log('Updated source amounts', { transactionId, sourceAmounts });
28
28
  transactionData.sourceAmounts = sourceAmounts;