@metamask/transaction-pay-controller 14.0.0 → 15.0.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 +16 -1
- package/dist/strategy/relay/relay-quotes.cjs +74 -13
- package/dist/strategy/relay/relay-quotes.cjs.map +1 -1
- package/dist/strategy/relay/relay-quotes.mjs +74 -13
- package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
- package/dist/strategy/relay/relay-submit.cjs +1 -5
- package/dist/strategy/relay/relay-submit.cjs.map +1 -1
- package/dist/strategy/relay/relay-submit.mjs +1 -5
- package/dist/strategy/relay/relay-submit.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +0 -7
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +0 -7
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils/totals.cjs +0 -4
- package/dist/utils/totals.cjs.map +1 -1
- package/dist/utils/totals.d.cts.map +1 -1
- package/dist/utils/totals.d.mts.map +1 -1
- package/dist/utils/totals.mjs +0 -4
- package/dist/utils/totals.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [15.0.1]
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Estimate relay transactions separately and combine with original transaction gas at quote time ([#7933](https://github.com/MetaMask/core/pull/7933))
|
|
15
|
+
|
|
16
|
+
## [15.0.0]
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **BREAKING:** Remove `transactionGas` from `TransactionPayFees` ([#7929](https://github.com/MetaMask/core/pull/7929))
|
|
21
|
+
- The original transaction's gas cost is now included in `sourceNetwork` for post-quote flows instead of being reported separately, so gas estimation and gas-fee-token detection cover both the Relay deposit and the user's original transaction
|
|
22
|
+
|
|
10
23
|
## [14.0.0]
|
|
11
24
|
|
|
12
25
|
### Changed
|
|
@@ -373,7 +386,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
373
386
|
|
|
374
387
|
- Initial release ([#6820](https://github.com/MetaMask/core/pull/6820))
|
|
375
388
|
|
|
376
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@
|
|
389
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@15.0.1...HEAD
|
|
390
|
+
[15.0.1]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@15.0.0...@metamask/transaction-pay-controller@15.0.1
|
|
391
|
+
[15.0.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@14.0.0...@metamask/transaction-pay-controller@15.0.0
|
|
377
392
|
[14.0.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@13.0.0...@metamask/transaction-pay-controller@14.0.0
|
|
378
393
|
[13.0.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@12.2.0...@metamask/transaction-pay-controller@13.0.0
|
|
379
394
|
[12.2.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@12.1.0...@metamask/transaction-pay-controller@12.2.0
|
|
@@ -199,7 +199,7 @@ async function normalizeQuote(quote, request, fullRequest) {
|
|
|
199
199
|
const provider = subsidizedFeeUsd.gt(0)
|
|
200
200
|
? { usd: '0', fiat: '0' }
|
|
201
201
|
: getFiatValueFromUsd(calculateProviderFee(quote), usdToFiatRate);
|
|
202
|
-
const { gasLimits, isGasFeeToken: isSourceGasFeeToken, ...sourceNetwork } = await calculateSourceNetworkCost(quote, messenger, request);
|
|
202
|
+
const { gasLimits, isGasFeeToken: isSourceGasFeeToken, ...sourceNetwork } = await calculateSourceNetworkCost(quote, messenger, request, fullRequest.transaction);
|
|
203
203
|
const targetNetwork = {
|
|
204
204
|
usd: '0',
|
|
205
205
|
fiat: '0',
|
|
@@ -295,19 +295,26 @@ function getFiatRates(messenger, request) {
|
|
|
295
295
|
/**
|
|
296
296
|
* Calculates source network cost from a Relay quote.
|
|
297
297
|
*
|
|
298
|
+
* For post-quote flows (e.g. predictWithdraw), the cost also includes the
|
|
299
|
+
* original transaction's gas (the user's Polygon USDC.e transfer) in addition
|
|
300
|
+
* to the Relay deposit transaction gas, by appending the original
|
|
301
|
+
* transaction's params so that gas estimation and gas-fee-token logic handle
|
|
302
|
+
* both transactions together.
|
|
303
|
+
*
|
|
298
304
|
* @param quote - Relay quote.
|
|
299
305
|
* @param messenger - Controller messenger.
|
|
300
306
|
* @param request - Quote request.
|
|
307
|
+
* @param transaction - Original transaction metadata.
|
|
301
308
|
* @returns Total source network cost in USD and fiat.
|
|
302
309
|
*/
|
|
303
|
-
async function calculateSourceNetworkCost(quote, messenger, request) {
|
|
310
|
+
async function calculateSourceNetworkCost(quote, messenger, request, transaction) {
|
|
304
311
|
const { from, sourceChainId, sourceTokenAddress } = request;
|
|
305
|
-
const
|
|
312
|
+
const relayParams = quote.steps
|
|
306
313
|
.flatMap((step) => step.items)
|
|
307
314
|
.map((item) => item.data);
|
|
308
315
|
const { relayDisabledGasStationChains } = (0, feature_flags_1.getFeatureFlags)(messenger);
|
|
309
|
-
const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } =
|
|
310
|
-
const { totalGasEstimate, totalGasLimit, gasLimits } = await calculateSourceNetworkGasLimit(
|
|
316
|
+
const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } = relayParams[0];
|
|
317
|
+
const { totalGasEstimate, totalGasLimit, gasLimits } = await calculateSourceNetworkGasLimit(relayParams, messenger, request.isPostQuote ? transaction : undefined);
|
|
311
318
|
log('Gas limit', {
|
|
312
319
|
totalGasEstimate,
|
|
313
320
|
totalGasLimit,
|
|
@@ -370,7 +377,8 @@ async function calculateSourceNetworkCost(quote, messenger, request) {
|
|
|
370
377
|
return result;
|
|
371
378
|
}
|
|
372
379
|
let finalAmount = gasFeeToken.amount;
|
|
373
|
-
|
|
380
|
+
const hasMultipleTransactions = relayParams.length > 1 || gasLimits.length > 1;
|
|
381
|
+
if (hasMultipleTransactions) {
|
|
374
382
|
const gasRate = new bignumber_js_1.BigNumber(gasFeeToken.amount, 16).dividedBy(gasFeeToken.gas, 16);
|
|
375
383
|
const finalAmountValue = gasRate.multipliedBy(totalGasEstimate);
|
|
376
384
|
finalAmount = (0, controller_utils_1.toHex)(finalAmountValue.toFixed(0));
|
|
@@ -400,17 +408,70 @@ async function calculateSourceNetworkCost(quote, messenger, request) {
|
|
|
400
408
|
};
|
|
401
409
|
}
|
|
402
410
|
/**
|
|
403
|
-
* Calculate the total gas limit for the source network
|
|
411
|
+
* Calculate the total gas limit for the source network.
|
|
404
412
|
*
|
|
405
|
-
*
|
|
413
|
+
* For post-quote flows (e.g. predict withdrawals), the original transaction's
|
|
414
|
+
* gas is combined with the relay gas so that source network cost accounts for
|
|
415
|
+
* both the user's transaction and the relay transactions.
|
|
416
|
+
*
|
|
417
|
+
* @param params - Array of relay transaction parameters.
|
|
406
418
|
* @param messenger - Controller messenger.
|
|
407
|
-
* @
|
|
419
|
+
* @param postQuoteTransaction - Original transaction for post-quote flows.
|
|
420
|
+
* When provided, its gas is included in the returned totals.
|
|
421
|
+
* @returns Total gas estimates and per-transaction gas limits.
|
|
422
|
+
*/
|
|
423
|
+
async function calculateSourceNetworkGasLimit(params, messenger, postQuoteTransaction) {
|
|
424
|
+
const relayGas = params.length === 1
|
|
425
|
+
? await calculateSourceNetworkGasLimitSingle(params[0], messenger)
|
|
426
|
+
: await calculateSourceNetworkGasLimitBatch(params, messenger);
|
|
427
|
+
if (!postQuoteTransaction?.txParams.to) {
|
|
428
|
+
return relayGas;
|
|
429
|
+
}
|
|
430
|
+
return combinePostQuoteGas(relayGas, params.length, postQuoteTransaction);
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Combine the original transaction's gas with relay gas for post-quote flows.
|
|
434
|
+
*
|
|
435
|
+
* Prefers gas from `nestedTransactions` (preserves the caller-provided value)
|
|
436
|
+
* since TransactionController may re-estimate `txParams.gas` during batch
|
|
437
|
+
* creation.
|
|
438
|
+
*
|
|
439
|
+
* @param relayGas - Gas estimates from relay transactions.
|
|
440
|
+
* @param relayGas.totalGasEstimate - Estimated gas total.
|
|
441
|
+
* @param relayGas.totalGasLimit - Maximum gas total.
|
|
442
|
+
* @param relayGas.gasLimits - Per-transaction gas limits.
|
|
443
|
+
* @param relayParamCount - Number of relay transaction parameters.
|
|
444
|
+
* @param transaction - Original transaction metadata.
|
|
445
|
+
* @returns Combined gas estimates including the original transaction.
|
|
408
446
|
*/
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
447
|
+
function combinePostQuoteGas(relayGas, relayParamCount, transaction) {
|
|
448
|
+
const nestedGas = transaction.nestedTransactions?.find((tx) => tx.gas)?.gas;
|
|
449
|
+
const rawGas = nestedGas ?? transaction.txParams.gas;
|
|
450
|
+
const originalTxGas = rawGas ? new bignumber_js_1.BigNumber(rawGas).toNumber() : undefined;
|
|
451
|
+
if (originalTxGas === undefined) {
|
|
452
|
+
return relayGas;
|
|
453
|
+
}
|
|
454
|
+
let { gasLimits } = relayGas;
|
|
455
|
+
const isEIP7702 = gasLimits.length === 1 && relayParamCount > 1;
|
|
456
|
+
if (isEIP7702) {
|
|
457
|
+
// EIP-7702: single combined gas limit — add the original tx gas
|
|
458
|
+
// so the atomic batch covers both relay and original transactions.
|
|
459
|
+
gasLimits = [gasLimits[0] + originalTxGas];
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
// Non-7702: individual gas limits — prepend the original tx gas
|
|
463
|
+
// so the list order matches relay-submit's transaction order.
|
|
464
|
+
gasLimits = [originalTxGas, ...gasLimits];
|
|
412
465
|
}
|
|
413
|
-
|
|
466
|
+
const totalGasEstimate = relayGas.totalGasEstimate + originalTxGas;
|
|
467
|
+
const totalGasLimit = relayGas.totalGasLimit + originalTxGas;
|
|
468
|
+
log('Combined original tx gas with relay gas', {
|
|
469
|
+
originalTxGas,
|
|
470
|
+
isEIP7702,
|
|
471
|
+
gasLimits,
|
|
472
|
+
totalGasLimit,
|
|
473
|
+
});
|
|
474
|
+
return { totalGasEstimate, totalGasLimit, gasLimits };
|
|
414
475
|
}
|
|
415
476
|
/**
|
|
416
477
|
* Calculate the provider fee for a Relay quote.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay-quotes.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable require-atomic-updates */\n\nimport { Interface } from '@ethersproject/abi';\nimport { successfulFetch, toHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TOKEN_TRANSFER_FOUR_BYTE } from './constants';\nimport type { RelayQuote, RelayQuoteRequest } from './types';\nimport { TransactionPayStrategy } from '../..';\nimport type {\n BatchTransactionParams,\n TransactionMeta,\n} from '../../../../transaction-controller/src';\nimport {\n ARBITRUM_USDC_ADDRESS,\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_HYPERCORE,\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n STABLECOINS,\n} from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n Amount,\n FiatRates,\n FiatValue,\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport {\n getEIP7702SupportedChains,\n getFeatureFlags,\n getGasBuffer,\n getSlippage,\n} from '../../utils/feature-flags';\nimport { calculateGasCost, calculateGasFeeTokenCost } from '../../utils/gas';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n} from '../../utils/token';\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n/**\n * Fetches Relay quotes.\n *\n * @param request - Request object.\n * @returns Array of quotes.\n */\nexport async function getRelayQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>[]> {\n const { requests } = request;\n\n log('Fetching quotes', requests);\n\n try {\n const normalizedRequests = requests\n // Ignore gas fee token requests (which have both target=0 and source=0)\n // but keep post-quote requests (identified by isPostQuote flag)\n .filter(\n (singleRequest) =>\n singleRequest.targetAmountMinimum !== '0' ||\n singleRequest.isPostQuote,\n )\n .map((singleRequest) => normalizeRequest(singleRequest));\n\n log('Normalized requests', normalizedRequests);\n\n return await Promise.all(\n normalizedRequests.map((singleRequest) =>\n getSingleQuote(singleRequest, request),\n ),\n );\n } catch (error) {\n log('Error fetching quotes', { error });\n throw new Error(`Failed to fetch Relay quotes: ${String(error)}`);\n }\n}\n\n/**\n * Fetches a single Relay quote.\n *\n * @param request - Quote request.\n * @param fullRequest - Full quotes request.\n * @returns Single quote.\n */\nasync function getSingleQuote(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger, transaction } = fullRequest;\n\n const {\n from,\n isMaxAmount,\n sourceChainId,\n sourceTokenAddress,\n sourceTokenAmount,\n targetAmountMinimum,\n targetChainId,\n targetTokenAddress,\n } = request;\n\n const slippageDecimal = getSlippage(\n messenger,\n sourceChainId,\n sourceTokenAddress,\n );\n\n const slippageTolerance = new BigNumber(slippageDecimal * 100 * 100).toFixed(\n 0,\n );\n\n try {\n // For post-quote or max amount flows, use EXACT_INPUT - user specifies how much to send,\n // and we show them how much they'll receive after fees.\n // For regular flows with a target amount, use EXPECTED_OUTPUT.\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n const useExactInput = isMaxAmount || request.isPostQuote;\n\n const body: RelayQuoteRequest = {\n amount: useExactInput ? sourceTokenAmount : targetAmountMinimum,\n destinationChainId: Number(targetChainId),\n destinationCurrency: targetTokenAddress,\n originChainId: Number(sourceChainId),\n originCurrency: sourceTokenAddress,\n recipient: from,\n slippageTolerance,\n tradeType: useExactInput ? 'EXACT_INPUT' : 'EXPECTED_OUTPUT',\n user: from,\n };\n\n // Skip transaction processing for post-quote flows - the original transaction\n // will be included in the batch separately, not as part of the quote\n if (!request.isPostQuote) {\n await processTransactions(transaction, request, body, messenger);\n }\n\n const url = getFeatureFlags(messenger).relayQuoteUrl;\n\n log('Request body', { body, url });\n\n const response = await successfulFetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const quote = (await response.json()) as RelayQuote;\n quote.request = body;\n\n log('Fetched relay quote', quote);\n\n return await normalizeQuote(quote, request, fullRequest);\n } catch (error) {\n log('Error fetching relay quote', error);\n throw error;\n }\n}\n\n/**\n * Add tranasction data to request body if needed.\n *\n * @param transaction - Transaction metadata.\n * @param request - Quote request.\n * @param requestBody - Request body to populate.\n * @param messenger - Controller messenger.\n */\nasync function processTransactions(\n transaction: TransactionMeta,\n request: QuoteRequest,\n requestBody: RelayQuoteRequest,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { nestedTransactions, txParams } = transaction;\n const { isMaxAmount, targetChainId } = request;\n const data = txParams?.data as Hex | undefined;\n\n const singleData =\n nestedTransactions?.length === 1 ? nestedTransactions[0].data : data;\n\n const isHypercore = targetChainId === CHAIN_ID_HYPERCORE;\n\n const isTokenTransfer =\n !isHypercore && Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));\n\n if (isTokenTransfer) {\n requestBody.recipient = getTransferRecipient(singleData as Hex);\n\n log('Updating recipient as token transfer', requestBody.recipient);\n }\n\n const hasNoData = singleData === undefined || singleData === '0x';\n const skipDelegation = hasNoData || isTokenTransfer || isHypercore;\n\n if (skipDelegation) {\n log('Skipping delegation as token transfer or Hypercore deposit');\n return;\n }\n\n if (isMaxAmount) {\n throw new Error('Max amount quotes do not support included transactions');\n }\n\n const delegation = await messenger.call(\n 'TransactionPayController:getDelegationTransaction',\n { transaction },\n );\n\n const normalizedAuthorizationList = delegation.authorizationList?.map(\n (a) => ({\n ...a,\n chainId: Number(a.chainId),\n nonce: Number(a.nonce),\n r: a.r as Hex,\n s: a.s as Hex,\n yParity: Number(a.yParity),\n }),\n );\n\n requestBody.authorizationList = normalizedAuthorizationList;\n requestBody.tradeType = 'EXACT_OUTPUT';\n\n const tokenTransferData = nestedTransactions?.find((nestedTx) =>\n nestedTx.data?.startsWith(TOKEN_TRANSFER_FOUR_BYTE),\n )?.data;\n\n // If the transactions include a token transfer, change the recipient\n // so any extra dust is also sent to the same address, rather than back to the user.\n if (tokenTransferData) {\n requestBody.recipient = getTransferRecipient(tokenTransferData);\n requestBody.refundTo = request.from;\n }\n\n requestBody.txs = [\n {\n to: request.targetTokenAddress,\n data: buildTokenTransferData(request.from, request.targetAmountMinimum),\n value: '0x0',\n },\n {\n to: delegation.to,\n data: delegation.data,\n value: delegation.value,\n },\n ];\n}\n\n/**\n * Normalizes requests for Relay.\n *\n * @param request - Quote request to normalize.\n * @returns Normalized request.\n */\nfunction normalizeRequest(request: QuoteRequest): QuoteRequest {\n const newRequest = {\n ...request,\n };\n\n const isHyperliquidDeposit =\n !request.isPostQuote &&\n request.targetChainId === CHAIN_ID_ARBITRUM &&\n request.targetTokenAddress.toLowerCase() ===\n ARBITRUM_USDC_ADDRESS.toLowerCase();\n\n const isPolygonNativeSource =\n request.sourceChainId === CHAIN_ID_POLYGON &&\n request.sourceTokenAddress === getNativeToken(request.sourceChainId);\n\n if (isPolygonNativeSource) {\n newRequest.sourceTokenAddress = NATIVE_TOKEN_ADDRESS;\n }\n\n if (isHyperliquidDeposit) {\n newRequest.targetChainId = CHAIN_ID_HYPERCORE;\n newRequest.targetTokenAddress = '0x00000000000000000000000000000000';\n newRequest.targetAmountMinimum = new BigNumber(request.targetAmountMinimum)\n .shiftedBy(2)\n .toString(10);\n\n log('Converting Arbitrum Hyperliquid deposit to direct deposit', {\n originalRequest: request,\n normalizedRequest: newRequest,\n });\n }\n\n return newRequest;\n}\n\n/**\n * Normalizes a Relay quote into a TransactionPayQuote.\n *\n * @param quote - Relay quote.\n * @param request - Original quote request.\n * @param fullRequest - Full quotes request.\n * @returns Normalized quote.\n */\nasync function normalizeQuote(\n quote: RelayQuote,\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger } = fullRequest;\n const { details } = quote;\n const { currencyIn, currencyOut } = details;\n\n const { usdToFiatRate } = getFiatRates(messenger, request);\n\n const dust = getFiatValueFromUsd(\n calculateDustUsd(quote, request),\n usdToFiatRate,\n );\n\n const subsidizedFeeUsd = getSubsidizedFeeAmountUsd(quote);\n\n const provider = subsidizedFeeUsd.gt(0)\n ? { usd: '0', fiat: '0' }\n : getFiatValueFromUsd(calculateProviderFee(quote), usdToFiatRate);\n\n const {\n gasLimits,\n isGasFeeToken: isSourceGasFeeToken,\n ...sourceNetwork\n } = await calculateSourceNetworkCost(quote, messenger, request);\n\n const targetNetwork = {\n usd: '0',\n fiat: '0',\n };\n\n const sourceAmount: Amount = {\n human: currencyIn.amountFormatted,\n raw: currencyIn.amount,\n ...getFiatValueFromUsd(new BigNumber(currencyIn.amountUsd), usdToFiatRate),\n };\n\n const isTargetStablecoin = isStablecoin(\n request.targetChainId,\n request.targetTokenAddress,\n );\n\n const additionalTargetAmountUsd =\n quote.request.tradeType === 'EXACT_INPUT'\n ? subsidizedFeeUsd\n : new BigNumber(0);\n\n if (additionalTargetAmountUsd.gt(0)) {\n log(\n 'Including subsidized fee in target amount',\n additionalTargetAmountUsd.toString(10),\n );\n }\n\n const baseTargetAmountUsd = isTargetStablecoin\n ? new BigNumber(currencyOut.amountFormatted)\n : new BigNumber(currencyOut.amountUsd);\n\n const targetAmountUsd = baseTargetAmountUsd.plus(additionalTargetAmountUsd);\n\n const targetAmount = getFiatValueFromUsd(targetAmountUsd, usdToFiatRate);\n\n const metamask = {\n gasLimits,\n };\n\n return {\n dust,\n estimatedDuration: details.timeEstimate,\n fees: {\n isSourceGasFeeToken,\n provider,\n sourceNetwork,\n targetNetwork,\n },\n original: {\n ...quote,\n metamask,\n },\n request,\n sourceAmount,\n targetAmount,\n strategy: TransactionPayStrategy.Relay,\n };\n}\n\n/**\n * Calculate dust USD value.\n *\n * @param quote - Relay quote.\n * @param request - Quote request.\n * @returns Dust value in USD and fiat.\n */\nfunction calculateDustUsd(quote: RelayQuote, request: QuoteRequest): BigNumber {\n const { currencyOut } = quote.details;\n const { amountUsd, amountFormatted, minimumAmount } = currencyOut;\n const { decimals: targetDecimals } = currencyOut.currency;\n\n const targetUsdRate = new BigNumber(amountUsd).dividedBy(amountFormatted);\n\n const dustRaw = new BigNumber(minimumAmount).minus(\n request.targetAmountMinimum,\n );\n\n return dustRaw.shiftedBy(-targetDecimals).multipliedBy(targetUsdRate);\n}\n\n/**\n * Converts USD value to fiat value.\n *\n * @param usdValue - USD value.\n * @param usdToFiatRate - USD to fiat rate.\n * @returns Fiat value.\n */\nfunction getFiatValueFromUsd(\n usdValue: BigNumber,\n usdToFiatRate: BigNumber,\n): FiatValue {\n const fiatValue = usdValue.multipliedBy(usdToFiatRate);\n\n return {\n usd: usdValue.toString(10),\n fiat: fiatValue.toString(10),\n };\n}\n\n/**\n * Calculates USD to fiat rate.\n *\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @returns USD to fiat rate.\n */\nfunction getFiatRates(\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): {\n sourceFiatRate: FiatRates;\n usdToFiatRate: BigNumber;\n} {\n const { sourceChainId, sourceTokenAddress } = request;\n\n const finalSourceTokenAddress =\n sourceChainId === CHAIN_ID_POLYGON &&\n sourceTokenAddress === NATIVE_TOKEN_ADDRESS\n ? getNativeToken(sourceChainId)\n : sourceTokenAddress;\n\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n finalSourceTokenAddress,\n sourceChainId,\n );\n\n if (!sourceFiatRate) {\n throw new Error('Source token fiat rate not found');\n }\n\n const usdToFiatRate = new BigNumber(sourceFiatRate.fiatRate).dividedBy(\n sourceFiatRate.usdRate,\n );\n\n return { sourceFiatRate, usdToFiatRate };\n}\n\n/**\n * Calculates source network cost from a Relay quote.\n *\n * @param quote - Relay quote.\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @returns Total source network cost in USD and fiat.\n */\nasync function calculateSourceNetworkCost(\n quote: RelayQuote,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): Promise<\n TransactionPayQuote<RelayQuote>['fees']['sourceNetwork'] & {\n gasLimits: number[];\n isGasFeeToken?: boolean;\n }\n> {\n const { from, sourceChainId, sourceTokenAddress } = request;\n\n const allParams = quote.steps\n .flatMap((step) => step.items)\n .map((item) => item.data);\n\n const { relayDisabledGasStationChains } = getFeatureFlags(messenger);\n\n const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } =\n allParams[0];\n\n const { totalGasEstimate, totalGasLimit, gasLimits } =\n await calculateSourceNetworkGasLimit(allParams, messenger);\n\n log('Gas limit', {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n });\n\n const estimate = calculateGasCost({\n chainId,\n gas: totalGasEstimate,\n maxFeePerGas,\n maxPriorityFeePerGas,\n messenger,\n });\n\n const max = calculateGasCost({\n chainId,\n gas: totalGasLimit,\n maxFeePerGas,\n maxPriorityFeePerGas,\n messenger,\n isMax: true,\n });\n\n const nativeBalance = getTokenBalance(\n messenger,\n from,\n sourceChainId,\n getNativeToken(sourceChainId),\n );\n\n const result = { estimate, max, gasLimits };\n\n if (new BigNumber(nativeBalance).isGreaterThanOrEqualTo(max.raw)) {\n return result;\n }\n\n if (relayDisabledGasStationChains.includes(sourceChainId)) {\n log('Skipping gas station as disabled chain', {\n sourceChainId,\n disabledChainIds: relayDisabledGasStationChains,\n });\n\n return result;\n }\n\n const supportedChains = getEIP7702SupportedChains(messenger);\n const chainSupportsGasStation = supportedChains.some(\n (supportedChainId) =>\n supportedChainId.toLowerCase() === sourceChainId.toLowerCase(),\n );\n\n if (!chainSupportsGasStation) {\n log('Skipping gas station as chain does not support EIP-7702', {\n sourceChainId,\n });\n\n return result;\n }\n\n log('Checking gas fee tokens as insufficient native balance', {\n nativeBalance,\n max: max.raw,\n });\n\n const gasFeeTokens = await messenger.call(\n 'TransactionController:getGasFeeTokens',\n {\n chainId: sourceChainId,\n data,\n from,\n to,\n value: toHex(value ?? '0'),\n },\n );\n\n log('Source gas fee tokens', { gasFeeTokens });\n\n const gasFeeToken = gasFeeTokens.find(\n (singleGasFeeToken) =>\n singleGasFeeToken.tokenAddress.toLowerCase() ===\n sourceTokenAddress.toLowerCase(),\n );\n\n if (!gasFeeToken) {\n log('No matching gas fee token found', {\n sourceTokenAddress,\n gasFeeTokens,\n });\n\n return result;\n }\n\n let finalAmount = gasFeeToken.amount;\n\n if (allParams.length > 1) {\n const gasRate = new BigNumber(gasFeeToken.amount, 16).dividedBy(\n gasFeeToken.gas,\n 16,\n );\n\n const finalAmountValue = gasRate.multipliedBy(totalGasEstimate);\n\n finalAmount = toHex(finalAmountValue.toFixed(0));\n\n log('Estimated gas fee token amount for batch', {\n finalAmount: finalAmountValue.toString(10),\n gasRate: gasRate.toString(10),\n totalGasEstimate,\n });\n }\n\n const finalGasFeeToken = { ...gasFeeToken, amount: finalAmount };\n\n const gasFeeTokenCost = calculateGasFeeTokenCost({\n chainId: sourceChainId,\n gasFeeToken: finalGasFeeToken,\n messenger,\n });\n\n if (!gasFeeTokenCost) {\n return result;\n }\n\n log('Using gas fee token for source network', {\n gasFeeTokenCost,\n });\n\n return {\n isGasFeeToken: true,\n estimate: gasFeeTokenCost,\n max: gasFeeTokenCost,\n gasLimits,\n };\n}\n\n/**\n * Calculate the total gas limit for the source network transactions.\n *\n * @param params - Array of transaction parameters.\n * @param messenger - Controller messenger.\n * @returns - Total gas limit.\n */\nasync function calculateSourceNetworkGasLimit(\n params: RelayQuote['steps'][0]['items'][0]['data'][],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n}> {\n if (params.length === 1) {\n return calculateSourceNetworkGasLimitSingle(params[0], messenger);\n }\n\n return calculateSourceNetworkGasLimitBatch(params, messenger);\n}\n\n/**\n * Calculate the provider fee for a Relay quote.\n *\n * @param quote - Relay quote.\n * @returns - Provider fee in USD.\n */\nfunction calculateProviderFee(quote: RelayQuote): BigNumber {\n return new BigNumber(quote.details.totalImpact.usd).abs();\n}\n\n/**\n * Build token transfer data.\n *\n * @param recipient - Recipient address.\n * @param amountRaw - Amount in raw format.\n * @returns Token transfer data.\n */\nfunction buildTokenTransferData(recipient: Hex, amountRaw: string): Hex {\n return new Interface([\n 'function transfer(address to, uint256 amount)',\n ]).encodeFunctionData('transfer', [recipient, amountRaw]) as Hex;\n}\n\n/**\n * Get transfer recipient from token transfer data.\n *\n * @param data - Token transfer data.\n * @returns Transfer recipient.\n */\nfunction getTransferRecipient(data: Hex): Hex {\n return new Interface(['function transfer(address to, uint256 amount)'])\n .decodeFunctionData('transfer', data)\n .to.toLowerCase();\n}\n\nasync function calculateSourceNetworkGasLimitSingle(\n params: RelayQuote['steps'][0]['items'][0]['data'],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n}> {\n const paramGasLimit = params.gas\n ? new BigNumber(params.gas).toNumber()\n : undefined;\n\n if (paramGasLimit) {\n log('Using single gas limit from params', { paramGasLimit });\n\n return {\n totalGasEstimate: paramGasLimit,\n totalGasLimit: paramGasLimit,\n gasLimits: [paramGasLimit],\n };\n }\n\n try {\n const {\n chainId: chainIdNumber,\n data,\n from,\n to,\n value: valueString,\n } = params;\n\n const chainId = toHex(chainIdNumber);\n const value = toHex(valueString ?? '0');\n const gasBuffer = getGasBuffer(messenger, chainId);\n\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n const { gas: gasHex, simulationFails } = await messenger.call(\n 'TransactionController:estimateGas',\n { from, data, to, value },\n networkClientId,\n );\n\n const estimatedGas = new BigNumber(gasHex).toNumber();\n const bufferedGas = Math.ceil(estimatedGas * gasBuffer);\n\n if (!simulationFails) {\n log('Estimated gas limit for single transaction', {\n chainId,\n estimatedGas,\n bufferedGas,\n gasBuffer,\n });\n\n return {\n totalGasEstimate: bufferedGas,\n totalGasLimit: bufferedGas,\n gasLimits: [bufferedGas],\n };\n }\n } catch (error) {\n log('Failed to estimate gas limit for single transaction', error);\n }\n\n const fallbackGas = getFeatureFlags(messenger).relayFallbackGas;\n\n log('Using fallback gas for single transaction', { fallbackGas });\n\n return {\n totalGasEstimate: fallbackGas.estimate,\n totalGasLimit: fallbackGas.max,\n gasLimits: [fallbackGas.max],\n };\n}\n\n/**\n * Calculate the gas limits for a batch of transactions.\n *\n * @param params - Array of transaction parameters.\n * @param messenger - Controller messenger.\n * @returns - Gas limits.\n */\nasync function calculateSourceNetworkGasLimitBatch(\n params: RelayQuote['steps'][0]['items'][0]['data'][],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n}> {\n try {\n const { chainId: chainIdNumber, from } = params[0];\n const chainId = toHex(chainIdNumber);\n const gasBuffer = getGasBuffer(messenger, chainId);\n\n const transactions: BatchTransactionParams[] = params.map(\n (singleParams) => ({\n ...singleParams,\n gas: singleParams.gas ? toHex(singleParams.gas) : undefined,\n maxFeePerGas: undefined,\n maxPriorityFeePerGas: undefined,\n value: toHex(singleParams.value ?? '0'),\n }),\n );\n\n const paramGasLimits = params.map((singleParams) =>\n singleParams.gas ? new BigNumber(singleParams.gas).toNumber() : undefined,\n );\n\n const { totalGasLimit, gasLimits } = await messenger.call(\n 'TransactionController:estimateGasBatch',\n {\n chainId,\n from,\n transactions,\n },\n );\n\n const bufferedGasLimits = gasLimits.map((limit, index) => {\n const useBuffer =\n gasLimits.length === 1 || paramGasLimits[index] !== gasLimits[index];\n\n const buffer = useBuffer ? gasBuffer : 1;\n\n return Math.ceil(limit * buffer);\n });\n\n const bufferedTotalGasLimit = bufferedGasLimits.reduce(\n (acc, limit) => acc + limit,\n 0,\n );\n\n log('Estimated gas limit for batch', {\n chainId,\n totalGasLimit,\n gasLimits,\n bufferedTotalGasLimit,\n bufferedGasLimits,\n gasBuffer,\n });\n\n return {\n totalGasEstimate: bufferedTotalGasLimit,\n totalGasLimit: bufferedTotalGasLimit,\n gasLimits: bufferedGasLimits,\n };\n } catch (error) {\n log('Failed to estimate gas limit for batch', error);\n }\n\n const fallbackGas = getFeatureFlags(messenger).relayFallbackGas;\n\n const totalGasEstimate = params.reduce((acc, singleParams) => {\n const gas = singleParams.gas ?? fallbackGas.estimate;\n return acc + new BigNumber(gas).toNumber();\n }, 0);\n\n const gasLimits = params.map((singleParams) => {\n const gas = singleParams.gas ?? fallbackGas.max;\n return new BigNumber(gas).toNumber();\n });\n\n const totalGasLimit = gasLimits.reduce(\n (acc, singleGasLimit) => acc + singleGasLimit,\n 0,\n );\n\n log('Using fallback gas for batch', {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n });\n\n return {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n };\n}\n\nfunction getSubsidizedFeeAmountUsd(quote: RelayQuote): BigNumber {\n const subsidizedFee = quote.fees?.subsidized;\n const amountUsd = new BigNumber(subsidizedFee?.amountUsd ?? '0');\n const amountFormatted = new BigNumber(subsidizedFee?.amountFormatted ?? '0');\n\n if (!subsidizedFee || amountUsd.isZero()) {\n return new BigNumber(0);\n }\n\n const isSubsidizedStablecoin = isStablecoin(\n toHex(subsidizedFee.currency.chainId),\n subsidizedFee.currency.address,\n );\n\n return isSubsidizedStablecoin ? amountFormatted : amountUsd;\n}\n\nfunction isStablecoin(chainId: string, tokenAddress: string): boolean {\n return Boolean(\n STABLECOINS[chainId as Hex]?.includes(tokenAddress.toLowerCase() as Hex),\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"relay-quotes.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable require-atomic-updates */\n\nimport { Interface } from '@ethersproject/abi';\nimport { successfulFetch, toHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TOKEN_TRANSFER_FOUR_BYTE } from './constants';\nimport type { RelayQuote, RelayQuoteRequest } from './types';\nimport { TransactionPayStrategy } from '../..';\nimport type {\n BatchTransactionParams,\n TransactionMeta,\n} from '../../../../transaction-controller/src';\nimport {\n ARBITRUM_USDC_ADDRESS,\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_HYPERCORE,\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n STABLECOINS,\n} from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n Amount,\n FiatRates,\n FiatValue,\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport {\n getEIP7702SupportedChains,\n getFeatureFlags,\n getGasBuffer,\n getSlippage,\n} from '../../utils/feature-flags';\nimport { calculateGasCost, calculateGasFeeTokenCost } from '../../utils/gas';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n} from '../../utils/token';\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n/**\n * Fetches Relay quotes.\n *\n * @param request - Request object.\n * @returns Array of quotes.\n */\nexport async function getRelayQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>[]> {\n const { requests } = request;\n\n log('Fetching quotes', requests);\n\n try {\n const normalizedRequests = requests\n // Ignore gas fee token requests (which have both target=0 and source=0)\n // but keep post-quote requests (identified by isPostQuote flag)\n .filter(\n (singleRequest) =>\n singleRequest.targetAmountMinimum !== '0' ||\n singleRequest.isPostQuote,\n )\n .map((singleRequest) => normalizeRequest(singleRequest));\n\n log('Normalized requests', normalizedRequests);\n\n return await Promise.all(\n normalizedRequests.map((singleRequest) =>\n getSingleQuote(singleRequest, request),\n ),\n );\n } catch (error) {\n log('Error fetching quotes', { error });\n throw new Error(`Failed to fetch Relay quotes: ${String(error)}`);\n }\n}\n\n/**\n * Fetches a single Relay quote.\n *\n * @param request - Quote request.\n * @param fullRequest - Full quotes request.\n * @returns Single quote.\n */\nasync function getSingleQuote(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger, transaction } = fullRequest;\n\n const {\n from,\n isMaxAmount,\n sourceChainId,\n sourceTokenAddress,\n sourceTokenAmount,\n targetAmountMinimum,\n targetChainId,\n targetTokenAddress,\n } = request;\n\n const slippageDecimal = getSlippage(\n messenger,\n sourceChainId,\n sourceTokenAddress,\n );\n\n const slippageTolerance = new BigNumber(slippageDecimal * 100 * 100).toFixed(\n 0,\n );\n\n try {\n // For post-quote or max amount flows, use EXACT_INPUT - user specifies how much to send,\n // and we show them how much they'll receive after fees.\n // For regular flows with a target amount, use EXPECTED_OUTPUT.\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n const useExactInput = isMaxAmount || request.isPostQuote;\n\n const body: RelayQuoteRequest = {\n amount: useExactInput ? sourceTokenAmount : targetAmountMinimum,\n destinationChainId: Number(targetChainId),\n destinationCurrency: targetTokenAddress,\n originChainId: Number(sourceChainId),\n originCurrency: sourceTokenAddress,\n recipient: from,\n slippageTolerance,\n tradeType: useExactInput ? 'EXACT_INPUT' : 'EXPECTED_OUTPUT',\n user: from,\n };\n\n // Skip transaction processing for post-quote flows - the original transaction\n // will be included in the batch separately, not as part of the quote\n if (!request.isPostQuote) {\n await processTransactions(transaction, request, body, messenger);\n }\n\n const url = getFeatureFlags(messenger).relayQuoteUrl;\n\n log('Request body', { body, url });\n\n const response = await successfulFetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const quote = (await response.json()) as RelayQuote;\n quote.request = body;\n\n log('Fetched relay quote', quote);\n\n return await normalizeQuote(quote, request, fullRequest);\n } catch (error) {\n log('Error fetching relay quote', error);\n throw error;\n }\n}\n\n/**\n * Add tranasction data to request body if needed.\n *\n * @param transaction - Transaction metadata.\n * @param request - Quote request.\n * @param requestBody - Request body to populate.\n * @param messenger - Controller messenger.\n */\nasync function processTransactions(\n transaction: TransactionMeta,\n request: QuoteRequest,\n requestBody: RelayQuoteRequest,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { nestedTransactions, txParams } = transaction;\n const { isMaxAmount, targetChainId } = request;\n const data = txParams?.data as Hex | undefined;\n\n const singleData =\n nestedTransactions?.length === 1 ? nestedTransactions[0].data : data;\n\n const isHypercore = targetChainId === CHAIN_ID_HYPERCORE;\n\n const isTokenTransfer =\n !isHypercore && Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));\n\n if (isTokenTransfer) {\n requestBody.recipient = getTransferRecipient(singleData as Hex);\n\n log('Updating recipient as token transfer', requestBody.recipient);\n }\n\n const hasNoData = singleData === undefined || singleData === '0x';\n const skipDelegation = hasNoData || isTokenTransfer || isHypercore;\n\n if (skipDelegation) {\n log('Skipping delegation as token transfer or Hypercore deposit');\n return;\n }\n\n if (isMaxAmount) {\n throw new Error('Max amount quotes do not support included transactions');\n }\n\n const delegation = await messenger.call(\n 'TransactionPayController:getDelegationTransaction',\n { transaction },\n );\n\n const normalizedAuthorizationList = delegation.authorizationList?.map(\n (a) => ({\n ...a,\n chainId: Number(a.chainId),\n nonce: Number(a.nonce),\n r: a.r as Hex,\n s: a.s as Hex,\n yParity: Number(a.yParity),\n }),\n );\n\n requestBody.authorizationList = normalizedAuthorizationList;\n requestBody.tradeType = 'EXACT_OUTPUT';\n\n const tokenTransferData = nestedTransactions?.find((nestedTx) =>\n nestedTx.data?.startsWith(TOKEN_TRANSFER_FOUR_BYTE),\n )?.data;\n\n // If the transactions include a token transfer, change the recipient\n // so any extra dust is also sent to the same address, rather than back to the user.\n if (tokenTransferData) {\n requestBody.recipient = getTransferRecipient(tokenTransferData);\n requestBody.refundTo = request.from;\n }\n\n requestBody.txs = [\n {\n to: request.targetTokenAddress,\n data: buildTokenTransferData(request.from, request.targetAmountMinimum),\n value: '0x0',\n },\n {\n to: delegation.to,\n data: delegation.data,\n value: delegation.value,\n },\n ];\n}\n\n/**\n * Normalizes requests for Relay.\n *\n * @param request - Quote request to normalize.\n * @returns Normalized request.\n */\nfunction normalizeRequest(request: QuoteRequest): QuoteRequest {\n const newRequest = {\n ...request,\n };\n\n const isHyperliquidDeposit =\n !request.isPostQuote &&\n request.targetChainId === CHAIN_ID_ARBITRUM &&\n request.targetTokenAddress.toLowerCase() ===\n ARBITRUM_USDC_ADDRESS.toLowerCase();\n\n const isPolygonNativeSource =\n request.sourceChainId === CHAIN_ID_POLYGON &&\n request.sourceTokenAddress === getNativeToken(request.sourceChainId);\n\n if (isPolygonNativeSource) {\n newRequest.sourceTokenAddress = NATIVE_TOKEN_ADDRESS;\n }\n\n if (isHyperliquidDeposit) {\n newRequest.targetChainId = CHAIN_ID_HYPERCORE;\n newRequest.targetTokenAddress = '0x00000000000000000000000000000000';\n newRequest.targetAmountMinimum = new BigNumber(request.targetAmountMinimum)\n .shiftedBy(2)\n .toString(10);\n\n log('Converting Arbitrum Hyperliquid deposit to direct deposit', {\n originalRequest: request,\n normalizedRequest: newRequest,\n });\n }\n\n return newRequest;\n}\n\n/**\n * Normalizes a Relay quote into a TransactionPayQuote.\n *\n * @param quote - Relay quote.\n * @param request - Original quote request.\n * @param fullRequest - Full quotes request.\n * @returns Normalized quote.\n */\nasync function normalizeQuote(\n quote: RelayQuote,\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger } = fullRequest;\n const { details } = quote;\n const { currencyIn, currencyOut } = details;\n\n const { usdToFiatRate } = getFiatRates(messenger, request);\n\n const dust = getFiatValueFromUsd(\n calculateDustUsd(quote, request),\n usdToFiatRate,\n );\n\n const subsidizedFeeUsd = getSubsidizedFeeAmountUsd(quote);\n\n const provider = subsidizedFeeUsd.gt(0)\n ? { usd: '0', fiat: '0' }\n : getFiatValueFromUsd(calculateProviderFee(quote), usdToFiatRate);\n\n const {\n gasLimits,\n isGasFeeToken: isSourceGasFeeToken,\n ...sourceNetwork\n } = await calculateSourceNetworkCost(\n quote,\n messenger,\n request,\n fullRequest.transaction,\n );\n\n const targetNetwork = {\n usd: '0',\n fiat: '0',\n };\n\n const sourceAmount: Amount = {\n human: currencyIn.amountFormatted,\n raw: currencyIn.amount,\n ...getFiatValueFromUsd(new BigNumber(currencyIn.amountUsd), usdToFiatRate),\n };\n\n const isTargetStablecoin = isStablecoin(\n request.targetChainId,\n request.targetTokenAddress,\n );\n\n const additionalTargetAmountUsd =\n quote.request.tradeType === 'EXACT_INPUT'\n ? subsidizedFeeUsd\n : new BigNumber(0);\n\n if (additionalTargetAmountUsd.gt(0)) {\n log(\n 'Including subsidized fee in target amount',\n additionalTargetAmountUsd.toString(10),\n );\n }\n\n const baseTargetAmountUsd = isTargetStablecoin\n ? new BigNumber(currencyOut.amountFormatted)\n : new BigNumber(currencyOut.amountUsd);\n\n const targetAmountUsd = baseTargetAmountUsd.plus(additionalTargetAmountUsd);\n\n const targetAmount = getFiatValueFromUsd(targetAmountUsd, usdToFiatRate);\n\n const metamask = {\n gasLimits,\n };\n\n return {\n dust,\n estimatedDuration: details.timeEstimate,\n fees: {\n isSourceGasFeeToken,\n provider,\n sourceNetwork,\n targetNetwork,\n },\n original: {\n ...quote,\n metamask,\n },\n request,\n sourceAmount,\n targetAmount,\n strategy: TransactionPayStrategy.Relay,\n };\n}\n\n/**\n * Calculate dust USD value.\n *\n * @param quote - Relay quote.\n * @param request - Quote request.\n * @returns Dust value in USD and fiat.\n */\nfunction calculateDustUsd(quote: RelayQuote, request: QuoteRequest): BigNumber {\n const { currencyOut } = quote.details;\n const { amountUsd, amountFormatted, minimumAmount } = currencyOut;\n const { decimals: targetDecimals } = currencyOut.currency;\n\n const targetUsdRate = new BigNumber(amountUsd).dividedBy(amountFormatted);\n\n const dustRaw = new BigNumber(minimumAmount).minus(\n request.targetAmountMinimum,\n );\n\n return dustRaw.shiftedBy(-targetDecimals).multipliedBy(targetUsdRate);\n}\n\n/**\n * Converts USD value to fiat value.\n *\n * @param usdValue - USD value.\n * @param usdToFiatRate - USD to fiat rate.\n * @returns Fiat value.\n */\nfunction getFiatValueFromUsd(\n usdValue: BigNumber,\n usdToFiatRate: BigNumber,\n): FiatValue {\n const fiatValue = usdValue.multipliedBy(usdToFiatRate);\n\n return {\n usd: usdValue.toString(10),\n fiat: fiatValue.toString(10),\n };\n}\n\n/**\n * Calculates USD to fiat rate.\n *\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @returns USD to fiat rate.\n */\nfunction getFiatRates(\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): {\n sourceFiatRate: FiatRates;\n usdToFiatRate: BigNumber;\n} {\n const { sourceChainId, sourceTokenAddress } = request;\n\n const finalSourceTokenAddress =\n sourceChainId === CHAIN_ID_POLYGON &&\n sourceTokenAddress === NATIVE_TOKEN_ADDRESS\n ? getNativeToken(sourceChainId)\n : sourceTokenAddress;\n\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n finalSourceTokenAddress,\n sourceChainId,\n );\n\n if (!sourceFiatRate) {\n throw new Error('Source token fiat rate not found');\n }\n\n const usdToFiatRate = new BigNumber(sourceFiatRate.fiatRate).dividedBy(\n sourceFiatRate.usdRate,\n );\n\n return { sourceFiatRate, usdToFiatRate };\n}\n\n/**\n * Calculates source network cost from a Relay quote.\n *\n * For post-quote flows (e.g. predictWithdraw), the cost also includes the\n * original transaction's gas (the user's Polygon USDC.e transfer) in addition\n * to the Relay deposit transaction gas, by appending the original\n * transaction's params so that gas estimation and gas-fee-token logic handle\n * both transactions together.\n *\n * @param quote - Relay quote.\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @param transaction - Original transaction metadata.\n * @returns Total source network cost in USD and fiat.\n */\nasync function calculateSourceNetworkCost(\n quote: RelayQuote,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n transaction: TransactionMeta,\n): Promise<\n TransactionPayQuote<RelayQuote>['fees']['sourceNetwork'] & {\n gasLimits: number[];\n isGasFeeToken?: boolean;\n }\n> {\n const { from, sourceChainId, sourceTokenAddress } = request;\n\n const relayParams = quote.steps\n .flatMap((step) => step.items)\n .map((item) => item.data);\n\n const { relayDisabledGasStationChains } = getFeatureFlags(messenger);\n\n const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } =\n relayParams[0];\n\n const { totalGasEstimate, totalGasLimit, gasLimits } =\n await calculateSourceNetworkGasLimit(\n relayParams,\n messenger,\n request.isPostQuote ? transaction : undefined,\n );\n\n log('Gas limit', {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n });\n\n const estimate = calculateGasCost({\n chainId,\n gas: totalGasEstimate,\n maxFeePerGas,\n maxPriorityFeePerGas,\n messenger,\n });\n\n const max = calculateGasCost({\n chainId,\n gas: totalGasLimit,\n maxFeePerGas,\n maxPriorityFeePerGas,\n messenger,\n isMax: true,\n });\n\n const nativeBalance = getTokenBalance(\n messenger,\n from,\n sourceChainId,\n getNativeToken(sourceChainId),\n );\n\n const result = { estimate, max, gasLimits };\n\n if (new BigNumber(nativeBalance).isGreaterThanOrEqualTo(max.raw)) {\n return result;\n }\n\n if (relayDisabledGasStationChains.includes(sourceChainId)) {\n log('Skipping gas station as disabled chain', {\n sourceChainId,\n disabledChainIds: relayDisabledGasStationChains,\n });\n\n return result;\n }\n\n const supportedChains = getEIP7702SupportedChains(messenger);\n const chainSupportsGasStation = supportedChains.some(\n (supportedChainId) =>\n supportedChainId.toLowerCase() === sourceChainId.toLowerCase(),\n );\n\n if (!chainSupportsGasStation) {\n log('Skipping gas station as chain does not support EIP-7702', {\n sourceChainId,\n });\n\n return result;\n }\n\n log('Checking gas fee tokens as insufficient native balance', {\n nativeBalance,\n max: max.raw,\n });\n\n const gasFeeTokens = await messenger.call(\n 'TransactionController:getGasFeeTokens',\n {\n chainId: sourceChainId,\n data,\n from,\n to,\n value: toHex(value ?? '0'),\n },\n );\n\n log('Source gas fee tokens', { gasFeeTokens });\n\n const gasFeeToken = gasFeeTokens.find(\n (singleGasFeeToken) =>\n singleGasFeeToken.tokenAddress.toLowerCase() ===\n sourceTokenAddress.toLowerCase(),\n );\n\n if (!gasFeeToken) {\n log('No matching gas fee token found', {\n sourceTokenAddress,\n gasFeeTokens,\n });\n\n return result;\n }\n\n let finalAmount = gasFeeToken.amount;\n\n const hasMultipleTransactions =\n relayParams.length > 1 || gasLimits.length > 1;\n\n if (hasMultipleTransactions) {\n const gasRate = new BigNumber(gasFeeToken.amount, 16).dividedBy(\n gasFeeToken.gas,\n 16,\n );\n\n const finalAmountValue = gasRate.multipliedBy(totalGasEstimate);\n\n finalAmount = toHex(finalAmountValue.toFixed(0));\n\n log('Estimated gas fee token amount for batch', {\n finalAmount: finalAmountValue.toString(10),\n gasRate: gasRate.toString(10),\n totalGasEstimate,\n });\n }\n\n const finalGasFeeToken = { ...gasFeeToken, amount: finalAmount };\n\n const gasFeeTokenCost = calculateGasFeeTokenCost({\n chainId: sourceChainId,\n gasFeeToken: finalGasFeeToken,\n messenger,\n });\n\n if (!gasFeeTokenCost) {\n return result;\n }\n\n log('Using gas fee token for source network', {\n gasFeeTokenCost,\n });\n\n return {\n isGasFeeToken: true,\n estimate: gasFeeTokenCost,\n max: gasFeeTokenCost,\n gasLimits,\n };\n}\n\n/**\n * Calculate the total gas limit for the source network.\n *\n * For post-quote flows (e.g. predict withdrawals), the original transaction's\n * gas is combined with the relay gas so that source network cost accounts for\n * both the user's transaction and the relay transactions.\n *\n * @param params - Array of relay transaction parameters.\n * @param messenger - Controller messenger.\n * @param postQuoteTransaction - Original transaction for post-quote flows.\n * When provided, its gas is included in the returned totals.\n * @returns Total gas estimates and per-transaction gas limits.\n */\nasync function calculateSourceNetworkGasLimit(\n params: RelayQuote['steps'][0]['items'][0]['data'][],\n messenger: TransactionPayControllerMessenger,\n postQuoteTransaction?: TransactionMeta,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n}> {\n const relayGas =\n params.length === 1\n ? await calculateSourceNetworkGasLimitSingle(params[0], messenger)\n : await calculateSourceNetworkGasLimitBatch(params, messenger);\n\n if (!postQuoteTransaction?.txParams.to) {\n return relayGas;\n }\n\n return combinePostQuoteGas(relayGas, params.length, postQuoteTransaction);\n}\n\n/**\n * Combine the original transaction's gas with relay gas for post-quote flows.\n *\n * Prefers gas from `nestedTransactions` (preserves the caller-provided value)\n * since TransactionController may re-estimate `txParams.gas` during batch\n * creation.\n *\n * @param relayGas - Gas estimates from relay transactions.\n * @param relayGas.totalGasEstimate - Estimated gas total.\n * @param relayGas.totalGasLimit - Maximum gas total.\n * @param relayGas.gasLimits - Per-transaction gas limits.\n * @param relayParamCount - Number of relay transaction parameters.\n * @param transaction - Original transaction metadata.\n * @returns Combined gas estimates including the original transaction.\n */\nfunction combinePostQuoteGas(\n relayGas: {\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n },\n relayParamCount: number,\n transaction: TransactionMeta,\n): { totalGasEstimate: number; totalGasLimit: number; gasLimits: number[] } {\n const nestedGas = transaction.nestedTransactions?.find((tx) => tx.gas)?.gas;\n const rawGas = nestedGas ?? transaction.txParams.gas;\n const originalTxGas = rawGas ? new BigNumber(rawGas).toNumber() : undefined;\n\n if (originalTxGas === undefined) {\n return relayGas;\n }\n\n let { gasLimits } = relayGas;\n const isEIP7702 = gasLimits.length === 1 && relayParamCount > 1;\n\n if (isEIP7702) {\n // EIP-7702: single combined gas limit — add the original tx gas\n // so the atomic batch covers both relay and original transactions.\n gasLimits = [gasLimits[0] + originalTxGas];\n } else {\n // Non-7702: individual gas limits — prepend the original tx gas\n // so the list order matches relay-submit's transaction order.\n gasLimits = [originalTxGas, ...gasLimits];\n }\n\n const totalGasEstimate = relayGas.totalGasEstimate + originalTxGas;\n const totalGasLimit = relayGas.totalGasLimit + originalTxGas;\n\n log('Combined original tx gas with relay gas', {\n originalTxGas,\n isEIP7702,\n gasLimits,\n totalGasLimit,\n });\n\n return { totalGasEstimate, totalGasLimit, gasLimits };\n}\n\n/**\n * Calculate the provider fee for a Relay quote.\n *\n * @param quote - Relay quote.\n * @returns - Provider fee in USD.\n */\nfunction calculateProviderFee(quote: RelayQuote): BigNumber {\n return new BigNumber(quote.details.totalImpact.usd).abs();\n}\n\n/**\n * Build token transfer data.\n *\n * @param recipient - Recipient address.\n * @param amountRaw - Amount in raw format.\n * @returns Token transfer data.\n */\nfunction buildTokenTransferData(recipient: Hex, amountRaw: string): Hex {\n return new Interface([\n 'function transfer(address to, uint256 amount)',\n ]).encodeFunctionData('transfer', [recipient, amountRaw]) as Hex;\n}\n\n/**\n * Get transfer recipient from token transfer data.\n *\n * @param data - Token transfer data.\n * @returns Transfer recipient.\n */\nfunction getTransferRecipient(data: Hex): Hex {\n return new Interface(['function transfer(address to, uint256 amount)'])\n .decodeFunctionData('transfer', data)\n .to.toLowerCase();\n}\n\nasync function calculateSourceNetworkGasLimitSingle(\n params: RelayQuote['steps'][0]['items'][0]['data'],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n}> {\n const paramGasLimit = params.gas\n ? new BigNumber(params.gas).toNumber()\n : undefined;\n\n if (paramGasLimit) {\n log('Using single gas limit from params', { paramGasLimit });\n\n return {\n totalGasEstimate: paramGasLimit,\n totalGasLimit: paramGasLimit,\n gasLimits: [paramGasLimit],\n };\n }\n\n try {\n const {\n chainId: chainIdNumber,\n data,\n from,\n to,\n value: valueString,\n } = params;\n\n const chainId = toHex(chainIdNumber);\n const value = toHex(valueString ?? '0');\n const gasBuffer = getGasBuffer(messenger, chainId);\n\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n const { gas: gasHex, simulationFails } = await messenger.call(\n 'TransactionController:estimateGas',\n { from, data, to, value },\n networkClientId,\n );\n\n const estimatedGas = new BigNumber(gasHex).toNumber();\n const bufferedGas = Math.ceil(estimatedGas * gasBuffer);\n\n if (!simulationFails) {\n log('Estimated gas limit for single transaction', {\n chainId,\n estimatedGas,\n bufferedGas,\n gasBuffer,\n });\n\n return {\n totalGasEstimate: bufferedGas,\n totalGasLimit: bufferedGas,\n gasLimits: [bufferedGas],\n };\n }\n } catch (error) {\n log('Failed to estimate gas limit for single transaction', error);\n }\n\n const fallbackGas = getFeatureFlags(messenger).relayFallbackGas;\n\n log('Using fallback gas for single transaction', { fallbackGas });\n\n return {\n totalGasEstimate: fallbackGas.estimate,\n totalGasLimit: fallbackGas.max,\n gasLimits: [fallbackGas.max],\n };\n}\n\n/**\n * Calculate the gas limits for a batch of transactions.\n *\n * @param params - Array of transaction parameters.\n * @param messenger - Controller messenger.\n * @returns - Gas limits.\n */\nasync function calculateSourceNetworkGasLimitBatch(\n params: RelayQuote['steps'][0]['items'][0]['data'][],\n messenger: TransactionPayControllerMessenger,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n}> {\n try {\n const { chainId: chainIdNumber, from } = params[0];\n const chainId = toHex(chainIdNumber);\n const gasBuffer = getGasBuffer(messenger, chainId);\n\n const transactions: BatchTransactionParams[] = params.map(\n (singleParams) => ({\n ...singleParams,\n gas: singleParams.gas ? toHex(singleParams.gas) : undefined,\n maxFeePerGas: undefined,\n maxPriorityFeePerGas: undefined,\n value: toHex(singleParams.value ?? '0'),\n }),\n );\n\n const paramGasLimits = params.map((singleParams) =>\n singleParams.gas ? new BigNumber(singleParams.gas).toNumber() : undefined,\n );\n\n const { totalGasLimit, gasLimits } = await messenger.call(\n 'TransactionController:estimateGasBatch',\n {\n chainId,\n from,\n transactions,\n },\n );\n\n const bufferedGasLimits = gasLimits.map((limit, index) => {\n const useBuffer =\n gasLimits.length === 1 || paramGasLimits[index] !== gasLimits[index];\n\n const buffer = useBuffer ? gasBuffer : 1;\n\n return Math.ceil(limit * buffer);\n });\n\n const bufferedTotalGasLimit = bufferedGasLimits.reduce(\n (acc, limit) => acc + limit,\n 0,\n );\n\n log('Estimated gas limit for batch', {\n chainId,\n totalGasLimit,\n gasLimits,\n bufferedTotalGasLimit,\n bufferedGasLimits,\n gasBuffer,\n });\n\n return {\n totalGasEstimate: bufferedTotalGasLimit,\n totalGasLimit: bufferedTotalGasLimit,\n gasLimits: bufferedGasLimits,\n };\n } catch (error) {\n log('Failed to estimate gas limit for batch', error);\n }\n\n const fallbackGas = getFeatureFlags(messenger).relayFallbackGas;\n\n const totalGasEstimate = params.reduce((acc, singleParams) => {\n const gas = singleParams.gas ?? fallbackGas.estimate;\n return acc + new BigNumber(gas).toNumber();\n }, 0);\n\n const gasLimits = params.map((singleParams) => {\n const gas = singleParams.gas ?? fallbackGas.max;\n return new BigNumber(gas).toNumber();\n });\n\n const totalGasLimit = gasLimits.reduce(\n (acc, singleGasLimit) => acc + singleGasLimit,\n 0,\n );\n\n log('Using fallback gas for batch', {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n });\n\n return {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n };\n}\n\nfunction getSubsidizedFeeAmountUsd(quote: RelayQuote): BigNumber {\n const subsidizedFee = quote.fees?.subsidized;\n const amountUsd = new BigNumber(subsidizedFee?.amountUsd ?? '0');\n const amountFormatted = new BigNumber(subsidizedFee?.amountFormatted ?? '0');\n\n if (!subsidizedFee || amountUsd.isZero()) {\n return new BigNumber(0);\n }\n\n const isSubsidizedStablecoin = isStablecoin(\n toHex(subsidizedFee.currency.chainId),\n subsidizedFee.currency.address,\n );\n\n return isSubsidizedStablecoin ? amountFormatted : amountUsd;\n}\n\nfunction isStablecoin(chainId: string, tokenAddress: string): boolean {\n return Boolean(\n STABLECOINS[chainId as Hex]?.includes(tokenAddress.toLowerCase() as Hex),\n );\n}\n"]}
|
|
@@ -195,7 +195,7 @@ async function normalizeQuote(quote, request, fullRequest) {
|
|
|
195
195
|
const provider = subsidizedFeeUsd.gt(0)
|
|
196
196
|
? { usd: '0', fiat: '0' }
|
|
197
197
|
: getFiatValueFromUsd(calculateProviderFee(quote), usdToFiatRate);
|
|
198
|
-
const { gasLimits, isGasFeeToken: isSourceGasFeeToken, ...sourceNetwork } = await calculateSourceNetworkCost(quote, messenger, request);
|
|
198
|
+
const { gasLimits, isGasFeeToken: isSourceGasFeeToken, ...sourceNetwork } = await calculateSourceNetworkCost(quote, messenger, request, fullRequest.transaction);
|
|
199
199
|
const targetNetwork = {
|
|
200
200
|
usd: '0',
|
|
201
201
|
fiat: '0',
|
|
@@ -291,19 +291,26 @@ function getFiatRates(messenger, request) {
|
|
|
291
291
|
/**
|
|
292
292
|
* Calculates source network cost from a Relay quote.
|
|
293
293
|
*
|
|
294
|
+
* For post-quote flows (e.g. predictWithdraw), the cost also includes the
|
|
295
|
+
* original transaction's gas (the user's Polygon USDC.e transfer) in addition
|
|
296
|
+
* to the Relay deposit transaction gas, by appending the original
|
|
297
|
+
* transaction's params so that gas estimation and gas-fee-token logic handle
|
|
298
|
+
* both transactions together.
|
|
299
|
+
*
|
|
294
300
|
* @param quote - Relay quote.
|
|
295
301
|
* @param messenger - Controller messenger.
|
|
296
302
|
* @param request - Quote request.
|
|
303
|
+
* @param transaction - Original transaction metadata.
|
|
297
304
|
* @returns Total source network cost in USD and fiat.
|
|
298
305
|
*/
|
|
299
|
-
async function calculateSourceNetworkCost(quote, messenger, request) {
|
|
306
|
+
async function calculateSourceNetworkCost(quote, messenger, request, transaction) {
|
|
300
307
|
const { from, sourceChainId, sourceTokenAddress } = request;
|
|
301
|
-
const
|
|
308
|
+
const relayParams = quote.steps
|
|
302
309
|
.flatMap((step) => step.items)
|
|
303
310
|
.map((item) => item.data);
|
|
304
311
|
const { relayDisabledGasStationChains } = getFeatureFlags(messenger);
|
|
305
|
-
const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } =
|
|
306
|
-
const { totalGasEstimate, totalGasLimit, gasLimits } = await calculateSourceNetworkGasLimit(
|
|
312
|
+
const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } = relayParams[0];
|
|
313
|
+
const { totalGasEstimate, totalGasLimit, gasLimits } = await calculateSourceNetworkGasLimit(relayParams, messenger, request.isPostQuote ? transaction : undefined);
|
|
307
314
|
log('Gas limit', {
|
|
308
315
|
totalGasEstimate,
|
|
309
316
|
totalGasLimit,
|
|
@@ -366,7 +373,8 @@ async function calculateSourceNetworkCost(quote, messenger, request) {
|
|
|
366
373
|
return result;
|
|
367
374
|
}
|
|
368
375
|
let finalAmount = gasFeeToken.amount;
|
|
369
|
-
|
|
376
|
+
const hasMultipleTransactions = relayParams.length > 1 || gasLimits.length > 1;
|
|
377
|
+
if (hasMultipleTransactions) {
|
|
370
378
|
const gasRate = new BigNumber(gasFeeToken.amount, 16).dividedBy(gasFeeToken.gas, 16);
|
|
371
379
|
const finalAmountValue = gasRate.multipliedBy(totalGasEstimate);
|
|
372
380
|
finalAmount = toHex(finalAmountValue.toFixed(0));
|
|
@@ -396,17 +404,70 @@ async function calculateSourceNetworkCost(quote, messenger, request) {
|
|
|
396
404
|
};
|
|
397
405
|
}
|
|
398
406
|
/**
|
|
399
|
-
* Calculate the total gas limit for the source network
|
|
407
|
+
* Calculate the total gas limit for the source network.
|
|
400
408
|
*
|
|
401
|
-
*
|
|
409
|
+
* For post-quote flows (e.g. predict withdrawals), the original transaction's
|
|
410
|
+
* gas is combined with the relay gas so that source network cost accounts for
|
|
411
|
+
* both the user's transaction and the relay transactions.
|
|
412
|
+
*
|
|
413
|
+
* @param params - Array of relay transaction parameters.
|
|
402
414
|
* @param messenger - Controller messenger.
|
|
403
|
-
* @
|
|
415
|
+
* @param postQuoteTransaction - Original transaction for post-quote flows.
|
|
416
|
+
* When provided, its gas is included in the returned totals.
|
|
417
|
+
* @returns Total gas estimates and per-transaction gas limits.
|
|
418
|
+
*/
|
|
419
|
+
async function calculateSourceNetworkGasLimit(params, messenger, postQuoteTransaction) {
|
|
420
|
+
const relayGas = params.length === 1
|
|
421
|
+
? await calculateSourceNetworkGasLimitSingle(params[0], messenger)
|
|
422
|
+
: await calculateSourceNetworkGasLimitBatch(params, messenger);
|
|
423
|
+
if (!postQuoteTransaction?.txParams.to) {
|
|
424
|
+
return relayGas;
|
|
425
|
+
}
|
|
426
|
+
return combinePostQuoteGas(relayGas, params.length, postQuoteTransaction);
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Combine the original transaction's gas with relay gas for post-quote flows.
|
|
430
|
+
*
|
|
431
|
+
* Prefers gas from `nestedTransactions` (preserves the caller-provided value)
|
|
432
|
+
* since TransactionController may re-estimate `txParams.gas` during batch
|
|
433
|
+
* creation.
|
|
434
|
+
*
|
|
435
|
+
* @param relayGas - Gas estimates from relay transactions.
|
|
436
|
+
* @param relayGas.totalGasEstimate - Estimated gas total.
|
|
437
|
+
* @param relayGas.totalGasLimit - Maximum gas total.
|
|
438
|
+
* @param relayGas.gasLimits - Per-transaction gas limits.
|
|
439
|
+
* @param relayParamCount - Number of relay transaction parameters.
|
|
440
|
+
* @param transaction - Original transaction metadata.
|
|
441
|
+
* @returns Combined gas estimates including the original transaction.
|
|
404
442
|
*/
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
443
|
+
function combinePostQuoteGas(relayGas, relayParamCount, transaction) {
|
|
444
|
+
const nestedGas = transaction.nestedTransactions?.find((tx) => tx.gas)?.gas;
|
|
445
|
+
const rawGas = nestedGas ?? transaction.txParams.gas;
|
|
446
|
+
const originalTxGas = rawGas ? new BigNumber(rawGas).toNumber() : undefined;
|
|
447
|
+
if (originalTxGas === undefined) {
|
|
448
|
+
return relayGas;
|
|
449
|
+
}
|
|
450
|
+
let { gasLimits } = relayGas;
|
|
451
|
+
const isEIP7702 = gasLimits.length === 1 && relayParamCount > 1;
|
|
452
|
+
if (isEIP7702) {
|
|
453
|
+
// EIP-7702: single combined gas limit — add the original tx gas
|
|
454
|
+
// so the atomic batch covers both relay and original transactions.
|
|
455
|
+
gasLimits = [gasLimits[0] + originalTxGas];
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
// Non-7702: individual gas limits — prepend the original tx gas
|
|
459
|
+
// so the list order matches relay-submit's transaction order.
|
|
460
|
+
gasLimits = [originalTxGas, ...gasLimits];
|
|
408
461
|
}
|
|
409
|
-
|
|
462
|
+
const totalGasEstimate = relayGas.totalGasEstimate + originalTxGas;
|
|
463
|
+
const totalGasLimit = relayGas.totalGasLimit + originalTxGas;
|
|
464
|
+
log('Combined original tx gas with relay gas', {
|
|
465
|
+
originalTxGas,
|
|
466
|
+
isEIP7702,
|
|
467
|
+
gasLimits,
|
|
468
|
+
totalGasLimit,
|
|
469
|
+
});
|
|
470
|
+
return { totalGasEstimate, totalGasLimit, gasLimits };
|
|
410
471
|
}
|
|
411
472
|
/**
|
|
412
473
|
* Calculate the provider fee for a Relay quote.
|