@metamask/transaction-controller 31.0.0 → 33.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 (145) hide show
  1. package/CHANGELOG.md +34 -1
  2. package/dist/TransactionController.js +17 -17
  3. package/dist/TransactionController.mjs +16 -16
  4. package/dist/{chunk-Q6Q44V4W.js → chunk-3LWN55E6.js} +6 -6
  5. package/dist/{chunk-RAOYRJ25.js → chunk-3WTSRETF.js} +1 -1
  6. package/dist/chunk-3WTSRETF.js.map +1 -0
  7. package/dist/{chunk-Y7ENNK7L.mjs → chunk-3ZV5YEUV.mjs} +6 -5
  8. package/dist/chunk-3ZV5YEUV.mjs.map +1 -0
  9. package/dist/{chunk-3ZRHCVVS.js → chunk-4IBBHNWG.js} +7 -5
  10. package/dist/chunk-4IBBHNWG.js.map +1 -0
  11. package/dist/{chunk-AZ4WIRH3.mjs → chunk-4V4XIPCI.mjs} +5 -2
  12. package/dist/chunk-4V4XIPCI.mjs.map +1 -0
  13. package/dist/{chunk-NM6OYEPP.mjs → chunk-5ZEJT5SN.mjs} +6 -2
  14. package/dist/chunk-5ZEJT5SN.mjs.map +1 -0
  15. package/dist/{chunk-5YES3V2R.mjs → chunk-6B5BEO3R.mjs} +1 -1
  16. package/dist/chunk-6B5BEO3R.mjs.map +1 -0
  17. package/dist/{chunk-PUESYN62.js → chunk-6OLJWLKK.js} +6 -3
  18. package/dist/chunk-6OLJWLKK.js.map +1 -0
  19. package/dist/{chunk-IT3SYNZ6.js → chunk-74W7X6BE.js} +1 -1
  20. package/dist/chunk-74W7X6BE.js.map +1 -0
  21. package/dist/{chunk-7MKQDZKY.js → chunk-7KREIKNY.js} +3 -3
  22. package/dist/{chunk-EQT25RSP.js → chunk-7NMV2NPM.js} +6 -4
  23. package/dist/chunk-7NMV2NPM.js.map +1 -0
  24. package/dist/{chunk-CDF4QNJA.mjs → chunk-D6BF3IZK.mjs} +2 -2
  25. package/dist/{chunk-QZLPYOGC.mjs → chunk-EGQCE3FK.mjs} +1 -1
  26. package/dist/chunk-EGQCE3FK.mjs.map +1 -0
  27. package/dist/{chunk-CPMTUMMZ.mjs → chunk-EKJXGERC.mjs} +4 -2
  28. package/dist/chunk-EKJXGERC.mjs.map +1 -0
  29. package/dist/{chunk-AHSDUIMT.mjs → chunk-EVL6KODQ.mjs} +1 -1
  30. package/dist/chunk-EVL6KODQ.mjs.map +1 -0
  31. package/dist/{chunk-IJ5GUKRO.mjs → chunk-GNAL5HC2.mjs} +2 -2
  32. package/dist/{chunk-PQCHA5KF.mjs → chunk-K2JC276W.mjs} +38 -26
  33. package/dist/chunk-K2JC276W.mjs.map +1 -0
  34. package/dist/{chunk-G5U6ABRU.mjs → chunk-KLDYR4HR.mjs} +5 -3
  35. package/dist/{chunk-G5U6ABRU.mjs.map → chunk-KLDYR4HR.mjs.map} +1 -1
  36. package/dist/{chunk-METHOFMG.mjs → chunk-KPP6SU7S.mjs} +1 -1
  37. package/dist/chunk-KPP6SU7S.mjs.map +1 -0
  38. package/dist/{chunk-PBYK4OMK.js → chunk-LLXPT2H5.js} +83 -71
  39. package/dist/chunk-LLXPT2H5.js.map +1 -0
  40. package/dist/{chunk-NRQUBP3S.mjs → chunk-MILG772S.mjs} +2 -2
  41. package/dist/{chunk-YXSCBWTU.js → chunk-N6OMDPDK.js} +9 -9
  42. package/dist/{chunk-YXSCBWTU.js.map → chunk-N6OMDPDK.js.map} +1 -1
  43. package/dist/{chunk-V6HVF4EN.mjs → chunk-OGK76ZPK.mjs} +3 -3
  44. package/dist/chunk-OGK76ZPK.mjs.map +1 -0
  45. package/dist/{chunk-UGFBA4GV.js → chunk-OZ6UB42C.js} +5 -1
  46. package/dist/chunk-OZ6UB42C.js.map +1 -0
  47. package/dist/{chunk-J56A7UCK.mjs → chunk-Q56I5ONX.mjs} +5 -1
  48. package/dist/chunk-Q56I5ONX.mjs.map +1 -0
  49. package/dist/{chunk-UT4M4XI3.js → chunk-QH2H4W3N.js} +5 -5
  50. package/dist/{chunk-DTDTOMTB.js → chunk-RHDPOIS4.js} +6 -5
  51. package/dist/chunk-RHDPOIS4.js.map +1 -0
  52. package/dist/{chunk-VH47Q6TS.js → chunk-RXIUMVA5.js} +7 -3
  53. package/dist/chunk-RXIUMVA5.js.map +1 -0
  54. package/dist/{chunk-5KMU2IAT.js → chunk-ULD4JC3Q.js} +1 -1
  55. package/dist/chunk-ULD4JC3Q.js.map +1 -0
  56. package/dist/{chunk-2TUDWNEI.mjs → chunk-UZFDPHQI.mjs} +3 -3
  57. package/dist/{chunk-DLOQPH4M.js → chunk-V4FONAI2.js} +4 -4
  58. package/dist/{chunk-FDUCRHYT.js → chunk-XVYXRCRL.js} +1 -1
  59. package/dist/chunk-XVYXRCRL.js.map +1 -0
  60. package/dist/errors.js +1 -1
  61. package/dist/errors.mjs +1 -1
  62. package/dist/gas-flows/DefaultGasFeeFlow.js +7 -7
  63. package/dist/gas-flows/DefaultGasFeeFlow.mjs +6 -6
  64. package/dist/gas-flows/LineaGasFeeFlow.js +8 -8
  65. package/dist/gas-flows/LineaGasFeeFlow.mjs +7 -7
  66. package/dist/gas-flows/TestGasFeeFlow.js +1 -1
  67. package/dist/gas-flows/TestGasFeeFlow.mjs +1 -1
  68. package/dist/helpers/EtherscanRemoteTransactionSource.js +4 -4
  69. package/dist/helpers/EtherscanRemoteTransactionSource.mjs +3 -3
  70. package/dist/helpers/GasFeePoller.js +4 -4
  71. package/dist/helpers/GasFeePoller.mjs +3 -3
  72. package/dist/helpers/IncomingTransactionHelper.js +2 -2
  73. package/dist/helpers/IncomingTransactionHelper.mjs +1 -1
  74. package/dist/helpers/MultichainTrackingHelper.js +5 -5
  75. package/dist/helpers/MultichainTrackingHelper.mjs +4 -4
  76. package/dist/helpers/PendingTransactionTracker.js +3 -3
  77. package/dist/helpers/PendingTransactionTracker.mjs +2 -2
  78. package/dist/index.js +17 -17
  79. package/dist/index.mjs +16 -16
  80. package/dist/tsconfig.build.tsbuildinfo +1 -1
  81. package/dist/types/TransactionController.d.ts +3 -5
  82. package/dist/types/TransactionController.d.ts.map +1 -1
  83. package/dist/types/gas-flows/DefaultGasFeeFlow.d.ts.map +1 -1
  84. package/dist/types/helpers/EtherscanRemoteTransactionSource.d.ts.map +1 -1
  85. package/dist/types/helpers/IncomingTransactionHelper.d.ts +2 -1
  86. package/dist/types/helpers/IncomingTransactionHelper.d.ts.map +1 -1
  87. package/dist/types/helpers/MultichainTrackingHelper.d.ts.map +1 -1
  88. package/dist/types/helpers/PendingTransactionTracker.d.ts.map +1 -1
  89. package/dist/types/types.d.ts.map +1 -1
  90. package/dist/types/utils/etherscan.d.ts.map +1 -1
  91. package/dist/types/utils/simulation.d.ts.map +1 -1
  92. package/dist/types/utils/utils.d.ts.map +1 -1
  93. package/dist/types.js +2 -2
  94. package/dist/types.mjs +1 -1
  95. package/dist/utils/etherscan.js +2 -2
  96. package/dist/utils/etherscan.mjs +1 -1
  97. package/dist/utils/external-transactions.js +1 -1
  98. package/dist/utils/external-transactions.mjs +1 -1
  99. package/dist/utils/gas-fees.js +6 -6
  100. package/dist/utils/gas-fees.mjs +5 -5
  101. package/dist/utils/gas-flow.js +3 -3
  102. package/dist/utils/gas-flow.mjs +2 -2
  103. package/dist/utils/simulation-api.js +1 -1
  104. package/dist/utils/simulation-api.mjs +1 -1
  105. package/dist/utils/simulation.js +3 -3
  106. package/dist/utils/simulation.mjs +2 -2
  107. package/dist/utils/swaps.js +4 -4
  108. package/dist/utils/swaps.mjs +3 -3
  109. package/dist/utils/transaction-type.js +1 -1
  110. package/dist/utils/transaction-type.mjs +1 -1
  111. package/dist/utils/utils.js +3 -3
  112. package/dist/utils/utils.mjs +2 -2
  113. package/dist/utils/validation.js +4 -4
  114. package/dist/utils/validation.mjs +3 -3
  115. package/package.json +14 -10
  116. package/dist/chunk-3ZRHCVVS.js.map +0 -1
  117. package/dist/chunk-5KMU2IAT.js.map +0 -1
  118. package/dist/chunk-5YES3V2R.mjs.map +0 -1
  119. package/dist/chunk-AHSDUIMT.mjs.map +0 -1
  120. package/dist/chunk-AZ4WIRH3.mjs.map +0 -1
  121. package/dist/chunk-CPMTUMMZ.mjs.map +0 -1
  122. package/dist/chunk-DTDTOMTB.js.map +0 -1
  123. package/dist/chunk-EQT25RSP.js.map +0 -1
  124. package/dist/chunk-FDUCRHYT.js.map +0 -1
  125. package/dist/chunk-IT3SYNZ6.js.map +0 -1
  126. package/dist/chunk-J56A7UCK.mjs.map +0 -1
  127. package/dist/chunk-METHOFMG.mjs.map +0 -1
  128. package/dist/chunk-NM6OYEPP.mjs.map +0 -1
  129. package/dist/chunk-PBYK4OMK.js.map +0 -1
  130. package/dist/chunk-PQCHA5KF.mjs.map +0 -1
  131. package/dist/chunk-PUESYN62.js.map +0 -1
  132. package/dist/chunk-QZLPYOGC.mjs.map +0 -1
  133. package/dist/chunk-RAOYRJ25.js.map +0 -1
  134. package/dist/chunk-UGFBA4GV.js.map +0 -1
  135. package/dist/chunk-V6HVF4EN.mjs.map +0 -1
  136. package/dist/chunk-VH47Q6TS.js.map +0 -1
  137. package/dist/chunk-Y7ENNK7L.mjs.map +0 -1
  138. /package/dist/{chunk-Q6Q44V4W.js.map → chunk-3LWN55E6.js.map} +0 -0
  139. /package/dist/{chunk-7MKQDZKY.js.map → chunk-7KREIKNY.js.map} +0 -0
  140. /package/dist/{chunk-CDF4QNJA.mjs.map → chunk-D6BF3IZK.mjs.map} +0 -0
  141. /package/dist/{chunk-IJ5GUKRO.mjs.map → chunk-GNAL5HC2.mjs.map} +0 -0
  142. /package/dist/{chunk-NRQUBP3S.mjs.map → chunk-MILG772S.mjs.map} +0 -0
  143. /package/dist/{chunk-UT4M4XI3.js.map → chunk-QH2H4W3N.js.map} +0 -0
  144. /package/dist/{chunk-2TUDWNEI.mjs.map → chunk-UZFDPHQI.mjs.map} +0 -0
  145. /package/dist/{chunk-DLOQPH4M.js.map → chunk-V4FONAI2.js.map} +0 -0
@@ -396,4 +396,4 @@ getCurrentChainTransactions_fn = function() {
396
396
  export {
397
397
  PendingTransactionTracker
398
398
  };
399
- //# sourceMappingURL=chunk-5YES3V2R.mjs.map
399
+ //# sourceMappingURL=chunk-6B5BEO3R.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/helpers/PendingTransactionTracker.ts"],"sourcesContent":["import { query } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport type {\n BlockTracker,\n NetworkClientId,\n} from '@metamask/network-controller';\nimport EventEmitter from 'events';\nimport { cloneDeep, merge } from 'lodash';\n\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { TransactionMeta, TransactionReceipt } from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\n\n/**\n * We wait this many blocks before emitting a 'transaction-dropped' event\n * This is because we could be talking to a node that is out of sync\n */\nconst DROPPED_BLOCK_COUNT = 3;\n\nconst RECEIPT_STATUS_SUCCESS = '0x1';\nconst RECEIPT_STATUS_FAILURE = '0x0';\nconst MAX_RETRY_BLOCK_DISTANCE = 50;\n\nconst KNOWN_TRANSACTION_ERRORS = [\n 'replacement transaction underpriced',\n 'known transaction',\n 'gas price too low to replace',\n 'transaction with the same hash was already imported',\n 'gateway timeout',\n 'nonce too low',\n];\n\nconst log = createModuleLogger(projectLogger, 'pending-transactions');\n\ntype SuccessfulTransactionReceipt = TransactionReceipt & {\n blockNumber: string;\n blockHash: string;\n};\n\ntype Events = {\n 'transaction-confirmed': [txMeta: TransactionMeta];\n 'transaction-dropped': [txMeta: TransactionMeta];\n 'transaction-failed': [txMeta: TransactionMeta, error: Error];\n 'transaction-updated': [txMeta: TransactionMeta, note: string];\n};\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface PendingTransactionTrackerEventEmitter extends EventEmitter {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n on<T extends keyof Events>(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): this;\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n emit<T extends keyof Events>(eventName: T, ...args: Events[T]): boolean;\n}\n\nexport class PendingTransactionTracker {\n hub: PendingTransactionTrackerEventEmitter;\n\n #approveTransaction: (transactionId: string) => Promise<void>;\n\n #blockTracker: BlockTracker;\n\n #droppedBlockCountByHash: Map<string, number>;\n\n #getChainId: () => string;\n\n #getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n\n #getTransactions: () => TransactionMeta[];\n\n #isResubmitEnabled: () => boolean;\n\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #listener: any;\n\n #getGlobalLock: () => Promise<() => void>;\n\n #publishTransaction: (ethQuery: EthQuery, rawTx: string) => Promise<string>;\n\n #running: boolean;\n\n #beforeCheckPendingTransaction: (transactionMeta: TransactionMeta) => boolean;\n\n #beforePublish: (transactionMeta: TransactionMeta) => boolean;\n\n constructor({\n approveTransaction,\n blockTracker,\n getChainId,\n getEthQuery,\n getTransactions,\n isResubmitEnabled,\n getGlobalLock,\n publishTransaction,\n hooks,\n }: {\n approveTransaction: (transactionId: string) => Promise<void>;\n blockTracker: BlockTracker;\n getChainId: () => string;\n getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n getTransactions: () => TransactionMeta[];\n isResubmitEnabled?: () => boolean;\n getGlobalLock: () => Promise<() => void>;\n publishTransaction: (ethQuery: EthQuery, rawTx: string) => Promise<string>;\n hooks?: {\n beforeCheckPendingTransaction?: (\n transactionMeta: TransactionMeta,\n ) => boolean;\n beforePublish?: (transactionMeta: TransactionMeta) => boolean;\n };\n }) {\n this.hub = new EventEmitter() as PendingTransactionTrackerEventEmitter;\n\n this.#approveTransaction = approveTransaction;\n this.#blockTracker = blockTracker;\n this.#droppedBlockCountByHash = new Map();\n this.#getChainId = getChainId;\n this.#getEthQuery = getEthQuery;\n this.#getTransactions = getTransactions;\n this.#isResubmitEnabled = isResubmitEnabled ?? (() => true);\n this.#listener = this.#onLatestBlock.bind(this);\n this.#getGlobalLock = getGlobalLock;\n this.#publishTransaction = publishTransaction;\n this.#running = false;\n this.#beforePublish = hooks?.beforePublish ?? (() => true);\n this.#beforeCheckPendingTransaction =\n hooks?.beforeCheckPendingTransaction ?? (() => true);\n }\n\n startIfPendingTransactions = () => {\n const pendingTransactions = this.#getPendingTransactions();\n\n if (pendingTransactions.length) {\n this.#start();\n } else {\n this.stop();\n }\n };\n\n /**\n * Force checks the network if the given transaction is confirmed and updates it's status.\n *\n * @param txMeta - The transaction to check\n */\n async forceCheckTransaction(txMeta: TransactionMeta) {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransaction(txMeta);\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to check transaction', error);\n } finally {\n releaseLock();\n }\n }\n\n #start() {\n if (this.#running) {\n return;\n }\n\n this.#blockTracker.on('latest', this.#listener);\n this.#running = true;\n\n log('Started polling');\n }\n\n stop() {\n if (!this.#running) {\n return;\n }\n\n this.#blockTracker.removeListener('latest', this.#listener);\n this.#running = false;\n\n log('Stopped polling');\n }\n\n async #onLatestBlock(latestBlockNumber: string) {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransactions();\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to check transactions', error);\n } finally {\n releaseLock();\n }\n\n try {\n await this.#resubmitTransactions(latestBlockNumber);\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to resubmit transactions', error);\n }\n }\n\n async #checkTransactions() {\n log('Checking transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n log('No pending transactions to check');\n return;\n }\n\n log('Found pending transactions to check', {\n count: pendingTransactions.length,\n ids: pendingTransactions.map((tx) => tx.id),\n });\n\n await Promise.all(\n pendingTransactions.map((tx) => this.#checkTransaction(tx)),\n );\n }\n\n async #resubmitTransactions(latestBlockNumber: string) {\n if (!this.#isResubmitEnabled() || !this.#running) {\n return;\n }\n\n log('Resubmitting transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n log('No pending transactions to resubmit');\n return;\n }\n\n log('Found pending transactions to resubmit', {\n count: pendingTransactions.length,\n ids: pendingTransactions.map((tx) => tx.id),\n });\n\n for (const txMeta of pendingTransactions) {\n try {\n await this.#resubmitTransaction(txMeta, latestBlockNumber);\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n /* istanbul ignore next */\n const errorMessage =\n error.value?.message?.toLowerCase() || error.message.toLowerCase();\n\n if (this.#isKnownTransactionError(errorMessage)) {\n log('Ignoring known transaction error', errorMessage);\n return;\n }\n\n this.#warnTransaction(\n txMeta,\n error.message,\n 'There was an error when resubmitting this transaction.',\n );\n }\n }\n }\n\n #isKnownTransactionError(errorMessage: string) {\n return KNOWN_TRANSACTION_ERRORS.some((knownError) =>\n errorMessage.includes(knownError),\n );\n }\n\n async #resubmitTransaction(\n txMeta: TransactionMeta,\n latestBlockNumber: string,\n ) {\n if (!this.#isResubmitDue(txMeta, latestBlockNumber)) {\n return;\n }\n\n const { rawTx } = txMeta;\n\n if (!this.#beforePublish(txMeta)) {\n return;\n }\n\n if (!rawTx?.length) {\n log('Approving transaction as no raw value');\n await this.#approveTransaction(txMeta.id);\n return;\n }\n\n const ethQuery = this.#getEthQuery(txMeta.networkClientId);\n await this.#publishTransaction(ethQuery, rawTx);\n\n const retryCount = (txMeta.retryCount ?? 0) + 1;\n\n this.#updateTransaction(\n merge({}, txMeta, { retryCount }),\n 'PendingTransactionTracker:transaction-retry - Retry count increased',\n );\n }\n\n #isResubmitDue(txMeta: TransactionMeta, latestBlockNumber: string): boolean {\n const txMetaWithFirstRetryBlockNumber = cloneDeep(txMeta);\n\n if (!txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber) {\n txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber = latestBlockNumber;\n\n this.#updateTransaction(\n txMetaWithFirstRetryBlockNumber,\n 'PendingTransactionTracker:#isResubmitDue - First retry block number set',\n );\n }\n\n const { firstRetryBlockNumber } = txMetaWithFirstRetryBlockNumber;\n\n const blocksSinceFirstRetry =\n Number.parseInt(latestBlockNumber, 16) -\n Number.parseInt(firstRetryBlockNumber, 16);\n\n const retryCount = txMeta.retryCount || 0;\n\n // Exponential backoff to limit retries at publishing\n // Capped at ~15 minutes between retries\n const requiredBlocksSinceFirstRetry = Math.min(\n MAX_RETRY_BLOCK_DISTANCE,\n Math.pow(2, retryCount),\n );\n\n return blocksSinceFirstRetry >= requiredBlocksSinceFirstRetry;\n }\n\n async #checkTransaction(txMeta: TransactionMeta) {\n const { hash, id } = txMeta;\n\n if (!hash && this.#beforeCheckPendingTransaction(txMeta)) {\n const error = new Error(\n 'We had an error while submitting this transaction, please try again.',\n );\n\n error.name = 'NoTxHashError';\n\n this.#failTransaction(txMeta, error);\n\n return;\n }\n\n if (this.#isNonceTaken(txMeta)) {\n log('Nonce already taken', id);\n this.#dropTransaction(txMeta);\n return;\n }\n\n try {\n const receipt = await this.#getTransactionReceipt(hash);\n const isSuccess = receipt?.status === RECEIPT_STATUS_SUCCESS;\n const isFailure = receipt?.status === RECEIPT_STATUS_FAILURE;\n\n if (isFailure) {\n log('Transaction receipt has failed status');\n\n this.#failTransaction(\n txMeta,\n new Error('Transaction dropped or replaced'),\n );\n\n return;\n }\n\n const { blockNumber, blockHash } = receipt || {};\n\n if (isSuccess && blockNumber && blockHash) {\n await this.#onTransactionConfirmed(txMeta, {\n ...receipt,\n blockNumber,\n blockHash,\n });\n\n return;\n }\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n log('Failed to check transaction', id, error);\n\n this.#warnTransaction(\n txMeta,\n error.message,\n 'There was a problem loading this transaction.',\n );\n\n return;\n }\n\n if (await this.#isTransactionDropped(txMeta)) {\n this.#dropTransaction(txMeta);\n }\n }\n\n async #onTransactionConfirmed(\n txMeta: TransactionMeta,\n receipt: SuccessfulTransactionReceipt,\n ) {\n const { id } = txMeta;\n const { blockHash } = receipt;\n\n log('Transaction confirmed', id);\n\n const { baseFeePerGas, timestamp: blockTimestamp } =\n await this.#getBlockByHash(blockHash, false);\n\n const updatedTxMeta = cloneDeep(txMeta);\n updatedTxMeta.baseFeePerGas = baseFeePerGas;\n updatedTxMeta.blockTimestamp = blockTimestamp;\n updatedTxMeta.status = TransactionStatus.confirmed;\n updatedTxMeta.txParams = {\n ...updatedTxMeta.txParams,\n gasUsed: receipt.gasUsed,\n };\n updatedTxMeta.txReceipt = receipt;\n updatedTxMeta.verifiedOnBlockchain = true;\n\n this.#updateTransaction(\n updatedTxMeta,\n 'PendingTransactionTracker:#onTransactionConfirmed - Transaction confirmed',\n );\n\n this.hub.emit('transaction-confirmed', updatedTxMeta);\n }\n\n async #isTransactionDropped(txMeta: TransactionMeta) {\n const {\n hash,\n id,\n txParams: { nonce, from },\n } = txMeta;\n\n /* istanbul ignore next */\n if (!nonce || !hash) {\n return false;\n }\n\n const networkNextNonceHex = await this.#getNetworkTransactionCount(from);\n const networkNextNonceNumber = parseInt(networkNextNonceHex, 16);\n const nonceNumber = parseInt(nonce, 16);\n\n if (nonceNumber >= networkNextNonceNumber) {\n return false;\n }\n\n let droppedBlockCount = this.#droppedBlockCountByHash.get(hash);\n\n if (droppedBlockCount === undefined) {\n droppedBlockCount = 0;\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount);\n }\n\n if (droppedBlockCount < DROPPED_BLOCK_COUNT) {\n log('Incrementing dropped block count', { id, droppedBlockCount });\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount + 1);\n return false;\n }\n\n log('Hit dropped block count', id);\n\n this.#droppedBlockCountByHash.delete(hash);\n return true;\n }\n\n #isNonceTaken(txMeta: TransactionMeta): boolean {\n const { id, txParams } = txMeta;\n\n return this.#getCurrentChainTransactions().some(\n (tx) =>\n tx.id !== id &&\n tx.txParams.from === txParams.from &&\n tx.status === TransactionStatus.confirmed &&\n tx.txParams.nonce === txParams.nonce &&\n tx.type !== TransactionType.incoming,\n );\n }\n\n #getPendingTransactions(): TransactionMeta[] {\n return this.#getCurrentChainTransactions().filter(\n (tx) =>\n tx.status === TransactionStatus.submitted &&\n !tx.verifiedOnBlockchain &&\n !tx.isUserOperation,\n );\n }\n\n #warnTransaction(txMeta: TransactionMeta, error: string, message: string) {\n this.#updateTransaction(\n {\n ...txMeta,\n warning: { error, message },\n },\n 'PendingTransactionTracker:#warnTransaction - Warning added',\n );\n }\n\n #failTransaction(txMeta: TransactionMeta, error: Error) {\n log('Transaction failed', txMeta.id, error);\n this.hub.emit('transaction-failed', txMeta, error);\n }\n\n #dropTransaction(txMeta: TransactionMeta) {\n log('Transaction dropped', txMeta.id);\n this.hub.emit('transaction-dropped', txMeta);\n }\n\n #updateTransaction(txMeta: TransactionMeta, note: string) {\n this.hub.emit('transaction-updated', txMeta, note);\n }\n\n async #getTransactionReceipt(\n txHash?: string,\n ): Promise<TransactionReceipt | undefined> {\n return await query(this.#getEthQuery(), 'getTransactionReceipt', [txHash]);\n }\n\n async #getBlockByHash(\n blockHash: string,\n includeTransactionDetails: boolean,\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): Promise<any> {\n return await query(this.#getEthQuery(), 'getBlockByHash', [\n blockHash,\n includeTransactionDetails,\n ]);\n }\n\n async #getNetworkTransactionCount(address: string): Promise<string> {\n return await query(this.#getEthQuery(), 'getTransactionCount', [address]);\n }\n\n #getCurrentChainTransactions(): TransactionMeta[] {\n const currentChainId = this.#getChainId();\n\n return this.#getTransactions().filter(\n (tx) => tx.chainId === currentChainId,\n );\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2
2
 
3
- var _chunkEQT25RSPjs = require('./chunk-EQT25RSP.js');
3
+ var _chunk7NMV2NPMjs = require('./chunk-7NMV2NPM.js');
4
4
 
5
5
 
6
6
  var _chunkS6VGOPUYjs = require('./chunk-S6VGOPUY.js');
@@ -125,6 +125,9 @@ var MultichainTrackingHelper = class {
125
125
  networkClientId,
126
126
  chainId
127
127
  } = {}) {
128
+ if (!_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _isMultichainEnabled)) {
129
+ return new (0, _ethquery2.default)(this.getProvider());
130
+ }
128
131
  return new (0, _ethquery2.default)(this.getProvider({ networkClientId, chainId }));
129
132
  }
130
133
  getProvider({
@@ -275,7 +278,7 @@ startTrackingByNetworkClientId_fn = function(networkClientId) {
275
278
  } = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getNetworkClientById).call(this, networkClientId);
276
279
  let etherscanRemoteTransactionSource = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _etherscanRemoteTransactionSourcesMap).get(chainId);
277
280
  if (!etherscanRemoteTransactionSource) {
278
- etherscanRemoteTransactionSource = new (0, _chunkEQT25RSPjs.EtherscanRemoteTransactionSource)({
281
+ etherscanRemoteTransactionSource = new (0, _chunk7NMV2NPMjs.EtherscanRemoteTransactionSource)({
279
282
  includeTokenTransfers: _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _incomingTransactionOptions).includeTokenTransfers
280
283
  });
281
284
  _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _etherscanRemoteTransactionSourcesMap).set(
@@ -332,4 +335,4 @@ getNetworkClient_fn = function({
332
335
 
333
336
 
334
337
  exports.MultichainTrackingHelper = MultichainTrackingHelper;
335
- //# sourceMappingURL=chunk-PUESYN62.js.map
338
+ //# sourceMappingURL=chunk-6OLJWLKK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/helpers/MultichainTrackingHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClientId,\n NetworkController,\n NetworkClient,\n BlockTracker,\n Provider,\n NetworkControllerStateChangeEvent,\n} from '@metamask/network-controller';\nimport type { NonceLock, NonceTracker } from '@metamask/nonce-tracker';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport { incomingTransactionsLogger as log } from '../logger';\nimport { EtherscanRemoteTransactionSource } from './EtherscanRemoteTransactionSource';\nimport type {\n IncomingTransactionHelper,\n IncomingTransactionOptions,\n} from './IncomingTransactionHelper';\nimport type { PendingTransactionTracker } from './PendingTransactionTracker';\n\n/**\n * Registry of network clients provided by the NetworkController\n */\ntype NetworkClientRegistry = ReturnType<\n NetworkController['getNetworkClientRegistry']\n>;\n\nexport type MultichainTrackingHelperOptions = {\n isMultichainEnabled: boolean;\n provider: Provider;\n nonceTracker: NonceTracker;\n incomingTransactionOptions: IncomingTransactionOptions;\n\n findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n getNetworkClientById: NetworkController['getNetworkClientById'];\n getNetworkClientRegistry: NetworkController['getNetworkClientRegistry'];\n\n removeIncomingTransactionHelperListeners: (\n IncomingTransactionHelper: IncomingTransactionHelper,\n ) => void;\n removePendingTransactionTrackerListeners: (\n pendingTransactionTracker: PendingTransactionTracker,\n ) => void;\n createNonceTracker: (opts: {\n provider: Provider;\n blockTracker: BlockTracker;\n chainId?: Hex;\n }) => NonceTracker;\n createIncomingTransactionHelper: (opts: {\n blockTracker: BlockTracker;\n etherscanRemoteTransactionSource: EtherscanRemoteTransactionSource;\n chainId?: Hex;\n }) => IncomingTransactionHelper;\n createPendingTransactionTracker: (opts: {\n provider: Provider;\n blockTracker: BlockTracker;\n chainId?: Hex;\n }) => PendingTransactionTracker;\n onNetworkStateChange: (\n listener: (\n ...payload: NetworkControllerStateChangeEvent['payload']\n ) => void,\n ) => void;\n};\n\nexport class MultichainTrackingHelper {\n #isMultichainEnabled: boolean;\n\n readonly #provider: Provider;\n\n readonly #nonceTracker: NonceTracker;\n\n readonly #incomingTransactionOptions: IncomingTransactionOptions;\n\n readonly #findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n\n readonly #getNetworkClientById: NetworkController['getNetworkClientById'];\n\n readonly #getNetworkClientRegistry: NetworkController['getNetworkClientRegistry'];\n\n readonly #removeIncomingTransactionHelperListeners: (\n IncomingTransactionHelper: IncomingTransactionHelper,\n ) => void;\n\n readonly #removePendingTransactionTrackerListeners: (\n pendingTransactionTracker: PendingTransactionTracker,\n ) => void;\n\n readonly #createNonceTracker: (opts: {\n provider: Provider;\n blockTracker: BlockTracker;\n chainId?: Hex;\n }) => NonceTracker;\n\n readonly #createIncomingTransactionHelper: (opts: {\n blockTracker: BlockTracker;\n chainId?: Hex;\n etherscanRemoteTransactionSource: EtherscanRemoteTransactionSource;\n }) => IncomingTransactionHelper;\n\n readonly #createPendingTransactionTracker: (opts: {\n provider: Provider;\n blockTracker: BlockTracker;\n chainId?: Hex;\n }) => PendingTransactionTracker;\n\n readonly #nonceMutexesByChainId = new Map<Hex, Map<string, Mutex>>();\n\n readonly #trackingMap: Map<\n NetworkClientId,\n {\n nonceTracker: NonceTracker;\n pendingTransactionTracker: PendingTransactionTracker;\n incomingTransactionHelper: IncomingTransactionHelper;\n }\n > = new Map();\n\n readonly #etherscanRemoteTransactionSourcesMap: Map<\n Hex,\n EtherscanRemoteTransactionSource\n > = new Map();\n\n constructor({\n isMultichainEnabled,\n provider,\n nonceTracker,\n incomingTransactionOptions,\n findNetworkClientIdByChainId,\n getNetworkClientById,\n getNetworkClientRegistry,\n removeIncomingTransactionHelperListeners,\n removePendingTransactionTrackerListeners,\n createNonceTracker,\n createIncomingTransactionHelper,\n createPendingTransactionTracker,\n onNetworkStateChange,\n }: MultichainTrackingHelperOptions) {\n this.#isMultichainEnabled = isMultichainEnabled;\n this.#provider = provider;\n this.#nonceTracker = nonceTracker;\n this.#incomingTransactionOptions = incomingTransactionOptions;\n\n this.#findNetworkClientIdByChainId = findNetworkClientIdByChainId;\n this.#getNetworkClientById = getNetworkClientById;\n this.#getNetworkClientRegistry = getNetworkClientRegistry;\n\n this.#removeIncomingTransactionHelperListeners =\n removeIncomingTransactionHelperListeners;\n this.#removePendingTransactionTrackerListeners =\n removePendingTransactionTrackerListeners;\n this.#createNonceTracker = createNonceTracker;\n this.#createIncomingTransactionHelper = createIncomingTransactionHelper;\n this.#createPendingTransactionTracker = createPendingTransactionTracker;\n\n onNetworkStateChange((_, patches) => {\n if (this.#isMultichainEnabled) {\n const networkClients = this.#getNetworkClientRegistry();\n patches.forEach(({ op, path }) => {\n if (op === 'remove' && path[0] === 'networkConfigurations') {\n const networkClientId = path[1] as NetworkClientId;\n delete networkClients[networkClientId];\n }\n });\n\n this.#refreshTrackingMap(networkClients);\n }\n });\n }\n\n initialize() {\n if (!this.#isMultichainEnabled) {\n return;\n }\n const networkClients = this.#getNetworkClientRegistry();\n this.#refreshTrackingMap(networkClients);\n }\n\n has(networkClientId: NetworkClientId) {\n return this.#trackingMap.has(networkClientId);\n }\n\n getEthQuery({\n networkClientId,\n chainId,\n }: {\n networkClientId?: NetworkClientId;\n chainId?: Hex;\n } = {}): EthQuery {\n if (!this.#isMultichainEnabled) {\n return new EthQuery(this.getProvider());\n }\n return new EthQuery(this.getProvider({ networkClientId, chainId }));\n }\n\n getProvider({\n networkClientId,\n chainId,\n }: {\n networkClientId?: NetworkClientId;\n chainId?: Hex;\n } = {}): Provider {\n if (!this.#isMultichainEnabled) {\n return this.#provider;\n }\n\n const networkClient = this.#getNetworkClient({\n networkClientId,\n chainId,\n });\n\n return networkClient?.provider || this.#provider;\n }\n\n /**\n * Gets the mutex intended to guard the nonceTracker for a particular chainId and key .\n *\n * @param opts - The options object.\n * @param opts.chainId - The hex chainId.\n * @param opts.key - The hex address (or constant) pertaining to the chainId\n * @returns Mutex instance for the given chainId and key pair\n */\n async acquireNonceLockForChainIdKey({\n chainId,\n key = 'global',\n }: {\n chainId: Hex;\n key?: string;\n }): Promise<() => void> {\n let nonceMutexesForChainId = this.#nonceMutexesByChainId.get(chainId);\n if (!nonceMutexesForChainId) {\n nonceMutexesForChainId = new Map<string, Mutex>();\n this.#nonceMutexesByChainId.set(chainId, nonceMutexesForChainId);\n }\n let nonceMutexForKey = nonceMutexesForChainId.get(key);\n if (!nonceMutexForKey) {\n nonceMutexForKey = new Mutex();\n nonceMutexesForChainId.set(key, nonceMutexForKey);\n }\n\n return await nonceMutexForKey.acquire();\n }\n\n /**\n * Gets the next nonce according to the nonce-tracker.\n * Ensure `releaseLock` is called once processing of the `nonce` value is complete.\n *\n * @param address - The hex string address for the transaction.\n * @param networkClientId - The network client ID for the transaction, used to fetch the correct nonce tracker.\n * @returns object with the `nextNonce` `nonceDetails`, and the releaseLock.\n */\n async getNonceLock(\n address: string,\n networkClientId?: NetworkClientId,\n ): Promise<NonceLock> {\n let releaseLockForChainIdKey: (() => void) | undefined;\n let nonceTracker = this.#nonceTracker;\n if (networkClientId && this.#isMultichainEnabled) {\n const networkClient = this.#getNetworkClientById(networkClientId);\n releaseLockForChainIdKey = await this.acquireNonceLockForChainIdKey({\n chainId: networkClient.configuration.chainId,\n key: address,\n });\n const trackers = this.#trackingMap.get(networkClientId);\n if (!trackers) {\n throw new Error('missing nonceTracker for networkClientId');\n }\n nonceTracker = trackers.nonceTracker;\n }\n\n // Acquires the lock for the chainId + address and the nonceLock from the nonceTracker, then\n // couples them together by replacing the nonceLock's releaseLock method with\n // an anonymous function that calls releases both the original nonceLock and the\n // lock for the chainId.\n try {\n const nonceLock = await nonceTracker.getNonceLock(address);\n return {\n ...nonceLock,\n releaseLock: () => {\n nonceLock.releaseLock();\n releaseLockForChainIdKey?.();\n },\n };\n } catch (err) {\n releaseLockForChainIdKey?.();\n throw err;\n }\n }\n\n startIncomingTransactionPolling(networkClientIds: NetworkClientId[] = []) {\n networkClientIds.forEach((networkClientId) => {\n this.#trackingMap.get(networkClientId)?.incomingTransactionHelper.start();\n });\n }\n\n stopIncomingTransactionPolling(networkClientIds: NetworkClientId[] = []) {\n networkClientIds.forEach((networkClientId) => {\n this.#trackingMap.get(networkClientId)?.incomingTransactionHelper.stop();\n });\n }\n\n stopAllIncomingTransactionPolling() {\n for (const [, trackers] of this.#trackingMap) {\n trackers.incomingTransactionHelper.stop();\n }\n }\n\n async updateIncomingTransactions(networkClientIds: NetworkClientId[] = []) {\n const promises = await Promise.allSettled(\n networkClientIds.map(async (networkClientId) => {\n return await this.#trackingMap\n .get(networkClientId)\n ?.incomingTransactionHelper.update();\n }),\n );\n\n promises\n .filter((result) => result.status === 'rejected')\n .forEach((result) => {\n log(\n 'failed to update incoming transactions',\n (result as PromiseRejectedResult).reason,\n );\n });\n }\n\n checkForPendingTransactionAndStartPolling = () => {\n for (const [, trackers] of this.#trackingMap) {\n trackers.pendingTransactionTracker.startIfPendingTransactions();\n }\n };\n\n stopAllTracking() {\n for (const [networkClientId] of this.#trackingMap) {\n this.#stopTrackingByNetworkClientId(networkClientId);\n }\n }\n\n #refreshTrackingMap = (networkClients: NetworkClientRegistry) => {\n this.#refreshEtherscanRemoteTransactionSources(networkClients);\n\n const networkClientIds = Object.keys(networkClients);\n const existingNetworkClientIds = Array.from(this.#trackingMap.keys());\n\n // Remove tracking for NetworkClientIds that no longer exist\n const networkClientIdsToRemove = existingNetworkClientIds.filter(\n (id) => !networkClientIds.includes(id),\n );\n networkClientIdsToRemove.forEach((id) => {\n this.#stopTrackingByNetworkClientId(id);\n });\n\n // Start tracking new NetworkClientIds from the registry\n const networkClientIdsToAdd = networkClientIds.filter(\n (id) => !existingNetworkClientIds.includes(id),\n );\n networkClientIdsToAdd.forEach((id) => {\n this.#startTrackingByNetworkClientId(id);\n });\n };\n\n #stopTrackingByNetworkClientId(networkClientId: NetworkClientId) {\n const trackers = this.#trackingMap.get(networkClientId);\n if (trackers) {\n trackers.pendingTransactionTracker.stop();\n this.#removePendingTransactionTrackerListeners(\n trackers.pendingTransactionTracker,\n );\n trackers.incomingTransactionHelper.stop();\n this.#removeIncomingTransactionHelperListeners(\n trackers.incomingTransactionHelper,\n );\n this.#trackingMap.delete(networkClientId);\n }\n }\n\n #startTrackingByNetworkClientId(networkClientId: NetworkClientId) {\n const trackers = this.#trackingMap.get(networkClientId);\n if (trackers) {\n return;\n }\n\n const {\n provider,\n blockTracker,\n configuration: { chainId },\n } = this.#getNetworkClientById(networkClientId);\n\n let etherscanRemoteTransactionSource =\n this.#etherscanRemoteTransactionSourcesMap.get(chainId);\n if (!etherscanRemoteTransactionSource) {\n etherscanRemoteTransactionSource = new EtherscanRemoteTransactionSource({\n includeTokenTransfers:\n this.#incomingTransactionOptions.includeTokenTransfers,\n });\n this.#etherscanRemoteTransactionSourcesMap.set(\n chainId,\n etherscanRemoteTransactionSource,\n );\n }\n\n const nonceTracker = this.#createNonceTracker({\n provider,\n blockTracker,\n chainId,\n });\n\n const incomingTransactionHelper = this.#createIncomingTransactionHelper({\n blockTracker,\n etherscanRemoteTransactionSource,\n chainId,\n });\n\n const pendingTransactionTracker = this.#createPendingTransactionTracker({\n provider,\n blockTracker,\n chainId,\n });\n\n this.#trackingMap.set(networkClientId, {\n nonceTracker,\n incomingTransactionHelper,\n pendingTransactionTracker,\n });\n }\n\n #refreshEtherscanRemoteTransactionSources = (\n networkClients: NetworkClientRegistry,\n ) => {\n // this will be prettier when we have consolidated network clients with a single chainId:\n // check if there are still other network clients using the same chainId\n // if not remove the etherscanRemoteTransaction source from the map\n const chainIdsInRegistry = new Set();\n Object.values(networkClients).forEach((networkClient) =>\n chainIdsInRegistry.add(networkClient.configuration.chainId),\n );\n const existingChainIds = Array.from(\n this.#etherscanRemoteTransactionSourcesMap.keys(),\n );\n const chainIdsToRemove = existingChainIds.filter(\n (chainId) => !chainIdsInRegistry.has(chainId),\n );\n\n chainIdsToRemove.forEach((chainId) => {\n this.#etherscanRemoteTransactionSourcesMap.delete(chainId);\n });\n };\n\n #getNetworkClient({\n networkClientId,\n chainId,\n }: {\n networkClientId?: NetworkClientId;\n chainId?: Hex;\n } = {}): NetworkClient | undefined {\n let networkClient: NetworkClient | undefined;\n\n if (networkClientId) {\n try {\n networkClient = this.#getNetworkClientById(networkClientId);\n } catch (err) {\n log('failed to get network client by networkClientId');\n }\n }\n if (!networkClient && chainId) {\n try {\n const networkClientIdForChainId =\n this.#findNetworkClientIdByChainId(chainId);\n networkClient = this.#getNetworkClientById(networkClientIdForChainId);\n } catch (err) {\n log('failed to get network client by chainId');\n }\n }\n return networkClient;\n }\n}\n"]}
@@ -349,4 +349,4 @@ function getContractInterfaces() {
349
349
 
350
350
 
351
351
  exports.SupportedToken = SupportedToken; exports.getSimulationData = getSimulationData; exports.getEvents = getEvents;
352
- //# sourceMappingURL=chunk-IT3SYNZ6.js.map
352
+ //# sourceMappingURL=chunk-74W7X6BE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/simulation.ts"],"names":["SupportedToken"],"mappings":"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","sourcesContent":["import type { Fragment, LogDescription, Result } from '@ethersproject/abi';\nimport { Interface } from '@ethersproject/abi';\nimport { hexToBN, toHex } from '@metamask/controller-utils';\nimport { abiERC20, abiERC721, abiERC1155 } from '@metamask/metamask-eth-abis';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\n\nimport {\n ABI_SIMULATION_ERC20_WRAPPED,\n ABI_SIMULATION_ERC721_LEGACY,\n} from '../constants';\nimport {\n SimulationError,\n SimulationInvalidResponseError,\n SimulationRevertedError,\n} from '../errors';\nimport { projectLogger } from '../logger';\nimport type {\n SimulationBalanceChange,\n SimulationData,\n SimulationTokenBalanceChange,\n SimulationToken,\n} from '../types';\nimport { SimulationTokenStandard } from '../types';\nimport { simulateTransactions } from './simulation-api';\nimport type {\n SimulationResponseLog,\n SimulationRequestTransaction,\n SimulationResponse,\n SimulationResponseCallTrace,\n SimulationResponseTransaction,\n} from './simulation-api';\n\nexport enum SupportedToken {\n ERC20 = 'erc20',\n ERC721 = 'erc721',\n ERC1155 = 'erc1155',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ERC20_WRAPPED = 'erc20Wrapped',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ERC721_LEGACY = 'erc721Legacy',\n}\n\ntype ABI = Fragment[];\n\nexport type GetSimulationDataRequest = {\n chainId: Hex;\n from: Hex;\n to?: Hex;\n value?: Hex;\n data?: Hex;\n};\n\ntype ParsedEvent = {\n contractAddress: Hex;\n tokenStandard: SimulationTokenStandard;\n name: string;\n args: Record<string, Hex | Hex[]>;\n abi: ABI;\n};\n\nconst log = createModuleLogger(projectLogger, 'simulation');\n\nconst SUPPORTED_EVENTS = [\n 'Transfer',\n 'TransferSingle',\n 'TransferBatch',\n 'Deposit',\n 'Withdrawal',\n];\n\nconst SUPPORTED_TOKEN_ABIS = {\n [SupportedToken.ERC20]: {\n abi: abiERC20,\n standard: SimulationTokenStandard.erc20,\n },\n [SupportedToken.ERC721]: {\n abi: abiERC721,\n standard: SimulationTokenStandard.erc721,\n },\n [SupportedToken.ERC1155]: {\n abi: abiERC1155,\n standard: SimulationTokenStandard.erc1155,\n },\n [SupportedToken.ERC20_WRAPPED]: {\n abi: ABI_SIMULATION_ERC20_WRAPPED,\n standard: SimulationTokenStandard.erc20,\n },\n [SupportedToken.ERC721_LEGACY]: {\n abi: ABI_SIMULATION_ERC721_LEGACY,\n standard: SimulationTokenStandard.erc721,\n },\n};\n\nconst REVERTED_ERRORS = ['execution reverted', 'insufficient funds for gas'];\n\ntype BalanceTransactionMap = Map<SimulationToken, SimulationRequestTransaction>;\n\n/**\n * Generate simulation data for a transaction.\n * @param request - The transaction to simulate.\n * @param request.chainId - The chain ID of the transaction.\n * @param request.from - The sender of the transaction.\n * @param request.to - The recipient of the transaction.\n * @param request.value - The value of the transaction.\n * @param request.data - The data of the transaction.\n * @returns The simulation data.\n */\nexport async function getSimulationData(\n request: GetSimulationDataRequest,\n): Promise<SimulationData> {\n const { chainId, from, to, value, data } = request;\n\n log('Getting simulation data', request);\n\n try {\n const response = await simulateTransactions(chainId, {\n transactions: [\n {\n data,\n from,\n maxFeePerGas: '0x0',\n maxPriorityFeePerGas: '0x0',\n to,\n value,\n },\n ],\n withCallTrace: true,\n withLogs: true,\n });\n\n const transactionError = response.transactions?.[0]?.error;\n\n if (transactionError) {\n throw new SimulationError(transactionError);\n }\n\n const nativeBalanceChange = getNativeBalanceChange(request.from, response);\n const events = getEvents(response);\n\n log('Parsed events', events);\n\n const tokenBalanceChanges = await getTokenBalanceChanges(request, events);\n\n return {\n nativeBalanceChange,\n tokenBalanceChanges,\n };\n } catch (error) {\n log('Failed to get simulation data', error, request);\n\n let simulationError = error as SimulationError;\n\n if (\n REVERTED_ERRORS.some((revertErrorMessage) =>\n simulationError.message?.includes(revertErrorMessage),\n )\n ) {\n simulationError = new SimulationRevertedError();\n }\n\n const { code, message } = simulationError;\n\n return {\n tokenBalanceChanges: [],\n error: {\n code,\n message,\n },\n };\n }\n}\n\n/**\n * Extract the native balance change from a simulation response.\n * @param userAddress - The user's account address.\n * @param response - The simulation response.\n * @returns The native balance change or undefined if unchanged.\n */\nfunction getNativeBalanceChange(\n userAddress: Hex,\n response: SimulationResponse,\n): SimulationBalanceChange | undefined {\n const transactionResponse = response.transactions[0];\n\n /* istanbul ignore next */\n if (!transactionResponse) {\n return undefined;\n }\n\n const { stateDiff } = transactionResponse;\n const previousBalance = stateDiff?.pre?.[userAddress]?.balance;\n const newBalance = stateDiff?.post?.[userAddress]?.balance;\n\n if (!previousBalance || !newBalance) {\n return undefined;\n }\n\n return getSimulationBalanceChange(previousBalance, newBalance);\n}\n\n/**\n * Extract events from a simulation response.\n * @param response - The simulation response.\n * @returns The parsed events.\n */\nexport function getEvents(response: SimulationResponse): ParsedEvent[] {\n /* istanbul ignore next */\n const logs = extractLogs(\n response.transactions[0]?.callTrace ?? ({} as SimulationResponseCallTrace),\n );\n\n log('Extracted logs', logs);\n\n const interfaces = getContractInterfaces();\n\n return logs\n .map((currentLog) => {\n const event = parseLog(currentLog, interfaces);\n\n if (!event) {\n log('Failed to parse log', currentLog);\n return undefined;\n }\n\n /* istanbul ignore next */\n const inputs = event.abi.find((e) => e.name === event.name)?.inputs;\n\n /* istanbul ignore if */\n if (!inputs) {\n log('Failed to find inputs for event', event);\n return undefined;\n }\n\n const args = parseEventArgs(event.args, inputs);\n\n return {\n contractAddress: currentLog.address,\n tokenStandard: event.standard,\n name: event.name,\n args,\n abi: event.abi,\n };\n })\n .filter((e) => e !== undefined) as ParsedEvent[];\n}\n\n/**\n * Parse event arguments using ABI input definitions.\n * @param args - The raw event arguments.\n * @param abiInputs - The ABI input definitions.\n * @returns The parsed event arguments.\n */\nfunction parseEventArgs(\n args: Result,\n abiInputs: { name: string }[],\n): Record<string, Hex | Hex[]> {\n return args.reduce((result, arg, index) => {\n const name = abiInputs[index].name.replace('_', '');\n const value = parseEventArgValue(arg);\n\n result[name] = value;\n\n return result;\n }, {});\n}\n\n/**\n * Parse an event argument value.\n * @param value - The event argument value.\n * @returns The parsed event argument value.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction parseEventArgValue(value: any): Hex | Hex[] {\n if (Array.isArray(value)) {\n return value.map(parseEventArgValue) as Hex[];\n }\n\n return (value.toHexString?.() ?? value).toLowerCase();\n}\n\n/**\n * Generate token balance changes from parsed events.\n * @param request - The transaction that was simulated.\n * @param events - The parsed events.\n * @returns An array of token balance changes.\n */\nasync function getTokenBalanceChanges(\n request: GetSimulationDataRequest,\n events: ParsedEvent[],\n): Promise<SimulationTokenBalanceChange[]> {\n const balanceTxs = getTokenBalanceTransactions(request, events);\n\n log('Generated balance transactions', [...balanceTxs.after.values()]);\n\n const transactions = [\n ...balanceTxs.before.values(),\n request,\n ...balanceTxs.after.values(),\n ];\n\n if (transactions.length === 1) {\n return [];\n }\n\n const response = await simulateTransactions(request.chainId as Hex, {\n transactions,\n });\n\n log('Balance simulation response', response);\n\n if (response.transactions.length !== transactions.length) {\n throw new SimulationInvalidResponseError();\n }\n\n let prevBalanceTxIndex = 0;\n return [...balanceTxs.after.keys()]\n .map((token, index) => {\n const previousBalanceCheckSkipped = !balanceTxs.before.get(token);\n const previousBalance = previousBalanceCheckSkipped\n ? '0x0'\n : getValueFromBalanceTransaction(\n request.from,\n token,\n // eslint-disable-next-line no-plusplus\n response.transactions[prevBalanceTxIndex++],\n );\n\n const newBalance = getValueFromBalanceTransaction(\n request.from,\n token,\n response.transactions[index + balanceTxs.before.size + 1],\n );\n\n const balanceChange = getSimulationBalanceChange(\n previousBalance,\n newBalance,\n );\n\n if (!balanceChange) {\n return undefined;\n }\n\n return {\n ...token,\n ...balanceChange,\n };\n })\n .filter((change) => change !== undefined) as SimulationTokenBalanceChange[];\n}\n\n/**\n * Generate transactions to check token balances.\n * @param request - The transaction that was simulated.\n * @param events - The parsed events.\n * @returns A map of token balance transactions keyed by token.\n */\nfunction getTokenBalanceTransactions(\n request: GetSimulationDataRequest,\n events: ParsedEvent[],\n): {\n before: BalanceTransactionMap;\n after: BalanceTransactionMap;\n} {\n const tokenKeys = new Set();\n const before = new Map();\n const after = new Map();\n\n const userEvents = events.filter(\n (event) =>\n SUPPORTED_EVENTS.includes(event.name) &&\n [event.args.from, event.args.to].includes(request.from),\n );\n\n log('Filtered user events', userEvents);\n\n for (const event of userEvents) {\n const tokenIds = getEventTokenIds(event);\n\n log('Extracted token ids', tokenIds);\n\n for (const tokenId of tokenIds) {\n const simulationToken: SimulationToken = {\n address: event.contractAddress,\n standard: event.tokenStandard,\n id: tokenId,\n };\n\n const tokenKey = JSON.stringify(simulationToken);\n\n if (tokenKeys.has(tokenKey)) {\n log(\n 'Ignoring additional event with same contract and token ID',\n simulationToken,\n );\n continue;\n }\n\n tokenKeys.add(tokenKey);\n\n const data = getBalanceTransactionData(\n event.tokenStandard,\n request.from,\n tokenId,\n );\n\n const transaction: SimulationRequestTransaction = {\n from: request.from,\n to: event.contractAddress,\n data,\n };\n\n if (skipPriorBalanceCheck(event)) {\n after.set(simulationToken, transaction);\n } else {\n before.set(simulationToken, transaction);\n after.set(simulationToken, transaction);\n }\n }\n }\n\n return { before, after };\n}\n\n/**\n * Check if an event needs to check the previous balance.\n * @param event - The parsed event.\n * @returns True if the prior balance check should be skipped.\n */\nfunction skipPriorBalanceCheck(event: ParsedEvent): boolean {\n // In the case of an NFT mint, we cannot check the NFT owner before the mint\n // as the balance check transaction would revert.\n return (\n event.name === 'Transfer' &&\n event.tokenStandard === SimulationTokenStandard.erc721 &&\n parseInt(event.args.from as string, 16) === 0\n );\n}\n\n/**\n * Extract token IDs from a parsed event.\n * @param event - The parsed event.\n * @returns An array of token IDs.\n */\nfunction getEventTokenIds(event: ParsedEvent): (Hex | undefined)[] {\n if (event.tokenStandard === SimulationTokenStandard.erc721) {\n return [event.args.tokenId as Hex];\n }\n\n if (\n event.tokenStandard === SimulationTokenStandard.erc1155 &&\n event.name === 'TransferSingle'\n ) {\n return [event.args.id as Hex];\n }\n\n if (\n event.tokenStandard === SimulationTokenStandard.erc1155 &&\n event.name === 'TransferBatch'\n ) {\n return event.args.ids as Hex[];\n }\n\n // ERC-20 does not have a token ID so default to undefined.\n return [undefined];\n}\n\n/**\n * Extract the value from a balance transaction response.\n * @param from - The address to check the balance of.\n * @param token - The token to check the balance of.\n * @param response - The balance transaction response.\n * @returns The value of the balance transaction.\n */\nfunction getValueFromBalanceTransaction(\n from: Hex,\n token: SimulationToken,\n response: SimulationResponseTransaction,\n): Hex {\n const normalizedReturn = normalizeReturnValue(response.return);\n\n if (token.standard === SimulationTokenStandard.erc721) {\n return normalizedReturn === from ? '0x1' : '0x0';\n }\n\n return normalizedReturn;\n}\n\n/**\n * Generate the balance transaction data for a token.\n * @param tokenStandard - The token standard.\n * @param from - The address to check the balance of.\n * @param tokenId - The token ID to check the balance of.\n * @returns The balance transaction data.\n */\nfunction getBalanceTransactionData(\n tokenStandard: SimulationTokenStandard,\n from: Hex,\n tokenId?: Hex,\n): Hex {\n switch (tokenStandard) {\n case SimulationTokenStandard.erc721:\n return new Interface(abiERC721).encodeFunctionData('ownerOf', [\n tokenId,\n ]) as Hex;\n\n case SimulationTokenStandard.erc1155:\n return new Interface(abiERC1155).encodeFunctionData('balanceOf', [\n from,\n tokenId,\n ]) as Hex;\n\n default:\n return new Interface(abiERC20).encodeFunctionData('balanceOf', [\n from,\n ]) as Hex;\n }\n}\n\n/**\n * Parse a raw event log using known ABIs.\n * @param eventLog - The raw event log.\n * @param interfaces - The contract interfaces.\n * @returns The parsed event log or undefined if it could not be parsed.\n */\nfunction parseLog(\n eventLog: SimulationResponseLog,\n interfaces: Map<SupportedToken, Interface>,\n):\n | (LogDescription & { abi: ABI; standard: SimulationTokenStandard })\n | undefined {\n const supportedTokens = Object.values(SupportedToken);\n\n for (const token of supportedTokens) {\n try {\n const contractInterface = interfaces.get(token) as Interface;\n const { abi, standard } = SUPPORTED_TOKEN_ABIS[token];\n\n return {\n ...contractInterface.parseLog(eventLog),\n abi,\n standard,\n };\n } catch (e) {\n continue;\n }\n }\n\n return undefined;\n}\n\n/**\n * Extract all logs from a call trace tree.\n * @param call - The root call trace.\n * @returns An array of logs.\n */\nfunction extractLogs(\n call: SimulationResponseCallTrace,\n): SimulationResponseLog[] {\n /* istanbul ignore next */\n const logs = call.logs ?? [];\n\n /* istanbul ignore next */\n const nestedCalls = call.calls ?? [];\n\n return [\n ...logs,\n ...nestedCalls.map((nestedCall) => extractLogs(nestedCall)).flat(),\n ];\n}\n\n/**\n * Generate balance change data from previous and new balances.\n * @param previousBalance - The previous balance.\n * @param newBalance - The new balance.\n * @returns The balance change data or undefined if unchanged.\n */\nfunction getSimulationBalanceChange(\n previousBalance: Hex,\n newBalance: Hex,\n): SimulationBalanceChange | undefined {\n const differenceBN = hexToBN(newBalance).sub(hexToBN(previousBalance));\n const isDecrease = differenceBN.isNeg();\n const difference = toHex(differenceBN.abs());\n\n if (differenceBN.isZero()) {\n log('Balance change is zero');\n return undefined;\n }\n\n return {\n previousBalance,\n newBalance,\n difference,\n isDecrease,\n };\n}\n\n/**\n * Normalize a return value.\n * @param value - The return value to normalize.\n * @returns The normalized return value.\n */\nfunction normalizeReturnValue(value: Hex): Hex {\n return toHex(hexToBN(value));\n}\n\n/**\n * Get the contract interfaces for all supported tokens.\n * @returns A map of supported tokens to their contract interfaces.\n */\nfunction getContractInterfaces(): Map<SupportedToken, Interface> {\n const supportedTokens = Object.values(SupportedToken);\n\n return new Map(\n supportedTokens.map((tokenType) => {\n const { abi } = SUPPORTED_TOKEN_ABIS[tokenType];\n const contractInterface = new Interface(abi);\n return [tokenType, contractInterface];\n }),\n );\n}\n"]}
@@ -3,7 +3,7 @@
3
3
  var _chunk2XKEAKQGjs = require('./chunk-2XKEAKQG.js');
4
4
 
5
5
 
6
- var _chunkDLOQPH4Mjs = require('./chunk-DLOQPH4M.js');
6
+ var _chunkV4FONAI2js = require('./chunk-V4FONAI2.js');
7
7
 
8
8
 
9
9
  var _chunkS6VGOPUYjs = require('./chunk-S6VGOPUY.js');
@@ -148,7 +148,7 @@ _updateTransactionGasFeeEstimates = new WeakSet();
148
148
  updateTransactionGasFeeEstimates_fn = async function(transactionMeta, gasFeeControllerData) {
149
149
  const { chainId, networkClientId } = transactionMeta;
150
150
  const ethQuery = new (0, _ethquery2.default)(_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getProvider).call(this, chainId, networkClientId));
151
- const gasFeeFlow = _chunkDLOQPH4Mjs.getGasFeeFlow.call(void 0, transactionMeta, _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _gasFeeFlows));
151
+ const gasFeeFlow = _chunkV4FONAI2js.getGasFeeFlow.call(void 0, transactionMeta, _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _gasFeeFlows));
152
152
  if (gasFeeFlow) {
153
153
  log(
154
154
  "Found gas fee flow",
@@ -225,4 +225,4 @@ getGasFeeControllerData_fn = async function(transactions) {
225
225
 
226
226
 
227
227
  exports.GasFeePoller = GasFeePoller;
228
- //# sourceMappingURL=chunk-7MKQDZKY.js.map
228
+ //# sourceMappingURL=chunk-7KREIKNY.js.map
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2
2
 
3
3
 
4
- var _chunkFDUCRHYTjs = require('./chunk-FDUCRHYT.js');
4
+ var _chunkXVYXRCRLjs = require('./chunk-XVYXRCRL.js');
5
5
 
6
6
 
7
7
  var _chunkUGN7PBONjs = require('./chunk-UGN7PBON.js');
@@ -27,6 +27,8 @@ var EtherscanRemoteTransactionSource = class {
27
27
  includeTokenTransfers
28
28
  } = {}) {
29
29
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _releaseLockAfterInterval);
30
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
31
+ // eslint-disable-next-line @typescript-eslint/naming-convention
30
32
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getResponseTransactions);
31
33
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _normalizeTransaction);
32
34
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _normalizeTokenTransaction);
@@ -36,7 +38,7 @@ var EtherscanRemoteTransactionSource = class {
36
38
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _mutex, new (0, _asyncmutex.Mutex)());
37
39
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _fetchNormalTransactions, async (request, etherscanRequest) => {
38
40
  const { currentChainId } = request;
39
- const etherscanTransactions = await _chunkFDUCRHYTjs.fetchEtherscanTransactions.call(void 0,
41
+ const etherscanTransactions = await _chunkXVYXRCRLjs.fetchEtherscanTransactions.call(void 0,
40
42
  etherscanRequest
41
43
  );
42
44
  return _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getResponseTransactions, getResponseTransactions_fn).call(this, etherscanTransactions).map(
@@ -45,7 +47,7 @@ var EtherscanRemoteTransactionSource = class {
45
47
  });
46
48
  _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _fetchTokenTransactions, async (request, etherscanRequest) => {
47
49
  const { currentChainId } = request;
48
- const etherscanTransactions = await _chunkFDUCRHYTjs.fetchEtherscanTokenTransactions.call(void 0,
50
+ const etherscanTransactions = await _chunkXVYXRCRLjs.fetchEtherscanTokenTransactions.call(void 0,
49
51
  etherscanRequest
50
52
  );
51
53
  return _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getResponseTransactions, getResponseTransactions_fn).call(this, etherscanTransactions).map(
@@ -167,4 +169,4 @@ normalizeTransactionBase_fn = function(txMeta, currentChainId) {
167
169
 
168
170
 
169
171
  exports.EtherscanRemoteTransactionSource = EtherscanRemoteTransactionSource;
170
- //# sourceMappingURL=chunk-EQT25RSP.js.map
172
+ //# sourceMappingURL=chunk-7NMV2NPM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/helpers/EtherscanRemoteTransactionSource.ts"],"names":[],"mappings":"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","sourcesContent":["import { BNToHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport BN from 'bn.js';\nimport { v1 as random } from 'uuid';\n\nimport { ETHERSCAN_SUPPORTED_NETWORKS } from '../constants';\nimport { incomingTransactionsLogger as log } from '../logger';\nimport type {\n RemoteTransactionSource,\n RemoteTransactionSourceRequest,\n TransactionMeta,\n} from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\nimport {\n fetchEtherscanTokenTransactions,\n fetchEtherscanTransactions,\n} from '../utils/etherscan';\nimport type {\n EtherscanTokenTransactionMeta,\n EtherscanTransactionMeta,\n EtherscanTransactionMetaBase,\n EtherscanTransactionRequest,\n EtherscanTransactionResponse,\n} from '../utils/etherscan';\n\nconst ETHERSCAN_RATE_LIMIT_INTERVAL = 5000;\n/**\n * A RemoteTransactionSource that fetches transaction data from Etherscan.\n */\nexport class EtherscanRemoteTransactionSource\n implements RemoteTransactionSource\n{\n #includeTokenTransfers: boolean;\n\n #isTokenRequestPending: boolean;\n\n #mutex = new Mutex();\n\n constructor({\n includeTokenTransfers,\n }: { includeTokenTransfers?: boolean } = {}) {\n this.#includeTokenTransfers = includeTokenTransfers ?? true;\n this.#isTokenRequestPending = false;\n }\n\n isSupportedNetwork(chainId: Hex): boolean {\n return Object.keys(ETHERSCAN_SUPPORTED_NETWORKS).includes(chainId);\n }\n\n getLastBlockVariations(): string[] {\n return [this.#isTokenRequestPending ? 'token' : 'normal'];\n }\n\n async fetchTransactions(\n request: RemoteTransactionSourceRequest,\n ): Promise<TransactionMeta[]> {\n const releaseLock = await this.#mutex.acquire();\n const acquiredTime = Date.now();\n\n const etherscanRequest: EtherscanTransactionRequest = {\n ...request,\n chainId: request.currentChainId,\n };\n\n try {\n const transactions = this.#isTokenRequestPending\n ? await this.#fetchTokenTransactions(request, etherscanRequest)\n : await this.#fetchNormalTransactions(request, etherscanRequest);\n\n if (this.#includeTokenTransfers) {\n this.#isTokenRequestPending = !this.#isTokenRequestPending;\n }\n\n return transactions;\n } finally {\n this.#releaseLockAfterInterval(acquiredTime, releaseLock);\n }\n }\n\n #releaseLockAfterInterval(acquireTime: number, releaseLock: () => void) {\n const elapsedTime = Date.now() - acquireTime;\n const remainingTime = Math.max(\n 0,\n ETHERSCAN_RATE_LIMIT_INTERVAL - elapsedTime,\n );\n // Wait for the remaining time if it hasn't been 5 seconds yet\n if (remainingTime > 0) {\n setTimeout(releaseLock, remainingTime);\n } else {\n releaseLock();\n }\n }\n\n #fetchNormalTransactions = async (\n request: RemoteTransactionSourceRequest,\n etherscanRequest: EtherscanTransactionRequest,\n ) => {\n const { currentChainId } = request;\n\n const etherscanTransactions = await fetchEtherscanTransactions(\n etherscanRequest,\n );\n\n return this.#getResponseTransactions(etherscanTransactions).map((tx) =>\n this.#normalizeTransaction(tx, currentChainId),\n );\n };\n\n #fetchTokenTransactions = async (\n request: RemoteTransactionSourceRequest,\n etherscanRequest: EtherscanTransactionRequest,\n ) => {\n const { currentChainId } = request;\n\n const etherscanTransactions = await fetchEtherscanTokenTransactions(\n etherscanRequest,\n );\n\n return this.#getResponseTransactions(etherscanTransactions).map((tx) =>\n this.#normalizeTokenTransaction(tx, currentChainId),\n );\n };\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n #getResponseTransactions<T extends EtherscanTransactionMetaBase>(\n response: EtherscanTransactionResponse<T>,\n ): T[] {\n let result = response.result as T[];\n\n if (response.status === '0') {\n result = [];\n\n if (response.result.length) {\n log('Ignored Etherscan request error', {\n message: response.result,\n type: this.#isTokenRequestPending ? 'token' : 'normal',\n });\n }\n }\n\n return result;\n }\n\n #normalizeTransaction(\n txMeta: EtherscanTransactionMeta,\n currentChainId: Hex,\n ): TransactionMeta {\n const base = this.#normalizeTransactionBase(txMeta, currentChainId);\n\n return {\n ...base,\n txParams: {\n ...base.txParams,\n data: txMeta.input,\n },\n ...(txMeta.isError === '0'\n ? { status: TransactionStatus.confirmed }\n : {\n error: new Error('Transaction failed'),\n status: TransactionStatus.failed,\n }),\n };\n }\n\n #normalizeTokenTransaction(\n txMeta: EtherscanTokenTransactionMeta,\n currentChainId: Hex,\n ): TransactionMeta {\n const base = this.#normalizeTransactionBase(txMeta, currentChainId);\n\n return {\n ...base,\n isTransfer: true,\n transferInformation: {\n contractAddress: txMeta.contractAddress,\n decimals: Number(txMeta.tokenDecimal),\n symbol: txMeta.tokenSymbol,\n },\n };\n }\n\n #normalizeTransactionBase(\n txMeta: EtherscanTransactionMetaBase,\n currentChainId: Hex,\n ): TransactionMeta {\n const time = parseInt(txMeta.timeStamp, 10) * 1000;\n\n return {\n blockNumber: txMeta.blockNumber,\n chainId: currentChainId,\n hash: txMeta.hash,\n id: random({ msecs: time }),\n status: TransactionStatus.confirmed,\n time,\n txParams: {\n chainId: currentChainId,\n from: txMeta.from,\n gas: BNToHex(new BN(txMeta.gas)),\n gasPrice: BNToHex(new BN(txMeta.gasPrice)),\n gasUsed: BNToHex(new BN(txMeta.gasUsed)),\n nonce: BNToHex(new BN(txMeta.nonce)),\n to: txMeta.to,\n value: BNToHex(new BN(txMeta.value)),\n },\n type: TransactionType.incoming,\n verifiedOnBlockchain: false,\n };\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  GasFeeEstimateLevel
3
- } from "./chunk-METHOFMG.mjs";
3
+ } from "./chunk-KPP6SU7S.mjs";
4
4
 
5
5
  // src/utils/gas-flow.ts
6
6
  import { weiHexToGweiDec } from "@metamask/controller-utils";
@@ -64,4 +64,4 @@ export {
64
64
  getGasFeeFlow,
65
65
  mergeGasFeeEstimates
66
66
  };
67
- //# sourceMappingURL=chunk-CDF4QNJA.mjs.map
67
+ //# sourceMappingURL=chunk-D6BF3IZK.mjs.map
@@ -82,4 +82,4 @@ export {
82
82
  fetchEtherscanTokenTransactions,
83
83
  getEtherscanApiHost
84
84
  };
85
- //# sourceMappingURL=chunk-QZLPYOGC.mjs.map
85
+ //# sourceMappingURL=chunk-EGQCE3FK.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/etherscan.ts"],"sourcesContent":["import { handleFetch } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\n\nimport { ETHERSCAN_SUPPORTED_NETWORKS } from '../constants';\nimport { incomingTransactionsLogger as log } from '../logger';\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTransactionMetaBase {\n blockNumber: string;\n blockHash: string;\n confirmations: string;\n contractAddress: string;\n cumulativeGasUsed: string;\n from: string;\n gas: string;\n gasPrice: string;\n gasUsed: string;\n hash: string;\n nonce: string;\n timeStamp: string;\n to: string;\n transactionIndex: string;\n value: string;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTransactionMeta extends EtherscanTransactionMetaBase {\n functionName: string;\n input: string;\n isError: string;\n methodId: string;\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n txreceipt_status: string;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTokenTransactionMeta\n extends EtherscanTransactionMetaBase {\n tokenDecimal: string;\n tokenName: string;\n tokenSymbol: string;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTransactionResponse<\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n T extends EtherscanTransactionMetaBase,\n> {\n status: '0' | '1';\n message?: string;\n result: string | T[];\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTransactionRequest {\n address: string;\n chainId: Hex;\n fromBlock?: number;\n limit?: number;\n}\n\n/**\n * Retrieves transaction data from Etherscan.\n *\n * @param request - Configuration required to fetch transactions.\n * @param request.address - Address to retrieve transactions for.\n * @param request.chainId - Current chain ID used to determine subdomain and domain.\n * @param request.fromBlock - Block number to start fetching transactions from.\n * @param request.limit - Number of transactions to retrieve.\n * @returns An Etherscan response object containing the request status and an array of token transaction data.\n */\nexport async function fetchEtherscanTransactions({\n address,\n chainId,\n fromBlock,\n limit,\n}: EtherscanTransactionRequest): Promise<\n EtherscanTransactionResponse<EtherscanTransactionMeta>\n> {\n return await fetchTransactions('txlist', {\n address,\n chainId,\n fromBlock,\n limit,\n });\n}\n\n/**\n * Retrieves token transaction data from Etherscan.\n *\n * @param request - Configuration required to fetch token transactions.\n * @param request.address - Address to retrieve token transactions for.\n * @param request.chainId - Current chain ID used to determine subdomain and domain.\n * @param request.fromBlock - Block number to start fetching token transactions from.\n * @param request.limit - Number of token transactions to retrieve.\n * @returns An Etherscan response object containing the request status and an array of token transaction data.\n */\nexport async function fetchEtherscanTokenTransactions({\n address,\n chainId,\n fromBlock,\n limit,\n}: EtherscanTransactionRequest): Promise<\n EtherscanTransactionResponse<EtherscanTokenTransactionMeta>\n> {\n return await fetchTransactions('tokentx', {\n address,\n chainId,\n fromBlock,\n limit,\n });\n}\n\n/**\n * Retrieves transaction data from Etherscan from a specific endpoint.\n *\n * @param action - The Etherscan endpoint to use.\n * @param options - Options bag.\n * @param options.address - Address to retrieve transactions for.\n * @param options.chainId - Current chain ID used to determine subdomain and domain.\n * @param options.fromBlock - Block number to start fetching transactions from.\n * @param options.limit - Number of transactions to retrieve.\n * @returns An object containing the request status and an array of transaction data.\n */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nasync function fetchTransactions<T extends EtherscanTransactionMetaBase>(\n action: string,\n {\n address,\n chainId,\n fromBlock,\n limit,\n }: {\n address: string;\n chainId: Hex;\n fromBlock?: number;\n limit?: number;\n },\n): Promise<EtherscanTransactionResponse<T>> {\n const urlParams = {\n module: 'account',\n address,\n startBlock: fromBlock?.toString(),\n offset: limit?.toString(),\n sort: 'desc',\n };\n\n const etherscanTxUrl = getEtherscanApiUrl(chainId, {\n ...urlParams,\n action,\n });\n\n log('Sending Etherscan request', etherscanTxUrl);\n\n const response = (await handleFetch(\n etherscanTxUrl,\n )) as EtherscanTransactionResponse<T>;\n\n return response;\n}\n\n/**\n * Return a URL that can be used to fetch data from Etherscan.\n *\n * @param chainId - Current chain ID used to determine subdomain and domain.\n * @param urlParams - The parameters used to construct the URL.\n * @returns URL to access Etherscan data.\n */\nfunction getEtherscanApiUrl(\n chainId: Hex,\n urlParams: Record<string, string | undefined>,\n): string {\n const apiUrl = getEtherscanApiHost(chainId);\n let url = `${apiUrl}/api?`;\n\n for (const paramKey of Object.keys(urlParams)) {\n const value = urlParams[paramKey];\n\n if (!value) {\n continue;\n }\n\n url += `${paramKey}=${value}&`;\n }\n\n url += 'tag=latest&page=1';\n\n return url;\n}\n\n/**\n * Return the host url used to fetch data from Etherscan.\n *\n * @param chainId - Current chain ID used to determine subdomain and domain.\n * @returns host URL to access Etherscan data.\n */\nexport function getEtherscanApiHost(chainId: Hex) {\n // @ts-expect-error We account for `chainId` not being a property below\n const networkInfo = ETHERSCAN_SUPPORTED_NETWORKS[chainId];\n\n if (!networkInfo) {\n throw new Error(`Etherscan does not support chain with ID: ${chainId}`);\n }\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `https://${networkInfo.subdomain}.${networkInfo.domain}`;\n}\n"],"mappings":";;;;;;;;AAAA,SAAS,mBAAmB;AAmF5B,eAAsB,2BAA2B;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEE;AACA,SAAO,MAAM,kBAAkB,UAAU;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAYA,eAAsB,gCAAgC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEE;AACA,SAAO,MAAM,kBAAkB,WAAW;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAeA,eAAe,kBACb,QACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAM0C;AAC1C,QAAM,YAAY;AAAA,IAChB,QAAQ;AAAA,IACR;AAAA,IACA,YAAY,WAAW,SAAS;AAAA,IAChC,QAAQ,OAAO,SAAS;AAAA,IACxB,MAAM;AAAA,EACR;AAEA,QAAM,iBAAiB,mBAAmB,SAAS;AAAA,IACjD,GAAG;AAAA,IACH;AAAA,EACF,CAAC;AAED,6BAAI,6BAA6B,cAAc;AAE/C,QAAM,WAAY,MAAM;AAAA,IACtB;AAAA,EACF;AAEA,SAAO;AACT;AASA,SAAS,mBACP,SACA,WACQ;AACR,QAAM,SAAS,oBAAoB,OAAO;AAC1C,MAAI,MAAM,GAAG,MAAM;AAEnB,aAAW,YAAY,OAAO,KAAK,SAAS,GAAG;AAC7C,UAAM,QAAQ,UAAU,QAAQ;AAEhC,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AAEA,WAAO,GAAG,QAAQ,IAAI,KAAK;AAAA,EAC7B;AAEA,SAAO;AAEP,SAAO;AACT;AAQO,SAAS,oBAAoB,SAAc;AAEhD,QAAM,cAAc,6BAA6B,OAAO;AAExD,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,MAAM,6CAA6C,OAAO,EAAE;AAAA,EACxE;AAIA,SAAO,WAAW,YAAY,SAAS,IAAI,YAAY,MAAM;AAC/D;","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  fetchEtherscanTokenTransactions,
3
3
  fetchEtherscanTransactions
4
- } from "./chunk-QZLPYOGC.mjs";
4
+ } from "./chunk-EGQCE3FK.mjs";
5
5
  import {
6
6
  ETHERSCAN_SUPPORTED_NETWORKS
7
7
  } from "./chunk-O6ZZVIFH.mjs";
@@ -27,6 +27,8 @@ var EtherscanRemoteTransactionSource = class {
27
27
  includeTokenTransfers
28
28
  } = {}) {
29
29
  __privateAdd(this, _releaseLockAfterInterval);
30
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
31
+ // eslint-disable-next-line @typescript-eslint/naming-convention
30
32
  __privateAdd(this, _getResponseTransactions);
31
33
  __privateAdd(this, _normalizeTransaction);
32
34
  __privateAdd(this, _normalizeTokenTransaction);
@@ -167,4 +169,4 @@ normalizeTransactionBase_fn = function(txMeta, currentChainId) {
167
169
  export {
168
170
  EtherscanRemoteTransactionSource
169
171
  };
170
- //# sourceMappingURL=chunk-CPMTUMMZ.mjs.map
172
+ //# sourceMappingURL=chunk-EKJXGERC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/helpers/EtherscanRemoteTransactionSource.ts"],"sourcesContent":["import { BNToHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport BN from 'bn.js';\nimport { v1 as random } from 'uuid';\n\nimport { ETHERSCAN_SUPPORTED_NETWORKS } from '../constants';\nimport { incomingTransactionsLogger as log } from '../logger';\nimport type {\n RemoteTransactionSource,\n RemoteTransactionSourceRequest,\n TransactionMeta,\n} from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\nimport {\n fetchEtherscanTokenTransactions,\n fetchEtherscanTransactions,\n} from '../utils/etherscan';\nimport type {\n EtherscanTokenTransactionMeta,\n EtherscanTransactionMeta,\n EtherscanTransactionMetaBase,\n EtherscanTransactionRequest,\n EtherscanTransactionResponse,\n} from '../utils/etherscan';\n\nconst ETHERSCAN_RATE_LIMIT_INTERVAL = 5000;\n/**\n * A RemoteTransactionSource that fetches transaction data from Etherscan.\n */\nexport class EtherscanRemoteTransactionSource\n implements RemoteTransactionSource\n{\n #includeTokenTransfers: boolean;\n\n #isTokenRequestPending: boolean;\n\n #mutex = new Mutex();\n\n constructor({\n includeTokenTransfers,\n }: { includeTokenTransfers?: boolean } = {}) {\n this.#includeTokenTransfers = includeTokenTransfers ?? true;\n this.#isTokenRequestPending = false;\n }\n\n isSupportedNetwork(chainId: Hex): boolean {\n return Object.keys(ETHERSCAN_SUPPORTED_NETWORKS).includes(chainId);\n }\n\n getLastBlockVariations(): string[] {\n return [this.#isTokenRequestPending ? 'token' : 'normal'];\n }\n\n async fetchTransactions(\n request: RemoteTransactionSourceRequest,\n ): Promise<TransactionMeta[]> {\n const releaseLock = await this.#mutex.acquire();\n const acquiredTime = Date.now();\n\n const etherscanRequest: EtherscanTransactionRequest = {\n ...request,\n chainId: request.currentChainId,\n };\n\n try {\n const transactions = this.#isTokenRequestPending\n ? await this.#fetchTokenTransactions(request, etherscanRequest)\n : await this.#fetchNormalTransactions(request, etherscanRequest);\n\n if (this.#includeTokenTransfers) {\n this.#isTokenRequestPending = !this.#isTokenRequestPending;\n }\n\n return transactions;\n } finally {\n this.#releaseLockAfterInterval(acquiredTime, releaseLock);\n }\n }\n\n #releaseLockAfterInterval(acquireTime: number, releaseLock: () => void) {\n const elapsedTime = Date.now() - acquireTime;\n const remainingTime = Math.max(\n 0,\n ETHERSCAN_RATE_LIMIT_INTERVAL - elapsedTime,\n );\n // Wait for the remaining time if it hasn't been 5 seconds yet\n if (remainingTime > 0) {\n setTimeout(releaseLock, remainingTime);\n } else {\n releaseLock();\n }\n }\n\n #fetchNormalTransactions = async (\n request: RemoteTransactionSourceRequest,\n etherscanRequest: EtherscanTransactionRequest,\n ) => {\n const { currentChainId } = request;\n\n const etherscanTransactions = await fetchEtherscanTransactions(\n etherscanRequest,\n );\n\n return this.#getResponseTransactions(etherscanTransactions).map((tx) =>\n this.#normalizeTransaction(tx, currentChainId),\n );\n };\n\n #fetchTokenTransactions = async (\n request: RemoteTransactionSourceRequest,\n etherscanRequest: EtherscanTransactionRequest,\n ) => {\n const { currentChainId } = request;\n\n const etherscanTransactions = await fetchEtherscanTokenTransactions(\n etherscanRequest,\n );\n\n return this.#getResponseTransactions(etherscanTransactions).map((tx) =>\n this.#normalizeTokenTransaction(tx, currentChainId),\n );\n };\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n #getResponseTransactions<T extends EtherscanTransactionMetaBase>(\n response: EtherscanTransactionResponse<T>,\n ): T[] {\n let result = response.result as T[];\n\n if (response.status === '0') {\n result = [];\n\n if (response.result.length) {\n log('Ignored Etherscan request error', {\n message: response.result,\n type: this.#isTokenRequestPending ? 'token' : 'normal',\n });\n }\n }\n\n return result;\n }\n\n #normalizeTransaction(\n txMeta: EtherscanTransactionMeta,\n currentChainId: Hex,\n ): TransactionMeta {\n const base = this.#normalizeTransactionBase(txMeta, currentChainId);\n\n return {\n ...base,\n txParams: {\n ...base.txParams,\n data: txMeta.input,\n },\n ...(txMeta.isError === '0'\n ? { status: TransactionStatus.confirmed }\n : {\n error: new Error('Transaction failed'),\n status: TransactionStatus.failed,\n }),\n };\n }\n\n #normalizeTokenTransaction(\n txMeta: EtherscanTokenTransactionMeta,\n currentChainId: Hex,\n ): TransactionMeta {\n const base = this.#normalizeTransactionBase(txMeta, currentChainId);\n\n return {\n ...base,\n isTransfer: true,\n transferInformation: {\n contractAddress: txMeta.contractAddress,\n decimals: Number(txMeta.tokenDecimal),\n symbol: txMeta.tokenSymbol,\n },\n };\n }\n\n #normalizeTransactionBase(\n txMeta: EtherscanTransactionMetaBase,\n currentChainId: Hex,\n ): TransactionMeta {\n const time = parseInt(txMeta.timeStamp, 10) * 1000;\n\n return {\n blockNumber: txMeta.blockNumber,\n chainId: currentChainId,\n hash: txMeta.hash,\n id: random({ msecs: time }),\n status: TransactionStatus.confirmed,\n time,\n txParams: {\n chainId: currentChainId,\n from: txMeta.from,\n gas: BNToHex(new BN(txMeta.gas)),\n gasPrice: BNToHex(new BN(txMeta.gasPrice)),\n gasUsed: BNToHex(new BN(txMeta.gasUsed)),\n nonce: BNToHex(new BN(txMeta.nonce)),\n to: txMeta.to,\n value: BNToHex(new BN(txMeta.value)),\n },\n type: TransactionType.incoming,\n verifiedOnBlockchain: false,\n };\n }\n}\n"],"mappings":"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","names":[]}
@@ -349,4 +349,4 @@ export {
349
349
  getSimulationData,
350
350
  getEvents
351
351
  };
352
- //# sourceMappingURL=chunk-AHSDUIMT.mjs.map
352
+ //# sourceMappingURL=chunk-EVL6KODQ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/simulation.ts"],"sourcesContent":["import type { Fragment, LogDescription, Result } from '@ethersproject/abi';\nimport { Interface } from '@ethersproject/abi';\nimport { hexToBN, toHex } from '@metamask/controller-utils';\nimport { abiERC20, abiERC721, abiERC1155 } from '@metamask/metamask-eth-abis';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\n\nimport {\n ABI_SIMULATION_ERC20_WRAPPED,\n ABI_SIMULATION_ERC721_LEGACY,\n} from '../constants';\nimport {\n SimulationError,\n SimulationInvalidResponseError,\n SimulationRevertedError,\n} from '../errors';\nimport { projectLogger } from '../logger';\nimport type {\n SimulationBalanceChange,\n SimulationData,\n SimulationTokenBalanceChange,\n SimulationToken,\n} from '../types';\nimport { SimulationTokenStandard } from '../types';\nimport { simulateTransactions } from './simulation-api';\nimport type {\n SimulationResponseLog,\n SimulationRequestTransaction,\n SimulationResponse,\n SimulationResponseCallTrace,\n SimulationResponseTransaction,\n} from './simulation-api';\n\nexport enum SupportedToken {\n ERC20 = 'erc20',\n ERC721 = 'erc721',\n ERC1155 = 'erc1155',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ERC20_WRAPPED = 'erc20Wrapped',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n ERC721_LEGACY = 'erc721Legacy',\n}\n\ntype ABI = Fragment[];\n\nexport type GetSimulationDataRequest = {\n chainId: Hex;\n from: Hex;\n to?: Hex;\n value?: Hex;\n data?: Hex;\n};\n\ntype ParsedEvent = {\n contractAddress: Hex;\n tokenStandard: SimulationTokenStandard;\n name: string;\n args: Record<string, Hex | Hex[]>;\n abi: ABI;\n};\n\nconst log = createModuleLogger(projectLogger, 'simulation');\n\nconst SUPPORTED_EVENTS = [\n 'Transfer',\n 'TransferSingle',\n 'TransferBatch',\n 'Deposit',\n 'Withdrawal',\n];\n\nconst SUPPORTED_TOKEN_ABIS = {\n [SupportedToken.ERC20]: {\n abi: abiERC20,\n standard: SimulationTokenStandard.erc20,\n },\n [SupportedToken.ERC721]: {\n abi: abiERC721,\n standard: SimulationTokenStandard.erc721,\n },\n [SupportedToken.ERC1155]: {\n abi: abiERC1155,\n standard: SimulationTokenStandard.erc1155,\n },\n [SupportedToken.ERC20_WRAPPED]: {\n abi: ABI_SIMULATION_ERC20_WRAPPED,\n standard: SimulationTokenStandard.erc20,\n },\n [SupportedToken.ERC721_LEGACY]: {\n abi: ABI_SIMULATION_ERC721_LEGACY,\n standard: SimulationTokenStandard.erc721,\n },\n};\n\nconst REVERTED_ERRORS = ['execution reverted', 'insufficient funds for gas'];\n\ntype BalanceTransactionMap = Map<SimulationToken, SimulationRequestTransaction>;\n\n/**\n * Generate simulation data for a transaction.\n * @param request - The transaction to simulate.\n * @param request.chainId - The chain ID of the transaction.\n * @param request.from - The sender of the transaction.\n * @param request.to - The recipient of the transaction.\n * @param request.value - The value of the transaction.\n * @param request.data - The data of the transaction.\n * @returns The simulation data.\n */\nexport async function getSimulationData(\n request: GetSimulationDataRequest,\n): Promise<SimulationData> {\n const { chainId, from, to, value, data } = request;\n\n log('Getting simulation data', request);\n\n try {\n const response = await simulateTransactions(chainId, {\n transactions: [\n {\n data,\n from,\n maxFeePerGas: '0x0',\n maxPriorityFeePerGas: '0x0',\n to,\n value,\n },\n ],\n withCallTrace: true,\n withLogs: true,\n });\n\n const transactionError = response.transactions?.[0]?.error;\n\n if (transactionError) {\n throw new SimulationError(transactionError);\n }\n\n const nativeBalanceChange = getNativeBalanceChange(request.from, response);\n const events = getEvents(response);\n\n log('Parsed events', events);\n\n const tokenBalanceChanges = await getTokenBalanceChanges(request, events);\n\n return {\n nativeBalanceChange,\n tokenBalanceChanges,\n };\n } catch (error) {\n log('Failed to get simulation data', error, request);\n\n let simulationError = error as SimulationError;\n\n if (\n REVERTED_ERRORS.some((revertErrorMessage) =>\n simulationError.message?.includes(revertErrorMessage),\n )\n ) {\n simulationError = new SimulationRevertedError();\n }\n\n const { code, message } = simulationError;\n\n return {\n tokenBalanceChanges: [],\n error: {\n code,\n message,\n },\n };\n }\n}\n\n/**\n * Extract the native balance change from a simulation response.\n * @param userAddress - The user's account address.\n * @param response - The simulation response.\n * @returns The native balance change or undefined if unchanged.\n */\nfunction getNativeBalanceChange(\n userAddress: Hex,\n response: SimulationResponse,\n): SimulationBalanceChange | undefined {\n const transactionResponse = response.transactions[0];\n\n /* istanbul ignore next */\n if (!transactionResponse) {\n return undefined;\n }\n\n const { stateDiff } = transactionResponse;\n const previousBalance = stateDiff?.pre?.[userAddress]?.balance;\n const newBalance = stateDiff?.post?.[userAddress]?.balance;\n\n if (!previousBalance || !newBalance) {\n return undefined;\n }\n\n return getSimulationBalanceChange(previousBalance, newBalance);\n}\n\n/**\n * Extract events from a simulation response.\n * @param response - The simulation response.\n * @returns The parsed events.\n */\nexport function getEvents(response: SimulationResponse): ParsedEvent[] {\n /* istanbul ignore next */\n const logs = extractLogs(\n response.transactions[0]?.callTrace ?? ({} as SimulationResponseCallTrace),\n );\n\n log('Extracted logs', logs);\n\n const interfaces = getContractInterfaces();\n\n return logs\n .map((currentLog) => {\n const event = parseLog(currentLog, interfaces);\n\n if (!event) {\n log('Failed to parse log', currentLog);\n return undefined;\n }\n\n /* istanbul ignore next */\n const inputs = event.abi.find((e) => e.name === event.name)?.inputs;\n\n /* istanbul ignore if */\n if (!inputs) {\n log('Failed to find inputs for event', event);\n return undefined;\n }\n\n const args = parseEventArgs(event.args, inputs);\n\n return {\n contractAddress: currentLog.address,\n tokenStandard: event.standard,\n name: event.name,\n args,\n abi: event.abi,\n };\n })\n .filter((e) => e !== undefined) as ParsedEvent[];\n}\n\n/**\n * Parse event arguments using ABI input definitions.\n * @param args - The raw event arguments.\n * @param abiInputs - The ABI input definitions.\n * @returns The parsed event arguments.\n */\nfunction parseEventArgs(\n args: Result,\n abiInputs: { name: string }[],\n): Record<string, Hex | Hex[]> {\n return args.reduce((result, arg, index) => {\n const name = abiInputs[index].name.replace('_', '');\n const value = parseEventArgValue(arg);\n\n result[name] = value;\n\n return result;\n }, {});\n}\n\n/**\n * Parse an event argument value.\n * @param value - The event argument value.\n * @returns The parsed event argument value.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction parseEventArgValue(value: any): Hex | Hex[] {\n if (Array.isArray(value)) {\n return value.map(parseEventArgValue) as Hex[];\n }\n\n return (value.toHexString?.() ?? value).toLowerCase();\n}\n\n/**\n * Generate token balance changes from parsed events.\n * @param request - The transaction that was simulated.\n * @param events - The parsed events.\n * @returns An array of token balance changes.\n */\nasync function getTokenBalanceChanges(\n request: GetSimulationDataRequest,\n events: ParsedEvent[],\n): Promise<SimulationTokenBalanceChange[]> {\n const balanceTxs = getTokenBalanceTransactions(request, events);\n\n log('Generated balance transactions', [...balanceTxs.after.values()]);\n\n const transactions = [\n ...balanceTxs.before.values(),\n request,\n ...balanceTxs.after.values(),\n ];\n\n if (transactions.length === 1) {\n return [];\n }\n\n const response = await simulateTransactions(request.chainId as Hex, {\n transactions,\n });\n\n log('Balance simulation response', response);\n\n if (response.transactions.length !== transactions.length) {\n throw new SimulationInvalidResponseError();\n }\n\n let prevBalanceTxIndex = 0;\n return [...balanceTxs.after.keys()]\n .map((token, index) => {\n const previousBalanceCheckSkipped = !balanceTxs.before.get(token);\n const previousBalance = previousBalanceCheckSkipped\n ? '0x0'\n : getValueFromBalanceTransaction(\n request.from,\n token,\n // eslint-disable-next-line no-plusplus\n response.transactions[prevBalanceTxIndex++],\n );\n\n const newBalance = getValueFromBalanceTransaction(\n request.from,\n token,\n response.transactions[index + balanceTxs.before.size + 1],\n );\n\n const balanceChange = getSimulationBalanceChange(\n previousBalance,\n newBalance,\n );\n\n if (!balanceChange) {\n return undefined;\n }\n\n return {\n ...token,\n ...balanceChange,\n };\n })\n .filter((change) => change !== undefined) as SimulationTokenBalanceChange[];\n}\n\n/**\n * Generate transactions to check token balances.\n * @param request - The transaction that was simulated.\n * @param events - The parsed events.\n * @returns A map of token balance transactions keyed by token.\n */\nfunction getTokenBalanceTransactions(\n request: GetSimulationDataRequest,\n events: ParsedEvent[],\n): {\n before: BalanceTransactionMap;\n after: BalanceTransactionMap;\n} {\n const tokenKeys = new Set();\n const before = new Map();\n const after = new Map();\n\n const userEvents = events.filter(\n (event) =>\n SUPPORTED_EVENTS.includes(event.name) &&\n [event.args.from, event.args.to].includes(request.from),\n );\n\n log('Filtered user events', userEvents);\n\n for (const event of userEvents) {\n const tokenIds = getEventTokenIds(event);\n\n log('Extracted token ids', tokenIds);\n\n for (const tokenId of tokenIds) {\n const simulationToken: SimulationToken = {\n address: event.contractAddress,\n standard: event.tokenStandard,\n id: tokenId,\n };\n\n const tokenKey = JSON.stringify(simulationToken);\n\n if (tokenKeys.has(tokenKey)) {\n log(\n 'Ignoring additional event with same contract and token ID',\n simulationToken,\n );\n continue;\n }\n\n tokenKeys.add(tokenKey);\n\n const data = getBalanceTransactionData(\n event.tokenStandard,\n request.from,\n tokenId,\n );\n\n const transaction: SimulationRequestTransaction = {\n from: request.from,\n to: event.contractAddress,\n data,\n };\n\n if (skipPriorBalanceCheck(event)) {\n after.set(simulationToken, transaction);\n } else {\n before.set(simulationToken, transaction);\n after.set(simulationToken, transaction);\n }\n }\n }\n\n return { before, after };\n}\n\n/**\n * Check if an event needs to check the previous balance.\n * @param event - The parsed event.\n * @returns True if the prior balance check should be skipped.\n */\nfunction skipPriorBalanceCheck(event: ParsedEvent): boolean {\n // In the case of an NFT mint, we cannot check the NFT owner before the mint\n // as the balance check transaction would revert.\n return (\n event.name === 'Transfer' &&\n event.tokenStandard === SimulationTokenStandard.erc721 &&\n parseInt(event.args.from as string, 16) === 0\n );\n}\n\n/**\n * Extract token IDs from a parsed event.\n * @param event - The parsed event.\n * @returns An array of token IDs.\n */\nfunction getEventTokenIds(event: ParsedEvent): (Hex | undefined)[] {\n if (event.tokenStandard === SimulationTokenStandard.erc721) {\n return [event.args.tokenId as Hex];\n }\n\n if (\n event.tokenStandard === SimulationTokenStandard.erc1155 &&\n event.name === 'TransferSingle'\n ) {\n return [event.args.id as Hex];\n }\n\n if (\n event.tokenStandard === SimulationTokenStandard.erc1155 &&\n event.name === 'TransferBatch'\n ) {\n return event.args.ids as Hex[];\n }\n\n // ERC-20 does not have a token ID so default to undefined.\n return [undefined];\n}\n\n/**\n * Extract the value from a balance transaction response.\n * @param from - The address to check the balance of.\n * @param token - The token to check the balance of.\n * @param response - The balance transaction response.\n * @returns The value of the balance transaction.\n */\nfunction getValueFromBalanceTransaction(\n from: Hex,\n token: SimulationToken,\n response: SimulationResponseTransaction,\n): Hex {\n const normalizedReturn = normalizeReturnValue(response.return);\n\n if (token.standard === SimulationTokenStandard.erc721) {\n return normalizedReturn === from ? '0x1' : '0x0';\n }\n\n return normalizedReturn;\n}\n\n/**\n * Generate the balance transaction data for a token.\n * @param tokenStandard - The token standard.\n * @param from - The address to check the balance of.\n * @param tokenId - The token ID to check the balance of.\n * @returns The balance transaction data.\n */\nfunction getBalanceTransactionData(\n tokenStandard: SimulationTokenStandard,\n from: Hex,\n tokenId?: Hex,\n): Hex {\n switch (tokenStandard) {\n case SimulationTokenStandard.erc721:\n return new Interface(abiERC721).encodeFunctionData('ownerOf', [\n tokenId,\n ]) as Hex;\n\n case SimulationTokenStandard.erc1155:\n return new Interface(abiERC1155).encodeFunctionData('balanceOf', [\n from,\n tokenId,\n ]) as Hex;\n\n default:\n return new Interface(abiERC20).encodeFunctionData('balanceOf', [\n from,\n ]) as Hex;\n }\n}\n\n/**\n * Parse a raw event log using known ABIs.\n * @param eventLog - The raw event log.\n * @param interfaces - The contract interfaces.\n * @returns The parsed event log or undefined if it could not be parsed.\n */\nfunction parseLog(\n eventLog: SimulationResponseLog,\n interfaces: Map<SupportedToken, Interface>,\n):\n | (LogDescription & { abi: ABI; standard: SimulationTokenStandard })\n | undefined {\n const supportedTokens = Object.values(SupportedToken);\n\n for (const token of supportedTokens) {\n try {\n const contractInterface = interfaces.get(token) as Interface;\n const { abi, standard } = SUPPORTED_TOKEN_ABIS[token];\n\n return {\n ...contractInterface.parseLog(eventLog),\n abi,\n standard,\n };\n } catch (e) {\n continue;\n }\n }\n\n return undefined;\n}\n\n/**\n * Extract all logs from a call trace tree.\n * @param call - The root call trace.\n * @returns An array of logs.\n */\nfunction extractLogs(\n call: SimulationResponseCallTrace,\n): SimulationResponseLog[] {\n /* istanbul ignore next */\n const logs = call.logs ?? [];\n\n /* istanbul ignore next */\n const nestedCalls = call.calls ?? [];\n\n return [\n ...logs,\n ...nestedCalls.map((nestedCall) => extractLogs(nestedCall)).flat(),\n ];\n}\n\n/**\n * Generate balance change data from previous and new balances.\n * @param previousBalance - The previous balance.\n * @param newBalance - The new balance.\n * @returns The balance change data or undefined if unchanged.\n */\nfunction getSimulationBalanceChange(\n previousBalance: Hex,\n newBalance: Hex,\n): SimulationBalanceChange | undefined {\n const differenceBN = hexToBN(newBalance).sub(hexToBN(previousBalance));\n const isDecrease = differenceBN.isNeg();\n const difference = toHex(differenceBN.abs());\n\n if (differenceBN.isZero()) {\n log('Balance change is zero');\n return undefined;\n }\n\n return {\n previousBalance,\n newBalance,\n difference,\n isDecrease,\n };\n}\n\n/**\n * Normalize a return value.\n * @param value - The return value to normalize.\n * @returns The normalized return value.\n */\nfunction normalizeReturnValue(value: Hex): Hex {\n return toHex(hexToBN(value));\n}\n\n/**\n * Get the contract interfaces for all supported tokens.\n * @returns A map of supported tokens to their contract interfaces.\n */\nfunction getContractInterfaces(): Map<SupportedToken, Interface> {\n const supportedTokens = Object.values(SupportedToken);\n\n return new Map(\n supportedTokens.map((tokenType) => {\n const { abi } = SUPPORTED_TOKEN_ABIS[tokenType];\n const contractInterface = new Interface(abi);\n return [tokenType, contractInterface];\n }),\n );\n}\n"],"mappings":"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","names":["SupportedToken"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  validateIfTransactionUnapproved
3
- } from "./chunk-J56A7UCK.mjs";
3
+ } from "./chunk-Q56I5ONX.mjs";
4
4
  import {
5
5
  CHAIN_IDS
6
6
  } from "./chunk-O6ZZVIFH.mjs";
@@ -254,4 +254,4 @@ export {
254
254
  updateSwapsTransaction,
255
255
  updatePostTransactionBalance
256
256
  };
257
- //# sourceMappingURL=chunk-IJ5GUKRO.mjs.map
257
+ //# sourceMappingURL=chunk-GNAL5HC2.mjs.map