@metamask/transaction-controller 42.1.0 → 44.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 (38) hide show
  1. package/CHANGELOG.md +21 -1
  2. package/dist/TransactionController.cjs +1 -2
  3. package/dist/TransactionController.cjs.map +1 -1
  4. package/dist/TransactionController.d.cts +2 -62
  5. package/dist/TransactionController.d.cts.map +1 -1
  6. package/dist/TransactionController.d.mts +2 -62
  7. package/dist/TransactionController.d.mts.map +1 -1
  8. package/dist/TransactionController.mjs +1 -2
  9. package/dist/TransactionController.mjs.map +1 -1
  10. package/dist/helpers/GasFeePoller.cjs +1 -1
  11. package/dist/helpers/GasFeePoller.cjs.map +1 -1
  12. package/dist/helpers/GasFeePoller.mjs +1 -1
  13. package/dist/helpers/GasFeePoller.mjs.map +1 -1
  14. package/dist/helpers/IncomingTransactionHelper.cjs +1 -1
  15. package/dist/helpers/IncomingTransactionHelper.cjs.map +1 -1
  16. package/dist/helpers/IncomingTransactionHelper.mjs +1 -1
  17. package/dist/helpers/IncomingTransactionHelper.mjs.map +1 -1
  18. package/dist/helpers/MethodDataHelper.cjs +1 -1
  19. package/dist/helpers/MethodDataHelper.cjs.map +1 -1
  20. package/dist/helpers/MethodDataHelper.mjs +1 -1
  21. package/dist/helpers/MethodDataHelper.mjs.map +1 -1
  22. package/dist/helpers/PendingTransactionTracker.cjs +1 -1
  23. package/dist/helpers/PendingTransactionTracker.cjs.map +1 -1
  24. package/dist/helpers/PendingTransactionTracker.mjs +1 -1
  25. package/dist/helpers/PendingTransactionTracker.mjs.map +1 -1
  26. package/dist/types.cjs.map +1 -1
  27. package/dist/types.d.cts +4 -0
  28. package/dist/types.d.cts.map +1 -1
  29. package/dist/types.d.mts +4 -0
  30. package/dist/types.d.mts.map +1 -1
  31. package/dist/types.mjs.map +1 -1
  32. package/dist/utils/gas.cjs +6 -5
  33. package/dist/utils/gas.cjs.map +1 -1
  34. package/dist/utils/gas.d.cts.map +1 -1
  35. package/dist/utils/gas.d.mts.map +1 -1
  36. package/dist/utils/gas.mjs +6 -5
  37. package/dist/utils/gas.mjs.map +1 -1
  38. package/package.json +6 -6
@@ -19,7 +19,7 @@ exports.GasFeePoller = void 0;
19
19
  const eth_query_1 = __importDefault(require("@metamask/eth-query"));
20
20
  const utils_1 = require("@metamask/utils");
21
21
  // This package purposefully relies on Node's EventEmitter module.
22
- // eslint-disable-next-line import/no-nodejs-modules
22
+ // eslint-disable-next-line import-x/no-nodejs-modules
23
23
  const events_1 = __importDefault(require("events"));
24
24
  const logger_1 = require("../logger.cjs");
25
25
  const types_1 = require("../types.cjs");
@@ -1 +1 @@
1
- {"version":3,"file":"GasFeePoller.cjs","sourceRoot":"","sources":["../../src/helpers/GasFeePoller.ts"],"names":[],"mappings":"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","sourcesContent":["import EthQuery from '@metamask/eth-query';\nimport type {\n FetchGasFeeEstimateOptions,\n GasFeeState,\n} from '@metamask/gas-fee-controller';\nimport type { NetworkClientId, Provider } from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { projectLogger } from '../logger';\nimport type {\n GasFeeEstimates,\n GasFeeFlow,\n GasFeeFlowRequest,\n Layer1GasFeeFlow,\n} from '../types';\nimport { TransactionStatus, type TransactionMeta } from '../types';\nimport { getGasFeeFlow } from '../utils/gas-flow';\nimport { getTransactionLayer1GasFee } from '../utils/layer1-gas-fee-flow';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-poller');\n\nconst INTERVAL_MILLISECONDS = 10000;\n\n/**\n * Automatically polls and updates suggested gas fees on unapproved transactions.\n */\nexport class GasFeePoller {\n hub: EventEmitter = new EventEmitter();\n\n #findNetworkClientIdByChainId: (chainId: Hex) => NetworkClientId | undefined;\n\n #gasFeeFlows: GasFeeFlow[];\n\n #getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n\n #getProvider: (networkClientId: NetworkClientId) => Provider;\n\n #getTransactions: () => TransactionMeta[];\n\n #layer1GasFeeFlows: Layer1GasFeeFlow[];\n\n #timeout: ReturnType<typeof setTimeout> | undefined;\n\n #running = false;\n\n /**\n * Constructs a new instance of the GasFeePoller.\n * @param options - The options for this instance.\n * @param options.findNetworkClientIdByChainId - Callback to find the network client ID by chain ID.\n * @param options.gasFeeFlows - The gas fee flows to use to obtain suitable gas fees.\n * @param options.getGasFeeControllerEstimates - Callback to obtain the default fee estimates.\n * @param options.getProvider - Callback to obtain a provider instance.\n * @param options.getTransactions - Callback to obtain the transaction data.\n * @param options.layer1GasFeeFlows - The layer 1 gas fee flows to use to obtain suitable layer 1 gas fees.\n * @param options.onStateChange - Callback to register a listener for controller state changes.\n */\n constructor({\n findNetworkClientIdByChainId,\n gasFeeFlows,\n getGasFeeControllerEstimates,\n getProvider,\n getTransactions,\n layer1GasFeeFlows,\n onStateChange,\n }: {\n findNetworkClientIdByChainId: (chainId: Hex) => NetworkClientId | undefined;\n gasFeeFlows: GasFeeFlow[];\n getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n getProvider: (networkClientId: NetworkClientId) => Provider;\n getTransactions: () => TransactionMeta[];\n layer1GasFeeFlows: Layer1GasFeeFlow[];\n onStateChange: (listener: () => void) => void;\n }) {\n this.#findNetworkClientIdByChainId = findNetworkClientIdByChainId;\n this.#gasFeeFlows = gasFeeFlows;\n this.#layer1GasFeeFlows = layer1GasFeeFlows;\n this.#getGasFeeControllerEstimates = getGasFeeControllerEstimates;\n this.#getProvider = getProvider;\n this.#getTransactions = getTransactions;\n\n onStateChange(() => {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n if (unapprovedTransactions.length) {\n this.#start();\n } else {\n this.#stop();\n }\n });\n }\n\n #start() {\n if (this.#running) {\n return;\n }\n\n // Intentionally not awaiting since this starts the timeout chain.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#onTimeout();\n\n this.#running = true;\n\n log('Started polling');\n }\n\n #stop() {\n if (!this.#running) {\n return;\n }\n\n clearTimeout(this.#timeout);\n\n this.#timeout = undefined;\n this.#running = false;\n\n log('Stopped polling');\n }\n\n async #onTimeout() {\n await this.#updateUnapprovedTransactions();\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeout = setTimeout(() => this.#onTimeout(), INTERVAL_MILLISECONDS);\n }\n\n async #updateUnapprovedTransactions() {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n if (!unapprovedTransactions.length) {\n return;\n }\n\n log('Found unapproved transactions', unapprovedTransactions.length);\n\n const gasFeeControllerDataByChainId = await this.#getGasFeeControllerData(\n unapprovedTransactions,\n );\n\n log('Retrieved gas fee controller data', gasFeeControllerDataByChainId);\n\n await Promise.all(\n unapprovedTransactions.flatMap((tx) => {\n const { chainId } = tx;\n\n const gasFeeControllerData = gasFeeControllerDataByChainId.get(\n chainId,\n ) as GasFeeState;\n\n return this.#updateUnapprovedTransaction(tx, gasFeeControllerData);\n }),\n );\n }\n\n async #updateUnapprovedTransaction(\n transactionMeta: TransactionMeta,\n gasFeeControllerData: GasFeeState,\n ) {\n const { id } = transactionMeta;\n\n const [gasFeeEstimatesResponse, layer1GasFee] = await Promise.all([\n this.#updateTransactionGasFeeEstimates(\n transactionMeta,\n gasFeeControllerData,\n ),\n this.#updateTransactionLayer1GasFee(transactionMeta),\n ]);\n\n if (!gasFeeEstimatesResponse && !layer1GasFee) {\n return;\n }\n\n this.hub.emit('transaction-updated', {\n transactionId: id,\n gasFeeEstimates: gasFeeEstimatesResponse?.gasFeeEstimates,\n gasFeeEstimatesLoaded: gasFeeEstimatesResponse?.gasFeeEstimatesLoaded,\n layer1GasFee,\n });\n }\n\n async #updateTransactionGasFeeEstimates(\n transactionMeta: TransactionMeta,\n gasFeeControllerData: GasFeeState,\n ): Promise<\n | { gasFeeEstimates?: GasFeeEstimates; gasFeeEstimatesLoaded: boolean }\n | undefined\n > {\n const { networkClientId } = transactionMeta;\n\n const ethQuery = new EthQuery(this.#getProvider(networkClientId));\n const gasFeeFlow = getGasFeeFlow(transactionMeta, this.#gasFeeFlows);\n\n if (gasFeeFlow) {\n log(\n 'Found gas fee flow',\n gasFeeFlow.constructor.name,\n transactionMeta.id,\n );\n }\n\n const request: GasFeeFlowRequest = {\n ethQuery,\n gasFeeControllerData,\n transactionMeta,\n };\n\n let gasFeeEstimates: GasFeeEstimates | undefined;\n\n if (gasFeeFlow) {\n try {\n const response = await gasFeeFlow.getGasFees(request);\n gasFeeEstimates = response.estimates;\n } catch (error) {\n log('Failed to get suggested gas fees', transactionMeta.id, error);\n }\n }\n\n if (!gasFeeEstimates && transactionMeta.gasFeeEstimatesLoaded) {\n return undefined;\n }\n\n log('Updated gas fee estimates', {\n gasFeeEstimates,\n transaction: transactionMeta.id,\n });\n\n return { gasFeeEstimates, gasFeeEstimatesLoaded: true };\n }\n\n async #updateTransactionLayer1GasFee(\n transactionMeta: TransactionMeta,\n ): Promise<Hex | undefined> {\n const { networkClientId } = transactionMeta;\n const provider = this.#getProvider(networkClientId);\n\n const layer1GasFee = await getTransactionLayer1GasFee({\n layer1GasFeeFlows: this.#layer1GasFeeFlows,\n provider,\n transactionMeta,\n });\n\n if (layer1GasFee) {\n log('Updated layer 1 gas fee', layer1GasFee, transactionMeta.id);\n }\n\n return layer1GasFee;\n }\n\n #getUnapprovedTransactions() {\n return this.#getTransactions().filter(\n (tx) => tx.status === TransactionStatus.unapproved,\n );\n }\n\n async #getGasFeeControllerData(\n transactions: TransactionMeta[],\n ): Promise<Map<string, GasFeeState>> {\n const networkClientIdsByChainId = new Map<Hex, NetworkClientId>();\n\n for (const transaction of transactions) {\n const { chainId, networkClientId: transactionNetworkClientId } =\n transaction;\n\n if (networkClientIdsByChainId.has(chainId)) {\n continue;\n }\n\n const networkClientId =\n transactionNetworkClientId ??\n (this.#findNetworkClientIdByChainId(chainId) as string);\n\n networkClientIdsByChainId.set(chainId, networkClientId);\n }\n\n log('Extracted network client IDs by chain ID', networkClientIdsByChainId);\n\n const entryPromises = Array.from(networkClientIdsByChainId.entries()).map(\n async ([chainId, networkClientId]) => {\n return [\n chainId,\n await this.#getGasFeeControllerEstimates({ networkClientId }),\n ] as const;\n },\n );\n\n return new Map(await Promise.all(entryPromises));\n }\n}\n"]}
1
+ {"version":3,"file":"GasFeePoller.cjs","sourceRoot":"","sources":["../../src/helpers/GasFeePoller.ts"],"names":[],"mappings":"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","sourcesContent":["import EthQuery from '@metamask/eth-query';\nimport type {\n FetchGasFeeEstimateOptions,\n GasFeeState,\n} from '@metamask/gas-fee-controller';\nimport type { NetworkClientId, Provider } from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { projectLogger } from '../logger';\nimport type {\n GasFeeEstimates,\n GasFeeFlow,\n GasFeeFlowRequest,\n Layer1GasFeeFlow,\n} from '../types';\nimport { TransactionStatus, type TransactionMeta } from '../types';\nimport { getGasFeeFlow } from '../utils/gas-flow';\nimport { getTransactionLayer1GasFee } from '../utils/layer1-gas-fee-flow';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-poller');\n\nconst INTERVAL_MILLISECONDS = 10000;\n\n/**\n * Automatically polls and updates suggested gas fees on unapproved transactions.\n */\nexport class GasFeePoller {\n hub: EventEmitter = new EventEmitter();\n\n #findNetworkClientIdByChainId: (chainId: Hex) => NetworkClientId | undefined;\n\n #gasFeeFlows: GasFeeFlow[];\n\n #getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n\n #getProvider: (networkClientId: NetworkClientId) => Provider;\n\n #getTransactions: () => TransactionMeta[];\n\n #layer1GasFeeFlows: Layer1GasFeeFlow[];\n\n #timeout: ReturnType<typeof setTimeout> | undefined;\n\n #running = false;\n\n /**\n * Constructs a new instance of the GasFeePoller.\n * @param options - The options for this instance.\n * @param options.findNetworkClientIdByChainId - Callback to find the network client ID by chain ID.\n * @param options.gasFeeFlows - The gas fee flows to use to obtain suitable gas fees.\n * @param options.getGasFeeControllerEstimates - Callback to obtain the default fee estimates.\n * @param options.getProvider - Callback to obtain a provider instance.\n * @param options.getTransactions - Callback to obtain the transaction data.\n * @param options.layer1GasFeeFlows - The layer 1 gas fee flows to use to obtain suitable layer 1 gas fees.\n * @param options.onStateChange - Callback to register a listener for controller state changes.\n */\n constructor({\n findNetworkClientIdByChainId,\n gasFeeFlows,\n getGasFeeControllerEstimates,\n getProvider,\n getTransactions,\n layer1GasFeeFlows,\n onStateChange,\n }: {\n findNetworkClientIdByChainId: (chainId: Hex) => NetworkClientId | undefined;\n gasFeeFlows: GasFeeFlow[];\n getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n getProvider: (networkClientId: NetworkClientId) => Provider;\n getTransactions: () => TransactionMeta[];\n layer1GasFeeFlows: Layer1GasFeeFlow[];\n onStateChange: (listener: () => void) => void;\n }) {\n this.#findNetworkClientIdByChainId = findNetworkClientIdByChainId;\n this.#gasFeeFlows = gasFeeFlows;\n this.#layer1GasFeeFlows = layer1GasFeeFlows;\n this.#getGasFeeControllerEstimates = getGasFeeControllerEstimates;\n this.#getProvider = getProvider;\n this.#getTransactions = getTransactions;\n\n onStateChange(() => {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n if (unapprovedTransactions.length) {\n this.#start();\n } else {\n this.#stop();\n }\n });\n }\n\n #start() {\n if (this.#running) {\n return;\n }\n\n // Intentionally not awaiting since this starts the timeout chain.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#onTimeout();\n\n this.#running = true;\n\n log('Started polling');\n }\n\n #stop() {\n if (!this.#running) {\n return;\n }\n\n clearTimeout(this.#timeout);\n\n this.#timeout = undefined;\n this.#running = false;\n\n log('Stopped polling');\n }\n\n async #onTimeout() {\n await this.#updateUnapprovedTransactions();\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeout = setTimeout(() => this.#onTimeout(), INTERVAL_MILLISECONDS);\n }\n\n async #updateUnapprovedTransactions() {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n if (!unapprovedTransactions.length) {\n return;\n }\n\n log('Found unapproved transactions', unapprovedTransactions.length);\n\n const gasFeeControllerDataByChainId = await this.#getGasFeeControllerData(\n unapprovedTransactions,\n );\n\n log('Retrieved gas fee controller data', gasFeeControllerDataByChainId);\n\n await Promise.all(\n unapprovedTransactions.flatMap((tx) => {\n const { chainId } = tx;\n\n const gasFeeControllerData = gasFeeControllerDataByChainId.get(\n chainId,\n ) as GasFeeState;\n\n return this.#updateUnapprovedTransaction(tx, gasFeeControllerData);\n }),\n );\n }\n\n async #updateUnapprovedTransaction(\n transactionMeta: TransactionMeta,\n gasFeeControllerData: GasFeeState,\n ) {\n const { id } = transactionMeta;\n\n const [gasFeeEstimatesResponse, layer1GasFee] = await Promise.all([\n this.#updateTransactionGasFeeEstimates(\n transactionMeta,\n gasFeeControllerData,\n ),\n this.#updateTransactionLayer1GasFee(transactionMeta),\n ]);\n\n if (!gasFeeEstimatesResponse && !layer1GasFee) {\n return;\n }\n\n this.hub.emit('transaction-updated', {\n transactionId: id,\n gasFeeEstimates: gasFeeEstimatesResponse?.gasFeeEstimates,\n gasFeeEstimatesLoaded: gasFeeEstimatesResponse?.gasFeeEstimatesLoaded,\n layer1GasFee,\n });\n }\n\n async #updateTransactionGasFeeEstimates(\n transactionMeta: TransactionMeta,\n gasFeeControllerData: GasFeeState,\n ): Promise<\n | { gasFeeEstimates?: GasFeeEstimates; gasFeeEstimatesLoaded: boolean }\n | undefined\n > {\n const { networkClientId } = transactionMeta;\n\n const ethQuery = new EthQuery(this.#getProvider(networkClientId));\n const gasFeeFlow = getGasFeeFlow(transactionMeta, this.#gasFeeFlows);\n\n if (gasFeeFlow) {\n log(\n 'Found gas fee flow',\n gasFeeFlow.constructor.name,\n transactionMeta.id,\n );\n }\n\n const request: GasFeeFlowRequest = {\n ethQuery,\n gasFeeControllerData,\n transactionMeta,\n };\n\n let gasFeeEstimates: GasFeeEstimates | undefined;\n\n if (gasFeeFlow) {\n try {\n const response = await gasFeeFlow.getGasFees(request);\n gasFeeEstimates = response.estimates;\n } catch (error) {\n log('Failed to get suggested gas fees', transactionMeta.id, error);\n }\n }\n\n if (!gasFeeEstimates && transactionMeta.gasFeeEstimatesLoaded) {\n return undefined;\n }\n\n log('Updated gas fee estimates', {\n gasFeeEstimates,\n transaction: transactionMeta.id,\n });\n\n return { gasFeeEstimates, gasFeeEstimatesLoaded: true };\n }\n\n async #updateTransactionLayer1GasFee(\n transactionMeta: TransactionMeta,\n ): Promise<Hex | undefined> {\n const { networkClientId } = transactionMeta;\n const provider = this.#getProvider(networkClientId);\n\n const layer1GasFee = await getTransactionLayer1GasFee({\n layer1GasFeeFlows: this.#layer1GasFeeFlows,\n provider,\n transactionMeta,\n });\n\n if (layer1GasFee) {\n log('Updated layer 1 gas fee', layer1GasFee, transactionMeta.id);\n }\n\n return layer1GasFee;\n }\n\n #getUnapprovedTransactions() {\n return this.#getTransactions().filter(\n (tx) => tx.status === TransactionStatus.unapproved,\n );\n }\n\n async #getGasFeeControllerData(\n transactions: TransactionMeta[],\n ): Promise<Map<string, GasFeeState>> {\n const networkClientIdsByChainId = new Map<Hex, NetworkClientId>();\n\n for (const transaction of transactions) {\n const { chainId, networkClientId: transactionNetworkClientId } =\n transaction;\n\n if (networkClientIdsByChainId.has(chainId)) {\n continue;\n }\n\n const networkClientId =\n transactionNetworkClientId ??\n (this.#findNetworkClientIdByChainId(chainId) as string);\n\n networkClientIdsByChainId.set(chainId, networkClientId);\n }\n\n log('Extracted network client IDs by chain ID', networkClientIdsByChainId);\n\n const entryPromises = Array.from(networkClientIdsByChainId.entries()).map(\n async ([chainId, networkClientId]) => {\n return [\n chainId,\n await this.#getGasFeeControllerEstimates({ networkClientId }),\n ] as const;\n },\n );\n\n return new Map(await Promise.all(entryPromises));\n }\n}\n"]}
@@ -20,7 +20,7 @@ import $EthQuery from "@metamask/eth-query";
20
20
  const EthQuery = $importDefault($EthQuery);
21
21
  import { createModuleLogger } from "@metamask/utils";
22
22
  // This package purposefully relies on Node's EventEmitter module.
23
- // eslint-disable-next-line import/no-nodejs-modules
23
+ // eslint-disable-next-line import-x/no-nodejs-modules
24
24
  import EventEmitter from "events";
25
25
  import { projectLogger } from "../logger.mjs";
26
26
  import { TransactionStatus } from "../types.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"GasFeePoller.mjs","sourceRoot":"","sources":["../../src/helpers/GasFeePoller.ts"],"names":[],"mappings":"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","sourcesContent":["import EthQuery from '@metamask/eth-query';\nimport type {\n FetchGasFeeEstimateOptions,\n GasFeeState,\n} from '@metamask/gas-fee-controller';\nimport type { NetworkClientId, Provider } from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { projectLogger } from '../logger';\nimport type {\n GasFeeEstimates,\n GasFeeFlow,\n GasFeeFlowRequest,\n Layer1GasFeeFlow,\n} from '../types';\nimport { TransactionStatus, type TransactionMeta } from '../types';\nimport { getGasFeeFlow } from '../utils/gas-flow';\nimport { getTransactionLayer1GasFee } from '../utils/layer1-gas-fee-flow';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-poller');\n\nconst INTERVAL_MILLISECONDS = 10000;\n\n/**\n * Automatically polls and updates suggested gas fees on unapproved transactions.\n */\nexport class GasFeePoller {\n hub: EventEmitter = new EventEmitter();\n\n #findNetworkClientIdByChainId: (chainId: Hex) => NetworkClientId | undefined;\n\n #gasFeeFlows: GasFeeFlow[];\n\n #getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n\n #getProvider: (networkClientId: NetworkClientId) => Provider;\n\n #getTransactions: () => TransactionMeta[];\n\n #layer1GasFeeFlows: Layer1GasFeeFlow[];\n\n #timeout: ReturnType<typeof setTimeout> | undefined;\n\n #running = false;\n\n /**\n * Constructs a new instance of the GasFeePoller.\n * @param options - The options for this instance.\n * @param options.findNetworkClientIdByChainId - Callback to find the network client ID by chain ID.\n * @param options.gasFeeFlows - The gas fee flows to use to obtain suitable gas fees.\n * @param options.getGasFeeControllerEstimates - Callback to obtain the default fee estimates.\n * @param options.getProvider - Callback to obtain a provider instance.\n * @param options.getTransactions - Callback to obtain the transaction data.\n * @param options.layer1GasFeeFlows - The layer 1 gas fee flows to use to obtain suitable layer 1 gas fees.\n * @param options.onStateChange - Callback to register a listener for controller state changes.\n */\n constructor({\n findNetworkClientIdByChainId,\n gasFeeFlows,\n getGasFeeControllerEstimates,\n getProvider,\n getTransactions,\n layer1GasFeeFlows,\n onStateChange,\n }: {\n findNetworkClientIdByChainId: (chainId: Hex) => NetworkClientId | undefined;\n gasFeeFlows: GasFeeFlow[];\n getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n getProvider: (networkClientId: NetworkClientId) => Provider;\n getTransactions: () => TransactionMeta[];\n layer1GasFeeFlows: Layer1GasFeeFlow[];\n onStateChange: (listener: () => void) => void;\n }) {\n this.#findNetworkClientIdByChainId = findNetworkClientIdByChainId;\n this.#gasFeeFlows = gasFeeFlows;\n this.#layer1GasFeeFlows = layer1GasFeeFlows;\n this.#getGasFeeControllerEstimates = getGasFeeControllerEstimates;\n this.#getProvider = getProvider;\n this.#getTransactions = getTransactions;\n\n onStateChange(() => {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n if (unapprovedTransactions.length) {\n this.#start();\n } else {\n this.#stop();\n }\n });\n }\n\n #start() {\n if (this.#running) {\n return;\n }\n\n // Intentionally not awaiting since this starts the timeout chain.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#onTimeout();\n\n this.#running = true;\n\n log('Started polling');\n }\n\n #stop() {\n if (!this.#running) {\n return;\n }\n\n clearTimeout(this.#timeout);\n\n this.#timeout = undefined;\n this.#running = false;\n\n log('Stopped polling');\n }\n\n async #onTimeout() {\n await this.#updateUnapprovedTransactions();\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeout = setTimeout(() => this.#onTimeout(), INTERVAL_MILLISECONDS);\n }\n\n async #updateUnapprovedTransactions() {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n if (!unapprovedTransactions.length) {\n return;\n }\n\n log('Found unapproved transactions', unapprovedTransactions.length);\n\n const gasFeeControllerDataByChainId = await this.#getGasFeeControllerData(\n unapprovedTransactions,\n );\n\n log('Retrieved gas fee controller data', gasFeeControllerDataByChainId);\n\n await Promise.all(\n unapprovedTransactions.flatMap((tx) => {\n const { chainId } = tx;\n\n const gasFeeControllerData = gasFeeControllerDataByChainId.get(\n chainId,\n ) as GasFeeState;\n\n return this.#updateUnapprovedTransaction(tx, gasFeeControllerData);\n }),\n );\n }\n\n async #updateUnapprovedTransaction(\n transactionMeta: TransactionMeta,\n gasFeeControllerData: GasFeeState,\n ) {\n const { id } = transactionMeta;\n\n const [gasFeeEstimatesResponse, layer1GasFee] = await Promise.all([\n this.#updateTransactionGasFeeEstimates(\n transactionMeta,\n gasFeeControllerData,\n ),\n this.#updateTransactionLayer1GasFee(transactionMeta),\n ]);\n\n if (!gasFeeEstimatesResponse && !layer1GasFee) {\n return;\n }\n\n this.hub.emit('transaction-updated', {\n transactionId: id,\n gasFeeEstimates: gasFeeEstimatesResponse?.gasFeeEstimates,\n gasFeeEstimatesLoaded: gasFeeEstimatesResponse?.gasFeeEstimatesLoaded,\n layer1GasFee,\n });\n }\n\n async #updateTransactionGasFeeEstimates(\n transactionMeta: TransactionMeta,\n gasFeeControllerData: GasFeeState,\n ): Promise<\n | { gasFeeEstimates?: GasFeeEstimates; gasFeeEstimatesLoaded: boolean }\n | undefined\n > {\n const { networkClientId } = transactionMeta;\n\n const ethQuery = new EthQuery(this.#getProvider(networkClientId));\n const gasFeeFlow = getGasFeeFlow(transactionMeta, this.#gasFeeFlows);\n\n if (gasFeeFlow) {\n log(\n 'Found gas fee flow',\n gasFeeFlow.constructor.name,\n transactionMeta.id,\n );\n }\n\n const request: GasFeeFlowRequest = {\n ethQuery,\n gasFeeControllerData,\n transactionMeta,\n };\n\n let gasFeeEstimates: GasFeeEstimates | undefined;\n\n if (gasFeeFlow) {\n try {\n const response = await gasFeeFlow.getGasFees(request);\n gasFeeEstimates = response.estimates;\n } catch (error) {\n log('Failed to get suggested gas fees', transactionMeta.id, error);\n }\n }\n\n if (!gasFeeEstimates && transactionMeta.gasFeeEstimatesLoaded) {\n return undefined;\n }\n\n log('Updated gas fee estimates', {\n gasFeeEstimates,\n transaction: transactionMeta.id,\n });\n\n return { gasFeeEstimates, gasFeeEstimatesLoaded: true };\n }\n\n async #updateTransactionLayer1GasFee(\n transactionMeta: TransactionMeta,\n ): Promise<Hex | undefined> {\n const { networkClientId } = transactionMeta;\n const provider = this.#getProvider(networkClientId);\n\n const layer1GasFee = await getTransactionLayer1GasFee({\n layer1GasFeeFlows: this.#layer1GasFeeFlows,\n provider,\n transactionMeta,\n });\n\n if (layer1GasFee) {\n log('Updated layer 1 gas fee', layer1GasFee, transactionMeta.id);\n }\n\n return layer1GasFee;\n }\n\n #getUnapprovedTransactions() {\n return this.#getTransactions().filter(\n (tx) => tx.status === TransactionStatus.unapproved,\n );\n }\n\n async #getGasFeeControllerData(\n transactions: TransactionMeta[],\n ): Promise<Map<string, GasFeeState>> {\n const networkClientIdsByChainId = new Map<Hex, NetworkClientId>();\n\n for (const transaction of transactions) {\n const { chainId, networkClientId: transactionNetworkClientId } =\n transaction;\n\n if (networkClientIdsByChainId.has(chainId)) {\n continue;\n }\n\n const networkClientId =\n transactionNetworkClientId ??\n (this.#findNetworkClientIdByChainId(chainId) as string);\n\n networkClientIdsByChainId.set(chainId, networkClientId);\n }\n\n log('Extracted network client IDs by chain ID', networkClientIdsByChainId);\n\n const entryPromises = Array.from(networkClientIdsByChainId.entries()).map(\n async ([chainId, networkClientId]) => {\n return [\n chainId,\n await this.#getGasFeeControllerEstimates({ networkClientId }),\n ] as const;\n },\n );\n\n return new Map(await Promise.all(entryPromises));\n }\n}\n"]}
1
+ {"version":3,"file":"GasFeePoller.mjs","sourceRoot":"","sources":["../../src/helpers/GasFeePoller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,OAAO,SAAQ,4BAA4B;;AAO3C,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AACrD,kEAAkE;AAClE,sDAAsD;AACtD,OAAO,YAAY,eAAe;AAElC,OAAO,EAAE,aAAa,EAAE,sBAAkB;AAO1C,OAAO,EAAE,iBAAiB,EAAwB,qBAAiB;AACnE,OAAO,EAAE,aAAa,EAAE,8BAA0B;AAClD,OAAO,EAAE,0BAA0B,EAAE,yCAAqC;AAE1E,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;AAEhE,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAEpC;;GAEG;AACH,MAAM,OAAO,YAAY;IAqBvB;;;;;;;;;;OAUG;IACH,YAAY,EACV,4BAA4B,EAC5B,WAAW,EACX,4BAA4B,EAC5B,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,aAAa,GAWd;;QAjDD,QAAG,GAAiB,IAAI,YAAY,EAAE,CAAC;QAEvC,6DAA6E;QAE7E,4CAA2B;QAE3B,6DAE0B;QAE1B,4CAA6D;QAE7D,gDAA0C;QAE1C,kDAAuC;QAEvC,wCAAoD;QAEpD,gCAAW,KAAK,EAAC;QAgCf,uBAAA,IAAI,8CAAiC,4BAA4B,MAAA,CAAC;QAClE,uBAAA,IAAI,6BAAgB,WAAW,MAAA,CAAC;QAChC,uBAAA,IAAI,mCAAsB,iBAAiB,MAAA,CAAC;QAC5C,uBAAA,IAAI,8CAAiC,4BAA4B,MAAA,CAAC;QAClE,uBAAA,IAAI,6BAAgB,WAAW,MAAA,CAAC;QAChC,uBAAA,IAAI,iCAAoB,eAAe,MAAA,CAAC;QAExC,aAAa,CAAC,GAAG,EAAE;YACjB,MAAM,sBAAsB,GAAG,uBAAA,IAAI,wEAA2B,MAA/B,IAAI,CAA6B,CAAC;YAEjE,IAAI,sBAAsB,CAAC,MAAM,EAAE;gBACjC,uBAAA,IAAI,oDAAO,MAAX,IAAI,CAAS,CAAC;aACf;iBAAM;gBACL,uBAAA,IAAI,mDAAM,MAAV,IAAI,CAAQ,CAAC;aACd;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CAqMF;;IAlMG,IAAI,uBAAA,IAAI,6BAAS,EAAE;QACjB,OAAO;KACR;IAED,kEAAkE;IAClE,mEAAmE;IACnE,uBAAA,IAAI,wDAAW,MAAf,IAAI,CAAa,CAAC;IAElB,uBAAA,IAAI,yBAAY,IAAI,MAAA,CAAC;IAErB,GAAG,CAAC,iBAAiB,CAAC,CAAC;AACzB,CAAC;IAGC,IAAI,CAAC,uBAAA,IAAI,6BAAS,EAAE;QAClB,OAAO;KACR;IAED,YAAY,CAAC,uBAAA,IAAI,6BAAS,CAAC,CAAC;IAE5B,uBAAA,IAAI,yBAAY,SAAS,MAAA,CAAC;IAC1B,uBAAA,IAAI,yBAAY,KAAK,MAAA,CAAC;IAEtB,GAAG,CAAC,iBAAiB,CAAC,CAAC;AACzB,CAAC,4BAED,KAAK;IACH,MAAM,uBAAA,IAAI,2EAA8B,MAAlC,IAAI,CAAgC,CAAC;IAE3C,kEAAkE;IAClE,uBAAA,IAAI,yBAAY,UAAU,CAAC,GAAG,EAAE,CAAC,uBAAA,IAAI,wDAAW,MAAf,IAAI,CAAa,EAAE,qBAAqB,CAAC,MAAA,CAAC;AAC7E,CAAC,+CAED,KAAK;IACH,MAAM,sBAAsB,GAAG,uBAAA,IAAI,wEAA2B,MAA/B,IAAI,CAA6B,CAAC;IAEjE,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE;QAClC,OAAO;KACR;IAED,GAAG,CAAC,+BAA+B,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAEpE,MAAM,6BAA6B,GAAG,MAAM,uBAAA,IAAI,sEAAyB,MAA7B,IAAI,EAC9C,sBAAsB,CACvB,CAAC;IAEF,GAAG,CAAC,mCAAmC,EAAE,6BAA6B,CAAC,CAAC;IAExE,MAAM,OAAO,CAAC,GAAG,CACf,sBAAsB,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;QACpC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QAEvB,MAAM,oBAAoB,GAAG,6BAA6B,CAAC,GAAG,CAC5D,OAAO,CACO,CAAC;QAEjB,OAAO,uBAAA,IAAI,0EAA6B,MAAjC,IAAI,EAA8B,EAAE,EAAE,oBAAoB,CAAC,CAAC;IACrE,CAAC,CAAC,CACH,CAAC;AACJ,CAAC,8CAED,KAAK,oDACH,eAAgC,EAChC,oBAAiC;IAEjC,MAAM,EAAE,EAAE,EAAE,GAAG,eAAe,CAAC;IAE/B,MAAM,CAAC,uBAAuB,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAChE,uBAAA,IAAI,+EAAkC,MAAtC,IAAI,EACF,eAAe,EACf,oBAAoB,CACrB;QACD,uBAAA,IAAI,4EAA+B,MAAnC,IAAI,EAAgC,eAAe,CAAC;KACrD,CAAC,CAAC;IAEH,IAAI,CAAC,uBAAuB,IAAI,CAAC,YAAY,EAAE;QAC7C,OAAO;KACR;IAED,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAAE;QACnC,aAAa,EAAE,EAAE;QACjB,eAAe,EAAE,uBAAuB,EAAE,eAAe;QACzD,qBAAqB,EAAE,uBAAuB,EAAE,qBAAqB;QACrE,YAAY;KACb,CAAC,CAAC;AACL,CAAC,mDAED,KAAK,yDACH,eAAgC,EAChC,oBAAiC;IAKjC,MAAM,EAAE,eAAe,EAAE,GAAG,eAAe,CAAC;IAE5C,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,uBAAA,IAAI,iCAAa,MAAjB,IAAI,EAAc,eAAe,CAAC,CAAC,CAAC;IAClE,MAAM,UAAU,GAAG,aAAa,CAAC,eAAe,EAAE,uBAAA,IAAI,iCAAa,CAAC,CAAC;IAErE,IAAI,UAAU,EAAE;QACd,GAAG,CACD,oBAAoB,EACpB,UAAU,CAAC,WAAW,CAAC,IAAI,EAC3B,eAAe,CAAC,EAAE,CACnB,CAAC;KACH;IAED,MAAM,OAAO,GAAsB;QACjC,QAAQ;QACR,oBAAoB;QACpB,eAAe;KAChB,CAAC;IAEF,IAAI,eAA4C,CAAC;IAEjD,IAAI,UAAU,EAAE;QACd,IAAI;YACF,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACtD,eAAe,GAAG,QAAQ,CAAC,SAAS,CAAC;SACtC;QAAC,OAAO,KAAK,EAAE;YACd,GAAG,CAAC,kCAAkC,EAAE,eAAe,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;SACpE;KACF;IAED,IAAI,CAAC,eAAe,IAAI,eAAe,CAAC,qBAAqB,EAAE;QAC7D,OAAO,SAAS,CAAC;KAClB;IAED,GAAG,CAAC,2BAA2B,EAAE;QAC/B,eAAe;QACf,WAAW,EAAE,eAAe,CAAC,EAAE;KAChC,CAAC,CAAC;IAEH,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC;AAC1D,CAAC,gDAED,KAAK,sDACH,eAAgC;IAEhC,MAAM,EAAE,eAAe,EAAE,GAAG,eAAe,CAAC;IAC5C,MAAM,QAAQ,GAAG,uBAAA,IAAI,iCAAa,MAAjB,IAAI,EAAc,eAAe,CAAC,CAAC;IAEpD,MAAM,YAAY,GAAG,MAAM,0BAA0B,CAAC;QACpD,iBAAiB,EAAE,uBAAA,IAAI,uCAAmB;QAC1C,QAAQ;QACR,eAAe;KAChB,CAAC,CAAC;IAEH,IAAI,YAAY,EAAE;QAChB,GAAG,CAAC,yBAAyB,EAAE,YAAY,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC;KAClE;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;IAGC,OAAO,uBAAA,IAAI,qCAAiB,MAArB,IAAI,CAAmB,CAAC,MAAM,CACnC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,KAAK,iBAAiB,CAAC,UAAU,CACnD,CAAC;AACJ,CAAC,0CAED,KAAK,gDACH,YAA+B;IAE/B,MAAM,yBAAyB,GAAG,IAAI,GAAG,EAAwB,CAAC;IAElE,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE;QACtC,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,0BAA0B,EAAE,GAC5D,WAAW,CAAC;QAEd,IAAI,yBAAyB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;YAC1C,SAAS;SACV;QAED,MAAM,eAAe,GACnB,0BAA0B;YACzB,uBAAA,IAAI,kDAA8B,MAAlC,IAAI,EAA+B,OAAO,CAAY,CAAC;QAE1D,yBAAyB,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;KACzD;IAED,GAAG,CAAC,0CAA0C,EAAE,yBAAyB,CAAC,CAAC;IAE3E,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CACvE,KAAK,EAAE,CAAC,OAAO,EAAE,eAAe,CAAC,EAAE,EAAE;QACnC,OAAO;YACL,OAAO;YACP,MAAM,uBAAA,IAAI,kDAA8B,MAAlC,IAAI,EAA+B,EAAE,eAAe,EAAE,CAAC;SACrD,CAAC;IACb,CAAC,CACF,CAAC;IAEF,OAAO,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;AACnD,CAAC","sourcesContent":["import EthQuery from '@metamask/eth-query';\nimport type {\n FetchGasFeeEstimateOptions,\n GasFeeState,\n} from '@metamask/gas-fee-controller';\nimport type { NetworkClientId, Provider } from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { projectLogger } from '../logger';\nimport type {\n GasFeeEstimates,\n GasFeeFlow,\n GasFeeFlowRequest,\n Layer1GasFeeFlow,\n} from '../types';\nimport { TransactionStatus, type TransactionMeta } from '../types';\nimport { getGasFeeFlow } from '../utils/gas-flow';\nimport { getTransactionLayer1GasFee } from '../utils/layer1-gas-fee-flow';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-poller');\n\nconst INTERVAL_MILLISECONDS = 10000;\n\n/**\n * Automatically polls and updates suggested gas fees on unapproved transactions.\n */\nexport class GasFeePoller {\n hub: EventEmitter = new EventEmitter();\n\n #findNetworkClientIdByChainId: (chainId: Hex) => NetworkClientId | undefined;\n\n #gasFeeFlows: GasFeeFlow[];\n\n #getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n\n #getProvider: (networkClientId: NetworkClientId) => Provider;\n\n #getTransactions: () => TransactionMeta[];\n\n #layer1GasFeeFlows: Layer1GasFeeFlow[];\n\n #timeout: ReturnType<typeof setTimeout> | undefined;\n\n #running = false;\n\n /**\n * Constructs a new instance of the GasFeePoller.\n * @param options - The options for this instance.\n * @param options.findNetworkClientIdByChainId - Callback to find the network client ID by chain ID.\n * @param options.gasFeeFlows - The gas fee flows to use to obtain suitable gas fees.\n * @param options.getGasFeeControllerEstimates - Callback to obtain the default fee estimates.\n * @param options.getProvider - Callback to obtain a provider instance.\n * @param options.getTransactions - Callback to obtain the transaction data.\n * @param options.layer1GasFeeFlows - The layer 1 gas fee flows to use to obtain suitable layer 1 gas fees.\n * @param options.onStateChange - Callback to register a listener for controller state changes.\n */\n constructor({\n findNetworkClientIdByChainId,\n gasFeeFlows,\n getGasFeeControllerEstimates,\n getProvider,\n getTransactions,\n layer1GasFeeFlows,\n onStateChange,\n }: {\n findNetworkClientIdByChainId: (chainId: Hex) => NetworkClientId | undefined;\n gasFeeFlows: GasFeeFlow[];\n getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n getProvider: (networkClientId: NetworkClientId) => Provider;\n getTransactions: () => TransactionMeta[];\n layer1GasFeeFlows: Layer1GasFeeFlow[];\n onStateChange: (listener: () => void) => void;\n }) {\n this.#findNetworkClientIdByChainId = findNetworkClientIdByChainId;\n this.#gasFeeFlows = gasFeeFlows;\n this.#layer1GasFeeFlows = layer1GasFeeFlows;\n this.#getGasFeeControllerEstimates = getGasFeeControllerEstimates;\n this.#getProvider = getProvider;\n this.#getTransactions = getTransactions;\n\n onStateChange(() => {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n if (unapprovedTransactions.length) {\n this.#start();\n } else {\n this.#stop();\n }\n });\n }\n\n #start() {\n if (this.#running) {\n return;\n }\n\n // Intentionally not awaiting since this starts the timeout chain.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#onTimeout();\n\n this.#running = true;\n\n log('Started polling');\n }\n\n #stop() {\n if (!this.#running) {\n return;\n }\n\n clearTimeout(this.#timeout);\n\n this.#timeout = undefined;\n this.#running = false;\n\n log('Stopped polling');\n }\n\n async #onTimeout() {\n await this.#updateUnapprovedTransactions();\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeout = setTimeout(() => this.#onTimeout(), INTERVAL_MILLISECONDS);\n }\n\n async #updateUnapprovedTransactions() {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n if (!unapprovedTransactions.length) {\n return;\n }\n\n log('Found unapproved transactions', unapprovedTransactions.length);\n\n const gasFeeControllerDataByChainId = await this.#getGasFeeControllerData(\n unapprovedTransactions,\n );\n\n log('Retrieved gas fee controller data', gasFeeControllerDataByChainId);\n\n await Promise.all(\n unapprovedTransactions.flatMap((tx) => {\n const { chainId } = tx;\n\n const gasFeeControllerData = gasFeeControllerDataByChainId.get(\n chainId,\n ) as GasFeeState;\n\n return this.#updateUnapprovedTransaction(tx, gasFeeControllerData);\n }),\n );\n }\n\n async #updateUnapprovedTransaction(\n transactionMeta: TransactionMeta,\n gasFeeControllerData: GasFeeState,\n ) {\n const { id } = transactionMeta;\n\n const [gasFeeEstimatesResponse, layer1GasFee] = await Promise.all([\n this.#updateTransactionGasFeeEstimates(\n transactionMeta,\n gasFeeControllerData,\n ),\n this.#updateTransactionLayer1GasFee(transactionMeta),\n ]);\n\n if (!gasFeeEstimatesResponse && !layer1GasFee) {\n return;\n }\n\n this.hub.emit('transaction-updated', {\n transactionId: id,\n gasFeeEstimates: gasFeeEstimatesResponse?.gasFeeEstimates,\n gasFeeEstimatesLoaded: gasFeeEstimatesResponse?.gasFeeEstimatesLoaded,\n layer1GasFee,\n });\n }\n\n async #updateTransactionGasFeeEstimates(\n transactionMeta: TransactionMeta,\n gasFeeControllerData: GasFeeState,\n ): Promise<\n | { gasFeeEstimates?: GasFeeEstimates; gasFeeEstimatesLoaded: boolean }\n | undefined\n > {\n const { networkClientId } = transactionMeta;\n\n const ethQuery = new EthQuery(this.#getProvider(networkClientId));\n const gasFeeFlow = getGasFeeFlow(transactionMeta, this.#gasFeeFlows);\n\n if (gasFeeFlow) {\n log(\n 'Found gas fee flow',\n gasFeeFlow.constructor.name,\n transactionMeta.id,\n );\n }\n\n const request: GasFeeFlowRequest = {\n ethQuery,\n gasFeeControllerData,\n transactionMeta,\n };\n\n let gasFeeEstimates: GasFeeEstimates | undefined;\n\n if (gasFeeFlow) {\n try {\n const response = await gasFeeFlow.getGasFees(request);\n gasFeeEstimates = response.estimates;\n } catch (error) {\n log('Failed to get suggested gas fees', transactionMeta.id, error);\n }\n }\n\n if (!gasFeeEstimates && transactionMeta.gasFeeEstimatesLoaded) {\n return undefined;\n }\n\n log('Updated gas fee estimates', {\n gasFeeEstimates,\n transaction: transactionMeta.id,\n });\n\n return { gasFeeEstimates, gasFeeEstimatesLoaded: true };\n }\n\n async #updateTransactionLayer1GasFee(\n transactionMeta: TransactionMeta,\n ): Promise<Hex | undefined> {\n const { networkClientId } = transactionMeta;\n const provider = this.#getProvider(networkClientId);\n\n const layer1GasFee = await getTransactionLayer1GasFee({\n layer1GasFeeFlows: this.#layer1GasFeeFlows,\n provider,\n transactionMeta,\n });\n\n if (layer1GasFee) {\n log('Updated layer 1 gas fee', layer1GasFee, transactionMeta.id);\n }\n\n return layer1GasFee;\n }\n\n #getUnapprovedTransactions() {\n return this.#getTransactions().filter(\n (tx) => tx.status === TransactionStatus.unapproved,\n );\n }\n\n async #getGasFeeControllerData(\n transactions: TransactionMeta[],\n ): Promise<Map<string, GasFeeState>> {\n const networkClientIdsByChainId = new Map<Hex, NetworkClientId>();\n\n for (const transaction of transactions) {\n const { chainId, networkClientId: transactionNetworkClientId } =\n transaction;\n\n if (networkClientIdsByChainId.has(chainId)) {\n continue;\n }\n\n const networkClientId =\n transactionNetworkClientId ??\n (this.#findNetworkClientIdByChainId(chainId) as string);\n\n networkClientIdsByChainId.set(chainId, networkClientId);\n }\n\n log('Extracted network client IDs by chain ID', networkClientIdsByChainId);\n\n const entryPromises = Array.from(networkClientIdsByChainId.entries()).map(\n async ([chainId, networkClientId]) => {\n return [\n chainId,\n await this.#getGasFeeControllerEstimates({ networkClientId }),\n ] as const;\n },\n );\n\n return new Map(await Promise.all(entryPromises));\n }\n}\n"]}
@@ -17,7 +17,7 @@ var _IncomingTransactionHelper_instances, _IncomingTransactionHelper_getCache, _
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.IncomingTransactionHelper = void 0;
19
19
  // This package purposefully relies on Node's EventEmitter module.
20
- // eslint-disable-next-line import/no-nodejs-modules
20
+ // eslint-disable-next-line import-x/no-nodejs-modules
21
21
  const events_1 = __importDefault(require("events"));
22
22
  const logger_1 = require("../logger.cjs");
23
23
  const INTERVAL = 1000 * 30; // 30 Seconds
@@ -1 +1 @@
1
- {"version":3,"file":"IncomingTransactionHelper.cjs","sourceRoot":"","sources":["../../src/helpers/IncomingTransactionHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountsController } from '@metamask/accounts-controller';\nimport type { Hex } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { incomingTransactionsLogger as log } from '../logger';\nimport type { RemoteTransactionSource, TransactionMeta } from '../types';\n\nexport type IncomingTransactionOptions = {\n includeTokenTransfers?: boolean;\n isEnabled?: () => boolean;\n queryEntireHistory?: boolean;\n updateTransactions?: boolean;\n};\n\nconst INTERVAL = 1000 * 30; // 30 Seconds\n\nexport class IncomingTransactionHelper {\n hub: EventEmitter;\n\n #getCache: () => Record<string, unknown>;\n\n #getCurrentAccount: () => ReturnType<\n AccountsController['getSelectedAccount']\n >;\n\n #getChainIds: () => Hex[];\n\n #getLocalTransactions: () => TransactionMeta[];\n\n #includeTokenTransfers?: boolean;\n\n #isEnabled: () => boolean;\n\n #isRunning: boolean;\n\n #queryEntireHistory?: boolean;\n\n #remoteTransactionSource: RemoteTransactionSource;\n\n #timeoutId?: unknown;\n\n #trimTransactions: (transactions: TransactionMeta[]) => TransactionMeta[];\n\n #updateCache: (fn: (cache: Record<string, unknown>) => void) => void;\n\n #updateTransactions?: boolean;\n\n constructor({\n getCache,\n getCurrentAccount,\n getChainIds,\n getLocalTransactions,\n includeTokenTransfers,\n isEnabled,\n queryEntireHistory,\n remoteTransactionSource,\n trimTransactions,\n updateCache,\n updateTransactions,\n }: {\n getCache: () => Record<string, unknown>;\n getCurrentAccount: () => ReturnType<\n AccountsController['getSelectedAccount']\n >;\n getChainIds: () => Hex[];\n getLocalTransactions: () => TransactionMeta[];\n includeTokenTransfers?: boolean;\n isEnabled?: () => boolean;\n queryEntireHistory?: boolean;\n remoteTransactionSource: RemoteTransactionSource;\n trimTransactions: (transactions: TransactionMeta[]) => TransactionMeta[];\n updateCache: (fn: (cache: Record<string, unknown>) => void) => void;\n updateTransactions?: boolean;\n }) {\n this.hub = new EventEmitter();\n\n this.#getCache = getCache;\n this.#getCurrentAccount = getCurrentAccount;\n this.#getChainIds = getChainIds;\n this.#getLocalTransactions = getLocalTransactions;\n this.#includeTokenTransfers = includeTokenTransfers;\n this.#isEnabled = isEnabled ?? (() => true);\n this.#isRunning = false;\n this.#queryEntireHistory = queryEntireHistory;\n this.#remoteTransactionSource = remoteTransactionSource;\n this.#trimTransactions = trimTransactions;\n this.#updateCache = updateCache;\n this.#updateTransactions = updateTransactions;\n }\n\n start() {\n if (this.#isRunning) {\n return;\n }\n\n if (!this.#canStart()) {\n return;\n }\n\n log('Starting polling');\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeoutId = setTimeout(() => this.#onInterval(), INTERVAL);\n this.#isRunning = true;\n\n log('Started polling');\n }\n\n stop() {\n if (this.#timeoutId) {\n clearTimeout(this.#timeoutId as number);\n }\n\n if (!this.#isRunning) {\n return;\n }\n\n this.#isRunning = false;\n\n log('Stopped polling');\n }\n\n async #onInterval() {\n try {\n await this.update({ isInterval: true });\n } catch (error) {\n console.error('Error while checking incoming transactions', error);\n }\n\n if (this.#isRunning) {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeoutId = setTimeout(() => this.#onInterval(), INTERVAL);\n }\n }\n\n async update({ isInterval }: { isInterval?: boolean } = {}): Promise<void> {\n log('Checking for incoming transactions', {\n isInterval: Boolean(isInterval),\n });\n\n if (!this.#canStart()) {\n return;\n }\n\n const account = this.#getCurrentAccount();\n const chainIds = this.#getChainIds();\n const cache = this.#getCache();\n const includeTokenTransfers = this.#includeTokenTransfers ?? true;\n const queryEntireHistory = this.#queryEntireHistory ?? true;\n const updateTransactions = this.#updateTransactions ?? false;\n\n let remoteTransactions: TransactionMeta[] = [];\n\n try {\n remoteTransactions =\n await this.#remoteTransactionSource.fetchTransactions({\n address: account.address as Hex,\n cache,\n chainIds,\n includeTokenTransfers,\n queryEntireHistory,\n updateCache: this.#updateCache,\n updateTransactions,\n });\n } catch (error: unknown) {\n log('Error while fetching remote transactions', error);\n return;\n }\n\n if (!remoteTransactions.length) {\n return;\n }\n\n this.#sortTransactionsByTime(remoteTransactions);\n\n log(\n 'Found potential transactions',\n remoteTransactions.length,\n remoteTransactions,\n );\n\n const localTransactions = this.#getLocalTransactions();\n\n const uniqueTransactions = remoteTransactions.filter(\n (tx) =>\n !localTransactions.some(\n (currentTx) =>\n currentTx.hash?.toLowerCase() === tx.hash?.toLowerCase() &&\n currentTx.txParams.from?.toLowerCase() ===\n tx.txParams.from?.toLowerCase(),\n ),\n );\n\n if (!uniqueTransactions.length) {\n log('All transactions are already known');\n return;\n }\n\n log(\n 'Found unique transactions',\n uniqueTransactions.length,\n uniqueTransactions,\n );\n\n const trimmedTransactions = this.#trimTransactions([\n ...uniqueTransactions,\n ...localTransactions,\n ]);\n\n const uniqueTransactionIds = uniqueTransactions.map((tx) => tx.id);\n\n const newTransactions = trimmedTransactions.filter((tx) =>\n uniqueTransactionIds.includes(tx.id),\n );\n\n if (!newTransactions.length) {\n log('All unique transactions truncated due to limit');\n return;\n }\n\n log('Adding new transactions', newTransactions.length, newTransactions);\n\n this.hub.emit('transactions', newTransactions);\n }\n\n #sortTransactionsByTime(transactions: TransactionMeta[]) {\n transactions.sort((a, b) => (a.time < b.time ? -1 : 1));\n }\n\n #canStart(): boolean {\n const isEnabled = this.#isEnabled();\n const chainIds = this.#getChainIds();\n\n const supportedChainIds =\n this.#remoteTransactionSource.getSupportedChains();\n\n const isAnyChainSupported = chainIds.some((chainId) =>\n supportedChainIds.includes(chainId),\n );\n\n return isEnabled && isAnyChainSupported;\n }\n}\n"]}
1
+ {"version":3,"file":"IncomingTransactionHelper.cjs","sourceRoot":"","sources":["../../src/helpers/IncomingTransactionHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountsController } from '@metamask/accounts-controller';\nimport type { Hex } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { incomingTransactionsLogger as log } from '../logger';\nimport type { RemoteTransactionSource, TransactionMeta } from '../types';\n\nexport type IncomingTransactionOptions = {\n includeTokenTransfers?: boolean;\n isEnabled?: () => boolean;\n queryEntireHistory?: boolean;\n updateTransactions?: boolean;\n};\n\nconst INTERVAL = 1000 * 30; // 30 Seconds\n\nexport class IncomingTransactionHelper {\n hub: EventEmitter;\n\n #getCache: () => Record<string, unknown>;\n\n #getCurrentAccount: () => ReturnType<\n AccountsController['getSelectedAccount']\n >;\n\n #getChainIds: () => Hex[];\n\n #getLocalTransactions: () => TransactionMeta[];\n\n #includeTokenTransfers?: boolean;\n\n #isEnabled: () => boolean;\n\n #isRunning: boolean;\n\n #queryEntireHistory?: boolean;\n\n #remoteTransactionSource: RemoteTransactionSource;\n\n #timeoutId?: unknown;\n\n #trimTransactions: (transactions: TransactionMeta[]) => TransactionMeta[];\n\n #updateCache: (fn: (cache: Record<string, unknown>) => void) => void;\n\n #updateTransactions?: boolean;\n\n constructor({\n getCache,\n getCurrentAccount,\n getChainIds,\n getLocalTransactions,\n includeTokenTransfers,\n isEnabled,\n queryEntireHistory,\n remoteTransactionSource,\n trimTransactions,\n updateCache,\n updateTransactions,\n }: {\n getCache: () => Record<string, unknown>;\n getCurrentAccount: () => ReturnType<\n AccountsController['getSelectedAccount']\n >;\n getChainIds: () => Hex[];\n getLocalTransactions: () => TransactionMeta[];\n includeTokenTransfers?: boolean;\n isEnabled?: () => boolean;\n queryEntireHistory?: boolean;\n remoteTransactionSource: RemoteTransactionSource;\n trimTransactions: (transactions: TransactionMeta[]) => TransactionMeta[];\n updateCache: (fn: (cache: Record<string, unknown>) => void) => void;\n updateTransactions?: boolean;\n }) {\n this.hub = new EventEmitter();\n\n this.#getCache = getCache;\n this.#getCurrentAccount = getCurrentAccount;\n this.#getChainIds = getChainIds;\n this.#getLocalTransactions = getLocalTransactions;\n this.#includeTokenTransfers = includeTokenTransfers;\n this.#isEnabled = isEnabled ?? (() => true);\n this.#isRunning = false;\n this.#queryEntireHistory = queryEntireHistory;\n this.#remoteTransactionSource = remoteTransactionSource;\n this.#trimTransactions = trimTransactions;\n this.#updateCache = updateCache;\n this.#updateTransactions = updateTransactions;\n }\n\n start() {\n if (this.#isRunning) {\n return;\n }\n\n if (!this.#canStart()) {\n return;\n }\n\n log('Starting polling');\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeoutId = setTimeout(() => this.#onInterval(), INTERVAL);\n this.#isRunning = true;\n\n log('Started polling');\n }\n\n stop() {\n if (this.#timeoutId) {\n clearTimeout(this.#timeoutId as number);\n }\n\n if (!this.#isRunning) {\n return;\n }\n\n this.#isRunning = false;\n\n log('Stopped polling');\n }\n\n async #onInterval() {\n try {\n await this.update({ isInterval: true });\n } catch (error) {\n console.error('Error while checking incoming transactions', error);\n }\n\n if (this.#isRunning) {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeoutId = setTimeout(() => this.#onInterval(), INTERVAL);\n }\n }\n\n async update({ isInterval }: { isInterval?: boolean } = {}): Promise<void> {\n log('Checking for incoming transactions', {\n isInterval: Boolean(isInterval),\n });\n\n if (!this.#canStart()) {\n return;\n }\n\n const account = this.#getCurrentAccount();\n const chainIds = this.#getChainIds();\n const cache = this.#getCache();\n const includeTokenTransfers = this.#includeTokenTransfers ?? true;\n const queryEntireHistory = this.#queryEntireHistory ?? true;\n const updateTransactions = this.#updateTransactions ?? false;\n\n let remoteTransactions: TransactionMeta[] = [];\n\n try {\n remoteTransactions =\n await this.#remoteTransactionSource.fetchTransactions({\n address: account.address as Hex,\n cache,\n chainIds,\n includeTokenTransfers,\n queryEntireHistory,\n updateCache: this.#updateCache,\n updateTransactions,\n });\n } catch (error: unknown) {\n log('Error while fetching remote transactions', error);\n return;\n }\n\n if (!remoteTransactions.length) {\n return;\n }\n\n this.#sortTransactionsByTime(remoteTransactions);\n\n log(\n 'Found potential transactions',\n remoteTransactions.length,\n remoteTransactions,\n );\n\n const localTransactions = this.#getLocalTransactions();\n\n const uniqueTransactions = remoteTransactions.filter(\n (tx) =>\n !localTransactions.some(\n (currentTx) =>\n currentTx.hash?.toLowerCase() === tx.hash?.toLowerCase() &&\n currentTx.txParams.from?.toLowerCase() ===\n tx.txParams.from?.toLowerCase(),\n ),\n );\n\n if (!uniqueTransactions.length) {\n log('All transactions are already known');\n return;\n }\n\n log(\n 'Found unique transactions',\n uniqueTransactions.length,\n uniqueTransactions,\n );\n\n const trimmedTransactions = this.#trimTransactions([\n ...uniqueTransactions,\n ...localTransactions,\n ]);\n\n const uniqueTransactionIds = uniqueTransactions.map((tx) => tx.id);\n\n const newTransactions = trimmedTransactions.filter((tx) =>\n uniqueTransactionIds.includes(tx.id),\n );\n\n if (!newTransactions.length) {\n log('All unique transactions truncated due to limit');\n return;\n }\n\n log('Adding new transactions', newTransactions.length, newTransactions);\n\n this.hub.emit('transactions', newTransactions);\n }\n\n #sortTransactionsByTime(transactions: TransactionMeta[]) {\n transactions.sort((a, b) => (a.time < b.time ? -1 : 1));\n }\n\n #canStart(): boolean {\n const isEnabled = this.#isEnabled();\n const chainIds = this.#getChainIds();\n\n const supportedChainIds =\n this.#remoteTransactionSource.getSupportedChains();\n\n const isAnyChainSupported = chainIds.some((chainId) =>\n supportedChainIds.includes(chainId),\n );\n\n return isEnabled && isAnyChainSupported;\n }\n}\n"]}
@@ -11,7 +11,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
11
11
  };
12
12
  var _IncomingTransactionHelper_instances, _IncomingTransactionHelper_getCache, _IncomingTransactionHelper_getCurrentAccount, _IncomingTransactionHelper_getChainIds, _IncomingTransactionHelper_getLocalTransactions, _IncomingTransactionHelper_includeTokenTransfers, _IncomingTransactionHelper_isEnabled, _IncomingTransactionHelper_isRunning, _IncomingTransactionHelper_queryEntireHistory, _IncomingTransactionHelper_remoteTransactionSource, _IncomingTransactionHelper_timeoutId, _IncomingTransactionHelper_trimTransactions, _IncomingTransactionHelper_updateCache, _IncomingTransactionHelper_updateTransactions, _IncomingTransactionHelper_onInterval, _IncomingTransactionHelper_sortTransactionsByTime, _IncomingTransactionHelper_canStart;
13
13
  // This package purposefully relies on Node's EventEmitter module.
14
- // eslint-disable-next-line import/no-nodejs-modules
14
+ // eslint-disable-next-line import-x/no-nodejs-modules
15
15
  import EventEmitter from "events";
16
16
  import { incomingTransactionsLogger as log } from "../logger.mjs";
17
17
  const INTERVAL = 1000 * 30; // 30 Seconds
@@ -1 +1 @@
1
- {"version":3,"file":"IncomingTransactionHelper.mjs","sourceRoot":"","sources":["../../src/helpers/IncomingTransactionHelper.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,kEAAkE;AAClE,oDAAoD;AACpD,OAAO,YAAY,eAAe;AAElC,OAAO,EAAE,0BAA0B,IAAI,GAAG,EAAE,sBAAkB;AAU9D,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC,aAAa;AAEzC,MAAM,OAAO,yBAAyB;IA+BpC,YAAY,EACV,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,oBAAoB,EACpB,qBAAqB,EACrB,SAAS,EACT,kBAAkB,EAClB,uBAAuB,EACvB,gBAAgB,EAChB,WAAW,EACX,kBAAkB,GAenB;;QAtDD,sDAAyC;QAEzC,+DAEE;QAEF,yDAA0B;QAE1B,kEAA+C;QAE/C,mEAAiC;QAEjC,uDAA0B;QAE1B,uDAAoB;QAEpB,gEAA8B;QAE9B,qEAAkD;QAElD,uDAAqB;QAErB,8DAA0E;QAE1E,yDAAqE;QAErE,gEAA8B;QA6B5B,IAAI,CAAC,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;QAE9B,uBAAA,IAAI,uCAAa,QAAQ,MAAA,CAAC;QAC1B,uBAAA,IAAI,gDAAsB,iBAAiB,MAAA,CAAC;QAC5C,uBAAA,IAAI,0CAAgB,WAAW,MAAA,CAAC;QAChC,uBAAA,IAAI,mDAAyB,oBAAoB,MAAA,CAAC;QAClD,uBAAA,IAAI,oDAA0B,qBAAqB,MAAA,CAAC;QACpD,uBAAA,IAAI,wCAAc,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAA,CAAC;QAC5C,uBAAA,IAAI,wCAAc,KAAK,MAAA,CAAC;QACxB,uBAAA,IAAI,iDAAuB,kBAAkB,MAAA,CAAC;QAC9C,uBAAA,IAAI,sDAA4B,uBAAuB,MAAA,CAAC;QACxD,uBAAA,IAAI,+CAAqB,gBAAgB,MAAA,CAAC;QAC1C,uBAAA,IAAI,0CAAgB,WAAW,MAAA,CAAC;QAChC,uBAAA,IAAI,iDAAuB,kBAAkB,MAAA,CAAC;IAChD,CAAC;IAED,KAAK;QACH,IAAI,uBAAA,IAAI,4CAAW,EAAE;YACnB,OAAO;SACR;QAED,IAAI,CAAC,uBAAA,IAAI,iFAAU,MAAd,IAAI,CAAY,EAAE;YACrB,OAAO;SACR;QAED,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAExB,kEAAkE;QAClE,uBAAA,IAAI,wCAAc,UAAU,CAAC,GAAG,EAAE,CAAC,uBAAA,IAAI,mFAAY,MAAhB,IAAI,CAAc,EAAE,QAAQ,CAAC,MAAA,CAAC;QACjE,uBAAA,IAAI,wCAAc,IAAI,MAAA,CAAC;QAEvB,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACzB,CAAC;IAED,IAAI;QACF,IAAI,uBAAA,IAAI,4CAAW,EAAE;YACnB,YAAY,CAAC,uBAAA,IAAI,4CAAqB,CAAC,CAAC;SACzC;QAED,IAAI,CAAC,uBAAA,IAAI,4CAAW,EAAE;YACpB,OAAO;SACR;QAED,uBAAA,IAAI,wCAAc,KAAK,MAAA,CAAC;QAExB,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACzB,CAAC;IAeD,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,KAA+B,EAAE;QACxD,GAAG,CAAC,oCAAoC,EAAE;YACxC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC,uBAAA,IAAI,iFAAU,MAAd,IAAI,CAAY,EAAE;YACrB,OAAO;SACR;QAED,MAAM,OAAO,GAAG,uBAAA,IAAI,oDAAmB,MAAvB,IAAI,CAAqB,CAAC;QAC1C,MAAM,QAAQ,GAAG,uBAAA,IAAI,8CAAa,MAAjB,IAAI,CAAe,CAAC;QACrC,MAAM,KAAK,GAAG,uBAAA,IAAI,2CAAU,MAAd,IAAI,CAAY,CAAC;QAC/B,MAAM,qBAAqB,GAAG,uBAAA,IAAI,wDAAuB,IAAI,IAAI,CAAC;QAClE,MAAM,kBAAkB,GAAG,uBAAA,IAAI,qDAAoB,IAAI,IAAI,CAAC;QAC5D,MAAM,kBAAkB,GAAG,uBAAA,IAAI,qDAAoB,IAAI,KAAK,CAAC;QAE7D,IAAI,kBAAkB,GAAsB,EAAE,CAAC;QAE/C,IAAI;YACF,kBAAkB;gBAChB,MAAM,uBAAA,IAAI,0DAAyB,CAAC,iBAAiB,CAAC;oBACpD,OAAO,EAAE,OAAO,CAAC,OAAc;oBAC/B,KAAK;oBACL,QAAQ;oBACR,qBAAqB;oBACrB,kBAAkB;oBAClB,WAAW,EAAE,uBAAA,IAAI,8CAAa;oBAC9B,kBAAkB;iBACnB,CAAC,CAAC;SACN;QAAC,OAAO,KAAc,EAAE;YACvB,GAAG,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAC;YACvD,OAAO;SACR;QAED,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE;YAC9B,OAAO;SACR;QAED,uBAAA,IAAI,+FAAwB,MAA5B,IAAI,EAAyB,kBAAkB,CAAC,CAAC;QAEjD,GAAG,CACD,8BAA8B,EAC9B,kBAAkB,CAAC,MAAM,EACzB,kBAAkB,CACnB,CAAC;QAEF,MAAM,iBAAiB,GAAG,uBAAA,IAAI,uDAAsB,MAA1B,IAAI,CAAwB,CAAC;QAEvD,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,MAAM,CAClD,CAAC,EAAE,EAAE,EAAE,CACL,CAAC,iBAAiB,CAAC,IAAI,CACrB,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE;YACxD,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE;gBACpC,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,CACpC,CACJ,CAAC;QAEF,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE;YAC9B,GAAG,CAAC,oCAAoC,CAAC,CAAC;YAC1C,OAAO;SACR;QAED,GAAG,CACD,2BAA2B,EAC3B,kBAAkB,CAAC,MAAM,EACzB,kBAAkB,CACnB,CAAC;QAEF,MAAM,mBAAmB,GAAG,uBAAA,IAAI,mDAAkB,MAAtB,IAAI,EAAmB;YACjD,GAAG,kBAAkB;YACrB,GAAG,iBAAiB;SACrB,CAAC,CAAC;QAEH,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAEnE,MAAM,eAAe,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CACxD,oBAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CACrC,CAAC;QAEF,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE;YAC3B,GAAG,CAAC,gDAAgD,CAAC,CAAC;YACtD,OAAO;SACR;QAED,GAAG,CAAC,yBAAyB,EAAE,eAAe,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QAExE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;IACjD,CAAC;CAmBF;q2BAxHC,KAAK;IACH,IAAI;QACF,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;KACzC;IAAC,OAAO,KAAK,EAAE;QACd,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,KAAK,CAAC,CAAC;KACpE;IAED,IAAI,uBAAA,IAAI,4CAAW,EAAE;QACnB,kEAAkE;QAClE,uBAAA,IAAI,wCAAc,UAAU,CAAC,GAAG,EAAE,CAAC,uBAAA,IAAI,mFAAY,MAAhB,IAAI,CAAc,EAAE,QAAQ,CAAC,MAAA,CAAC;KAClE;AACH,CAAC,iHA4FuB,YAA+B;IACrD,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC;IAGC,MAAM,SAAS,GAAG,uBAAA,IAAI,4CAAW,MAAf,IAAI,CAAa,CAAC;IACpC,MAAM,QAAQ,GAAG,uBAAA,IAAI,8CAAa,MAAjB,IAAI,CAAe,CAAC;IAErC,MAAM,iBAAiB,GACrB,uBAAA,IAAI,0DAAyB,CAAC,kBAAkB,EAAE,CAAC;IAErD,MAAM,mBAAmB,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CACpD,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,CACpC,CAAC;IAEF,OAAO,SAAS,IAAI,mBAAmB,CAAC;AAC1C,CAAC","sourcesContent":["import type { AccountsController } from '@metamask/accounts-controller';\nimport type { Hex } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { incomingTransactionsLogger as log } from '../logger';\nimport type { RemoteTransactionSource, TransactionMeta } from '../types';\n\nexport type IncomingTransactionOptions = {\n includeTokenTransfers?: boolean;\n isEnabled?: () => boolean;\n queryEntireHistory?: boolean;\n updateTransactions?: boolean;\n};\n\nconst INTERVAL = 1000 * 30; // 30 Seconds\n\nexport class IncomingTransactionHelper {\n hub: EventEmitter;\n\n #getCache: () => Record<string, unknown>;\n\n #getCurrentAccount: () => ReturnType<\n AccountsController['getSelectedAccount']\n >;\n\n #getChainIds: () => Hex[];\n\n #getLocalTransactions: () => TransactionMeta[];\n\n #includeTokenTransfers?: boolean;\n\n #isEnabled: () => boolean;\n\n #isRunning: boolean;\n\n #queryEntireHistory?: boolean;\n\n #remoteTransactionSource: RemoteTransactionSource;\n\n #timeoutId?: unknown;\n\n #trimTransactions: (transactions: TransactionMeta[]) => TransactionMeta[];\n\n #updateCache: (fn: (cache: Record<string, unknown>) => void) => void;\n\n #updateTransactions?: boolean;\n\n constructor({\n getCache,\n getCurrentAccount,\n getChainIds,\n getLocalTransactions,\n includeTokenTransfers,\n isEnabled,\n queryEntireHistory,\n remoteTransactionSource,\n trimTransactions,\n updateCache,\n updateTransactions,\n }: {\n getCache: () => Record<string, unknown>;\n getCurrentAccount: () => ReturnType<\n AccountsController['getSelectedAccount']\n >;\n getChainIds: () => Hex[];\n getLocalTransactions: () => TransactionMeta[];\n includeTokenTransfers?: boolean;\n isEnabled?: () => boolean;\n queryEntireHistory?: boolean;\n remoteTransactionSource: RemoteTransactionSource;\n trimTransactions: (transactions: TransactionMeta[]) => TransactionMeta[];\n updateCache: (fn: (cache: Record<string, unknown>) => void) => void;\n updateTransactions?: boolean;\n }) {\n this.hub = new EventEmitter();\n\n this.#getCache = getCache;\n this.#getCurrentAccount = getCurrentAccount;\n this.#getChainIds = getChainIds;\n this.#getLocalTransactions = getLocalTransactions;\n this.#includeTokenTransfers = includeTokenTransfers;\n this.#isEnabled = isEnabled ?? (() => true);\n this.#isRunning = false;\n this.#queryEntireHistory = queryEntireHistory;\n this.#remoteTransactionSource = remoteTransactionSource;\n this.#trimTransactions = trimTransactions;\n this.#updateCache = updateCache;\n this.#updateTransactions = updateTransactions;\n }\n\n start() {\n if (this.#isRunning) {\n return;\n }\n\n if (!this.#canStart()) {\n return;\n }\n\n log('Starting polling');\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeoutId = setTimeout(() => this.#onInterval(), INTERVAL);\n this.#isRunning = true;\n\n log('Started polling');\n }\n\n stop() {\n if (this.#timeoutId) {\n clearTimeout(this.#timeoutId as number);\n }\n\n if (!this.#isRunning) {\n return;\n }\n\n this.#isRunning = false;\n\n log('Stopped polling');\n }\n\n async #onInterval() {\n try {\n await this.update({ isInterval: true });\n } catch (error) {\n console.error('Error while checking incoming transactions', error);\n }\n\n if (this.#isRunning) {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeoutId = setTimeout(() => this.#onInterval(), INTERVAL);\n }\n }\n\n async update({ isInterval }: { isInterval?: boolean } = {}): Promise<void> {\n log('Checking for incoming transactions', {\n isInterval: Boolean(isInterval),\n });\n\n if (!this.#canStart()) {\n return;\n }\n\n const account = this.#getCurrentAccount();\n const chainIds = this.#getChainIds();\n const cache = this.#getCache();\n const includeTokenTransfers = this.#includeTokenTransfers ?? true;\n const queryEntireHistory = this.#queryEntireHistory ?? true;\n const updateTransactions = this.#updateTransactions ?? false;\n\n let remoteTransactions: TransactionMeta[] = [];\n\n try {\n remoteTransactions =\n await this.#remoteTransactionSource.fetchTransactions({\n address: account.address as Hex,\n cache,\n chainIds,\n includeTokenTransfers,\n queryEntireHistory,\n updateCache: this.#updateCache,\n updateTransactions,\n });\n } catch (error: unknown) {\n log('Error while fetching remote transactions', error);\n return;\n }\n\n if (!remoteTransactions.length) {\n return;\n }\n\n this.#sortTransactionsByTime(remoteTransactions);\n\n log(\n 'Found potential transactions',\n remoteTransactions.length,\n remoteTransactions,\n );\n\n const localTransactions = this.#getLocalTransactions();\n\n const uniqueTransactions = remoteTransactions.filter(\n (tx) =>\n !localTransactions.some(\n (currentTx) =>\n currentTx.hash?.toLowerCase() === tx.hash?.toLowerCase() &&\n currentTx.txParams.from?.toLowerCase() ===\n tx.txParams.from?.toLowerCase(),\n ),\n );\n\n if (!uniqueTransactions.length) {\n log('All transactions are already known');\n return;\n }\n\n log(\n 'Found unique transactions',\n uniqueTransactions.length,\n uniqueTransactions,\n );\n\n const trimmedTransactions = this.#trimTransactions([\n ...uniqueTransactions,\n ...localTransactions,\n ]);\n\n const uniqueTransactionIds = uniqueTransactions.map((tx) => tx.id);\n\n const newTransactions = trimmedTransactions.filter((tx) =>\n uniqueTransactionIds.includes(tx.id),\n );\n\n if (!newTransactions.length) {\n log('All unique transactions truncated due to limit');\n return;\n }\n\n log('Adding new transactions', newTransactions.length, newTransactions);\n\n this.hub.emit('transactions', newTransactions);\n }\n\n #sortTransactionsByTime(transactions: TransactionMeta[]) {\n transactions.sort((a, b) => (a.time < b.time ? -1 : 1));\n }\n\n #canStart(): boolean {\n const isEnabled = this.#isEnabled();\n const chainIds = this.#getChainIds();\n\n const supportedChainIds =\n this.#remoteTransactionSource.getSupportedChains();\n\n const isAnyChainSupported = chainIds.some((chainId) =>\n supportedChainIds.includes(chainId),\n );\n\n return isEnabled && isAnyChainSupported;\n }\n}\n"]}
1
+ {"version":3,"file":"IncomingTransactionHelper.mjs","sourceRoot":"","sources":["../../src/helpers/IncomingTransactionHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountsController } from '@metamask/accounts-controller';\nimport type { Hex } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { incomingTransactionsLogger as log } from '../logger';\nimport type { RemoteTransactionSource, TransactionMeta } from '../types';\n\nexport type IncomingTransactionOptions = {\n includeTokenTransfers?: boolean;\n isEnabled?: () => boolean;\n queryEntireHistory?: boolean;\n updateTransactions?: boolean;\n};\n\nconst INTERVAL = 1000 * 30; // 30 Seconds\n\nexport class IncomingTransactionHelper {\n hub: EventEmitter;\n\n #getCache: () => Record<string, unknown>;\n\n #getCurrentAccount: () => ReturnType<\n AccountsController['getSelectedAccount']\n >;\n\n #getChainIds: () => Hex[];\n\n #getLocalTransactions: () => TransactionMeta[];\n\n #includeTokenTransfers?: boolean;\n\n #isEnabled: () => boolean;\n\n #isRunning: boolean;\n\n #queryEntireHistory?: boolean;\n\n #remoteTransactionSource: RemoteTransactionSource;\n\n #timeoutId?: unknown;\n\n #trimTransactions: (transactions: TransactionMeta[]) => TransactionMeta[];\n\n #updateCache: (fn: (cache: Record<string, unknown>) => void) => void;\n\n #updateTransactions?: boolean;\n\n constructor({\n getCache,\n getCurrentAccount,\n getChainIds,\n getLocalTransactions,\n includeTokenTransfers,\n isEnabled,\n queryEntireHistory,\n remoteTransactionSource,\n trimTransactions,\n updateCache,\n updateTransactions,\n }: {\n getCache: () => Record<string, unknown>;\n getCurrentAccount: () => ReturnType<\n AccountsController['getSelectedAccount']\n >;\n getChainIds: () => Hex[];\n getLocalTransactions: () => TransactionMeta[];\n includeTokenTransfers?: boolean;\n isEnabled?: () => boolean;\n queryEntireHistory?: boolean;\n remoteTransactionSource: RemoteTransactionSource;\n trimTransactions: (transactions: TransactionMeta[]) => TransactionMeta[];\n updateCache: (fn: (cache: Record<string, unknown>) => void) => void;\n updateTransactions?: boolean;\n }) {\n this.hub = new EventEmitter();\n\n this.#getCache = getCache;\n this.#getCurrentAccount = getCurrentAccount;\n this.#getChainIds = getChainIds;\n this.#getLocalTransactions = getLocalTransactions;\n this.#includeTokenTransfers = includeTokenTransfers;\n this.#isEnabled = isEnabled ?? (() => true);\n this.#isRunning = false;\n this.#queryEntireHistory = queryEntireHistory;\n this.#remoteTransactionSource = remoteTransactionSource;\n this.#trimTransactions = trimTransactions;\n this.#updateCache = updateCache;\n this.#updateTransactions = updateTransactions;\n }\n\n start() {\n if (this.#isRunning) {\n return;\n }\n\n if (!this.#canStart()) {\n return;\n }\n\n log('Starting polling');\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeoutId = setTimeout(() => this.#onInterval(), INTERVAL);\n this.#isRunning = true;\n\n log('Started polling');\n }\n\n stop() {\n if (this.#timeoutId) {\n clearTimeout(this.#timeoutId as number);\n }\n\n if (!this.#isRunning) {\n return;\n }\n\n this.#isRunning = false;\n\n log('Stopped polling');\n }\n\n async #onInterval() {\n try {\n await this.update({ isInterval: true });\n } catch (error) {\n console.error('Error while checking incoming transactions', error);\n }\n\n if (this.#isRunning) {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeoutId = setTimeout(() => this.#onInterval(), INTERVAL);\n }\n }\n\n async update({ isInterval }: { isInterval?: boolean } = {}): Promise<void> {\n log('Checking for incoming transactions', {\n isInterval: Boolean(isInterval),\n });\n\n if (!this.#canStart()) {\n return;\n }\n\n const account = this.#getCurrentAccount();\n const chainIds = this.#getChainIds();\n const cache = this.#getCache();\n const includeTokenTransfers = this.#includeTokenTransfers ?? true;\n const queryEntireHistory = this.#queryEntireHistory ?? true;\n const updateTransactions = this.#updateTransactions ?? false;\n\n let remoteTransactions: TransactionMeta[] = [];\n\n try {\n remoteTransactions =\n await this.#remoteTransactionSource.fetchTransactions({\n address: account.address as Hex,\n cache,\n chainIds,\n includeTokenTransfers,\n queryEntireHistory,\n updateCache: this.#updateCache,\n updateTransactions,\n });\n } catch (error: unknown) {\n log('Error while fetching remote transactions', error);\n return;\n }\n\n if (!remoteTransactions.length) {\n return;\n }\n\n this.#sortTransactionsByTime(remoteTransactions);\n\n log(\n 'Found potential transactions',\n remoteTransactions.length,\n remoteTransactions,\n );\n\n const localTransactions = this.#getLocalTransactions();\n\n const uniqueTransactions = remoteTransactions.filter(\n (tx) =>\n !localTransactions.some(\n (currentTx) =>\n currentTx.hash?.toLowerCase() === tx.hash?.toLowerCase() &&\n currentTx.txParams.from?.toLowerCase() ===\n tx.txParams.from?.toLowerCase(),\n ),\n );\n\n if (!uniqueTransactions.length) {\n log('All transactions are already known');\n return;\n }\n\n log(\n 'Found unique transactions',\n uniqueTransactions.length,\n uniqueTransactions,\n );\n\n const trimmedTransactions = this.#trimTransactions([\n ...uniqueTransactions,\n ...localTransactions,\n ]);\n\n const uniqueTransactionIds = uniqueTransactions.map((tx) => tx.id);\n\n const newTransactions = trimmedTransactions.filter((tx) =>\n uniqueTransactionIds.includes(tx.id),\n );\n\n if (!newTransactions.length) {\n log('All unique transactions truncated due to limit');\n return;\n }\n\n log('Adding new transactions', newTransactions.length, newTransactions);\n\n this.hub.emit('transactions', newTransactions);\n }\n\n #sortTransactionsByTime(transactions: TransactionMeta[]) {\n transactions.sort((a, b) => (a.time < b.time ? -1 : 1));\n }\n\n #canStart(): boolean {\n const isEnabled = this.#isEnabled();\n const chainIds = this.#getChainIds();\n\n const supportedChainIds =\n this.#remoteTransactionSource.getSupportedChains();\n\n const isAnyChainSupported = chainIds.some((chainId) =>\n supportedChainIds.includes(chainId),\n );\n\n return isEnabled && isAnyChainSupported;\n }\n}\n"]}
@@ -20,7 +20,7 @@ const utils_1 = require("@metamask/utils");
20
20
  const async_mutex_1 = require("async-mutex");
21
21
  const eth_method_registry_1 = require("eth-method-registry");
22
22
  // This package purposefully relies on Node's EventEmitter module.
23
- // eslint-disable-next-line import/no-nodejs-modules
23
+ // eslint-disable-next-line import-x/no-nodejs-modules
24
24
  const events_1 = __importDefault(require("events"));
25
25
  const logger_1 = require("../logger.cjs");
26
26
  const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'method-data');
@@ -1 +1 @@
1
- {"version":3,"file":"MethodDataHelper.cjs","sourceRoot":"","sources":["../../src/helpers/MethodDataHelper.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AACA,2CAAqD;AACrD,6CAAoC;AACpC,6DAAqD;AACrD,kEAAkE;AAClE,oDAAoD;AACpD,oDAAkC;AAElC,0CAA0C;AAG1C,MAAM,GAAG,GAAG,IAAA,0BAAkB,EAAC,sBAAa,EAAE,aAAa,CAAC,CAAC;AAE7D,MAAa,gBAAgB;IAW3B,YAAY,EACV,WAAW,EACX,QAAQ,GAIT;;QAdD,gDAA6D;QAE7D,6CAA4C;QAE5C,oEAAuE;QAEvE,kCAAS,IAAI,mBAAK,EAAE,EAAC;QASnB,IAAI,CAAC,GAAG,GAAG,IAAI,gBAAY,EAAE,CAAC;QAE9B,uBAAA,IAAI,iCAAgB,WAAW,MAAA,CAAC;QAChC,uBAAA,IAAI,8BAAa,QAAQ,MAAA,CAAC;QAC1B,uBAAA,IAAI,qDAAoC,IAAI,GAAG,EAAE,MAAA,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,MAAM,CACV,cAAsB,EACtB,eAAgC;QAEhC,GAAG,CAAC,QAAQ,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;QAE/C,MAAM,WAAW,GAAG,MAAM,uBAAA,IAAI,+BAAO,CAAC,OAAO,EAAE,CAAC;QAEhD,IAAI;YACF,MAAM,YAAY,GAAG,uBAAA,IAAI,kCAAU,MAAd,IAAI,CAAY,CAAC,cAAc,CAAC,CAAC;YAEtD,IAAI,YAAY,EAAE;gBAChB,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;gBAC5B,OAAO,YAAY,CAAC;aACrB;YAED,IAAI,QAAQ,GAAG,uBAAA,IAAI,yDAAiC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YAE1E,IAAI,CAAC,QAAQ,EAAE;gBACb,MAAM,QAAQ,GAAG,uBAAA,IAAI,qCAAa,MAAjB,IAAI,EAAc,eAAe,CAAC,CAAC;gBAEpD,sFAAsF;gBACtF,QAAQ,GAAG,IAAI,oCAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAE5C,uBAAA,IAAI,yDAAiC,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;gBAErE,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;aAC1C;YAED,MAAM,UAAU,GAAG,MAAM,uBAAA,IAAI,qEAAgB,MAApB,IAAI,EAAiB,cAAc,EAAE,QAAQ,CAAC,CAAC;YAExE,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YAE1B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC,CAAC;YAExD,OAAO,UAAU,CAAC;SACnB;gBAAS;YACR,WAAW,EAAE,CAAC;SACf;IACH,CAAC;CAuBF;AAvFD,4CAuFC;uRArBC,KAAK,2CACH,cAAsB,EACtB,cAA8B;IAE9B,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAEnE,IAAI,CAAC,cAAc,EAAE;QACnB,GAAG,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;QAEvC,OAAO;YACL,cAAc,EAAE,EAAE;YAClB,oBAAoB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;SAC3D,CAAC;KACH;IAED,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAE/B,MAAM,oBAAoB,GAAG,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAElE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,CAAC;AAClD,CAAC","sourcesContent":["import type { NetworkClientId, Provider } from '@metamask/network-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { MethodRegistry } from 'eth-method-registry';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { projectLogger } from '../logger';\nimport type { MethodData } from '../TransactionController';\n\nconst log = createModuleLogger(projectLogger, 'method-data');\n\nexport class MethodDataHelper {\n hub: EventEmitter;\n\n #getProvider: (networkClientId: NetworkClientId) => Provider;\n\n #getState: () => Record<string, MethodData>;\n\n #methodRegistryByNetworkClientId: Map<NetworkClientId, MethodRegistry>;\n\n #mutex = new Mutex();\n\n constructor({\n getProvider,\n getState,\n }: {\n getProvider: (networkClientId: NetworkClientId) => Provider;\n getState: () => Record<string, MethodData>;\n }) {\n this.hub = new EventEmitter();\n\n this.#getProvider = getProvider;\n this.#getState = getState;\n this.#methodRegistryByNetworkClientId = new Map();\n }\n\n async lookup(\n fourBytePrefix: string,\n networkClientId: NetworkClientId,\n ): Promise<MethodData> {\n log('lookup', fourBytePrefix, networkClientId);\n\n const releaseLock = await this.#mutex.acquire();\n\n try {\n const cachedResult = this.#getState()[fourBytePrefix];\n\n if (cachedResult) {\n log('Cached', cachedResult);\n return cachedResult;\n }\n\n let registry = this.#methodRegistryByNetworkClientId.get(networkClientId);\n\n if (!registry) {\n const provider = this.#getProvider(networkClientId);\n\n // @ts-expect-error Type in eth-method-registry is inappropriate and should be changed\n registry = new MethodRegistry({ provider });\n\n this.#methodRegistryByNetworkClientId.set(networkClientId, registry);\n\n log('Created registry', networkClientId);\n }\n\n const methodData = await this.#registryLookup(fourBytePrefix, registry);\n\n log('Result', methodData);\n\n this.hub.emit('update', { fourBytePrefix, methodData });\n\n return methodData;\n } finally {\n releaseLock();\n }\n }\n\n async #registryLookup(\n fourBytePrefix: string,\n methodRegistry: MethodRegistry,\n ): Promise<MethodData> {\n const registryMethod = await methodRegistry.lookup(fourBytePrefix);\n\n if (!registryMethod) {\n log('No method found', fourBytePrefix);\n\n return {\n registryMethod: '',\n parsedRegistryMethod: { name: undefined, args: undefined },\n };\n }\n\n log('Parsing', registryMethod);\n\n const parsedRegistryMethod = methodRegistry.parse(registryMethod);\n\n return { registryMethod, parsedRegistryMethod };\n }\n}\n"]}
1
+ {"version":3,"file":"MethodDataHelper.cjs","sourceRoot":"","sources":["../../src/helpers/MethodDataHelper.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AACA,2CAAqD;AACrD,6CAAoC;AACpC,6DAAqD;AACrD,kEAAkE;AAClE,sDAAsD;AACtD,oDAAkC;AAElC,0CAA0C;AAG1C,MAAM,GAAG,GAAG,IAAA,0BAAkB,EAAC,sBAAa,EAAE,aAAa,CAAC,CAAC;AAE7D,MAAa,gBAAgB;IAW3B,YAAY,EACV,WAAW,EACX,QAAQ,GAIT;;QAdD,gDAA6D;QAE7D,6CAA4C;QAE5C,oEAAuE;QAEvE,kCAAS,IAAI,mBAAK,EAAE,EAAC;QASnB,IAAI,CAAC,GAAG,GAAG,IAAI,gBAAY,EAAE,CAAC;QAE9B,uBAAA,IAAI,iCAAgB,WAAW,MAAA,CAAC;QAChC,uBAAA,IAAI,8BAAa,QAAQ,MAAA,CAAC;QAC1B,uBAAA,IAAI,qDAAoC,IAAI,GAAG,EAAE,MAAA,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,MAAM,CACV,cAAsB,EACtB,eAAgC;QAEhC,GAAG,CAAC,QAAQ,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;QAE/C,MAAM,WAAW,GAAG,MAAM,uBAAA,IAAI,+BAAO,CAAC,OAAO,EAAE,CAAC;QAEhD,IAAI;YACF,MAAM,YAAY,GAAG,uBAAA,IAAI,kCAAU,MAAd,IAAI,CAAY,CAAC,cAAc,CAAC,CAAC;YAEtD,IAAI,YAAY,EAAE;gBAChB,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;gBAC5B,OAAO,YAAY,CAAC;aACrB;YAED,IAAI,QAAQ,GAAG,uBAAA,IAAI,yDAAiC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YAE1E,IAAI,CAAC,QAAQ,EAAE;gBACb,MAAM,QAAQ,GAAG,uBAAA,IAAI,qCAAa,MAAjB,IAAI,EAAc,eAAe,CAAC,CAAC;gBAEpD,sFAAsF;gBACtF,QAAQ,GAAG,IAAI,oCAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAE5C,uBAAA,IAAI,yDAAiC,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;gBAErE,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;aAC1C;YAED,MAAM,UAAU,GAAG,MAAM,uBAAA,IAAI,qEAAgB,MAApB,IAAI,EAAiB,cAAc,EAAE,QAAQ,CAAC,CAAC;YAExE,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YAE1B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC,CAAC;YAExD,OAAO,UAAU,CAAC;SACnB;gBAAS;YACR,WAAW,EAAE,CAAC;SACf;IACH,CAAC;CAuBF;AAvFD,4CAuFC;uRArBC,KAAK,2CACH,cAAsB,EACtB,cAA8B;IAE9B,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAEnE,IAAI,CAAC,cAAc,EAAE;QACnB,GAAG,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;QAEvC,OAAO;YACL,cAAc,EAAE,EAAE;YAClB,oBAAoB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;SAC3D,CAAC;KACH;IAED,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAE/B,MAAM,oBAAoB,GAAG,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAElE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,CAAC;AAClD,CAAC","sourcesContent":["import type { NetworkClientId, Provider } from '@metamask/network-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { MethodRegistry } from 'eth-method-registry';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { projectLogger } from '../logger';\nimport type { MethodData } from '../TransactionController';\n\nconst log = createModuleLogger(projectLogger, 'method-data');\n\nexport class MethodDataHelper {\n hub: EventEmitter;\n\n #getProvider: (networkClientId: NetworkClientId) => Provider;\n\n #getState: () => Record<string, MethodData>;\n\n #methodRegistryByNetworkClientId: Map<NetworkClientId, MethodRegistry>;\n\n #mutex = new Mutex();\n\n constructor({\n getProvider,\n getState,\n }: {\n getProvider: (networkClientId: NetworkClientId) => Provider;\n getState: () => Record<string, MethodData>;\n }) {\n this.hub = new EventEmitter();\n\n this.#getProvider = getProvider;\n this.#getState = getState;\n this.#methodRegistryByNetworkClientId = new Map();\n }\n\n async lookup(\n fourBytePrefix: string,\n networkClientId: NetworkClientId,\n ): Promise<MethodData> {\n log('lookup', fourBytePrefix, networkClientId);\n\n const releaseLock = await this.#mutex.acquire();\n\n try {\n const cachedResult = this.#getState()[fourBytePrefix];\n\n if (cachedResult) {\n log('Cached', cachedResult);\n return cachedResult;\n }\n\n let registry = this.#methodRegistryByNetworkClientId.get(networkClientId);\n\n if (!registry) {\n const provider = this.#getProvider(networkClientId);\n\n // @ts-expect-error Type in eth-method-registry is inappropriate and should be changed\n registry = new MethodRegistry({ provider });\n\n this.#methodRegistryByNetworkClientId.set(networkClientId, registry);\n\n log('Created registry', networkClientId);\n }\n\n const methodData = await this.#registryLookup(fourBytePrefix, registry);\n\n log('Result', methodData);\n\n this.hub.emit('update', { fourBytePrefix, methodData });\n\n return methodData;\n } finally {\n releaseLock();\n }\n }\n\n async #registryLookup(\n fourBytePrefix: string,\n methodRegistry: MethodRegistry,\n ): Promise<MethodData> {\n const registryMethod = await methodRegistry.lookup(fourBytePrefix);\n\n if (!registryMethod) {\n log('No method found', fourBytePrefix);\n\n return {\n registryMethod: '',\n parsedRegistryMethod: { name: undefined, args: undefined },\n };\n }\n\n log('Parsing', registryMethod);\n\n const parsedRegistryMethod = methodRegistry.parse(registryMethod);\n\n return { registryMethod, parsedRegistryMethod };\n }\n}\n"]}
@@ -14,7 +14,7 @@ import { createModuleLogger } from "@metamask/utils";
14
14
  import { Mutex } from "async-mutex";
15
15
  import { MethodRegistry } from "eth-method-registry";
16
16
  // This package purposefully relies on Node's EventEmitter module.
17
- // eslint-disable-next-line import/no-nodejs-modules
17
+ // eslint-disable-next-line import-x/no-nodejs-modules
18
18
  import EventEmitter from "events";
19
19
  import { projectLogger } from "../logger.mjs";
20
20
  const log = createModuleLogger(projectLogger, 'method-data');
@@ -1 +1 @@
1
- {"version":3,"file":"MethodDataHelper.mjs","sourceRoot":"","sources":["../../src/helpers/MethodDataHelper.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AACrD,OAAO,EAAE,KAAK,EAAE,oBAAoB;AACpC,OAAO,EAAE,cAAc,EAAE,4BAA4B;AACrD,kEAAkE;AAClE,oDAAoD;AACpD,OAAO,YAAY,eAAe;AAElC,OAAO,EAAE,aAAa,EAAE,sBAAkB;AAG1C,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AAE7D,MAAM,OAAO,gBAAgB;IAW3B,YAAY,EACV,WAAW,EACX,QAAQ,GAIT;;QAdD,gDAA6D;QAE7D,6CAA4C;QAE5C,oEAAuE;QAEvE,kCAAS,IAAI,KAAK,EAAE,EAAC;QASnB,IAAI,CAAC,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;QAE9B,uBAAA,IAAI,iCAAgB,WAAW,MAAA,CAAC;QAChC,uBAAA,IAAI,8BAAa,QAAQ,MAAA,CAAC;QAC1B,uBAAA,IAAI,qDAAoC,IAAI,GAAG,EAAE,MAAA,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,MAAM,CACV,cAAsB,EACtB,eAAgC;QAEhC,GAAG,CAAC,QAAQ,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;QAE/C,MAAM,WAAW,GAAG,MAAM,uBAAA,IAAI,+BAAO,CAAC,OAAO,EAAE,CAAC;QAEhD,IAAI;YACF,MAAM,YAAY,GAAG,uBAAA,IAAI,kCAAU,MAAd,IAAI,CAAY,CAAC,cAAc,CAAC,CAAC;YAEtD,IAAI,YAAY,EAAE;gBAChB,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;gBAC5B,OAAO,YAAY,CAAC;aACrB;YAED,IAAI,QAAQ,GAAG,uBAAA,IAAI,yDAAiC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YAE1E,IAAI,CAAC,QAAQ,EAAE;gBACb,MAAM,QAAQ,GAAG,uBAAA,IAAI,qCAAa,MAAjB,IAAI,EAAc,eAAe,CAAC,CAAC;gBAEpD,sFAAsF;gBACtF,QAAQ,GAAG,IAAI,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAE5C,uBAAA,IAAI,yDAAiC,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;gBAErE,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;aAC1C;YAED,MAAM,UAAU,GAAG,MAAM,uBAAA,IAAI,qEAAgB,MAApB,IAAI,EAAiB,cAAc,EAAE,QAAQ,CAAC,CAAC;YAExE,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YAE1B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC,CAAC;YAExD,OAAO,UAAU,CAAC;SACnB;gBAAS;YACR,WAAW,EAAE,CAAC;SACf;IACH,CAAC;CAuBF;uRArBC,KAAK,2CACH,cAAsB,EACtB,cAA8B;IAE9B,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAEnE,IAAI,CAAC,cAAc,EAAE;QACnB,GAAG,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;QAEvC,OAAO;YACL,cAAc,EAAE,EAAE;YAClB,oBAAoB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;SAC3D,CAAC;KACH;IAED,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAE/B,MAAM,oBAAoB,GAAG,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAElE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,CAAC;AAClD,CAAC","sourcesContent":["import type { NetworkClientId, Provider } from '@metamask/network-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { MethodRegistry } from 'eth-method-registry';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { projectLogger } from '../logger';\nimport type { MethodData } from '../TransactionController';\n\nconst log = createModuleLogger(projectLogger, 'method-data');\n\nexport class MethodDataHelper {\n hub: EventEmitter;\n\n #getProvider: (networkClientId: NetworkClientId) => Provider;\n\n #getState: () => Record<string, MethodData>;\n\n #methodRegistryByNetworkClientId: Map<NetworkClientId, MethodRegistry>;\n\n #mutex = new Mutex();\n\n constructor({\n getProvider,\n getState,\n }: {\n getProvider: (networkClientId: NetworkClientId) => Provider;\n getState: () => Record<string, MethodData>;\n }) {\n this.hub = new EventEmitter();\n\n this.#getProvider = getProvider;\n this.#getState = getState;\n this.#methodRegistryByNetworkClientId = new Map();\n }\n\n async lookup(\n fourBytePrefix: string,\n networkClientId: NetworkClientId,\n ): Promise<MethodData> {\n log('lookup', fourBytePrefix, networkClientId);\n\n const releaseLock = await this.#mutex.acquire();\n\n try {\n const cachedResult = this.#getState()[fourBytePrefix];\n\n if (cachedResult) {\n log('Cached', cachedResult);\n return cachedResult;\n }\n\n let registry = this.#methodRegistryByNetworkClientId.get(networkClientId);\n\n if (!registry) {\n const provider = this.#getProvider(networkClientId);\n\n // @ts-expect-error Type in eth-method-registry is inappropriate and should be changed\n registry = new MethodRegistry({ provider });\n\n this.#methodRegistryByNetworkClientId.set(networkClientId, registry);\n\n log('Created registry', networkClientId);\n }\n\n const methodData = await this.#registryLookup(fourBytePrefix, registry);\n\n log('Result', methodData);\n\n this.hub.emit('update', { fourBytePrefix, methodData });\n\n return methodData;\n } finally {\n releaseLock();\n }\n }\n\n async #registryLookup(\n fourBytePrefix: string,\n methodRegistry: MethodRegistry,\n ): Promise<MethodData> {\n const registryMethod = await methodRegistry.lookup(fourBytePrefix);\n\n if (!registryMethod) {\n log('No method found', fourBytePrefix);\n\n return {\n registryMethod: '',\n parsedRegistryMethod: { name: undefined, args: undefined },\n };\n }\n\n log('Parsing', registryMethod);\n\n const parsedRegistryMethod = methodRegistry.parse(registryMethod);\n\n return { registryMethod, parsedRegistryMethod };\n }\n}\n"]}
1
+ {"version":3,"file":"MethodDataHelper.mjs","sourceRoot":"","sources":["../../src/helpers/MethodDataHelper.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AACrD,OAAO,EAAE,KAAK,EAAE,oBAAoB;AACpC,OAAO,EAAE,cAAc,EAAE,4BAA4B;AACrD,kEAAkE;AAClE,sDAAsD;AACtD,OAAO,YAAY,eAAe;AAElC,OAAO,EAAE,aAAa,EAAE,sBAAkB;AAG1C,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AAE7D,MAAM,OAAO,gBAAgB;IAW3B,YAAY,EACV,WAAW,EACX,QAAQ,GAIT;;QAdD,gDAA6D;QAE7D,6CAA4C;QAE5C,oEAAuE;QAEvE,kCAAS,IAAI,KAAK,EAAE,EAAC;QASnB,IAAI,CAAC,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;QAE9B,uBAAA,IAAI,iCAAgB,WAAW,MAAA,CAAC;QAChC,uBAAA,IAAI,8BAAa,QAAQ,MAAA,CAAC;QAC1B,uBAAA,IAAI,qDAAoC,IAAI,GAAG,EAAE,MAAA,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,MAAM,CACV,cAAsB,EACtB,eAAgC;QAEhC,GAAG,CAAC,QAAQ,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;QAE/C,MAAM,WAAW,GAAG,MAAM,uBAAA,IAAI,+BAAO,CAAC,OAAO,EAAE,CAAC;QAEhD,IAAI;YACF,MAAM,YAAY,GAAG,uBAAA,IAAI,kCAAU,MAAd,IAAI,CAAY,CAAC,cAAc,CAAC,CAAC;YAEtD,IAAI,YAAY,EAAE;gBAChB,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;gBAC5B,OAAO,YAAY,CAAC;aACrB;YAED,IAAI,QAAQ,GAAG,uBAAA,IAAI,yDAAiC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YAE1E,IAAI,CAAC,QAAQ,EAAE;gBACb,MAAM,QAAQ,GAAG,uBAAA,IAAI,qCAAa,MAAjB,IAAI,EAAc,eAAe,CAAC,CAAC;gBAEpD,sFAAsF;gBACtF,QAAQ,GAAG,IAAI,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAE5C,uBAAA,IAAI,yDAAiC,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;gBAErE,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;aAC1C;YAED,MAAM,UAAU,GAAG,MAAM,uBAAA,IAAI,qEAAgB,MAApB,IAAI,EAAiB,cAAc,EAAE,QAAQ,CAAC,CAAC;YAExE,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YAE1B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC,CAAC;YAExD,OAAO,UAAU,CAAC;SACnB;gBAAS;YACR,WAAW,EAAE,CAAC;SACf;IACH,CAAC;CAuBF;uRArBC,KAAK,2CACH,cAAsB,EACtB,cAA8B;IAE9B,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAEnE,IAAI,CAAC,cAAc,EAAE;QACnB,GAAG,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;QAEvC,OAAO;YACL,cAAc,EAAE,EAAE;YAClB,oBAAoB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;SAC3D,CAAC;KACH;IAED,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAE/B,MAAM,oBAAoB,GAAG,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAElE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,CAAC;AAClD,CAAC","sourcesContent":["import type { NetworkClientId, Provider } from '@metamask/network-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { MethodRegistry } from 'eth-method-registry';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { projectLogger } from '../logger';\nimport type { MethodData } from '../TransactionController';\n\nconst log = createModuleLogger(projectLogger, 'method-data');\n\nexport class MethodDataHelper {\n hub: EventEmitter;\n\n #getProvider: (networkClientId: NetworkClientId) => Provider;\n\n #getState: () => Record<string, MethodData>;\n\n #methodRegistryByNetworkClientId: Map<NetworkClientId, MethodRegistry>;\n\n #mutex = new Mutex();\n\n constructor({\n getProvider,\n getState,\n }: {\n getProvider: (networkClientId: NetworkClientId) => Provider;\n getState: () => Record<string, MethodData>;\n }) {\n this.hub = new EventEmitter();\n\n this.#getProvider = getProvider;\n this.#getState = getState;\n this.#methodRegistryByNetworkClientId = new Map();\n }\n\n async lookup(\n fourBytePrefix: string,\n networkClientId: NetworkClientId,\n ): Promise<MethodData> {\n log('lookup', fourBytePrefix, networkClientId);\n\n const releaseLock = await this.#mutex.acquire();\n\n try {\n const cachedResult = this.#getState()[fourBytePrefix];\n\n if (cachedResult) {\n log('Cached', cachedResult);\n return cachedResult;\n }\n\n let registry = this.#methodRegistryByNetworkClientId.get(networkClientId);\n\n if (!registry) {\n const provider = this.#getProvider(networkClientId);\n\n // @ts-expect-error Type in eth-method-registry is inappropriate and should be changed\n registry = new MethodRegistry({ provider });\n\n this.#methodRegistryByNetworkClientId.set(networkClientId, registry);\n\n log('Created registry', networkClientId);\n }\n\n const methodData = await this.#registryLookup(fourBytePrefix, registry);\n\n log('Result', methodData);\n\n this.hub.emit('update', { fourBytePrefix, methodData });\n\n return methodData;\n } finally {\n releaseLock();\n }\n }\n\n async #registryLookup(\n fourBytePrefix: string,\n methodRegistry: MethodRegistry,\n ): Promise<MethodData> {\n const registryMethod = await methodRegistry.lookup(fourBytePrefix);\n\n if (!registryMethod) {\n log('No method found', fourBytePrefix);\n\n return {\n registryMethod: '',\n parsedRegistryMethod: { name: undefined, args: undefined },\n };\n }\n\n log('Parsing', registryMethod);\n\n const parsedRegistryMethod = methodRegistry.parse(registryMethod);\n\n return { registryMethod, parsedRegistryMethod };\n }\n}\n"]}
@@ -18,7 +18,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.PendingTransactionTracker = void 0;
19
19
  const controller_utils_1 = require("@metamask/controller-utils");
20
20
  // This package purposefully relies on Node's EventEmitter module.
21
- // eslint-disable-next-line import/no-nodejs-modules
21
+ // eslint-disable-next-line import-x/no-nodejs-modules
22
22
  const events_1 = __importDefault(require("events"));
23
23
  const lodash_1 = require("lodash");
24
24
  const logger_1 = require("../logger.cjs");
@@ -1 +1 @@
1
- {"version":3,"file":"PendingTransactionTracker.cjs","sourceRoot":"","sources":["../../src/helpers/PendingTransactionTracker.ts"],"names":[],"mappings":"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","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';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import/no-nodejs-modules\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';\nimport { TransactionPoller } from './TransactionPoller';\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 #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 #log: debug.Debugger;\n\n #getGlobalLock: () => Promise<() => void>;\n\n #publishTransaction: (\n ethQuery: EthQuery,\n transactionMeta: TransactionMeta,\n ) => Promise<string>;\n\n #running: boolean;\n\n #transactionPoller: TransactionPoller;\n\n #beforeCheckPendingTransaction: (transactionMeta: TransactionMeta) => boolean;\n\n #beforePublish: (transactionMeta: TransactionMeta) => boolean;\n\n constructor({\n blockTracker,\n getChainId,\n getEthQuery,\n getTransactions,\n isResubmitEnabled,\n getGlobalLock,\n publishTransaction,\n hooks,\n }: {\n blockTracker: BlockTracker;\n getChainId: () => string;\n getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n getTransactions: () => TransactionMeta[];\n isResubmitEnabled?: () => boolean;\n getGlobalLock: () => Promise<() => void>;\n publishTransaction: (\n ethQuery: EthQuery,\n transactionMeta: TransactionMeta,\n ) => 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.#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.#log = createModuleLogger(log, getChainId());\n this.#getGlobalLock = getGlobalLock;\n this.#publishTransaction = publishTransaction;\n this.#running = false;\n this.#transactionPoller = new TransactionPoller(blockTracker);\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(pendingTransactions);\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 this.#log('Failed to check transaction', error);\n } finally {\n releaseLock();\n }\n }\n\n #start(pendingTransactions: TransactionMeta[]) {\n this.#transactionPoller.setPendingTransactions(pendingTransactions);\n\n if (this.#running) {\n return;\n }\n\n this.#transactionPoller.start(this.#listener);\n this.#running = true;\n\n this.#log('Started polling');\n }\n\n stop() {\n if (!this.#running) {\n return;\n }\n\n this.#transactionPoller.stop();\n this.#running = false;\n\n this.#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 this.#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 this.#log('Failed to resubmit transactions', error);\n }\n }\n\n async #checkTransactions() {\n this.#log('Checking transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n this.#log('No pending transactions to check');\n return;\n }\n\n this.#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 this.#log('Resubmitting transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n this.#log('No pending transactions to resubmit');\n return;\n }\n\n this.#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() ||\n error.message?.toLowerCase() ||\n String(error);\n\n if (this.#isKnownTransactionError(errorMessage)) {\n this.#log('Ignoring known transaction error', errorMessage);\n continue;\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 if (!this.#beforePublish(txMeta)) {\n return;\n }\n\n const ethQuery = this.#getEthQuery(txMeta.networkClientId);\n await this.#publishTransaction(ethQuery, txMeta);\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 this.#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 this.#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 this.#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 this.#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 this.#log('Incrementing dropped block count', { id, droppedBlockCount });\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount + 1);\n return false;\n }\n\n this.#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 this.#log('Transaction failed', txMeta.id, error);\n this.hub.emit('transaction-failed', txMeta, error);\n }\n\n #dropTransaction(txMeta: TransactionMeta) {\n this.#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"]}
1
+ {"version":3,"file":"PendingTransactionTracker.cjs","sourceRoot":"","sources":["../../src/helpers/PendingTransactionTracker.ts"],"names":[],"mappings":"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","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';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import-x/no-nodejs-modules\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';\nimport { TransactionPoller } from './TransactionPoller';\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 #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 #log: debug.Debugger;\n\n #getGlobalLock: () => Promise<() => void>;\n\n #publishTransaction: (\n ethQuery: EthQuery,\n transactionMeta: TransactionMeta,\n ) => Promise<string>;\n\n #running: boolean;\n\n #transactionPoller: TransactionPoller;\n\n #beforeCheckPendingTransaction: (transactionMeta: TransactionMeta) => boolean;\n\n #beforePublish: (transactionMeta: TransactionMeta) => boolean;\n\n constructor({\n blockTracker,\n getChainId,\n getEthQuery,\n getTransactions,\n isResubmitEnabled,\n getGlobalLock,\n publishTransaction,\n hooks,\n }: {\n blockTracker: BlockTracker;\n getChainId: () => string;\n getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n getTransactions: () => TransactionMeta[];\n isResubmitEnabled?: () => boolean;\n getGlobalLock: () => Promise<() => void>;\n publishTransaction: (\n ethQuery: EthQuery,\n transactionMeta: TransactionMeta,\n ) => 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.#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.#log = createModuleLogger(log, getChainId());\n this.#getGlobalLock = getGlobalLock;\n this.#publishTransaction = publishTransaction;\n this.#running = false;\n this.#transactionPoller = new TransactionPoller(blockTracker);\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(pendingTransactions);\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 this.#log('Failed to check transaction', error);\n } finally {\n releaseLock();\n }\n }\n\n #start(pendingTransactions: TransactionMeta[]) {\n this.#transactionPoller.setPendingTransactions(pendingTransactions);\n\n if (this.#running) {\n return;\n }\n\n this.#transactionPoller.start(this.#listener);\n this.#running = true;\n\n this.#log('Started polling');\n }\n\n stop() {\n if (!this.#running) {\n return;\n }\n\n this.#transactionPoller.stop();\n this.#running = false;\n\n this.#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 this.#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 this.#log('Failed to resubmit transactions', error);\n }\n }\n\n async #checkTransactions() {\n this.#log('Checking transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n this.#log('No pending transactions to check');\n return;\n }\n\n this.#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 this.#log('Resubmitting transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n this.#log('No pending transactions to resubmit');\n return;\n }\n\n this.#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() ||\n error.message?.toLowerCase() ||\n String(error);\n\n if (this.#isKnownTransactionError(errorMessage)) {\n this.#log('Ignoring known transaction error', errorMessage);\n continue;\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 if (!this.#beforePublish(txMeta)) {\n return;\n }\n\n const ethQuery = this.#getEthQuery(txMeta.networkClientId);\n await this.#publishTransaction(ethQuery, txMeta);\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 this.#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 this.#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 this.#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 this.#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 this.#log('Incrementing dropped block count', { id, droppedBlockCount });\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount + 1);\n return false;\n }\n\n this.#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 this.#log('Transaction failed', txMeta.id, error);\n this.hub.emit('transaction-failed', txMeta, error);\n }\n\n #dropTransaction(txMeta: TransactionMeta) {\n this.#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"]}
@@ -12,7 +12,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
12
12
  var _PendingTransactionTracker_instances, _PendingTransactionTracker_droppedBlockCountByHash, _PendingTransactionTracker_getChainId, _PendingTransactionTracker_getEthQuery, _PendingTransactionTracker_getTransactions, _PendingTransactionTracker_isResubmitEnabled, _PendingTransactionTracker_listener, _PendingTransactionTracker_log, _PendingTransactionTracker_getGlobalLock, _PendingTransactionTracker_publishTransaction, _PendingTransactionTracker_running, _PendingTransactionTracker_transactionPoller, _PendingTransactionTracker_beforeCheckPendingTransaction, _PendingTransactionTracker_beforePublish, _PendingTransactionTracker_start, _PendingTransactionTracker_onLatestBlock, _PendingTransactionTracker_checkTransactions, _PendingTransactionTracker_resubmitTransactions, _PendingTransactionTracker_isKnownTransactionError, _PendingTransactionTracker_resubmitTransaction, _PendingTransactionTracker_isResubmitDue, _PendingTransactionTracker_checkTransaction, _PendingTransactionTracker_onTransactionConfirmed, _PendingTransactionTracker_isTransactionDropped, _PendingTransactionTracker_isNonceTaken, _PendingTransactionTracker_getPendingTransactions, _PendingTransactionTracker_warnTransaction, _PendingTransactionTracker_failTransaction, _PendingTransactionTracker_dropTransaction, _PendingTransactionTracker_updateTransaction, _PendingTransactionTracker_getTransactionReceipt, _PendingTransactionTracker_getBlockByHash, _PendingTransactionTracker_getNetworkTransactionCount, _PendingTransactionTracker_getCurrentChainTransactions;
13
13
  import { query } from "@metamask/controller-utils";
14
14
  // This package purposefully relies on Node's EventEmitter module.
15
- // eslint-disable-next-line import/no-nodejs-modules
15
+ // eslint-disable-next-line import-x/no-nodejs-modules
16
16
  import EventEmitter from "events";
17
17
  import $lodash from "lodash";
18
18
  const { cloneDeep, merge } = $lodash;