{"version":3,"file":"relay-quotes.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { successfulFetch, toHex } from '@metamask/controller-utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n  ARBITRUM_USDC_ADDRESS,\n  CHAIN_ID_ARBITRUM,\n  RELAY_URL_QUOTE,\n} from './constants';\nimport type { RelayQuote } from './types';\nimport { TransactionPayStrategy } from '../..';\nimport { projectLogger } from '../../logger';\nimport type {\n  FiatValue,\n  PayStrategyGetQuotesRequest,\n  QuoteRequest,\n  TransactionPayControllerMessenger,\n  TransactionPayQuote,\n} from '../../types';\nimport { calculateGasCost } from '../../utils/gas';\nimport { 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  const result = requests\n    // Ignore gas fee token requests\n    .filter((r) => r.targetAmountMinimum !== '0')\n    .map((r) => normalizeRequest(r));\n\n  const normalizedRequests = result.map((r) => r.request);\n  const isSkipTransaction = result.some((r) => r.isSkipTransaction);\n\n  log('Normalized requests', { normalizedRequests, isSkipTransaction });\n\n  return await Promise.all(\n    normalizedRequests.map((r) =>\n      getSingleQuote(r, isSkipTransaction, request),\n    ),\n  );\n}\n\n/**\n * Fetches a single Relay quote.\n *\n * @param request  - Quote request.\n * @param isSkipTransaction - Whether to skip the transaction.\n * @param fullRequest - Full quotes request.\n * @returns  Single quote.\n */\nasync function getSingleQuote(\n  request: QuoteRequest,\n  isSkipTransaction: boolean,\n  fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<RelayQuote>> {\n  const { messenger } = 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    const url = getFeatureFlags(messenger).relayQuoteUrl;\n\n    const response = await successfulFetch(url, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify(body),\n    });\n\n    const quote = (await response.json()) as RelayQuote;\n    quote.skipTransaction = isSkipTransaction;\n\n    log('Fetched relay quote', { quote, url });\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 * 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 requestOutput = {\n    ...request,\n    targetChainId: isHyperliquidDeposit ? toHex(1337) : 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 {\n    request: requestOutput,\n    isSkipTransaction: isHyperliquidDeposit,\n  };\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, transaction } = fullRequest;\n  const { details, fees } = quote;\n  const { currencyIn, currencyOut } = details;\n\n  const usdToFiatRate = getUsdToFiatRate(messenger, request);\n\n  const dust = getFiatValueFromUsd(\n    calculateDustUsd(quote, request),\n    usdToFiatRate,\n  );\n\n  const provider = getFiatValueFromUsd(\n    new BigNumber(currencyIn.amountUsd).minus(currencyOut.amountUsd),\n    usdToFiatRate,\n  );\n\n  const sourceNetwork = getFiatValueFromUsd(\n    new BigNumber(fees.gas.amountUsd),\n    usdToFiatRate,\n  );\n\n  const targetNetwork = quote.skipTransaction\n    ? {\n        usd: '0',\n        fiat: '0',\n      }\n    : calculateGasCost(transaction, messenger);\n\n  return {\n    dust,\n    estimatedDuration: details.timeEstimate,\n    fees: {\n      provider,\n      sourceNetwork,\n      targetNetwork,\n    },\n    original: quote,\n    request,\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 getUsdToFiatRate(\n  messenger: TransactionPayControllerMessenger,\n  request: QuoteRequest,\n) {\n  const { sourceChainId, sourceTokenAddress } = request;\n\n  const sourceFiatRate = getTokenFiatRate(\n    messenger,\n    sourceTokenAddress,\n    sourceChainId,\n  );\n\n  if (!sourceFiatRate) {\n    throw new Error('Source token fiat rate not found');\n  }\n\n  return new BigNumber(sourceFiatRate.fiatRate).dividedBy(\n    sourceFiatRate.usdRate,\n  );\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?.confirmation_pay as\n    | Record<string, string>\n    | undefined;\n\n  const relayQuoteUrl = featureFlags?.relayQuoteUrl ?? RELAY_URL_QUOTE;\n\n  return {\n    relayQuoteUrl,\n  };\n}\n"]}