@metamask/transaction-pay-controller 23.8.0 → 23.9.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 (114) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/dist/TransactionPayController-method-action-types.cjs.map +1 -1
  3. package/dist/TransactionPayController-method-action-types.d.cts +12 -1
  4. package/dist/TransactionPayController-method-action-types.d.cts.map +1 -1
  5. package/dist/TransactionPayController-method-action-types.d.mts +12 -1
  6. package/dist/TransactionPayController-method-action-types.d.mts.map +1 -1
  7. package/dist/TransactionPayController-method-action-types.mjs.map +1 -1
  8. package/dist/TransactionPayController.cjs +16 -3
  9. package/dist/TransactionPayController.cjs.map +1 -1
  10. package/dist/TransactionPayController.d.cts +10 -2
  11. package/dist/TransactionPayController.d.cts.map +1 -1
  12. package/dist/TransactionPayController.d.mts +10 -2
  13. package/dist/TransactionPayController.d.mts.map +1 -1
  14. package/dist/TransactionPayController.mjs +16 -3
  15. package/dist/TransactionPayController.mjs.map +1 -1
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +2 -2
  18. package/dist/index.d.cts.map +1 -1
  19. package/dist/index.d.mts +2 -2
  20. package/dist/index.d.mts.map +1 -1
  21. package/dist/index.mjs.map +1 -1
  22. package/dist/strategy/fiat/constants.cjs +1 -3
  23. package/dist/strategy/fiat/constants.cjs.map +1 -1
  24. package/dist/strategy/fiat/constants.d.cts +0 -2
  25. package/dist/strategy/fiat/constants.d.cts.map +1 -1
  26. package/dist/strategy/fiat/constants.d.mts +0 -2
  27. package/dist/strategy/fiat/constants.d.mts.map +1 -1
  28. package/dist/strategy/fiat/constants.mjs +0 -2
  29. package/dist/strategy/fiat/constants.mjs.map +1 -1
  30. package/dist/strategy/fiat/fiat-direct-musd.cjs +246 -0
  31. package/dist/strategy/fiat/fiat-direct-musd.cjs.map +1 -0
  32. package/dist/strategy/fiat/fiat-direct-musd.d.cts +47 -0
  33. package/dist/strategy/fiat/fiat-direct-musd.d.cts.map +1 -0
  34. package/dist/strategy/fiat/fiat-direct-musd.d.mts +47 -0
  35. package/dist/strategy/fiat/fiat-direct-musd.d.mts.map +1 -0
  36. package/dist/strategy/fiat/fiat-direct-musd.mjs +240 -0
  37. package/dist/strategy/fiat/fiat-direct-musd.mjs.map +1 -0
  38. package/dist/strategy/fiat/fiat-quotes.cjs +27 -79
  39. package/dist/strategy/fiat/fiat-quotes.cjs.map +1 -1
  40. package/dist/strategy/fiat/fiat-quotes.d.cts +2 -3
  41. package/dist/strategy/fiat/fiat-quotes.d.cts.map +1 -1
  42. package/dist/strategy/fiat/fiat-quotes.d.mts +2 -3
  43. package/dist/strategy/fiat/fiat-quotes.d.mts.map +1 -1
  44. package/dist/strategy/fiat/fiat-quotes.mjs +28 -80
  45. package/dist/strategy/fiat/fiat-quotes.mjs.map +1 -1
  46. package/dist/strategy/fiat/fiat-submit-simple.cjs +3 -0
  47. package/dist/strategy/fiat/fiat-submit-simple.cjs.map +1 -1
  48. package/dist/strategy/fiat/fiat-submit-simple.d.cts.map +1 -1
  49. package/dist/strategy/fiat/fiat-submit-simple.d.mts.map +1 -1
  50. package/dist/strategy/fiat/fiat-submit-simple.mjs +3 -0
  51. package/dist/strategy/fiat/fiat-submit-simple.mjs.map +1 -1
  52. package/dist/strategy/fiat/fiat-submit-with-transaction-data.cjs +5 -2
  53. package/dist/strategy/fiat/fiat-submit-with-transaction-data.cjs.map +1 -1
  54. package/dist/strategy/fiat/fiat-submit-with-transaction-data.d.cts.map +1 -1
  55. package/dist/strategy/fiat/fiat-submit-with-transaction-data.d.mts.map +1 -1
  56. package/dist/strategy/fiat/fiat-submit-with-transaction-data.mjs +5 -2
  57. package/dist/strategy/fiat/fiat-submit-with-transaction-data.mjs.map +1 -1
  58. package/dist/strategy/fiat/fiat-submit.cjs +57 -35
  59. package/dist/strategy/fiat/fiat-submit.cjs.map +1 -1
  60. package/dist/strategy/fiat/fiat-submit.d.cts.map +1 -1
  61. package/dist/strategy/fiat/fiat-submit.d.mts.map +1 -1
  62. package/dist/strategy/fiat/fiat-submit.mjs +57 -35
  63. package/dist/strategy/fiat/fiat-submit.mjs.map +1 -1
  64. package/dist/strategy/fiat/fiat-test-funding.cjs +166 -0
  65. package/dist/strategy/fiat/fiat-test-funding.cjs.map +1 -0
  66. package/dist/strategy/fiat/fiat-test-funding.d.cts +21 -0
  67. package/dist/strategy/fiat/fiat-test-funding.d.cts.map +1 -0
  68. package/dist/strategy/fiat/fiat-test-funding.d.mts +21 -0
  69. package/dist/strategy/fiat/fiat-test-funding.d.mts.map +1 -0
  70. package/dist/strategy/fiat/fiat-test-funding.mjs +162 -0
  71. package/dist/strategy/fiat/fiat-test-funding.mjs.map +1 -0
  72. package/dist/strategy/fiat/types.cjs.map +1 -1
  73. package/dist/strategy/fiat/types.d.cts +1 -1
  74. package/dist/strategy/fiat/types.d.cts.map +1 -1
  75. package/dist/strategy/fiat/types.d.mts +1 -1
  76. package/dist/strategy/fiat/types.d.mts.map +1 -1
  77. package/dist/strategy/fiat/types.mjs.map +1 -1
  78. package/dist/strategy/fiat/utils.cjs +33 -1
  79. package/dist/strategy/fiat/utils.cjs.map +1 -1
  80. package/dist/strategy/fiat/utils.d.cts +21 -1
  81. package/dist/strategy/fiat/utils.d.cts.map +1 -1
  82. package/dist/strategy/fiat/utils.d.mts +21 -1
  83. package/dist/strategy/fiat/utils.d.mts.map +1 -1
  84. package/dist/strategy/fiat/utils.mjs +33 -2
  85. package/dist/strategy/fiat/utils.mjs.map +1 -1
  86. package/dist/tests/messenger-mock.cjs +3 -0
  87. package/dist/tests/messenger-mock.cjs.map +1 -1
  88. package/dist/tests/messenger-mock.d.cts +1 -0
  89. package/dist/tests/messenger-mock.d.cts.map +1 -1
  90. package/dist/tests/messenger-mock.d.mts +1 -0
  91. package/dist/tests/messenger-mock.d.mts.map +1 -1
  92. package/dist/tests/messenger-mock.mjs +3 -0
  93. package/dist/tests/messenger-mock.mjs.map +1 -1
  94. package/dist/types.cjs.map +1 -1
  95. package/dist/types.d.cts +11 -0
  96. package/dist/types.d.cts.map +1 -1
  97. package/dist/types.d.mts +11 -0
  98. package/dist/types.d.mts.map +1 -1
  99. package/dist/types.mjs.map +1 -1
  100. package/dist/utils/feature-flags.cjs +7 -1
  101. package/dist/utils/feature-flags.cjs.map +1 -1
  102. package/dist/utils/feature-flags.d.cts +1 -0
  103. package/dist/utils/feature-flags.d.cts.map +1 -1
  104. package/dist/utils/feature-flags.d.mts +1 -0
  105. package/dist/utils/feature-flags.d.mts.map +1 -1
  106. package/dist/utils/feature-flags.mjs +5 -0
  107. package/dist/utils/feature-flags.mjs.map +1 -1
  108. package/dist/utils/quotes.cjs +6 -4
  109. package/dist/utils/quotes.cjs.map +1 -1
  110. package/dist/utils/quotes.d.cts.map +1 -1
  111. package/dist/utils/quotes.d.mts.map +1 -1
  112. package/dist/utils/quotes.mjs +6 -4
  113. package/dist/utils/quotes.mjs.map +1 -1
  114. package/package.json +2 -2
@@ -1,68 +1,61 @@
1
1
  import { createModuleLogger } from "@metamask/utils";
2
2
  import { BigNumber } from "bignumber.js";
3
- import { NATIVE_TOKEN_ADDRESS, PaymentOverride, TransactionPayStrategy } from "../../constants.mjs";
3
+ import { NATIVE_TOKEN_ADDRESS, TransactionPayStrategy } from "../../constants.mjs";
4
4
  import { projectLogger } from "../../logger.mjs";
5
5
  import { getDirectMoneyMusdEnabled } from "../../utils/feature-flags.mjs";
6
6
  import { buildCaipAssetType, computeRawFromFiatAmount, getTokenFiatRate, getTokenInfo } from "../../utils/token.mjs";
7
7
  import { getRelayQuotes } from "../relay/relay-quotes.mjs";
8
- import { DEFAULT_FIAT_CURRENCY, MUSD_MONAD_FIAT_ASSET, MUSD_PROBE_AMOUNT_USD } from "./constants.mjs";
9
- import { deriveFiatAssetForFiatPayment, isMoneyAccountDepositTransaction } from "./utils.mjs";
8
+ import { getDirectMusdFiatQuote } from "./fiat-direct-musd.mjs";
9
+ import { deriveFiatAssetForFiatPayment, getRampsQuote, isMoneyAccountDepositTransaction } from "./utils.mjs";
10
10
  const log = createModuleLogger(projectLogger, 'fiat-strategy');
11
11
  /**
12
12
  * Fetches MM Pay fiat strategy quotes using a relay-first estimation flow.
13
13
  *
14
14
  * When the direct-to-mUSD flag is enabled and the transaction is a Money
15
- * Account deposit, probes ramps for mUSD availability on Monad. If viable,
16
- * uses direct mUSD params (asset, wallet, recipient); otherwise falls back
17
- * to the standard ETH flow. Both paths share a single quote pipeline.
15
+ * Account deposit, uses direct mUSD params (asset, wallet, recipient).
16
+ * Otherwise, uses the standard ETH flow.
18
17
  *
19
18
  * @param request - Strategy quotes request.
20
19
  * @returns A single combined fiat strategy quote, or an empty array when inputs/quotes are unavailable.
21
20
  */
22
21
  export async function getFiatQuotes(request) {
23
22
  const { messenger, transaction } = request;
23
+ const state = messenger.call('TransactionPayController:getState');
24
+ const transactionData = state.transactionData[transaction.id];
25
+ const amountFiat = transactionData?.fiatPayment?.amountFiat;
26
+ const requiredTokens = transactionData?.tokens ?? [];
27
+ if (!amountFiat ||
28
+ !request.fiatPaymentMethod ||
29
+ requiredTokens.length !== 1) {
30
+ return [];
31
+ }
24
32
  const useDirectMusd = getDirectMoneyMusdEnabled(messenger) &&
25
33
  isMoneyAccountDepositTransaction(transaction);
26
34
  if (useDirectMusd) {
27
- const moneyAccountAddress = transaction.txParams.from;
28
- const probeOk = await probeMusdFiatAvailability({
35
+ const requiredToken = requiredTokens[0];
36
+ const directQuote = await getDirectMusdFiatQuote({
37
+ amountFiat,
38
+ fiatPaymentMethod: request.fiatPaymentMethod,
29
39
  messenger,
30
- walletAddress: moneyAccountAddress,
40
+ moneyAccountAddress: transaction.txParams.from,
41
+ requiredToken,
42
+ transactionId: transaction.id,
31
43
  });
32
- if (probeOk) {
33
- const directResult = await executeFiatQuotePipeline(request, {
34
- fiatAsset: MUSD_MONAD_FIAT_ASSET,
35
- rampsWalletAddress: moneyAccountAddress,
36
- relayRequestOverrides: {
37
- paymentOverride: PaymentOverride.MoneyAccount,
38
- recipient: moneyAccountAddress,
39
- },
40
- });
41
- if (directResult.length > 0) {
42
- return directResult;
43
- }
44
- }
44
+ return directQuote ? [directQuote] : [];
45
45
  }
46
46
  return executeFiatQuotePipeline(request, {
47
+ amountFiat,
47
48
  fiatAsset: deriveFiatAssetForFiatPayment(transaction, messenger),
49
+ fiatPaymentMethod: request.fiatPaymentMethod,
48
50
  rampsWalletAddress: request.from,
51
+ requiredTokens,
49
52
  });
50
53
  }
51
54
  async function executeFiatQuotePipeline(request, options) {
52
- const { accountSupports7702, fiatPaymentMethod, from: walletAddress, messenger, transaction, } = request;
53
- const { fiatAsset, rampsWalletAddress, relayRequestOverrides } = options;
55
+ const { accountSupports7702, from: walletAddress, messenger, transaction, } = request;
56
+ const { amountFiat, fiatAsset, fiatPaymentMethod, rampsWalletAddress, requiredTokens, } = options;
54
57
  const transactionId = transaction.id;
55
- const state = messenger.call('TransactionPayController:getState');
56
- const transactionData = state.transactionData[transactionId];
57
- const amountFiat = transactionData?.fiatPayment?.amountFiat;
58
- const requiredTokens = transactionData?.tokens ?? [];
59
- if (!amountFiat || !fiatPaymentMethod || !requiredTokens.length) {
60
- return [];
61
- }
62
58
  try {
63
- if (requiredTokens.length > 1) {
64
- throw new Error('Multiple required tokens not supported for fiat strategy');
65
- }
66
59
  const requiredToken = requiredTokens[0];
67
60
  const relayRequest = buildRelayRequestFromAmountFiat({
68
61
  amountFiat,
@@ -74,14 +67,11 @@ async function executeFiatQuotePipeline(request, options) {
74
67
  if (!relayRequest) {
75
68
  throw new Error('Failed to build relay request from fiat amount');
76
69
  }
77
- const finalRelayRequest = relayRequestOverrides
78
- ? { ...relayRequest, ...relayRequestOverrides }
79
- : relayRequest;
80
70
  const relayQuotes = await getRelayQuotes({
81
71
  accountSupports7702,
82
72
  from: walletAddress,
83
73
  messenger,
84
- requests: [finalRelayRequest],
74
+ requests: [relayRequest],
85
75
  transaction,
86
76
  });
87
77
  const relayQuote = relayQuotes[0];
@@ -107,7 +97,6 @@ async function executeFiatQuotePipeline(request, options) {
107
97
  log('Fiat quote flow', {
108
98
  adjustedAmountFiat: adjustedAmountFiat.toString(10),
109
99
  amountFiat,
110
- isDirectMusd: Boolean(relayRequestOverrides),
111
100
  rampsWalletAddress,
112
101
  relayTotalFeeUsd: relayTotalFeeUsd.toString(10),
113
102
  sourceAmountRaw: relayRequest.sourceTokenAmount,
@@ -147,47 +136,6 @@ async function executeFiatQuotePipeline(request, options) {
147
136
  }
148
137
  return [];
149
138
  }
150
- async function probeMusdFiatAvailability({ messenger, walletAddress, }) {
151
- try {
152
- const quotes = await messenger.call('RampsController:getQuotes', {
153
- amount: MUSD_PROBE_AMOUNT_USD,
154
- assetId: buildCaipAssetType(MUSD_MONAD_FIAT_ASSET.chainId, MUSD_MONAD_FIAT_ASSET.address),
155
- autoSelectProvider: true,
156
- fiat: DEFAULT_FIAT_CURRENCY,
157
- restrictToKnownOrNativeProviders: true,
158
- walletAddress,
159
- });
160
- const isAvailable = (quotes.success?.length ?? 0) > 0;
161
- log('mUSD fiat probe result', {
162
- isAvailable,
163
- providerCount: quotes.success?.length ?? 0,
164
- });
165
- return isAvailable;
166
- }
167
- catch (error) {
168
- log('mUSD fiat probe failed', { error });
169
- return false;
170
- }
171
- }
172
- async function getRampsQuote({ adjustedAmount, fiatAsset, fiatPaymentMethod, messenger, walletAddress, }) {
173
- const quotes = await messenger.call('RampsController:getQuotes', {
174
- amount: adjustedAmount,
175
- assetId: buildCaipAssetType(fiatAsset.chainId, fiatAsset.address),
176
- autoSelectProvider: true,
177
- fiat: DEFAULT_FIAT_CURRENCY,
178
- paymentMethods: [fiatPaymentMethod],
179
- restrictToKnownOrNativeProviders: true,
180
- walletAddress,
181
- });
182
- log('Fetched ramps quotes', {
183
- quotesCount: quotes.success?.length ?? 0,
184
- });
185
- const quote = quotes.success?.[0];
186
- if (!quote) {
187
- throw new Error('No matching ramps quote found for selected provider');
188
- }
189
- return quote;
190
- }
191
139
  function buildRelayRequestFromAmountFiat({ amountFiat, fiatAsset, messenger, requiredToken, walletAddress, }) {
192
140
  const sourceFiatRate = getTokenFiatRate(messenger, fiatAsset.address, fiatAsset.chainId);
193
141
  if (!sourceFiatRate) {
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-quotes.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Quote as RampsQuote } from '@metamask/ramps-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n NATIVE_TOKEN_ADDRESS,\n PaymentOverride,\n TransactionPayStrategy,\n} from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionFiatPayment,\n TransactionPayRequiredToken,\n TransactionPayQuote,\n} from '../../types';\nimport { getDirectMoneyMusdEnabled } from '../../utils/feature-flags';\nimport {\n buildCaipAssetType,\n computeRawFromFiatAmount,\n getTokenFiatRate,\n getTokenInfo,\n} from '../../utils/token';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport type { RelayQuote } from '../relay/types';\nimport {\n DEFAULT_FIAT_CURRENCY,\n MUSD_MONAD_FIAT_ASSET,\n MUSD_PROBE_AMOUNT_USD,\n} from './constants';\nimport type { TransactionPayFiatAsset } from './constants';\nimport type { FiatQuote } from './types';\nimport {\n deriveFiatAssetForFiatPayment,\n isMoneyAccountDepositTransaction,\n} from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-strategy');\n\n/**\n * Fetches MM Pay fiat strategy quotes using a relay-first estimation flow.\n *\n * When the direct-to-mUSD flag is enabled and the transaction is a Money\n * Account deposit, probes ramps for mUSD availability on Monad. If viable,\n * uses direct mUSD params (asset, wallet, recipient); otherwise falls back\n * to the standard ETH flow. Both paths share a single quote pipeline.\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 useDirectMusd =\n getDirectMoneyMusdEnabled(messenger) &&\n isMoneyAccountDepositTransaction(transaction);\n\n if (useDirectMusd) {\n const moneyAccountAddress = transaction.txParams.from as Hex;\n\n const probeOk = await probeMusdFiatAvailability({\n messenger,\n walletAddress: moneyAccountAddress,\n });\n\n if (probeOk) {\n const directResult = await executeFiatQuotePipeline(request, {\n fiatAsset: MUSD_MONAD_FIAT_ASSET,\n rampsWalletAddress: moneyAccountAddress,\n relayRequestOverrides: {\n paymentOverride: PaymentOverride.MoneyAccount,\n recipient: moneyAccountAddress,\n },\n });\n\n if (directResult.length > 0) {\n return directResult;\n }\n }\n }\n\n return executeFiatQuotePipeline(request, {\n fiatAsset: deriveFiatAssetForFiatPayment(transaction, messenger),\n rampsWalletAddress: request.from,\n });\n}\n\ntype FiatQuotePipelineOptions = {\n fiatAsset: TransactionPayFiatAsset;\n rampsWalletAddress: Hex;\n relayRequestOverrides?: Partial<QuoteRequest>;\n};\n\nasync function executeFiatQuotePipeline(\n request: PayStrategyGetQuotesRequest,\n options: FiatQuotePipelineOptions,\n): Promise<TransactionPayQuote<FiatQuote>[]> {\n const {\n accountSupports7702,\n fiatPaymentMethod,\n from: walletAddress,\n messenger,\n transaction,\n } = request;\n const { fiatAsset, rampsWalletAddress, relayRequestOverrides } = options;\n const transactionId = transaction.id;\n\n const state = messenger.call('TransactionPayController:getState');\n const transactionData = state.transactionData[transactionId];\n const amountFiat = transactionData?.fiatPayment?.amountFiat;\n const requiredTokens = transactionData?.tokens ?? [];\n\n if (!amountFiat || !fiatPaymentMethod || !requiredTokens.length) {\n return [];\n }\n\n try {\n if (requiredTokens.length > 1) {\n throw new Error(\n 'Multiple required tokens not supported for fiat strategy',\n );\n }\n\n const requiredToken = requiredTokens[0];\n\n const relayRequest = buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n });\n\n if (!relayRequest) {\n throw new Error('Failed to build relay request from fiat amount');\n }\n\n const finalRelayRequest = relayRequestOverrides\n ? { ...relayRequest, ...relayRequestOverrides }\n : relayRequest;\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702,\n from: walletAddress,\n messenger,\n requests: [finalRelayRequest],\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 isDirectMusd: Boolean(relayRequestOverrides),\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\nasync function probeMusdFiatAvailability({\n messenger,\n walletAddress,\n}: {\n messenger: PayStrategyGetQuotesRequest['messenger'];\n walletAddress: string;\n}): Promise<boolean> {\n try {\n const quotes = await messenger.call('RampsController:getQuotes', {\n amount: MUSD_PROBE_AMOUNT_USD,\n assetId: buildCaipAssetType(\n MUSD_MONAD_FIAT_ASSET.chainId,\n MUSD_MONAD_FIAT_ASSET.address,\n ),\n autoSelectProvider: true,\n fiat: DEFAULT_FIAT_CURRENCY,\n restrictToKnownOrNativeProviders: true,\n walletAddress,\n });\n\n const isAvailable = (quotes.success?.length ?? 0) > 0;\n\n log('mUSD fiat probe result', {\n isAvailable,\n providerCount: quotes.success?.length ?? 0,\n });\n\n return isAvailable;\n } catch (error) {\n log('mUSD fiat probe failed', { error });\n return false;\n }\n}\n\nasync function getRampsQuote({\n adjustedAmount,\n fiatAsset,\n fiatPaymentMethod,\n messenger,\n walletAddress,\n}: {\n adjustedAmount: number;\n fiatAsset: TransactionPayFiatAsset;\n fiatPaymentMethod: string;\n messenger: PayStrategyGetQuotesRequest['messenger'];\n walletAddress: string;\n}): Promise<RampsQuote> {\n const quotes = await messenger.call('RampsController:getQuotes', {\n amount: adjustedAmount,\n assetId: buildCaipAssetType(fiatAsset.chainId, fiatAsset.address),\n autoSelectProvider: true,\n fiat: DEFAULT_FIAT_CURRENCY,\n paymentMethods: [fiatPaymentMethod],\n restrictToKnownOrNativeProviders: true,\n walletAddress,\n });\n\n log('Fetched ramps quotes', {\n quotesCount: quotes.success?.length ?? 0,\n });\n\n const quote = quotes.success?.[0];\n\n if (!quote) {\n throw new Error('No matching ramps quote found for selected provider');\n }\n\n return quote;\n}\n\nfunction buildRelayRequestFromAmountFiat({\n amountFiat,\n fiatAsset,\n messenger,\n requiredToken,\n walletAddress,\n}: {\n amountFiat: string;\n fiatAsset: {\n address: Hex;\n chainId: Hex;\n };\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.\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.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Quote as RampsQuote } from '@metamask/ramps-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { NATIVE_TOKEN_ADDRESS, TransactionPayStrategy } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionFiatPayment,\n TransactionPayRequiredToken,\n TransactionPayQuote,\n} from '../../types';\nimport { getDirectMoneyMusdEnabled } from '../../utils/feature-flags';\nimport {\n buildCaipAssetType,\n computeRawFromFiatAmount,\n getTokenFiatRate,\n getTokenInfo,\n} from '../../utils/token';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport type { RelayQuote } from '../relay/types';\nimport type { TransactionPayFiatAsset } from './constants';\nimport { getDirectMusdFiatQuote } from './fiat-direct-musd';\nimport type { FiatQuote } from './types';\nimport {\n deriveFiatAssetForFiatPayment,\n getRampsQuote,\n isMoneyAccountDepositTransaction,\n} from './utils';\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.\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"]}
@@ -23,6 +23,9 @@ async function submitSimpleRelay({ baseRequest, request, sourceAmountRaw, transa
23
23
  const { messenger } = request;
24
24
  const transactionId = transaction.id;
25
25
  const originalRelayQuote = request.quotes[0].original.relayQuote;
26
+ if (!originalRelayQuote) {
27
+ throw new Error('Missing Relay quote for fiat submission');
28
+ }
26
29
  const relayRequest = {
27
30
  ...baseRequest,
28
31
  isMaxAmount: false,
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-submit-simple.cjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-simple.ts"],"names":[],"mappings":";;;AACA,2CAAqD;AAErD,6CAA6C;AAE7C,iEAAuE;AACvE,4DAAuD;AACvD,4DAA0D;AAE1D,uCAAiD;AAEjD,MAAM,GAAG,GAAG,IAAA,0BAAkB,EAAC,sBAAa,EAAE,oBAAoB,CAAC,CAAC;AAEpE;;;;;;;;;;GAUG;AACI,KAAK,UAAU,iBAAiB,CAAC,EACtC,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GAMZ;IACC,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC9B,MAAM,aAAa,GAAG,WAAW,CAAC,EAAE,CAAC;IAErC,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;IAEjE,MAAM,YAAY,GAAiB;QACjC,GAAG,WAAW;QACd,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,IAAI;QACjB,uBAAuB,EAAE,KAAK;QAC9B,gBAAgB,EAAE,eAAe;QACjC,iBAAiB,EAAE,eAAe;KACnC,CAAC;IAEF,MAAM,WAAW,GAAG,MAAM,IAAA,6BAAc,EAAC;QACvC,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,SAAS;QACT,QAAQ,EAAE,CAAC,YAAY,CAAC;QACxB,WAAW;KACZ,CAAC,CAAC;IAEH,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,IAAA,8BAAsB,EAAC;QACrB,aAAa,EAAE,kBAAkB;QACjC,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ;QACvC,mBAAmB,EAAE,IAAA,0CAA0B,EAAC,SAAS,CAAC;QAC1D,aAAa;KACd,CAAC,CAAC;IAEH,GAAG,CAAC,+CAA+C,EAAE;QACnD,eAAe,EAAE,WAAW,CAAC,MAAM;QACnC,aAAa;KACd,CAAC,CAAC;IAEH,OAAO,MAAM,IAAA,gCAAiB,EAAC;QAC7B,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,SAAS;QACT,MAAM,EAAE,WAAW;QACnB,WAAW;KACZ,CAAC,CAAC;AACL,CAAC;AAxDD,8CAwDC","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { projectLogger } from '../../logger';\nimport type { PayStrategyExecuteRequest, QuoteRequest } from '../../types';\nimport { getFiatMaxRateDriftPercent } from '../../utils/feature-flags';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport { submitRelayQuotes } from '../relay/relay-submit';\nimport type { FiatQuote } from './types';\nimport { validateRelayRateDrift } from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-submit-simple');\n\n/**\n * Submits a single EXACT_INPUT relay quote for simple deposits\n * that don't require nested calldata re-encoding or delegation.\n *\n * @param options - The submission options.\n * @param options.baseRequest - The base quote request from the original fiat quote.\n * @param options.request - The original fiat strategy execute request.\n * @param options.sourceAmountRaw - The settled source amount in atomic units.\n * @param options.transaction - The transaction metadata.\n * @returns An object containing the relay transaction hash if available.\n */\nexport async function submitSimpleRelay({\n baseRequest,\n request,\n sourceAmountRaw,\n transaction,\n}: {\n baseRequest: QuoteRequest;\n request: PayStrategyExecuteRequest<FiatQuote>;\n sourceAmountRaw: string;\n transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger } = request;\n const transactionId = transaction.id;\n\n const originalRelayQuote = request.quotes[0].original.relayQuote;\n\n const relayRequest: QuoteRequest = {\n ...baseRequest,\n isMaxAmount: false,\n isPostQuote: true,\n skipProcessTransactions: false,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: sourceAmountRaw,\n };\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n from: baseRequest.from,\n messenger,\n requests: [relayRequest],\n transaction,\n });\n\n if (!relayQuotes.length) {\n throw new Error('No relay quotes returned for completed fiat order');\n }\n\n validateRelayRateDrift({\n originalQuote: originalRelayQuote,\n discoveryQuote: relayQuotes[0].original,\n maxRateDriftPercent: getFiatMaxRateDriftPercent(messenger),\n transactionId,\n });\n\n log('Submitting simple relay after fiat settlement', {\n relayQuoteCount: relayQuotes.length,\n transactionId,\n });\n\n return await submitRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n isSmartTransaction: request.isSmartTransaction,\n messenger,\n quotes: relayQuotes,\n transaction,\n });\n}\n"]}
1
+ {"version":3,"file":"fiat-submit-simple.cjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-simple.ts"],"names":[],"mappings":";;;AACA,2CAAqD;AAErD,6CAA6C;AAE7C,iEAAuE;AACvE,4DAAuD;AACvD,4DAA0D;AAE1D,uCAAiD;AAEjD,MAAM,GAAG,GAAG,IAAA,0BAAkB,EAAC,sBAAa,EAAE,oBAAoB,CAAC,CAAC;AAEpE;;;;;;;;;;GAUG;AACI,KAAK,UAAU,iBAAiB,CAAC,EACtC,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GAMZ;IACC,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC9B,MAAM,aAAa,GAAG,WAAW,CAAC,EAAE,CAAC;IAErC,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;IAEjE,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,YAAY,GAAiB;QACjC,GAAG,WAAW;QACd,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,IAAI;QACjB,uBAAuB,EAAE,KAAK;QAC9B,gBAAgB,EAAE,eAAe;QACjC,iBAAiB,EAAE,eAAe;KACnC,CAAC;IAEF,MAAM,WAAW,GAAG,MAAM,IAAA,6BAAc,EAAC;QACvC,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,SAAS;QACT,QAAQ,EAAE,CAAC,YAAY,CAAC;QACxB,WAAW;KACZ,CAAC,CAAC;IAEH,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,IAAA,8BAAsB,EAAC;QACrB,aAAa,EAAE,kBAAkB;QACjC,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ;QACvC,mBAAmB,EAAE,IAAA,0CAA0B,EAAC,SAAS,CAAC;QAC1D,aAAa;KACd,CAAC,CAAC;IAEH,GAAG,CAAC,+CAA+C,EAAE;QACnD,eAAe,EAAE,WAAW,CAAC,MAAM;QACnC,aAAa;KACd,CAAC,CAAC;IAEH,OAAO,MAAM,IAAA,gCAAiB,EAAC;QAC7B,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,SAAS;QACT,MAAM,EAAE,WAAW;QACnB,WAAW;KACZ,CAAC,CAAC;AACL,CAAC;AA5DD,8CA4DC","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { projectLogger } from '../../logger';\nimport type { PayStrategyExecuteRequest, QuoteRequest } from '../../types';\nimport { getFiatMaxRateDriftPercent } from '../../utils/feature-flags';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport { submitRelayQuotes } from '../relay/relay-submit';\nimport type { FiatQuote } from './types';\nimport { validateRelayRateDrift } from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-submit-simple');\n\n/**\n * Submits a single EXACT_INPUT relay quote for simple deposits\n * that don't require nested calldata re-encoding or delegation.\n *\n * @param options - The submission options.\n * @param options.baseRequest - The base quote request from the original fiat quote.\n * @param options.request - The original fiat strategy execute request.\n * @param options.sourceAmountRaw - The settled source amount in atomic units.\n * @param options.transaction - The transaction metadata.\n * @returns An object containing the relay transaction hash if available.\n */\nexport async function submitSimpleRelay({\n baseRequest,\n request,\n sourceAmountRaw,\n transaction,\n}: {\n baseRequest: QuoteRequest;\n request: PayStrategyExecuteRequest<FiatQuote>;\n sourceAmountRaw: string;\n transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger } = request;\n const transactionId = transaction.id;\n\n const originalRelayQuote = request.quotes[0].original.relayQuote;\n\n if (!originalRelayQuote) {\n throw new Error('Missing Relay quote for fiat submission');\n }\n\n const relayRequest: QuoteRequest = {\n ...baseRequest,\n isMaxAmount: false,\n isPostQuote: true,\n skipProcessTransactions: false,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: sourceAmountRaw,\n };\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n from: baseRequest.from,\n messenger,\n requests: [relayRequest],\n transaction,\n });\n\n if (!relayQuotes.length) {\n throw new Error('No relay quotes returned for completed fiat order');\n }\n\n validateRelayRateDrift({\n originalQuote: originalRelayQuote,\n discoveryQuote: relayQuotes[0].original,\n maxRateDriftPercent: getFiatMaxRateDriftPercent(messenger),\n transactionId,\n });\n\n log('Submitting simple relay after fiat settlement', {\n relayQuoteCount: relayQuotes.length,\n transactionId,\n });\n\n return await submitRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n isSmartTransaction: request.isSmartTransaction,\n messenger,\n quotes: relayQuotes,\n transaction,\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-submit-simple.d.cts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-simple.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAE,yBAAyB,EAAE,YAAY,EAAE,wBAAoB;AAI3E,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,YAAY,CAAC;IAC1B,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC;CAClE,GAAG,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CA8CrC"}
1
+ {"version":3,"file":"fiat-submit-simple.d.cts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-simple.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAE,yBAAyB,EAAE,YAAY,EAAE,wBAAoB;AAI3E,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,YAAY,CAAC;IAC1B,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC;CAClE,GAAG,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAkDrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-submit-simple.d.mts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-simple.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAE,yBAAyB,EAAE,YAAY,EAAE,wBAAoB;AAI3E,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,YAAY,CAAC;IAC1B,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC;CAClE,GAAG,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CA8CrC"}
1
+ {"version":3,"file":"fiat-submit-simple.d.mts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-simple.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAE,yBAAyB,EAAE,YAAY,EAAE,wBAAoB;AAI3E,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,YAAY,CAAC;IAC1B,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC;CAClE,GAAG,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAkDrC"}
@@ -20,6 +20,9 @@ export async function submitSimpleRelay({ baseRequest, request, sourceAmountRaw,
20
20
  const { messenger } = request;
21
21
  const transactionId = transaction.id;
22
22
  const originalRelayQuote = request.quotes[0].original.relayQuote;
23
+ if (!originalRelayQuote) {
24
+ throw new Error('Missing Relay quote for fiat submission');
25
+ }
23
26
  const relayRequest = {
24
27
  ...baseRequest,
25
28
  isMaxAmount: false,
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-submit-simple.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-simple.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AAErD,OAAO,EAAE,aAAa,EAAE,yBAAqB;AAE7C,OAAO,EAAE,0BAA0B,EAAE,sCAAkC;AACvE,OAAO,EAAE,cAAc,EAAE,kCAA8B;AACvD,OAAO,EAAE,iBAAiB,EAAE,kCAA8B;AAE1D,OAAO,EAAE,sBAAsB,EAAE,oBAAgB;AAEjD,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,oBAAoB,CAAC,CAAC;AAEpE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EACtC,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GAMZ;IACC,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC9B,MAAM,aAAa,GAAG,WAAW,CAAC,EAAE,CAAC;IAErC,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;IAEjE,MAAM,YAAY,GAAiB;QACjC,GAAG,WAAW;QACd,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,IAAI;QACjB,uBAAuB,EAAE,KAAK;QAC9B,gBAAgB,EAAE,eAAe;QACjC,iBAAiB,EAAE,eAAe;KACnC,CAAC;IAEF,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC;QACvC,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,SAAS;QACT,QAAQ,EAAE,CAAC,YAAY,CAAC;QACxB,WAAW;KACZ,CAAC,CAAC;IAEH,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,sBAAsB,CAAC;QACrB,aAAa,EAAE,kBAAkB;QACjC,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ;QACvC,mBAAmB,EAAE,0BAA0B,CAAC,SAAS,CAAC;QAC1D,aAAa;KACd,CAAC,CAAC;IAEH,GAAG,CAAC,+CAA+C,EAAE;QACnD,eAAe,EAAE,WAAW,CAAC,MAAM;QACnC,aAAa;KACd,CAAC,CAAC;IAEH,OAAO,MAAM,iBAAiB,CAAC;QAC7B,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,SAAS;QACT,MAAM,EAAE,WAAW;QACnB,WAAW;KACZ,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { projectLogger } from '../../logger';\nimport type { PayStrategyExecuteRequest, QuoteRequest } from '../../types';\nimport { getFiatMaxRateDriftPercent } from '../../utils/feature-flags';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport { submitRelayQuotes } from '../relay/relay-submit';\nimport type { FiatQuote } from './types';\nimport { validateRelayRateDrift } from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-submit-simple');\n\n/**\n * Submits a single EXACT_INPUT relay quote for simple deposits\n * that don't require nested calldata re-encoding or delegation.\n *\n * @param options - The submission options.\n * @param options.baseRequest - The base quote request from the original fiat quote.\n * @param options.request - The original fiat strategy execute request.\n * @param options.sourceAmountRaw - The settled source amount in atomic units.\n * @param options.transaction - The transaction metadata.\n * @returns An object containing the relay transaction hash if available.\n */\nexport async function submitSimpleRelay({\n baseRequest,\n request,\n sourceAmountRaw,\n transaction,\n}: {\n baseRequest: QuoteRequest;\n request: PayStrategyExecuteRequest<FiatQuote>;\n sourceAmountRaw: string;\n transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger } = request;\n const transactionId = transaction.id;\n\n const originalRelayQuote = request.quotes[0].original.relayQuote;\n\n const relayRequest: QuoteRequest = {\n ...baseRequest,\n isMaxAmount: false,\n isPostQuote: true,\n skipProcessTransactions: false,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: sourceAmountRaw,\n };\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n from: baseRequest.from,\n messenger,\n requests: [relayRequest],\n transaction,\n });\n\n if (!relayQuotes.length) {\n throw new Error('No relay quotes returned for completed fiat order');\n }\n\n validateRelayRateDrift({\n originalQuote: originalRelayQuote,\n discoveryQuote: relayQuotes[0].original,\n maxRateDriftPercent: getFiatMaxRateDriftPercent(messenger),\n transactionId,\n });\n\n log('Submitting simple relay after fiat settlement', {\n relayQuoteCount: relayQuotes.length,\n transactionId,\n });\n\n return await submitRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n isSmartTransaction: request.isSmartTransaction,\n messenger,\n quotes: relayQuotes,\n transaction,\n });\n}\n"]}
1
+ {"version":3,"file":"fiat-submit-simple.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-simple.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AAErD,OAAO,EAAE,aAAa,EAAE,yBAAqB;AAE7C,OAAO,EAAE,0BAA0B,EAAE,sCAAkC;AACvE,OAAO,EAAE,cAAc,EAAE,kCAA8B;AACvD,OAAO,EAAE,iBAAiB,EAAE,kCAA8B;AAE1D,OAAO,EAAE,sBAAsB,EAAE,oBAAgB;AAEjD,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,oBAAoB,CAAC,CAAC;AAEpE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EACtC,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GAMZ;IACC,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC9B,MAAM,aAAa,GAAG,WAAW,CAAC,EAAE,CAAC;IAErC,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;IAEjE,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,YAAY,GAAiB;QACjC,GAAG,WAAW;QACd,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,IAAI;QACjB,uBAAuB,EAAE,KAAK;QAC9B,gBAAgB,EAAE,eAAe;QACjC,iBAAiB,EAAE,eAAe;KACnC,CAAC;IAEF,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC;QACvC,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,SAAS;QACT,QAAQ,EAAE,CAAC,YAAY,CAAC;QACxB,WAAW;KACZ,CAAC,CAAC;IAEH,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,sBAAsB,CAAC;QACrB,aAAa,EAAE,kBAAkB;QACjC,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ;QACvC,mBAAmB,EAAE,0BAA0B,CAAC,SAAS,CAAC;QAC1D,aAAa;KACd,CAAC,CAAC;IAEH,GAAG,CAAC,+CAA+C,EAAE;QACnD,eAAe,EAAE,WAAW,CAAC,MAAM;QACnC,aAAa;KACd,CAAC,CAAC;IAEH,OAAO,MAAM,iBAAiB,CAAC;QAC7B,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,SAAS;QACT,MAAM,EAAE,WAAW;QACnB,WAAW;KACZ,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { projectLogger } from '../../logger';\nimport type { PayStrategyExecuteRequest, QuoteRequest } from '../../types';\nimport { getFiatMaxRateDriftPercent } from '../../utils/feature-flags';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport { submitRelayQuotes } from '../relay/relay-submit';\nimport type { FiatQuote } from './types';\nimport { validateRelayRateDrift } from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-submit-simple');\n\n/**\n * Submits a single EXACT_INPUT relay quote for simple deposits\n * that don't require nested calldata re-encoding or delegation.\n *\n * @param options - The submission options.\n * @param options.baseRequest - The base quote request from the original fiat quote.\n * @param options.request - The original fiat strategy execute request.\n * @param options.sourceAmountRaw - The settled source amount in atomic units.\n * @param options.transaction - The transaction metadata.\n * @returns An object containing the relay transaction hash if available.\n */\nexport async function submitSimpleRelay({\n baseRequest,\n request,\n sourceAmountRaw,\n transaction,\n}: {\n baseRequest: QuoteRequest;\n request: PayStrategyExecuteRequest<FiatQuote>;\n sourceAmountRaw: string;\n transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger } = request;\n const transactionId = transaction.id;\n\n const originalRelayQuote = request.quotes[0].original.relayQuote;\n\n if (!originalRelayQuote) {\n throw new Error('Missing Relay quote for fiat submission');\n }\n\n const relayRequest: QuoteRequest = {\n ...baseRequest,\n isMaxAmount: false,\n isPostQuote: true,\n skipProcessTransactions: false,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: sourceAmountRaw,\n };\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n from: baseRequest.from,\n messenger,\n requests: [relayRequest],\n transaction,\n });\n\n if (!relayQuotes.length) {\n throw new Error('No relay quotes returned for completed fiat order');\n }\n\n validateRelayRateDrift({\n originalQuote: originalRelayQuote,\n discoveryQuote: relayQuotes[0].original,\n maxRateDriftPercent: getFiatMaxRateDriftPercent(messenger),\n transactionId,\n });\n\n log('Submitting simple relay after fiat settlement', {\n relayQuoteCount: relayQuotes.length,\n transactionId,\n });\n\n return await submitRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n isSmartTransaction: request.isSmartTransaction,\n messenger,\n quotes: relayQuotes,\n transaction,\n });\n}\n"]}
@@ -28,8 +28,12 @@ const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'fiat-submit
28
28
  async function submitWithTransactionData({ baseRequest, request, sourceAmountRaw, transaction, }) {
29
29
  const { messenger } = request;
30
30
  const transactionId = transaction.id;
31
+ const originalRelayQuote = request.quotes[0].original.relayQuote;
32
+ if (!originalRelayQuote) {
33
+ throw new Error('Missing Relay quote for fiat submission');
34
+ }
31
35
  const feeReserveRaw = calculateFeeReserve({
32
- feeQuote: request.quotes[0].original.relayQuote,
36
+ feeQuote: originalRelayQuote,
33
37
  multiplier: (0, feature_flags_1.getFiatFeeReserveMultiplier)(messenger),
34
38
  });
35
39
  const discoverySourceAmount = bignumber_js_1.BigNumber.max(new bignumber_js_1.BigNumber(sourceAmountRaw).minus(feeReserveRaw), 1).toFixed(0);
@@ -96,7 +100,6 @@ async function submitWithTransactionData({ baseRequest, request, sourceAmountRaw
96
100
  if (!relayQuotes.length) {
97
101
  throw new Error('No relay quotes returned for completed fiat order');
98
102
  }
99
- const originalRelayQuote = request.quotes[0].original.relayQuote;
100
103
  (0, utils_2.validateRelayRateDrift)({
101
104
  originalQuote: originalRelayQuote,
102
105
  discoveryQuote: relayQuotes[0].original,
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-submit-with-transaction-data.cjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-with-transaction-data.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { projectLogger } from '../../logger';\nimport type { PayStrategyExecuteRequest, QuoteRequest } from '../../types';\nimport {\n getFiatFeeReserveMultiplier,\n getFiatMaxRateDriftPercent,\n} from '../../utils/feature-flags';\nimport { getTransaction, updateTransaction } from '../../utils/transaction';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport { submitRelayQuotes } from '../relay/relay-submit';\nimport type { RelayQuote } from '../relay/types';\nimport type { FiatQuote } from './types';\nimport { validateRelayRateDrift } from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-submit-calldata');\n\n/**\n * Submits relay quotes using the three-phase flow for transactions with nested\n * calldata that needs re-encoding (e.g. moneyAccountDeposit with approve + deposit).\n *\n * Phase 1: Discovery quote (EXACT_INPUT) to learn the target token output.\n * Phase 2: Delegate calldata re-encoding to the client via getAmountData.\n * Phase 3: Delegation quote (EXACT_OUTPUT) with updated nested transaction data.\n *\n * @param options - The submission options.\n * @param options.baseRequest - The base quote request from the original fiat quote.\n * @param options.request - The original fiat strategy execute request.\n * @param options.sourceAmountRaw - The settled source amount in atomic units.\n * @param options.transaction - The transaction metadata.\n * @returns An object containing the relay transaction hash if available.\n */\nexport async function submitWithTransactionData({\n baseRequest,\n request,\n sourceAmountRaw,\n transaction,\n}: {\n baseRequest: QuoteRequest;\n request: PayStrategyExecuteRequest<FiatQuote>;\n sourceAmountRaw: string;\n transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger } = request;\n const transactionId = transaction.id;\n\n const feeReserveRaw = calculateFeeReserve({\n feeQuote: request.quotes[0].original.relayQuote,\n multiplier: getFiatFeeReserveMultiplier(messenger),\n });\n\n const discoverySourceAmount = BigNumber.max(\n new BigNumber(sourceAmountRaw).minus(feeReserveRaw),\n 1,\n ).toFixed(0);\n\n log('Fee reserve for discovery', {\n feeReserveRaw: feeReserveRaw.toFixed(0),\n discoverySourceAmount,\n sourceAmountRaw,\n transactionId,\n });\n\n const discoveryRequest: QuoteRequest = {\n ...baseRequest,\n isMaxAmount: false,\n isPostQuote: true,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: discoverySourceAmount,\n };\n\n const discoveryQuotes = await getRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n from: baseRequest.from,\n messenger,\n requests: [discoveryRequest],\n transaction,\n });\n\n if (!discoveryQuotes.length) {\n throw new Error('No relay quotes returned for fiat discovery');\n }\n\n const discoveryRelay = discoveryQuotes[0].original;\n\n const adjustedTargetRaw = calculateAdjustedTarget(discoveryRelay);\n\n log('Adjusted target for final quote', {\n discoveryMinimum: discoveryRelay.details.currencyOut.minimumAmount,\n adjustedTargetRaw,\n transactionId,\n });\n\n const { updates } = await messenger.call(\n 'TransactionPayController:getAmountData',\n { amount: adjustedTargetRaw, transaction },\n );\n\n if (!updates.length) {\n throw new Error(\n 'getAmountData returned no updates for transaction with nested calldata',\n );\n }\n\n updateTransaction(\n { transactionId, messenger, note: 'Fiat deposit: update settled amount' },\n (tx) => {\n for (const { nestedTransactionIndex, data } of updates) {\n if (tx.nestedTransactions?.[nestedTransactionIndex]) {\n tx.nestedTransactions[nestedTransactionIndex].data = data;\n }\n }\n if (tx.requiredAssets?.[0]) {\n tx.requiredAssets[0].amount = `0x${new BigNumber(adjustedTargetRaw).toString(16)}`;\n }\n },\n );\n\n const updatedTransaction =\n getTransaction(transactionId, messenger) ?? transaction;\n\n const relayRequest: QuoteRequest = {\n ...baseRequest,\n isMaxAmount: false,\n isPostQuote: false,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: adjustedTargetRaw,\n };\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n from: baseRequest.from,\n messenger,\n requests: [relayRequest],\n transaction: updatedTransaction,\n });\n\n if (!relayQuotes.length) {\n throw new Error('No relay quotes returned for completed fiat order');\n }\n\n const originalRelayQuote = request.quotes[0].original.relayQuote;\n validateRelayRateDrift({\n originalQuote: originalRelayQuote,\n discoveryQuote: relayQuotes[0].original,\n maxRateDriftPercent: getFiatMaxRateDriftPercent(messenger),\n transactionId,\n });\n\n log('Received relay quotes for completed fiat order', {\n relayQuoteCount: relayQuotes.length,\n transactionId,\n });\n\n return await submitRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n isSmartTransaction: request.isSmartTransaction,\n messenger,\n quotes: relayQuotes,\n transaction: updatedTransaction,\n });\n}\n\n/**\n * Calculates the fee reserve in raw source token units from the original\n * relay fee quote. This reserve is subtracted from the discovery quote's\n * source amount so the final EXACT_OUTPUT quote stays within the settled\n * balance.\n *\n * @param options - Calculation options.\n * @param options.feeQuote - The original relay quote from the fee/quoting phase.\n * @param options.multiplier - Multiplier applied to the fee reserve (default 1).\n * @returns The fee reserve in raw source token units.\n */\nfunction calculateFeeReserve({\n feeQuote,\n multiplier,\n}: {\n feeQuote: RelayQuote;\n multiplier: number;\n}): BigNumber {\n const sourceRaw = new BigNumber(feeQuote.details.currencyIn.amount);\n const sourceUsd = new BigNumber(feeQuote.details.currencyIn.amountUsd);\n const rawImpact = new BigNumber(feeQuote.details.totalImpact.usd);\n const feeUsd = rawImpact.isNegative() ? rawImpact.abs() : new BigNumber(0);\n\n if (!sourceUsd.gt(0) || !sourceRaw.gt(0) || !feeUsd.gt(0)) {\n return new BigNumber(0);\n }\n\n const usdPerSourceRaw = sourceUsd.dividedBy(sourceRaw);\n\n return feeUsd\n .dividedBy(usdPerSourceRaw)\n .multipliedBy(multiplier)\n .decimalPlaces(0, BigNumber.ROUND_UP);\n}\n\n/**\n * Calculates the adjusted target amount for the final EXACT_OUTPUT quote\n * by adding the discovery quote's fee back to its minimum output.\n *\n * The discovery quote (EXACT_INPUT) reports a smaller fee than the final\n * EXACT_OUTPUT quote will charge. Adding the discovery fee back to the\n * minimum output compensates for this differential, ensuring the final\n * quote targets a realistic amount.\n *\n * @param discoveryQuote - The relay quote from the discovery phase.\n * @returns The adjusted target amount in raw target token units.\n */\nfunction calculateAdjustedTarget(discoveryQuote: RelayQuote): string {\n const targetMinRaw = new BigNumber(\n discoveryQuote.details.currencyOut.minimumAmount,\n );\n const targetUsd = new BigNumber(discoveryQuote.details.currencyOut.amountUsd);\n const sourceUsd = new BigNumber(discoveryQuote.details.currencyIn.amountUsd);\n\n if (!targetUsd.gt(0) || !targetMinRaw.gt(0)) {\n return targetMinRaw.toFixed(0);\n }\n\n // Discovery fee in USD\n const discoveryFeeUsd = sourceUsd.minus(targetUsd);\n\n if (!discoveryFeeUsd.gt(0)) {\n return targetMinRaw.toFixed(0);\n }\n\n // Convert fee from USD to raw target token units\n const usdPerTargetRaw = targetUsd.dividedBy(targetMinRaw);\n const discoveryFeeInTargetRaw = discoveryFeeUsd\n .dividedBy(usdPerTargetRaw)\n .decimalPlaces(0, BigNumber.ROUND_DOWN);\n\n const adjusted = targetMinRaw.plus(discoveryFeeInTargetRaw);\n\n log('Adjusted target', {\n targetMinRaw: targetMinRaw.toFixed(0),\n discoveryFeeUsd: discoveryFeeUsd.toFixed(6),\n discoveryFeeInTargetRaw: discoveryFeeInTargetRaw.toFixed(0),\n adjustedTargetRaw: adjusted.toFixed(0),\n });\n\n return adjusted.toFixed(0);\n}\n"]}
1
+ {"version":3,"file":"fiat-submit-with-transaction-data.cjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-with-transaction-data.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { projectLogger } from '../../logger';\nimport type { PayStrategyExecuteRequest, QuoteRequest } from '../../types';\nimport {\n getFiatFeeReserveMultiplier,\n getFiatMaxRateDriftPercent,\n} from '../../utils/feature-flags';\nimport { getTransaction, updateTransaction } from '../../utils/transaction';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport { submitRelayQuotes } from '../relay/relay-submit';\nimport type { RelayQuote } from '../relay/types';\nimport type { FiatQuote } from './types';\nimport { validateRelayRateDrift } from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-submit-calldata');\n\n/**\n * Submits relay quotes using the three-phase flow for transactions with nested\n * calldata that needs re-encoding (e.g. moneyAccountDeposit with approve + deposit).\n *\n * Phase 1: Discovery quote (EXACT_INPUT) to learn the target token output.\n * Phase 2: Delegate calldata re-encoding to the client via getAmountData.\n * Phase 3: Delegation quote (EXACT_OUTPUT) with updated nested transaction data.\n *\n * @param options - The submission options.\n * @param options.baseRequest - The base quote request from the original fiat quote.\n * @param options.request - The original fiat strategy execute request.\n * @param options.sourceAmountRaw - The settled source amount in atomic units.\n * @param options.transaction - The transaction metadata.\n * @returns An object containing the relay transaction hash if available.\n */\nexport async function submitWithTransactionData({\n baseRequest,\n request,\n sourceAmountRaw,\n transaction,\n}: {\n baseRequest: QuoteRequest;\n request: PayStrategyExecuteRequest<FiatQuote>;\n sourceAmountRaw: string;\n transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger } = request;\n const transactionId = transaction.id;\n const originalRelayQuote = request.quotes[0].original.relayQuote;\n\n if (!originalRelayQuote) {\n throw new Error('Missing Relay quote for fiat submission');\n }\n\n const feeReserveRaw = calculateFeeReserve({\n feeQuote: originalRelayQuote,\n multiplier: getFiatFeeReserveMultiplier(messenger),\n });\n\n const discoverySourceAmount = BigNumber.max(\n new BigNumber(sourceAmountRaw).minus(feeReserveRaw),\n 1,\n ).toFixed(0);\n\n log('Fee reserve for discovery', {\n feeReserveRaw: feeReserveRaw.toFixed(0),\n discoverySourceAmount,\n sourceAmountRaw,\n transactionId,\n });\n\n const discoveryRequest: QuoteRequest = {\n ...baseRequest,\n isMaxAmount: false,\n isPostQuote: true,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: discoverySourceAmount,\n };\n\n const discoveryQuotes = await getRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n from: baseRequest.from,\n messenger,\n requests: [discoveryRequest],\n transaction,\n });\n\n if (!discoveryQuotes.length) {\n throw new Error('No relay quotes returned for fiat discovery');\n }\n\n const discoveryRelay = discoveryQuotes[0].original;\n\n const adjustedTargetRaw = calculateAdjustedTarget(discoveryRelay);\n\n log('Adjusted target for final quote', {\n discoveryMinimum: discoveryRelay.details.currencyOut.minimumAmount,\n adjustedTargetRaw,\n transactionId,\n });\n\n const { updates } = await messenger.call(\n 'TransactionPayController:getAmountData',\n { amount: adjustedTargetRaw, transaction },\n );\n\n if (!updates.length) {\n throw new Error(\n 'getAmountData returned no updates for transaction with nested calldata',\n );\n }\n\n updateTransaction(\n { transactionId, messenger, note: 'Fiat deposit: update settled amount' },\n (tx) => {\n for (const { nestedTransactionIndex, data } of updates) {\n if (tx.nestedTransactions?.[nestedTransactionIndex]) {\n tx.nestedTransactions[nestedTransactionIndex].data = data;\n }\n }\n if (tx.requiredAssets?.[0]) {\n tx.requiredAssets[0].amount = `0x${new BigNumber(adjustedTargetRaw).toString(16)}`;\n }\n },\n );\n\n const updatedTransaction =\n getTransaction(transactionId, messenger) ?? transaction;\n\n const relayRequest: QuoteRequest = {\n ...baseRequest,\n isMaxAmount: false,\n isPostQuote: false,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: adjustedTargetRaw,\n };\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n from: baseRequest.from,\n messenger,\n requests: [relayRequest],\n transaction: updatedTransaction,\n });\n\n if (!relayQuotes.length) {\n throw new Error('No relay quotes returned for completed fiat order');\n }\n\n validateRelayRateDrift({\n originalQuote: originalRelayQuote,\n discoveryQuote: relayQuotes[0].original,\n maxRateDriftPercent: getFiatMaxRateDriftPercent(messenger),\n transactionId,\n });\n\n log('Received relay quotes for completed fiat order', {\n relayQuoteCount: relayQuotes.length,\n transactionId,\n });\n\n return await submitRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n isSmartTransaction: request.isSmartTransaction,\n messenger,\n quotes: relayQuotes,\n transaction: updatedTransaction,\n });\n}\n\n/**\n * Calculates the fee reserve in raw source token units from the original\n * relay fee quote. This reserve is subtracted from the discovery quote's\n * source amount so the final EXACT_OUTPUT quote stays within the settled\n * balance.\n *\n * @param options - Calculation options.\n * @param options.feeQuote - The original relay quote from the fee/quoting phase.\n * @param options.multiplier - Multiplier applied to the fee reserve (default 1).\n * @returns The fee reserve in raw source token units.\n */\nfunction calculateFeeReserve({\n feeQuote,\n multiplier,\n}: {\n feeQuote: RelayQuote;\n multiplier: number;\n}): BigNumber {\n const sourceRaw = new BigNumber(feeQuote.details.currencyIn.amount);\n const sourceUsd = new BigNumber(feeQuote.details.currencyIn.amountUsd);\n const rawImpact = new BigNumber(feeQuote.details.totalImpact.usd);\n const feeUsd = rawImpact.isNegative() ? rawImpact.abs() : new BigNumber(0);\n\n if (!sourceUsd.gt(0) || !sourceRaw.gt(0) || !feeUsd.gt(0)) {\n return new BigNumber(0);\n }\n\n const usdPerSourceRaw = sourceUsd.dividedBy(sourceRaw);\n\n return feeUsd\n .dividedBy(usdPerSourceRaw)\n .multipliedBy(multiplier)\n .decimalPlaces(0, BigNumber.ROUND_UP);\n}\n\n/**\n * Calculates the adjusted target amount for the final EXACT_OUTPUT quote\n * by adding the discovery quote's fee back to its minimum output.\n *\n * The discovery quote (EXACT_INPUT) reports a smaller fee than the final\n * EXACT_OUTPUT quote will charge. Adding the discovery fee back to the\n * minimum output compensates for this differential, ensuring the final\n * quote targets a realistic amount.\n *\n * @param discoveryQuote - The relay quote from the discovery phase.\n * @returns The adjusted target amount in raw target token units.\n */\nfunction calculateAdjustedTarget(discoveryQuote: RelayQuote): string {\n const targetMinRaw = new BigNumber(\n discoveryQuote.details.currencyOut.minimumAmount,\n );\n const targetUsd = new BigNumber(discoveryQuote.details.currencyOut.amountUsd);\n const sourceUsd = new BigNumber(discoveryQuote.details.currencyIn.amountUsd);\n\n if (!targetUsd.gt(0) || !targetMinRaw.gt(0)) {\n return targetMinRaw.toFixed(0);\n }\n\n // Discovery fee in USD\n const discoveryFeeUsd = sourceUsd.minus(targetUsd);\n\n if (!discoveryFeeUsd.gt(0)) {\n return targetMinRaw.toFixed(0);\n }\n\n // Convert fee from USD to raw target token units\n const usdPerTargetRaw = targetUsd.dividedBy(targetMinRaw);\n const discoveryFeeInTargetRaw = discoveryFeeUsd\n .dividedBy(usdPerTargetRaw)\n .decimalPlaces(0, BigNumber.ROUND_DOWN);\n\n const adjusted = targetMinRaw.plus(discoveryFeeInTargetRaw);\n\n log('Adjusted target', {\n targetMinRaw: targetMinRaw.toFixed(0),\n discoveryFeeUsd: discoveryFeeUsd.toFixed(6),\n discoveryFeeInTargetRaw: discoveryFeeInTargetRaw.toFixed(0),\n adjustedTargetRaw: adjusted.toFixed(0),\n });\n\n return adjusted.toFixed(0);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-submit-with-transaction-data.d.cts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-with-transaction-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,KAAK,EAAE,yBAAyB,EAAE,YAAY,EAAE,wBAAoB;AAS3E,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,yBAAyB,CAAC,EAC9C,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,YAAY,CAAC;IAC1B,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC;CAClE,GAAG,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAwHrC"}
1
+ {"version":3,"file":"fiat-submit-with-transaction-data.d.cts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-with-transaction-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,KAAK,EAAE,yBAAyB,EAAE,YAAY,EAAE,wBAAoB;AAS3E,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,yBAAyB,CAAC,EAC9C,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,YAAY,CAAC;IAC1B,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC;CAClE,GAAG,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CA4HrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-submit-with-transaction-data.d.mts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-with-transaction-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,KAAK,EAAE,yBAAyB,EAAE,YAAY,EAAE,wBAAoB;AAS3E,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,yBAAyB,CAAC,EAC9C,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,YAAY,CAAC;IAC1B,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC;CAClE,GAAG,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAwHrC"}
1
+ {"version":3,"file":"fiat-submit-with-transaction-data.d.mts","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-with-transaction-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,KAAK,EAAE,yBAAyB,EAAE,YAAY,EAAE,wBAAoB;AAS3E,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAgB;AAKzC;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,yBAAyB,CAAC,EAC9C,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,YAAY,CAAC;IAC1B,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC9C,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC;CAClE,GAAG,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CA4HrC"}
@@ -25,8 +25,12 @@ const log = createModuleLogger(projectLogger, 'fiat-submit-calldata');
25
25
  export async function submitWithTransactionData({ baseRequest, request, sourceAmountRaw, transaction, }) {
26
26
  const { messenger } = request;
27
27
  const transactionId = transaction.id;
28
+ const originalRelayQuote = request.quotes[0].original.relayQuote;
29
+ if (!originalRelayQuote) {
30
+ throw new Error('Missing Relay quote for fiat submission');
31
+ }
28
32
  const feeReserveRaw = calculateFeeReserve({
29
- feeQuote: request.quotes[0].original.relayQuote,
33
+ feeQuote: originalRelayQuote,
30
34
  multiplier: getFiatFeeReserveMultiplier(messenger),
31
35
  });
32
36
  const discoverySourceAmount = BigNumber.max(new BigNumber(sourceAmountRaw).minus(feeReserveRaw), 1).toFixed(0);
@@ -93,7 +97,6 @@ export async function submitWithTransactionData({ baseRequest, request, sourceAm
93
97
  if (!relayQuotes.length) {
94
98
  throw new Error('No relay quotes returned for completed fiat order');
95
99
  }
96
- const originalRelayQuote = request.quotes[0].original.relayQuote;
97
100
  validateRelayRateDrift({
98
101
  originalQuote: originalRelayQuote,
99
102
  discoveryQuote: relayQuotes[0].original,
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-submit-with-transaction-data.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-with-transaction-data.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { projectLogger } from '../../logger';\nimport type { PayStrategyExecuteRequest, QuoteRequest } from '../../types';\nimport {\n getFiatFeeReserveMultiplier,\n getFiatMaxRateDriftPercent,\n} from '../../utils/feature-flags';\nimport { getTransaction, updateTransaction } from '../../utils/transaction';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport { submitRelayQuotes } from '../relay/relay-submit';\nimport type { RelayQuote } from '../relay/types';\nimport type { FiatQuote } from './types';\nimport { validateRelayRateDrift } from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-submit-calldata');\n\n/**\n * Submits relay quotes using the three-phase flow for transactions with nested\n * calldata that needs re-encoding (e.g. moneyAccountDeposit with approve + deposit).\n *\n * Phase 1: Discovery quote (EXACT_INPUT) to learn the target token output.\n * Phase 2: Delegate calldata re-encoding to the client via getAmountData.\n * Phase 3: Delegation quote (EXACT_OUTPUT) with updated nested transaction data.\n *\n * @param options - The submission options.\n * @param options.baseRequest - The base quote request from the original fiat quote.\n * @param options.request - The original fiat strategy execute request.\n * @param options.sourceAmountRaw - The settled source amount in atomic units.\n * @param options.transaction - The transaction metadata.\n * @returns An object containing the relay transaction hash if available.\n */\nexport async function submitWithTransactionData({\n baseRequest,\n request,\n sourceAmountRaw,\n transaction,\n}: {\n baseRequest: QuoteRequest;\n request: PayStrategyExecuteRequest<FiatQuote>;\n sourceAmountRaw: string;\n transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger } = request;\n const transactionId = transaction.id;\n\n const feeReserveRaw = calculateFeeReserve({\n feeQuote: request.quotes[0].original.relayQuote,\n multiplier: getFiatFeeReserveMultiplier(messenger),\n });\n\n const discoverySourceAmount = BigNumber.max(\n new BigNumber(sourceAmountRaw).minus(feeReserveRaw),\n 1,\n ).toFixed(0);\n\n log('Fee reserve for discovery', {\n feeReserveRaw: feeReserveRaw.toFixed(0),\n discoverySourceAmount,\n sourceAmountRaw,\n transactionId,\n });\n\n const discoveryRequest: QuoteRequest = {\n ...baseRequest,\n isMaxAmount: false,\n isPostQuote: true,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: discoverySourceAmount,\n };\n\n const discoveryQuotes = await getRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n from: baseRequest.from,\n messenger,\n requests: [discoveryRequest],\n transaction,\n });\n\n if (!discoveryQuotes.length) {\n throw new Error('No relay quotes returned for fiat discovery');\n }\n\n const discoveryRelay = discoveryQuotes[0].original;\n\n const adjustedTargetRaw = calculateAdjustedTarget(discoveryRelay);\n\n log('Adjusted target for final quote', {\n discoveryMinimum: discoveryRelay.details.currencyOut.minimumAmount,\n adjustedTargetRaw,\n transactionId,\n });\n\n const { updates } = await messenger.call(\n 'TransactionPayController:getAmountData',\n { amount: adjustedTargetRaw, transaction },\n );\n\n if (!updates.length) {\n throw new Error(\n 'getAmountData returned no updates for transaction with nested calldata',\n );\n }\n\n updateTransaction(\n { transactionId, messenger, note: 'Fiat deposit: update settled amount' },\n (tx) => {\n for (const { nestedTransactionIndex, data } of updates) {\n if (tx.nestedTransactions?.[nestedTransactionIndex]) {\n tx.nestedTransactions[nestedTransactionIndex].data = data;\n }\n }\n if (tx.requiredAssets?.[0]) {\n tx.requiredAssets[0].amount = `0x${new BigNumber(adjustedTargetRaw).toString(16)}`;\n }\n },\n );\n\n const updatedTransaction =\n getTransaction(transactionId, messenger) ?? transaction;\n\n const relayRequest: QuoteRequest = {\n ...baseRequest,\n isMaxAmount: false,\n isPostQuote: false,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: adjustedTargetRaw,\n };\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n from: baseRequest.from,\n messenger,\n requests: [relayRequest],\n transaction: updatedTransaction,\n });\n\n if (!relayQuotes.length) {\n throw new Error('No relay quotes returned for completed fiat order');\n }\n\n const originalRelayQuote = request.quotes[0].original.relayQuote;\n validateRelayRateDrift({\n originalQuote: originalRelayQuote,\n discoveryQuote: relayQuotes[0].original,\n maxRateDriftPercent: getFiatMaxRateDriftPercent(messenger),\n transactionId,\n });\n\n log('Received relay quotes for completed fiat order', {\n relayQuoteCount: relayQuotes.length,\n transactionId,\n });\n\n return await submitRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n isSmartTransaction: request.isSmartTransaction,\n messenger,\n quotes: relayQuotes,\n transaction: updatedTransaction,\n });\n}\n\n/**\n * Calculates the fee reserve in raw source token units from the original\n * relay fee quote. This reserve is subtracted from the discovery quote's\n * source amount so the final EXACT_OUTPUT quote stays within the settled\n * balance.\n *\n * @param options - Calculation options.\n * @param options.feeQuote - The original relay quote from the fee/quoting phase.\n * @param options.multiplier - Multiplier applied to the fee reserve (default 1).\n * @returns The fee reserve in raw source token units.\n */\nfunction calculateFeeReserve({\n feeQuote,\n multiplier,\n}: {\n feeQuote: RelayQuote;\n multiplier: number;\n}): BigNumber {\n const sourceRaw = new BigNumber(feeQuote.details.currencyIn.amount);\n const sourceUsd = new BigNumber(feeQuote.details.currencyIn.amountUsd);\n const rawImpact = new BigNumber(feeQuote.details.totalImpact.usd);\n const feeUsd = rawImpact.isNegative() ? rawImpact.abs() : new BigNumber(0);\n\n if (!sourceUsd.gt(0) || !sourceRaw.gt(0) || !feeUsd.gt(0)) {\n return new BigNumber(0);\n }\n\n const usdPerSourceRaw = sourceUsd.dividedBy(sourceRaw);\n\n return feeUsd\n .dividedBy(usdPerSourceRaw)\n .multipliedBy(multiplier)\n .decimalPlaces(0, BigNumber.ROUND_UP);\n}\n\n/**\n * Calculates the adjusted target amount for the final EXACT_OUTPUT quote\n * by adding the discovery quote's fee back to its minimum output.\n *\n * The discovery quote (EXACT_INPUT) reports a smaller fee than the final\n * EXACT_OUTPUT quote will charge. Adding the discovery fee back to the\n * minimum output compensates for this differential, ensuring the final\n * quote targets a realistic amount.\n *\n * @param discoveryQuote - The relay quote from the discovery phase.\n * @returns The adjusted target amount in raw target token units.\n */\nfunction calculateAdjustedTarget(discoveryQuote: RelayQuote): string {\n const targetMinRaw = new BigNumber(\n discoveryQuote.details.currencyOut.minimumAmount,\n );\n const targetUsd = new BigNumber(discoveryQuote.details.currencyOut.amountUsd);\n const sourceUsd = new BigNumber(discoveryQuote.details.currencyIn.amountUsd);\n\n if (!targetUsd.gt(0) || !targetMinRaw.gt(0)) {\n return targetMinRaw.toFixed(0);\n }\n\n // Discovery fee in USD\n const discoveryFeeUsd = sourceUsd.minus(targetUsd);\n\n if (!discoveryFeeUsd.gt(0)) {\n return targetMinRaw.toFixed(0);\n }\n\n // Convert fee from USD to raw target token units\n const usdPerTargetRaw = targetUsd.dividedBy(targetMinRaw);\n const discoveryFeeInTargetRaw = discoveryFeeUsd\n .dividedBy(usdPerTargetRaw)\n .decimalPlaces(0, BigNumber.ROUND_DOWN);\n\n const adjusted = targetMinRaw.plus(discoveryFeeInTargetRaw);\n\n log('Adjusted target', {\n targetMinRaw: targetMinRaw.toFixed(0),\n discoveryFeeUsd: discoveryFeeUsd.toFixed(6),\n discoveryFeeInTargetRaw: discoveryFeeInTargetRaw.toFixed(0),\n adjustedTargetRaw: adjusted.toFixed(0),\n });\n\n return adjusted.toFixed(0);\n}\n"]}
1
+ {"version":3,"file":"fiat-submit-with-transaction-data.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-submit-with-transaction-data.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AACrD,OAAO,EAAE,SAAS,EAAE,qBAAqB;AAEzC,OAAO,EAAE,aAAa,EAAE,yBAAqB;AAE7C,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,EAC3B,sCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,oCAAgC;AAC5E,OAAO,EAAE,cAAc,EAAE,kCAA8B;AACvD,OAAO,EAAE,iBAAiB,EAAE,kCAA8B;AAG1D,OAAO,EAAE,sBAAsB,EAAE,oBAAgB;AAEjD,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,sBAAsB,CAAC,CAAC;AAEtE;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,EAC9C,WAAW,EACX,OAAO,EACP,eAAe,EACf,WAAW,GAMZ;IACC,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC9B,MAAM,aAAa,GAAG,WAAW,CAAC,EAAE,CAAC;IACrC,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;IAEjE,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,aAAa,GAAG,mBAAmB,CAAC;QACxC,QAAQ,EAAE,kBAAkB;QAC5B,UAAU,EAAE,2BAA2B,CAAC,SAAS,CAAC;KACnD,CAAC,CAAC;IAEH,MAAM,qBAAqB,GAAG,SAAS,CAAC,GAAG,CACzC,IAAI,SAAS,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,EACnD,CAAC,CACF,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAEb,GAAG,CAAC,2BAA2B,EAAE;QAC/B,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;QACvC,qBAAqB;QACrB,eAAe;QACf,aAAa;KACd,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAiB;QACrC,GAAG,WAAW;QACd,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,IAAI;QACjB,gBAAgB,EAAE,eAAe;QACjC,iBAAiB,EAAE,qBAAqB;KACzC,CAAC;IAEF,MAAM,eAAe,GAAG,MAAM,cAAc,CAAC;QAC3C,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,SAAS;QACT,QAAQ,EAAE,CAAC,gBAAgB,CAAC;QAC5B,WAAW;KACZ,CAAC,CAAC;IAEH,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,cAAc,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEnD,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,cAAc,CAAC,CAAC;IAElE,GAAG,CAAC,iCAAiC,EAAE;QACrC,gBAAgB,EAAE,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,aAAa;QAClE,iBAAiB;QACjB,aAAa;KACd,CAAC,CAAC;IAEH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,IAAI,CACtC,wCAAwC,EACxC,EAAE,MAAM,EAAE,iBAAiB,EAAE,WAAW,EAAE,CAC3C,CAAC;IAEF,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,wEAAwE,CACzE,CAAC;IACJ,CAAC;IAED,iBAAiB,CACf,EAAE,aAAa,EAAE,SAAS,EAAE,IAAI,EAAE,qCAAqC,EAAE,EACzE,CAAC,EAAE,EAAE,EAAE;QACL,KAAK,MAAM,EAAE,sBAAsB,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;YACvD,IAAI,EAAE,CAAC,kBAAkB,EAAE,CAAC,sBAAsB,CAAC,EAAE,CAAC;gBACpD,EAAE,CAAC,kBAAkB,CAAC,sBAAsB,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC;YAC5D,CAAC;QACH,CAAC;QACD,IAAI,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3B,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,KAAK,IAAI,SAAS,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;QACrF,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,kBAAkB,GACtB,cAAc,CAAC,aAAa,EAAE,SAAS,CAAC,IAAI,WAAW,CAAC;IAE1D,MAAM,YAAY,GAAiB;QACjC,GAAG,WAAW;QACd,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,KAAK;QAClB,gBAAgB,EAAE,eAAe;QACjC,iBAAiB,EAAE,eAAe;QAClC,mBAAmB,EAAE,iBAAiB;KACvC,CAAC;IAEF,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC;QACvC,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,SAAS;QACT,QAAQ,EAAE,CAAC,YAAY,CAAC;QACxB,WAAW,EAAE,kBAAkB;KAChC,CAAC,CAAC;IAEH,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,sBAAsB,CAAC;QACrB,aAAa,EAAE,kBAAkB;QACjC,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ;QACvC,mBAAmB,EAAE,0BAA0B,CAAC,SAAS,CAAC;QAC1D,aAAa;KACd,CAAC,CAAC;IAEH,GAAG,CAAC,gDAAgD,EAAE;QACpD,eAAe,EAAE,WAAW,CAAC,MAAM;QACnC,aAAa;KACd,CAAC,CAAC;IAEH,OAAO,MAAM,iBAAiB,CAAC;QAC7B,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,SAAS;QACT,MAAM,EAAE,WAAW;QACnB,WAAW,EAAE,kBAAkB;KAChC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,mBAAmB,CAAC,EAC3B,QAAQ,EACR,UAAU,GAIX;IACC,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACpE,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACvE,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;IAE3E,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,OAAO,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,eAAe,GAAG,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAEvD,OAAO,MAAM;SACV,SAAS,CAAC,eAAe,CAAC;SAC1B,YAAY,CAAC,UAAU,CAAC;SACxB,aAAa,CAAC,CAAC,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,uBAAuB,CAAC,cAA0B;IACzD,MAAM,YAAY,GAAG,IAAI,SAAS,CAChC,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,aAAa,CACjD,CAAC;IACF,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAC9E,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAE7E,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC;IAED,uBAAuB;IACvB,MAAM,eAAe,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAEnD,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3B,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC;IAED,iDAAiD;IACjD,MAAM,eAAe,GAAG,SAAS,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IAC1D,MAAM,uBAAuB,GAAG,eAAe;SAC5C,SAAS,CAAC,eAAe,CAAC;SAC1B,aAAa,CAAC,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IAE1C,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAE5D,GAAG,CAAC,iBAAiB,EAAE;QACrB,YAAY,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;QACrC,eAAe,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3C,uBAAuB,EAAE,uBAAuB,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3D,iBAAiB,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;KACvC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { projectLogger } from '../../logger';\nimport type { PayStrategyExecuteRequest, QuoteRequest } from '../../types';\nimport {\n getFiatFeeReserveMultiplier,\n getFiatMaxRateDriftPercent,\n} from '../../utils/feature-flags';\nimport { getTransaction, updateTransaction } from '../../utils/transaction';\nimport { getRelayQuotes } from '../relay/relay-quotes';\nimport { submitRelayQuotes } from '../relay/relay-submit';\nimport type { RelayQuote } from '../relay/types';\nimport type { FiatQuote } from './types';\nimport { validateRelayRateDrift } from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-submit-calldata');\n\n/**\n * Submits relay quotes using the three-phase flow for transactions with nested\n * calldata that needs re-encoding (e.g. moneyAccountDeposit with approve + deposit).\n *\n * Phase 1: Discovery quote (EXACT_INPUT) to learn the target token output.\n * Phase 2: Delegate calldata re-encoding to the client via getAmountData.\n * Phase 3: Delegation quote (EXACT_OUTPUT) with updated nested transaction data.\n *\n * @param options - The submission options.\n * @param options.baseRequest - The base quote request from the original fiat quote.\n * @param options.request - The original fiat strategy execute request.\n * @param options.sourceAmountRaw - The settled source amount in atomic units.\n * @param options.transaction - The transaction metadata.\n * @returns An object containing the relay transaction hash if available.\n */\nexport async function submitWithTransactionData({\n baseRequest,\n request,\n sourceAmountRaw,\n transaction,\n}: {\n baseRequest: QuoteRequest;\n request: PayStrategyExecuteRequest<FiatQuote>;\n sourceAmountRaw: string;\n transaction: PayStrategyExecuteRequest<FiatQuote>['transaction'];\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger } = request;\n const transactionId = transaction.id;\n const originalRelayQuote = request.quotes[0].original.relayQuote;\n\n if (!originalRelayQuote) {\n throw new Error('Missing Relay quote for fiat submission');\n }\n\n const feeReserveRaw = calculateFeeReserve({\n feeQuote: originalRelayQuote,\n multiplier: getFiatFeeReserveMultiplier(messenger),\n });\n\n const discoverySourceAmount = BigNumber.max(\n new BigNumber(sourceAmountRaw).minus(feeReserveRaw),\n 1,\n ).toFixed(0);\n\n log('Fee reserve for discovery', {\n feeReserveRaw: feeReserveRaw.toFixed(0),\n discoverySourceAmount,\n sourceAmountRaw,\n transactionId,\n });\n\n const discoveryRequest: QuoteRequest = {\n ...baseRequest,\n isMaxAmount: false,\n isPostQuote: true,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: discoverySourceAmount,\n };\n\n const discoveryQuotes = await getRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n from: baseRequest.from,\n messenger,\n requests: [discoveryRequest],\n transaction,\n });\n\n if (!discoveryQuotes.length) {\n throw new Error('No relay quotes returned for fiat discovery');\n }\n\n const discoveryRelay = discoveryQuotes[0].original;\n\n const adjustedTargetRaw = calculateAdjustedTarget(discoveryRelay);\n\n log('Adjusted target for final quote', {\n discoveryMinimum: discoveryRelay.details.currencyOut.minimumAmount,\n adjustedTargetRaw,\n transactionId,\n });\n\n const { updates } = await messenger.call(\n 'TransactionPayController:getAmountData',\n { amount: adjustedTargetRaw, transaction },\n );\n\n if (!updates.length) {\n throw new Error(\n 'getAmountData returned no updates for transaction with nested calldata',\n );\n }\n\n updateTransaction(\n { transactionId, messenger, note: 'Fiat deposit: update settled amount' },\n (tx) => {\n for (const { nestedTransactionIndex, data } of updates) {\n if (tx.nestedTransactions?.[nestedTransactionIndex]) {\n tx.nestedTransactions[nestedTransactionIndex].data = data;\n }\n }\n if (tx.requiredAssets?.[0]) {\n tx.requiredAssets[0].amount = `0x${new BigNumber(adjustedTargetRaw).toString(16)}`;\n }\n },\n );\n\n const updatedTransaction =\n getTransaction(transactionId, messenger) ?? transaction;\n\n const relayRequest: QuoteRequest = {\n ...baseRequest,\n isMaxAmount: false,\n isPostQuote: false,\n sourceBalanceRaw: sourceAmountRaw,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: adjustedTargetRaw,\n };\n\n const relayQuotes = await getRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n from: baseRequest.from,\n messenger,\n requests: [relayRequest],\n transaction: updatedTransaction,\n });\n\n if (!relayQuotes.length) {\n throw new Error('No relay quotes returned for completed fiat order');\n }\n\n validateRelayRateDrift({\n originalQuote: originalRelayQuote,\n discoveryQuote: relayQuotes[0].original,\n maxRateDriftPercent: getFiatMaxRateDriftPercent(messenger),\n transactionId,\n });\n\n log('Received relay quotes for completed fiat order', {\n relayQuoteCount: relayQuotes.length,\n transactionId,\n });\n\n return await submitRelayQuotes({\n accountSupports7702: request.accountSupports7702,\n isSmartTransaction: request.isSmartTransaction,\n messenger,\n quotes: relayQuotes,\n transaction: updatedTransaction,\n });\n}\n\n/**\n * Calculates the fee reserve in raw source token units from the original\n * relay fee quote. This reserve is subtracted from the discovery quote's\n * source amount so the final EXACT_OUTPUT quote stays within the settled\n * balance.\n *\n * @param options - Calculation options.\n * @param options.feeQuote - The original relay quote from the fee/quoting phase.\n * @param options.multiplier - Multiplier applied to the fee reserve (default 1).\n * @returns The fee reserve in raw source token units.\n */\nfunction calculateFeeReserve({\n feeQuote,\n multiplier,\n}: {\n feeQuote: RelayQuote;\n multiplier: number;\n}): BigNumber {\n const sourceRaw = new BigNumber(feeQuote.details.currencyIn.amount);\n const sourceUsd = new BigNumber(feeQuote.details.currencyIn.amountUsd);\n const rawImpact = new BigNumber(feeQuote.details.totalImpact.usd);\n const feeUsd = rawImpact.isNegative() ? rawImpact.abs() : new BigNumber(0);\n\n if (!sourceUsd.gt(0) || !sourceRaw.gt(0) || !feeUsd.gt(0)) {\n return new BigNumber(0);\n }\n\n const usdPerSourceRaw = sourceUsd.dividedBy(sourceRaw);\n\n return feeUsd\n .dividedBy(usdPerSourceRaw)\n .multipliedBy(multiplier)\n .decimalPlaces(0, BigNumber.ROUND_UP);\n}\n\n/**\n * Calculates the adjusted target amount for the final EXACT_OUTPUT quote\n * by adding the discovery quote's fee back to its minimum output.\n *\n * The discovery quote (EXACT_INPUT) reports a smaller fee than the final\n * EXACT_OUTPUT quote will charge. Adding the discovery fee back to the\n * minimum output compensates for this differential, ensuring the final\n * quote targets a realistic amount.\n *\n * @param discoveryQuote - The relay quote from the discovery phase.\n * @returns The adjusted target amount in raw target token units.\n */\nfunction calculateAdjustedTarget(discoveryQuote: RelayQuote): string {\n const targetMinRaw = new BigNumber(\n discoveryQuote.details.currencyOut.minimumAmount,\n );\n const targetUsd = new BigNumber(discoveryQuote.details.currencyOut.amountUsd);\n const sourceUsd = new BigNumber(discoveryQuote.details.currencyIn.amountUsd);\n\n if (!targetUsd.gt(0) || !targetMinRaw.gt(0)) {\n return targetMinRaw.toFixed(0);\n }\n\n // Discovery fee in USD\n const discoveryFeeUsd = sourceUsd.minus(targetUsd);\n\n if (!discoveryFeeUsd.gt(0)) {\n return targetMinRaw.toFixed(0);\n }\n\n // Convert fee from USD to raw target token units\n const usdPerTargetRaw = targetUsd.dividedBy(targetMinRaw);\n const discoveryFeeInTargetRaw = discoveryFeeUsd\n .dividedBy(usdPerTargetRaw)\n .decimalPlaces(0, BigNumber.ROUND_DOWN);\n\n const adjusted = targetMinRaw.plus(discoveryFeeInTargetRaw);\n\n log('Adjusted target', {\n targetMinRaw: targetMinRaw.toFixed(0),\n discoveryFeeUsd: discoveryFeeUsd.toFixed(6),\n discoveryFeeInTargetRaw: discoveryFeeInTargetRaw.toFixed(0),\n adjustedTargetRaw: adjusted.toFixed(0),\n });\n\n return adjusted.toFixed(0);\n}\n"]}