@metamask-previews/transaction-pay-controller 31.2.1-preview-e80304db4 → 31.2.1-preview-1d88b8ba5

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 (105) hide show
  1. package/CHANGELOG.md +23 -1
  2. package/dist/TransactionPayController.d.ts.map +1 -1
  3. package/dist/TransactionPayController.js +4 -5
  4. package/dist/TransactionPayController.js.map +1 -1
  5. package/dist/actions/update-payment-token.d.ts.map +1 -1
  6. package/dist/actions/update-payment-token.js +51 -22
  7. package/dist/actions/update-payment-token.js.map +1 -1
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/strategy/across/AcrossStrategy.d.ts.map +1 -1
  12. package/dist/strategy/across/AcrossStrategy.js +6 -1
  13. package/dist/strategy/across/AcrossStrategy.js.map +1 -1
  14. package/dist/strategy/across/across-quotes.js +7 -4
  15. package/dist/strategy/across/across-quotes.js.map +1 -1
  16. package/dist/strategy/across/across-submit.d.ts.map +1 -1
  17. package/dist/strategy/across/across-submit.js +3 -1
  18. package/dist/strategy/across/across-submit.js.map +1 -1
  19. package/dist/strategy/fiat/FiatStrategy.d.ts +1 -0
  20. package/dist/strategy/fiat/FiatStrategy.d.ts.map +1 -1
  21. package/dist/strategy/fiat/FiatStrategy.js +4 -0
  22. package/dist/strategy/fiat/FiatStrategy.js.map +1 -1
  23. package/dist/strategy/fiat/fiat-direct-musd.d.ts.map +1 -1
  24. package/dist/strategy/fiat/fiat-direct-musd.js +4 -2
  25. package/dist/strategy/fiat/fiat-direct-musd.js.map +1 -1
  26. package/dist/strategy/fiat/fiat-quotes.d.ts.map +1 -1
  27. package/dist/strategy/fiat/fiat-quotes.js +4 -2
  28. package/dist/strategy/fiat/fiat-quotes.js.map +1 -1
  29. package/dist/strategy/fiat/fiat-submit.d.ts.map +1 -1
  30. package/dist/strategy/fiat/fiat-submit.js +5 -2
  31. package/dist/strategy/fiat/fiat-submit.js.map +1 -1
  32. package/dist/strategy/fiat/fiat-test-funding.d.ts.map +1 -1
  33. package/dist/strategy/fiat/fiat-test-funding.js +3 -5
  34. package/dist/strategy/fiat/fiat-test-funding.js.map +1 -1
  35. package/dist/strategy/relay/RelayStrategy.d.ts +4 -0
  36. package/dist/strategy/relay/RelayStrategy.d.ts.map +1 -1
  37. package/dist/strategy/relay/RelayStrategy.js +6 -1
  38. package/dist/strategy/relay/RelayStrategy.js.map +1 -1
  39. package/dist/strategy/relay/relay-quotes.d.ts.map +1 -1
  40. package/dist/strategy/relay/relay-quotes.js +10 -6
  41. package/dist/strategy/relay/relay-quotes.js.map +1 -1
  42. package/dist/strategy/relay/relay-submit-execute.d.ts.map +1 -1
  43. package/dist/strategy/relay/relay-submit-execute.js +3 -1
  44. package/dist/strategy/relay/relay-submit-execute.js.map +1 -1
  45. package/dist/strategy/relay/relay-submit.d.ts.map +1 -1
  46. package/dist/strategy/relay/relay-submit.js +8 -6
  47. package/dist/strategy/relay/relay-submit.js.map +1 -1
  48. package/dist/strategy/relay/relay-validation.d.ts.map +1 -1
  49. package/dist/strategy/relay/relay-validation.js +5 -2
  50. package/dist/strategy/relay/relay-validation.js.map +1 -1
  51. package/dist/strategy/server/ServerStrategy.d.ts.map +1 -1
  52. package/dist/strategy/server/ServerStrategy.js +4 -0
  53. package/dist/strategy/server/ServerStrategy.js.map +1 -1
  54. package/dist/strategy/server/server-quotes.d.ts.map +1 -1
  55. package/dist/strategy/server/server-quotes.js +54 -11
  56. package/dist/strategy/server/server-quotes.js.map +1 -1
  57. package/dist/strategy/server/server-submit.d.ts.map +1 -1
  58. package/dist/strategy/server/server-submit.js +9 -6
  59. package/dist/strategy/server/server-submit.js.map +1 -1
  60. package/dist/strategy/server/server-support.d.ts +1 -3
  61. package/dist/strategy/server/server-support.d.ts.map +1 -1
  62. package/dist/strategy/server/server-support.js +0 -5
  63. package/dist/strategy/server/server-support.js.map +1 -1
  64. package/dist/strategy/server/server-validation.d.ts.map +1 -1
  65. package/dist/strategy/server/server-validation.js +3 -1
  66. package/dist/strategy/server/server-validation.js.map +1 -1
  67. package/dist/types.d.ts +60 -25
  68. package/dist/types.d.ts.map +1 -1
  69. package/dist/types.js.map +1 -1
  70. package/dist/utils/account.d.ts +54 -0
  71. package/dist/utils/account.d.ts.map +1 -1
  72. package/dist/utils/account.js +124 -0
  73. package/dist/utils/account.js.map +1 -1
  74. package/dist/utils/gas-payment.d.ts +12 -3
  75. package/dist/utils/gas-payment.d.ts.map +1 -1
  76. package/dist/utils/gas-payment.js +2 -2
  77. package/dist/utils/gas-payment.js.map +1 -1
  78. package/dist/utils/max-gas-station.d.ts.map +1 -1
  79. package/dist/utils/max-gas-station.js +9 -5
  80. package/dist/utils/max-gas-station.js.map +1 -1
  81. package/dist/utils/max-quote.js +3 -2
  82. package/dist/utils/max-quote.js.map +1 -1
  83. package/dist/utils/no-op-quote.d.ts +3 -3
  84. package/dist/utils/no-op-quote.d.ts.map +1 -1
  85. package/dist/utils/no-op-quote.js +4 -3
  86. package/dist/utils/no-op-quote.js.map +1 -1
  87. package/dist/utils/perps.d.ts.map +1 -1
  88. package/dist/utils/perps.js +5 -2
  89. package/dist/utils/perps.js.map +1 -1
  90. package/dist/utils/post-quote.js +4 -3
  91. package/dist/utils/post-quote.js.map +1 -1
  92. package/dist/utils/quotes.d.ts.map +1 -1
  93. package/dist/utils/quotes.js +99 -25
  94. package/dist/utils/quotes.js.map +1 -1
  95. package/dist/utils/source-amounts.d.ts.map +1 -1
  96. package/dist/utils/source-amounts.js +25 -4
  97. package/dist/utils/source-amounts.js.map +1 -1
  98. package/dist/utils/token.d.ts +84 -1
  99. package/dist/utils/token.d.ts.map +1 -1
  100. package/dist/utils/token.js +144 -13
  101. package/dist/utils/token.js.map +1 -1
  102. package/dist/utils/validation.d.ts.map +1 -1
  103. package/dist/utils/validation.js +14 -11
  104. package/dist/utils/validation.js.map +1 -1
  105. package/package.json +2 -1
@@ -2,6 +2,7 @@ import { createModuleLogger } from '@metamask/utils';
2
2
  import { BigNumber } from 'bignumber.js';
3
3
  import { NATIVE_TOKEN_ADDRESS, TransactionPayStrategy, } from '../../constants.js';
4
4
  import { projectLogger } from '../../logger.js';
5
+ import { getCaipAccountId } from '../../utils/account.js';
5
6
  import { getDirectMoneyMusdEnabled } from '../../utils/feature-flags.js';
6
7
  import { buildCaipAssetType, computeRawFromFiatAmount, getTokenFiatRate, getTokenInfo, } from '../../utils/token.js';
7
8
  import { getRelayQuotes } from '../relay/relay-quotes.js';
@@ -149,15 +150,16 @@ function buildRelayRequestFromAmountFiat({ amountFiat, fiatAsset, messenger, req
149
150
  if (!sourceAmountRaw) {
150
151
  return undefined;
151
152
  }
153
+ const sourceAssetId = buildCaipAssetType(fiatAsset.chainId, fiatAsset.address);
152
154
  return {
153
155
  from: walletAddress,
154
156
  // Force EXACT_INPUT mode: source amount is pre-calculated from the fiat
155
157
  // amount, so the relay should treat it as a fixed input rather than
156
158
  // computing it from the target.
157
159
  isPostQuote: true,
160
+ sourceAccountId: getCaipAccountId(sourceAssetId, walletAddress),
161
+ sourceAssetId,
158
162
  sourceBalanceRaw: sourceAmountRaw,
159
- sourceChainId: fiatAsset.chainId,
160
- sourceTokenAddress: fiatAsset.address,
161
163
  sourceTokenAmount: sourceAmountRaw,
162
164
  targetAmountMinimum: requiredToken.amountRaw,
163
165
  targetChainId: requiredToken.chainId,
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-quotes.js","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Quote as RampsQuote } from '@metamask/ramps-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n NATIVE_TOKEN_ADDRESS,\n TransactionPayStrategy,\n} from '../../constants.js';\nimport { projectLogger } from '../../logger.js';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionFiatPayment,\n TransactionPayRequiredToken,\n TransactionPayQuote,\n} from '../../types.js';\nimport { getDirectMoneyMusdEnabled } from '../../utils/feature-flags.js';\nimport {\n buildCaipAssetType,\n computeRawFromFiatAmount,\n getTokenFiatRate,\n getTokenInfo,\n} from '../../utils/token.js';\nimport { getRelayQuotes } from '../relay/relay-quotes.js';\nimport type { RelayQuote } from '../relay/types.js';\nimport type { TransactionPayFiatAsset } from './constants.js';\nimport { getDirectMusdFiatQuote } from './fiat-direct-musd.js';\nimport type { FiatQuote } from './types.js';\nimport {\n deriveFiatAssetForFiatPayment,\n getRampsQuote,\n isMoneyAccountDepositTransaction,\n} from './utils.js';\n\nconst log = createModuleLogger(projectLogger, 'fiat-strategy');\n\ntype FiatQuotePipelineOptions = {\n amountFiat: string;\n fiatAsset: TransactionPayFiatAsset;\n fiatPaymentMethod: string;\n rampsWalletAddress: Hex;\n requiredTokens: TransactionPayRequiredToken[];\n};\n\n/**\n * Fetches MM Pay fiat strategy quotes using a relay-first estimation flow.\n *\n * When the direct-to-mUSD flag is enabled and the transaction is a Money\n * Account deposit, uses direct mUSD params (asset, wallet, recipient).\n * Otherwise, uses the standard ETH flow.\n *\n * @param request - Strategy quotes request.\n * @returns A single combined fiat strategy quote, or an empty array when inputs/quotes are unavailable.\n */\nexport async function getFiatQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<FiatQuote>[]> {\n const { messenger, transaction } = request;\n\n const state = messenger.call('TransactionPayController:getState');\n const transactionData = state.transactionData[transaction.id];\n const amountFiat = transactionData?.fiatPayment?.amountFiat;\n const requiredTokens = transactionData?.tokens ?? [];\n\n if (\n !amountFiat ||\n !request.fiatPaymentMethod ||\n requiredTokens.length !== 1\n ) {\n return [];\n }\n\n const useDirectMusd =\n getDirectMoneyMusdEnabled(messenger) &&\n isMoneyAccountDepositTransaction(transaction);\n\n if (useDirectMusd) {\n const requiredToken = requiredTokens[0];\n\n const directQuote = await getDirectMusdFiatQuote({\n amountFiat,\n fiatPaymentMethod: request.fiatPaymentMethod,\n messenger,\n moneyAccountAddress: transaction.txParams.from as Hex,\n requiredToken,\n transactionId: transaction.id,\n });\n\n return directQuote ? [directQuote] : [];\n }\n\n return executeFiatQuotePipeline(request, {\n amountFiat,\n fiatAsset: deriveFiatAssetForFiatPayment(transaction, messenger),\n fiatPaymentMethod: request.fiatPaymentMethod,\n rampsWalletAddress: request.from,\n requiredTokens,\n });\n}\n\nasync function executeFiatQuotePipeline(\n request: PayStrategyGetQuotesRequest,\n options: FiatQuotePipelineOptions,\n): Promise<TransactionPayQuote<FiatQuote>[]> {\n const {\n accountSupports7702,\n from: walletAddress,\n messenger,\n transaction,\n } = request;\n const {\n amountFiat,\n fiatAsset,\n fiatPaymentMethod,\n rampsWalletAddress,\n requiredTokens,\n } = options;\n const transactionId = transaction.id;\n\n try {\n const requiredToken = requiredTokens[0];\n\n const relayRequest = buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n });\n\n if (!relayRequest) {\n throw new Error('Failed to build relay request from fiat amount');\n }\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702,\n from: walletAddress,\n messenger,\n requests: [relayRequest],\n transaction,\n });\n\n const relayQuote = relayQuotes[0];\n if (!relayQuote) {\n throw new Error('No relay quote available for fiat estimation');\n }\n\n const isSourceNative =\n fiatAsset.address.toLowerCase() === NATIVE_TOKEN_ADDRESS.toLowerCase();\n const gasDeductedFromSource =\n isSourceNative || relayQuote.fees.isSourceGasFeeToken === true;\n\n const relayTotalFeeUsd = gasDeductedFromSource\n ? getRelayTotalFeeUsd(relayQuote)\n : getNonGasRelayFeeUsd(relayQuote);\n const adjustedAmountFiat = new BigNumber(amountFiat).plus(relayTotalFeeUsd);\n\n if (\n !adjustedAmountFiat.isFinite() ||\n !adjustedAmountFiat.gt(0) ||\n !relayTotalFeeUsd.isFinite() ||\n !relayTotalFeeUsd.gte(0)\n ) {\n throw new Error('Invalid fiat amount after relay fee adjustment');\n }\n\n const adjustedAmount = adjustedAmountFiat.toNumber();\n\n if (!Number.isFinite(adjustedAmount) || adjustedAmount <= 0) {\n throw new Error('Invalid fiat amount after relay fee adjustment');\n }\n\n log('Fiat quote flow', {\n adjustedAmountFiat: adjustedAmountFiat.toString(10),\n amountFiat,\n rampsWalletAddress,\n relayTotalFeeUsd: relayTotalFeeUsd.toString(10),\n sourceAmountRaw: relayRequest.sourceTokenAmount,\n transactionId,\n });\n\n const fiatQuote = await getRampsQuote({\n adjustedAmount,\n fiatAsset,\n fiatPaymentMethod,\n messenger,\n walletAddress: rampsWalletAddress,\n });\n\n messenger.call('TransactionPayController:updateFiatPayment', {\n callback: (fiatPayment: TransactionFiatPayment) => {\n fiatPayment.rampsQuote = fiatQuote;\n fiatPayment.caipAssetId = buildCaipAssetType(\n fiatAsset.chainId,\n fiatAsset.address,\n );\n },\n transactionId,\n });\n\n return [\n combineQuotes({\n adjustedAmountFiat: adjustedAmountFiat.toString(10),\n amountFiat,\n fiatQuote,\n relayQuote,\n }),\n ];\n } catch (error) {\n log('Failed to fetch fiat quotes', { error, transactionId });\n\n messenger.call('TransactionPayController:updateFiatPayment', {\n callback: (fiatPayment) => {\n fiatPayment.rampsQuote = undefined;\n },\n transactionId,\n });\n }\n\n return [];\n}\n\nfunction buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n}: {\n amountFiat: string;\n fiatAsset: {\n address: Hex;\n chainId: Hex;\n };\n messenger: PayStrategyGetQuotesRequest['messenger'];\n requiredToken: TransactionPayRequiredToken;\n walletAddress: Hex;\n}): QuoteRequest | undefined {\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n fiatAsset.address,\n fiatAsset.chainId,\n );\n\n if (!sourceFiatRate) {\n return undefined;\n }\n\n const tokenInfo = getTokenInfo(\n messenger,\n fiatAsset.address,\n fiatAsset.chainId,\n );\n\n if (!tokenInfo) {\n return undefined;\n }\n\n const sourceAmountRaw = computeRawFromFiatAmount(\n amountFiat,\n tokenInfo.decimals,\n sourceFiatRate.usdRate,\n );\n\n if (!sourceAmountRaw) {\n return undefined;\n }\n\n return {\n from: walletAddress,\n // Force EXACT_INPUT mode: source amount is pre-calculated from the fiat\n // amount, so the relay should treat it as a fixed input rather than\n // computing it from the target.\n isPostQuote: true,\n sourceBalanceRaw: sourceAmountRaw,\n sourceChainId: fiatAsset.chainId,\n sourceTokenAddress: fiatAsset.address,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: requiredToken.amountRaw,\n targetChainId: requiredToken.chainId,\n targetTokenAddress: requiredToken.address,\n };\n}\n\n/**\n * Combines fiat and relay legs into a single MM Pay fiat strategy quote.\n *\n * @param params - Combined quote inputs.\n * @param params.adjustedAmountFiat - Fiat amount sent to ramps after adding relay fee estimate.\n * @param params.amountFiat - User-entered fiat amount.\n * @param params.fiatQuote - Selected ramps quote, with fees already reconciled\n * to the resolved provider by `RampsController:getQuoteWithFees`.\n * @param params.relayQuote - Estimated relay quote.\n * @returns A single fiat strategy quote with split fee buckets.\n * @remarks\n * Fee mapping contract for MM Pay Fiat strategy:\n * - `fees.provider`: Total provider fee (relay provider/swap fee + ramps provider/network fee).\n * Consumed by UI transaction fee row and tooltip provider fee.\n * - `fees.providerFiat`: Fiat on-ramp provider fees only (`providerFee + networkFee` from ramps quote).\n * Optional breakdown; client can derive relay portion via `provider - providerFiat`.\n * - `fees.sourceNetwork` / `fees.targetNetwork`: Relay settlement network fees.\n * Consumed by UI transaction fee row and tooltip network fee.\n * - `fees.metaMask`: MM Pay fee (currently 100 bps over `amountFiat + adjustedAmountFiat`).\n * Consumed by UI transaction fee row and tooltip MetaMask fee.\n * - `totals.total` should represent Amount + Transaction Fee using the totals pipeline.\n */\nfunction combineQuotes({\n adjustedAmountFiat,\n amountFiat,\n fiatQuote,\n relayQuote,\n}: {\n adjustedAmountFiat: string;\n amountFiat: string;\n fiatQuote: RampsQuote;\n relayQuote: TransactionPayQuote<RelayQuote>;\n}): TransactionPayQuote<FiatQuote> {\n const rampsProviderFee = getRampsProviderFee(fiatQuote);\n const totalProviderFee = new BigNumber(relayQuote.fees.provider.usd)\n .plus(rampsProviderFee)\n .toString(10);\n const rampsProviderFeeStr = rampsProviderFee.toString(10);\n const metaMaskFee = getMetaMaskFee({\n adjustedAmountFiat,\n amountFiat,\n }).toString(10);\n\n return {\n ...relayQuote,\n fees: {\n ...relayQuote.fees,\n metaMask: {\n fiat: metaMaskFee,\n usd: metaMaskFee,\n },\n provider: {\n fiat: totalProviderFee,\n usd: totalProviderFee,\n },\n providerFiat: {\n fiat: rampsProviderFeeStr,\n usd: rampsProviderFeeStr,\n },\n },\n original: {\n rampsQuote: fiatQuote,\n relayQuote: relayQuote.original,\n },\n strategy: TransactionPayStrategy.Fiat,\n };\n}\n\n/**\n * Ramps providers handle network gas fees themselves but report them separately\n * as `networkFee` alongside their `providerFee`. We combine both into a single\n * ramps provider fee for the `providerFiat` breakdown.\n *\n * @param fiatQuote - The ramps quote containing provider and network fees.\n * @returns Combined ramps provider fee as a BigNumber.\n */\nfunction getRampsProviderFee(fiatQuote: RampsQuote): BigNumber {\n return new BigNumber(fiatQuote.quote.providerFee ?? 0).plus(\n fiatQuote.quote.networkFee ?? 0,\n );\n}\n\nfunction getRelayTotalFeeUsd(\n relayQuote: TransactionPayQuote<RelayQuote>,\n): BigNumber {\n return new BigNumber(relayQuote.fees.provider.usd)\n .plus(relayQuote.fees.sourceNetwork.estimate.usd)\n .plus(relayQuote.fees.targetNetwork.usd)\n .plus(relayQuote.fees.metaMask.usd);\n}\n\nfunction getNonGasRelayFeeUsd(\n relayQuote: TransactionPayQuote<RelayQuote>,\n): BigNumber {\n return new BigNumber(relayQuote.fees.provider.usd)\n .plus(relayQuote.fees.targetNetwork.usd)\n .plus(relayQuote.fees.metaMask.usd);\n}\n\nfunction getMetaMaskFee({\n adjustedAmountFiat,\n amountFiat,\n}: {\n adjustedAmountFiat: BigNumber.Value;\n amountFiat: BigNumber.Value;\n}): BigNumber {\n return new BigNumber(amountFiat).plus(adjustedAmountFiat).dividedBy(100);\n}\n"]}
1
+ {"version":3,"file":"fiat-quotes.js","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Quote as RampsQuote } from '@metamask/ramps-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n NATIVE_TOKEN_ADDRESS,\n TransactionPayStrategy,\n} from '../../constants.js';\nimport { projectLogger } from '../../logger.js';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionFiatPayment,\n TransactionPayRequiredToken,\n TransactionPayQuote,\n} from '../../types.js';\nimport { getCaipAccountId } from '../../utils/account.js';\nimport { getDirectMoneyMusdEnabled } from '../../utils/feature-flags.js';\nimport {\n buildCaipAssetType,\n computeRawFromFiatAmount,\n getTokenFiatRate,\n getTokenInfo,\n} from '../../utils/token.js';\nimport { getRelayQuotes } from '../relay/relay-quotes.js';\nimport type { RelayQuote } from '../relay/types.js';\nimport type { TransactionPayFiatAsset } from './constants.js';\nimport { getDirectMusdFiatQuote } from './fiat-direct-musd.js';\nimport type { FiatQuote } from './types.js';\nimport {\n deriveFiatAssetForFiatPayment,\n getRampsQuote,\n isMoneyAccountDepositTransaction,\n} from './utils.js';\n\nconst log = createModuleLogger(projectLogger, 'fiat-strategy');\n\ntype FiatQuotePipelineOptions = {\n amountFiat: string;\n fiatAsset: TransactionPayFiatAsset;\n fiatPaymentMethod: string;\n rampsWalletAddress: Hex;\n requiredTokens: TransactionPayRequiredToken[];\n};\n\n/**\n * Fetches MM Pay fiat strategy quotes using a relay-first estimation flow.\n *\n * When the direct-to-mUSD flag is enabled and the transaction is a Money\n * Account deposit, uses direct mUSD params (asset, wallet, recipient).\n * Otherwise, uses the standard ETH flow.\n *\n * @param request - Strategy quotes request.\n * @returns A single combined fiat strategy quote, or an empty array when inputs/quotes are unavailable.\n */\nexport async function getFiatQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<FiatQuote>[]> {\n const { messenger, transaction } = request;\n\n const state = messenger.call('TransactionPayController:getState');\n const transactionData = state.transactionData[transaction.id];\n const amountFiat = transactionData?.fiatPayment?.amountFiat;\n const requiredTokens = transactionData?.tokens ?? [];\n\n if (\n !amountFiat ||\n !request.fiatPaymentMethod ||\n requiredTokens.length !== 1\n ) {\n return [];\n }\n\n const useDirectMusd =\n getDirectMoneyMusdEnabled(messenger) &&\n isMoneyAccountDepositTransaction(transaction);\n\n if (useDirectMusd) {\n const requiredToken = requiredTokens[0];\n\n const directQuote = await getDirectMusdFiatQuote({\n amountFiat,\n fiatPaymentMethod: request.fiatPaymentMethod,\n messenger,\n moneyAccountAddress: transaction.txParams.from as Hex,\n requiredToken,\n transactionId: transaction.id,\n });\n\n return directQuote ? [directQuote] : [];\n }\n\n return executeFiatQuotePipeline(request, {\n amountFiat,\n fiatAsset: deriveFiatAssetForFiatPayment(transaction, messenger),\n fiatPaymentMethod: request.fiatPaymentMethod,\n rampsWalletAddress: request.from,\n requiredTokens,\n });\n}\n\nasync function executeFiatQuotePipeline(\n request: PayStrategyGetQuotesRequest,\n options: FiatQuotePipelineOptions,\n): Promise<TransactionPayQuote<FiatQuote>[]> {\n const {\n accountSupports7702,\n from: walletAddress,\n messenger,\n transaction,\n } = request;\n const {\n amountFiat,\n fiatAsset,\n fiatPaymentMethod,\n rampsWalletAddress,\n requiredTokens,\n } = options;\n const transactionId = transaction.id;\n\n try {\n const requiredToken = requiredTokens[0];\n\n const relayRequest = buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n });\n\n if (!relayRequest) {\n throw new Error('Failed to build relay request from fiat amount');\n }\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702,\n from: walletAddress,\n messenger,\n requests: [relayRequest],\n transaction,\n });\n\n const relayQuote = relayQuotes[0];\n if (!relayQuote) {\n throw new Error('No relay quote available for fiat estimation');\n }\n\n const isSourceNative =\n fiatAsset.address.toLowerCase() === NATIVE_TOKEN_ADDRESS.toLowerCase();\n const gasDeductedFromSource =\n isSourceNative || relayQuote.fees.isSourceGasFeeToken === true;\n\n const relayTotalFeeUsd = gasDeductedFromSource\n ? getRelayTotalFeeUsd(relayQuote)\n : getNonGasRelayFeeUsd(relayQuote);\n const adjustedAmountFiat = new BigNumber(amountFiat).plus(relayTotalFeeUsd);\n\n if (\n !adjustedAmountFiat.isFinite() ||\n !adjustedAmountFiat.gt(0) ||\n !relayTotalFeeUsd.isFinite() ||\n !relayTotalFeeUsd.gte(0)\n ) {\n throw new Error('Invalid fiat amount after relay fee adjustment');\n }\n\n const adjustedAmount = adjustedAmountFiat.toNumber();\n\n if (!Number.isFinite(adjustedAmount) || adjustedAmount <= 0) {\n throw new Error('Invalid fiat amount after relay fee adjustment');\n }\n\n log('Fiat quote flow', {\n adjustedAmountFiat: adjustedAmountFiat.toString(10),\n amountFiat,\n rampsWalletAddress,\n relayTotalFeeUsd: relayTotalFeeUsd.toString(10),\n sourceAmountRaw: relayRequest.sourceTokenAmount,\n transactionId,\n });\n\n const fiatQuote = await getRampsQuote({\n adjustedAmount,\n fiatAsset,\n fiatPaymentMethod,\n messenger,\n walletAddress: rampsWalletAddress,\n });\n\n messenger.call('TransactionPayController:updateFiatPayment', {\n callback: (fiatPayment: TransactionFiatPayment) => {\n fiatPayment.rampsQuote = fiatQuote;\n fiatPayment.caipAssetId = buildCaipAssetType(\n fiatAsset.chainId,\n fiatAsset.address,\n );\n },\n transactionId,\n });\n\n return [\n combineQuotes({\n adjustedAmountFiat: adjustedAmountFiat.toString(10),\n amountFiat,\n fiatQuote,\n relayQuote,\n }),\n ];\n } catch (error) {\n log('Failed to fetch fiat quotes', { error, transactionId });\n\n messenger.call('TransactionPayController:updateFiatPayment', {\n callback: (fiatPayment) => {\n fiatPayment.rampsQuote = undefined;\n },\n transactionId,\n });\n }\n\n return [];\n}\n\nfunction buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n}: {\n amountFiat: string;\n fiatAsset: {\n address: Hex;\n chainId: Hex;\n };\n messenger: PayStrategyGetQuotesRequest['messenger'];\n requiredToken: TransactionPayRequiredToken;\n walletAddress: Hex;\n}): QuoteRequest | undefined {\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n fiatAsset.address,\n fiatAsset.chainId,\n );\n\n if (!sourceFiatRate) {\n return undefined;\n }\n\n const tokenInfo = getTokenInfo(\n messenger,\n fiatAsset.address,\n fiatAsset.chainId,\n );\n\n if (!tokenInfo) {\n return undefined;\n }\n\n const sourceAmountRaw = computeRawFromFiatAmount(\n amountFiat,\n tokenInfo.decimals,\n sourceFiatRate.usdRate,\n );\n\n if (!sourceAmountRaw) {\n return undefined;\n }\n\n const sourceAssetId = buildCaipAssetType(\n fiatAsset.chainId,\n fiatAsset.address,\n );\n\n return {\n from: walletAddress,\n // Force EXACT_INPUT mode: source amount is pre-calculated from the fiat\n // amount, so the relay should treat it as a fixed input rather than\n // computing it from the target.\n isPostQuote: true,\n sourceAccountId: getCaipAccountId(sourceAssetId, walletAddress),\n sourceAssetId,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: requiredToken.amountRaw,\n targetChainId: requiredToken.chainId,\n targetTokenAddress: requiredToken.address,\n };\n}\n\n/**\n * Combines fiat and relay legs into a single MM Pay fiat strategy quote.\n *\n * @param params - Combined quote inputs.\n * @param params.adjustedAmountFiat - Fiat amount sent to ramps after adding relay fee estimate.\n * @param params.amountFiat - User-entered fiat amount.\n * @param params.fiatQuote - Selected ramps quote, with fees already reconciled\n * to the resolved provider by `RampsController:getQuoteWithFees`.\n * @param params.relayQuote - Estimated relay quote.\n * @returns A single fiat strategy quote with split fee buckets.\n * @remarks\n * Fee mapping contract for MM Pay Fiat strategy:\n * - `fees.provider`: Total provider fee (relay provider/swap fee + ramps provider/network fee).\n * Consumed by UI transaction fee row and tooltip provider fee.\n * - `fees.providerFiat`: Fiat on-ramp provider fees only (`providerFee + networkFee` from ramps quote).\n * Optional breakdown; client can derive relay portion via `provider - providerFiat`.\n * - `fees.sourceNetwork` / `fees.targetNetwork`: Relay settlement network fees.\n * Consumed by UI transaction fee row and tooltip network fee.\n * - `fees.metaMask`: MM Pay fee (currently 100 bps over `amountFiat + adjustedAmountFiat`).\n * Consumed by UI transaction fee row and tooltip MetaMask fee.\n * - `totals.total` should represent Amount + Transaction Fee using the totals pipeline.\n */\nfunction combineQuotes({\n adjustedAmountFiat,\n amountFiat,\n fiatQuote,\n relayQuote,\n}: {\n adjustedAmountFiat: string;\n amountFiat: string;\n fiatQuote: RampsQuote;\n relayQuote: TransactionPayQuote<RelayQuote>;\n}): TransactionPayQuote<FiatQuote> {\n const rampsProviderFee = getRampsProviderFee(fiatQuote);\n const totalProviderFee = new BigNumber(relayQuote.fees.provider.usd)\n .plus(rampsProviderFee)\n .toString(10);\n const rampsProviderFeeStr = rampsProviderFee.toString(10);\n const metaMaskFee = getMetaMaskFee({\n adjustedAmountFiat,\n amountFiat,\n }).toString(10);\n\n return {\n ...relayQuote,\n fees: {\n ...relayQuote.fees,\n metaMask: {\n fiat: metaMaskFee,\n usd: metaMaskFee,\n },\n provider: {\n fiat: totalProviderFee,\n usd: totalProviderFee,\n },\n providerFiat: {\n fiat: rampsProviderFeeStr,\n usd: rampsProviderFeeStr,\n },\n },\n original: {\n rampsQuote: fiatQuote,\n relayQuote: relayQuote.original,\n },\n strategy: TransactionPayStrategy.Fiat,\n };\n}\n\n/**\n * Ramps providers handle network gas fees themselves but report them separately\n * as `networkFee` alongside their `providerFee`. We combine both into a single\n * ramps provider fee for the `providerFiat` breakdown.\n *\n * @param fiatQuote - The ramps quote containing provider and network fees.\n * @returns Combined ramps provider fee as a BigNumber.\n */\nfunction getRampsProviderFee(fiatQuote: RampsQuote): BigNumber {\n return new BigNumber(fiatQuote.quote.providerFee ?? 0).plus(\n fiatQuote.quote.networkFee ?? 0,\n );\n}\n\nfunction getRelayTotalFeeUsd(\n relayQuote: TransactionPayQuote<RelayQuote>,\n): BigNumber {\n return new BigNumber(relayQuote.fees.provider.usd)\n .plus(relayQuote.fees.sourceNetwork.estimate.usd)\n .plus(relayQuote.fees.targetNetwork.usd)\n .plus(relayQuote.fees.metaMask.usd);\n}\n\nfunction getNonGasRelayFeeUsd(\n relayQuote: TransactionPayQuote<RelayQuote>,\n): BigNumber {\n return new BigNumber(relayQuote.fees.provider.usd)\n .plus(relayQuote.fees.targetNetwork.usd)\n .plus(relayQuote.fees.metaMask.usd);\n}\n\nfunction getMetaMaskFee({\n adjustedAmountFiat,\n amountFiat,\n}: {\n adjustedAmountFiat: BigNumber.Value;\n amountFiat: BigNumber.Value;\n}): BigNumber {\n return new BigNumber(amountFiat).plus(adjustedAmountFiat).dividedBy(100);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-submit.d.ts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,WAAW,EACX,yBAAyB,EAG1B,MAAM,gBAAgB,CAAC;AAcxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAiB5C;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,GAC5C,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAwF/C"}
1
+ {"version":3,"file":"fiat-submit.d.ts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,WAAW,EACX,yBAAyB,EAG1B,MAAM,gBAAgB,CAAC;AAexB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAiB5C;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,GAC5C,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAyF/C"}
@@ -1,6 +1,7 @@
1
1
  import { RampsOrderStatus } from '@metamask/ramps-controller';
2
2
  import { createModuleLogger } from '@metamask/utils';
3
3
  import { projectLogger } from '../../logger.js';
4
+ import { getEvmAccountOverride } from '../../utils/account.js';
4
5
  import { prefixError } from '../../utils/error-prefix.js';
5
6
  import { getFiatOrderPollIntervalMs, getFiatOrderPollTimeoutMs, } from '../../utils/feature-flags.js';
6
7
  import { updateTransaction } from '../../utils/transaction.js';
@@ -33,6 +34,7 @@ export async function submitFiatQuotes(request) {
33
34
  const state = messenger.call('TransactionPayController:getState');
34
35
  const transactionData = state.transactionData[transactionId];
35
36
  const walletAddress = getWalletAddress({
37
+ messenger,
36
38
  quotes: request.quotes,
37
39
  transaction,
38
40
  accountOverride: transactionData?.accountOverride,
@@ -210,10 +212,11 @@ async function submitRelayAfterFiatCompletion({ order, request, }) {
210
212
  transaction,
211
213
  });
212
214
  }
213
- function getWalletAddress({ quotes, transaction, accountOverride, }) {
215
+ function getWalletAddress({ messenger, quotes, transaction, accountOverride, }) {
214
216
  const address = isDirectMusdMoneyAccountQuote(quotes[0])
215
217
  ? transaction.txParams.from
216
- : (accountOverride ?? transaction.txParams.from);
218
+ : (getEvmAccountOverride(messenger, accountOverride) ??
219
+ transaction.txParams.from);
217
220
  if (!address) {
218
221
  throw new Error('Missing wallet address');
219
222
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-submit.js","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RampsOrder } from '@metamask/ramps-controller';\nimport { RampsOrderStatus } from '@metamask/ramps-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { projectLogger } from '../../logger.js';\nimport type {\n PayStrategy,\n PayStrategyExecuteRequest,\n TransactionPayFiatOptions,\n TransactionPayControllerMessenger,\n} from '../../types.js';\nimport { prefixError } from '../../utils/error-prefix.js';\nimport {\n getFiatOrderPollIntervalMs,\n getFiatOrderPollTimeoutMs,\n} from '../../utils/feature-flags.js';\nimport { updateTransaction } from '../../utils/transaction.js';\nimport {\n isDirectMusdMoneyAccountQuote,\n submitDirectMusdAfterFiatCompletion,\n} from './fiat-direct-musd.js';\nimport { submitSimpleRelay } from './fiat-submit-simple.js';\nimport { submitWithTransactionData } from './fiat-submit-with-transaction-data.js';\nimport { fundFiatOrderFromTestSource } from './fiat-test-funding.js';\nimport type { FiatQuote } from './types.js';\nimport {\n deriveFiatAssetForFiatPayment,\n extractProviderCode,\n resolveSourceAmountRaw,\n validateOrderAsset,\n} from './utils.js';\n\nconst log = createModuleLogger(projectLogger, 'fiat-submit');\nconst POST_RAMP_ERROR_PREFIX = 'Post-Ramp: ';\n\nconst TERMINAL_FAILURE_STATUSES: RampsOrderStatus[] = [\n RampsOrderStatus.Cancelled,\n RampsOrderStatus.Failed,\n RampsOrderStatus.IdExpired,\n];\n\n/**\n * Submits fiat strategy quotes by polling the on-ramp order until completion,\n * then re-quoting and submitting the relay leg with the settled crypto amount.\n *\n * @param request - Strategy execute request containing fiat quotes, messenger, and transaction metadata.\n * @param request.messenger - Controller messenger for cross-controller calls.\n * @param request.quotes - Fiat quotes to execute (exactly one expected).\n * @param request.transaction - Original transaction metadata.\n * @param request.isSmartTransaction - Callback to check smart transaction eligibility.\n * @returns An object containing the relay transaction hash if available.\n */\nexport async function submitFiatQuotes(\n request: PayStrategyExecuteRequest<FiatQuote>,\n): ReturnType<PayStrategy<FiatQuote>['execute']> {\n const { messenger, transaction } = request;\n const transactionId = transaction.id;\n const state = messenger.call('TransactionPayController:getState');\n const transactionData = state.transactionData[transactionId];\n\n const walletAddress = getWalletAddress({\n quotes: request.quotes,\n transaction,\n accountOverride: transactionData?.accountOverride,\n });\n\n const fiatPayment = transactionData?.fiatPayment;\n const orderId = fiatPayment?.orderId;\n\n if (!orderId) {\n throw new Error('Missing order ID');\n }\n\n const providerCode = extractProviderCode(fiatPayment?.rampsQuote?.provider);\n\n if (!providerCode) {\n throw new Error('Missing provider code');\n }\n\n updateTransaction(\n {\n transactionId,\n messenger,\n note: 'Persist fiat order metadata',\n },\n (tx) => {\n tx.metamaskPay ??= {};\n tx.metamaskPay.fiat = { orderId, provider: providerCode };\n },\n );\n\n log('Starting fiat order polling', {\n orderId,\n providerCode,\n transactionId,\n });\n\n const fiatQuote = request.quotes[0];\n\n if (!fiatQuote) {\n throw new Error('Missing quote');\n }\n\n const fiatOptions = getFiatOptions(messenger);\n\n const order = fiatOptions?.testFundingSource\n ? await fundFiatOrderFromTestSource({\n fiat: fiatOptions,\n messenger,\n quote: fiatQuote,\n transaction,\n })\n : await waitForOrderCompletion({\n messenger,\n orderCode: orderId,\n providerCode,\n transactionId,\n walletAddress,\n });\n\n log('Fiat order completed', {\n cryptoAmount: order.cryptoAmount,\n orderId,\n transactionId,\n });\n\n try {\n await waitForKeyringUnlock(messenger, transactionId);\n\n const result = await submitRelayAfterFiatCompletion({\n order,\n request,\n });\n\n if (result.transactionHash === undefined) {\n throw new Error('Missing transaction hash');\n }\n\n return result;\n } catch (error) {\n throw prefixError(error, POST_RAMP_ERROR_PREFIX);\n }\n}\n\nfunction getFiatOptions(\n messenger: TransactionPayControllerMessenger,\n): TransactionPayFiatOptions | undefined {\n try {\n return messenger.call('TransactionPayController:getFiatOptions');\n } catch (error) {\n log('Failed to retrieve fiat options', error);\n return undefined;\n }\n}\n\n/**\n * Polls the on-ramp order until it reaches a terminal status.\n *\n * @param options - The polling options.\n * @param options.messenger - Controller messenger for calling `RampsController:getOrder`.\n * @param options.orderCode - The order identifier within the provider.\n * @param options.providerCode - The on-ramp provider code (e.g. \"transak\").\n * @param options.transactionId - Transaction ID for logging.\n * @param options.walletAddress - Wallet address associated with the order.\n * @returns The completed order data.\n */\nasync function waitForOrderCompletion({\n messenger,\n orderCode,\n providerCode,\n transactionId,\n walletAddress,\n}: {\n messenger: TransactionPayControllerMessenger;\n orderCode: string;\n providerCode: string;\n transactionId: string;\n walletAddress: string;\n}): Promise<RampsOrder> {\n const pollIntervalMs = getFiatOrderPollIntervalMs(messenger);\n const pollTimeoutMs = getFiatOrderPollTimeoutMs(messenger);\n const startTime = Date.now();\n let lastStatus: string | undefined;\n\n while (true) {\n let order: RampsOrder | undefined;\n\n try {\n order = await messenger.call(\n 'RampsController:getOrder',\n providerCode,\n orderCode,\n walletAddress,\n );\n } catch (error) {\n log('Order polling network error', error);\n }\n\n if (order) {\n lastStatus = order.status;\n\n log('Polled fiat order', {\n orderStatus: order.status,\n providerCode,\n transactionId,\n });\n\n if (order.status === RampsOrderStatus.Completed) {\n return order;\n }\n\n if (TERMINAL_FAILURE_STATUSES.includes(order.status)) {\n throw new Error(`Fiat order ${order.status.toLowerCase()}`);\n }\n }\n\n if (Date.now() - startTime >= pollTimeoutMs) {\n throw new Error(\n `Fiat order polling timed out (last status: ${lastStatus})`,\n );\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n }\n}\n\n/**\n * Re-quotes and submits the relay leg using the settled amount from a completed fiat order.\n *\n * @param options - The submission options.\n * @param options.order - The completed on-ramp order containing the settled crypto amount.\n * @param options.request - The original fiat strategy execute request.\n * @returns An object containing the relay transaction hash if available.\n */\nasync function submitRelayAfterFiatCompletion({\n order,\n request,\n}: {\n order: RampsOrder;\n request: PayStrategyExecuteRequest<FiatQuote>;\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger, quotes, transaction } = request;\n const transactionId = transaction.id;\n\n if (quotes.length > 1) {\n throw new Error('Multiple fiat quotes are not supported for submission');\n }\n\n const fiatQuote = quotes[0];\n const isDirectMusd = isDirectMusdMoneyAccountQuote(fiatQuote);\n\n if (isDirectMusd) {\n return await submitDirectMusdAfterFiatCompletion({\n order,\n request,\n });\n }\n\n const fiatAsset = deriveFiatAssetForFiatPayment(transaction, messenger);\n\n validateOrderAsset({\n expectedAsset: fiatAsset,\n orderCrypto: order.cryptoCurrency,\n transactionId,\n });\n\n const baseRequest = fiatQuote.request;\n\n const sourceAmountRaw = await resolveSourceAmountRaw({\n messenger,\n order,\n fiatAsset,\n walletAddress: baseRequest.from,\n });\n\n if (!fiatQuote.original.relayQuote) {\n throw new Error('Missing Relay quote');\n }\n\n const hasNestedCalldata = (transaction.nestedTransactions?.length ?? 0) >= 2;\n\n // Transactions with nested calldata (e.g. moneyAccountDeposit with\n // approve + deposit) need a three-phase flow: discovery quote to learn\n // the target amount, calldata re-encoding, then a delegation quote.\n // Simple deposits (Perps, Predict) skip straight to a single EXACT_INPUT\n // relay quote — cheaper fees, no leftover dust, one fewer request.\n if (hasNestedCalldata) {\n return await submitWithTransactionData({\n baseRequest,\n request,\n sourceAmountRaw,\n transaction,\n });\n }\n\n return await submitSimpleRelay({\n baseRequest,\n request,\n sourceAmountRaw,\n transaction,\n });\n}\n\nfunction getWalletAddress({\n quotes,\n transaction,\n accountOverride,\n}: {\n quotes: PayStrategyExecuteRequest<FiatQuote>['quotes'];\n transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];\n accountOverride: Hex | undefined;\n}): Hex {\n const address = isDirectMusdMoneyAccountQuote(quotes[0])\n ? transaction.txParams.from\n : (accountOverride ?? transaction.txParams.from);\n\n if (!address) {\n throw new Error('Missing wallet address');\n }\n\n return address as Hex;\n}\n\nfunction waitForKeyringUnlock(\n messenger: TransactionPayControllerMessenger,\n transactionId: string,\n): Promise<void> {\n const { isUnlocked } = messenger.call('KeyringController:getState');\n\n if (isUnlocked) {\n return Promise.resolve();\n }\n\n log(\n 'KeyringController is locked; waiting for unlock before fiat submit second leg',\n {\n transactionId,\n },\n );\n\n return new Promise((resolve) => {\n const handler = (): void => {\n messenger.unsubscribe('KeyringController:unlock', handler);\n\n log('KeyringController unlocked; resuming fiat submit second leg', {\n transactionId,\n });\n\n resolve();\n };\n\n messenger.subscribe('KeyringController:unlock', handler);\n });\n}\n"]}
1
+ {"version":3,"file":"fiat-submit.js","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RampsOrder } from '@metamask/ramps-controller';\nimport { RampsOrderStatus } from '@metamask/ramps-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { projectLogger } from '../../logger.js';\nimport type {\n PayStrategy,\n PayStrategyExecuteRequest,\n TransactionPayFiatOptions,\n TransactionPayControllerMessenger,\n} from '../../types.js';\nimport { getEvmAccountOverride } from '../../utils/account.js';\nimport { prefixError } from '../../utils/error-prefix.js';\nimport {\n getFiatOrderPollIntervalMs,\n getFiatOrderPollTimeoutMs,\n} from '../../utils/feature-flags.js';\nimport { updateTransaction } from '../../utils/transaction.js';\nimport {\n isDirectMusdMoneyAccountQuote,\n submitDirectMusdAfterFiatCompletion,\n} from './fiat-direct-musd.js';\nimport { submitSimpleRelay } from './fiat-submit-simple.js';\nimport { submitWithTransactionData } from './fiat-submit-with-transaction-data.js';\nimport { fundFiatOrderFromTestSource } from './fiat-test-funding.js';\nimport type { FiatQuote } from './types.js';\nimport {\n deriveFiatAssetForFiatPayment,\n extractProviderCode,\n resolveSourceAmountRaw,\n validateOrderAsset,\n} from './utils.js';\n\nconst log = createModuleLogger(projectLogger, 'fiat-submit');\nconst POST_RAMP_ERROR_PREFIX = 'Post-Ramp: ';\n\nconst TERMINAL_FAILURE_STATUSES: RampsOrderStatus[] = [\n RampsOrderStatus.Cancelled,\n RampsOrderStatus.Failed,\n RampsOrderStatus.IdExpired,\n];\n\n/**\n * Submits fiat strategy quotes by polling the on-ramp order until completion,\n * then re-quoting and submitting the relay leg with the settled crypto amount.\n *\n * @param request - Strategy execute request containing fiat quotes, messenger, and transaction metadata.\n * @param request.messenger - Controller messenger for cross-controller calls.\n * @param request.quotes - Fiat quotes to execute (exactly one expected).\n * @param request.transaction - Original transaction metadata.\n * @param request.isSmartTransaction - Callback to check smart transaction eligibility.\n * @returns An object containing the relay transaction hash if available.\n */\nexport async function submitFiatQuotes(\n request: PayStrategyExecuteRequest<FiatQuote>,\n): ReturnType<PayStrategy<FiatQuote>['execute']> {\n const { messenger, transaction } = request;\n const transactionId = transaction.id;\n const state = messenger.call('TransactionPayController:getState');\n const transactionData = state.transactionData[transactionId];\n\n const walletAddress = getWalletAddress({\n messenger,\n quotes: request.quotes,\n transaction,\n accountOverride: transactionData?.accountOverride,\n });\n\n const fiatPayment = transactionData?.fiatPayment;\n const orderId = fiatPayment?.orderId;\n\n if (!orderId) {\n throw new Error('Missing order ID');\n }\n\n const providerCode = extractProviderCode(fiatPayment?.rampsQuote?.provider);\n\n if (!providerCode) {\n throw new Error('Missing provider code');\n }\n\n updateTransaction(\n {\n transactionId,\n messenger,\n note: 'Persist fiat order metadata',\n },\n (tx) => {\n tx.metamaskPay ??= {};\n tx.metamaskPay.fiat = { orderId, provider: providerCode };\n },\n );\n\n log('Starting fiat order polling', {\n orderId,\n providerCode,\n transactionId,\n });\n\n const fiatQuote = request.quotes[0];\n\n if (!fiatQuote) {\n throw new Error('Missing quote');\n }\n\n const fiatOptions = getFiatOptions(messenger);\n\n const order = fiatOptions?.testFundingSource\n ? await fundFiatOrderFromTestSource({\n fiat: fiatOptions,\n messenger,\n quote: fiatQuote,\n transaction,\n })\n : await waitForOrderCompletion({\n messenger,\n orderCode: orderId,\n providerCode,\n transactionId,\n walletAddress,\n });\n\n log('Fiat order completed', {\n cryptoAmount: order.cryptoAmount,\n orderId,\n transactionId,\n });\n\n try {\n await waitForKeyringUnlock(messenger, transactionId);\n\n const result = await submitRelayAfterFiatCompletion({\n order,\n request,\n });\n\n if (result.transactionHash === undefined) {\n throw new Error('Missing transaction hash');\n }\n\n return result;\n } catch (error) {\n throw prefixError(error, POST_RAMP_ERROR_PREFIX);\n }\n}\n\nfunction getFiatOptions(\n messenger: TransactionPayControllerMessenger,\n): TransactionPayFiatOptions | undefined {\n try {\n return messenger.call('TransactionPayController:getFiatOptions');\n } catch (error) {\n log('Failed to retrieve fiat options', error);\n return undefined;\n }\n}\n\n/**\n * Polls the on-ramp order until it reaches a terminal status.\n *\n * @param options - The polling options.\n * @param options.messenger - Controller messenger for calling `RampsController:getOrder`.\n * @param options.orderCode - The order identifier within the provider.\n * @param options.providerCode - The on-ramp provider code (e.g. \"transak\").\n * @param options.transactionId - Transaction ID for logging.\n * @param options.walletAddress - Wallet address associated with the order.\n * @returns The completed order data.\n */\nasync function waitForOrderCompletion({\n messenger,\n orderCode,\n providerCode,\n transactionId,\n walletAddress,\n}: {\n messenger: TransactionPayControllerMessenger;\n orderCode: string;\n providerCode: string;\n transactionId: string;\n walletAddress: string;\n}): Promise<RampsOrder> {\n const pollIntervalMs = getFiatOrderPollIntervalMs(messenger);\n const pollTimeoutMs = getFiatOrderPollTimeoutMs(messenger);\n const startTime = Date.now();\n let lastStatus: string | undefined;\n\n while (true) {\n let order: RampsOrder | undefined;\n\n try {\n order = await messenger.call(\n 'RampsController:getOrder',\n providerCode,\n orderCode,\n walletAddress,\n );\n } catch (error) {\n log('Order polling network error', error);\n }\n\n if (order) {\n lastStatus = order.status;\n\n log('Polled fiat order', {\n orderStatus: order.status,\n providerCode,\n transactionId,\n });\n\n if (order.status === RampsOrderStatus.Completed) {\n return order;\n }\n\n if (TERMINAL_FAILURE_STATUSES.includes(order.status)) {\n throw new Error(`Fiat order ${order.status.toLowerCase()}`);\n }\n }\n\n if (Date.now() - startTime >= pollTimeoutMs) {\n throw new Error(\n `Fiat order polling timed out (last status: ${lastStatus})`,\n );\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n }\n}\n\n/**\n * Re-quotes and submits the relay leg using the settled amount from a completed fiat order.\n *\n * @param options - The submission options.\n * @param options.order - The completed on-ramp order containing the settled crypto amount.\n * @param options.request - The original fiat strategy execute request.\n * @returns An object containing the relay transaction hash if available.\n */\nasync function submitRelayAfterFiatCompletion({\n order,\n request,\n}: {\n order: RampsOrder;\n request: PayStrategyExecuteRequest<FiatQuote>;\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger, quotes, transaction } = request;\n const transactionId = transaction.id;\n\n if (quotes.length > 1) {\n throw new Error('Multiple fiat quotes are not supported for submission');\n }\n\n const fiatQuote = quotes[0];\n const isDirectMusd = isDirectMusdMoneyAccountQuote(fiatQuote);\n\n if (isDirectMusd) {\n return await submitDirectMusdAfterFiatCompletion({\n order,\n request,\n });\n }\n\n const fiatAsset = deriveFiatAssetForFiatPayment(transaction, messenger);\n\n validateOrderAsset({\n expectedAsset: fiatAsset,\n orderCrypto: order.cryptoCurrency,\n transactionId,\n });\n\n const baseRequest = fiatQuote.request;\n\n const sourceAmountRaw = await resolveSourceAmountRaw({\n messenger,\n order,\n fiatAsset,\n walletAddress: baseRequest.from,\n });\n\n if (!fiatQuote.original.relayQuote) {\n throw new Error('Missing Relay quote');\n }\n\n const hasNestedCalldata = (transaction.nestedTransactions?.length ?? 0) >= 2;\n\n // Transactions with nested calldata (e.g. moneyAccountDeposit with\n // approve + deposit) need a three-phase flow: discovery quote to learn\n // the target amount, calldata re-encoding, then a delegation quote.\n // Simple deposits (Perps, Predict) skip straight to a single EXACT_INPUT\n // relay quote — cheaper fees, no leftover dust, one fewer request.\n if (hasNestedCalldata) {\n return await submitWithTransactionData({\n baseRequest,\n request,\n sourceAmountRaw,\n transaction,\n });\n }\n\n return await submitSimpleRelay({\n baseRequest,\n request,\n sourceAmountRaw,\n transaction,\n });\n}\n\nfunction getWalletAddress({\n messenger,\n quotes,\n transaction,\n accountOverride,\n}: {\n messenger: TransactionPayControllerMessenger;\n quotes: PayStrategyExecuteRequest<FiatQuote>['quotes'];\n transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];\n accountOverride: string | undefined;\n}): Hex {\n const address = isDirectMusdMoneyAccountQuote(quotes[0])\n ? transaction.txParams.from\n : (getEvmAccountOverride(messenger, accountOverride) ??\n transaction.txParams.from);\n\n if (!address) {\n throw new Error('Missing wallet address');\n }\n\n return address as Hex;\n}\n\nfunction waitForKeyringUnlock(\n messenger: TransactionPayControllerMessenger,\n transactionId: string,\n): Promise<void> {\n const { isUnlocked } = messenger.call('KeyringController:getState');\n\n if (isUnlocked) {\n return Promise.resolve();\n }\n\n log(\n 'KeyringController is locked; waiting for unlock before fiat submit second leg',\n {\n transactionId,\n },\n );\n\n return new Promise((resolve) => {\n const handler = (): void => {\n messenger.unsubscribe('KeyringController:unlock', handler);\n\n log('KeyringController unlocked; resuming fiat submit second leg', {\n transactionId,\n });\n\n resolve();\n };\n\n messenger.subscribe('KeyringController:unlock', handler);\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-test-funding.d.ts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-test-funding.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAG7D,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,kCAAkC,CAAC;AAO1C,OAAO,KAAK,EACV,iCAAiC,EACjC,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAUxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAS5C;;;;;;;;;GASG;AACH,wBAAsB,2BAA2B,CAAC,EAChD,IAAI,EACJ,SAAS,EACT,KAAK,EACL,WAAW,GACZ,EAAE;IACD,IAAI,EAAE,yBAAyB,CAAC;IAChC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,KAAK,EAAE,mBAAmB,CAAC,SAAS,CAAC,CAAC;IACtC,WAAW,EAAE,eAAe,CAAC;CAC9B,GAAG,OAAO,CAAC,UAAU,CAAC,CA6EtB"}
1
+ {"version":3,"file":"fiat-test-funding.d.ts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-test-funding.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAG7D,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,kCAAkC,CAAC;AAO1C,OAAO,KAAK,EACV,iCAAiC,EACjC,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAWxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAS5C;;;;;;;;;GASG;AACH,wBAAsB,2BAA2B,CAAC,EAChD,IAAI,EACJ,SAAS,EACT,KAAK,EACL,WAAW,GACZ,EAAE;IACD,IAAI,EAAE,yBAAyB,CAAC;IAChC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,KAAK,EAAE,mBAAmB,CAAC,SAAS,CAAC,CAAC;IACtC,WAAW,EAAE,eAAe,CAAC;CAC9B,GAAG,OAAO,CAAC,UAAU,CAAC,CA2EtB"}
@@ -7,7 +7,7 @@ import { BigNumber } from 'bignumber.js';
7
7
  import { NATIVE_TOKEN_ADDRESS } from '../../constants.js';
8
8
  import { projectLogger } from '../../logger.js';
9
9
  import { getNetworkClientId } from '../../utils/provider.js';
10
- import { buildCaipAssetType, getLiveTokenBalance, getNativeToken, getTokenInfo, } from '../../utils/token.js';
10
+ import { buildCaipAssetType, getEvmQuoteSource, getLiveTokenBalance, getNativeToken, getTokenInfo, } from '../../utils/token.js';
11
11
  import { waitForTransactionConfirmed } from '../../utils/transaction.js';
12
12
  import { isDirectMusdMoneyAccountQuote } from './fiat-direct-musd.js';
13
13
  import { deriveFiatAssetForFiatPayment } from './utils.js';
@@ -32,11 +32,9 @@ export async function fundFiatOrderFromTestSource({ fiat, messenger, quote, tran
32
32
  throw new Error('Missing fiat test funding source');
33
33
  }
34
34
  const isDirectMusd = isDirectMusdMoneyAccountQuote(quote);
35
+ const quoteSource = getEvmQuoteSource(quote.request);
35
36
  const fiatAsset = isDirectMusd
36
- ? {
37
- address: quote.request.sourceTokenAddress,
38
- chainId: quote.request.sourceChainId,
39
- }
37
+ ? { address: quoteSource.tokenAddress, chainId: quoteSource.chainId }
40
38
  : deriveFiatAssetForFiatPayment(transaction, messenger);
41
39
  const recipient = getFiatFundingRecipient({ quote, transaction });
42
40
  const cryptoAmount = fiat.testAmountOverride ?? quote.original.rampsQuote.quote.amountOut;
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-test-funding.js","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-test-funding.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { ORIGIN_METAMASK, toHex } from '@metamask/controller-utils';\nimport type { RampsOrder } from '@metamask/ramps-controller';\nimport { RampsOrderStatus } from '@metamask/ramps-controller';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type {\n TransactionMeta,\n TransactionParams,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { NATIVE_TOKEN_ADDRESS } from '../../constants.js';\nimport { projectLogger } from '../../logger.js';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayFiatOptions,\n TransactionPayQuote,\n} from '../../types.js';\nimport { getNetworkClientId } from '../../utils/provider.js';\nimport {\n buildCaipAssetType,\n getLiveTokenBalance,\n getNativeToken,\n getTokenInfo,\n} from '../../utils/token.js';\nimport { waitForTransactionConfirmed } from '../../utils/transaction.js';\nimport { isDirectMusdMoneyAccountQuote } from './fiat-direct-musd.js';\nimport type { FiatQuote } from './types.js';\nimport { deriveFiatAssetForFiatPayment } from './utils.js';\nimport { getRawSourceAmountFromOrderCryptoAmount } from './utils.js';\n\nconst log = createModuleLogger(projectLogger, 'fiat-test-funding');\nconst TOKEN_TRANSFER_INTERFACE = new Interface([\n 'function transfer(address to, uint256 amount)',\n]);\n\n/**\n * Funds the fiat recipient from a test source instead of waiting for ramps.\n *\n * @param options - Test funding options.\n * @param options.fiat - Fiat local-QA execution options.\n * @param options.messenger - Controller messenger.\n * @param options.quote - Fiat quote being submitted.\n * @param options.transaction - Original transaction metadata.\n * @returns A synthetic completed ramps order for the existing fiat submit flow.\n */\nexport async function fundFiatOrderFromTestSource({\n fiat,\n messenger,\n quote,\n transaction,\n}: {\n fiat: TransactionPayFiatOptions;\n messenger: TransactionPayControllerMessenger;\n quote: TransactionPayQuote<FiatQuote>;\n transaction: TransactionMeta;\n}): Promise<RampsOrder> {\n const fundingSource = fiat.testFundingSource;\n\n if (!fundingSource) {\n throw new Error('Missing fiat test funding source');\n }\n\n const isDirectMusd = isDirectMusdMoneyAccountQuote(quote);\n const fiatAsset = isDirectMusd\n ? {\n address: quote.request.sourceTokenAddress,\n chainId: quote.request.sourceChainId,\n }\n : deriveFiatAssetForFiatPayment(transaction, messenger);\n\n const recipient = getFiatFundingRecipient({ quote, transaction });\n const cryptoAmount =\n fiat.testAmountOverride ?? quote.original.rampsQuote.quote.amountOut;\n const tokenInfo = getTokenInfo(\n messenger,\n fiatAsset.address,\n fiatAsset.chainId,\n );\n\n if (!tokenInfo) {\n throw new Error(\n `Unable to resolve fiat test funding token info for ${fiatAsset.address} on chain ${fiatAsset.chainId}`,\n );\n }\n\n const amountRaw = getRawSourceAmountFromOrderCryptoAmount({\n cryptoAmount,\n decimals: tokenInfo.decimals,\n });\n\n log('Preparing fiat test funding transfer', {\n amountRaw,\n chainId: fiatAsset.chainId,\n fundingSource,\n recipient,\n testAmountOverride: fiat.testAmountOverride,\n });\n\n await assertTestFundingBalances({\n amountRaw,\n fiatAsset,\n fundingSource,\n messenger,\n symbol: tokenInfo.symbol,\n });\n\n const txHash = await submitTestFundingTransfer({\n amountRaw,\n fiatAsset,\n fundingSource,\n messenger,\n recipient,\n });\n\n log('Fiat test funding complete', {\n amountRaw,\n chainId: fiatAsset.chainId,\n fundingSource,\n recipient,\n txHash,\n });\n\n return {\n cryptoAmount,\n cryptoCurrency: {\n assetId: buildCaipAssetType(fiatAsset.chainId, fiatAsset.address),\n chainId: `eip155:${Number(fiatAsset.chainId)}`,\n symbol: tokenInfo.symbol,\n },\n status: RampsOrderStatus.Completed,\n txHash,\n } as RampsOrder;\n}\n\nfunction getFiatFundingRecipient({\n quote,\n transaction,\n}: {\n quote: TransactionPayQuote<FiatQuote>;\n transaction: TransactionMeta;\n}): Hex {\n if (isDirectMusdMoneyAccountQuote(quote)) {\n const moneyAccountAddress = transaction.txParams.from as Hex | undefined;\n\n if (!moneyAccountAddress) {\n throw new Error('Missing Money Account address for fiat test funding');\n }\n\n return moneyAccountAddress;\n }\n\n return quote.request.from;\n}\n\nasync function assertTestFundingBalances({\n amountRaw,\n fiatAsset,\n fundingSource,\n messenger,\n symbol,\n}: {\n amountRaw: string;\n fiatAsset: { address: Hex; chainId: Hex };\n fundingSource: Hex;\n messenger: TransactionPayControllerMessenger;\n symbol: string;\n}): Promise<void> {\n const balance = await getLiveTokenBalance(\n messenger,\n fundingSource,\n fiatAsset.chainId,\n fiatAsset.address,\n );\n\n if (new BigNumber(balance).lt(amountRaw)) {\n throw new Error(\n `Fiat test funding source has insufficient ${symbol} on chain ${fiatAsset.chainId}. ` +\n `Required: ${amountRaw}, Available: ${balance}, Source: ${fundingSource}`,\n );\n }\n\n const nativeToken = getNativeToken(fiatAsset.chainId);\n const isNative = isNativeFiatAsset(fiatAsset);\n const nativeBalance = isNative\n ? balance\n : await getLiveTokenBalance(\n messenger,\n fundingSource,\n fiatAsset.chainId,\n nativeToken,\n );\n\n const requiredNativeBalance = isNative ? amountRaw : '0';\n\n if (new BigNumber(nativeBalance).lte(requiredNativeBalance)) {\n throw new Error(\n `Fiat test funding source has insufficient native gas on chain ${fiatAsset.chainId}. ` +\n `Native balance: ${nativeBalance}, Source: ${fundingSource}`,\n );\n }\n}\n\nasync function submitTestFundingTransfer({\n amountRaw,\n fiatAsset,\n fundingSource,\n messenger,\n recipient,\n}: {\n amountRaw: string;\n fiatAsset: { address: Hex; chainId: Hex };\n fundingSource: Hex;\n messenger: TransactionPayControllerMessenger;\n recipient: Hex;\n}): Promise<Hex> {\n const networkClientId = getNetworkClientId(messenger, fiatAsset.chainId);\n const params = buildTestFundingTransferParams({\n amountRaw,\n fiatAsset,\n fundingSource,\n recipient,\n });\n\n const result = await messenger.call(\n 'TransactionController:addTransaction',\n params,\n {\n isInternal: true,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n type: TransactionType.simpleSend,\n },\n );\n\n const txHash = (await result.result) as Hex;\n\n await waitForTransactionConfirmed(result.transactionMeta.id, messenger);\n\n return txHash;\n}\n\nfunction buildTestFundingTransferParams({\n amountRaw,\n fiatAsset,\n fundingSource,\n recipient,\n}: {\n amountRaw: string;\n fiatAsset: { address: Hex; chainId: Hex };\n fundingSource: Hex;\n recipient: Hex;\n}): TransactionParams {\n if (isNativeFiatAsset(fiatAsset)) {\n return {\n from: fundingSource,\n to: recipient,\n value: toHex(amountRaw),\n };\n }\n\n return {\n data: buildTokenTransferData(recipient, amountRaw),\n from: fundingSource,\n to: fiatAsset.address,\n value: '0x0',\n };\n}\n\nfunction buildTokenTransferData(recipient: Hex, amountRaw: string): Hex {\n return TOKEN_TRANSFER_INTERFACE.encodeFunctionData('transfer', [\n recipient,\n amountRaw,\n ]) as Hex;\n}\n\nfunction isNativeFiatAsset({\n address,\n chainId,\n}: {\n address: Hex;\n chainId: Hex;\n}): boolean {\n const normalizedAddress = address.toLowerCase();\n\n return (\n normalizedAddress === NATIVE_TOKEN_ADDRESS.toLowerCase() ||\n normalizedAddress === getNativeToken(chainId).toLowerCase()\n );\n}\n"]}
1
+ {"version":3,"file":"fiat-test-funding.js","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-test-funding.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { ORIGIN_METAMASK, toHex } from '@metamask/controller-utils';\nimport type { RampsOrder } from '@metamask/ramps-controller';\nimport { RampsOrderStatus } from '@metamask/ramps-controller';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type {\n TransactionMeta,\n TransactionParams,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { NATIVE_TOKEN_ADDRESS } from '../../constants.js';\nimport { projectLogger } from '../../logger.js';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayFiatOptions,\n TransactionPayQuote,\n} from '../../types.js';\nimport { getNetworkClientId } from '../../utils/provider.js';\nimport {\n buildCaipAssetType,\n getEvmQuoteSource,\n getLiveTokenBalance,\n getNativeToken,\n getTokenInfo,\n} from '../../utils/token.js';\nimport { waitForTransactionConfirmed } from '../../utils/transaction.js';\nimport { isDirectMusdMoneyAccountQuote } from './fiat-direct-musd.js';\nimport type { FiatQuote } from './types.js';\nimport { deriveFiatAssetForFiatPayment } from './utils.js';\nimport { getRawSourceAmountFromOrderCryptoAmount } from './utils.js';\n\nconst log = createModuleLogger(projectLogger, 'fiat-test-funding');\nconst TOKEN_TRANSFER_INTERFACE = new Interface([\n 'function transfer(address to, uint256 amount)',\n]);\n\n/**\n * Funds the fiat recipient from a test source instead of waiting for ramps.\n *\n * @param options - Test funding options.\n * @param options.fiat - Fiat local-QA execution options.\n * @param options.messenger - Controller messenger.\n * @param options.quote - Fiat quote being submitted.\n * @param options.transaction - Original transaction metadata.\n * @returns A synthetic completed ramps order for the existing fiat submit flow.\n */\nexport async function fundFiatOrderFromTestSource({\n fiat,\n messenger,\n quote,\n transaction,\n}: {\n fiat: TransactionPayFiatOptions;\n messenger: TransactionPayControllerMessenger;\n quote: TransactionPayQuote<FiatQuote>;\n transaction: TransactionMeta;\n}): Promise<RampsOrder> {\n const fundingSource = fiat.testFundingSource;\n\n if (!fundingSource) {\n throw new Error('Missing fiat test funding source');\n }\n\n const isDirectMusd = isDirectMusdMoneyAccountQuote(quote);\n const quoteSource = getEvmQuoteSource(quote.request);\n const fiatAsset = isDirectMusd\n ? { address: quoteSource.tokenAddress, chainId: quoteSource.chainId }\n : deriveFiatAssetForFiatPayment(transaction, messenger);\n\n const recipient = getFiatFundingRecipient({ quote, transaction });\n const cryptoAmount =\n fiat.testAmountOverride ?? quote.original.rampsQuote.quote.amountOut;\n const tokenInfo = getTokenInfo(\n messenger,\n fiatAsset.address,\n fiatAsset.chainId,\n );\n\n if (!tokenInfo) {\n throw new Error(\n `Unable to resolve fiat test funding token info for ${fiatAsset.address} on chain ${fiatAsset.chainId}`,\n );\n }\n\n const amountRaw = getRawSourceAmountFromOrderCryptoAmount({\n cryptoAmount,\n decimals: tokenInfo.decimals,\n });\n\n log('Preparing fiat test funding transfer', {\n amountRaw,\n chainId: fiatAsset.chainId,\n fundingSource,\n recipient,\n testAmountOverride: fiat.testAmountOverride,\n });\n\n await assertTestFundingBalances({\n amountRaw,\n fiatAsset,\n fundingSource,\n messenger,\n symbol: tokenInfo.symbol,\n });\n\n const txHash = await submitTestFundingTransfer({\n amountRaw,\n fiatAsset,\n fundingSource,\n messenger,\n recipient,\n });\n\n log('Fiat test funding complete', {\n amountRaw,\n chainId: fiatAsset.chainId,\n fundingSource,\n recipient,\n txHash,\n });\n\n return {\n cryptoAmount,\n cryptoCurrency: {\n assetId: buildCaipAssetType(fiatAsset.chainId, fiatAsset.address),\n chainId: `eip155:${Number(fiatAsset.chainId)}`,\n symbol: tokenInfo.symbol,\n },\n status: RampsOrderStatus.Completed,\n txHash,\n } as RampsOrder;\n}\n\nfunction getFiatFundingRecipient({\n quote,\n transaction,\n}: {\n quote: TransactionPayQuote<FiatQuote>;\n transaction: TransactionMeta;\n}): Hex {\n if (isDirectMusdMoneyAccountQuote(quote)) {\n const moneyAccountAddress = transaction.txParams.from as Hex | undefined;\n\n if (!moneyAccountAddress) {\n throw new Error('Missing Money Account address for fiat test funding');\n }\n\n return moneyAccountAddress;\n }\n\n return quote.request.from;\n}\n\nasync function assertTestFundingBalances({\n amountRaw,\n fiatAsset,\n fundingSource,\n messenger,\n symbol,\n}: {\n amountRaw: string;\n fiatAsset: { address: Hex; chainId: Hex };\n fundingSource: Hex;\n messenger: TransactionPayControllerMessenger;\n symbol: string;\n}): Promise<void> {\n const balance = await getLiveTokenBalance(\n messenger,\n fundingSource,\n fiatAsset.chainId,\n fiatAsset.address,\n );\n\n if (new BigNumber(balance).lt(amountRaw)) {\n throw new Error(\n `Fiat test funding source has insufficient ${symbol} on chain ${fiatAsset.chainId}. ` +\n `Required: ${amountRaw}, Available: ${balance}, Source: ${fundingSource}`,\n );\n }\n\n const nativeToken = getNativeToken(fiatAsset.chainId);\n const isNative = isNativeFiatAsset(fiatAsset);\n const nativeBalance = isNative\n ? balance\n : await getLiveTokenBalance(\n messenger,\n fundingSource,\n fiatAsset.chainId,\n nativeToken,\n );\n\n const requiredNativeBalance = isNative ? amountRaw : '0';\n\n if (new BigNumber(nativeBalance).lte(requiredNativeBalance)) {\n throw new Error(\n `Fiat test funding source has insufficient native gas on chain ${fiatAsset.chainId}. ` +\n `Native balance: ${nativeBalance}, Source: ${fundingSource}`,\n );\n }\n}\n\nasync function submitTestFundingTransfer({\n amountRaw,\n fiatAsset,\n fundingSource,\n messenger,\n recipient,\n}: {\n amountRaw: string;\n fiatAsset: { address: Hex; chainId: Hex };\n fundingSource: Hex;\n messenger: TransactionPayControllerMessenger;\n recipient: Hex;\n}): Promise<Hex> {\n const networkClientId = getNetworkClientId(messenger, fiatAsset.chainId);\n const params = buildTestFundingTransferParams({\n amountRaw,\n fiatAsset,\n fundingSource,\n recipient,\n });\n\n const result = await messenger.call(\n 'TransactionController:addTransaction',\n params,\n {\n isInternal: true,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n type: TransactionType.simpleSend,\n },\n );\n\n const txHash = (await result.result) as Hex;\n\n await waitForTransactionConfirmed(result.transactionMeta.id, messenger);\n\n return txHash;\n}\n\nfunction buildTestFundingTransferParams({\n amountRaw,\n fiatAsset,\n fundingSource,\n recipient,\n}: {\n amountRaw: string;\n fiatAsset: { address: Hex; chainId: Hex };\n fundingSource: Hex;\n recipient: Hex;\n}): TransactionParams {\n if (isNativeFiatAsset(fiatAsset)) {\n return {\n from: fundingSource,\n to: recipient,\n value: toHex(amountRaw),\n };\n }\n\n return {\n data: buildTokenTransferData(recipient, amountRaw),\n from: fundingSource,\n to: fiatAsset.address,\n value: '0x0',\n };\n}\n\nfunction buildTokenTransferData(recipient: Hex, amountRaw: string): Hex {\n return TOKEN_TRANSFER_INTERFACE.encodeFunctionData('transfer', [\n recipient,\n amountRaw,\n ]) as Hex;\n}\n\nfunction isNativeFiatAsset({\n address,\n chainId,\n}: {\n address: Hex;\n chainId: Hex;\n}): boolean {\n const normalizedAddress = address.toLowerCase();\n\n return (\n normalizedAddress === NATIVE_TOKEN_ADDRESS.toLowerCase() ||\n normalizedAddress === getNativeToken(chainId).toLowerCase()\n );\n}\n"]}
@@ -1,5 +1,9 @@
1
1
  import type { PayStrategy, PayStrategyExecuteRequest, PayStrategyGetRefreshIntervalRequest, PayStrategyGetQuotesRequest, TransactionPayQuote } from '../../types.js';
2
2
  import type { RelayQuote } from './types.js';
3
+ /**
4
+ * Pay strategy that quotes and submits through Relay. Only supports requests
5
+ * with an EVM source asset.
6
+ */
3
7
  export declare class RelayStrategy implements PayStrategy<RelayQuote> {
4
8
  supports(request: PayStrategyGetQuotesRequest): boolean;
5
9
  getQuotes(request: PayStrategyGetQuotesRequest): Promise<TransactionPayQuote<RelayQuote>[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"RelayStrategy.d.ts","sourceRoot":"","sources":["../../../src/strategy/relay/RelayStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,yBAAyB,EACzB,oCAAoC,EACpC,2BAA2B,EAC3B,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAQxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,qBAAa,aAAc,YAAW,WAAW,CAAC,UAAU,CAAC;IAC3D,QAAQ,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAGtD;IAEK,SAAS,CACb,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CAE5C;IAEK,kBAAkB,CACtB,OAAO,EAAE,oCAAoC,GAC5C,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAY7B;IAEK,OAAO,CACX,OAAO,EAAE,yBAAyB,CAAC,UAAU,CAAC,GAC7C,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,CAEhD;CACF"}
1
+ {"version":3,"file":"RelayStrategy.d.ts","sourceRoot":"","sources":["../../../src/strategy/relay/RelayStrategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,yBAAyB,EACzB,oCAAoC,EACpC,2BAA2B,EAC3B,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AASxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;GAGG;AACH,qBAAa,aAAc,YAAW,WAAW,CAAC,UAAU,CAAC;IAC3D,QAAQ,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAItD;IAEK,SAAS,CACb,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CAE5C;IAEK,kBAAkB,CACtB,OAAO,EAAE,oCAAoC,GAC5C,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAY7B;IAEK,OAAO,CACX,OAAO,EAAE,yBAAyB,CAAC,UAAU,CAAC,GAC7C,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,CAEhD;CACF"}
@@ -1,11 +1,16 @@
1
1
  import { getMaxBalanceRefreshInterval, getPayStrategiesConfig, } from '../../utils/feature-flags.js';
2
+ import { isEvmQuoteRequest } from '../../utils/token.js';
2
3
  import { getTransaction } from '../../utils/transaction.js';
3
4
  import { getRelayQuotes } from './relay-quotes.js';
4
5
  import { submitRelayQuotes } from './relay-submit.js';
6
+ /**
7
+ * Pay strategy that quotes and submits through Relay. Only supports requests
8
+ * with an EVM source asset.
9
+ */
5
10
  export class RelayStrategy {
6
11
  supports(request) {
7
12
  const config = getPayStrategiesConfig(request.messenger);
8
- return config.relay.enabled;
13
+ return config.relay.enabled && request.requests.every(isEvmQuoteRequest);
9
14
  }
10
15
  async getQuotes(request) {
11
16
  return getRelayQuotes(request);
@@ -1 +1 @@
1
- {"version":3,"file":"RelayStrategy.js","sourceRoot":"","sources":["../../../src/strategy/relay/RelayStrategy.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtD,MAAM,OAAO,aAAa;IACxB,QAAQ,CAAC,OAAoC;QAC3C,MAAM,MAAM,GAAG,sBAAsB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACzD,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,SAAS,CACb,OAAoC;QAEpC,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,kBAAkB,CACtB,OAA6C;QAE7C,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;QAC7C,MAAM,eAAe,GAAG,SAAS,CAAC,IAAI,CAAC,mCAAmC,CAAC;aACxE,eAAe,CAAC,aAAa,CAAC,CAAC;QAElC,IAAI,CAAC,eAAe,EAAE,WAAW,EAAE,CAAC;YAClC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,WAAW,GAAG,cAAc,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;QAE7D,OAAO,4BAA4B,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,OAAO,CACX,OAA8C;QAE9C,OAAO,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;CACF","sourcesContent":["import type {\n PayStrategy,\n PayStrategyExecuteRequest,\n PayStrategyGetRefreshIntervalRequest,\n PayStrategyGetQuotesRequest,\n TransactionPayQuote,\n} from '../../types.js';\nimport {\n getMaxBalanceRefreshInterval,\n getPayStrategiesConfig,\n} from '../../utils/feature-flags.js';\nimport { getTransaction } from '../../utils/transaction.js';\nimport { getRelayQuotes } from './relay-quotes.js';\nimport { submitRelayQuotes } from './relay-submit.js';\nimport type { RelayQuote } from './types.js';\n\nexport class RelayStrategy implements PayStrategy<RelayQuote> {\n supports(request: PayStrategyGetQuotesRequest): boolean {\n const config = getPayStrategiesConfig(request.messenger);\n return config.relay.enabled;\n }\n\n async getQuotes(\n request: PayStrategyGetQuotesRequest,\n ): Promise<TransactionPayQuote<RelayQuote>[]> {\n return getRelayQuotes(request);\n }\n\n async getRefreshInterval(\n request: PayStrategyGetRefreshIntervalRequest,\n ): Promise<number | undefined> {\n const { messenger, transactionId } = request;\n const transactionData = messenger.call('TransactionPayController:getState')\n .transactionData[transactionId];\n\n if (!transactionData?.isMaxAmount) {\n return undefined;\n }\n\n const transaction = getTransaction(transactionId, messenger);\n\n return getMaxBalanceRefreshInterval(messenger, transaction);\n }\n\n async execute(\n request: PayStrategyExecuteRequest<RelayQuote>,\n ): ReturnType<PayStrategy<RelayQuote>['execute']> {\n return await submitRelayQuotes(request);\n }\n}\n"]}
1
+ {"version":3,"file":"RelayStrategy.js","sourceRoot":"","sources":["../../../src/strategy/relay/RelayStrategy.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtD;;;GAGG;AACH,MAAM,OAAO,aAAa;IACxB,QAAQ,CAAC,OAAoC;QAC3C,MAAM,MAAM,GAAG,sBAAsB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAEzD,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC3E,CAAC;IAED,KAAK,CAAC,SAAS,CACb,OAAoC;QAEpC,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,kBAAkB,CACtB,OAA6C;QAE7C,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;QAC7C,MAAM,eAAe,GAAG,SAAS,CAAC,IAAI,CAAC,mCAAmC,CAAC;aACxE,eAAe,CAAC,aAAa,CAAC,CAAC;QAElC,IAAI,CAAC,eAAe,EAAE,WAAW,EAAE,CAAC;YAClC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,WAAW,GAAG,cAAc,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;QAE7D,OAAO,4BAA4B,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,OAAO,CACX,OAA8C;QAE9C,OAAO,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;CACF","sourcesContent":["import type {\n PayStrategy,\n PayStrategyExecuteRequest,\n PayStrategyGetRefreshIntervalRequest,\n PayStrategyGetQuotesRequest,\n TransactionPayQuote,\n} from '../../types.js';\nimport {\n getMaxBalanceRefreshInterval,\n getPayStrategiesConfig,\n} from '../../utils/feature-flags.js';\nimport { isEvmQuoteRequest } from '../../utils/token.js';\nimport { getTransaction } from '../../utils/transaction.js';\nimport { getRelayQuotes } from './relay-quotes.js';\nimport { submitRelayQuotes } from './relay-submit.js';\nimport type { RelayQuote } from './types.js';\n\n/**\n * Pay strategy that quotes and submits through Relay. Only supports requests\n * with an EVM source asset.\n */\nexport class RelayStrategy implements PayStrategy<RelayQuote> {\n supports(request: PayStrategyGetQuotesRequest): boolean {\n const config = getPayStrategiesConfig(request.messenger);\n\n return config.relay.enabled && request.requests.every(isEvmQuoteRequest);\n }\n\n async getQuotes(\n request: PayStrategyGetQuotesRequest,\n ): Promise<TransactionPayQuote<RelayQuote>[]> {\n return getRelayQuotes(request);\n }\n\n async getRefreshInterval(\n request: PayStrategyGetRefreshIntervalRequest,\n ): Promise<number | undefined> {\n const { messenger, transactionId } = request;\n const transactionData = messenger.call('TransactionPayController:getState')\n .transactionData[transactionId];\n\n if (!transactionData?.isMaxAmount) {\n return undefined;\n }\n\n const transaction = getTransaction(transactionId, messenger);\n\n return getMaxBalanceRefreshInterval(messenger, transaction);\n }\n\n async execute(\n request: PayStrategyExecuteRequest<RelayQuote>,\n ): ReturnType<PayStrategy<RelayQuote>['execute']> {\n return await submitRelayQuotes(request);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"relay-quotes.d.ts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAGV,2BAA2B,EAG3B,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAgDxB,OAAO,KAAK,EACV,UAAU,EAIX,MAAM,YAAY,CAAC;AASpB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CAuD5C"}
1
+ {"version":3,"file":"relay-quotes.d.ts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAGV,2BAA2B,EAG3B,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAkDxB,OAAO,KAAK,EACV,UAAU,EAIX,MAAM,YAAY,CAAC;AASpB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CAuD5C"}
@@ -17,7 +17,7 @@ import { processPostQuotePaymentOverride } from '../../utils/post-quote-payment-
17
17
  import { reservePostQuoteGas } from '../../utils/post-quote.js';
18
18
  import { estimateSourceGas } from '../../utils/quote-gas.js';
19
19
  import { resolveQuoteRecipient } from '../../utils/quote-recipient.js';
20
- import { getNativeToken, getTokenFiatRate, normalizeTokenAddress, TokenAddressTarget, } from '../../utils/token.js';
20
+ import { buildCaipAssetType, getEvmQuoteSource, getNativeToken, getTokenFiatRate, normalizeTokenAddress, TokenAddressTarget, } from '../../utils/token.js';
21
21
  import { getQuotePricing } from '../../utils/trade-type.js';
22
22
  import { TOKEN_TRANSFER_FOUR_BYTE } from './constants.js';
23
23
  import { hasRelayDepositStep } from './deposit-step.js';
@@ -121,7 +121,8 @@ async function getQuoteWithPostQuoteGasHandling(request, fullRequest) {
121
121
  */
122
122
  async function getSingleQuote(request, fullRequest) {
123
123
  const { accountSupports7702: supports7702, messenger, signal, transaction, } = fullRequest;
124
- const { from, sourceChainId, sourceTokenAddress, sourceTokenAmount, targetAmountMinimum, targetChainId, targetTokenAddress, } = request;
124
+ const { from, sourceTokenAmount, targetAmountMinimum, targetChainId, targetTokenAddress, } = request;
125
+ const { chainId: sourceChainId, tokenAddress: sourceTokenAddress } = getEvmQuoteSource(request);
125
126
  const slippageDecimal = getSlippage(messenger, sourceChainId, sourceTokenAddress);
126
127
  const slippageTolerance = new BigNumber(slippageDecimal * 100 * 100).toFixed(0);
127
128
  try {
@@ -288,9 +289,10 @@ async function processTransactions(transaction, request, requestBody, messenger)
288
289
  * @returns Normalized request.
289
290
  */
290
291
  function normalizeRequest(request, transaction) {
292
+ const { chainId: sourceChainId, tokenAddress: sourceTokenAddress } = getEvmQuoteSource(request);
291
293
  const newRequest = {
292
294
  ...request,
293
- sourceTokenAddress: normalizeTokenAddress(request.sourceTokenAddress, request.sourceChainId, TokenAddressTarget.Relay),
295
+ sourceAssetId: buildCaipAssetType(sourceChainId, normalizeTokenAddress(sourceTokenAddress, sourceChainId, TokenAddressTarget.Relay)),
294
296
  targetTokenAddress: normalizeTokenAddress(request.targetTokenAddress, request.targetChainId, TokenAddressTarget.Relay),
295
297
  };
296
298
  const depositRequest = normalizePerpsDepositRequest(newRequest, transaction, HYPERCORE_USDC_ADDRESS);
@@ -395,12 +397,13 @@ function getFiatRates(messenger, request) {
395
397
  // For HyperLiquid source, the normalized chain/token (HyperCore + Perps USDC)
396
398
  // won't have a fiat rate entry. Use Arbitrum USDC instead since Perps USDC
397
399
  // is pegged 1:1.
400
+ const quoteSource = getEvmQuoteSource(request);
398
401
  const sourceChainId = request.isHyperliquidSource
399
402
  ? CHAIN_ID_ARBITRUM
400
- : request.sourceChainId;
403
+ : quoteSource.chainId;
401
404
  const sourceTokenAddress = request.isHyperliquidSource
402
405
  ? ARBITRUM_USDC_ADDRESS
403
- : request.sourceTokenAddress;
406
+ : quoteSource.tokenAddress;
404
407
  const finalSourceTokenAddress = sourceChainId === CHAIN_ID_POLYGON &&
405
408
  sourceTokenAddress === NATIVE_TOKEN_ADDRESS
406
409
  ? getNativeToken(sourceChainId)
@@ -432,7 +435,8 @@ function getFiatRates(messenger, request) {
432
435
  * @returns Total source network cost in USD and fiat.
433
436
  */
434
437
  async function calculateSourceNetworkCost(quote, messenger, request, transaction, accountSupports7702) {
435
- const { from, sourceChainId, sourceTokenAddress } = request;
438
+ const { from } = request;
439
+ const { chainId: sourceChainId, tokenAddress: sourceTokenAddress } = getEvmQuoteSource(request);
436
440
  // None of these flows bill origin gas to the user: the execute flow has a
437
441
  // relayer redeem a signed delegation, a HyperLiquid withdrawal's "deposit"
438
442
  // step is an off-chain HL sendAsset signature rather than an on-chain