@metamask/transaction-pay-controller 23.5.1 → 23.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +21 -1
  2. package/dist/TransactionPayController.cjs +0 -17
  3. package/dist/TransactionPayController.cjs.map +1 -1
  4. package/dist/TransactionPayController.d.cts.map +1 -1
  5. package/dist/TransactionPayController.d.mts.map +1 -1
  6. package/dist/TransactionPayController.mjs +1 -18
  7. package/dist/TransactionPayController.mjs.map +1 -1
  8. package/dist/constants.cjs +3 -1
  9. package/dist/constants.cjs.map +1 -1
  10. package/dist/constants.d.cts +2 -0
  11. package/dist/constants.d.cts.map +1 -1
  12. package/dist/constants.d.mts +2 -0
  13. package/dist/constants.d.mts.map +1 -1
  14. package/dist/constants.mjs +2 -0
  15. package/dist/constants.mjs.map +1 -1
  16. package/dist/strategy/fiat/constants.cjs +8 -1
  17. package/dist/strategy/fiat/constants.cjs.map +1 -1
  18. package/dist/strategy/fiat/constants.d.cts +4 -0
  19. package/dist/strategy/fiat/constants.d.cts.map +1 -1
  20. package/dist/strategy/fiat/constants.d.mts +4 -0
  21. package/dist/strategy/fiat/constants.d.mts.map +1 -1
  22. package/dist/strategy/fiat/constants.mjs +8 -1
  23. package/dist/strategy/fiat/constants.mjs.map +1 -1
  24. package/dist/strategy/fiat/fiat-quotes.cjs +83 -16
  25. package/dist/strategy/fiat/fiat-quotes.cjs.map +1 -1
  26. package/dist/strategy/fiat/fiat-quotes.d.cts +5 -7
  27. package/dist/strategy/fiat/fiat-quotes.d.cts.map +1 -1
  28. package/dist/strategy/fiat/fiat-quotes.d.mts +5 -7
  29. package/dist/strategy/fiat/fiat-quotes.d.mts.map +1 -1
  30. package/dist/strategy/fiat/fiat-quotes.mjs +85 -18
  31. package/dist/strategy/fiat/fiat-quotes.mjs.map +1 -1
  32. package/dist/strategy/fiat/fiat-submit.cjs +43 -12
  33. package/dist/strategy/fiat/fiat-submit.cjs.map +1 -1
  34. package/dist/strategy/fiat/fiat-submit.d.cts.map +1 -1
  35. package/dist/strategy/fiat/fiat-submit.d.mts.map +1 -1
  36. package/dist/strategy/fiat/fiat-submit.mjs +43 -12
  37. package/dist/strategy/fiat/fiat-submit.mjs.map +1 -1
  38. package/dist/strategy/fiat/utils.cjs +31 -1
  39. package/dist/strategy/fiat/utils.cjs.map +1 -1
  40. package/dist/strategy/fiat/utils.d.cts +26 -0
  41. package/dist/strategy/fiat/utils.d.cts.map +1 -1
  42. package/dist/strategy/fiat/utils.d.mts +26 -0
  43. package/dist/strategy/fiat/utils.d.mts.map +1 -1
  44. package/dist/strategy/fiat/utils.mjs +29 -1
  45. package/dist/strategy/fiat/utils.mjs.map +1 -1
  46. package/dist/strategy/relay/relay-quotes.cjs +1 -1
  47. package/dist/strategy/relay/relay-quotes.cjs.map +1 -1
  48. package/dist/strategy/relay/relay-quotes.mjs +1 -1
  49. package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
  50. package/dist/types.cjs.map +1 -1
  51. package/dist/types.d.cts +2 -0
  52. package/dist/types.d.cts.map +1 -1
  53. package/dist/types.d.mts +2 -0
  54. package/dist/types.d.mts.map +1 -1
  55. package/dist/types.mjs.map +1 -1
  56. package/dist/utils/feature-flags.cjs +48 -3
  57. package/dist/utils/feature-flags.cjs.map +1 -1
  58. package/dist/utils/feature-flags.d.cts +23 -0
  59. package/dist/utils/feature-flags.d.cts.map +1 -1
  60. package/dist/utils/feature-flags.d.mts +23 -0
  61. package/dist/utils/feature-flags.d.mts.map +1 -1
  62. package/dist/utils/feature-flags.mjs +44 -2
  63. package/dist/utils/feature-flags.mjs.map +1 -1
  64. package/package.json +6 -6
@@ -5,19 +5,47 @@ import { projectLogger } from "../../logger.mjs";
5
5
  import { getFiatAssetPerTransactionType, getFiatEnabledTypes } from "../../utils/feature-flags.mjs";
6
6
  import { getTokenInfo } from "../../utils/token.mjs";
7
7
  import { getTransferredAmountFromTxHash } from "../../utils/transaction.mjs";
8
+ import { FIAT_ENABLED_TYPES } from "./constants.mjs";
8
9
  const log = createModuleLogger(projectLogger, 'fiat-utils');
9
10
  export function deriveFiatAssetForFiatPayment(transaction, messenger) {
10
11
  const enabledTypes = getFiatEnabledTypes(messenger);
11
12
  const txType = resolveTransactionType(transaction, enabledTypes);
12
13
  return getFiatAssetPerTransactionType(messenger, txType);
13
14
  }
14
- function resolveTransactionType(transaction, enabledTypes) {
15
+ /**
16
+ * Resolves the effective transaction type for fiat strategy purposes.
17
+ *
18
+ * For non-batch transactions returns the transaction's own type.
19
+ * For batch transactions returns the first nested transaction type
20
+ * that appears in the enabled types list, or the batch type itself
21
+ * if no nested type matches.
22
+ *
23
+ * @param transaction - The transaction metadata to inspect.
24
+ * @param enabledTypes - Transaction types eligible for fiat payment.
25
+ * @returns The resolved transaction type, or `undefined`.
26
+ */
27
+ export function resolveTransactionType(transaction, enabledTypes) {
15
28
  if (transaction.type !== TransactionType.batch) {
16
29
  return transaction.type;
17
30
  }
18
31
  const nestedType = transaction.nestedTransactions?.find((tx) => tx.type && enabledTypes.includes(tx.type))?.type;
19
32
  return nestedType ?? transaction.type;
20
33
  }
34
+ /**
35
+ * Checks whether a transaction is a Money Account deposit.
36
+ *
37
+ * Handles both direct `moneyAccountDeposit` transactions and EIP-7702
38
+ * batch transactions that contain a `moneyAccountDeposit` nested call.
39
+ * Uses {@link resolveTransactionType} with `FIAT_ENABLED_TYPES` to
40
+ * correctly skip non-deposit nested types (e.g. `tokenMethodApprove`).
41
+ *
42
+ * @param transaction - The transaction metadata to inspect.
43
+ * @returns `true` if the transaction is a Money Account deposit.
44
+ */
45
+ export function isMoneyAccountDepositTransaction(transaction) {
46
+ return (resolveTransactionType(transaction, FIAT_ENABLED_TYPES) ===
47
+ TransactionType.moneyAccountDeposit);
48
+ }
21
49
  /**
22
50
  * Resolves the raw source amount for a completed fiat order.
23
51
  *
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RampsOrder } from '@metamask/ramps-controller';\nimport type { TransactionMeta } from '@metamask/transaction-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 { projectLogger } from '../../logger';\nimport type { TransactionPayControllerMessenger } from '../../types';\nimport {\n getFiatAssetPerTransactionType,\n getFiatEnabledTypes,\n} from '../../utils/feature-flags';\nimport { getTokenInfo } from '../../utils/token';\nimport { getTransferredAmountFromTxHash } from '../../utils/transaction';\nimport type { RelayQuote } from '../relay/types';\nimport type { TransactionPayFiatAsset } from './constants';\n\nconst log = createModuleLogger(projectLogger, 'fiat-utils');\n\nexport function deriveFiatAssetForFiatPayment(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayFiatAsset {\n const enabledTypes = getFiatEnabledTypes(messenger);\n const txType = resolveTransactionType(transaction, enabledTypes);\n\n return getFiatAssetPerTransactionType(messenger, txType);\n}\n\nfunction resolveTransactionType(\n transaction: TransactionMeta,\n enabledTypes: TransactionType[],\n): TransactionType | undefined {\n if (transaction.type !== TransactionType.batch) {\n return transaction.type;\n }\n\n const nestedType = transaction.nestedTransactions?.find(\n (tx) => tx.type && enabledTypes.includes(tx.type),\n )?.type;\n\n return nestedType ?? transaction.type;\n}\n\n/**\n * Resolves the raw source amount for a completed fiat order.\n *\n * Attempts to read the actual transferred amount from the on-chain transaction\n * identified by `order.txHash`. If the on-chain read fails or returns\n * no amount, falls back to computing the amount from `order.cryptoAmount`.\n *\n * @param options - The resolution options.\n * @param options.messenger - Controller messenger for network access.\n * @param options.order - The completed on-ramp order.\n * @param options.fiatAsset - The fiat asset describing the expected token.\n * @param options.walletAddress - Recipient wallet address for on-chain lookup.\n * @returns The raw (atomic) source amount as a decimal string.\n */\nexport async function resolveSourceAmountRaw({\n messenger,\n order,\n fiatAsset,\n walletAddress,\n}: {\n messenger: TransactionPayControllerMessenger;\n order: RampsOrder;\n fiatAsset: TransactionPayFiatAsset;\n walletAddress: Hex;\n}): Promise<string> {\n if (order.txHash) {\n try {\n const onChainAmount = await getTransferredAmountFromTxHash({\n messenger,\n txHash: order.txHash,\n chainId: fiatAsset.chainId,\n tokenAddress: fiatAsset.address,\n walletAddress,\n });\n\n if (onChainAmount) {\n log('Resolved source amount from on-chain transaction', {\n txHash: order.txHash,\n onChainAmount,\n });\n return onChainAmount;\n }\n } catch (error) {\n log(\n 'Failed to read on-chain amount, falling back to order.cryptoAmount',\n { txHash: order.txHash, error },\n );\n }\n }\n\n const tokenInfo = getTokenInfo(\n messenger,\n fiatAsset.address,\n fiatAsset.chainId,\n );\n\n if (!tokenInfo) {\n throw new Error(\n `Unable to resolve token info for fiat asset ${fiatAsset.address} on chain ${fiatAsset.chainId}`,\n );\n }\n\n return getRawSourceAmountFromOrderCryptoAmount({\n cryptoAmount: order.cryptoAmount,\n decimals: tokenInfo.decimals,\n });\n}\n\n/**\n * Converts the order's human-readable crypto amount to a raw token amount.\n *\n * @param options - The conversion options.\n * @param options.cryptoAmount - Human-readable crypto amount from the completed order.\n * @param options.decimals - Token decimals for the fiat asset.\n * @returns The raw token amount as a string.\n */\nexport function getRawSourceAmountFromOrderCryptoAmount({\n cryptoAmount,\n decimals,\n}: {\n cryptoAmount: RampsOrder['cryptoAmount'];\n decimals: number;\n}): string {\n const normalizedAmount = new BigNumber(String(cryptoAmount));\n\n if (!normalizedAmount.isFinite() || normalizedAmount.lte(0)) {\n throw new Error(\n `Invalid fiat order crypto amount: ${String(cryptoAmount)}`,\n );\n }\n\n const rawAmount = normalizedAmount\n .shiftedBy(decimals)\n .decimalPlaces(0, BigNumber.ROUND_DOWN)\n .toFixed(0);\n\n if (!new BigNumber(rawAmount).gt(0)) {\n throw new Error('Computed fiat order source amount is not positive');\n }\n\n return rawAmount;\n}\n\n/**\n * Validates that the relay exchange rate hasn't drifted significantly between\n * the original quoting phase and the post-settlement discovery quote.\n *\n * Compares the USD output/input ratio from both quotes. This normalises for\n * different source amounts (quoting phase uses a theoretical amount, discovery\n * uses the actual settled amount) so the comparison reflects genuine rate\n * movement rather than amount differences.\n *\n * @param options - The validation options.\n * @param options.originalQuote - Relay quote from the original quoting phase.\n * @param options.discoveryQuote - Relay quote from the post-settlement discovery.\n * @param options.maxRateDriftPercent - Maximum allowed rate drift percentage.\n * @param options.transactionId - Transaction ID for error reporting.\n */\nexport function validateRelayRateDrift({\n originalQuote,\n discoveryQuote,\n maxRateDriftPercent,\n transactionId,\n}: {\n originalQuote: RelayQuote;\n discoveryQuote: RelayQuote;\n maxRateDriftPercent: number;\n transactionId: string;\n}): void {\n const originalIn = new BigNumber(originalQuote.details.currencyIn.amountUsd);\n const originalOut = new BigNumber(\n originalQuote.details.currencyOut.amountUsd,\n );\n const discoveryIn = new BigNumber(\n discoveryQuote.details.currencyIn.amountUsd,\n );\n const discoveryOut = new BigNumber(\n discoveryQuote.details.currencyOut.amountUsd,\n );\n\n if (\n !originalIn.gt(0) ||\n !originalOut.gt(0) ||\n !discoveryIn.gt(0) ||\n !discoveryOut.gt(0)\n ) {\n return;\n }\n\n const originalRate = originalOut.dividedBy(originalIn);\n const discoveryRate = discoveryOut.dividedBy(discoveryIn);\n\n const driftPercent = originalRate\n .minus(discoveryRate)\n .dividedBy(originalRate)\n .multipliedBy(100);\n\n log('Relay rate drift check', {\n originalRate: originalRate.toFixed(6),\n discoveryRate: discoveryRate.toFixed(6),\n driftPercent: driftPercent.toFixed(2),\n maxRateDriftPercent,\n transactionId,\n });\n\n if (driftPercent.gt(maxRateDriftPercent)) {\n throw new Error(\n `Relay rate drift too high for transaction ` +\n `${driftPercent.toFixed(2)}% exceeds ${maxRateDriftPercent}% max`,\n );\n }\n}\n\n/**\n * Extracts the provider code from a ramps provider string.\n *\n * Accepts the canonical provider code (e.g. `transak-native`) and, for\n * backwards compatibility, the legacy path form (e.g. `/providers/transak-native`).\n *\n * @param provider - Canonical provider code, or legacy provider path.\n * @returns The provider code, or `null` if the format is invalid.\n */\nexport function extractProviderCode(\n provider: string | undefined,\n): string | null {\n if (!provider) {\n return null;\n }\n\n const parts = provider.split('/').filter(Boolean);\n\n if (parts[0] === 'providers') {\n return parts[1] ?? null;\n }\n\n return parts.length === 1 ? parts[0] : null;\n}\n"]}
1
+ {"version":3,"file":"utils.mjs","sourceRoot":"","sources":["../../../src/strategy/fiat/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RampsOrder } from '@metamask/ramps-controller';\nimport type { TransactionMeta } from '@metamask/transaction-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 { projectLogger } from '../../logger';\nimport type { TransactionPayControllerMessenger } from '../../types';\nimport {\n getFiatAssetPerTransactionType,\n getFiatEnabledTypes,\n} from '../../utils/feature-flags';\nimport { getTokenInfo } from '../../utils/token';\nimport { getTransferredAmountFromTxHash } from '../../utils/transaction';\nimport type { RelayQuote } from '../relay/types';\nimport type { TransactionPayFiatAsset } from './constants';\nimport { FIAT_ENABLED_TYPES } from './constants';\n\nconst log = createModuleLogger(projectLogger, 'fiat-utils');\n\nexport function deriveFiatAssetForFiatPayment(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayFiatAsset {\n const enabledTypes = getFiatEnabledTypes(messenger);\n const txType = resolveTransactionType(transaction, enabledTypes);\n\n return getFiatAssetPerTransactionType(messenger, txType);\n}\n\n/**\n * Resolves the effective transaction type for fiat strategy purposes.\n *\n * For non-batch transactions returns the transaction's own type.\n * For batch transactions returns the first nested transaction type\n * that appears in the enabled types list, or the batch type itself\n * if no nested type matches.\n *\n * @param transaction - The transaction metadata to inspect.\n * @param enabledTypes - Transaction types eligible for fiat payment.\n * @returns The resolved transaction type, or `undefined`.\n */\nexport function resolveTransactionType(\n transaction: TransactionMeta,\n enabledTypes: TransactionType[],\n): TransactionType | undefined {\n if (transaction.type !== TransactionType.batch) {\n return transaction.type;\n }\n\n const nestedType = transaction.nestedTransactions?.find(\n (tx) => tx.type && enabledTypes.includes(tx.type),\n )?.type;\n\n return nestedType ?? transaction.type;\n}\n\n/**\n * Checks whether a transaction is a Money Account deposit.\n *\n * Handles both direct `moneyAccountDeposit` transactions and EIP-7702\n * batch transactions that contain a `moneyAccountDeposit` nested call.\n * Uses {@link resolveTransactionType} with `FIAT_ENABLED_TYPES` to\n * correctly skip non-deposit nested types (e.g. `tokenMethodApprove`).\n *\n * @param transaction - The transaction metadata to inspect.\n * @returns `true` if the transaction is a Money Account deposit.\n */\nexport function isMoneyAccountDepositTransaction(\n transaction: TransactionMeta,\n): boolean {\n return (\n resolveTransactionType(transaction, FIAT_ENABLED_TYPES) ===\n TransactionType.moneyAccountDeposit\n );\n}\n\n/**\n * Resolves the raw source amount for a completed fiat order.\n *\n * Attempts to read the actual transferred amount from the on-chain transaction\n * identified by `order.txHash`. If the on-chain read fails or returns\n * no amount, falls back to computing the amount from `order.cryptoAmount`.\n *\n * @param options - The resolution options.\n * @param options.messenger - Controller messenger for network access.\n * @param options.order - The completed on-ramp order.\n * @param options.fiatAsset - The fiat asset describing the expected token.\n * @param options.walletAddress - Recipient wallet address for on-chain lookup.\n * @returns The raw (atomic) source amount as a decimal string.\n */\nexport async function resolveSourceAmountRaw({\n messenger,\n order,\n fiatAsset,\n walletAddress,\n}: {\n messenger: TransactionPayControllerMessenger;\n order: RampsOrder;\n fiatAsset: TransactionPayFiatAsset;\n walletAddress: Hex;\n}): Promise<string> {\n if (order.txHash) {\n try {\n const onChainAmount = await getTransferredAmountFromTxHash({\n messenger,\n txHash: order.txHash,\n chainId: fiatAsset.chainId,\n tokenAddress: fiatAsset.address,\n walletAddress,\n });\n\n if (onChainAmount) {\n log('Resolved source amount from on-chain transaction', {\n txHash: order.txHash,\n onChainAmount,\n });\n return onChainAmount;\n }\n } catch (error) {\n log(\n 'Failed to read on-chain amount, falling back to order.cryptoAmount',\n { txHash: order.txHash, error },\n );\n }\n }\n\n const tokenInfo = getTokenInfo(\n messenger,\n fiatAsset.address,\n fiatAsset.chainId,\n );\n\n if (!tokenInfo) {\n throw new Error(\n `Unable to resolve token info for fiat asset ${fiatAsset.address} on chain ${fiatAsset.chainId}`,\n );\n }\n\n return getRawSourceAmountFromOrderCryptoAmount({\n cryptoAmount: order.cryptoAmount,\n decimals: tokenInfo.decimals,\n });\n}\n\n/**\n * Converts the order's human-readable crypto amount to a raw token amount.\n *\n * @param options - The conversion options.\n * @param options.cryptoAmount - Human-readable crypto amount from the completed order.\n * @param options.decimals - Token decimals for the fiat asset.\n * @returns The raw token amount as a string.\n */\nexport function getRawSourceAmountFromOrderCryptoAmount({\n cryptoAmount,\n decimals,\n}: {\n cryptoAmount: RampsOrder['cryptoAmount'];\n decimals: number;\n}): string {\n const normalizedAmount = new BigNumber(String(cryptoAmount));\n\n if (!normalizedAmount.isFinite() || normalizedAmount.lte(0)) {\n throw new Error(\n `Invalid fiat order crypto amount: ${String(cryptoAmount)}`,\n );\n }\n\n const rawAmount = normalizedAmount\n .shiftedBy(decimals)\n .decimalPlaces(0, BigNumber.ROUND_DOWN)\n .toFixed(0);\n\n if (!new BigNumber(rawAmount).gt(0)) {\n throw new Error('Computed fiat order source amount is not positive');\n }\n\n return rawAmount;\n}\n\n/**\n * Validates that the relay exchange rate hasn't drifted significantly between\n * the original quoting phase and the post-settlement discovery quote.\n *\n * Compares the USD output/input ratio from both quotes. This normalises for\n * different source amounts (quoting phase uses a theoretical amount, discovery\n * uses the actual settled amount) so the comparison reflects genuine rate\n * movement rather than amount differences.\n *\n * @param options - The validation options.\n * @param options.originalQuote - Relay quote from the original quoting phase.\n * @param options.discoveryQuote - Relay quote from the post-settlement discovery.\n * @param options.maxRateDriftPercent - Maximum allowed rate drift percentage.\n * @param options.transactionId - Transaction ID for error reporting.\n */\nexport function validateRelayRateDrift({\n originalQuote,\n discoveryQuote,\n maxRateDriftPercent,\n transactionId,\n}: {\n originalQuote: RelayQuote;\n discoveryQuote: RelayQuote;\n maxRateDriftPercent: number;\n transactionId: string;\n}): void {\n const originalIn = new BigNumber(originalQuote.details.currencyIn.amountUsd);\n const originalOut = new BigNumber(\n originalQuote.details.currencyOut.amountUsd,\n );\n const discoveryIn = new BigNumber(\n discoveryQuote.details.currencyIn.amountUsd,\n );\n const discoveryOut = new BigNumber(\n discoveryQuote.details.currencyOut.amountUsd,\n );\n\n if (\n !originalIn.gt(0) ||\n !originalOut.gt(0) ||\n !discoveryIn.gt(0) ||\n !discoveryOut.gt(0)\n ) {\n return;\n }\n\n const originalRate = originalOut.dividedBy(originalIn);\n const discoveryRate = discoveryOut.dividedBy(discoveryIn);\n\n const driftPercent = originalRate\n .minus(discoveryRate)\n .dividedBy(originalRate)\n .multipliedBy(100);\n\n log('Relay rate drift check', {\n originalRate: originalRate.toFixed(6),\n discoveryRate: discoveryRate.toFixed(6),\n driftPercent: driftPercent.toFixed(2),\n maxRateDriftPercent,\n transactionId,\n });\n\n if (driftPercent.gt(maxRateDriftPercent)) {\n throw new Error(\n `Relay rate drift too high for transaction ` +\n `${driftPercent.toFixed(2)}% exceeds ${maxRateDriftPercent}% max`,\n );\n }\n}\n\n/**\n * Extracts the provider code from a ramps provider string.\n *\n * Accepts the canonical provider code (e.g. `transak-native`) and, for\n * backwards compatibility, the legacy path form (e.g. `/providers/transak-native`).\n *\n * @param provider - Canonical provider code, or legacy provider path.\n * @returns The provider code, or `null` if the format is invalid.\n */\nexport function extractProviderCode(\n provider: string | undefined,\n): string | null {\n if (!provider) {\n return null;\n }\n\n const parts = provider.split('/').filter(Boolean);\n\n if (parts[0] === 'providers') {\n return parts[1] ?? null;\n }\n\n return parts.length === 1 ? parts[0] : null;\n}\n"]}
@@ -161,7 +161,7 @@ async function getSingleQuote(request, fullRequest) {
161
161
  ...(useExecute
162
162
  ? { originGasOverhead: (0, feature_flags_1.getRelayOriginGasOverhead)(messenger) }
163
163
  : {}),
164
- recipient: from,
164
+ recipient: request.recipient ?? from,
165
165
  slippageTolerance,
166
166
  tradeType: useExactInput ? 'EXACT_INPUT' : 'EXPECTED_OUTPUT',
167
167
  user: from,
@@ -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 { toHex } from '@metamask/controller-utils';\nimport type {\n AuthorizationList,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TransactionPayStrategy } from '../..';\nimport {\n ARBITRUM_USDC_ADDRESS,\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_HYPERCORE,\n CHAIN_ID_POLYGON,\n HYPERCORE_USDC_ADDRESS,\n HYPERCORE_USDC_DECIMALS,\n NATIVE_TOKEN_ADDRESS,\n PERPS_DEPOSIT_TYPES,\n USDC_DECIMALS,\n STABLECOINS,\n PaymentOverride,\n} from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n Amount,\n FiatRates,\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { getFiatValueFromUsd } from '../../utils/amounts';\nimport {\n getFeatureFlags,\n getRelayOriginGasOverhead,\n getSlippage,\n isEIP7702Chain,\n isRelayExecuteEnabled,\n} from '../../utils/feature-flags';\nimport { calculateGasCost } from '../../utils/gas';\nimport {\n getGasStationCostInSourceTokenRaw,\n getGasStationEligibility,\n} from '../../utils/gas-station';\nimport { estimateQuoteGasLimits } from '../../utils/quote-gas';\nimport type { QuoteGasTransaction } from '../../utils/quote-gas';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n normalizeTokenAddress,\n TokenAddressTarget,\n} from '../../utils/token';\nimport { isPredictWithdrawTransaction } from '../../utils/transaction';\nimport { TOKEN_TRANSFER_FOUR_BYTE } from './constants';\nimport { applyPolymarketDepositWalletOverrides } from './polymarket/withdraw';\nimport { fetchRelayQuote } from './relay-api';\nimport { getRelayMaxGasStationQuote } from './relay-max-gas-station';\nimport type {\n RelayQuote,\n RelayQuoteMetamask,\n RelayQuoteRequest,\n RelayTransactionStep,\n} from './types';\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n// Buffer applied to the gas cost when reserving native tokens for gas in\n// post-quote flows, accounting for gas limit re-estimation variance.\nconst POST_QUOTE_GAS_BUFFER = 1.1;\n\n// Hardcoded gas allowance for the prepended payment override transaction(s).\nconst PAYMENT_OVERRIDE_GAS = 75_000;\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 .filter((singleRequest) => {\n const hasTargetMinimum = singleRequest.targetAmountMinimum !== '0';\n const isPostQuote = Boolean(singleRequest.isPostQuote);\n const isExactInputRequest =\n Boolean(singleRequest.isMaxAmount) &&\n new BigNumber(singleRequest.sourceTokenAmount).gt(0);\n\n return hasTargetMinimum || isPostQuote || isExactInputRequest;\n })\n .map((singleRequest) =>\n normalizeRequest(singleRequest, request.transaction),\n );\n\n log('Normalized requests', normalizedRequests);\n\n return await Promise.all(\n normalizedRequests.map((singleRequest) =>\n getQuoteWithMaxAmountHandling(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\nasync function getQuoteWithMaxAmountHandling(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { isMaxAmount } = request;\n\n if (!isMaxAmount) {\n return getQuoteWithPostQuoteGasHandling(request, fullRequest);\n }\n\n return getRelayMaxGasStationQuote(request, fullRequest, getSingleQuote);\n}\n\n/**\n * For post-quote flows, fetch an initial quote to compute gas cost in source\n * token, then re-quote with the source amount reduced by the gas cost.\n * This ensures Relay reserves enough for the gas fee token payment.\n *\n * For non-post-quote flows, just returns a single quote.\n *\n * @param request - Quote request.\n * @param fullRequest - Full request context.\n * @returns The final quote (phase 2 for post-quote, or phase 1 for normal).\n */\nasync function getQuoteWithPostQuoteGasHandling(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const phase1Quote = await getSingleQuote(request, fullRequest);\n\n if (!request.isPostQuote) {\n return phase1Quote;\n }\n\n if (phase1Quote.original.metamask?.isExecute) {\n return phase1Quote;\n }\n\n // Gas must be subtracted from the source amount when the user's balance\n // is fully committed to the swap. This applies when gas is paid via an\n // ERC-20 fee token (isSourceGasFeeToken) OR when the source itself is\n // the native gas token (gas comes from the same pool as the swap value).\n const isSourceNative =\n request.sourceTokenAddress.toLowerCase() ===\n getNativeToken(request.sourceChainId).toLowerCase() ||\n request.sourceTokenAddress.toLowerCase() ===\n NATIVE_TOKEN_ADDRESS.toLowerCase();\n\n if (!phase1Quote.fees.isSourceGasFeeToken && !isSourceNative) {\n return phase1Quote;\n }\n\n const gasCostRaw = new BigNumber(phase1Quote.fees.sourceNetwork.max.raw)\n .multipliedBy(POST_QUOTE_GAS_BUFFER)\n .integerValue(BigNumber.ROUND_UP);\n\n const existingHeadroom = new BigNumber(request.sourceBalanceRaw).minus(\n request.sourceTokenAmount,\n );\n\n if (existingHeadroom.isGreaterThanOrEqualTo(gasCostRaw)) {\n log('Sufficient existing balance for gas, skipping subtraction', {\n existingHeadroom: existingHeadroom.toString(10),\n gasCostRaw: gasCostRaw.toString(10),\n });\n return phase1Quote;\n }\n\n const adjustedSourceAmount = new BigNumber(request.sourceTokenAmount)\n .minus(gasCostRaw)\n .integerValue(BigNumber.ROUND_DOWN);\n\n log('Subtracting gas from source for post-quote two-call', {\n originalSourceAmount: request.sourceTokenAmount,\n gasCostRaw,\n adjustedSourceAmount: adjustedSourceAmount.toString(10),\n });\n\n if (!adjustedSourceAmount.isGreaterThan(0)) {\n log(\n 'Insufficient balance after gas subtraction for post-quote, using phase 1',\n );\n return phase1Quote;\n }\n\n try {\n const phase2Quote = await getSingleQuote(\n {\n ...request,\n sourceTokenAmount: adjustedSourceAmount.toFixed(\n 0,\n BigNumber.ROUND_DOWN,\n ),\n },\n fullRequest,\n );\n\n if (\n phase1Quote.fees.isSourceGasFeeToken &&\n !phase2Quote.fees.isSourceGasFeeToken\n ) {\n log('Phase 2 lost gas fee token eligibility, falling back to phase 1');\n return phase1Quote;\n }\n\n return phase2Quote;\n } catch (error) {\n log('Phase 2 quote failed, falling back to phase 1', { error });\n return phase1Quote;\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 {\n accountSupports7702: supports7702,\n messenger,\n signal,\n transaction,\n } = 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 useExecute =\n supports7702 &&\n isRelayExecuteEnabled(messenger) &&\n isEIP7702Chain(messenger, sourceChainId);\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 ...(useExecute\n ? { originGasOverhead: getRelayOriginGasOverhead(messenger) }\n : {}),\n recipient: from,\n slippageTolerance,\n tradeType: useExactInput ? 'EXACT_INPUT' : 'EXPECTED_OUTPUT',\n user: from,\n };\n\n if (request.isPolymarketDepositWallet) {\n await applyPolymarketDepositWalletOverrides(body, request, messenger);\n }\n\n // Skip transaction processing when skipProcessTransactions (defaulting to\n // isPostQuote) is true — the original transaction will be included in the\n // batch separately, not as part of the quote.\n // Skip for Polymarket deposit wallet flows — the source is already a\n // bridged token transfer, not a contract call to embed.\n const shouldProcessTransactions =\n !(request.skipProcessTransactions ?? request.isPostQuote) &&\n !request.isPolymarketDepositWallet;\n\n if (shouldProcessTransactions) {\n await processTransactions(transaction, request, body, messenger);\n } else if (\n request.isPostQuote &&\n request.paymentOverride === PaymentOverride.MoneyAccount\n ) {\n await processMoneyAccountPostQuote(transaction, request, body, messenger);\n } else if (request.refundTo) {\n // For post-quote flows, honour the caller-specified refund address so that\n // failed Relay transactions refund to the correct account (e.g. the Predict\n // Safe proxy) rather than defaulting to the EOA.\n body.refundTo = request.refundTo;\n }\n\n log('Request body', body);\n\n const quote = await fetchRelayQuote(messenger, body, signal);\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\nfunction normalizeAuthorizationList(\n authorizationList: AuthorizationList | undefined,\n): RelayQuoteRequest['authorizationList'] {\n return authorizationList?.map((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/**\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 requestBody.authorizationList = normalizeAuthorizationList(\n delegation.authorizationList,\n );\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 const fundingRecipient = (transaction.txParams?.from as Hex) ?? request.from;\n\n requestBody.txs = [\n {\n to: request.targetTokenAddress,\n data: buildTokenTransferData(\n fundingRecipient,\n request.targetAmountMinimum,\n ),\n value: '0x0',\n },\n {\n to: delegation.to,\n data: delegation.data,\n value: delegation.value,\n },\n ];\n}\n\nasync function processMoneyAccountPostQuote(\n transaction: TransactionMeta,\n request: QuoteRequest,\n requestBody: RelayQuoteRequest,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { transactionData: transactionDataList } = messenger.call(\n 'TransactionPayController:getState',\n );\n\n const transactionData = transactionDataList[transaction.id];\n const amountHuman = transactionData?.tokens?.[0]?.amountHuman ?? '0';\n\n const {\n calls: overrideCalls,\n recipient,\n authorizationList,\n } = await messenger.call('TransactionPayController:getPaymentOverrideData', {\n amount: amountHuman,\n transaction,\n transactionData,\n });\n\n if (!overrideCalls.length) {\n log('No payment override calls for money account post-quote');\n return;\n }\n\n const fundingRecipient = recipient ?? request.from;\n\n requestBody.authorizationList = normalizeAuthorizationList(authorizationList);\n requestBody.tradeType = 'EXACT_OUTPUT';\n requestBody.amount = transactionData?.tokens?.[0]?.amountRaw ?? '0';\n requestBody.txs = [\n {\n to: request.targetTokenAddress,\n data: buildTokenTransferData(fundingRecipient, request.sourceTokenAmount),\n value: '0x0',\n },\n ...overrideCalls.map((call) => ({\n to: call.to as Hex,\n data: call.data as Hex,\n value: (call.value as Hex) ?? '0x0',\n })),\n ];\n\n log('Added money account deposit calls to quote body', {\n callCount: overrideCalls.length,\n });\n}\n\n/**\n * Normalizes requests for Relay.\n *\n * @param request - Quote request to normalize.\n * @param transaction - Parent transaction metadata, used to gate\n * Hyperliquid-specific rewrites on transaction type.\n * @returns Normalized request.\n */\nfunction normalizeRequest(\n request: QuoteRequest,\n transaction: TransactionMeta,\n): QuoteRequest {\n const newRequest = {\n ...request,\n };\n\n const isPerpsDeposit =\n transaction.type !== undefined &&\n PERPS_DEPOSIT_TYPES.includes(transaction.type);\n\n const isHyperliquidDeposit =\n isPerpsDeposit &&\n !request.isPostQuote &&\n request.targetChainId === CHAIN_ID_ARBITRUM &&\n request.targetTokenAddress.toLowerCase() ===\n ARBITRUM_USDC_ADDRESS.toLowerCase();\n\n newRequest.sourceTokenAddress = normalizeTokenAddress(\n newRequest.sourceTokenAddress,\n newRequest.sourceChainId,\n TokenAddressTarget.Relay,\n );\n newRequest.targetTokenAddress = normalizeTokenAddress(\n newRequest.targetTokenAddress,\n newRequest.targetChainId,\n TokenAddressTarget.Relay,\n );\n\n if (isHyperliquidDeposit) {\n newRequest.targetChainId = CHAIN_ID_HYPERCORE;\n newRequest.targetTokenAddress = HYPERCORE_USDC_ADDRESS;\n newRequest.targetAmountMinimum = new BigNumber(request.targetAmountMinimum)\n .shiftedBy(HYPERCORE_USDC_DECIMALS - USDC_DECIMALS)\n .toString(10);\n\n log('Converting Arbitrum Hyperliquid deposit to direct deposit', {\n originalRequest: request,\n normalizedRequest: newRequest,\n });\n }\n\n // HyperLiquid withdrawal: source is HyperCore Perps USDC, not Arbitrum.\n if (request.isHyperliquidSource) {\n newRequest.sourceChainId = CHAIN_ID_HYPERCORE;\n newRequest.sourceTokenAddress = HYPERCORE_USDC_ADDRESS;\n\n if (newRequest.sourceTokenAmount) {\n newRequest.sourceTokenAmount = new BigNumber(newRequest.sourceTokenAmount)\n .shiftedBy(HYPERCORE_USDC_DECIMALS - USDC_DECIMALS)\n .toString(10);\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 appFeeUsd = new BigNumber(quote.fees?.app?.amountUsd ?? '0');\n const metaMaskFee = getFiatValueFromUsd(appFeeUsd, usdToFiatRate);\n\n // Subtract app fee from provider fee since totalImpact.usd already includes it\n const providerFeeUsd = calculateProviderFee(quote).minus(appFeeUsd);\n const provider = subsidizedFeeUsd.gt(0)\n ? { usd: '0', fiat: '0' }\n : getFiatValueFromUsd(providerFeeUsd, usdToFiatRate);\n\n const {\n gasLimits,\n is7702,\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 targetAmountUsd = isTargetStablecoin\n ? new BigNumber(currencyOut.amountFormatted)\n : new BigNumber(currencyOut.amountUsd);\n\n const targetAmount = getFiatValueFromUsd(targetAmountUsd, usdToFiatRate);\n\n const metamask: RelayQuoteMetamask = {\n ...quote.metamask,\n gasLimits: is7702 ? [gasLimits[0]] : gasLimits,\n is7702,\n };\n\n return {\n dust,\n estimatedDuration: details.timeEstimate,\n fees: {\n isSourceGasFeeToken,\n metaMask: metaMaskFee,\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 * 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 // For HyperLiquid source, the normalized chain/token (HyperCore + Perps USDC)\n // won't have a fiat rate entry. Use Arbitrum USDC instead since Perps USDC\n // is pegged 1:1.\n const sourceChainId = request.isHyperliquidSource\n ? CHAIN_ID_ARBITRUM\n : request.sourceChainId;\n const sourceTokenAddress = request.isHyperliquidSource\n ? ARBITRUM_USDC_ADDRESS\n : request.sourceTokenAddress;\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 * When the execute flow is active (indicated by `quote.metamask.isExecute`),\n * network fees are zeroed because the relayer covers them.\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 is7702: boolean;\n }\n> {\n const { from, sourceChainId, sourceTokenAddress } = request;\n\n if (quote.metamask?.isExecute) {\n log('Zeroing network fees for execute flow');\n\n const zeroAmount = { fiat: '0', human: '0', raw: '0', usd: '0' };\n\n return {\n estimate: zeroAmount,\n max: zeroAmount,\n gasLimits: [],\n is7702: false,\n };\n }\n\n // HyperLiquid withdrawals are gasless -- the \"deposit\" step is an HL\n // sendAsset (off-chain signature), not an on-chain transaction.\n if (request.isHyperliquidSource) {\n log('Zeroing network fees for HyperLiquid withdrawal (gasless)');\n\n const zeroAmount = { fiat: '0', human: '0', raw: '0', usd: '0' };\n\n return {\n estimate: zeroAmount,\n max: zeroAmount,\n gasLimits: [],\n is7702: false,\n };\n }\n\n const txSteps = quote.steps.filter(\n (step): step is RelayTransactionStep => step.kind === 'transaction',\n );\n const relayParams = txSteps\n .flatMap((step) => step.items)\n .map((item) => item.data);\n\n const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } =\n relayParams[0];\n\n const isPredictWithdraw =\n request.isPostQuote && isPredictWithdrawTransaction(transaction);\n\n // `fromOverride = Safe proxy` is only valid for deposit-style Relay routes\n // where the deposit contract reads the user's source-token balance directly.\n // Same-chain destinations route through DEX swap aggregators that frequently\n // reject contract callers (anti-MEV `msg.sender == tx.origin` checks,\n // ERC777-style callback interfaces, native wrap/unwrap requiring caller\n // native balance). Simulating those from the Safe proxy reverts and breaks\n // gas estimation. For swap-only routes, fall back to the relay params'\n // EOA `from` so simulation succeeds.\n const hasDepositStep = quote.steps.some((step) => step.id === 'deposit');\n const useFromOverride = isPredictWithdraw && hasDepositStep;\n const fromOverride = useFromOverride ? request.refundTo : undefined;\n\n // For post-quote flows the original transaction will be prepended to the\n // batch at submission time. Include it in the gas estimation so\n // estimateGasBatch sees the full batch and can detect EIP-7702 support.\n // Without this, a single relay step is estimated alone, gets is7702=false,\n // and the batch falls back to separate type-0x2 transactions that each\n // need native gas — breaking zero-balance fiat-funded accounts.\n const originalTxGasParams = getOriginalTxGasParams(request, transaction);\n const allGasParams = originalTxGasParams\n ? [originalTxGasParams, ...relayParams]\n : relayParams;\n\n const gasResult = await calculateSourceNetworkGasLimit(\n allGasParams,\n messenger,\n fromOverride,\n );\n\n // When the original tx was NOT included in gas estimation (no gas params\n // available), fall back to the legacy prepend-after-the-fact approach.\n const { gasLimits, is7702, totalGasEstimate, totalGasLimit } =\n originalTxGasParams\n ? gasResult\n : combinePrependedGas(gasResult, request, transaction);\n\n log('Gas limit', {\n is7702,\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, is7702 };\n\n if (new BigNumber(nativeBalance).isGreaterThanOrEqualTo(max.raw)) {\n return result;\n }\n\n const gasStationEligibility = getGasStationEligibility(\n messenger,\n sourceChainId,\n );\n\n if (gasStationEligibility.isDisabledChain) {\n log('Skipping gas station as disabled chain', {\n sourceChainId,\n });\n\n return result;\n }\n\n if (!gasStationEligibility.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 // Gas-fee-token lookup must use the Safe proxy for ALL Predict withdraws,\n // not only deposit-style routes. The user's source token (pUSD) lives in\n // the Safe; the EOA is empty until the Safe.execTransaction sub-call runs\n // mid-batch. Querying the EOA for gas-fee-token availability would always\n // return nothing and force users to hold POL.\n // (`useFromOverride` only governs the gas-estimation `from` address, where\n // swap-style routes need EOA because DEX routers reject contract callers.)\n if (isPredictWithdraw && request.refundTo) {\n log('Using proxy address for predict withdraw gas station simulation', {\n proxyAddress: request.refundTo,\n sourceTokenAddress,\n totalGasEstimate,\n });\n\n const gasFeeTokenCost = await getGasStationCostInSourceTokenRaw({\n firstStepData: {\n data,\n to,\n value,\n },\n messenger,\n request: {\n from: request.refundTo,\n sourceChainId,\n sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount: relayParams.length + 1,\n });\n\n if (gasFeeTokenCost) {\n log('Using predict withdraw gas fee token for source network', {\n gasFeeTokenCost,\n });\n\n return {\n isGasFeeToken: true,\n estimate: gasFeeTokenCost,\n max: gasFeeTokenCost,\n gasLimits,\n is7702,\n };\n }\n\n return result;\n }\n\n const gasFeeTokenCost = await getGasStationCostInSourceTokenRaw({\n firstStepData: {\n data,\n to,\n value,\n },\n messenger,\n request: {\n from,\n sourceChainId,\n sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount: Math.max(relayParams.length, gasLimits.length),\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 is7702,\n };\n}\n\n/**\n * Calculate the total gas limit for the source network.\n *\n * @param params - Array of relay transaction parameters.\n * @param messenger - Controller messenger.\n * @param fromOverride - Optional address to use as `from` in gas estimation\n * instead of the address in the relay params. Used in predict withdraw flows\n * to estimate with the proxy/Safe address that holds the source token balance.\n * @returns Total gas estimates and per-transaction gas limits.\n */\nasync function calculateSourceNetworkGasLimit(\n params: RelayTransactionStep['items'][0]['data'][],\n messenger: TransactionPayControllerMessenger,\n fromOverride?: Hex,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n is7702: boolean;\n}> {\n const transactions = params.map((singleParams) =>\n toRelayQuoteGasTransaction(singleParams, fromOverride),\n );\n\n const relayGasResult = await estimateQuoteGasLimits({\n fallbackGas: getFeatureFlags(messenger).relayFallbackGas,\n fallbackOnSimulationFailure: true,\n messenger,\n transactions,\n });\n\n return {\n gasLimits: relayGasResult.gasLimits.map((gasLimit) => gasLimit.max),\n is7702: relayGasResult.is7702,\n totalGasEstimate: relayGasResult.totalGasEstimate,\n totalGasLimit: relayGasResult.totalGasLimit,\n };\n}\n\nfunction toRelayQuoteGasTransaction(\n singleParams: RelayTransactionStep['items'][0]['data'],\n fromOverride?: Hex,\n): QuoteGasTransaction {\n return {\n chainId: toHex(singleParams.chainId),\n data: singleParams.data,\n from: fromOverride ?? singleParams.from,\n gas: fromOverride ? undefined : singleParams.gas,\n to: singleParams.to,\n value: singleParams.value ?? '0',\n };\n}\n\ntype RelayStepData = RelayTransactionStep['items'][0]['data'];\n\nfunction getOriginalTxGasParams(\n request: QuoteRequest,\n transaction: TransactionMeta,\n): RelayStepData | undefined {\n if (!request.isPostQuote) {\n return undefined;\n }\n\n const { txParams } = transaction;\n const to = txParams.to as Hex | undefined;\n\n if (!to) {\n return undefined;\n }\n\n const hasAccountOverride =\n request.from.toLowerCase() !== (txParams.from as Hex).toLowerCase();\n\n if (hasAccountOverride) {\n return undefined;\n }\n\n const nestedGas = transaction.nestedTransactions?.find((tx) => tx.gas)?.gas;\n const gas = nestedGas ?? txParams.gas;\n\n return {\n chainId: Number(transaction.chainId),\n data: (txParams.data as Hex) ?? ('0x' as Hex),\n from: txParams.from as Hex,\n gas: gas ? String(gas) : undefined,\n maxFeePerGas: '0',\n maxPriorityFeePerGas: '0',\n to,\n value: (txParams.value as string) ?? '0',\n };\n}\n\ntype RelayGasResult = {\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n is7702: boolean;\n};\n\nfunction combinePrependedGas(\n relayOnlyGas: RelayGasResult,\n request: QuoteRequest,\n transaction: TransactionMeta,\n): RelayGasResult {\n const gas = request.isPostQuote\n ? combinePostQuoteGas(relayOnlyGas, transaction)\n : relayOnlyGas;\n\n return request.paymentOverride ? addPaymentOverrideGas(gas) : gas;\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 relayGas.is7702 - Whether the relay gas came from a combined 7702 batch estimate.\n * @param transaction - Original transaction metadata.\n * @returns Combined gas estimates including the original transaction.\n */\nfunction combinePostQuoteGas(\n relayGas: RelayGasResult,\n transaction: TransactionMeta,\n): RelayGasResult {\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\n if (relayGas.is7702) {\n // Combined 7702 gas limit — add the original tx gas so the batch\n // keeps using a single 7702 limit.\n gasLimits = [gasLimits[0] + originalTxGas];\n } else {\n // Multiple 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 is7702: relayGas.is7702,\n gasLimits,\n totalGasLimit,\n });\n\n return {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n is7702: relayGas.is7702,\n };\n}\n\nfunction addPaymentOverrideGas(relayGas: RelayGasResult): RelayGasResult {\n const gasLimits = relayGas.is7702\n ? [relayGas.gasLimits[0] + PAYMENT_OVERRIDE_GAS]\n : [PAYMENT_OVERRIDE_GAS, ...relayGas.gasLimits];\n\n return {\n totalGasEstimate: relayGas.totalGasEstimate + PAYMENT_OVERRIDE_GAS,\n totalGasLimit: relayGas.totalGasLimit + PAYMENT_OVERRIDE_GAS,\n gasLimits,\n is7702: relayGas.is7702,\n };\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}\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 { toHex } from '@metamask/controller-utils';\nimport type {\n AuthorizationList,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { TransactionPayStrategy } from '../..';\nimport {\n ARBITRUM_USDC_ADDRESS,\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_HYPERCORE,\n CHAIN_ID_POLYGON,\n HYPERCORE_USDC_ADDRESS,\n HYPERCORE_USDC_DECIMALS,\n NATIVE_TOKEN_ADDRESS,\n PERPS_DEPOSIT_TYPES,\n USDC_DECIMALS,\n STABLECOINS,\n PaymentOverride,\n} from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n Amount,\n FiatRates,\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { getFiatValueFromUsd } from '../../utils/amounts';\nimport {\n getFeatureFlags,\n getRelayOriginGasOverhead,\n getSlippage,\n isEIP7702Chain,\n isRelayExecuteEnabled,\n} from '../../utils/feature-flags';\nimport { calculateGasCost } from '../../utils/gas';\nimport {\n getGasStationCostInSourceTokenRaw,\n getGasStationEligibility,\n} from '../../utils/gas-station';\nimport { estimateQuoteGasLimits } from '../../utils/quote-gas';\nimport type { QuoteGasTransaction } from '../../utils/quote-gas';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n normalizeTokenAddress,\n TokenAddressTarget,\n} from '../../utils/token';\nimport { isPredictWithdrawTransaction } from '../../utils/transaction';\nimport { TOKEN_TRANSFER_FOUR_BYTE } from './constants';\nimport { applyPolymarketDepositWalletOverrides } from './polymarket/withdraw';\nimport { fetchRelayQuote } from './relay-api';\nimport { getRelayMaxGasStationQuote } from './relay-max-gas-station';\nimport type {\n RelayQuote,\n RelayQuoteMetamask,\n RelayQuoteRequest,\n RelayTransactionStep,\n} from './types';\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n// Buffer applied to the gas cost when reserving native tokens for gas in\n// post-quote flows, accounting for gas limit re-estimation variance.\nconst POST_QUOTE_GAS_BUFFER = 1.1;\n\n// Hardcoded gas allowance for the prepended payment override transaction(s).\nconst PAYMENT_OVERRIDE_GAS = 75_000;\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 .filter((singleRequest) => {\n const hasTargetMinimum = singleRequest.targetAmountMinimum !== '0';\n const isPostQuote = Boolean(singleRequest.isPostQuote);\n const isExactInputRequest =\n Boolean(singleRequest.isMaxAmount) &&\n new BigNumber(singleRequest.sourceTokenAmount).gt(0);\n\n return hasTargetMinimum || isPostQuote || isExactInputRequest;\n })\n .map((singleRequest) =>\n normalizeRequest(singleRequest, request.transaction),\n );\n\n log('Normalized requests', normalizedRequests);\n\n return await Promise.all(\n normalizedRequests.map((singleRequest) =>\n getQuoteWithMaxAmountHandling(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\nasync function getQuoteWithMaxAmountHandling(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { isMaxAmount } = request;\n\n if (!isMaxAmount) {\n return getQuoteWithPostQuoteGasHandling(request, fullRequest);\n }\n\n return getRelayMaxGasStationQuote(request, fullRequest, getSingleQuote);\n}\n\n/**\n * For post-quote flows, fetch an initial quote to compute gas cost in source\n * token, then re-quote with the source amount reduced by the gas cost.\n * This ensures Relay reserves enough for the gas fee token payment.\n *\n * For non-post-quote flows, just returns a single quote.\n *\n * @param request - Quote request.\n * @param fullRequest - Full request context.\n * @returns The final quote (phase 2 for post-quote, or phase 1 for normal).\n */\nasync function getQuoteWithPostQuoteGasHandling(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const phase1Quote = await getSingleQuote(request, fullRequest);\n\n if (!request.isPostQuote) {\n return phase1Quote;\n }\n\n if (phase1Quote.original.metamask?.isExecute) {\n return phase1Quote;\n }\n\n // Gas must be subtracted from the source amount when the user's balance\n // is fully committed to the swap. This applies when gas is paid via an\n // ERC-20 fee token (isSourceGasFeeToken) OR when the source itself is\n // the native gas token (gas comes from the same pool as the swap value).\n const isSourceNative =\n request.sourceTokenAddress.toLowerCase() ===\n getNativeToken(request.sourceChainId).toLowerCase() ||\n request.sourceTokenAddress.toLowerCase() ===\n NATIVE_TOKEN_ADDRESS.toLowerCase();\n\n if (!phase1Quote.fees.isSourceGasFeeToken && !isSourceNative) {\n return phase1Quote;\n }\n\n const gasCostRaw = new BigNumber(phase1Quote.fees.sourceNetwork.max.raw)\n .multipliedBy(POST_QUOTE_GAS_BUFFER)\n .integerValue(BigNumber.ROUND_UP);\n\n const existingHeadroom = new BigNumber(request.sourceBalanceRaw).minus(\n request.sourceTokenAmount,\n );\n\n if (existingHeadroom.isGreaterThanOrEqualTo(gasCostRaw)) {\n log('Sufficient existing balance for gas, skipping subtraction', {\n existingHeadroom: existingHeadroom.toString(10),\n gasCostRaw: gasCostRaw.toString(10),\n });\n return phase1Quote;\n }\n\n const adjustedSourceAmount = new BigNumber(request.sourceTokenAmount)\n .minus(gasCostRaw)\n .integerValue(BigNumber.ROUND_DOWN);\n\n log('Subtracting gas from source for post-quote two-call', {\n originalSourceAmount: request.sourceTokenAmount,\n gasCostRaw,\n adjustedSourceAmount: adjustedSourceAmount.toString(10),\n });\n\n if (!adjustedSourceAmount.isGreaterThan(0)) {\n log(\n 'Insufficient balance after gas subtraction for post-quote, using phase 1',\n );\n return phase1Quote;\n }\n\n try {\n const phase2Quote = await getSingleQuote(\n {\n ...request,\n sourceTokenAmount: adjustedSourceAmount.toFixed(\n 0,\n BigNumber.ROUND_DOWN,\n ),\n },\n fullRequest,\n );\n\n if (\n phase1Quote.fees.isSourceGasFeeToken &&\n !phase2Quote.fees.isSourceGasFeeToken\n ) {\n log('Phase 2 lost gas fee token eligibility, falling back to phase 1');\n return phase1Quote;\n }\n\n return phase2Quote;\n } catch (error) {\n log('Phase 2 quote failed, falling back to phase 1', { error });\n return phase1Quote;\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 {\n accountSupports7702: supports7702,\n messenger,\n signal,\n transaction,\n } = 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 useExecute =\n supports7702 &&\n isRelayExecuteEnabled(messenger) &&\n isEIP7702Chain(messenger, sourceChainId);\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 ...(useExecute\n ? { originGasOverhead: getRelayOriginGasOverhead(messenger) }\n : {}),\n recipient: request.recipient ?? from,\n slippageTolerance,\n tradeType: useExactInput ? 'EXACT_INPUT' : 'EXPECTED_OUTPUT',\n user: from,\n };\n\n if (request.isPolymarketDepositWallet) {\n await applyPolymarketDepositWalletOverrides(body, request, messenger);\n }\n\n // Skip transaction processing when skipProcessTransactions (defaulting to\n // isPostQuote) is true — the original transaction will be included in the\n // batch separately, not as part of the quote.\n // Skip for Polymarket deposit wallet flows — the source is already a\n // bridged token transfer, not a contract call to embed.\n const shouldProcessTransactions =\n !(request.skipProcessTransactions ?? request.isPostQuote) &&\n !request.isPolymarketDepositWallet;\n\n if (shouldProcessTransactions) {\n await processTransactions(transaction, request, body, messenger);\n } else if (\n request.isPostQuote &&\n request.paymentOverride === PaymentOverride.MoneyAccount\n ) {\n await processMoneyAccountPostQuote(transaction, request, body, messenger);\n } else if (request.refundTo) {\n // For post-quote flows, honour the caller-specified refund address so that\n // failed Relay transactions refund to the correct account (e.g. the Predict\n // Safe proxy) rather than defaulting to the EOA.\n body.refundTo = request.refundTo;\n }\n\n log('Request body', body);\n\n const quote = await fetchRelayQuote(messenger, body, signal);\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\nfunction normalizeAuthorizationList(\n authorizationList: AuthorizationList | undefined,\n): RelayQuoteRequest['authorizationList'] {\n return authorizationList?.map((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/**\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 requestBody.authorizationList = normalizeAuthorizationList(\n delegation.authorizationList,\n );\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 const fundingRecipient = (transaction.txParams?.from as Hex) ?? request.from;\n\n requestBody.txs = [\n {\n to: request.targetTokenAddress,\n data: buildTokenTransferData(\n fundingRecipient,\n request.targetAmountMinimum,\n ),\n value: '0x0',\n },\n {\n to: delegation.to,\n data: delegation.data,\n value: delegation.value,\n },\n ];\n}\n\nasync function processMoneyAccountPostQuote(\n transaction: TransactionMeta,\n request: QuoteRequest,\n requestBody: RelayQuoteRequest,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { transactionData: transactionDataList } = messenger.call(\n 'TransactionPayController:getState',\n );\n\n const transactionData = transactionDataList[transaction.id];\n const amountHuman = transactionData?.tokens?.[0]?.amountHuman ?? '0';\n\n const {\n calls: overrideCalls,\n recipient,\n authorizationList,\n } = await messenger.call('TransactionPayController:getPaymentOverrideData', {\n amount: amountHuman,\n transaction,\n transactionData,\n });\n\n if (!overrideCalls.length) {\n log('No payment override calls for money account post-quote');\n return;\n }\n\n const fundingRecipient = recipient ?? request.from;\n\n requestBody.authorizationList = normalizeAuthorizationList(authorizationList);\n requestBody.tradeType = 'EXACT_OUTPUT';\n requestBody.amount = transactionData?.tokens?.[0]?.amountRaw ?? '0';\n requestBody.txs = [\n {\n to: request.targetTokenAddress,\n data: buildTokenTransferData(fundingRecipient, request.sourceTokenAmount),\n value: '0x0',\n },\n ...overrideCalls.map((call) => ({\n to: call.to as Hex,\n data: call.data as Hex,\n value: (call.value as Hex) ?? '0x0',\n })),\n ];\n\n log('Added money account deposit calls to quote body', {\n callCount: overrideCalls.length,\n });\n}\n\n/**\n * Normalizes requests for Relay.\n *\n * @param request - Quote request to normalize.\n * @param transaction - Parent transaction metadata, used to gate\n * Hyperliquid-specific rewrites on transaction type.\n * @returns Normalized request.\n */\nfunction normalizeRequest(\n request: QuoteRequest,\n transaction: TransactionMeta,\n): QuoteRequest {\n const newRequest = {\n ...request,\n };\n\n const isPerpsDeposit =\n transaction.type !== undefined &&\n PERPS_DEPOSIT_TYPES.includes(transaction.type);\n\n const isHyperliquidDeposit =\n isPerpsDeposit &&\n !request.isPostQuote &&\n request.targetChainId === CHAIN_ID_ARBITRUM &&\n request.targetTokenAddress.toLowerCase() ===\n ARBITRUM_USDC_ADDRESS.toLowerCase();\n\n newRequest.sourceTokenAddress = normalizeTokenAddress(\n newRequest.sourceTokenAddress,\n newRequest.sourceChainId,\n TokenAddressTarget.Relay,\n );\n newRequest.targetTokenAddress = normalizeTokenAddress(\n newRequest.targetTokenAddress,\n newRequest.targetChainId,\n TokenAddressTarget.Relay,\n );\n\n if (isHyperliquidDeposit) {\n newRequest.targetChainId = CHAIN_ID_HYPERCORE;\n newRequest.targetTokenAddress = HYPERCORE_USDC_ADDRESS;\n newRequest.targetAmountMinimum = new BigNumber(request.targetAmountMinimum)\n .shiftedBy(HYPERCORE_USDC_DECIMALS - USDC_DECIMALS)\n .toString(10);\n\n log('Converting Arbitrum Hyperliquid deposit to direct deposit', {\n originalRequest: request,\n normalizedRequest: newRequest,\n });\n }\n\n // HyperLiquid withdrawal: source is HyperCore Perps USDC, not Arbitrum.\n if (request.isHyperliquidSource) {\n newRequest.sourceChainId = CHAIN_ID_HYPERCORE;\n newRequest.sourceTokenAddress = HYPERCORE_USDC_ADDRESS;\n\n if (newRequest.sourceTokenAmount) {\n newRequest.sourceTokenAmount = new BigNumber(newRequest.sourceTokenAmount)\n .shiftedBy(HYPERCORE_USDC_DECIMALS - USDC_DECIMALS)\n .toString(10);\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 appFeeUsd = new BigNumber(quote.fees?.app?.amountUsd ?? '0');\n const metaMaskFee = getFiatValueFromUsd(appFeeUsd, usdToFiatRate);\n\n // Subtract app fee from provider fee since totalImpact.usd already includes it\n const providerFeeUsd = calculateProviderFee(quote).minus(appFeeUsd);\n const provider = subsidizedFeeUsd.gt(0)\n ? { usd: '0', fiat: '0' }\n : getFiatValueFromUsd(providerFeeUsd, usdToFiatRate);\n\n const {\n gasLimits,\n is7702,\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 targetAmountUsd = isTargetStablecoin\n ? new BigNumber(currencyOut.amountFormatted)\n : new BigNumber(currencyOut.amountUsd);\n\n const targetAmount = getFiatValueFromUsd(targetAmountUsd, usdToFiatRate);\n\n const metamask: RelayQuoteMetamask = {\n ...quote.metamask,\n gasLimits: is7702 ? [gasLimits[0]] : gasLimits,\n is7702,\n };\n\n return {\n dust,\n estimatedDuration: details.timeEstimate,\n fees: {\n isSourceGasFeeToken,\n metaMask: metaMaskFee,\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 * 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 // For HyperLiquid source, the normalized chain/token (HyperCore + Perps USDC)\n // won't have a fiat rate entry. Use Arbitrum USDC instead since Perps USDC\n // is pegged 1:1.\n const sourceChainId = request.isHyperliquidSource\n ? CHAIN_ID_ARBITRUM\n : request.sourceChainId;\n const sourceTokenAddress = request.isHyperliquidSource\n ? ARBITRUM_USDC_ADDRESS\n : request.sourceTokenAddress;\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 * When the execute flow is active (indicated by `quote.metamask.isExecute`),\n * network fees are zeroed because the relayer covers them.\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 is7702: boolean;\n }\n> {\n const { from, sourceChainId, sourceTokenAddress } = request;\n\n if (quote.metamask?.isExecute) {\n log('Zeroing network fees for execute flow');\n\n const zeroAmount = { fiat: '0', human: '0', raw: '0', usd: '0' };\n\n return {\n estimate: zeroAmount,\n max: zeroAmount,\n gasLimits: [],\n is7702: false,\n };\n }\n\n // HyperLiquid withdrawals are gasless -- the \"deposit\" step is an HL\n // sendAsset (off-chain signature), not an on-chain transaction.\n if (request.isHyperliquidSource) {\n log('Zeroing network fees for HyperLiquid withdrawal (gasless)');\n\n const zeroAmount = { fiat: '0', human: '0', raw: '0', usd: '0' };\n\n return {\n estimate: zeroAmount,\n max: zeroAmount,\n gasLimits: [],\n is7702: false,\n };\n }\n\n const txSteps = quote.steps.filter(\n (step): step is RelayTransactionStep => step.kind === 'transaction',\n );\n const relayParams = txSteps\n .flatMap((step) => step.items)\n .map((item) => item.data);\n\n const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } =\n relayParams[0];\n\n const isPredictWithdraw =\n request.isPostQuote && isPredictWithdrawTransaction(transaction);\n\n // `fromOverride = Safe proxy` is only valid for deposit-style Relay routes\n // where the deposit contract reads the user's source-token balance directly.\n // Same-chain destinations route through DEX swap aggregators that frequently\n // reject contract callers (anti-MEV `msg.sender == tx.origin` checks,\n // ERC777-style callback interfaces, native wrap/unwrap requiring caller\n // native balance). Simulating those from the Safe proxy reverts and breaks\n // gas estimation. For swap-only routes, fall back to the relay params'\n // EOA `from` so simulation succeeds.\n const hasDepositStep = quote.steps.some((step) => step.id === 'deposit');\n const useFromOverride = isPredictWithdraw && hasDepositStep;\n const fromOverride = useFromOverride ? request.refundTo : undefined;\n\n // For post-quote flows the original transaction will be prepended to the\n // batch at submission time. Include it in the gas estimation so\n // estimateGasBatch sees the full batch and can detect EIP-7702 support.\n // Without this, a single relay step is estimated alone, gets is7702=false,\n // and the batch falls back to separate type-0x2 transactions that each\n // need native gas — breaking zero-balance fiat-funded accounts.\n const originalTxGasParams = getOriginalTxGasParams(request, transaction);\n const allGasParams = originalTxGasParams\n ? [originalTxGasParams, ...relayParams]\n : relayParams;\n\n const gasResult = await calculateSourceNetworkGasLimit(\n allGasParams,\n messenger,\n fromOverride,\n );\n\n // When the original tx was NOT included in gas estimation (no gas params\n // available), fall back to the legacy prepend-after-the-fact approach.\n const { gasLimits, is7702, totalGasEstimate, totalGasLimit } =\n originalTxGasParams\n ? gasResult\n : combinePrependedGas(gasResult, request, transaction);\n\n log('Gas limit', {\n is7702,\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, is7702 };\n\n if (new BigNumber(nativeBalance).isGreaterThanOrEqualTo(max.raw)) {\n return result;\n }\n\n const gasStationEligibility = getGasStationEligibility(\n messenger,\n sourceChainId,\n );\n\n if (gasStationEligibility.isDisabledChain) {\n log('Skipping gas station as disabled chain', {\n sourceChainId,\n });\n\n return result;\n }\n\n if (!gasStationEligibility.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 // Gas-fee-token lookup must use the Safe proxy for ALL Predict withdraws,\n // not only deposit-style routes. The user's source token (pUSD) lives in\n // the Safe; the EOA is empty until the Safe.execTransaction sub-call runs\n // mid-batch. Querying the EOA for gas-fee-token availability would always\n // return nothing and force users to hold POL.\n // (`useFromOverride` only governs the gas-estimation `from` address, where\n // swap-style routes need EOA because DEX routers reject contract callers.)\n if (isPredictWithdraw && request.refundTo) {\n log('Using proxy address for predict withdraw gas station simulation', {\n proxyAddress: request.refundTo,\n sourceTokenAddress,\n totalGasEstimate,\n });\n\n const gasFeeTokenCost = await getGasStationCostInSourceTokenRaw({\n firstStepData: {\n data,\n to,\n value,\n },\n messenger,\n request: {\n from: request.refundTo,\n sourceChainId,\n sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount: relayParams.length + 1,\n });\n\n if (gasFeeTokenCost) {\n log('Using predict withdraw gas fee token for source network', {\n gasFeeTokenCost,\n });\n\n return {\n isGasFeeToken: true,\n estimate: gasFeeTokenCost,\n max: gasFeeTokenCost,\n gasLimits,\n is7702,\n };\n }\n\n return result;\n }\n\n const gasFeeTokenCost = await getGasStationCostInSourceTokenRaw({\n firstStepData: {\n data,\n to,\n value,\n },\n messenger,\n request: {\n from,\n sourceChainId,\n sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount: Math.max(relayParams.length, gasLimits.length),\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 is7702,\n };\n}\n\n/**\n * Calculate the total gas limit for the source network.\n *\n * @param params - Array of relay transaction parameters.\n * @param messenger - Controller messenger.\n * @param fromOverride - Optional address to use as `from` in gas estimation\n * instead of the address in the relay params. Used in predict withdraw flows\n * to estimate with the proxy/Safe address that holds the source token balance.\n * @returns Total gas estimates and per-transaction gas limits.\n */\nasync function calculateSourceNetworkGasLimit(\n params: RelayTransactionStep['items'][0]['data'][],\n messenger: TransactionPayControllerMessenger,\n fromOverride?: Hex,\n): Promise<{\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n is7702: boolean;\n}> {\n const transactions = params.map((singleParams) =>\n toRelayQuoteGasTransaction(singleParams, fromOverride),\n );\n\n const relayGasResult = await estimateQuoteGasLimits({\n fallbackGas: getFeatureFlags(messenger).relayFallbackGas,\n fallbackOnSimulationFailure: true,\n messenger,\n transactions,\n });\n\n return {\n gasLimits: relayGasResult.gasLimits.map((gasLimit) => gasLimit.max),\n is7702: relayGasResult.is7702,\n totalGasEstimate: relayGasResult.totalGasEstimate,\n totalGasLimit: relayGasResult.totalGasLimit,\n };\n}\n\nfunction toRelayQuoteGasTransaction(\n singleParams: RelayTransactionStep['items'][0]['data'],\n fromOverride?: Hex,\n): QuoteGasTransaction {\n return {\n chainId: toHex(singleParams.chainId),\n data: singleParams.data,\n from: fromOverride ?? singleParams.from,\n gas: fromOverride ? undefined : singleParams.gas,\n to: singleParams.to,\n value: singleParams.value ?? '0',\n };\n}\n\ntype RelayStepData = RelayTransactionStep['items'][0]['data'];\n\nfunction getOriginalTxGasParams(\n request: QuoteRequest,\n transaction: TransactionMeta,\n): RelayStepData | undefined {\n if (!request.isPostQuote) {\n return undefined;\n }\n\n const { txParams } = transaction;\n const to = txParams.to as Hex | undefined;\n\n if (!to) {\n return undefined;\n }\n\n const hasAccountOverride =\n request.from.toLowerCase() !== (txParams.from as Hex).toLowerCase();\n\n if (hasAccountOverride) {\n return undefined;\n }\n\n const nestedGas = transaction.nestedTransactions?.find((tx) => tx.gas)?.gas;\n const gas = nestedGas ?? txParams.gas;\n\n return {\n chainId: Number(transaction.chainId),\n data: (txParams.data as Hex) ?? ('0x' as Hex),\n from: txParams.from as Hex,\n gas: gas ? String(gas) : undefined,\n maxFeePerGas: '0',\n maxPriorityFeePerGas: '0',\n to,\n value: (txParams.value as string) ?? '0',\n };\n}\n\ntype RelayGasResult = {\n totalGasEstimate: number;\n totalGasLimit: number;\n gasLimits: number[];\n is7702: boolean;\n};\n\nfunction combinePrependedGas(\n relayOnlyGas: RelayGasResult,\n request: QuoteRequest,\n transaction: TransactionMeta,\n): RelayGasResult {\n const gas = request.isPostQuote\n ? combinePostQuoteGas(relayOnlyGas, transaction)\n : relayOnlyGas;\n\n return request.paymentOverride ? addPaymentOverrideGas(gas) : gas;\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 relayGas.is7702 - Whether the relay gas came from a combined 7702 batch estimate.\n * @param transaction - Original transaction metadata.\n * @returns Combined gas estimates including the original transaction.\n */\nfunction combinePostQuoteGas(\n relayGas: RelayGasResult,\n transaction: TransactionMeta,\n): RelayGasResult {\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\n if (relayGas.is7702) {\n // Combined 7702 gas limit — add the original tx gas so the batch\n // keeps using a single 7702 limit.\n gasLimits = [gasLimits[0] + originalTxGas];\n } else {\n // Multiple 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 is7702: relayGas.is7702,\n gasLimits,\n totalGasLimit,\n });\n\n return {\n totalGasEstimate,\n totalGasLimit,\n gasLimits,\n is7702: relayGas.is7702,\n };\n}\n\nfunction addPaymentOverrideGas(relayGas: RelayGasResult): RelayGasResult {\n const gasLimits = relayGas.is7702\n ? [relayGas.gasLimits[0] + PAYMENT_OVERRIDE_GAS]\n : [PAYMENT_OVERRIDE_GAS, ...relayGas.gasLimits];\n\n return {\n totalGasEstimate: relayGas.totalGasEstimate + PAYMENT_OVERRIDE_GAS,\n totalGasLimit: relayGas.totalGasLimit + PAYMENT_OVERRIDE_GAS,\n gasLimits,\n is7702: relayGas.is7702,\n };\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}\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"]}
@@ -157,7 +157,7 @@ async function getSingleQuote(request, fullRequest) {
157
157
  ...(useExecute
158
158
  ? { originGasOverhead: getRelayOriginGasOverhead(messenger) }
159
159
  : {}),
160
- recipient: from,
160
+ recipient: request.recipient ?? from,
161
161
  slippageTolerance,
162
162
  tradeType: useExactInput ? 'EXACT_INPUT' : 'EXPECTED_OUTPUT',
163
163
  user: from,