@metamask/transaction-pay-controller 23.11.0 → 23.13.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 (80) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/dist/helpers/TransactionPayPublishHook.cjs +9 -4
  3. package/dist/helpers/TransactionPayPublishHook.cjs.map +1 -1
  4. package/dist/helpers/TransactionPayPublishHook.d.cts.map +1 -1
  5. package/dist/helpers/TransactionPayPublishHook.d.mts.map +1 -1
  6. package/dist/helpers/TransactionPayPublishHook.mjs +9 -4
  7. package/dist/helpers/TransactionPayPublishHook.mjs.map +1 -1
  8. package/dist/strategy/fiat/FiatStrategy.cjs +12 -1
  9. package/dist/strategy/fiat/FiatStrategy.cjs.map +1 -1
  10. package/dist/strategy/fiat/FiatStrategy.d.cts.map +1 -1
  11. package/dist/strategy/fiat/FiatStrategy.d.mts.map +1 -1
  12. package/dist/strategy/fiat/FiatStrategy.mjs +12 -1
  13. package/dist/strategy/fiat/FiatStrategy.mjs.map +1 -1
  14. package/dist/strategy/fiat/fiat-direct-musd.cjs +74 -23
  15. package/dist/strategy/fiat/fiat-direct-musd.cjs.map +1 -1
  16. package/dist/strategy/fiat/fiat-direct-musd.d.cts +15 -0
  17. package/dist/strategy/fiat/fiat-direct-musd.d.cts.map +1 -1
  18. package/dist/strategy/fiat/fiat-direct-musd.d.mts +15 -0
  19. package/dist/strategy/fiat/fiat-direct-musd.d.mts.map +1 -1
  20. package/dist/strategy/fiat/fiat-direct-musd.mjs +73 -23
  21. package/dist/strategy/fiat/fiat-direct-musd.mjs.map +1 -1
  22. package/dist/strategy/fiat/fiat-submit-simple.cjs +1 -1
  23. package/dist/strategy/fiat/fiat-submit-simple.cjs.map +1 -1
  24. package/dist/strategy/fiat/fiat-submit-simple.mjs +1 -1
  25. package/dist/strategy/fiat/fiat-submit-simple.mjs.map +1 -1
  26. package/dist/strategy/fiat/fiat-submit-with-transaction-data.cjs +1 -1
  27. package/dist/strategy/fiat/fiat-submit-with-transaction-data.cjs.map +1 -1
  28. package/dist/strategy/fiat/fiat-submit-with-transaction-data.mjs +1 -1
  29. package/dist/strategy/fiat/fiat-submit-with-transaction-data.mjs.map +1 -1
  30. package/dist/strategy/fiat/fiat-submit.cjs +19 -47
  31. package/dist/strategy/fiat/fiat-submit.cjs.map +1 -1
  32. package/dist/strategy/fiat/fiat-submit.d.cts.map +1 -1
  33. package/dist/strategy/fiat/fiat-submit.d.mts.map +1 -1
  34. package/dist/strategy/fiat/fiat-submit.mjs +20 -48
  35. package/dist/strategy/fiat/fiat-submit.mjs.map +1 -1
  36. package/dist/strategy/fiat/utils.cjs +24 -1
  37. package/dist/strategy/fiat/utils.cjs.map +1 -1
  38. package/dist/strategy/fiat/utils.d.cts +14 -1
  39. package/dist/strategy/fiat/utils.d.cts.map +1 -1
  40. package/dist/strategy/fiat/utils.d.mts +14 -1
  41. package/dist/strategy/fiat/utils.d.mts.map +1 -1
  42. package/dist/strategy/fiat/utils.mjs +22 -0
  43. package/dist/strategy/fiat/utils.mjs.map +1 -1
  44. package/dist/strategy/relay/RelayStrategy.cjs +1 -7
  45. package/dist/strategy/relay/RelayStrategy.cjs.map +1 -1
  46. package/dist/strategy/relay/RelayStrategy.d.cts.map +1 -1
  47. package/dist/strategy/relay/RelayStrategy.d.mts.map +1 -1
  48. package/dist/strategy/relay/RelayStrategy.mjs +1 -7
  49. package/dist/strategy/relay/RelayStrategy.mjs.map +1 -1
  50. package/dist/strategy/relay/relay-quotes.cjs +1 -29
  51. package/dist/strategy/relay/relay-quotes.cjs.map +1 -1
  52. package/dist/strategy/relay/relay-quotes.mjs +1 -29
  53. package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
  54. package/dist/strategy/relay/relay-submit.cjs +30 -7
  55. package/dist/strategy/relay/relay-submit.cjs.map +1 -1
  56. package/dist/strategy/relay/relay-submit.d.cts.map +1 -1
  57. package/dist/strategy/relay/relay-submit.d.mts.map +1 -1
  58. package/dist/strategy/relay/relay-submit.mjs +29 -6
  59. package/dist/strategy/relay/relay-submit.mjs.map +1 -1
  60. package/dist/utils/error-prefix.cjs +21 -0
  61. package/dist/utils/error-prefix.cjs.map +1 -0
  62. package/dist/utils/error-prefix.d.cts +9 -0
  63. package/dist/utils/error-prefix.d.cts.map +1 -0
  64. package/dist/utils/error-prefix.d.mts +9 -0
  65. package/dist/utils/error-prefix.d.mts.map +1 -0
  66. package/dist/utils/error-prefix.mjs +17 -0
  67. package/dist/utils/error-prefix.mjs.map +1 -0
  68. package/dist/utils/provider.cjs +28 -2
  69. package/dist/utils/provider.cjs.map +1 -1
  70. package/dist/utils/provider.d.cts.map +1 -1
  71. package/dist/utils/provider.d.mts.map +1 -1
  72. package/dist/utils/provider.mjs +29 -3
  73. package/dist/utils/provider.mjs.map +1 -1
  74. package/dist/utils/source-amounts.cjs +4 -6
  75. package/dist/utils/source-amounts.cjs.map +1 -1
  76. package/dist/utils/source-amounts.d.cts.map +1 -1
  77. package/dist/utils/source-amounts.d.mts.map +1 -1
  78. package/dist/utils/source-amounts.mjs +4 -6
  79. package/dist/utils/source-amounts.mjs.map +1 -1
  80. package/package.json +4 -4
@@ -4,13 +4,16 @@ import { createModuleLogger } from "@metamask/utils";
4
4
  import { BigNumber } from "bignumber.js";
5
5
  import { TransactionPayStrategy } from "../../constants.mjs";
6
6
  import { projectLogger } from "../../logger.mjs";
7
+ import { prefixError } from "../../utils/error-prefix.mjs";
7
8
  import { getFiatVaultDisabled } from "../../utils/feature-flags.mjs";
8
9
  import { getNetworkClientId } from "../../utils/provider.mjs";
9
10
  import { buildCaipAssetType, getTokenInfo } from "../../utils/token.mjs";
10
11
  import { collectTransactionIds, getTransaction, updateTransaction, waitForTransactionConfirmed } from "../../utils/transaction.mjs";
11
12
  import { MUSD_MONAD_FIAT_ASSET } from "./constants.mjs";
12
- import { getRampsQuote, getRawSourceAmountFromOrderCryptoAmount } from "./utils.mjs";
13
+ import { getRampsQuote, getRawSourceAmountFromOrderCryptoAmount, resolveSourceAmountRaw, validateOrderAsset } from "./utils.mjs";
13
14
  const log = createModuleLogger(projectLogger, 'fiat-direct-musd');
15
+ const DIRECT_MUSD_ERROR_PREFIX = 'Direct mUSD: ';
16
+ const VAULT_ERROR_PREFIX = 'Vault: ';
14
17
  /**
15
18
  * Returns a direct mUSD fiat quote to the Money Account.
16
19
  *
@@ -71,6 +74,38 @@ export async function getDirectMusdFiatQuote({ amountFiat, fiatPaymentMethod, me
71
74
  export function isDirectMusdMoneyAccountQuote(quote) {
72
75
  return quote?.request.isDirectMusdMoneyAccount === true;
73
76
  }
77
+ /**
78
+ * Submits the direct mUSD post-Ramp path after fiat settlement.
79
+ *
80
+ * @param options - Submit options.
81
+ * @param options.order - Completed fiat order.
82
+ * @param options.request - Strategy execute request.
83
+ * @returns Hash of the submitted direct mUSD transaction, if available.
84
+ */
85
+ export async function submitDirectMusdAfterFiatCompletion({ order, request, }) {
86
+ const { messenger, transaction } = request;
87
+ try {
88
+ validateOrderAsset({
89
+ expectedAsset: MUSD_MONAD_FIAT_ASSET,
90
+ orderCrypto: order.cryptoCurrency,
91
+ transactionId: transaction.id,
92
+ });
93
+ const sourceAmountRaw = await resolveSourceAmountRaw({
94
+ messenger,
95
+ order,
96
+ fiatAsset: MUSD_MONAD_FIAT_ASSET,
97
+ walletAddress: transaction.txParams.from,
98
+ });
99
+ return await submitDirectMusdVaultDeposit({
100
+ request,
101
+ sourceAmountRaw,
102
+ transaction,
103
+ });
104
+ }
105
+ catch (error) {
106
+ throw prefixError(error, DIRECT_MUSD_ERROR_PREFIX);
107
+ }
108
+ }
74
109
  /**
75
110
  * Submits the direct mUSD Money Account vault batch after fiat settlement.
76
111
  *
@@ -85,7 +120,7 @@ export async function submitDirectMusdVaultDeposit({ request, sourceAmountRaw, t
85
120
  const transactionId = transaction.id;
86
121
  const moneyAccountAddress = transaction.txParams.from;
87
122
  if (!moneyAccountAddress) {
88
- throw new Error('Missing Money Account address for direct mUSD submit');
123
+ throw new Error('Missing Money Account address');
89
124
  }
90
125
  if (getFiatVaultDisabled(messenger)) {
91
126
  log('Skipping direct mUSD vault deposit because vaultDisabled is enabled', {
@@ -101,18 +136,22 @@ export async function submitDirectMusdVaultDeposit({ request, sourceAmountRaw, t
101
136
  transaction: updatedTransaction,
102
137
  });
103
138
  if (!updates.length) {
104
- throw new Error('getAmountData returned no updates for direct mUSD submit');
139
+ throw new Error('No amount updates');
105
140
  }
106
141
  const nestedTransactions = updatedTransaction.nestedTransactions?.map((nestedTransaction) => ({ ...nestedTransaction }));
107
142
  if (!nestedTransactions?.length) {
108
- throw new Error('Missing nested transactions for direct mUSD submit');
143
+ throw new Error('Missing nested transactions');
109
144
  }
110
145
  for (const { nestedTransactionIndex, data } of updates) {
111
146
  if (nestedTransactions[nestedTransactionIndex]) {
112
147
  nestedTransactions[nestedTransactionIndex].data = data;
113
148
  }
114
149
  }
115
- updateTransaction({ transactionId, messenger, note: 'Direct mUSD fiat: update vault amount' }, (tx) => {
150
+ updateTransaction({
151
+ transactionId,
152
+ messenger,
153
+ note: 'Direct mUSD fiat: update vault amount',
154
+ }, (tx) => {
116
155
  for (const { nestedTransactionIndex, data } of updates) {
117
156
  if (tx.nestedTransactions?.[nestedTransactionIndex]) {
118
157
  tx.nestedTransactions[nestedTransactionIndex].data = data;
@@ -142,24 +181,29 @@ export async function submitDirectMusdVaultDeposit({ request, sourceAmountRaw, t
142
181
  sourceAmountRaw,
143
182
  transactionId,
144
183
  });
145
- await messenger.call('TransactionController:addTransactionBatch', {
146
- from: moneyAccountAddress,
147
- isGasFeeSponsored: true,
148
- isInternal: true,
149
- networkClientId,
150
- origin: ORIGIN_METAMASK,
151
- requireApproval: false,
152
- transactions: nestedTransactions.map((nestedTransaction, index) => ({
153
- params: {
154
- data: nestedTransaction.data,
155
- to: nestedTransaction.to,
156
- value: nestedTransaction.value ?? '0x0',
157
- },
158
- type: index === 0
159
- ? (nestedTransaction.type ?? TransactionType.tokenMethodApprove)
160
- : TransactionType.contractInteraction,
161
- })),
162
- });
184
+ try {
185
+ await messenger.call('TransactionController:addTransactionBatch', {
186
+ from: moneyAccountAddress,
187
+ isGasFeeSponsored: true,
188
+ isInternal: true,
189
+ networkClientId,
190
+ origin: ORIGIN_METAMASK,
191
+ requireApproval: false,
192
+ transactions: nestedTransactions.map((nestedTransaction, index) => ({
193
+ params: {
194
+ data: nestedTransaction.data,
195
+ to: nestedTransaction.to,
196
+ value: nestedTransaction.value ?? '0x0',
197
+ },
198
+ type: index === 0
199
+ ? (nestedTransaction.type ?? TransactionType.tokenMethodApprove)
200
+ : TransactionType.contractInteraction,
201
+ })),
202
+ });
203
+ }
204
+ catch (error) {
205
+ throw prefixError(error, VAULT_ERROR_PREFIX);
206
+ }
163
207
  end();
164
208
  log('Submitted direct mUSD vault deposit', {
165
209
  moneyAccountAddress,
@@ -169,8 +213,14 @@ export async function submitDirectMusdVaultDeposit({ request, sourceAmountRaw, t
169
213
  transactionId,
170
214
  transactionIds,
171
215
  });
216
+ if (!transactionIds.length) {
217
+ throw new Error('No transactions submitted');
218
+ }
172
219
  await Promise.all(transactionIds.map((id) => waitForTransactionConfirmed(id, messenger)));
173
220
  const hash = getTransaction(transactionIds.slice(-1)[0], messenger)?.hash;
221
+ if (!hash) {
222
+ throw new Error('Missing transaction hash');
223
+ }
174
224
  log('Confirmed direct mUSD vault deposit', {
175
225
  hash,
176
226
  moneyAccountAddress,
@@ -1 +1 @@
1
- {"version":3,"file":"fiat-direct-musd.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-direct-musd.ts"],"names":[],"mappings":"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","sourcesContent":["import { ORIGIN_METAMASK } from '@metamask/controller-utils';\nimport type { Quote as RampsQuote } from '@metamask/ramps-controller';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TransactionPayStrategy } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyExecuteRequest,\n PayStrategyGetQuotesRequest,\n TransactionFiatPayment,\n TransactionPayRequiredToken,\n TransactionPayQuote,\n} from '../../types';\nimport { getFiatVaultDisabled } from '../../utils/feature-flags';\nimport { getNetworkClientId } from '../../utils/provider';\nimport { buildCaipAssetType, getTokenInfo } from '../../utils/token';\nimport {\n collectTransactionIds,\n getTransaction,\n updateTransaction,\n waitForTransactionConfirmed,\n} from '../../utils/transaction';\nimport { MUSD_MONAD_FIAT_ASSET } from './constants';\nimport type { FiatQuote } from './types';\nimport {\n getRampsQuote,\n getRawSourceAmountFromOrderCryptoAmount,\n} from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-direct-musd');\n\n/**\n * Returns a direct mUSD fiat quote to the Money Account.\n *\n * @param options - Direct quote options.\n * @param options.amountFiat - Fiat amount entered by the user.\n * @param options.fiatPaymentMethod - Selected fiat payment method.\n * @param options.messenger - Controller messenger.\n * @param options.moneyAccountAddress - Money Account receiving the on-ramped mUSD.\n * @param options.requiredToken - Required token from the original Money Account transaction.\n * @param options.transactionId - Transaction ID for state updates and logs.\n * @returns Direct mUSD Fiat quote, or undefined when unavailable.\n */\nexport async function getDirectMusdFiatQuote({\n amountFiat,\n fiatPaymentMethod,\n messenger,\n moneyAccountAddress,\n requiredToken,\n transactionId,\n}: {\n amountFiat: string;\n fiatPaymentMethod: string;\n messenger: PayStrategyGetQuotesRequest['messenger'];\n moneyAccountAddress: Hex;\n requiredToken: TransactionPayRequiredToken;\n transactionId: string;\n}): Promise<TransactionPayQuote<FiatQuote> | undefined> {\n try {\n const adjustedAmount = Number(amountFiat);\n\n if (!Number.isFinite(adjustedAmount) || adjustedAmount <= 0) {\n throw new Error('Invalid fiat amount for direct mUSD quote');\n }\n\n const fiatQuote = await getRampsQuote({\n adjustedAmount,\n errorMessage: 'No matching ramps quote found for direct mUSD provider',\n fiatAsset: MUSD_MONAD_FIAT_ASSET,\n fiatPaymentMethod,\n messenger,\n walletAddress: moneyAccountAddress,\n });\n\n messenger.call('TransactionPayController:updateFiatPayment', {\n callback: (fiatPayment: TransactionFiatPayment) => {\n fiatPayment.rampsQuote = fiatQuote;\n fiatPayment.caipAssetId = buildCaipAssetType(\n MUSD_MONAD_FIAT_ASSET.chainId,\n MUSD_MONAD_FIAT_ASSET.address,\n );\n },\n transactionId,\n });\n\n log('Direct mUSD fiat quote flow', {\n amountFiat,\n moneyAccountAddress,\n transactionId,\n });\n\n return combineDirectMusdFiatQuote({\n amountFiat,\n fiatQuote,\n messenger,\n moneyAccountAddress,\n requiredToken,\n });\n } catch (error) {\n log('Direct mUSD fiat quote failed', { error, transactionId });\n return undefined;\n }\n}\n\n/**\n * Detects a direct mUSD Money Account quote from its stored request marker.\n *\n * @param quote - Quote to inspect.\n * @returns True when the quote originated from the direct mUSD fiat path.\n */\nexport function isDirectMusdMoneyAccountQuote(\n quote: Pick<TransactionPayQuote<unknown>, 'request'> | undefined,\n): boolean {\n return quote?.request.isDirectMusdMoneyAccount === true;\n}\n\n/**\n * Submits the direct mUSD Money Account vault batch after fiat settlement.\n *\n * @param options - Submit options.\n * @param options.request - Strategy execute request.\n * @param options.sourceAmountRaw - Settled source amount in raw mUSD units.\n * @param options.transaction - Original Money Account transaction.\n * @returns Hash of the final submitted child transaction, if available.\n */\nexport async function submitDirectMusdVaultDeposit({\n request,\n sourceAmountRaw,\n transaction,\n}: {\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 moneyAccountAddress = transaction.txParams.from as Hex | undefined;\n\n if (!moneyAccountAddress) {\n throw new Error('Missing Money Account address for direct mUSD submit');\n }\n\n if (getFiatVaultDisabled(messenger)) {\n log('Skipping direct mUSD vault deposit because vaultDisabled is enabled', {\n moneyAccountAddress,\n sourceAmountRaw,\n transactionId,\n });\n\n return { transactionHash: '0x' };\n }\n\n const updatedTransaction =\n getTransaction(transactionId, messenger) ?? transaction;\n const { updates } = await messenger.call(\n 'TransactionPayController:getAmountData',\n {\n amount: sourceAmountRaw,\n transaction: updatedTransaction,\n },\n );\n\n if (!updates.length) {\n throw new Error('getAmountData returned no updates for direct mUSD submit');\n }\n\n const nestedTransactions = updatedTransaction.nestedTransactions?.map(\n (nestedTransaction) => ({ ...nestedTransaction }),\n );\n\n if (!nestedTransactions?.length) {\n throw new Error('Missing nested transactions for direct mUSD submit');\n }\n\n for (const { nestedTransactionIndex, data } of updates) {\n if (nestedTransactions[nestedTransactionIndex]) {\n nestedTransactions[nestedTransactionIndex].data = data;\n }\n }\n\n updateTransaction(\n { transactionId, messenger, note: 'Direct mUSD fiat: update vault amount' },\n (tx) => {\n for (const { nestedTransactionIndex, data } of updates) {\n if (tx.nestedTransactions?.[nestedTransactionIndex]) {\n tx.nestedTransactions[nestedTransactionIndex].data = data;\n }\n }\n\n if (tx.requiredAssets?.[0]) {\n tx.requiredAssets[0].amount = `0x${BigInt(sourceAmountRaw).toString(\n 16,\n )}`;\n }\n },\n );\n\n const networkClientId = getNetworkClientId(\n messenger,\n MUSD_MONAD_FIAT_ASSET.chainId,\n );\n const transactionIds: string[] = [];\n const { end } = collectTransactionIds(\n MUSD_MONAD_FIAT_ASSET.chainId,\n moneyAccountAddress,\n messenger,\n (id) => {\n transactionIds.push(id);\n updateTransaction(\n {\n transactionId,\n messenger,\n note: 'Add required transaction ID from direct mUSD vault submission',\n },\n (tx) => {\n tx.requiredTransactionIds ??= [];\n tx.requiredTransactionIds.push(id);\n },\n );\n },\n );\n\n log('Submitting direct mUSD vault deposit', {\n moneyAccountAddress,\n nestedTransactionCount: nestedTransactions.length,\n networkClientId,\n sourceAmountRaw,\n transactionId,\n });\n\n await messenger.call('TransactionController:addTransactionBatch', {\n from: moneyAccountAddress,\n isGasFeeSponsored: true,\n isInternal: true,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n transactions: nestedTransactions.map((nestedTransaction, index) => ({\n params: {\n data: nestedTransaction.data,\n to: nestedTransaction.to,\n value: nestedTransaction.value ?? '0x0',\n },\n type:\n index === 0\n ? (nestedTransaction.type ?? TransactionType.tokenMethodApprove)\n : TransactionType.contractInteraction,\n })),\n });\n\n end();\n\n log('Submitted direct mUSD vault deposit', {\n moneyAccountAddress,\n nestedTransactionCount: nestedTransactions.length,\n networkClientId,\n sourceAmountRaw,\n transactionId,\n transactionIds,\n });\n\n await Promise.all(\n transactionIds.map((id) => waitForTransactionConfirmed(id, messenger)),\n );\n\n const hash = getTransaction(transactionIds.slice(-1)[0], messenger)?.hash;\n\n log('Confirmed direct mUSD vault deposit', {\n hash,\n moneyAccountAddress,\n nestedTransactionCount: nestedTransactions.length,\n networkClientId,\n sourceAmountRaw,\n transactionId,\n transactionIds,\n });\n\n return { transactionHash: hash as Hex | undefined };\n}\n\nfunction combineDirectMusdFiatQuote({\n amountFiat,\n fiatQuote,\n messenger,\n moneyAccountAddress,\n requiredToken,\n}: {\n amountFiat: string;\n fiatQuote: RampsQuote;\n messenger: PayStrategyGetQuotesRequest['messenger'];\n moneyAccountAddress: Hex;\n requiredToken: TransactionPayRequiredToken;\n}): TransactionPayQuote<FiatQuote> {\n const tokenInfo = getTokenInfo(\n messenger,\n MUSD_MONAD_FIAT_ASSET.address,\n MUSD_MONAD_FIAT_ASSET.chainId,\n );\n\n if (!tokenInfo) {\n throw new Error('Unable to resolve mUSD token info for direct fiat quote');\n }\n\n const sourceAmountRaw = getRawSourceAmountFromOrderCryptoAmount({\n cryptoAmount: fiatQuote.quote.amountOut,\n decimals: tokenInfo.decimals,\n });\n const rampsProviderFee = getRampsProviderFee(fiatQuote).toString(10);\n const sourceAmountHuman = new BigNumber(sourceAmountRaw)\n .shiftedBy(-tokenInfo.decimals)\n .toString(10);\n\n return {\n dust: { fiat: '0', usd: '0' },\n estimatedDuration: 0,\n fees: {\n metaMask: { fiat: '0', usd: '0' },\n provider: { fiat: rampsProviderFee, usd: rampsProviderFee },\n providerFiat: { fiat: rampsProviderFee, usd: rampsProviderFee },\n sourceNetwork: {\n estimate: { fiat: '0', human: '0', raw: '0', usd: '0' },\n max: { fiat: '0', human: '0', raw: '0', usd: '0' },\n },\n targetNetwork: { fiat: '0', usd: '0' },\n },\n original: {\n rampsQuote: fiatQuote,\n relayQuote: undefined,\n },\n request: {\n from: moneyAccountAddress,\n isDirectMusdMoneyAccount: true,\n recipient: moneyAccountAddress,\n sourceBalanceRaw: sourceAmountRaw,\n sourceChainId: MUSD_MONAD_FIAT_ASSET.chainId,\n sourceTokenAddress: MUSD_MONAD_FIAT_ASSET.address,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: sourceAmountRaw,\n targetChainId: requiredToken.chainId,\n targetTokenAddress: requiredToken.address,\n },\n sourceAmount: {\n fiat: amountFiat,\n human: sourceAmountHuman,\n raw: sourceAmountRaw,\n usd: amountFiat,\n },\n strategy: TransactionPayStrategy.Fiat,\n targetAmount: { fiat: amountFiat, usd: amountFiat },\n };\n}\n\nfunction getRampsProviderFee(fiatQuote: RampsQuote): BigNumber {\n return new BigNumber(fiatQuote.quote.providerFee ?? 0).plus(\n fiatQuote.quote.networkFee ?? 0,\n );\n}\n"]}
1
+ {"version":3,"file":"fiat-direct-musd.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/fiat-direct-musd.ts"],"names":[],"mappings":"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","sourcesContent":["import { ORIGIN_METAMASK } from '@metamask/controller-utils';\nimport type {\n Quote as RampsQuote,\n RampsOrder,\n} from '@metamask/ramps-controller';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TransactionPayStrategy } from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyExecuteRequest,\n PayStrategyGetQuotesRequest,\n TransactionFiatPayment,\n TransactionPayRequiredToken,\n TransactionPayQuote,\n} from '../../types';\nimport { prefixError } from '../../utils/error-prefix';\nimport { getFiatVaultDisabled } from '../../utils/feature-flags';\nimport { getNetworkClientId } from '../../utils/provider';\nimport { buildCaipAssetType, getTokenInfo } from '../../utils/token';\nimport {\n collectTransactionIds,\n getTransaction,\n updateTransaction,\n waitForTransactionConfirmed,\n} from '../../utils/transaction';\nimport { MUSD_MONAD_FIAT_ASSET } from './constants';\nimport type { FiatQuote } from './types';\nimport {\n getRampsQuote,\n getRawSourceAmountFromOrderCryptoAmount,\n resolveSourceAmountRaw,\n validateOrderAsset,\n} from './utils';\n\nconst log = createModuleLogger(projectLogger, 'fiat-direct-musd');\nconst DIRECT_MUSD_ERROR_PREFIX = 'Direct mUSD: ';\nconst VAULT_ERROR_PREFIX = 'Vault: ';\n\n/**\n * Returns a direct mUSD fiat quote to the Money Account.\n *\n * @param options - Direct quote options.\n * @param options.amountFiat - Fiat amount entered by the user.\n * @param options.fiatPaymentMethod - Selected fiat payment method.\n * @param options.messenger - Controller messenger.\n * @param options.moneyAccountAddress - Money Account receiving the on-ramped mUSD.\n * @param options.requiredToken - Required token from the original Money Account transaction.\n * @param options.transactionId - Transaction ID for state updates and logs.\n * @returns Direct mUSD Fiat quote, or undefined when unavailable.\n */\nexport async function getDirectMusdFiatQuote({\n amountFiat,\n fiatPaymentMethod,\n messenger,\n moneyAccountAddress,\n requiredToken,\n transactionId,\n}: {\n amountFiat: string;\n fiatPaymentMethod: string;\n messenger: PayStrategyGetQuotesRequest['messenger'];\n moneyAccountAddress: Hex;\n requiredToken: TransactionPayRequiredToken;\n transactionId: string;\n}): Promise<TransactionPayQuote<FiatQuote> | undefined> {\n try {\n const adjustedAmount = Number(amountFiat);\n\n if (!Number.isFinite(adjustedAmount) || adjustedAmount <= 0) {\n throw new Error('Invalid fiat amount for direct mUSD quote');\n }\n\n const fiatQuote = await getRampsQuote({\n adjustedAmount,\n errorMessage: 'No matching ramps quote found for direct mUSD provider',\n fiatAsset: MUSD_MONAD_FIAT_ASSET,\n fiatPaymentMethod,\n messenger,\n walletAddress: moneyAccountAddress,\n });\n\n messenger.call('TransactionPayController:updateFiatPayment', {\n callback: (fiatPayment: TransactionFiatPayment) => {\n fiatPayment.rampsQuote = fiatQuote;\n fiatPayment.caipAssetId = buildCaipAssetType(\n MUSD_MONAD_FIAT_ASSET.chainId,\n MUSD_MONAD_FIAT_ASSET.address,\n );\n },\n transactionId,\n });\n\n log('Direct mUSD fiat quote flow', {\n amountFiat,\n moneyAccountAddress,\n transactionId,\n });\n\n return combineDirectMusdFiatQuote({\n amountFiat,\n fiatQuote,\n messenger,\n moneyAccountAddress,\n requiredToken,\n });\n } catch (error) {\n log('Direct mUSD fiat quote failed', { error, transactionId });\n return undefined;\n }\n}\n\n/**\n * Detects a direct mUSD Money Account quote from its stored request marker.\n *\n * @param quote - Quote to inspect.\n * @returns True when the quote originated from the direct mUSD fiat path.\n */\nexport function isDirectMusdMoneyAccountQuote(\n quote: Pick<TransactionPayQuote<unknown>, 'request'> | undefined,\n): boolean {\n return quote?.request.isDirectMusdMoneyAccount === true;\n}\n\n/**\n * Submits the direct mUSD post-Ramp path after fiat settlement.\n *\n * @param options - Submit options.\n * @param options.order - Completed fiat order.\n * @param options.request - Strategy execute request.\n * @returns Hash of the submitted direct mUSD transaction, if available.\n */\nexport async function submitDirectMusdAfterFiatCompletion({\n order,\n request,\n}: {\n order: RampsOrder;\n request: PayStrategyExecuteRequest<FiatQuote>;\n}): Promise<{ transactionHash?: Hex }> {\n const { messenger, transaction } = request;\n\n try {\n validateOrderAsset({\n expectedAsset: MUSD_MONAD_FIAT_ASSET,\n orderCrypto: order.cryptoCurrency,\n transactionId: transaction.id,\n });\n\n const sourceAmountRaw = await resolveSourceAmountRaw({\n messenger,\n order,\n fiatAsset: MUSD_MONAD_FIAT_ASSET,\n walletAddress: transaction.txParams.from as Hex,\n });\n\n return await submitDirectMusdVaultDeposit({\n request,\n sourceAmountRaw,\n transaction,\n });\n } catch (error) {\n throw prefixError(error, DIRECT_MUSD_ERROR_PREFIX);\n }\n}\n\n/**\n * Submits the direct mUSD Money Account vault batch after fiat settlement.\n *\n * @param options - Submit options.\n * @param options.request - Strategy execute request.\n * @param options.sourceAmountRaw - Settled source amount in raw mUSD units.\n * @param options.transaction - Original Money Account transaction.\n * @returns Hash of the final submitted child transaction, if available.\n */\nexport async function submitDirectMusdVaultDeposit({\n request,\n sourceAmountRaw,\n transaction,\n}: {\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 moneyAccountAddress = transaction.txParams.from as Hex | undefined;\n\n if (!moneyAccountAddress) {\n throw new Error('Missing Money Account address');\n }\n\n if (getFiatVaultDisabled(messenger)) {\n log('Skipping direct mUSD vault deposit because vaultDisabled is enabled', {\n moneyAccountAddress,\n sourceAmountRaw,\n transactionId,\n });\n\n return { transactionHash: '0x' };\n }\n\n const updatedTransaction =\n getTransaction(transactionId, messenger) ?? transaction;\n const { updates } = await messenger.call(\n 'TransactionPayController:getAmountData',\n {\n amount: sourceAmountRaw,\n transaction: updatedTransaction,\n },\n );\n\n if (!updates.length) {\n throw new Error('No amount updates');\n }\n\n const nestedTransactions = updatedTransaction.nestedTransactions?.map(\n (nestedTransaction) => ({ ...nestedTransaction }),\n );\n\n if (!nestedTransactions?.length) {\n throw new Error('Missing nested transactions');\n }\n\n for (const { nestedTransactionIndex, data } of updates) {\n if (nestedTransactions[nestedTransactionIndex]) {\n nestedTransactions[nestedTransactionIndex].data = data;\n }\n }\n\n updateTransaction(\n {\n transactionId,\n messenger,\n note: 'Direct mUSD fiat: update vault amount',\n },\n (tx) => {\n for (const { nestedTransactionIndex, data } of updates) {\n if (tx.nestedTransactions?.[nestedTransactionIndex]) {\n tx.nestedTransactions[nestedTransactionIndex].data = data;\n }\n }\n\n if (tx.requiredAssets?.[0]) {\n tx.requiredAssets[0].amount = `0x${BigInt(sourceAmountRaw).toString(\n 16,\n )}`;\n }\n },\n );\n\n const networkClientId = getNetworkClientId(\n messenger,\n MUSD_MONAD_FIAT_ASSET.chainId,\n );\n const transactionIds: string[] = [];\n const { end } = collectTransactionIds(\n MUSD_MONAD_FIAT_ASSET.chainId,\n moneyAccountAddress,\n messenger,\n (id) => {\n transactionIds.push(id);\n updateTransaction(\n {\n transactionId,\n messenger,\n note: 'Add required transaction ID from direct mUSD vault submission',\n },\n (tx) => {\n tx.requiredTransactionIds ??= [];\n tx.requiredTransactionIds.push(id);\n },\n );\n },\n );\n\n log('Submitting direct mUSD vault deposit', {\n moneyAccountAddress,\n nestedTransactionCount: nestedTransactions.length,\n networkClientId,\n sourceAmountRaw,\n transactionId,\n });\n\n try {\n await messenger.call('TransactionController:addTransactionBatch', {\n from: moneyAccountAddress,\n isGasFeeSponsored: true,\n isInternal: true,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n transactions: nestedTransactions.map((nestedTransaction, index) => ({\n params: {\n data: nestedTransaction.data,\n to: nestedTransaction.to,\n value: nestedTransaction.value ?? '0x0',\n },\n type:\n index === 0\n ? (nestedTransaction.type ?? TransactionType.tokenMethodApprove)\n : TransactionType.contractInteraction,\n })),\n });\n } catch (error) {\n throw prefixError(error, VAULT_ERROR_PREFIX);\n }\n\n end();\n\n log('Submitted direct mUSD vault deposit', {\n moneyAccountAddress,\n nestedTransactionCount: nestedTransactions.length,\n networkClientId,\n sourceAmountRaw,\n transactionId,\n transactionIds,\n });\n\n if (!transactionIds.length) {\n throw new Error('No transactions submitted');\n }\n\n await Promise.all(\n transactionIds.map((id) => waitForTransactionConfirmed(id, messenger)),\n );\n\n const hash = getTransaction(transactionIds.slice(-1)[0], messenger)?.hash;\n\n if (!hash) {\n throw new Error('Missing transaction hash');\n }\n\n log('Confirmed direct mUSD vault deposit', {\n hash,\n moneyAccountAddress,\n nestedTransactionCount: nestedTransactions.length,\n networkClientId,\n sourceAmountRaw,\n transactionId,\n transactionIds,\n });\n\n return { transactionHash: hash as Hex };\n}\n\nfunction combineDirectMusdFiatQuote({\n amountFiat,\n fiatQuote,\n messenger,\n moneyAccountAddress,\n requiredToken,\n}: {\n amountFiat: string;\n fiatQuote: RampsQuote;\n messenger: PayStrategyGetQuotesRequest['messenger'];\n moneyAccountAddress: Hex;\n requiredToken: TransactionPayRequiredToken;\n}): TransactionPayQuote<FiatQuote> {\n const tokenInfo = getTokenInfo(\n messenger,\n MUSD_MONAD_FIAT_ASSET.address,\n MUSD_MONAD_FIAT_ASSET.chainId,\n );\n\n if (!tokenInfo) {\n throw new Error('Unable to resolve mUSD token info for direct fiat quote');\n }\n\n const sourceAmountRaw = getRawSourceAmountFromOrderCryptoAmount({\n cryptoAmount: fiatQuote.quote.amountOut,\n decimals: tokenInfo.decimals,\n });\n const rampsProviderFee = getRampsProviderFee(fiatQuote).toString(10);\n const sourceAmountHuman = new BigNumber(sourceAmountRaw)\n .shiftedBy(-tokenInfo.decimals)\n .toString(10);\n\n return {\n dust: { fiat: '0', usd: '0' },\n estimatedDuration: 0,\n fees: {\n metaMask: { fiat: '0', usd: '0' },\n provider: { fiat: rampsProviderFee, usd: rampsProviderFee },\n providerFiat: { fiat: rampsProviderFee, usd: rampsProviderFee },\n sourceNetwork: {\n estimate: { fiat: '0', human: '0', raw: '0', usd: '0' },\n max: { fiat: '0', human: '0', raw: '0', usd: '0' },\n },\n targetNetwork: { fiat: '0', usd: '0' },\n },\n original: {\n rampsQuote: fiatQuote,\n relayQuote: undefined,\n },\n request: {\n from: moneyAccountAddress,\n isDirectMusdMoneyAccount: true,\n recipient: moneyAccountAddress,\n sourceBalanceRaw: sourceAmountRaw,\n sourceChainId: MUSD_MONAD_FIAT_ASSET.chainId,\n sourceTokenAddress: MUSD_MONAD_FIAT_ASSET.address,\n sourceTokenAmount: sourceAmountRaw,\n targetAmountMinimum: sourceAmountRaw,\n targetChainId: requiredToken.chainId,\n targetTokenAddress: requiredToken.address,\n },\n sourceAmount: {\n fiat: amountFiat,\n human: sourceAmountHuman,\n raw: sourceAmountRaw,\n usd: amountFiat,\n },\n strategy: TransactionPayStrategy.Fiat,\n targetAmount: { fiat: amountFiat, usd: amountFiat },\n };\n}\n\nfunction getRampsProviderFee(fiatQuote: RampsQuote): BigNumber {\n return new BigNumber(fiatQuote.quote.providerFee ?? 0).plus(\n fiatQuote.quote.networkFee ?? 0,\n );\n}\n"]}
@@ -24,7 +24,7 @@ async function submitSimpleRelay({ baseRequest, request, sourceAmountRaw, transa
24
24
  const transactionId = transaction.id;
25
25
  const originalRelayQuote = request.quotes[0].original.relayQuote;
26
26
  if (!originalRelayQuote) {
27
- throw new Error('Missing Relay quote for fiat submission');
27
+ throw new Error('Missing Relay quote');
28
28
  }
29
29
  const relayRequest = {
30
30
  ...baseRequest,
@@ -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,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
+ {"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,qBAAqB,CAAC,CAAC;IACzC,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');\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"]}
@@ -21,7 +21,7 @@ export async function submitSimpleRelay({ baseRequest, request, sourceAmountRaw,
21
21
  const transactionId = transaction.id;
22
22
  const originalRelayQuote = request.quotes[0].original.relayQuote;
23
23
  if (!originalRelayQuote) {
24
- throw new Error('Missing Relay quote for fiat submission');
24
+ throw new Error('Missing Relay quote');
25
25
  }
26
26
  const relayRequest = {
27
27
  ...baseRequest,
@@ -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,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"]}
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,qBAAqB,CAAC,CAAC;IACzC,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');\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"]}
@@ -30,7 +30,7 @@ async function submitWithTransactionData({ baseRequest, request, sourceAmountRaw
30
30
  const transactionId = transaction.id;
31
31
  const originalRelayQuote = request.quotes[0].original.relayQuote;
32
32
  if (!originalRelayQuote) {
33
- throw new Error('Missing Relay quote for fiat submission');
33
+ throw new Error('Missing Relay quote');
34
34
  }
35
35
  const feeReserveRaw = calculateFeeReserve({
36
36
  feeQuote: originalRelayQuote,
@@ -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 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
+ {"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');\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"]}
@@ -27,7 +27,7 @@ export async function submitWithTransactionData({ baseRequest, request, sourceAm
27
27
  const transactionId = transaction.id;
28
28
  const originalRelayQuote = request.quotes[0].original.relayQuote;
29
29
  if (!originalRelayQuote) {
30
- throw new Error('Missing Relay quote for fiat submission');
30
+ throw new Error('Missing Relay quote');
31
31
  }
32
32
  const feeReserveRaw = calculateFeeReserve({
33
33
  feeQuote: originalRelayQuote,
@@ -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 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
+ {"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 const originalRelayQuote = request.quotes[0].original.relayQuote;\n\n if (!originalRelayQuote) {\n throw new Error('Missing Relay quote');\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"]}
@@ -4,16 +4,16 @@ exports.submitFiatQuotes = void 0;
4
4
  const ramps_controller_1 = require("@metamask/ramps-controller");
5
5
  const utils_1 = require("@metamask/utils");
6
6
  const logger_1 = require("../../logger.cjs");
7
+ const error_prefix_1 = require("../../utils/error-prefix.cjs");
7
8
  const feature_flags_1 = require("../../utils/feature-flags.cjs");
8
- const token_1 = require("../../utils/token.cjs");
9
9
  const transaction_1 = require("../../utils/transaction.cjs");
10
- const constants_1 = require("./constants.cjs");
11
10
  const fiat_direct_musd_1 = require("./fiat-direct-musd.cjs");
12
11
  const fiat_submit_simple_1 = require("./fiat-submit-simple.cjs");
13
12
  const fiat_submit_with_transaction_data_1 = require("./fiat-submit-with-transaction-data.cjs");
14
13
  const fiat_test_funding_1 = require("./fiat-test-funding.cjs");
15
14
  const utils_2 = require("./utils.cjs");
16
15
  const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'fiat-submit');
16
+ const POST_RAMP_ERROR_PREFIX = 'Post-Ramp: ';
17
17
  const TERMINAL_FAILURE_STATUSES = [
18
18
  ramps_controller_1.RampsOrderStatus.Cancelled,
19
19
  ramps_controller_1.RampsOrderStatus.Failed,
@@ -43,11 +43,11 @@ async function submitFiatQuotes(request) {
43
43
  const fiatPayment = transactionData?.fiatPayment;
44
44
  const orderId = fiatPayment?.orderId;
45
45
  if (!orderId) {
46
- throw new Error('Missing order ID for fiat submission');
46
+ throw new Error('Missing order ID');
47
47
  }
48
48
  const providerCode = (0, utils_2.extractProviderCode)(fiatPayment?.rampsQuote?.provider);
49
49
  if (!providerCode) {
50
- throw new Error('Missing provider code for fiat submission');
50
+ throw new Error('Missing provider code');
51
51
  }
52
52
  (0, transaction_1.updateTransaction)({
53
53
  transactionId,
@@ -64,7 +64,7 @@ async function submitFiatQuotes(request) {
64
64
  });
65
65
  const fiatQuote = request.quotes[0];
66
66
  if (!fiatQuote) {
67
- throw new Error('Missing fiat quote for relay submission');
67
+ throw new Error('Missing quote');
68
68
  }
69
69
  const fiatOptions = getFiatOptions(messenger);
70
70
  const order = fiatOptions?.testFundingSource
@@ -86,7 +86,16 @@ async function submitFiatQuotes(request) {
86
86
  orderId,
87
87
  transactionId,
88
88
  });
89
- return await submitRelayAfterFiatCompletion({ order, request });
89
+ try {
90
+ const result = await submitRelayAfterFiatCompletion({ order, request });
91
+ if (result.transactionHash === undefined) {
92
+ throw new Error('Missing transaction hash');
93
+ }
94
+ return result;
95
+ }
96
+ catch (error) {
97
+ throw (0, error_prefix_1.prefixError)(error, POST_RAMP_ERROR_PREFIX);
98
+ }
90
99
  }
91
100
  exports.submitFiatQuotes = submitFiatQuotes;
92
101
  function getFiatOptions(messenger) {
@@ -98,28 +107,6 @@ function getFiatOptions(messenger) {
98
107
  return undefined;
99
108
  }
100
109
  }
101
- /**
102
- * Validates that the completed order's crypto asset matches the expected fiat asset.
103
- *
104
- * @param options - The validation options.
105
- * @param options.expectedAsset - The expected fiat asset derived from the transaction type.
106
- * @param options.orderCrypto - The crypto currency information from the completed order.
107
- * @param options.transactionId - Transaction ID for error reporting.
108
- */
109
- function validateOrderAsset({ expectedAsset, orderCrypto, transactionId, }) {
110
- const orderAssetId = orderCrypto?.assetId?.toLowerCase();
111
- const expectedAssetId = (0, token_1.buildCaipAssetType)(expectedAsset.chainId, expectedAsset.address).toLowerCase();
112
- const expectedChainId = expectedAssetId.split('/')[0];
113
- const orderChainId = orderCrypto?.chainId?.toLowerCase();
114
- if (orderAssetId && orderAssetId !== expectedAssetId) {
115
- throw new Error(`Fiat order asset mismatch for transaction ${transactionId}: ` +
116
- `expected ${expectedAssetId}, got ${orderAssetId}`);
117
- }
118
- if (orderChainId && orderChainId !== expectedChainId) {
119
- throw new Error(`Fiat order chain mismatch for transaction ${transactionId}: ` +
120
- `expected ${expectedChainId}, got ${orderChainId}`);
121
- }
122
- }
123
110
  /**
124
111
  * Polls the on-ramp order until it reaches a terminal status.
125
112
  *
@@ -181,25 +168,10 @@ async function submitRelayAfterFiatCompletion({ order, request, }) {
181
168
  const fiatQuote = quotes[0];
182
169
  const isDirectMusd = (0, fiat_direct_musd_1.isDirectMusdMoneyAccountQuote)(fiatQuote);
183
170
  if (isDirectMusd) {
184
- validateOrderAsset({
185
- expectedAsset: constants_1.MUSD_MONAD_FIAT_ASSET,
186
- orderCrypto: order.cryptoCurrency,
187
- transactionId,
188
- });
189
- const sourceAmountRaw = await (0, utils_2.resolveSourceAmountRaw)({
190
- messenger,
191
- order,
192
- fiatAsset: constants_1.MUSD_MONAD_FIAT_ASSET,
193
- walletAddress: transaction.txParams.from,
194
- });
195
- return await (0, fiat_direct_musd_1.submitDirectMusdVaultDeposit)({
196
- request,
197
- sourceAmountRaw,
198
- transaction,
199
- });
171
+ return await (0, fiat_direct_musd_1.submitDirectMusdAfterFiatCompletion)({ order, request });
200
172
  }
201
173
  const fiatAsset = (0, utils_2.deriveFiatAssetForFiatPayment)(transaction, messenger);
202
- validateOrderAsset({
174
+ (0, utils_2.validateOrderAsset)({
203
175
  expectedAsset: fiatAsset,
204
176
  orderCrypto: order.cryptoCurrency,
205
177
  transactionId,
@@ -212,7 +184,7 @@ async function submitRelayAfterFiatCompletion({ order, request, }) {
212
184
  walletAddress: baseRequest.from,
213
185
  });
214
186
  if (!fiatQuote.original.relayQuote) {
215
- throw new Error('Missing Relay quote for fiat submission');
187
+ throw new Error('Missing Relay quote');
216
188
  }
217
189
  const hasNestedCalldata = (transaction.nestedTransactions?.length ?? 0) >= 2;
218
190
  // Transactions with nested calldata (e.g. moneyAccountDeposit with
@@ -240,7 +212,7 @@ function getWalletAddress({ quotes, transaction, accountOverride, }) {
240
212
  ? transaction.txParams.from
241
213
  : (accountOverride ?? transaction.txParams.from);
242
214
  if (!address) {
243
- throw new Error('Missing wallet address for fiat submission');
215
+ throw new Error('Missing wallet address');
244
216
  }
245
217
  return address;
246
218
  }