@metamask/transaction-pay-controller 9.0.0 → 10.0.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 (42) hide show
  1. package/CHANGELOG.md +15 -1
  2. package/dist/strategy/relay/relay-quotes.cjs +59 -5
  3. package/dist/strategy/relay/relay-quotes.cjs.map +1 -1
  4. package/dist/strategy/relay/relay-quotes.d.cts.map +1 -1
  5. package/dist/strategy/relay/relay-quotes.d.mts.map +1 -1
  6. package/dist/strategy/relay/relay-quotes.mjs +62 -8
  7. package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
  8. package/dist/strategy/relay/relay-submit.cjs +19 -17
  9. package/dist/strategy/relay/relay-submit.cjs.map +1 -1
  10. package/dist/strategy/relay/relay-submit.d.cts.map +1 -1
  11. package/dist/strategy/relay/relay-submit.d.mts.map +1 -1
  12. package/dist/strategy/relay/relay-submit.mjs +19 -17
  13. package/dist/strategy/relay/relay-submit.mjs.map +1 -1
  14. package/dist/tests/messenger-mock.cjs +3 -0
  15. package/dist/tests/messenger-mock.cjs.map +1 -1
  16. package/dist/tests/messenger-mock.d.cts +1 -0
  17. package/dist/tests/messenger-mock.d.cts.map +1 -1
  18. package/dist/tests/messenger-mock.d.mts +1 -0
  19. package/dist/tests/messenger-mock.d.mts.map +1 -1
  20. package/dist/tests/messenger-mock.mjs +3 -0
  21. package/dist/tests/messenger-mock.mjs.map +1 -1
  22. package/dist/types.cjs.map +1 -1
  23. package/dist/types.d.cts +4 -7
  24. package/dist/types.d.cts.map +1 -1
  25. package/dist/types.d.mts +4 -7
  26. package/dist/types.d.mts.map +1 -1
  27. package/dist/types.mjs.map +1 -1
  28. package/dist/utils/gas.cjs +39 -22
  29. package/dist/utils/gas.cjs.map +1 -1
  30. package/dist/utils/gas.d.cts +17 -1
  31. package/dist/utils/gas.d.cts.map +1 -1
  32. package/dist/utils/gas.d.mts +17 -1
  33. package/dist/utils/gas.d.mts.map +1 -1
  34. package/dist/utils/gas.mjs +38 -22
  35. package/dist/utils/gas.mjs.map +1 -1
  36. package/dist/utils/totals.cjs +2 -0
  37. package/dist/utils/totals.cjs.map +1 -1
  38. package/dist/utils/totals.d.cts.map +1 -1
  39. package/dist/utils/totals.d.mts.map +1 -1
  40. package/dist/utils/totals.mjs +2 -0
  41. package/dist/utils/totals.mjs.map +1 -1
  42. package/package.json +7 -7
package/CHANGELOG.md CHANGED
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [10.0.0]
11
+
12
+ ### Added
13
+
14
+ - Use gas fee token for Relay deposit transactions if insufficient native balance ([#7193](https://github.com/MetaMask/core/pull/7193))
15
+ - Add optional `fees.isSourceGasFeeToken` property to `TransactionPayQuote` and `TransactionPayTotals` type.
16
+
17
+ ### Changed
18
+
19
+ - **BREAKING:** Bump `@metamask/bridge-status-controller` from `^62.0.0` to `^63.0.0` ([#7207](https://github.com/MetaMask/core/pull/7207))
20
+ - **BREAKING:** Bump `@metamask/bridge-controller` from `^62.0.0` to `^63.0.0` ([#7207](https://github.com/MetaMask/core/pull/7207))
21
+ - **BREAKING:** Bump `@metamask/assets-controllers` from `^90.0.0` to `^91.0.0` ([#7207](https://github.com/MetaMask/core/pull/7207))
22
+
10
23
  ## [9.0.0]
11
24
 
12
25
  ### Changed
@@ -124,7 +137,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
124
137
 
125
138
  - Initial release ([#6820](https://github.com/MetaMask/core/pull/6820))
126
139
 
127
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@9.0.0...HEAD
140
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@10.0.0...HEAD
141
+ [10.0.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@9.0.0...@metamask/transaction-pay-controller@10.0.0
128
142
  [9.0.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@8.0.0...@metamask/transaction-pay-controller@9.0.0
129
143
  [8.0.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@7.0.0...@metamask/transaction-pay-controller@8.0.0
130
144
  [7.0.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@6.0.0...@metamask/transaction-pay-controller@7.0.0
@@ -160,14 +160,14 @@ function normalizeRequest(request) {
160
160
  * @param fullRequest - Full quotes request.
161
161
  * @returns Normalized quote.
162
162
  */
163
- function normalizeQuote(quote, request, fullRequest) {
163
+ async function normalizeQuote(quote, request, fullRequest) {
164
164
  const { messenger } = fullRequest;
165
165
  const { details } = quote;
166
166
  const { currencyIn } = details;
167
167
  const { usdToFiatRate } = getFiatRates(messenger, request);
168
168
  const dust = getFiatValueFromUsd(calculateDustUsd(quote, request), usdToFiatRate);
169
169
  const provider = getFiatValueFromUsd(calculateProviderFee(quote), usdToFiatRate);
170
- const sourceNetwork = calculateSourceNetworkCost(quote, messenger);
170
+ const { isGasFeeToken: isSourceGasFeeToken, ...sourceNetwork } = await calculateSourceNetworkCost(quote, messenger, request);
171
171
  const targetNetwork = {
172
172
  usd: '0',
173
173
  fiat: '0',
@@ -181,6 +181,7 @@ function normalizeQuote(quote, request, fullRequest) {
181
181
  dust,
182
182
  estimatedDuration: details.timeEstimate,
183
183
  fees: {
184
+ isSourceGasFeeToken,
184
185
  provider,
185
186
  sourceNetwork,
186
187
  targetNetwork,
@@ -260,11 +261,13 @@ function getFeatureFlags(messenger) {
260
261
  *
261
262
  * @param quote - Relay quote.
262
263
  * @param messenger - Controller messenger.
264
+ * @param request - Quote request.
263
265
  * @returns Total source network cost in USD and fiat.
264
266
  */
265
- function calculateSourceNetworkCost(quote, messenger) {
267
+ async function calculateSourceNetworkCost(quote, messenger, request) {
268
+ const { from, sourceChainId, sourceTokenAddress } = request;
266
269
  const allParams = quote.steps.flatMap((s) => s.items).map((i) => i.data);
267
- const { chainId } = allParams[0];
270
+ const { chainId, data, to, value } = allParams[0];
268
271
  const totalGasLimit = calculateSourceNetworkGasLimit(allParams);
269
272
  const estimate = (0, gas_1.calculateGasCost)({
270
273
  chainId,
@@ -277,7 +280,58 @@ function calculateSourceNetworkCost(quote, messenger) {
277
280
  messenger,
278
281
  isMax: true,
279
282
  });
280
- return { estimate, max };
283
+ const nativeBalance = (0, token_1.getTokenBalance)(messenger, from, sourceChainId, (0, token_1.getNativeToken)(sourceChainId));
284
+ if (new bignumber_js_1.BigNumber(nativeBalance).isGreaterThanOrEqualTo(max.raw)) {
285
+ return { estimate, max };
286
+ }
287
+ log('Checking gas fee tokens as insufficient native balance', {
288
+ nativeBalance,
289
+ max: max.raw,
290
+ });
291
+ const gasFeeTokens = await messenger.call('TransactionController:getGasFeeTokens', {
292
+ chainId: sourceChainId,
293
+ data,
294
+ from,
295
+ to,
296
+ value: (0, controller_utils_1.toHex)(value ?? '0'),
297
+ });
298
+ log('Source gas fee tokens', { gasFeeTokens });
299
+ const gasFeeToken = gasFeeTokens.find((t) => t.tokenAddress.toLowerCase() === sourceTokenAddress.toLowerCase());
300
+ if (!gasFeeToken) {
301
+ log('No matching gas fee token found', {
302
+ sourceTokenAddress,
303
+ gasFeeTokens,
304
+ });
305
+ return { estimate, max };
306
+ }
307
+ let finalAmount = gasFeeToken.amount;
308
+ if (allParams.length > 1) {
309
+ const gasRate = new bignumber_js_1.BigNumber(gasFeeToken.amount, 16).dividedBy(gasFeeToken.gas, 16);
310
+ const finalAmountValue = gasRate.multipliedBy(totalGasLimit);
311
+ finalAmount = (0, controller_utils_1.toHex)(finalAmountValue.toFixed(0));
312
+ log('Estimated gas fee token amount for batch', {
313
+ finalAmount: finalAmountValue.toString(10),
314
+ gasRate: gasRate.toString(10),
315
+ totalGasLimit,
316
+ });
317
+ }
318
+ const finalGasFeeToken = { ...gasFeeToken, amount: finalAmount };
319
+ const gasFeeTokenCost = (0, gas_1.calculateGasFeeTokenCost)({
320
+ chainId: sourceChainId,
321
+ gasFeeToken: finalGasFeeToken,
322
+ messenger,
323
+ });
324
+ if (!gasFeeTokenCost) {
325
+ return { estimate, max };
326
+ }
327
+ log('Using gas fee token for source network', {
328
+ gasFeeTokenCost,
329
+ });
330
+ return {
331
+ isGasFeeToken: true,
332
+ estimate: gasFeeTokenCost,
333
+ max: gasFeeTokenCost,
334
+ };
281
335
  }
282
336
  /**
283
337
  * Calculate the total gas limit for the source network transactions.
@@ -1 +1 @@
1
- {"version":3,"file":"relay-quotes.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { successfulFetch } from '@metamask/controller-utils';\nimport type { Json } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n CHAIN_ID_HYPERCORE,\n RELAY_FALLBACK_GAS_LIMIT,\n RELAY_URL_QUOTE,\n} from './constants';\nimport type { RelayQuote } from './types';\nimport { TransactionPayStrategy } from '../..';\nimport type { TransactionMeta } from '../../../../transaction-controller/src';\nimport {\n ARBITRUM_USDC_ADDRESS,\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n} from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n Amount,\n FiatValue,\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { calculateGasCost } from '../../utils/gas';\nimport { getNativeToken, getTokenFiatRate } from '../../utils/token';\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n/**\n * Fetches Relay quotes.\n *\n * @param request - Request object.\n * @returns Array of quotes.\n */\nexport async function getRelayQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>[]> {\n const { requests } = request;\n\n log('Fetching quotes', requests);\n\n try {\n const normalizedRequests = requests\n // Ignore gas fee token requests\n .filter((r) => r.targetAmountMinimum !== '0')\n .map((r) => normalizeRequest(r));\n\n log('Normalized requests', normalizedRequests);\n\n return await Promise.all(\n normalizedRequests.map((r) => getSingleQuote(r, request)),\n );\n } catch (error) {\n log('Error fetching quotes', { error });\n throw new Error(`Failed to fetch Relay quotes: ${String(error)}`);\n }\n}\n\n/**\n * Fetches a single Relay quote.\n *\n * @param request - Quote request.\n * @param fullRequest - Full quotes request.\n * @returns Single quote.\n */\nasync function getSingleQuote(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger, transaction } = fullRequest;\n\n try {\n const body = {\n amount: request.targetAmountMinimum,\n destinationChainId: Number(request.targetChainId),\n destinationCurrency: request.targetTokenAddress,\n originChainId: Number(request.sourceChainId),\n originCurrency: request.sourceTokenAddress,\n recipient: request.from,\n tradeType: 'EXPECTED_OUTPUT',\n user: request.from,\n };\n\n await processTransactions(transaction, request, body, messenger);\n\n const url = getFeatureFlags(messenger).relayQuoteUrl;\n\n log('Request body', { body, url });\n\n const response = await successfulFetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const quote = (await response.json()) as RelayQuote;\n\n log('Fetched relay quote', quote);\n\n return normalizeQuote(quote, request, fullRequest);\n } catch (e) {\n log('Error fetching relay quote', e);\n throw e;\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: Record<string, Json | undefined>,\n messenger: TransactionPayControllerMessenger,\n) {\n const { data, value } = transaction.txParams;\n\n /* istanbul ignore next */\n const hasNoParams = (!data || data === '0x') && (!value || value === '0x0');\n\n const skipDelegation =\n hasNoParams || request.targetChainId === CHAIN_ID_HYPERCORE;\n\n if (skipDelegation) {\n log('Skipping delegation as no transaction data');\n return;\n }\n\n const delegation = await messenger.call(\n 'TransactionPayController:getDelegationTransaction',\n { transaction },\n );\n\n const normalizedAuthorizationList = delegation.authorizationList?.map(\n (a) => ({\n ...a,\n chainId: Number(a.chainId),\n nonce: Number(a.nonce),\n yParity: Number(a.yParity),\n }),\n );\n\n const tokenTransferData = new Interface([\n 'function transfer(address to, uint256 amount)',\n ]).encodeFunctionData('transfer', [\n request.from,\n request.targetAmountMinimum,\n ]);\n\n requestBody.authorizationList = normalizedAuthorizationList;\n requestBody.tradeType = 'EXACT_OUTPUT';\n\n requestBody.txs = [\n {\n to: request.targetTokenAddress,\n data: tokenTransferData,\n value: '0x0',\n },\n {\n to: delegation.to,\n data: delegation.data,\n value: delegation.value,\n },\n ];\n}\n\n/**\n * Normalizes requests for Relay.\n *\n * @param request - Quote request to normalize.\n * @returns Normalized request.\n */\nfunction normalizeRequest(request: QuoteRequest) {\n const isHyperliquidDeposit =\n request.targetChainId === CHAIN_ID_ARBITRUM &&\n request.targetTokenAddress.toLowerCase() ===\n ARBITRUM_USDC_ADDRESS.toLowerCase();\n\n const isPolygonNativeSource =\n request.sourceChainId === CHAIN_ID_POLYGON &&\n request.sourceTokenAddress === getNativeToken(request.sourceChainId);\n\n const requestOutput: QuoteRequest = {\n ...request,\n sourceTokenAddress: isPolygonNativeSource\n ? NATIVE_TOKEN_ADDRESS\n : request.sourceTokenAddress,\n targetChainId: isHyperliquidDeposit\n ? CHAIN_ID_HYPERCORE\n : request.targetChainId,\n targetTokenAddress: isHyperliquidDeposit\n ? '0x00000000000000000000000000000000'\n : request.targetTokenAddress,\n targetAmountMinimum: isHyperliquidDeposit\n ? new BigNumber(request.targetAmountMinimum).shiftedBy(2).toString(10)\n : request.targetAmountMinimum,\n };\n\n if (isHyperliquidDeposit) {\n log('Converting Arbitrum Hyperliquid deposit to direct deposit', {\n originalRequest: request,\n normalizedRequest: requestOutput,\n });\n }\n\n return requestOutput;\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 */\nfunction normalizeQuote(\n quote: RelayQuote,\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): TransactionPayQuote<RelayQuote> {\n const { messenger } = fullRequest;\n const { details } = quote;\n const { currencyIn } = details;\n\n const { usdToFiatRate } = getFiatRates(messenger, request);\n\n const dust = getFiatValueFromUsd(\n calculateDustUsd(quote, request),\n usdToFiatRate,\n );\n\n const provider = getFiatValueFromUsd(\n calculateProviderFee(quote),\n usdToFiatRate,\n );\n\n const sourceNetwork = calculateSourceNetworkCost(quote, messenger);\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 return {\n dust,\n estimatedDuration: details.timeEstimate,\n fees: {\n provider,\n sourceNetwork,\n targetNetwork,\n },\n original: quote,\n request,\n sourceAmount,\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) {\n const { currencyOut } = quote.details;\n const { amountUsd, amountFormatted, minimumAmount } = currencyOut;\n const { decimals: targetDecimals } = currencyOut.currency;\n\n const targetUsdRate = new BigNumber(amountUsd).dividedBy(amountFormatted);\n\n const dustRaw = new BigNumber(minimumAmount).minus(\n request.targetAmountMinimum,\n );\n\n return dustRaw.shiftedBy(-targetDecimals).multipliedBy(targetUsdRate);\n}\n\n/**\n * Converts USD value to fiat value.\n *\n * @param usdValue - USD value.\n * @param usdToFiatRate - USD to fiat rate.\n * @returns Fiat value.\n */\nfunction getFiatValueFromUsd(\n usdValue: BigNumber,\n usdToFiatRate: BigNumber,\n): FiatValue {\n const fiatValue = usdValue.multipliedBy(usdToFiatRate);\n\n return {\n usd: usdValue.toString(10),\n fiat: fiatValue.toString(10),\n };\n}\n\n/**\n * Calculates USD to fiat rate.\n *\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @returns USD to fiat rate.\n */\nfunction getFiatRates(\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n) {\n const { sourceChainId, sourceTokenAddress } = request;\n\n const finalSourceTokenAddress =\n sourceChainId === CHAIN_ID_POLYGON &&\n sourceTokenAddress === NATIVE_TOKEN_ADDRESS\n ? getNativeToken(sourceChainId)\n : sourceTokenAddress;\n\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n finalSourceTokenAddress,\n sourceChainId,\n );\n\n if (!sourceFiatRate) {\n throw new Error('Source token fiat rate not found');\n }\n\n const usdToFiatRate = new BigNumber(sourceFiatRate.fiatRate).dividedBy(\n sourceFiatRate.usdRate,\n );\n\n return { sourceFiatRate, usdToFiatRate };\n}\n\n/**\n * Gets feature flags for Relay quotes.\n *\n * @param messenger - Controller messenger.\n * @returns Feature flags.\n */\nfunction getFeatureFlags(messenger: TransactionPayControllerMessenger) {\n const featureFlagState = messenger.call(\n 'RemoteFeatureFlagController:getState',\n );\n\n const featureFlags = featureFlagState.remoteFeatureFlags\n ?.confirmations_pay as Record<string, string> | undefined;\n\n const relayQuoteUrl = featureFlags?.relayQuoteUrl ?? RELAY_URL_QUOTE;\n\n return {\n relayQuoteUrl,\n };\n}\n\n/**\n * Calculates source network cost from a Relay quote.\n *\n * @param quote - Relay quote.\n * @param messenger - Controller messenger.\n * @returns Total source network cost in USD and fiat.\n */\nfunction calculateSourceNetworkCost(\n quote: RelayQuote,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayQuote<RelayQuote>['fees']['sourceNetwork'] {\n const allParams = quote.steps.flatMap((s) => s.items).map((i) => i.data);\n const { chainId } = allParams[0];\n const totalGasLimit = calculateSourceNetworkGasLimit(allParams);\n\n const estimate = calculateGasCost({\n chainId,\n gas: totalGasLimit,\n messenger,\n });\n\n const max = calculateGasCost({\n chainId,\n gas: totalGasLimit,\n messenger,\n isMax: true,\n });\n\n return { estimate, max };\n}\n\n/**\n * Calculate the total gas limit for the source network transactions.\n *\n * @param params - Array of transaction parameters.\n * @returns - Total gas limit.\n */\nfunction calculateSourceNetworkGasLimit(\n params: RelayQuote['steps'][0]['items'][0]['data'][],\n): number {\n const allParamsHasGas = params.every((p) => p.gas !== undefined);\n\n if (allParamsHasGas) {\n return params.reduce(\n (total, p) => total + new BigNumber(p.gas as string).toNumber(),\n 0,\n );\n }\n\n // In future, call `TransactionController:estimateGas`\n // or `TransactionController:estimateGasBatch` based on params length.\n\n return params.reduce(\n (total, p) =>\n total + new BigNumber(p.gas ?? RELAY_FALLBACK_GAS_LIMIT).toNumber(),\n 0,\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) {\n const relayerFee = new BigNumber(quote.fees.relayer.amountUsd);\n\n const valueLoss = new BigNumber(quote.details.currencyIn.amountUsd).minus(\n quote.details.currencyOut.amountUsd,\n );\n\n return relayerFee.gt(valueLoss) ? relayerFee : valueLoss;\n}\n"]}
1
+ {"version":3,"file":"relay-quotes.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { successfulFetch, toHex } from '@metamask/controller-utils';\nimport type { Json } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n CHAIN_ID_HYPERCORE,\n RELAY_FALLBACK_GAS_LIMIT,\n RELAY_URL_QUOTE,\n} from './constants';\nimport type { RelayQuote } from './types';\nimport { TransactionPayStrategy } from '../..';\nimport type { TransactionMeta } from '../../../../transaction-controller/src';\nimport {\n ARBITRUM_USDC_ADDRESS,\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n} from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n Amount,\n FiatValue,\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { calculateGasCost, calculateGasFeeTokenCost } from '../../utils/gas';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n} from '../../utils/token';\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n/**\n * Fetches Relay quotes.\n *\n * @param request - Request object.\n * @returns Array of quotes.\n */\nexport async function getRelayQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>[]> {\n const { requests } = request;\n\n log('Fetching quotes', requests);\n\n try {\n const normalizedRequests = requests\n // Ignore gas fee token requests\n .filter((r) => r.targetAmountMinimum !== '0')\n .map((r) => normalizeRequest(r));\n\n log('Normalized requests', normalizedRequests);\n\n return await Promise.all(\n normalizedRequests.map((r) => getSingleQuote(r, request)),\n );\n } catch (error) {\n log('Error fetching quotes', { error });\n throw new Error(`Failed to fetch Relay quotes: ${String(error)}`);\n }\n}\n\n/**\n * Fetches a single Relay quote.\n *\n * @param request - Quote request.\n * @param fullRequest - Full quotes request.\n * @returns Single quote.\n */\nasync function getSingleQuote(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger, transaction } = fullRequest;\n\n try {\n const body = {\n amount: request.targetAmountMinimum,\n destinationChainId: Number(request.targetChainId),\n destinationCurrency: request.targetTokenAddress,\n originChainId: Number(request.sourceChainId),\n originCurrency: request.sourceTokenAddress,\n recipient: request.from,\n tradeType: 'EXPECTED_OUTPUT',\n user: request.from,\n };\n\n await processTransactions(transaction, request, body, messenger);\n\n const url = getFeatureFlags(messenger).relayQuoteUrl;\n\n log('Request body', { body, url });\n\n const response = await successfulFetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const quote = (await response.json()) as RelayQuote;\n\n log('Fetched relay quote', quote);\n\n return normalizeQuote(quote, request, fullRequest);\n } catch (e) {\n log('Error fetching relay quote', e);\n throw e;\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: Record<string, Json | undefined>,\n messenger: TransactionPayControllerMessenger,\n) {\n const { data, value } = transaction.txParams;\n\n /* istanbul ignore next */\n const hasNoParams = (!data || data === '0x') && (!value || value === '0x0');\n\n const skipDelegation =\n hasNoParams || request.targetChainId === CHAIN_ID_HYPERCORE;\n\n if (skipDelegation) {\n log('Skipping delegation as no transaction data');\n return;\n }\n\n const delegation = await messenger.call(\n 'TransactionPayController:getDelegationTransaction',\n { transaction },\n );\n\n const normalizedAuthorizationList = delegation.authorizationList?.map(\n (a) => ({\n ...a,\n chainId: Number(a.chainId),\n nonce: Number(a.nonce),\n yParity: Number(a.yParity),\n }),\n );\n\n const tokenTransferData = new Interface([\n 'function transfer(address to, uint256 amount)',\n ]).encodeFunctionData('transfer', [\n request.from,\n request.targetAmountMinimum,\n ]);\n\n requestBody.authorizationList = normalizedAuthorizationList;\n requestBody.tradeType = 'EXACT_OUTPUT';\n\n requestBody.txs = [\n {\n to: request.targetTokenAddress,\n data: tokenTransferData,\n value: '0x0',\n },\n {\n to: delegation.to,\n data: delegation.data,\n value: delegation.value,\n },\n ];\n}\n\n/**\n * Normalizes requests for Relay.\n *\n * @param request - Quote request to normalize.\n * @returns Normalized request.\n */\nfunction normalizeRequest(request: QuoteRequest) {\n const isHyperliquidDeposit =\n request.targetChainId === CHAIN_ID_ARBITRUM &&\n request.targetTokenAddress.toLowerCase() ===\n ARBITRUM_USDC_ADDRESS.toLowerCase();\n\n const isPolygonNativeSource =\n request.sourceChainId === CHAIN_ID_POLYGON &&\n request.sourceTokenAddress === getNativeToken(request.sourceChainId);\n\n const requestOutput: QuoteRequest = {\n ...request,\n sourceTokenAddress: isPolygonNativeSource\n ? NATIVE_TOKEN_ADDRESS\n : request.sourceTokenAddress,\n targetChainId: isHyperliquidDeposit\n ? CHAIN_ID_HYPERCORE\n : request.targetChainId,\n targetTokenAddress: isHyperliquidDeposit\n ? '0x00000000000000000000000000000000'\n : request.targetTokenAddress,\n targetAmountMinimum: isHyperliquidDeposit\n ? new BigNumber(request.targetAmountMinimum).shiftedBy(2).toString(10)\n : request.targetAmountMinimum,\n };\n\n if (isHyperliquidDeposit) {\n log('Converting Arbitrum Hyperliquid deposit to direct deposit', {\n originalRequest: request,\n normalizedRequest: requestOutput,\n });\n }\n\n return requestOutput;\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 } = details;\n\n const { usdToFiatRate } = getFiatRates(messenger, request);\n\n const dust = getFiatValueFromUsd(\n calculateDustUsd(quote, request),\n usdToFiatRate,\n );\n\n const provider = getFiatValueFromUsd(\n calculateProviderFee(quote),\n usdToFiatRate,\n );\n\n const { isGasFeeToken: isSourceGasFeeToken, ...sourceNetwork } =\n await calculateSourceNetworkCost(quote, messenger, request);\n\n const targetNetwork = {\n usd: '0',\n fiat: '0',\n };\n\n const sourceAmount: Amount = {\n human: currencyIn.amountFormatted,\n raw: currencyIn.amount,\n ...getFiatValueFromUsd(new BigNumber(currencyIn.amountUsd), usdToFiatRate),\n };\n\n return {\n dust,\n estimatedDuration: details.timeEstimate,\n fees: {\n isSourceGasFeeToken,\n provider,\n sourceNetwork,\n targetNetwork,\n },\n original: quote,\n request,\n sourceAmount,\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) {\n const { currencyOut } = quote.details;\n const { amountUsd, amountFormatted, minimumAmount } = currencyOut;\n const { decimals: targetDecimals } = currencyOut.currency;\n\n const targetUsdRate = new BigNumber(amountUsd).dividedBy(amountFormatted);\n\n const dustRaw = new BigNumber(minimumAmount).minus(\n request.targetAmountMinimum,\n );\n\n return dustRaw.shiftedBy(-targetDecimals).multipliedBy(targetUsdRate);\n}\n\n/**\n * Converts USD value to fiat value.\n *\n * @param usdValue - USD value.\n * @param usdToFiatRate - USD to fiat rate.\n * @returns Fiat value.\n */\nfunction getFiatValueFromUsd(\n usdValue: BigNumber,\n usdToFiatRate: BigNumber,\n): FiatValue {\n const fiatValue = usdValue.multipliedBy(usdToFiatRate);\n\n return {\n usd: usdValue.toString(10),\n fiat: fiatValue.toString(10),\n };\n}\n\n/**\n * Calculates USD to fiat rate.\n *\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @returns USD to fiat rate.\n */\nfunction getFiatRates(\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n) {\n const { sourceChainId, sourceTokenAddress } = request;\n\n const finalSourceTokenAddress =\n sourceChainId === CHAIN_ID_POLYGON &&\n sourceTokenAddress === NATIVE_TOKEN_ADDRESS\n ? getNativeToken(sourceChainId)\n : sourceTokenAddress;\n\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n finalSourceTokenAddress,\n sourceChainId,\n );\n\n if (!sourceFiatRate) {\n throw new Error('Source token fiat rate not found');\n }\n\n const usdToFiatRate = new BigNumber(sourceFiatRate.fiatRate).dividedBy(\n sourceFiatRate.usdRate,\n );\n\n return { sourceFiatRate, usdToFiatRate };\n}\n\n/**\n * Gets feature flags for Relay quotes.\n *\n * @param messenger - Controller messenger.\n * @returns Feature flags.\n */\nfunction getFeatureFlags(messenger: TransactionPayControllerMessenger) {\n const featureFlagState = messenger.call(\n 'RemoteFeatureFlagController:getState',\n );\n\n const featureFlags = featureFlagState.remoteFeatureFlags\n ?.confirmations_pay as Record<string, string> | undefined;\n\n const relayQuoteUrl = featureFlags?.relayQuoteUrl ?? RELAY_URL_QUOTE;\n\n return {\n relayQuoteUrl,\n };\n}\n\n/**\n * Calculates source network cost from a Relay quote.\n *\n * @param quote - Relay quote.\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @returns Total source network cost in USD and fiat.\n */\nasync function calculateSourceNetworkCost(\n quote: RelayQuote,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): Promise<\n TransactionPayQuote<RelayQuote>['fees']['sourceNetwork'] & {\n isGasFeeToken?: boolean;\n }\n> {\n const { from, sourceChainId, sourceTokenAddress } = request;\n const allParams = quote.steps.flatMap((s) => s.items).map((i) => i.data);\n const { chainId, data, to, value } = allParams[0];\n const totalGasLimit = calculateSourceNetworkGasLimit(allParams);\n\n const estimate = calculateGasCost({\n chainId,\n gas: totalGasLimit,\n messenger,\n });\n\n const max = calculateGasCost({\n chainId,\n gas: totalGasLimit,\n messenger,\n isMax: true,\n });\n\n const nativeBalance = getTokenBalance(\n messenger,\n from,\n sourceChainId,\n getNativeToken(sourceChainId),\n );\n\n if (new BigNumber(nativeBalance).isGreaterThanOrEqualTo(max.raw)) {\n return { estimate, max };\n }\n\n log('Checking gas fee tokens as insufficient native balance', {\n nativeBalance,\n max: max.raw,\n });\n\n const gasFeeTokens = await messenger.call(\n 'TransactionController:getGasFeeTokens',\n {\n chainId: sourceChainId,\n data,\n from,\n to,\n value: toHex(value ?? '0'),\n },\n );\n\n log('Source gas fee tokens', { gasFeeTokens });\n\n const gasFeeToken = gasFeeTokens.find(\n (t) => t.tokenAddress.toLowerCase() === sourceTokenAddress.toLowerCase(),\n );\n\n if (!gasFeeToken) {\n log('No matching gas fee token found', {\n sourceTokenAddress,\n gasFeeTokens,\n });\n\n return { estimate, max };\n }\n\n let finalAmount = gasFeeToken.amount;\n\n if (allParams.length > 1) {\n const gasRate = new BigNumber(gasFeeToken.amount, 16).dividedBy(\n gasFeeToken.gas,\n 16,\n );\n\n const finalAmountValue = gasRate.multipliedBy(totalGasLimit);\n\n finalAmount = toHex(finalAmountValue.toFixed(0));\n\n log('Estimated gas fee token amount for batch', {\n finalAmount: finalAmountValue.toString(10),\n gasRate: gasRate.toString(10),\n totalGasLimit,\n });\n }\n\n const finalGasFeeToken = { ...gasFeeToken, amount: finalAmount };\n\n const gasFeeTokenCost = calculateGasFeeTokenCost({\n chainId: sourceChainId,\n gasFeeToken: finalGasFeeToken,\n messenger,\n });\n\n if (!gasFeeTokenCost) {\n return { estimate, max };\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 };\n}\n\n/**\n * Calculate the total gas limit for the source network transactions.\n *\n * @param params - Array of transaction parameters.\n * @returns - Total gas limit.\n */\nfunction calculateSourceNetworkGasLimit(\n params: RelayQuote['steps'][0]['items'][0]['data'][],\n): number {\n const allParamsHasGas = params.every((p) => p.gas !== undefined);\n\n if (allParamsHasGas) {\n return params.reduce(\n (total, p) => total + new BigNumber(p.gas as string).toNumber(),\n 0,\n );\n }\n\n // In future, call `TransactionController:estimateGas`\n // or `TransactionController:estimateGasBatch` based on params length.\n\n return params.reduce(\n (total, p) =>\n total + new BigNumber(p.gas ?? RELAY_FALLBACK_GAS_LIMIT).toNumber(),\n 0,\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) {\n const relayerFee = new BigNumber(quote.fees.relayer.amountUsd);\n\n const valueLoss = new BigNumber(quote.details.currencyIn.amountUsd).minus(\n quote.details.currencyOut.amountUsd,\n );\n\n return relayerFee.gt(valueLoss) ? relayerFee : valueLoss;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"relay-quotes.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAgB;AAU1C,OAAO,KAAK,EAGV,2BAA2B,EAG3B,mBAAmB,EACpB,wBAAoB;AAMrB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CAoB5C"}
1
+ {"version":3,"file":"relay-quotes.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAgB;AAU1C,OAAO,KAAK,EAGV,2BAA2B,EAG3B,mBAAmB,EACpB,wBAAoB;AAUrB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CAoB5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"relay-quotes.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAgB;AAU1C,OAAO,KAAK,EAGV,2BAA2B,EAG3B,mBAAmB,EACpB,wBAAoB;AAMrB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CAoB5C"}
1
+ {"version":3,"file":"relay-quotes.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAgB;AAU1C,OAAO,KAAK,EAGV,2BAA2B,EAG3B,mBAAmB,EACpB,wBAAoB;AAUrB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CAoB5C"}
@@ -1,13 +1,13 @@
1
1
  import { Interface } from "@ethersproject/abi";
2
- import { successfulFetch } from "@metamask/controller-utils";
2
+ import { successfulFetch, toHex } from "@metamask/controller-utils";
3
3
  import { createModuleLogger } from "@metamask/utils";
4
4
  import { BigNumber } from "bignumber.js";
5
5
  import { CHAIN_ID_HYPERCORE, RELAY_FALLBACK_GAS_LIMIT, RELAY_URL_QUOTE } from "./constants.mjs";
6
6
  import { TransactionPayStrategy } from "../../index.mjs";
7
7
  import { ARBITRUM_USDC_ADDRESS, CHAIN_ID_ARBITRUM, CHAIN_ID_POLYGON, NATIVE_TOKEN_ADDRESS } from "../../constants.mjs";
8
8
  import { projectLogger } from "../../logger.mjs";
9
- import { calculateGasCost } from "../../utils/gas.mjs";
10
- import { getNativeToken, getTokenFiatRate } from "../../utils/token.mjs";
9
+ import { calculateGasCost, calculateGasFeeTokenCost } from "../../utils/gas.mjs";
10
+ import { getNativeToken, getTokenBalance, getTokenFiatRate } from "../../utils/token.mjs";
11
11
  const log = createModuleLogger(projectLogger, 'relay-strategy');
12
12
  /**
13
13
  * Fetches Relay quotes.
@@ -156,14 +156,14 @@ function normalizeRequest(request) {
156
156
  * @param fullRequest - Full quotes request.
157
157
  * @returns Normalized quote.
158
158
  */
159
- function normalizeQuote(quote, request, fullRequest) {
159
+ async function normalizeQuote(quote, request, fullRequest) {
160
160
  const { messenger } = fullRequest;
161
161
  const { details } = quote;
162
162
  const { currencyIn } = details;
163
163
  const { usdToFiatRate } = getFiatRates(messenger, request);
164
164
  const dust = getFiatValueFromUsd(calculateDustUsd(quote, request), usdToFiatRate);
165
165
  const provider = getFiatValueFromUsd(calculateProviderFee(quote), usdToFiatRate);
166
- const sourceNetwork = calculateSourceNetworkCost(quote, messenger);
166
+ const { isGasFeeToken: isSourceGasFeeToken, ...sourceNetwork } = await calculateSourceNetworkCost(quote, messenger, request);
167
167
  const targetNetwork = {
168
168
  usd: '0',
169
169
  fiat: '0',
@@ -177,6 +177,7 @@ function normalizeQuote(quote, request, fullRequest) {
177
177
  dust,
178
178
  estimatedDuration: details.timeEstimate,
179
179
  fees: {
180
+ isSourceGasFeeToken,
180
181
  provider,
181
182
  sourceNetwork,
182
183
  targetNetwork,
@@ -256,11 +257,13 @@ function getFeatureFlags(messenger) {
256
257
  *
257
258
  * @param quote - Relay quote.
258
259
  * @param messenger - Controller messenger.
260
+ * @param request - Quote request.
259
261
  * @returns Total source network cost in USD and fiat.
260
262
  */
261
- function calculateSourceNetworkCost(quote, messenger) {
263
+ async function calculateSourceNetworkCost(quote, messenger, request) {
264
+ const { from, sourceChainId, sourceTokenAddress } = request;
262
265
  const allParams = quote.steps.flatMap((s) => s.items).map((i) => i.data);
263
- const { chainId } = allParams[0];
266
+ const { chainId, data, to, value } = allParams[0];
264
267
  const totalGasLimit = calculateSourceNetworkGasLimit(allParams);
265
268
  const estimate = calculateGasCost({
266
269
  chainId,
@@ -273,7 +276,58 @@ function calculateSourceNetworkCost(quote, messenger) {
273
276
  messenger,
274
277
  isMax: true,
275
278
  });
276
- return { estimate, max };
279
+ const nativeBalance = getTokenBalance(messenger, from, sourceChainId, getNativeToken(sourceChainId));
280
+ if (new BigNumber(nativeBalance).isGreaterThanOrEqualTo(max.raw)) {
281
+ return { estimate, max };
282
+ }
283
+ log('Checking gas fee tokens as insufficient native balance', {
284
+ nativeBalance,
285
+ max: max.raw,
286
+ });
287
+ const gasFeeTokens = await messenger.call('TransactionController:getGasFeeTokens', {
288
+ chainId: sourceChainId,
289
+ data,
290
+ from,
291
+ to,
292
+ value: toHex(value ?? '0'),
293
+ });
294
+ log('Source gas fee tokens', { gasFeeTokens });
295
+ const gasFeeToken = gasFeeTokens.find((t) => t.tokenAddress.toLowerCase() === sourceTokenAddress.toLowerCase());
296
+ if (!gasFeeToken) {
297
+ log('No matching gas fee token found', {
298
+ sourceTokenAddress,
299
+ gasFeeTokens,
300
+ });
301
+ return { estimate, max };
302
+ }
303
+ let finalAmount = gasFeeToken.amount;
304
+ if (allParams.length > 1) {
305
+ const gasRate = new BigNumber(gasFeeToken.amount, 16).dividedBy(gasFeeToken.gas, 16);
306
+ const finalAmountValue = gasRate.multipliedBy(totalGasLimit);
307
+ finalAmount = toHex(finalAmountValue.toFixed(0));
308
+ log('Estimated gas fee token amount for batch', {
309
+ finalAmount: finalAmountValue.toString(10),
310
+ gasRate: gasRate.toString(10),
311
+ totalGasLimit,
312
+ });
313
+ }
314
+ const finalGasFeeToken = { ...gasFeeToken, amount: finalAmount };
315
+ const gasFeeTokenCost = calculateGasFeeTokenCost({
316
+ chainId: sourceChainId,
317
+ gasFeeToken: finalGasFeeToken,
318
+ messenger,
319
+ });
320
+ if (!gasFeeTokenCost) {
321
+ return { estimate, max };
322
+ }
323
+ log('Using gas fee token for source network', {
324
+ gasFeeTokenCost,
325
+ });
326
+ return {
327
+ isGasFeeToken: true,
328
+ estimate: gasFeeTokenCost,
329
+ max: gasFeeTokenCost,
330
+ };
277
331
  }
278
332
  /**
279
333
  * Calculate the total gas limit for the source network transactions.
@@ -1 +1 @@
1
- {"version":3,"file":"relay-quotes.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { successfulFetch } from '@metamask/controller-utils';\nimport type { Json } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n CHAIN_ID_HYPERCORE,\n RELAY_FALLBACK_GAS_LIMIT,\n RELAY_URL_QUOTE,\n} from './constants';\nimport type { RelayQuote } from './types';\nimport { TransactionPayStrategy } from '../..';\nimport type { TransactionMeta } from '../../../../transaction-controller/src';\nimport {\n ARBITRUM_USDC_ADDRESS,\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n} from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n Amount,\n FiatValue,\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { calculateGasCost } from '../../utils/gas';\nimport { getNativeToken, getTokenFiatRate } from '../../utils/token';\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n/**\n * Fetches Relay quotes.\n *\n * @param request - Request object.\n * @returns Array of quotes.\n */\nexport async function getRelayQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>[]> {\n const { requests } = request;\n\n log('Fetching quotes', requests);\n\n try {\n const normalizedRequests = requests\n // Ignore gas fee token requests\n .filter((r) => r.targetAmountMinimum !== '0')\n .map((r) => normalizeRequest(r));\n\n log('Normalized requests', normalizedRequests);\n\n return await Promise.all(\n normalizedRequests.map((r) => getSingleQuote(r, request)),\n );\n } catch (error) {\n log('Error fetching quotes', { error });\n throw new Error(`Failed to fetch Relay quotes: ${String(error)}`);\n }\n}\n\n/**\n * Fetches a single Relay quote.\n *\n * @param request - Quote request.\n * @param fullRequest - Full quotes request.\n * @returns Single quote.\n */\nasync function getSingleQuote(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger, transaction } = fullRequest;\n\n try {\n const body = {\n amount: request.targetAmountMinimum,\n destinationChainId: Number(request.targetChainId),\n destinationCurrency: request.targetTokenAddress,\n originChainId: Number(request.sourceChainId),\n originCurrency: request.sourceTokenAddress,\n recipient: request.from,\n tradeType: 'EXPECTED_OUTPUT',\n user: request.from,\n };\n\n await processTransactions(transaction, request, body, messenger);\n\n const url = getFeatureFlags(messenger).relayQuoteUrl;\n\n log('Request body', { body, url });\n\n const response = await successfulFetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const quote = (await response.json()) as RelayQuote;\n\n log('Fetched relay quote', quote);\n\n return normalizeQuote(quote, request, fullRequest);\n } catch (e) {\n log('Error fetching relay quote', e);\n throw e;\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: Record<string, Json | undefined>,\n messenger: TransactionPayControllerMessenger,\n) {\n const { data, value } = transaction.txParams;\n\n /* istanbul ignore next */\n const hasNoParams = (!data || data === '0x') && (!value || value === '0x0');\n\n const skipDelegation =\n hasNoParams || request.targetChainId === CHAIN_ID_HYPERCORE;\n\n if (skipDelegation) {\n log('Skipping delegation as no transaction data');\n return;\n }\n\n const delegation = await messenger.call(\n 'TransactionPayController:getDelegationTransaction',\n { transaction },\n );\n\n const normalizedAuthorizationList = delegation.authorizationList?.map(\n (a) => ({\n ...a,\n chainId: Number(a.chainId),\n nonce: Number(a.nonce),\n yParity: Number(a.yParity),\n }),\n );\n\n const tokenTransferData = new Interface([\n 'function transfer(address to, uint256 amount)',\n ]).encodeFunctionData('transfer', [\n request.from,\n request.targetAmountMinimum,\n ]);\n\n requestBody.authorizationList = normalizedAuthorizationList;\n requestBody.tradeType = 'EXACT_OUTPUT';\n\n requestBody.txs = [\n {\n to: request.targetTokenAddress,\n data: tokenTransferData,\n value: '0x0',\n },\n {\n to: delegation.to,\n data: delegation.data,\n value: delegation.value,\n },\n ];\n}\n\n/**\n * Normalizes requests for Relay.\n *\n * @param request - Quote request to normalize.\n * @returns Normalized request.\n */\nfunction normalizeRequest(request: QuoteRequest) {\n const isHyperliquidDeposit =\n request.targetChainId === CHAIN_ID_ARBITRUM &&\n request.targetTokenAddress.toLowerCase() ===\n ARBITRUM_USDC_ADDRESS.toLowerCase();\n\n const isPolygonNativeSource =\n request.sourceChainId === CHAIN_ID_POLYGON &&\n request.sourceTokenAddress === getNativeToken(request.sourceChainId);\n\n const requestOutput: QuoteRequest = {\n ...request,\n sourceTokenAddress: isPolygonNativeSource\n ? NATIVE_TOKEN_ADDRESS\n : request.sourceTokenAddress,\n targetChainId: isHyperliquidDeposit\n ? CHAIN_ID_HYPERCORE\n : request.targetChainId,\n targetTokenAddress: isHyperliquidDeposit\n ? '0x00000000000000000000000000000000'\n : request.targetTokenAddress,\n targetAmountMinimum: isHyperliquidDeposit\n ? new BigNumber(request.targetAmountMinimum).shiftedBy(2).toString(10)\n : request.targetAmountMinimum,\n };\n\n if (isHyperliquidDeposit) {\n log('Converting Arbitrum Hyperliquid deposit to direct deposit', {\n originalRequest: request,\n normalizedRequest: requestOutput,\n });\n }\n\n return requestOutput;\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 */\nfunction normalizeQuote(\n quote: RelayQuote,\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): TransactionPayQuote<RelayQuote> {\n const { messenger } = fullRequest;\n const { details } = quote;\n const { currencyIn } = details;\n\n const { usdToFiatRate } = getFiatRates(messenger, request);\n\n const dust = getFiatValueFromUsd(\n calculateDustUsd(quote, request),\n usdToFiatRate,\n );\n\n const provider = getFiatValueFromUsd(\n calculateProviderFee(quote),\n usdToFiatRate,\n );\n\n const sourceNetwork = calculateSourceNetworkCost(quote, messenger);\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 return {\n dust,\n estimatedDuration: details.timeEstimate,\n fees: {\n provider,\n sourceNetwork,\n targetNetwork,\n },\n original: quote,\n request,\n sourceAmount,\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) {\n const { currencyOut } = quote.details;\n const { amountUsd, amountFormatted, minimumAmount } = currencyOut;\n const { decimals: targetDecimals } = currencyOut.currency;\n\n const targetUsdRate = new BigNumber(amountUsd).dividedBy(amountFormatted);\n\n const dustRaw = new BigNumber(minimumAmount).minus(\n request.targetAmountMinimum,\n );\n\n return dustRaw.shiftedBy(-targetDecimals).multipliedBy(targetUsdRate);\n}\n\n/**\n * Converts USD value to fiat value.\n *\n * @param usdValue - USD value.\n * @param usdToFiatRate - USD to fiat rate.\n * @returns Fiat value.\n */\nfunction getFiatValueFromUsd(\n usdValue: BigNumber,\n usdToFiatRate: BigNumber,\n): FiatValue {\n const fiatValue = usdValue.multipliedBy(usdToFiatRate);\n\n return {\n usd: usdValue.toString(10),\n fiat: fiatValue.toString(10),\n };\n}\n\n/**\n * Calculates USD to fiat rate.\n *\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @returns USD to fiat rate.\n */\nfunction getFiatRates(\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n) {\n const { sourceChainId, sourceTokenAddress } = request;\n\n const finalSourceTokenAddress =\n sourceChainId === CHAIN_ID_POLYGON &&\n sourceTokenAddress === NATIVE_TOKEN_ADDRESS\n ? getNativeToken(sourceChainId)\n : sourceTokenAddress;\n\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n finalSourceTokenAddress,\n sourceChainId,\n );\n\n if (!sourceFiatRate) {\n throw new Error('Source token fiat rate not found');\n }\n\n const usdToFiatRate = new BigNumber(sourceFiatRate.fiatRate).dividedBy(\n sourceFiatRate.usdRate,\n );\n\n return { sourceFiatRate, usdToFiatRate };\n}\n\n/**\n * Gets feature flags for Relay quotes.\n *\n * @param messenger - Controller messenger.\n * @returns Feature flags.\n */\nfunction getFeatureFlags(messenger: TransactionPayControllerMessenger) {\n const featureFlagState = messenger.call(\n 'RemoteFeatureFlagController:getState',\n );\n\n const featureFlags = featureFlagState.remoteFeatureFlags\n ?.confirmations_pay as Record<string, string> | undefined;\n\n const relayQuoteUrl = featureFlags?.relayQuoteUrl ?? RELAY_URL_QUOTE;\n\n return {\n relayQuoteUrl,\n };\n}\n\n/**\n * Calculates source network cost from a Relay quote.\n *\n * @param quote - Relay quote.\n * @param messenger - Controller messenger.\n * @returns Total source network cost in USD and fiat.\n */\nfunction calculateSourceNetworkCost(\n quote: RelayQuote,\n messenger: TransactionPayControllerMessenger,\n): TransactionPayQuote<RelayQuote>['fees']['sourceNetwork'] {\n const allParams = quote.steps.flatMap((s) => s.items).map((i) => i.data);\n const { chainId } = allParams[0];\n const totalGasLimit = calculateSourceNetworkGasLimit(allParams);\n\n const estimate = calculateGasCost({\n chainId,\n gas: totalGasLimit,\n messenger,\n });\n\n const max = calculateGasCost({\n chainId,\n gas: totalGasLimit,\n messenger,\n isMax: true,\n });\n\n return { estimate, max };\n}\n\n/**\n * Calculate the total gas limit for the source network transactions.\n *\n * @param params - Array of transaction parameters.\n * @returns - Total gas limit.\n */\nfunction calculateSourceNetworkGasLimit(\n params: RelayQuote['steps'][0]['items'][0]['data'][],\n): number {\n const allParamsHasGas = params.every((p) => p.gas !== undefined);\n\n if (allParamsHasGas) {\n return params.reduce(\n (total, p) => total + new BigNumber(p.gas as string).toNumber(),\n 0,\n );\n }\n\n // In future, call `TransactionController:estimateGas`\n // or `TransactionController:estimateGasBatch` based on params length.\n\n return params.reduce(\n (total, p) =>\n total + new BigNumber(p.gas ?? RELAY_FALLBACK_GAS_LIMIT).toNumber(),\n 0,\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) {\n const relayerFee = new BigNumber(quote.fees.relayer.amountUsd);\n\n const valueLoss = new BigNumber(quote.details.currencyIn.amountUsd).minus(\n quote.details.currencyOut.amountUsd,\n );\n\n return relayerFee.gt(valueLoss) ? relayerFee : valueLoss;\n}\n"]}
1
+ {"version":3,"file":"relay-quotes.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,2BAA2B;AAC/C,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,mCAAmC;AAEpE,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AACrD,OAAO,EAAE,SAAS,EAAE,qBAAqB;AAEzC,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,eAAe,EAChB,wBAAoB;AAErB,OAAO,EAAE,sBAAsB,EAAE,wBAAc;AAE/C,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACrB,4BAAwB;AACzB,OAAO,EAAE,aAAa,EAAE,yBAAqB;AAS7C,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,4BAAwB;AAC7E,OAAO,EACL,cAAc,EACd,eAAe,EACf,gBAAgB,EACjB,8BAA0B;AAE3B,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;AAEhE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAoC;IAEpC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAE7B,GAAG,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;IAEjC,IAAI,CAAC;QACH,MAAM,kBAAkB,GAAG,QAAQ;YACjC,gCAAgC;aAC/B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,mBAAmB,KAAK,GAAG,CAAC;aAC5C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;QAEnC,GAAG,CAAC,qBAAqB,EAAE,kBAAkB,CAAC,CAAC;QAE/C,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAC1D,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,uBAAuB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,iCAAiC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,cAAc,CAC3B,OAAqB,EACrB,WAAwC;IAExC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,WAAW,CAAC;IAE/C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG;YACX,MAAM,EAAE,OAAO,CAAC,mBAAmB;YACnC,kBAAkB,EAAE,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC;YACjD,mBAAmB,EAAE,OAAO,CAAC,kBAAkB;YAC/C,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC;YAC5C,cAAc,EAAE,OAAO,CAAC,kBAAkB;YAC1C,SAAS,EAAE,OAAO,CAAC,IAAI;YACvB,SAAS,EAAE,iBAAiB;YAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC;QAEF,MAAM,mBAAmB,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAEjE,MAAM,GAAG,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC;QAErD,GAAG,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAEnC,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE;YAC1C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAe,CAAC;QAEpD,GAAG,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;QAElC,OAAO,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,4BAA4B,EAAE,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,mBAAmB,CAChC,WAA4B,EAC5B,OAAqB,EACrB,WAA6C,EAC7C,SAA4C;IAE5C,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC;IAE7C,0BAA0B;IAC1B,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,KAAK,KAAK,KAAK,CAAC,CAAC;IAE5E,MAAM,cAAc,GAClB,WAAW,IAAI,OAAO,CAAC,aAAa,KAAK,kBAAkB,CAAC;IAE9D,IAAI,cAAc,EAAE,CAAC;QACnB,GAAG,CAAC,4CAA4C,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,IAAI,CACrC,mDAAmD,EACnD,EAAE,WAAW,EAAE,CAChB,CAAC;IAEF,MAAM,2BAA2B,GAAG,UAAU,CAAC,iBAAiB,EAAE,GAAG,CACnE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACN,GAAG,CAAC;QACJ,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QAC1B,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QACtB,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;KAC3B,CAAC,CACH,CAAC;IAEF,MAAM,iBAAiB,GAAG,IAAI,SAAS,CAAC;QACtC,+CAA+C;KAChD,CAAC,CAAC,kBAAkB,CAAC,UAAU,EAAE;QAChC,OAAO,CAAC,IAAI;QACZ,OAAO,CAAC,mBAAmB;KAC5B,CAAC,CAAC;IAEH,WAAW,CAAC,iBAAiB,GAAG,2BAA2B,CAAC;IAC5D,WAAW,CAAC,SAAS,GAAG,cAAc,CAAC;IAEvC,WAAW,CAAC,GAAG,GAAG;QAChB;YACE,EAAE,EAAE,OAAO,CAAC,kBAAkB;YAC9B,IAAI,EAAE,iBAAiB;YACvB,KAAK,EAAE,KAAK;SACb;QACD;YACE,EAAE,EAAE,UAAU,CAAC,EAAE;YACjB,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,KAAK,EAAE,UAAU,CAAC,KAAK;SACxB;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,OAAqB;IAC7C,MAAM,oBAAoB,GACxB,OAAO,CAAC,aAAa,KAAK,iBAAiB;QAC3C,OAAO,CAAC,kBAAkB,CAAC,WAAW,EAAE;YACtC,qBAAqB,CAAC,WAAW,EAAE,CAAC;IAExC,MAAM,qBAAqB,GACzB,OAAO,CAAC,aAAa,KAAK,gBAAgB;QAC1C,OAAO,CAAC,kBAAkB,KAAK,cAAc,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAEvE,MAAM,aAAa,GAAiB;QAClC,GAAG,OAAO;QACV,kBAAkB,EAAE,qBAAqB;YACvC,CAAC,CAAC,oBAAoB;YACtB,CAAC,CAAC,OAAO,CAAC,kBAAkB;QAC9B,aAAa,EAAE,oBAAoB;YACjC,CAAC,CAAC,kBAAkB;YACpB,CAAC,CAAC,OAAO,CAAC,aAAa;QACzB,kBAAkB,EAAE,oBAAoB;YACtC,CAAC,CAAC,oCAAoC;YACtC,CAAC,CAAC,OAAO,CAAC,kBAAkB;QAC9B,mBAAmB,EAAE,oBAAoB;YACvC,CAAC,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtE,CAAC,CAAC,OAAO,CAAC,mBAAmB;KAChC,CAAC;IAEF,IAAI,oBAAoB,EAAE,CAAC;QACzB,GAAG,CAAC,2DAA2D,EAAE;YAC/D,eAAe,EAAE,OAAO;YACxB,iBAAiB,EAAE,aAAa;SACjC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,cAAc,CAC3B,KAAiB,EACjB,OAAqB,EACrB,WAAwC;IAExC,MAAM,EAAE,SAAS,EAAE,GAAG,WAAW,CAAC;IAClC,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAC1B,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAE/B,MAAM,EAAE,aAAa,EAAE,GAAG,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAE3D,MAAM,IAAI,GAAG,mBAAmB,CAC9B,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,EAChC,aAAa,CACd,CAAC;IAEF,MAAM,QAAQ,GAAG,mBAAmB,CAClC,oBAAoB,CAAC,KAAK,CAAC,EAC3B,aAAa,CACd,CAAC;IAEF,MAAM,EAAE,aAAa,EAAE,mBAAmB,EAAE,GAAG,aAAa,EAAE,GAC5D,MAAM,0BAA0B,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAE9D,MAAM,aAAa,GAAG;QACpB,GAAG,EAAE,GAAG;QACR,IAAI,EAAE,GAAG;KACV,CAAC;IAEF,MAAM,YAAY,GAAW;QAC3B,KAAK,EAAE,UAAU,CAAC,eAAe;QACjC,GAAG,EAAE,UAAU,CAAC,MAAM;QACtB,GAAG,mBAAmB,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;KAC3E,CAAC;IAEF,OAAO;QACL,IAAI;QACJ,iBAAiB,EAAE,OAAO,CAAC,YAAY;QACvC,IAAI,EAAE;YACJ,mBAAmB;YACnB,QAAQ;YACR,aAAa;YACb,aAAa;SACd;QACD,QAAQ,EAAE,KAAK;QACf,OAAO;QACP,YAAY;QACZ,QAAQ,EAAE,sBAAsB,CAAC,KAAK;KACvC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,gBAAgB,CAAC,KAAiB,EAAE,OAAqB;IAChE,MAAM,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC;IACtC,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,GAAG,WAAW,CAAC;IAClE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC;IAE1D,MAAM,aAAa,GAAG,IAAI,SAAS,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IAE1E,MAAM,OAAO,GAAG,IAAI,SAAS,CAAC,aAAa,CAAC,CAAC,KAAK,CAChD,OAAO,CAAC,mBAAmB,CAC5B,CAAC;IAEF,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;GAMG;AACH,SAAS,mBAAmB,CAC1B,QAAmB,EACnB,aAAwB;IAExB,MAAM,SAAS,GAAG,QAAQ,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;IAEvD,OAAO;QACL,GAAG,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,IAAI,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;KAC7B,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,YAAY,CACnB,SAA4C,EAC5C,OAAqB;IAErB,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC;IAEtD,MAAM,uBAAuB,GAC3B,aAAa,KAAK,gBAAgB;QAClC,kBAAkB,KAAK,oBAAoB;QACzC,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC;QAC/B,CAAC,CAAC,kBAAkB,CAAC;IAEzB,MAAM,cAAc,GAAG,gBAAgB,CACrC,SAAS,EACT,uBAAuB,EACvB,aAAa,CACd,CAAC;IAEF,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,SAAS,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,SAAS,CACpE,cAAc,CAAC,OAAO,CACvB,CAAC;IAEF,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAC,SAA4C;IACnE,MAAM,gBAAgB,GAAG,SAAS,CAAC,IAAI,CACrC,sCAAsC,CACvC,CAAC;IAEF,MAAM,YAAY,GAAG,gBAAgB,CAAC,kBAAkB;QACtD,EAAE,iBAAuD,CAAC;IAE5D,MAAM,aAAa,GAAG,YAAY,EAAE,aAAa,IAAI,eAAe,CAAC;IAErE,OAAO;QACL,aAAa;KACd,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,0BAA0B,CACvC,KAAiB,EACjB,SAA4C,EAC5C,OAAqB;IAMrB,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC;IAC5D,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACzE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,aAAa,GAAG,8BAA8B,CAAC,SAAS,CAAC,CAAC;IAEhE,MAAM,QAAQ,GAAG,gBAAgB,CAAC;QAChC,OAAO;QACP,GAAG,EAAE,aAAa;QAClB,SAAS;KACV,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,gBAAgB,CAAC;QAC3B,OAAO;QACP,GAAG,EAAE,aAAa;QAClB,SAAS;QACT,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,eAAe,CACnC,SAAS,EACT,IAAI,EACJ,aAAa,EACb,cAAc,CAAC,aAAa,CAAC,CAC9B,CAAC;IAEF,IAAI,IAAI,SAAS,CAAC,aAAa,CAAC,CAAC,sBAAsB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACjE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;IAC3B,CAAC;IAED,GAAG,CAAC,wDAAwD,EAAE;QAC5D,aAAa;QACb,GAAG,EAAE,GAAG,CAAC,GAAG;KACb,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,MAAM,SAAS,CAAC,IAAI,CACvC,uCAAuC,EACvC;QACE,OAAO,EAAE,aAAa;QACtB,IAAI;QACJ,IAAI;QACJ,EAAE;QACF,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,GAAG,CAAC;KAC3B,CACF,CAAC;IAEF,GAAG,CAAC,uBAAuB,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC;IAE/C,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,KAAK,kBAAkB,CAAC,WAAW,EAAE,CACzE,CAAC;IAEF,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,GAAG,CAAC,iCAAiC,EAAE;YACrC,kBAAkB;YAClB,YAAY;SACb,CAAC,CAAC;QAEH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC;IAErC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,SAAS,CAC7D,WAAW,CAAC,GAAG,EACf,EAAE,CACH,CAAC;QAEF,MAAM,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAE7D,WAAW,GAAG,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAEjD,GAAG,CAAC,0CAA0C,EAAE;YAC9C,WAAW,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1C,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,aAAa;SACd,CAAC,CAAC;IACL,CAAC;IAED,MAAM,gBAAgB,GAAG,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAEjE,MAAM,eAAe,GAAG,wBAAwB,CAAC;QAC/C,OAAO,EAAE,aAAa;QACtB,WAAW,EAAE,gBAAgB;QAC7B,SAAS;KACV,CAAC,CAAC;IAEH,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;IAC3B,CAAC;IAED,GAAG,CAAC,wCAAwC,EAAE;QAC5C,eAAe;KAChB,CAAC,CAAC;IAEH,OAAO;QACL,aAAa,EAAE,IAAI;QACnB,QAAQ,EAAE,eAAe;QACzB,GAAG,EAAE,eAAe;KACrB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,8BAA8B,CACrC,MAAoD;IAEpD,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC;IAEjE,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,MAAM,CAAC,MAAM,CAClB,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,GAAa,CAAC,CAAC,QAAQ,EAAE,EAC/D,CAAC,CACF,CAAC;IACJ,CAAC;IAED,sDAAsD;IACtD,sEAAsE;IAEtE,OAAO,MAAM,CAAC,MAAM,CAClB,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CACX,KAAK,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,wBAAwB,CAAC,CAAC,QAAQ,EAAE,EACrE,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,oBAAoB,CAAC,KAAiB;IAC7C,MAAM,UAAU,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAE/D,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,KAAK,CACvE,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,CACpC,CAAC;IAEF,OAAO,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3D,CAAC","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { successfulFetch, toHex } from '@metamask/controller-utils';\nimport type { Json } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n CHAIN_ID_HYPERCORE,\n RELAY_FALLBACK_GAS_LIMIT,\n RELAY_URL_QUOTE,\n} from './constants';\nimport type { RelayQuote } from './types';\nimport { TransactionPayStrategy } from '../..';\nimport type { TransactionMeta } from '../../../../transaction-controller/src';\nimport {\n ARBITRUM_USDC_ADDRESS,\n CHAIN_ID_ARBITRUM,\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n} from '../../constants';\nimport { projectLogger } from '../../logger';\nimport type {\n Amount,\n FiatValue,\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { calculateGasCost, calculateGasFeeTokenCost } from '../../utils/gas';\nimport {\n getNativeToken,\n getTokenBalance,\n getTokenFiatRate,\n} from '../../utils/token';\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n/**\n * Fetches Relay quotes.\n *\n * @param request - Request object.\n * @returns Array of quotes.\n */\nexport async function getRelayQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>[]> {\n const { requests } = request;\n\n log('Fetching quotes', requests);\n\n try {\n const normalizedRequests = requests\n // Ignore gas fee token requests\n .filter((r) => r.targetAmountMinimum !== '0')\n .map((r) => normalizeRequest(r));\n\n log('Normalized requests', normalizedRequests);\n\n return await Promise.all(\n normalizedRequests.map((r) => getSingleQuote(r, request)),\n );\n } catch (error) {\n log('Error fetching quotes', { error });\n throw new Error(`Failed to fetch Relay quotes: ${String(error)}`);\n }\n}\n\n/**\n * Fetches a single Relay quote.\n *\n * @param request - Quote request.\n * @param fullRequest - Full quotes request.\n * @returns Single quote.\n */\nasync function getSingleQuote(\n request: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n const { messenger, transaction } = fullRequest;\n\n try {\n const body = {\n amount: request.targetAmountMinimum,\n destinationChainId: Number(request.targetChainId),\n destinationCurrency: request.targetTokenAddress,\n originChainId: Number(request.sourceChainId),\n originCurrency: request.sourceTokenAddress,\n recipient: request.from,\n tradeType: 'EXPECTED_OUTPUT',\n user: request.from,\n };\n\n await processTransactions(transaction, request, body, messenger);\n\n const url = getFeatureFlags(messenger).relayQuoteUrl;\n\n log('Request body', { body, url });\n\n const response = await successfulFetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const quote = (await response.json()) as RelayQuote;\n\n log('Fetched relay quote', quote);\n\n return normalizeQuote(quote, request, fullRequest);\n } catch (e) {\n log('Error fetching relay quote', e);\n throw e;\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: Record<string, Json | undefined>,\n messenger: TransactionPayControllerMessenger,\n) {\n const { data, value } = transaction.txParams;\n\n /* istanbul ignore next */\n const hasNoParams = (!data || data === '0x') && (!value || value === '0x0');\n\n const skipDelegation =\n hasNoParams || request.targetChainId === CHAIN_ID_HYPERCORE;\n\n if (skipDelegation) {\n log('Skipping delegation as no transaction data');\n return;\n }\n\n const delegation = await messenger.call(\n 'TransactionPayController:getDelegationTransaction',\n { transaction },\n );\n\n const normalizedAuthorizationList = delegation.authorizationList?.map(\n (a) => ({\n ...a,\n chainId: Number(a.chainId),\n nonce: Number(a.nonce),\n yParity: Number(a.yParity),\n }),\n );\n\n const tokenTransferData = new Interface([\n 'function transfer(address to, uint256 amount)',\n ]).encodeFunctionData('transfer', [\n request.from,\n request.targetAmountMinimum,\n ]);\n\n requestBody.authorizationList = normalizedAuthorizationList;\n requestBody.tradeType = 'EXACT_OUTPUT';\n\n requestBody.txs = [\n {\n to: request.targetTokenAddress,\n data: tokenTransferData,\n value: '0x0',\n },\n {\n to: delegation.to,\n data: delegation.data,\n value: delegation.value,\n },\n ];\n}\n\n/**\n * Normalizes requests for Relay.\n *\n * @param request - Quote request to normalize.\n * @returns Normalized request.\n */\nfunction normalizeRequest(request: QuoteRequest) {\n const isHyperliquidDeposit =\n request.targetChainId === CHAIN_ID_ARBITRUM &&\n request.targetTokenAddress.toLowerCase() ===\n ARBITRUM_USDC_ADDRESS.toLowerCase();\n\n const isPolygonNativeSource =\n request.sourceChainId === CHAIN_ID_POLYGON &&\n request.sourceTokenAddress === getNativeToken(request.sourceChainId);\n\n const requestOutput: QuoteRequest = {\n ...request,\n sourceTokenAddress: isPolygonNativeSource\n ? NATIVE_TOKEN_ADDRESS\n : request.sourceTokenAddress,\n targetChainId: isHyperliquidDeposit\n ? CHAIN_ID_HYPERCORE\n : request.targetChainId,\n targetTokenAddress: isHyperliquidDeposit\n ? '0x00000000000000000000000000000000'\n : request.targetTokenAddress,\n targetAmountMinimum: isHyperliquidDeposit\n ? new BigNumber(request.targetAmountMinimum).shiftedBy(2).toString(10)\n : request.targetAmountMinimum,\n };\n\n if (isHyperliquidDeposit) {\n log('Converting Arbitrum Hyperliquid deposit to direct deposit', {\n originalRequest: request,\n normalizedRequest: requestOutput,\n });\n }\n\n return requestOutput;\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 } = details;\n\n const { usdToFiatRate } = getFiatRates(messenger, request);\n\n const dust = getFiatValueFromUsd(\n calculateDustUsd(quote, request),\n usdToFiatRate,\n );\n\n const provider = getFiatValueFromUsd(\n calculateProviderFee(quote),\n usdToFiatRate,\n );\n\n const { isGasFeeToken: isSourceGasFeeToken, ...sourceNetwork } =\n await calculateSourceNetworkCost(quote, messenger, request);\n\n const targetNetwork = {\n usd: '0',\n fiat: '0',\n };\n\n const sourceAmount: Amount = {\n human: currencyIn.amountFormatted,\n raw: currencyIn.amount,\n ...getFiatValueFromUsd(new BigNumber(currencyIn.amountUsd), usdToFiatRate),\n };\n\n return {\n dust,\n estimatedDuration: details.timeEstimate,\n fees: {\n isSourceGasFeeToken,\n provider,\n sourceNetwork,\n targetNetwork,\n },\n original: quote,\n request,\n sourceAmount,\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) {\n const { currencyOut } = quote.details;\n const { amountUsd, amountFormatted, minimumAmount } = currencyOut;\n const { decimals: targetDecimals } = currencyOut.currency;\n\n const targetUsdRate = new BigNumber(amountUsd).dividedBy(amountFormatted);\n\n const dustRaw = new BigNumber(minimumAmount).minus(\n request.targetAmountMinimum,\n );\n\n return dustRaw.shiftedBy(-targetDecimals).multipliedBy(targetUsdRate);\n}\n\n/**\n * Converts USD value to fiat value.\n *\n * @param usdValue - USD value.\n * @param usdToFiatRate - USD to fiat rate.\n * @returns Fiat value.\n */\nfunction getFiatValueFromUsd(\n usdValue: BigNumber,\n usdToFiatRate: BigNumber,\n): FiatValue {\n const fiatValue = usdValue.multipliedBy(usdToFiatRate);\n\n return {\n usd: usdValue.toString(10),\n fiat: fiatValue.toString(10),\n };\n}\n\n/**\n * Calculates USD to fiat rate.\n *\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @returns USD to fiat rate.\n */\nfunction getFiatRates(\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n) {\n const { sourceChainId, sourceTokenAddress } = request;\n\n const finalSourceTokenAddress =\n sourceChainId === CHAIN_ID_POLYGON &&\n sourceTokenAddress === NATIVE_TOKEN_ADDRESS\n ? getNativeToken(sourceChainId)\n : sourceTokenAddress;\n\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n finalSourceTokenAddress,\n sourceChainId,\n );\n\n if (!sourceFiatRate) {\n throw new Error('Source token fiat rate not found');\n }\n\n const usdToFiatRate = new BigNumber(sourceFiatRate.fiatRate).dividedBy(\n sourceFiatRate.usdRate,\n );\n\n return { sourceFiatRate, usdToFiatRate };\n}\n\n/**\n * Gets feature flags for Relay quotes.\n *\n * @param messenger - Controller messenger.\n * @returns Feature flags.\n */\nfunction getFeatureFlags(messenger: TransactionPayControllerMessenger) {\n const featureFlagState = messenger.call(\n 'RemoteFeatureFlagController:getState',\n );\n\n const featureFlags = featureFlagState.remoteFeatureFlags\n ?.confirmations_pay as Record<string, string> | undefined;\n\n const relayQuoteUrl = featureFlags?.relayQuoteUrl ?? RELAY_URL_QUOTE;\n\n return {\n relayQuoteUrl,\n };\n}\n\n/**\n * Calculates source network cost from a Relay quote.\n *\n * @param quote - Relay quote.\n * @param messenger - Controller messenger.\n * @param request - Quote request.\n * @returns Total source network cost in USD and fiat.\n */\nasync function calculateSourceNetworkCost(\n quote: RelayQuote,\n messenger: TransactionPayControllerMessenger,\n request: QuoteRequest,\n): Promise<\n TransactionPayQuote<RelayQuote>['fees']['sourceNetwork'] & {\n isGasFeeToken?: boolean;\n }\n> {\n const { from, sourceChainId, sourceTokenAddress } = request;\n const allParams = quote.steps.flatMap((s) => s.items).map((i) => i.data);\n const { chainId, data, to, value } = allParams[0];\n const totalGasLimit = calculateSourceNetworkGasLimit(allParams);\n\n const estimate = calculateGasCost({\n chainId,\n gas: totalGasLimit,\n messenger,\n });\n\n const max = calculateGasCost({\n chainId,\n gas: totalGasLimit,\n messenger,\n isMax: true,\n });\n\n const nativeBalance = getTokenBalance(\n messenger,\n from,\n sourceChainId,\n getNativeToken(sourceChainId),\n );\n\n if (new BigNumber(nativeBalance).isGreaterThanOrEqualTo(max.raw)) {\n return { estimate, max };\n }\n\n log('Checking gas fee tokens as insufficient native balance', {\n nativeBalance,\n max: max.raw,\n });\n\n const gasFeeTokens = await messenger.call(\n 'TransactionController:getGasFeeTokens',\n {\n chainId: sourceChainId,\n data,\n from,\n to,\n value: toHex(value ?? '0'),\n },\n );\n\n log('Source gas fee tokens', { gasFeeTokens });\n\n const gasFeeToken = gasFeeTokens.find(\n (t) => t.tokenAddress.toLowerCase() === sourceTokenAddress.toLowerCase(),\n );\n\n if (!gasFeeToken) {\n log('No matching gas fee token found', {\n sourceTokenAddress,\n gasFeeTokens,\n });\n\n return { estimate, max };\n }\n\n let finalAmount = gasFeeToken.amount;\n\n if (allParams.length > 1) {\n const gasRate = new BigNumber(gasFeeToken.amount, 16).dividedBy(\n gasFeeToken.gas,\n 16,\n );\n\n const finalAmountValue = gasRate.multipliedBy(totalGasLimit);\n\n finalAmount = toHex(finalAmountValue.toFixed(0));\n\n log('Estimated gas fee token amount for batch', {\n finalAmount: finalAmountValue.toString(10),\n gasRate: gasRate.toString(10),\n totalGasLimit,\n });\n }\n\n const finalGasFeeToken = { ...gasFeeToken, amount: finalAmount };\n\n const gasFeeTokenCost = calculateGasFeeTokenCost({\n chainId: sourceChainId,\n gasFeeToken: finalGasFeeToken,\n messenger,\n });\n\n if (!gasFeeTokenCost) {\n return { estimate, max };\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 };\n}\n\n/**\n * Calculate the total gas limit for the source network transactions.\n *\n * @param params - Array of transaction parameters.\n * @returns - Total gas limit.\n */\nfunction calculateSourceNetworkGasLimit(\n params: RelayQuote['steps'][0]['items'][0]['data'][],\n): number {\n const allParamsHasGas = params.every((p) => p.gas !== undefined);\n\n if (allParamsHasGas) {\n return params.reduce(\n (total, p) => total + new BigNumber(p.gas as string).toNumber(),\n 0,\n );\n }\n\n // In future, call `TransactionController:estimateGas`\n // or `TransactionController:estimateGasBatch` based on params length.\n\n return params.reduce(\n (total, p) =>\n total + new BigNumber(p.gas ?? RELAY_FALLBACK_GAS_LIMIT).toNumber(),\n 0,\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) {\n const relayerFee = new BigNumber(quote.fees.relayer.amountUsd);\n\n const valueLoss = new BigNumber(quote.details.currencyIn.amountUsd).minus(\n quote.details.currencyOut.amountUsd,\n );\n\n return relayerFee.gt(valueLoss) ? relayerFee : valueLoss;\n}\n"]}
@@ -20,7 +20,7 @@ async function submitRelayQuotes(request) {
20
20
  const { quotes, messenger, transaction } = request;
21
21
  let transactionHash;
22
22
  for (const quote of quotes) {
23
- ({ transactionHash } = await executeSingleQuote(quote.original, messenger, transaction));
23
+ ({ transactionHash } = await executeSingleQuote(quote, messenger, transaction));
24
24
  }
25
25
  return { transactionHash };
26
26
  }
@@ -35,13 +35,6 @@ exports.submitRelayQuotes = submitRelayQuotes;
35
35
  */
36
36
  async function executeSingleQuote(quote, messenger, transaction) {
37
37
  log('Executing single quote', quote);
38
- const { kind } = quote.steps[0];
39
- if (kind !== 'transaction') {
40
- throw new Error(`Unsupported step kind: ${kind}`);
41
- }
42
- const transactionParams = quote.steps[0].items[0].data;
43
- const chainId = (0, controller_utils_1.toHex)(transactionParams.chainId);
44
- const from = transactionParams.from;
45
38
  (0, transaction_1.updateTransaction)({
46
39
  transactionId: transaction.id,
47
40
  messenger,
@@ -49,8 +42,8 @@ async function executeSingleQuote(quote, messenger, transaction) {
49
42
  }, (tx) => {
50
43
  tx.txParams.nonce = undefined;
51
44
  });
52
- await submitTransactions(quote, chainId, from, transaction.id, messenger);
53
- const targetHash = await waitForRelayCompletion(quote);
45
+ await submitTransactions(quote, transaction.id, messenger);
46
+ const targetHash = await waitForRelayCompletion(quote.original);
54
47
  log('Relay request completed', targetHash);
55
48
  (0, transaction_1.updateTransaction)({
56
49
  transactionId: transaction.id,
@@ -112,24 +105,28 @@ function normalizeParams(params) {
112
105
  * Submit transactions for a relay quote.
113
106
  *
114
107
  * @param quote - Relay quote.
115
- * @param chainId - ID of the chain.
116
- * @param from - Address of the sender.
117
108
  * @param parentTransactionId - ID of the parent transaction.
118
109
  * @param messenger - Controller messenger.
119
110
  * @returns Hash of the last submitted transaction.
120
111
  */
121
- async function submitTransactions(quote, chainId, from, parentTransactionId, messenger) {
122
- const params = quote.steps.flatMap((s) => s.items).map((i) => i.data);
112
+ async function submitTransactions(quote, parentTransactionId, messenger) {
113
+ const { steps } = quote.original;
114
+ const params = steps.flatMap((s) => s.items).map((i) => i.data);
115
+ const invalidKind = steps.find((s) => s.kind !== 'transaction')?.kind;
116
+ if (invalidKind) {
117
+ throw new Error(`Unsupported step kind: ${invalidKind}`);
118
+ }
123
119
  const normalizedParams = params.map(normalizeParams);
124
120
  const transactionIds = [];
125
- const networkClientId = messenger.call('NetworkController:findNetworkClientIdByChainId', chainId);
121
+ const { from, sourceChainId, sourceTokenAddress } = quote.request;
122
+ const networkClientId = messenger.call('NetworkController:findNetworkClientIdByChainId', sourceChainId);
126
123
  log('Adding transactions', {
127
124
  normalizedParams,
128
- chainId,
125
+ sourceChainId,
129
126
  from,
130
127
  networkClientId,
131
128
  });
132
- const { end } = (0, transaction_1.collectTransactionIds)(chainId, from, messenger, (transactionId) => {
129
+ const { end } = (0, transaction_1.collectTransactionIds)(sourceChainId, from, messenger, (transactionId) => {
133
130
  transactionIds.push(transactionId);
134
131
  (0, transaction_1.updateTransaction)({
135
132
  transactionId: parentTransactionId,
@@ -143,8 +140,12 @@ async function submitTransactions(quote, chainId, from, parentTransactionId, mes
143
140
  });
144
141
  });
145
142
  let result;
143
+ const gasFeeToken = quote.fees.isSourceGasFeeToken
144
+ ? sourceTokenAddress
145
+ : undefined;
146
146
  if (params.length === 1) {
147
147
  result = await messenger.call('TransactionController:addTransaction', normalizedParams[0], {
148
+ gasFeeToken,
148
149
  networkClientId,
149
150
  origin: controller_utils_1.ORIGIN_METAMASK,
150
151
  requireApproval: false,
@@ -153,6 +154,7 @@ async function submitTransactions(quote, chainId, from, parentTransactionId, mes
153
154
  else {
154
155
  await messenger.call('TransactionController:addTransactionBatch', {
155
156
  from,
157
+ gasFeeToken,
156
158
  networkClientId,
157
159
  origin: controller_utils_1.ORIGIN_METAMASK,
158
160
  requireApproval: false,