@metamask/transaction-pay-controller 23.12.0 → 23.13.1
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.
- package/CHANGELOG.md +29 -1
- package/dist/helpers/TransactionPayPublishHook.cjs +9 -4
- package/dist/helpers/TransactionPayPublishHook.cjs.map +1 -1
- package/dist/helpers/TransactionPayPublishHook.d.cts.map +1 -1
- package/dist/helpers/TransactionPayPublishHook.d.mts.map +1 -1
- package/dist/helpers/TransactionPayPublishHook.mjs +9 -4
- package/dist/helpers/TransactionPayPublishHook.mjs.map +1 -1
- package/dist/strategy/fiat/FiatStrategy.cjs +12 -1
- package/dist/strategy/fiat/FiatStrategy.cjs.map +1 -1
- package/dist/strategy/fiat/FiatStrategy.d.cts.map +1 -1
- package/dist/strategy/fiat/FiatStrategy.d.mts.map +1 -1
- package/dist/strategy/fiat/FiatStrategy.mjs +12 -1
- package/dist/strategy/fiat/FiatStrategy.mjs.map +1 -1
- package/dist/strategy/fiat/fiat-direct-musd.cjs +74 -23
- package/dist/strategy/fiat/fiat-direct-musd.cjs.map +1 -1
- package/dist/strategy/fiat/fiat-direct-musd.d.cts +15 -0
- package/dist/strategy/fiat/fiat-direct-musd.d.cts.map +1 -1
- package/dist/strategy/fiat/fiat-direct-musd.d.mts +15 -0
- package/dist/strategy/fiat/fiat-direct-musd.d.mts.map +1 -1
- package/dist/strategy/fiat/fiat-direct-musd.mjs +73 -23
- package/dist/strategy/fiat/fiat-direct-musd.mjs.map +1 -1
- package/dist/strategy/fiat/fiat-submit-simple.cjs +1 -1
- package/dist/strategy/fiat/fiat-submit-simple.cjs.map +1 -1
- package/dist/strategy/fiat/fiat-submit-simple.mjs +1 -1
- package/dist/strategy/fiat/fiat-submit-simple.mjs.map +1 -1
- package/dist/strategy/fiat/fiat-submit-with-transaction-data.cjs +1 -1
- package/dist/strategy/fiat/fiat-submit-with-transaction-data.cjs.map +1 -1
- package/dist/strategy/fiat/fiat-submit-with-transaction-data.mjs +1 -1
- package/dist/strategy/fiat/fiat-submit-with-transaction-data.mjs.map +1 -1
- package/dist/strategy/fiat/fiat-submit.cjs +19 -47
- package/dist/strategy/fiat/fiat-submit.cjs.map +1 -1
- package/dist/strategy/fiat/fiat-submit.d.cts.map +1 -1
- package/dist/strategy/fiat/fiat-submit.d.mts.map +1 -1
- package/dist/strategy/fiat/fiat-submit.mjs +20 -48
- package/dist/strategy/fiat/fiat-submit.mjs.map +1 -1
- package/dist/strategy/fiat/utils.cjs +24 -1
- package/dist/strategy/fiat/utils.cjs.map +1 -1
- package/dist/strategy/fiat/utils.d.cts +14 -1
- package/dist/strategy/fiat/utils.d.cts.map +1 -1
- package/dist/strategy/fiat/utils.d.mts +14 -1
- package/dist/strategy/fiat/utils.d.mts.map +1 -1
- package/dist/strategy/fiat/utils.mjs +22 -0
- package/dist/strategy/fiat/utils.mjs.map +1 -1
- package/dist/strategy/relay/RelayStrategy.cjs +1 -7
- package/dist/strategy/relay/RelayStrategy.cjs.map +1 -1
- package/dist/strategy/relay/RelayStrategy.d.cts.map +1 -1
- package/dist/strategy/relay/RelayStrategy.d.mts.map +1 -1
- package/dist/strategy/relay/RelayStrategy.mjs +1 -7
- package/dist/strategy/relay/RelayStrategy.mjs.map +1 -1
- package/dist/strategy/relay/relay-submit.cjs +30 -7
- package/dist/strategy/relay/relay-submit.cjs.map +1 -1
- package/dist/strategy/relay/relay-submit.d.cts.map +1 -1
- package/dist/strategy/relay/relay-submit.d.mts.map +1 -1
- package/dist/strategy/relay/relay-submit.mjs +29 -6
- package/dist/strategy/relay/relay-submit.mjs.map +1 -1
- package/dist/tests/messenger-mock.d.cts +1 -1
- package/dist/tests/messenger-mock.d.mts +1 -1
- package/dist/utils/error-prefix.cjs +21 -0
- package/dist/utils/error-prefix.cjs.map +1 -0
- package/dist/utils/error-prefix.d.cts +9 -0
- package/dist/utils/error-prefix.d.cts.map +1 -0
- package/dist/utils/error-prefix.d.mts +9 -0
- package/dist/utils/error-prefix.d.mts.map +1 -0
- package/dist/utils/error-prefix.mjs +17 -0
- package/dist/utils/error-prefix.mjs.map +1 -0
- package/dist/utils/provider.cjs +28 -2
- package/dist/utils/provider.cjs.map +1 -1
- package/dist/utils/provider.d.cts.map +1 -1
- package/dist/utils/provider.d.mts.map +1 -1
- package/dist/utils/provider.mjs +29 -3
- package/dist/utils/provider.mjs.map +1 -1
- package/package.json +10 -10
|
@@ -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
|
|
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('
|
|
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
|
|
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({
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
215
|
+
throw new Error('Missing wallet address');
|
|
244
216
|
}
|
|
245
217
|
return address;
|
|
246
218
|
}
|