@metamask/transaction-controller 52.0.0 → 52.2.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 (96) hide show
  1. package/CHANGELOG.md +52 -4
  2. package/dist/TransactionController.cjs +113 -36
  3. package/dist/TransactionController.cjs.map +1 -1
  4. package/dist/TransactionController.d.cts +38 -5
  5. package/dist/TransactionController.d.cts.map +1 -1
  6. package/dist/TransactionController.d.mts +38 -5
  7. package/dist/TransactionController.d.mts.map +1 -1
  8. package/dist/TransactionController.mjs +114 -37
  9. package/dist/TransactionController.mjs.map +1 -1
  10. package/dist/helpers/GasFeePoller.cjs +73 -1
  11. package/dist/helpers/GasFeePoller.cjs.map +1 -1
  12. package/dist/helpers/GasFeePoller.d.cts +20 -2
  13. package/dist/helpers/GasFeePoller.d.cts.map +1 -1
  14. package/dist/helpers/GasFeePoller.d.mts +20 -2
  15. package/dist/helpers/GasFeePoller.d.mts.map +1 -1
  16. package/dist/helpers/GasFeePoller.mjs +72 -1
  17. package/dist/helpers/GasFeePoller.mjs.map +1 -1
  18. package/dist/hooks/CollectPublishHook.cjs +84 -0
  19. package/dist/hooks/CollectPublishHook.cjs.map +1 -0
  20. package/dist/hooks/CollectPublishHook.d.cts +29 -0
  21. package/dist/hooks/CollectPublishHook.d.cts.map +1 -0
  22. package/dist/hooks/CollectPublishHook.d.mts +29 -0
  23. package/dist/hooks/CollectPublishHook.d.mts.map +1 -0
  24. package/dist/hooks/CollectPublishHook.mjs +80 -0
  25. package/dist/hooks/CollectPublishHook.mjs.map +1 -0
  26. package/dist/hooks/ExtraTransactionsPublishHook.cjs +90 -0
  27. package/dist/hooks/ExtraTransactionsPublishHook.cjs.map +1 -0
  28. package/dist/hooks/ExtraTransactionsPublishHook.d.cts +18 -0
  29. package/dist/hooks/ExtraTransactionsPublishHook.d.cts.map +1 -0
  30. package/dist/hooks/ExtraTransactionsPublishHook.d.mts +18 -0
  31. package/dist/hooks/ExtraTransactionsPublishHook.d.mts.map +1 -0
  32. package/dist/hooks/ExtraTransactionsPublishHook.mjs +86 -0
  33. package/dist/hooks/ExtraTransactionsPublishHook.mjs.map +1 -0
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +1 -1
  36. package/dist/index.d.cts.map +1 -1
  37. package/dist/index.d.mts +1 -1
  38. package/dist/index.d.mts.map +1 -1
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/types.cjs.map +1 -1
  41. package/dist/types.d.cts +143 -2
  42. package/dist/types.d.cts.map +1 -1
  43. package/dist/types.d.mts +143 -2
  44. package/dist/types.d.mts.map +1 -1
  45. package/dist/types.mjs.map +1 -1
  46. package/dist/utils/batch.cjs +142 -1
  47. package/dist/utils/batch.cjs.map +1 -1
  48. package/dist/utils/batch.d.cts +7 -1
  49. package/dist/utils/batch.d.cts.map +1 -1
  50. package/dist/utils/batch.d.mts +7 -1
  51. package/dist/utils/batch.d.mts.map +1 -1
  52. package/dist/utils/batch.mjs +142 -1
  53. package/dist/utils/batch.mjs.map +1 -1
  54. package/dist/utils/eip7702.cjs +12 -0
  55. package/dist/utils/eip7702.cjs.map +1 -1
  56. package/dist/utils/eip7702.d.cts.map +1 -1
  57. package/dist/utils/eip7702.d.mts.map +1 -1
  58. package/dist/utils/eip7702.mjs +12 -0
  59. package/dist/utils/eip7702.mjs.map +1 -1
  60. package/dist/utils/feature-flags.cjs +2 -2
  61. package/dist/utils/feature-flags.cjs.map +1 -1
  62. package/dist/utils/feature-flags.d.cts +2 -2
  63. package/dist/utils/feature-flags.d.mts +2 -2
  64. package/dist/utils/feature-flags.mjs +2 -2
  65. package/dist/utils/feature-flags.mjs.map +1 -1
  66. package/dist/utils/gas.cjs +115 -11
  67. package/dist/utils/gas.cjs.map +1 -1
  68. package/dist/utils/gas.d.cts +16 -5
  69. package/dist/utils/gas.d.cts.map +1 -1
  70. package/dist/utils/gas.d.mts +16 -5
  71. package/dist/utils/gas.d.mts.map +1 -1
  72. package/dist/utils/gas.mjs +115 -11
  73. package/dist/utils/gas.mjs.map +1 -1
  74. package/dist/utils/nonce.cjs +3 -3
  75. package/dist/utils/nonce.cjs.map +1 -1
  76. package/dist/utils/nonce.d.cts +2 -2
  77. package/dist/utils/nonce.d.cts.map +1 -1
  78. package/dist/utils/nonce.d.mts +2 -2
  79. package/dist/utils/nonce.d.mts.map +1 -1
  80. package/dist/utils/nonce.mjs +3 -3
  81. package/dist/utils/nonce.mjs.map +1 -1
  82. package/dist/utils/simulation-api.cjs.map +1 -1
  83. package/dist/utils/simulation-api.d.cts +46 -5
  84. package/dist/utils/simulation-api.d.cts.map +1 -1
  85. package/dist/utils/simulation-api.d.mts +46 -5
  86. package/dist/utils/simulation-api.d.mts.map +1 -1
  87. package/dist/utils/simulation-api.mjs.map +1 -1
  88. package/dist/utils/simulation.cjs +46 -7
  89. package/dist/utils/simulation.cjs.map +1 -1
  90. package/dist/utils/simulation.d.cts +6 -2
  91. package/dist/utils/simulation.d.cts.map +1 -1
  92. package/dist/utils/simulation.d.mts +6 -2
  93. package/dist/utils/simulation.d.mts.map +1 -1
  94. package/dist/utils/simulation.mjs +46 -7
  95. package/dist/utils/simulation.mjs.map +1 -1
  96. package/package.json +2 -2
@@ -15,7 +15,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
15
15
  };
16
16
  var _GasFeePoller_instances, _GasFeePoller_findNetworkClientIdByChainId, _GasFeePoller_gasFeeFlows, _GasFeePoller_getGasFeeControllerEstimates, _GasFeePoller_getProvider, _GasFeePoller_getTransactions, _GasFeePoller_layer1GasFeeFlows, _GasFeePoller_timeout, _GasFeePoller_running, _GasFeePoller_start, _GasFeePoller_stop, _GasFeePoller_onTimeout, _GasFeePoller_updateUnapprovedTransactions, _GasFeePoller_updateUnapprovedTransaction, _GasFeePoller_updateTransactionGasFeeEstimates, _GasFeePoller_updateTransactionLayer1GasFee, _GasFeePoller_getUnapprovedTransactions, _GasFeePoller_getGasFeeControllerData;
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.GasFeePoller = void 0;
18
+ exports.updateTransactionGasFees = 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.
@@ -185,4 +185,76 @@ _GasFeePoller_findNetworkClientIdByChainId = new WeakMap(), _GasFeePoller_gasFee
185
185
  });
186
186
  return new Map(await Promise.all(entryPromises));
187
187
  };
188
+ /**
189
+ * Update the gas fees for a transaction.
190
+ *
191
+ * @param args - Argument bag.
192
+ * @param args.txMeta - The transaction meta.
193
+ * @param args.gasFeeEstimates - The gas fee estimates.
194
+ * @param args.gasFeeEstimatesLoaded - Whether the gas fee estimates are loaded.
195
+ * @param args.getEIP1559Compatibility - A function for verifying a network is EIP-1559 compatible.
196
+ * @param args.isTxParamsGasFeeUpdatesEnabled - Whether to update the gas fee properties in `txParams`.
197
+ * @param args.layer1GasFee - The layer 1 gas fee.
198
+ */
199
+ async function updateTransactionGasFees({ txMeta, getEIP1559Compatibility, gasFeeEstimates, gasFeeEstimatesLoaded, isTxParamsGasFeeUpdatesEnabled, layer1GasFee, }) {
200
+ const userFeeLevel = txMeta.userFeeLevel;
201
+ const isUsingGasFeeEstimateLevel = Object.values(types_1.GasFeeEstimateLevel).includes(userFeeLevel);
202
+ const { type: gasEstimateType } = gasFeeEstimates ?? {};
203
+ if (isTxParamsGasFeeUpdatesEnabled && isUsingGasFeeEstimateLevel) {
204
+ const isEIP1559Compatible = txMeta.txParams.type !== types_1.TransactionEnvelopeType.legacy &&
205
+ (await getEIP1559Compatibility(txMeta.networkClientId));
206
+ if (isEIP1559Compatible) {
207
+ // Handle EIP-1559 compatible transactions
208
+ if (gasEstimateType === types_1.GasFeeEstimateType.FeeMarket) {
209
+ const feeMarketGasFeeEstimates = gasFeeEstimates;
210
+ txMeta.txParams.maxFeePerGas =
211
+ feeMarketGasFeeEstimates[userFeeLevel].maxFeePerGas;
212
+ txMeta.txParams.maxPriorityFeePerGas =
213
+ feeMarketGasFeeEstimates[userFeeLevel].maxPriorityFeePerGas;
214
+ }
215
+ if (gasEstimateType === types_1.GasFeeEstimateType.GasPrice) {
216
+ const gasPriceGasFeeEstimates = gasFeeEstimates;
217
+ txMeta.txParams.maxFeePerGas = gasPriceGasFeeEstimates.gasPrice;
218
+ txMeta.txParams.maxPriorityFeePerGas = gasPriceGasFeeEstimates.gasPrice;
219
+ }
220
+ if (gasEstimateType === types_1.GasFeeEstimateType.Legacy) {
221
+ const legacyGasFeeEstimates = gasFeeEstimates;
222
+ const gasPrice = legacyGasFeeEstimates[userFeeLevel];
223
+ txMeta.txParams.maxFeePerGas = gasPrice;
224
+ txMeta.txParams.maxPriorityFeePerGas = gasPrice;
225
+ }
226
+ // Remove gasPrice for EIP-1559 transactions
227
+ delete txMeta.txParams.gasPrice;
228
+ }
229
+ else {
230
+ // Handle non-EIP-1559 transactions
231
+ if (gasEstimateType === types_1.GasFeeEstimateType.FeeMarket) {
232
+ const feeMarketGasFeeEstimates = gasFeeEstimates;
233
+ txMeta.txParams.gasPrice =
234
+ feeMarketGasFeeEstimates[userFeeLevel].maxFeePerGas;
235
+ }
236
+ if (gasEstimateType === types_1.GasFeeEstimateType.GasPrice) {
237
+ const gasPriceGasFeeEstimates = gasFeeEstimates;
238
+ txMeta.txParams.gasPrice = gasPriceGasFeeEstimates.gasPrice;
239
+ }
240
+ if (gasEstimateType === types_1.GasFeeEstimateType.Legacy) {
241
+ const legacyGasFeeEstimates = gasFeeEstimates;
242
+ txMeta.txParams.gasPrice = legacyGasFeeEstimates[userFeeLevel];
243
+ }
244
+ // Remove EIP-1559 specific parameters for legacy transactions
245
+ delete txMeta.txParams.maxFeePerGas;
246
+ delete txMeta.txParams.maxPriorityFeePerGas;
247
+ }
248
+ }
249
+ if (gasFeeEstimates) {
250
+ txMeta.gasFeeEstimates = gasFeeEstimates;
251
+ }
252
+ if (gasFeeEstimatesLoaded !== undefined) {
253
+ txMeta.gasFeeEstimatesLoaded = gasFeeEstimatesLoaded;
254
+ }
255
+ if (layer1GasFee) {
256
+ txMeta.layer1GasFee = layer1GasFee;
257
+ }
258
+ }
259
+ exports.updateTransactionGasFees = updateTransactionGasFees;
188
260
  //# sourceMappingURL=GasFeePoller.cjs.map
@@ -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-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 readonly #findNetworkClientIdByChainId: (\n chainId: Hex,\n ) => NetworkClientId | undefined;\n\n readonly #gasFeeFlows: GasFeeFlow[];\n\n readonly #getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n\n readonly #getProvider: (networkClientId: NetworkClientId) => Provider;\n\n readonly #getTransactions: () => TransactionMeta[];\n\n readonly #layer1GasFeeFlows: Layer1GasFeeFlow[];\n\n #timeout: ReturnType<typeof setTimeout> | undefined;\n\n #running = false;\n\n /**\n * Constructs a new instance of the GasFeePoller.\n *\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 GasPriceGasFeeEstimates,\n FeeMarketGasFeeEstimates,\n Layer1GasFeeFlow,\n LegacyGasFeeEstimates,\n TransactionMeta,\n} from '../types';\nimport {\n GasFeeEstimateLevel,\n GasFeeEstimateType,\n TransactionStatus,\n TransactionEnvelopeType,\n} 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 readonly #findNetworkClientIdByChainId: (\n chainId: Hex,\n ) => NetworkClientId | undefined;\n\n readonly #gasFeeFlows: GasFeeFlow[];\n\n readonly #getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n\n readonly #getProvider: (networkClientId: NetworkClientId) => Provider;\n\n readonly #getTransactions: () => TransactionMeta[];\n\n readonly #layer1GasFeeFlows: Layer1GasFeeFlow[];\n\n #timeout: ReturnType<typeof setTimeout> | undefined;\n\n #running = false;\n\n /**\n * Constructs a new instance of the GasFeePoller.\n *\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\n/**\n * Update the gas fees for a transaction.\n *\n * @param args - Argument bag.\n * @param args.txMeta - The transaction meta.\n * @param args.gasFeeEstimates - The gas fee estimates.\n * @param args.gasFeeEstimatesLoaded - Whether the gas fee estimates are loaded.\n * @param args.getEIP1559Compatibility - A function for verifying a network is EIP-1559 compatible.\n * @param args.isTxParamsGasFeeUpdatesEnabled - Whether to update the gas fee properties in `txParams`.\n * @param args.layer1GasFee - The layer 1 gas fee.\n */\nexport async function updateTransactionGasFees({\n txMeta,\n getEIP1559Compatibility,\n gasFeeEstimates,\n gasFeeEstimatesLoaded,\n isTxParamsGasFeeUpdatesEnabled,\n layer1GasFee,\n}: {\n txMeta: TransactionMeta;\n getEIP1559Compatibility: (\n networkClientId: NetworkClientId,\n ) => Promise<boolean>;\n gasFeeEstimates?: GasFeeEstimates;\n gasFeeEstimatesLoaded?: boolean;\n isTxParamsGasFeeUpdatesEnabled: boolean;\n layer1GasFee?: Hex;\n}): Promise<void> {\n const userFeeLevel = txMeta.userFeeLevel as GasFeeEstimateLevel;\n const isUsingGasFeeEstimateLevel =\n Object.values(GasFeeEstimateLevel).includes(userFeeLevel);\n const { type: gasEstimateType } = gasFeeEstimates ?? {};\n\n if (isTxParamsGasFeeUpdatesEnabled && isUsingGasFeeEstimateLevel) {\n const isEIP1559Compatible =\n txMeta.txParams.type !== TransactionEnvelopeType.legacy &&\n (await getEIP1559Compatibility(txMeta.networkClientId));\n\n if (isEIP1559Compatible) {\n // Handle EIP-1559 compatible transactions\n if (gasEstimateType === GasFeeEstimateType.FeeMarket) {\n const feeMarketGasFeeEstimates =\n gasFeeEstimates as FeeMarketGasFeeEstimates;\n\n txMeta.txParams.maxFeePerGas =\n feeMarketGasFeeEstimates[userFeeLevel].maxFeePerGas;\n txMeta.txParams.maxPriorityFeePerGas =\n feeMarketGasFeeEstimates[userFeeLevel].maxPriorityFeePerGas;\n }\n\n if (gasEstimateType === GasFeeEstimateType.GasPrice) {\n const gasPriceGasFeeEstimates =\n gasFeeEstimates as GasPriceGasFeeEstimates;\n\n txMeta.txParams.maxFeePerGas = gasPriceGasFeeEstimates.gasPrice;\n txMeta.txParams.maxPriorityFeePerGas = gasPriceGasFeeEstimates.gasPrice;\n }\n\n if (gasEstimateType === GasFeeEstimateType.Legacy) {\n const legacyGasFeeEstimates = gasFeeEstimates as LegacyGasFeeEstimates;\n const gasPrice = legacyGasFeeEstimates[userFeeLevel];\n\n txMeta.txParams.maxFeePerGas = gasPrice;\n txMeta.txParams.maxPriorityFeePerGas = gasPrice;\n }\n\n // Remove gasPrice for EIP-1559 transactions\n delete txMeta.txParams.gasPrice;\n } else {\n // Handle non-EIP-1559 transactions\n if (gasEstimateType === GasFeeEstimateType.FeeMarket) {\n const feeMarketGasFeeEstimates =\n gasFeeEstimates as FeeMarketGasFeeEstimates;\n txMeta.txParams.gasPrice =\n feeMarketGasFeeEstimates[userFeeLevel].maxFeePerGas;\n }\n\n if (gasEstimateType === GasFeeEstimateType.GasPrice) {\n const gasPriceGasFeeEstimates =\n gasFeeEstimates as GasPriceGasFeeEstimates;\n txMeta.txParams.gasPrice = gasPriceGasFeeEstimates.gasPrice;\n }\n\n if (gasEstimateType === GasFeeEstimateType.Legacy) {\n const legacyGasFeeEstimates = gasFeeEstimates as LegacyGasFeeEstimates;\n txMeta.txParams.gasPrice = legacyGasFeeEstimates[userFeeLevel];\n }\n\n // Remove EIP-1559 specific parameters for legacy transactions\n delete txMeta.txParams.maxFeePerGas;\n delete txMeta.txParams.maxPriorityFeePerGas;\n }\n }\n\n if (gasFeeEstimates) {\n txMeta.gasFeeEstimates = gasFeeEstimates;\n }\n\n if (gasFeeEstimatesLoaded !== undefined) {\n txMeta.gasFeeEstimatesLoaded = gasFeeEstimatesLoaded;\n }\n\n if (layer1GasFee) {\n txMeta.layer1GasFee = layer1GasFee;\n }\n}\n"]}
@@ -3,8 +3,7 @@ import type { FetchGasFeeEstimateOptions, GasFeeState } from "@metamask/gas-fee-
3
3
  import type { NetworkClientId, Provider } from "@metamask/network-controller";
4
4
  import type { Hex } from "@metamask/utils";
5
5
  import EventEmitter from "events";
6
- import type { GasFeeFlow, Layer1GasFeeFlow } from "../types.cjs";
7
- import { type TransactionMeta } from "../types.cjs";
6
+ import type { GasFeeEstimates, GasFeeFlow, Layer1GasFeeFlow, TransactionMeta } from "../types.cjs";
8
7
  /**
9
8
  * Automatically polls and updates suggested gas fees on unapproved transactions.
10
9
  */
@@ -33,4 +32,23 @@ export declare class GasFeePoller {
33
32
  onStateChange: (listener: () => void) => void;
34
33
  });
35
34
  }
35
+ /**
36
+ * Update the gas fees for a transaction.
37
+ *
38
+ * @param args - Argument bag.
39
+ * @param args.txMeta - The transaction meta.
40
+ * @param args.gasFeeEstimates - The gas fee estimates.
41
+ * @param args.gasFeeEstimatesLoaded - Whether the gas fee estimates are loaded.
42
+ * @param args.getEIP1559Compatibility - A function for verifying a network is EIP-1559 compatible.
43
+ * @param args.isTxParamsGasFeeUpdatesEnabled - Whether to update the gas fee properties in `txParams`.
44
+ * @param args.layer1GasFee - The layer 1 gas fee.
45
+ */
46
+ export declare function updateTransactionGasFees({ txMeta, getEIP1559Compatibility, gasFeeEstimates, gasFeeEstimatesLoaded, isTxParamsGasFeeUpdatesEnabled, layer1GasFee, }: {
47
+ txMeta: TransactionMeta;
48
+ getEIP1559Compatibility: (networkClientId: NetworkClientId) => Promise<boolean>;
49
+ gasFeeEstimates?: GasFeeEstimates;
50
+ gasFeeEstimatesLoaded?: boolean;
51
+ isTxParamsGasFeeUpdatesEnabled: boolean;
52
+ layer1GasFee?: Hex;
53
+ }): Promise<void>;
36
54
  //# sourceMappingURL=GasFeePoller.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GasFeePoller.d.cts","sourceRoot":"","sources":["../../src/helpers/GasFeePoller.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EACV,0BAA0B,EAC1B,WAAW,EACZ,qCAAqC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,qCAAqC;AAC9E,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,YAAY,eAAe;AAGlC,OAAO,KAAK,EAEV,UAAU,EAEV,gBAAgB,EACjB,qBAAiB;AAClB,OAAO,EAAqB,KAAK,eAAe,EAAE,qBAAiB;AAQnE;;GAEG;AACH,qBAAa,YAAY;;IACvB,GAAG,EAAE,YAAY,CAAsB;IAsBvC;;;;;;;;;;;OAWG;gBACS,EACV,4BAA4B,EAC5B,WAAW,EACX,4BAA4B,EAC5B,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,aAAa,GACd,EAAE;QACD,4BAA4B,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,eAAe,GAAG,SAAS,CAAC;QAC5E,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,4BAA4B,EAAE,CAC5B,OAAO,EAAE,0BAA0B,KAChC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC1B,WAAW,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,QAAQ,CAAC;QAC5D,eAAe,EAAE,MAAM,eAAe,EAAE,CAAC;QACzC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;QACtC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;KAC/C;CAsNF"}
1
+ {"version":3,"file":"GasFeePoller.d.cts","sourceRoot":"","sources":["../../src/helpers/GasFeePoller.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EACV,0BAA0B,EAC1B,WAAW,EACZ,qCAAqC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,qCAAqC;AAC9E,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,YAAY,eAAe;AAGlC,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EAIV,gBAAgB,EAEhB,eAAe,EAChB,qBAAiB;AAclB;;GAEG;AACH,qBAAa,YAAY;;IACvB,GAAG,EAAE,YAAY,CAAsB;IAsBvC;;;;;;;;;;;OAWG;gBACS,EACV,4BAA4B,EAC5B,WAAW,EACX,4BAA4B,EAC5B,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,aAAa,GACd,EAAE;QACD,4BAA4B,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,eAAe,GAAG,SAAS,CAAC;QAC5E,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,4BAA4B,EAAE,CAC5B,OAAO,EAAE,0BAA0B,KAChC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC1B,WAAW,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,QAAQ,CAAC;QAC5D,eAAe,EAAE,MAAM,eAAe,EAAE,CAAC;QACzC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;QACtC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;KAC/C;CAsNF;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,wBAAwB,CAAC,EAC7C,MAAM,EACN,uBAAuB,EACvB,eAAe,EACf,qBAAqB,EACrB,8BAA8B,EAC9B,YAAY,GACb,EAAE;IACD,MAAM,EAAE,eAAe,CAAC;IACxB,uBAAuB,EAAE,CACvB,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,8BAA8B,EAAE,OAAO,CAAC;IACxC,YAAY,CAAC,EAAE,GAAG,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8EhB"}
@@ -3,8 +3,7 @@ import type { FetchGasFeeEstimateOptions, GasFeeState } from "@metamask/gas-fee-
3
3
  import type { NetworkClientId, Provider } from "@metamask/network-controller";
4
4
  import type { Hex } from "@metamask/utils";
5
5
  import EventEmitter from "events";
6
- import type { GasFeeFlow, Layer1GasFeeFlow } from "../types.mjs";
7
- import { type TransactionMeta } from "../types.mjs";
6
+ import type { GasFeeEstimates, GasFeeFlow, Layer1GasFeeFlow, TransactionMeta } from "../types.mjs";
8
7
  /**
9
8
  * Automatically polls and updates suggested gas fees on unapproved transactions.
10
9
  */
@@ -33,4 +32,23 @@ export declare class GasFeePoller {
33
32
  onStateChange: (listener: () => void) => void;
34
33
  });
35
34
  }
35
+ /**
36
+ * Update the gas fees for a transaction.
37
+ *
38
+ * @param args - Argument bag.
39
+ * @param args.txMeta - The transaction meta.
40
+ * @param args.gasFeeEstimates - The gas fee estimates.
41
+ * @param args.gasFeeEstimatesLoaded - Whether the gas fee estimates are loaded.
42
+ * @param args.getEIP1559Compatibility - A function for verifying a network is EIP-1559 compatible.
43
+ * @param args.isTxParamsGasFeeUpdatesEnabled - Whether to update the gas fee properties in `txParams`.
44
+ * @param args.layer1GasFee - The layer 1 gas fee.
45
+ */
46
+ export declare function updateTransactionGasFees({ txMeta, getEIP1559Compatibility, gasFeeEstimates, gasFeeEstimatesLoaded, isTxParamsGasFeeUpdatesEnabled, layer1GasFee, }: {
47
+ txMeta: TransactionMeta;
48
+ getEIP1559Compatibility: (networkClientId: NetworkClientId) => Promise<boolean>;
49
+ gasFeeEstimates?: GasFeeEstimates;
50
+ gasFeeEstimatesLoaded?: boolean;
51
+ isTxParamsGasFeeUpdatesEnabled: boolean;
52
+ layer1GasFee?: Hex;
53
+ }): Promise<void>;
36
54
  //# sourceMappingURL=GasFeePoller.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GasFeePoller.d.mts","sourceRoot":"","sources":["../../src/helpers/GasFeePoller.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EACV,0BAA0B,EAC1B,WAAW,EACZ,qCAAqC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,qCAAqC;AAC9E,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,YAAY,eAAe;AAGlC,OAAO,KAAK,EAEV,UAAU,EAEV,gBAAgB,EACjB,qBAAiB;AAClB,OAAO,EAAqB,KAAK,eAAe,EAAE,qBAAiB;AAQnE;;GAEG;AACH,qBAAa,YAAY;;IACvB,GAAG,EAAE,YAAY,CAAsB;IAsBvC;;;;;;;;;;;OAWG;gBACS,EACV,4BAA4B,EAC5B,WAAW,EACX,4BAA4B,EAC5B,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,aAAa,GACd,EAAE;QACD,4BAA4B,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,eAAe,GAAG,SAAS,CAAC;QAC5E,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,4BAA4B,EAAE,CAC5B,OAAO,EAAE,0BAA0B,KAChC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC1B,WAAW,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,QAAQ,CAAC;QAC5D,eAAe,EAAE,MAAM,eAAe,EAAE,CAAC;QACzC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;QACtC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;KAC/C;CAsNF"}
1
+ {"version":3,"file":"GasFeePoller.d.mts","sourceRoot":"","sources":["../../src/helpers/GasFeePoller.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EACV,0BAA0B,EAC1B,WAAW,EACZ,qCAAqC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,qCAAqC;AAC9E,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,YAAY,eAAe;AAGlC,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EAIV,gBAAgB,EAEhB,eAAe,EAChB,qBAAiB;AAclB;;GAEG;AACH,qBAAa,YAAY;;IACvB,GAAG,EAAE,YAAY,CAAsB;IAsBvC;;;;;;;;;;;OAWG;gBACS,EACV,4BAA4B,EAC5B,WAAW,EACX,4BAA4B,EAC5B,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,aAAa,GACd,EAAE;QACD,4BAA4B,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,eAAe,GAAG,SAAS,CAAC;QAC5E,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,4BAA4B,EAAE,CAC5B,OAAO,EAAE,0BAA0B,KAChC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC1B,WAAW,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,QAAQ,CAAC;QAC5D,eAAe,EAAE,MAAM,eAAe,EAAE,CAAC;QACzC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;QACtC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;KAC/C;CAsNF;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,wBAAwB,CAAC,EAC7C,MAAM,EACN,uBAAuB,EACvB,eAAe,EACf,qBAAqB,EACrB,8BAA8B,EAC9B,YAAY,GACb,EAAE;IACD,MAAM,EAAE,eAAe,CAAC;IACxB,uBAAuB,EAAE,CACvB,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,8BAA8B,EAAE,OAAO,CAAC;IACxC,YAAY,CAAC,EAAE,GAAG,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8EhB"}
@@ -23,7 +23,7 @@ import { createModuleLogger } from "@metamask/utils";
23
23
  // eslint-disable-next-line import-x/no-nodejs-modules
24
24
  import EventEmitter from "events";
25
25
  import { projectLogger } from "../logger.mjs";
26
- import { TransactionStatus } from "../types.mjs";
26
+ import { GasFeeEstimateLevel, GasFeeEstimateType, TransactionStatus, TransactionEnvelopeType } from "../types.mjs";
27
27
  import { getGasFeeFlow } from "../utils/gas-flow.mjs";
28
28
  import { getTransactionLayer1GasFee } from "../utils/layer1-gas-fee-flow.mjs";
29
29
  const log = createModuleLogger(projectLogger, 'gas-fee-poller');
@@ -185,4 +185,75 @@ _GasFeePoller_findNetworkClientIdByChainId = new WeakMap(), _GasFeePoller_gasFee
185
185
  });
186
186
  return new Map(await Promise.all(entryPromises));
187
187
  };
188
+ /**
189
+ * Update the gas fees for a transaction.
190
+ *
191
+ * @param args - Argument bag.
192
+ * @param args.txMeta - The transaction meta.
193
+ * @param args.gasFeeEstimates - The gas fee estimates.
194
+ * @param args.gasFeeEstimatesLoaded - Whether the gas fee estimates are loaded.
195
+ * @param args.getEIP1559Compatibility - A function for verifying a network is EIP-1559 compatible.
196
+ * @param args.isTxParamsGasFeeUpdatesEnabled - Whether to update the gas fee properties in `txParams`.
197
+ * @param args.layer1GasFee - The layer 1 gas fee.
198
+ */
199
+ export async function updateTransactionGasFees({ txMeta, getEIP1559Compatibility, gasFeeEstimates, gasFeeEstimatesLoaded, isTxParamsGasFeeUpdatesEnabled, layer1GasFee, }) {
200
+ const userFeeLevel = txMeta.userFeeLevel;
201
+ const isUsingGasFeeEstimateLevel = Object.values(GasFeeEstimateLevel).includes(userFeeLevel);
202
+ const { type: gasEstimateType } = gasFeeEstimates ?? {};
203
+ if (isTxParamsGasFeeUpdatesEnabled && isUsingGasFeeEstimateLevel) {
204
+ const isEIP1559Compatible = txMeta.txParams.type !== TransactionEnvelopeType.legacy &&
205
+ (await getEIP1559Compatibility(txMeta.networkClientId));
206
+ if (isEIP1559Compatible) {
207
+ // Handle EIP-1559 compatible transactions
208
+ if (gasEstimateType === GasFeeEstimateType.FeeMarket) {
209
+ const feeMarketGasFeeEstimates = gasFeeEstimates;
210
+ txMeta.txParams.maxFeePerGas =
211
+ feeMarketGasFeeEstimates[userFeeLevel].maxFeePerGas;
212
+ txMeta.txParams.maxPriorityFeePerGas =
213
+ feeMarketGasFeeEstimates[userFeeLevel].maxPriorityFeePerGas;
214
+ }
215
+ if (gasEstimateType === GasFeeEstimateType.GasPrice) {
216
+ const gasPriceGasFeeEstimates = gasFeeEstimates;
217
+ txMeta.txParams.maxFeePerGas = gasPriceGasFeeEstimates.gasPrice;
218
+ txMeta.txParams.maxPriorityFeePerGas = gasPriceGasFeeEstimates.gasPrice;
219
+ }
220
+ if (gasEstimateType === GasFeeEstimateType.Legacy) {
221
+ const legacyGasFeeEstimates = gasFeeEstimates;
222
+ const gasPrice = legacyGasFeeEstimates[userFeeLevel];
223
+ txMeta.txParams.maxFeePerGas = gasPrice;
224
+ txMeta.txParams.maxPriorityFeePerGas = gasPrice;
225
+ }
226
+ // Remove gasPrice for EIP-1559 transactions
227
+ delete txMeta.txParams.gasPrice;
228
+ }
229
+ else {
230
+ // Handle non-EIP-1559 transactions
231
+ if (gasEstimateType === GasFeeEstimateType.FeeMarket) {
232
+ const feeMarketGasFeeEstimates = gasFeeEstimates;
233
+ txMeta.txParams.gasPrice =
234
+ feeMarketGasFeeEstimates[userFeeLevel].maxFeePerGas;
235
+ }
236
+ if (gasEstimateType === GasFeeEstimateType.GasPrice) {
237
+ const gasPriceGasFeeEstimates = gasFeeEstimates;
238
+ txMeta.txParams.gasPrice = gasPriceGasFeeEstimates.gasPrice;
239
+ }
240
+ if (gasEstimateType === GasFeeEstimateType.Legacy) {
241
+ const legacyGasFeeEstimates = gasFeeEstimates;
242
+ txMeta.txParams.gasPrice = legacyGasFeeEstimates[userFeeLevel];
243
+ }
244
+ // Remove EIP-1559 specific parameters for legacy transactions
245
+ delete txMeta.txParams.maxFeePerGas;
246
+ delete txMeta.txParams.maxPriorityFeePerGas;
247
+ }
248
+ }
249
+ if (gasFeeEstimates) {
250
+ txMeta.gasFeeEstimates = gasFeeEstimates;
251
+ }
252
+ if (gasFeeEstimatesLoaded !== undefined) {
253
+ txMeta.gasFeeEstimatesLoaded = gasFeeEstimatesLoaded;
254
+ }
255
+ if (layer1GasFee) {
256
+ txMeta.layer1GasFee = layer1GasFee;
257
+ }
258
+ }
188
259
  //# sourceMappingURL=GasFeePoller.mjs.map
@@ -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-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 readonly #findNetworkClientIdByChainId: (\n chainId: Hex,\n ) => NetworkClientId | undefined;\n\n readonly #gasFeeFlows: GasFeeFlow[];\n\n readonly #getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n\n readonly #getProvider: (networkClientId: NetworkClientId) => Provider;\n\n readonly #getTransactions: () => TransactionMeta[];\n\n readonly #layer1GasFeeFlows: Layer1GasFeeFlow[];\n\n #timeout: ReturnType<typeof setTimeout> | undefined;\n\n #running = false;\n\n /**\n * Constructs a new instance of the GasFeePoller.\n *\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":"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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 GasPriceGasFeeEstimates,\n FeeMarketGasFeeEstimates,\n Layer1GasFeeFlow,\n LegacyGasFeeEstimates,\n TransactionMeta,\n} from '../types';\nimport {\n GasFeeEstimateLevel,\n GasFeeEstimateType,\n TransactionStatus,\n TransactionEnvelopeType,\n} 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 readonly #findNetworkClientIdByChainId: (\n chainId: Hex,\n ) => NetworkClientId | undefined;\n\n readonly #gasFeeFlows: GasFeeFlow[];\n\n readonly #getGasFeeControllerEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise<GasFeeState>;\n\n readonly #getProvider: (networkClientId: NetworkClientId) => Provider;\n\n readonly #getTransactions: () => TransactionMeta[];\n\n readonly #layer1GasFeeFlows: Layer1GasFeeFlow[];\n\n #timeout: ReturnType<typeof setTimeout> | undefined;\n\n #running = false;\n\n /**\n * Constructs a new instance of the GasFeePoller.\n *\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\n/**\n * Update the gas fees for a transaction.\n *\n * @param args - Argument bag.\n * @param args.txMeta - The transaction meta.\n * @param args.gasFeeEstimates - The gas fee estimates.\n * @param args.gasFeeEstimatesLoaded - Whether the gas fee estimates are loaded.\n * @param args.getEIP1559Compatibility - A function for verifying a network is EIP-1559 compatible.\n * @param args.isTxParamsGasFeeUpdatesEnabled - Whether to update the gas fee properties in `txParams`.\n * @param args.layer1GasFee - The layer 1 gas fee.\n */\nexport async function updateTransactionGasFees({\n txMeta,\n getEIP1559Compatibility,\n gasFeeEstimates,\n gasFeeEstimatesLoaded,\n isTxParamsGasFeeUpdatesEnabled,\n layer1GasFee,\n}: {\n txMeta: TransactionMeta;\n getEIP1559Compatibility: (\n networkClientId: NetworkClientId,\n ) => Promise<boolean>;\n gasFeeEstimates?: GasFeeEstimates;\n gasFeeEstimatesLoaded?: boolean;\n isTxParamsGasFeeUpdatesEnabled: boolean;\n layer1GasFee?: Hex;\n}): Promise<void> {\n const userFeeLevel = txMeta.userFeeLevel as GasFeeEstimateLevel;\n const isUsingGasFeeEstimateLevel =\n Object.values(GasFeeEstimateLevel).includes(userFeeLevel);\n const { type: gasEstimateType } = gasFeeEstimates ?? {};\n\n if (isTxParamsGasFeeUpdatesEnabled && isUsingGasFeeEstimateLevel) {\n const isEIP1559Compatible =\n txMeta.txParams.type !== TransactionEnvelopeType.legacy &&\n (await getEIP1559Compatibility(txMeta.networkClientId));\n\n if (isEIP1559Compatible) {\n // Handle EIP-1559 compatible transactions\n if (gasEstimateType === GasFeeEstimateType.FeeMarket) {\n const feeMarketGasFeeEstimates =\n gasFeeEstimates as FeeMarketGasFeeEstimates;\n\n txMeta.txParams.maxFeePerGas =\n feeMarketGasFeeEstimates[userFeeLevel].maxFeePerGas;\n txMeta.txParams.maxPriorityFeePerGas =\n feeMarketGasFeeEstimates[userFeeLevel].maxPriorityFeePerGas;\n }\n\n if (gasEstimateType === GasFeeEstimateType.GasPrice) {\n const gasPriceGasFeeEstimates =\n gasFeeEstimates as GasPriceGasFeeEstimates;\n\n txMeta.txParams.maxFeePerGas = gasPriceGasFeeEstimates.gasPrice;\n txMeta.txParams.maxPriorityFeePerGas = gasPriceGasFeeEstimates.gasPrice;\n }\n\n if (gasEstimateType === GasFeeEstimateType.Legacy) {\n const legacyGasFeeEstimates = gasFeeEstimates as LegacyGasFeeEstimates;\n const gasPrice = legacyGasFeeEstimates[userFeeLevel];\n\n txMeta.txParams.maxFeePerGas = gasPrice;\n txMeta.txParams.maxPriorityFeePerGas = gasPrice;\n }\n\n // Remove gasPrice for EIP-1559 transactions\n delete txMeta.txParams.gasPrice;\n } else {\n // Handle non-EIP-1559 transactions\n if (gasEstimateType === GasFeeEstimateType.FeeMarket) {\n const feeMarketGasFeeEstimates =\n gasFeeEstimates as FeeMarketGasFeeEstimates;\n txMeta.txParams.gasPrice =\n feeMarketGasFeeEstimates[userFeeLevel].maxFeePerGas;\n }\n\n if (gasEstimateType === GasFeeEstimateType.GasPrice) {\n const gasPriceGasFeeEstimates =\n gasFeeEstimates as GasPriceGasFeeEstimates;\n txMeta.txParams.gasPrice = gasPriceGasFeeEstimates.gasPrice;\n }\n\n if (gasEstimateType === GasFeeEstimateType.Legacy) {\n const legacyGasFeeEstimates = gasFeeEstimates as LegacyGasFeeEstimates;\n txMeta.txParams.gasPrice = legacyGasFeeEstimates[userFeeLevel];\n }\n\n // Remove EIP-1559 specific parameters for legacy transactions\n delete txMeta.txParams.maxFeePerGas;\n delete txMeta.txParams.maxPriorityFeePerGas;\n }\n }\n\n if (gasFeeEstimates) {\n txMeta.gasFeeEstimates = gasFeeEstimates;\n }\n\n if (gasFeeEstimatesLoaded !== undefined) {\n txMeta.gasFeeEstimatesLoaded = gasFeeEstimatesLoaded;\n }\n\n if (layer1GasFee) {\n txMeta.layer1GasFee = layer1GasFee;\n }\n}\n"]}
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _CollectPublishHook_instances, _CollectPublishHook_publishPromises, _CollectPublishHook_signedTransactions, _CollectPublishHook_transactionCount, _CollectPublishHook_readyPromise, _CollectPublishHook_hook;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.CollectPublishHook = void 0;
16
+ const utils_1 = require("@metamask/utils");
17
+ const logger_1 = require("../logger.cjs");
18
+ const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'collect-publish-hook');
19
+ /**
20
+ * Custom publish logic that collects multiple signed transactions until a specific number is reached.
21
+ * Used by batch transactions to publish multiple transactions at once.
22
+ */
23
+ class CollectPublishHook {
24
+ constructor(transactionCount) {
25
+ _CollectPublishHook_instances.add(this);
26
+ _CollectPublishHook_publishPromises.set(this, void 0);
27
+ _CollectPublishHook_signedTransactions.set(this, void 0);
28
+ _CollectPublishHook_transactionCount.set(this, void 0);
29
+ _CollectPublishHook_readyPromise.set(this, void 0);
30
+ __classPrivateFieldSet(this, _CollectPublishHook_publishPromises, [], "f");
31
+ __classPrivateFieldSet(this, _CollectPublishHook_readyPromise, (0, utils_1.createDeferredPromise)(), "f");
32
+ __classPrivateFieldSet(this, _CollectPublishHook_signedTransactions, [], "f");
33
+ __classPrivateFieldSet(this, _CollectPublishHook_transactionCount, transactionCount, "f");
34
+ }
35
+ /**
36
+ * @returns The publish hook function to be passed to `addTransaction`.
37
+ */
38
+ getHook() {
39
+ return __classPrivateFieldGet(this, _CollectPublishHook_instances, "m", _CollectPublishHook_hook).bind(this);
40
+ }
41
+ /**
42
+ * @returns A promise that resolves when all transactions are signed.
43
+ */
44
+ ready() {
45
+ return __classPrivateFieldGet(this, _CollectPublishHook_readyPromise, "f").promise;
46
+ }
47
+ /**
48
+ * Resolve all publish promises with the provided transaction hashes.
49
+ *
50
+ * @param transactionHashes - The transaction hashes to pass to the original publish promises.
51
+ */
52
+ success(transactionHashes) {
53
+ log('Success', { transactionHashes });
54
+ if (transactionHashes.length !== __classPrivateFieldGet(this, _CollectPublishHook_transactionCount, "f")) {
55
+ throw new Error('Transaction hash count mismatch');
56
+ }
57
+ for (let i = 0; i < __classPrivateFieldGet(this, _CollectPublishHook_publishPromises, "f").length; i++) {
58
+ const publishPromise = __classPrivateFieldGet(this, _CollectPublishHook_publishPromises, "f")[i];
59
+ const transactionHash = transactionHashes[i];
60
+ publishPromise.resolve({ transactionHash });
61
+ }
62
+ }
63
+ error(error) {
64
+ log('Error', { error });
65
+ for (const publishPromise of __classPrivateFieldGet(this, _CollectPublishHook_publishPromises, "f")) {
66
+ publishPromise.reject(error);
67
+ }
68
+ }
69
+ }
70
+ exports.CollectPublishHook = CollectPublishHook;
71
+ _CollectPublishHook_publishPromises = new WeakMap(), _CollectPublishHook_signedTransactions = new WeakMap(), _CollectPublishHook_transactionCount = new WeakMap(), _CollectPublishHook_readyPromise = new WeakMap(), _CollectPublishHook_instances = new WeakSet(), _CollectPublishHook_hook = function _CollectPublishHook_hook(transactionMeta, signedTx) {
72
+ __classPrivateFieldGet(this, _CollectPublishHook_signedTransactions, "f").push(signedTx);
73
+ log('Processing transaction', { transactionMeta, signedTx });
74
+ const publishPromise = (0, utils_1.createDeferredPromise)();
75
+ __classPrivateFieldGet(this, _CollectPublishHook_publishPromises, "f").push(publishPromise);
76
+ if (__classPrivateFieldGet(this, _CollectPublishHook_signedTransactions, "f").length === __classPrivateFieldGet(this, _CollectPublishHook_transactionCount, "f")) {
77
+ log('All transactions signed');
78
+ __classPrivateFieldGet(this, _CollectPublishHook_readyPromise, "f").resolve({
79
+ signedTransactions: __classPrivateFieldGet(this, _CollectPublishHook_signedTransactions, "f"),
80
+ });
81
+ }
82
+ return publishPromise.promise;
83
+ };
84
+ //# sourceMappingURL=CollectPublishHook.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CollectPublishHook.cjs","sourceRoot":"","sources":["../../src/hooks/CollectPublishHook.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,2CAA4E;AAE5E,0CAA0C;AAG1C,MAAM,GAAG,GAAG,IAAA,0BAAkB,EAAC,sBAAa,EAAE,sBAAsB,CAAC,CAAC;AAMtE;;;GAGG;AACH,MAAa,kBAAkB;IAS7B,YAAY,gBAAwB;;QAR3B,sDAAuD;QAEvD,yDAA2B;QAE3B,uDAA0B;QAE1B,mDAAyD;QAGhE,uBAAA,IAAI,uCAAoB,EAAE,MAAA,CAAC;QAC3B,uBAAA,IAAI,oCAAiB,IAAA,6BAAqB,GAAE,MAAA,CAAC;QAC7C,uBAAA,IAAI,0CAAuB,EAAE,MAAA,CAAC;QAC9B,uBAAA,IAAI,wCAAqB,gBAAgB,MAAA,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,OAAO;QACL,OAAO,uBAAA,IAAI,+DAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,KAAK;QACH,OAAO,uBAAA,IAAI,wCAAc,CAAC,OAAO,CAAC;IACpC,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,iBAAwB;QAC9B,GAAG,CAAC,SAAS,EAAE,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAEtC,IAAI,iBAAiB,CAAC,MAAM,KAAK,uBAAA,IAAI,4CAAkB,EAAE;YACvD,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;SACpD;QAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,uBAAA,IAAI,2CAAiB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACrD,MAAM,cAAc,GAAG,uBAAA,IAAI,2CAAiB,CAAC,CAAC,CAAC,CAAC;YAChD,MAAM,eAAe,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;YAE7C,cAAc,CAAC,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC;SAC7C;IACH,CAAC;IAED,KAAK,CAAC,KAAc;QAClB,GAAG,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAExB,KAAK,MAAM,cAAc,IAAI,uBAAA,IAAI,2CAAiB,EAAE;YAClD,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SAC9B;IACH,CAAC;CAwBF;AAhFD,gDAgFC;iUArBG,eAAgC,EAChC,QAAgB;IAEhB,uBAAA,IAAI,8CAAoB,CAAC,IAAI,CAAC,QAAe,CAAC,CAAC;IAE/C,GAAG,CAAC,wBAAwB,EAAE,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,CAAC;IAE7D,MAAM,cAAc,GAAG,IAAA,6BAAqB,GAAqB,CAAC;IAElE,uBAAA,IAAI,2CAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAE3C,IAAI,uBAAA,IAAI,8CAAoB,CAAC,MAAM,KAAK,uBAAA,IAAI,4CAAkB,EAAE;QAC9D,GAAG,CAAC,yBAAyB,CAAC,CAAC;QAE/B,uBAAA,IAAI,wCAAc,CAAC,OAAO,CAAC;YACzB,kBAAkB,EAAE,uBAAA,IAAI,8CAAoB;SAC7C,CAAC,CAAC;KACJ;IAED,OAAO,cAAc,CAAC,OAAO,CAAC;AAChC,CAAC","sourcesContent":["import type { DeferredPromise, Hex } from '@metamask/utils';\nimport { createDeferredPromise, createModuleLogger } from '@metamask/utils';\n\nimport { projectLogger } from '../logger';\nimport type { PublishHook, PublishHookResult, TransactionMeta } from '../types';\n\nconst log = createModuleLogger(projectLogger, 'collect-publish-hook');\n\nexport type CollectPublishHookResult = {\n signedTransactions: Hex[];\n};\n\n/**\n * Custom publish logic that collects multiple signed transactions until a specific number is reached.\n * Used by batch transactions to publish multiple transactions at once.\n */\nexport class CollectPublishHook {\n readonly #publishPromises: DeferredPromise<PublishHookResult>[];\n\n readonly #signedTransactions: Hex[];\n\n readonly #transactionCount: number;\n\n readonly #readyPromise: DeferredPromise<CollectPublishHookResult>;\n\n constructor(transactionCount: number) {\n this.#publishPromises = [];\n this.#readyPromise = createDeferredPromise();\n this.#signedTransactions = [];\n this.#transactionCount = transactionCount;\n }\n\n /**\n * @returns The publish hook function to be passed to `addTransaction`.\n */\n getHook(): PublishHook {\n return this.#hook.bind(this);\n }\n\n /**\n * @returns A promise that resolves when all transactions are signed.\n */\n ready(): Promise<CollectPublishHookResult> {\n return this.#readyPromise.promise;\n }\n\n /**\n * Resolve all publish promises with the provided transaction hashes.\n *\n * @param transactionHashes - The transaction hashes to pass to the original publish promises.\n */\n success(transactionHashes: Hex[]) {\n log('Success', { transactionHashes });\n\n if (transactionHashes.length !== this.#transactionCount) {\n throw new Error('Transaction hash count mismatch');\n }\n\n for (let i = 0; i < this.#publishPromises.length; i++) {\n const publishPromise = this.#publishPromises[i];\n const transactionHash = transactionHashes[i];\n\n publishPromise.resolve({ transactionHash });\n }\n }\n\n error(error: unknown) {\n log('Error', { error });\n\n for (const publishPromise of this.#publishPromises) {\n publishPromise.reject(error);\n }\n }\n\n #hook(\n transactionMeta: TransactionMeta,\n signedTx: string,\n ): Promise<PublishHookResult> {\n this.#signedTransactions.push(signedTx as Hex);\n\n log('Processing transaction', { transactionMeta, signedTx });\n\n const publishPromise = createDeferredPromise<PublishHookResult>();\n\n this.#publishPromises.push(publishPromise);\n\n if (this.#signedTransactions.length === this.#transactionCount) {\n log('All transactions signed');\n\n this.#readyPromise.resolve({\n signedTransactions: this.#signedTransactions,\n });\n }\n\n return publishPromise.promise;\n }\n}\n"]}
@@ -0,0 +1,29 @@
1
+ import type { Hex } from "@metamask/utils";
2
+ import type { PublishHook } from "../types.cjs";
3
+ export type CollectPublishHookResult = {
4
+ signedTransactions: Hex[];
5
+ };
6
+ /**
7
+ * Custom publish logic that collects multiple signed transactions until a specific number is reached.
8
+ * Used by batch transactions to publish multiple transactions at once.
9
+ */
10
+ export declare class CollectPublishHook {
11
+ #private;
12
+ constructor(transactionCount: number);
13
+ /**
14
+ * @returns The publish hook function to be passed to `addTransaction`.
15
+ */
16
+ getHook(): PublishHook;
17
+ /**
18
+ * @returns A promise that resolves when all transactions are signed.
19
+ */
20
+ ready(): Promise<CollectPublishHookResult>;
21
+ /**
22
+ * Resolve all publish promises with the provided transaction hashes.
23
+ *
24
+ * @param transactionHashes - The transaction hashes to pass to the original publish promises.
25
+ */
26
+ success(transactionHashes: Hex[]): void;
27
+ error(error: unknown): void;
28
+ }
29
+ //# sourceMappingURL=CollectPublishHook.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CollectPublishHook.d.cts","sourceRoot":"","sources":["../../src/hooks/CollectPublishHook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,GAAG,EAAE,wBAAwB;AAI5D,OAAO,KAAK,EAAE,WAAW,EAAsC,qBAAiB;AAIhF,MAAM,MAAM,wBAAwB,GAAG;IACrC,kBAAkB,EAAE,GAAG,EAAE,CAAC;CAC3B,CAAC;AAEF;;;GAGG;AACH,qBAAa,kBAAkB;;gBASjB,gBAAgB,EAAE,MAAM;IAOpC;;OAEG;IACH,OAAO,IAAI,WAAW;IAItB;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAI1C;;;;OAIG;IACH,OAAO,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAehC,KAAK,CAAC,KAAK,EAAE,OAAO;CA8BrB"}
@@ -0,0 +1,29 @@
1
+ import type { Hex } from "@metamask/utils";
2
+ import type { PublishHook } from "../types.mjs";
3
+ export type CollectPublishHookResult = {
4
+ signedTransactions: Hex[];
5
+ };
6
+ /**
7
+ * Custom publish logic that collects multiple signed transactions until a specific number is reached.
8
+ * Used by batch transactions to publish multiple transactions at once.
9
+ */
10
+ export declare class CollectPublishHook {
11
+ #private;
12
+ constructor(transactionCount: number);
13
+ /**
14
+ * @returns The publish hook function to be passed to `addTransaction`.
15
+ */
16
+ getHook(): PublishHook;
17
+ /**
18
+ * @returns A promise that resolves when all transactions are signed.
19
+ */
20
+ ready(): Promise<CollectPublishHookResult>;
21
+ /**
22
+ * Resolve all publish promises with the provided transaction hashes.
23
+ *
24
+ * @param transactionHashes - The transaction hashes to pass to the original publish promises.
25
+ */
26
+ success(transactionHashes: Hex[]): void;
27
+ error(error: unknown): void;
28
+ }
29
+ //# sourceMappingURL=CollectPublishHook.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CollectPublishHook.d.mts","sourceRoot":"","sources":["../../src/hooks/CollectPublishHook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,GAAG,EAAE,wBAAwB;AAI5D,OAAO,KAAK,EAAE,WAAW,EAAsC,qBAAiB;AAIhF,MAAM,MAAM,wBAAwB,GAAG;IACrC,kBAAkB,EAAE,GAAG,EAAE,CAAC;CAC3B,CAAC;AAEF;;;GAGG;AACH,qBAAa,kBAAkB;;gBASjB,gBAAgB,EAAE,MAAM;IAOpC;;OAEG;IACH,OAAO,IAAI,WAAW;IAItB;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAI1C;;;;OAIG;IACH,OAAO,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAehC,KAAK,CAAC,KAAK,EAAE,OAAO;CA8BrB"}