{"version":3,"file":"transaction.cjs","sourceRoot":"","sources":["../../src/utils/transaction.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n  TransactionStatus,\n  type TransactionMeta,\n} from '@metamask/transaction-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport { cloneDeep } from 'lodash';\n\nimport { parseRequiredTokens } from './required-tokens';\nimport { projectLogger } from '../logger';\nimport type {\n  TransactionPayControllerMessenger,\n  UpdateTransactionDataCallback,\n} from '../types';\n\nconst log = createModuleLogger(projectLogger, 'transaction');\n\nexport const FINALIZED_STATUSES = [\n  TransactionStatus.confirmed,\n  TransactionStatus.dropped,\n  TransactionStatus.failed,\n];\n\n/**\n * Retrieve transaction metadata by ID.\n *\n * @param transactionId - ID of the transaction to retrieve.\n * @param messenger - Controller messenger.\n * @returns The transaction metadata or undefined if not found.\n */\nexport function getTransaction(\n  transactionId: string,\n  messenger: TransactionPayControllerMessenger,\n): TransactionMeta | undefined {\n  const transactionControllerState = messenger.call(\n    'TransactionController:getState',\n  );\n\n  return transactionControllerState.transactions.find(\n    (tx) => tx.id === transactionId,\n  );\n}\n\n/**\n * Poll for transaction changes and update the transaction data accordingly.\n *\n * @param messenger - Controller messenger.\n * @param updateTransactionData - Callback to update transaction data.\n * @param removeTransactionData - Callback to remove transaction data.\n */\nexport function pollTransactionChanges(\n  messenger: TransactionPayControllerMessenger,\n  updateTransactionData: UpdateTransactionDataCallback,\n  removeTransactionData: (transactionId: string) => void,\n) {\n  messenger.subscribe(\n    'TransactionController:stateChange',\n    (\n      transactions: TransactionMeta[],\n      previousTransactions: TransactionMeta[] | undefined,\n    ) => {\n      const newTransactions = transactions.filter(\n        (tx) => !previousTransactions?.find((prevTx) => prevTx.id === tx.id),\n      );\n\n      const updatedTransactions = transactions.filter((tx) => {\n        const previousTransaction = previousTransactions?.find(\n          (prevTx) => prevTx.id === tx.id,\n        );\n\n        return (\n          previousTransaction &&\n          previousTransaction?.txParams.data !== tx.txParams.data\n        );\n      });\n\n      const finalizedTransactions = transactions.filter((tx) => {\n        const previousTransaction = previousTransactions?.find(\n          (prevTx) => prevTx.id === tx.id,\n        );\n\n        return (\n          previousTransaction &&\n          !FINALIZED_STATUSES.includes(previousTransaction.status) &&\n          FINALIZED_STATUSES.includes(tx.status)\n        );\n      });\n\n      finalizedTransactions.forEach((tx) =>\n        onTransactionFinalized(tx, removeTransactionData),\n      );\n\n      [...newTransactions, ...updatedTransactions].forEach((tx) =>\n        onTransactionChange(tx, messenger, updateTransactionData),\n      );\n    },\n    (state) => state.transactions,\n  );\n}\n\n/**\n * Wait for a transaction to be confirmed or fail.\n *\n * @param transactionId - ID of the transaction to wait for.\n * @param messenger - Controller messenger.\n * @returns A promise that resolves when the transaction is confirmed or rejects if it fails.\n */\nexport function waitForTransactionConfirmed(\n  transactionId: string,\n  messenger: TransactionPayControllerMessenger,\n) {\n  return new Promise<void>((resolve, reject) => {\n    const isConfirmed = (tx?: TransactionMeta, fn?: () => void) => {\n      log('Checking transaction status', tx?.status, tx?.type);\n\n      if (tx?.status === TransactionStatus.confirmed) {\n        fn?.();\n        resolve();\n        return true;\n      }\n\n      if (\n        [TransactionStatus.dropped, TransactionStatus.failed].includes(\n          tx?.status as TransactionStatus,\n        )\n      ) {\n        fn?.();\n        reject(\n          new Error(`Transaction failed - ${tx?.type} - ${tx?.error?.message}`),\n        );\n        return true;\n      }\n\n      return false;\n    };\n\n    const initialState = messenger.call('TransactionController:getState');\n\n    const initialTx = initialState.transactions.find(\n      (t) => t.id === transactionId,\n    );\n\n    if (isConfirmed(initialTx)) {\n      return;\n    }\n\n    const handler = (tx?: TransactionMeta) => {\n      const unsubscribe = () =>\n        messenger.unsubscribe('TransactionController:stateChange', handler);\n\n      isConfirmed(tx, unsubscribe);\n    };\n\n    messenger.subscribe('TransactionController:stateChange', handler, (state) =>\n      state.transactions.find((tx) => tx.id === transactionId),\n    );\n  });\n}\n\n/**\n * Update a transaction by applying a function to its draft.\n *\n * @param request - Request object.\n * @param request.transactionId - ID of the transaction to update.\n * @param request.messenger - Controller messenger.\n * @param request.note - Note describing the update.\n * @param fn - Function that applies updates to the transaction draft.\n */\nexport function updateTransaction(\n  {\n    transactionId,\n    messenger,\n    note,\n  }: {\n    transactionId: string;\n    messenger: TransactionPayControllerMessenger;\n    note: string;\n  },\n  fn: (draft: TransactionMeta) => void,\n) {\n  const transaction = getTransaction(transactionId, messenger as never);\n\n  if (!transaction) {\n    throw new Error(`Transaction not found: ${transactionId}`);\n  }\n\n  const newTransaction = cloneDeep(transaction);\n\n  fn(newTransaction);\n\n  messenger.call(\n    'TransactionController:updateTransaction',\n    newTransaction,\n    note,\n  );\n}\n\n/**\n * Handle a transaction change by updating its associated data.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @param updateTransactionData - Callback to update transaction data.\n */\nfunction onTransactionChange(\n  transaction: TransactionMeta,\n  messenger: TransactionPayControllerMessenger,\n  updateTransactionData: UpdateTransactionDataCallback,\n) {\n  const tokens = parseRequiredTokens(transaction, messenger);\n\n  log('Transaction changed', { transaction, tokens });\n\n  updateTransactionData(transaction.id, (data) => {\n    data.tokens = tokens;\n  });\n}\n\n/**\n * Handle a finalized transaction by removing its associated data.\n *\n * @param transaction - Transaction metadata.\n * @param removeTransactionData - Callback to remove transaction data.\n */\nfunction onTransactionFinalized(\n  transaction: TransactionMeta,\n  removeTransactionData: (transactionId: string) => void,\n) {\n  log('Transaction finalized', { transaction });\n  removeTransactionData(transaction.id);\n}\n"]}