{"version":3,"file":"quotes.mjs","sourceRoot":"","sources":["../../src/utils/quotes.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AAErD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,uBAAmB;AAC5D,OAAO,EAAE,eAAe,EAAE,qBAAiB;AAC3C,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,0BAAsB;AAClE,OAAO,EAAE,aAAa,EAAE,sBAAkB;AAW1C,MAAM,qBAAqB,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW;AACnD,MAAM,wBAAwB,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAEzD,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;AASxD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B;IAC7D,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,qBAAqB,EAAE,GACxE,OAAO,CAAC;IAEV,MAAM,WAAW,GAAG,cAAc,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IAE7D,GAAG,CAAC,iBAAiB,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;IAE1C,IAAI,CAAC,WAAW,IAAI,CAAC,eAAe,EAAE;QACpC,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;KAC1C;IAED,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,eAAe,CAAC;IAEhE,IAAI,CAAC,YAAY,EAAE;QACjB,OAAO;KACR;IAED,MAAM,QAAQ,GAAmB,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,GAAG,CACxD,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE;QAClB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAExB,OAAO;YACL,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC,IAAW;YACtC,gBAAgB,EAAE,YAAY,CAAC,UAAU;YACzC,iBAAiB,EAAE,YAAY,CAAC,eAAe;YAC/C,aAAa,EAAE,YAAY,CAAC,OAAO;YACnC,kBAAkB,EAAE,YAAY,CAAC,OAAO;YACxC,mBAAmB,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS;YACpE,aAAa,EAAE,KAAK,CAAC,OAAO;YAC5B,kBAAkB,EAAE,KAAK,CAAC,OAAO;SAClC,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE;QACrB,GAAG,CAAC,mBAAmB,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;KAC7C;IAED,IAAI,MAAM,GAA4C,EAAE,CAAC;IAEzD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,SAAkB,EAAE,WAAW,CAAC,CAAC;IAEpE,IAAI;QACF,MAAM,GAAG,QAAQ,EAAE,MAAM;YACvB,CAAC,CAAE,CAAC,MAAM,QAAQ,CAAC,SAAS,CAAC;gBACzB,SAAS;gBACT,QAAQ;gBACR,WAAW;aACZ,CAAC,CAAiC;YACrC,CAAC,CAAC,EAAE,CAAC;KACR;IAAC,OAAO,KAAK,EAAE;QACd,GAAG,CAAC,uBAAuB,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;KACxD;IAED,GAAG,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;IAE1C,MAAM,iBAAiB,GACrB,MAAM,EAAE,MAAM,IAAI,QAAQ,CAAC,oBAAoB;QAC7C,CAAC,CAAC,MAAM,QAAQ,CAAC,oBAAoB,CAAC;YAClC,SAAS;YACT,MAAM;SACP,CAAC;QACJ,CAAC,CAAC,EAAE,CAAC;IAET,GAAG,CAAC,oBAAoB,EAAE,EAAE,aAAa,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAEhE,MAAM,MAAM,GAAG,eAAe,CAAC,MAAe,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;IAEnE,GAAG,CAAC,mBAAmB,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;IAEpD,eAAe,CAAC;QACd,iBAAiB;QACjB,SAAS,EAAE,SAAkB;QAC7B,YAAY;QACZ,MAAM;QACN,aAAa;KACd,CAAC,CAAC;IAEH,qBAAqB,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,EAAE;QAC5C,IAAI,CAAC,MAAM,GAAG,MAAe,CAAC;QAC9B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAA4C,EAC5C,qBAAoD;IAEpD,UAAU,CAAC,GAAG,EAAE;QACd,aAAa,CAAC,SAAS,EAAE,qBAAqB,CAAC;aAC5C,OAAO,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;aACnE,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACf,GAAG,CAAC,sBAAsB,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACP,CAAC,EAAE,qBAAqB,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,eAAe,CAAC,EACvB,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,MAAM,EACN,aAAa,GAOd;IACC,iBAAiB,CACf;QACE,aAAa;QACb,SAAS,EAAE,SAAkB;QAC7B,IAAI,EAAE,6BAA6B;KACpC,EACD,CAAC,EAAmB,EAAE,EAAE;QACtB,EAAE,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QACzC,EAAE,CAAC,wBAAwB,GAAG,EAAE,CAAC;QAEjC,EAAE,CAAC,WAAW,GAAG;YACf,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG;YACvC,OAAO,EAAE,YAAY,CAAC,OAAO;YAC7B,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG;YAC7C,YAAY,EAAE,YAAY,CAAC,OAAO;YAClC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG;SAC5B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,aAAa,CAC1B,SAA4C,EAC5C,qBAAoD;IAEpD,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IAClE,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAE1D,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE;QAC1C,MAAM,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;QAC7D,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,GAAG,eAAe,CAAC;QAEjE,IAAI,SAAS,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE;YAChC,SAAS;SACV;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACxC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAEjD,MAAM,eAAe,GACnB,CAAC,MAAM,QAAQ,CAAC,kBAAkB,EAAE,CAAC;YACnC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa;YACxC,SAAS;SACV,CAAC,CAAC,IAAI,wBAAwB,CAAC;QAElC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,iBAAiB,IAAI,CAAC,CAAC,GAAG,eAAe,CAAC;QAE1E,IAAI,CAAC,SAAS,EAAE;YACd,SAAS;SACV;QAED,GAAG,CAAC,2BAA2B,EAAE;YAC/B,aAAa;YACb,QAAQ,EAAE,YAAY;YACtB,eAAe;SAChB,CAAC,CAAC;QAEH,qBAAqB,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,EAAE;YAC5C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC,CAAC,CAAC;QAEH,MAAM,YAAY,CAAC;YACjB,SAAS;YACT,eAAe;YACf,aAAa;YACb,qBAAqB;SACtB,CAAC,CAAC;QAEH,GAAG,CAAC,kBAAkB,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;KACpE;AACH,CAAC","sourcesContent":["import type { BatchTransaction } from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex, Json } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { getStrategy, getStrategyByName } from './strategy';\nimport { calculateTotals } from './totals';\nimport { getTransaction, updateTransaction } from './transaction';\nimport { projectLogger } from '../logger';\nimport type {\n  QuoteRequest,\n  TransactionData,\n  TransactionPayControllerMessenger,\n  TransactionPayQuote,\n  TransactionPayTotals,\n  TransactionPaymentToken,\n  UpdateTransactionDataCallback,\n} from '../types';\n\nconst QUOTES_CHECK_INTERVAL = 1 * 1000; // 1 Second\nconst DEFAULT_REFRESH_INTERVAL = 30 * 1000; // 30 Seconds\n\nconst log = createModuleLogger(projectLogger, 'quotes');\n\nexport type UpdateQuotesRequest = {\n  messenger: TransactionPayControllerMessenger;\n  transactionData: TransactionData | undefined;\n  transactionId: string;\n  updateTransactionData: UpdateTransactionDataCallback;\n};\n\n/**\n * Update the quotes for a specific transaction.\n *\n * @param request - Request parameters.\n */\nexport async function updateQuotes(request: UpdateQuotesRequest) {\n  const { messenger, transactionData, transactionId, updateTransactionData } =\n    request;\n\n  const transaction = getTransaction(transactionId, messenger);\n\n  log('Updating quotes', { transactionId });\n\n  if (!transaction || !transactionData) {\n    throw new Error('Transaction not found');\n  }\n\n  const { paymentToken, sourceAmounts, tokens } = transactionData;\n\n  if (!paymentToken) {\n    return;\n  }\n\n  const requests: QuoteRequest[] = (sourceAmounts ?? []).map(\n    (sourceAmount, i) => {\n      const token = tokens[i];\n\n      return {\n        from: transaction.txParams.from as Hex,\n        sourceBalanceRaw: paymentToken.balanceRaw,\n        sourceTokenAmount: sourceAmount.sourceAmountRaw,\n        sourceChainId: paymentToken.chainId,\n        sourceTokenAddress: paymentToken.address,\n        targetAmountMinimum: token.allowUnderMinimum ? '0' : token.amountRaw,\n        targetChainId: token.chainId,\n        targetTokenAddress: token.address,\n      };\n    },\n  );\n\n  if (!requests?.length) {\n    log('No quote requests', { transactionId });\n  }\n\n  let quotes: TransactionPayQuote<Json>[] | undefined = [];\n\n  const strategy = await getStrategy(messenger as never, transaction);\n\n  try {\n    quotes = requests?.length\n      ? ((await strategy.getQuotes({\n          messenger,\n          requests,\n          transaction,\n        })) as TransactionPayQuote<Json>[])\n      : [];\n  } catch (error) {\n    log('Error fetching quotes', { error, transactionId });\n  }\n\n  log('Updated', { transactionId, quotes });\n\n  const batchTransactions =\n    quotes?.length && strategy.getBatchTransactions\n      ? await strategy.getBatchTransactions({\n          messenger,\n          quotes,\n        })\n      : [];\n\n  log('Batch transactions', { transactionId, batchTransactions });\n\n  const totals = calculateTotals(quotes as never, tokens, messenger);\n\n  log('Calculated totals', { transactionId, totals });\n\n  syncTransaction({\n    batchTransactions,\n    messenger: messenger as never,\n    paymentToken,\n    totals,\n    transactionId,\n  });\n\n  updateTransactionData(transactionId, (data) => {\n    data.quotes = quotes as never;\n    data.quotesLastUpdated = Date.now();\n    data.totals = totals;\n    data.isLoading = false;\n  });\n}\n\n/**\n * Poll quotes at regular intervals.\n *\n * @param messenger - Messenger instance.\n * @param updateTransactionData - Callback to update transaction data.\n */\nexport function queueRefreshQuotes(\n  messenger: TransactionPayControllerMessenger,\n  updateTransactionData: UpdateTransactionDataCallback,\n) {\n  setTimeout(() => {\n    refreshQuotes(messenger, updateTransactionData)\n      .finally(() => queueRefreshQuotes(messenger, updateTransactionData))\n      .catch((error) => {\n        log('Error polling quotes', { messenger, error });\n      });\n  }, QUOTES_CHECK_INTERVAL);\n}\n\n/**\n * Sync batch transactions to the transaction meta.\n *\n * @param request - Request object.\n * @param request.batchTransactions - Batch transactions to sync.\n * @param request.messenger - Messenger instance.\n * @param request.paymentToken - Payment token used.\n * @param request.totals - Calculated totals.\n * @param request.transactionId - ID of the transaction to sync.\n */\nfunction syncTransaction({\n  batchTransactions,\n  messenger,\n  paymentToken,\n  totals,\n  transactionId,\n}: {\n  batchTransactions: BatchTransaction[];\n  messenger: TransactionPayControllerMessenger;\n  paymentToken: TransactionPaymentToken;\n  totals: TransactionPayTotals;\n  transactionId: string;\n}) {\n  updateTransaction(\n    {\n      transactionId,\n      messenger: messenger as never,\n      note: 'Update transaction pay data',\n    },\n    (tx: TransactionMeta) => {\n      tx.batchTransactions = batchTransactions;\n      tx.batchTransactionsOptions = {};\n\n      tx.metamaskPay = {\n        bridgeFeeFiat: totals.fees.provider.usd,\n        chainId: paymentToken.chainId,\n        networkFeeFiat: totals.fees.sourceNetwork.usd,\n        tokenAddress: paymentToken.address,\n        totalFiat: totals.total.usd,\n      };\n    },\n  );\n}\n\n/**\n * Refresh quotes for all transactions if expired.\n *\n * @param messenger - Messenger instance.\n * @param updateTransactionData - Callback to update transaction data.\n */\nasync function refreshQuotes(\n  messenger: TransactionPayControllerMessenger,\n  updateTransactionData: UpdateTransactionDataCallback,\n) {\n  const state = messenger.call('TransactionPayController:getState');\n  const transactionIds = Object.keys(state.transactionData);\n\n  for (const transactionId of transactionIds) {\n    const transactionData = state.transactionData[transactionId];\n    const { isLoading, quotes, quotesLastUpdated } = transactionData;\n\n    if (isLoading || !quotes?.length) {\n      continue;\n    }\n\n    const strategyName = quotes[0].strategy;\n    const strategy = getStrategyByName(strategyName);\n\n    const refreshInterval =\n      (await strategy.getRefreshInterval?.({\n        chainId: quotes[0].request.sourceChainId,\n        messenger,\n      })) ?? DEFAULT_REFRESH_INTERVAL;\n\n    const isExpired = Date.now() - (quotesLastUpdated ?? 0) > refreshInterval;\n\n    if (!isExpired) {\n      continue;\n    }\n\n    log('Refreshing expired quotes', {\n      transactionId,\n      strategy: strategyName,\n      refreshInterval,\n    });\n\n    updateTransactionData(transactionId, (data) => {\n      data.isLoading = true;\n    });\n\n    await updateQuotes({\n      messenger,\n      transactionData,\n      transactionId,\n      updateTransactionData,\n    });\n\n    log('Refreshed quotes', { transactionId, strategy: strategyName });\n  }\n}\n"]}