@metamask/transaction-controller 25.2.1 → 26.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.
- package/CHANGELOG.md +39 -1
- package/dist/TransactionController.js +20 -18
- package/dist/TransactionController.mjs +19 -17
- package/dist/{chunk-5UL3VDFT.mjs → chunk-35MG26Y3.mjs} +13 -12
- package/dist/chunk-35MG26Y3.mjs.map +1 -0
- package/dist/{chunk-R7NJVDWN.js → chunk-5WFLNKCL.js} +7 -6
- package/dist/chunk-5WFLNKCL.js.map +1 -0
- package/dist/{chunk-PF3UOCRW.js → chunk-6V2LR6JL.js} +7 -7
- package/dist/{chunk-PGTV7236.mjs → chunk-7HNSDVVO.mjs} +3 -3
- package/dist/{chunk-BYBPZUHS.mjs → chunk-A4P4B3OF.mjs} +14 -6
- package/dist/chunk-A4P4B3OF.mjs.map +1 -0
- package/dist/{chunk-I6RY3XOG.mjs → chunk-APJWB5VY.mjs} +62 -27
- package/dist/chunk-APJWB5VY.mjs.map +1 -0
- package/dist/{chunk-F3CMU2DM.js → chunk-C3UHJPYJ.js} +6 -6
- package/dist/{chunk-Z3HHSD5I.mjs → chunk-DTMKGTYC.mjs} +3 -2
- package/dist/chunk-DTMKGTYC.mjs.map +1 -0
- package/dist/{chunk-VEJ3MIZG.js → chunk-FK7AP6SH.js} +11 -2
- package/dist/chunk-FK7AP6SH.js.map +1 -0
- package/dist/{chunk-ZQFMTLZJ.mjs → chunk-FTB6MCSH.mjs} +39 -24
- package/dist/chunk-FTB6MCSH.mjs.map +1 -0
- package/dist/{chunk-7BG5XOXJ.js → chunk-GASIS3QH.js} +77 -42
- package/dist/chunk-GASIS3QH.js.map +1 -0
- package/dist/{chunk-RQKICZYP.js → chunk-GRQB2ARK.js} +3 -3
- package/dist/{chunk-XKNFL657.mjs → chunk-HLG525BC.mjs} +2 -2
- package/dist/chunk-HMOSP33F.js +36 -0
- package/dist/chunk-HMOSP33F.js.map +1 -0
- package/dist/chunk-HQSNKCXI.mjs +36 -0
- package/dist/chunk-HQSNKCXI.mjs.map +1 -0
- package/dist/{chunk-QEX3QMSL.js → chunk-HUVOOFOM.js} +15 -14
- package/dist/chunk-HUVOOFOM.js.map +1 -0
- package/dist/{chunk-NRWEI43Q.js → chunk-I7VD6IET.js} +40 -25
- package/dist/chunk-I7VD6IET.js.map +1 -0
- package/dist/chunk-JW6P2G5A.mjs +132 -0
- package/dist/chunk-JW6P2G5A.mjs.map +1 -0
- package/dist/{chunk-6XMG522E.mjs → chunk-K4KOSAGM.mjs} +8 -3
- package/dist/chunk-K4KOSAGM.mjs.map +1 -0
- package/dist/{chunk-JRBREX22.mjs → chunk-KG4UW4K4.mjs} +17 -4
- package/dist/chunk-KG4UW4K4.mjs.map +1 -0
- package/dist/{chunk-QRSTF45Q.mjs → chunk-KKCD5UMP.mjs} +3 -3
- package/dist/{chunk-GE57YNGX.js → chunk-KT6UAKBB.js} +8 -3
- package/dist/chunk-KT6UAKBB.js.map +1 -0
- package/dist/chunk-QG2WVQE3.js +132 -0
- package/dist/chunk-QG2WVQE3.js.map +1 -0
- package/dist/{chunk-5OQ373JS.js → chunk-QTQSCTQA.js} +10 -10
- package/dist/{chunk-VEREDMI2.mjs → chunk-RIYIJTEU.mjs} +2 -2
- package/dist/{chunk-IZI7FQIN.mjs → chunk-RU6NJIUD.mjs} +3 -3
- package/dist/{chunk-HS277C77.js → chunk-SD6CWFDF.js} +16 -3
- package/dist/chunk-SD6CWFDF.js.map +1 -0
- package/dist/{chunk-3D3SA6PY.mjs → chunk-TJXPMOA6.mjs} +2 -2
- package/dist/{chunk-DWHMMJOW.mjs → chunk-TWND5SFD.mjs} +2 -2
- package/dist/{chunk-IK55QTGO.mjs → chunk-TZEAWUXE.mjs} +3 -3
- package/dist/{chunk-TZTP4JVA.js → chunk-UH7FNVKS.js} +4 -4
- package/dist/{chunk-5IHLDAOF.js → chunk-UUSYJGGQ.js} +5 -5
- package/dist/{chunk-GC77BSQZ.js → chunk-V5X6MZHN.js} +16 -8
- package/dist/chunk-V5X6MZHN.js.map +1 -0
- package/dist/{chunk-CXXGL43K.js → chunk-VP2DBWOT.js} +3 -3
- package/dist/{chunk-KFL2GGZC.mjs → chunk-W3CS5GRD.mjs} +7 -6
- package/dist/chunk-W3CS5GRD.mjs.map +1 -0
- package/dist/{chunk-ITDY6AIZ.js → chunk-WIZVJM2B.js} +3 -2
- package/dist/chunk-WIZVJM2B.js.map +1 -0
- package/dist/{chunk-FHG5GY6F.js → chunk-XZILQVNW.js} +6 -6
- package/dist/{chunk-W57BD6NX.mjs → chunk-YEJJKWT2.mjs} +11 -2
- package/dist/chunk-YEJJKWT2.mjs.map +1 -0
- package/dist/constants.js +2 -2
- package/dist/constants.mjs +1 -1
- package/dist/errors.js +15 -0
- package/dist/errors.js.map +1 -0
- package/dist/errors.mjs +15 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/gas-flows/DefaultGasFeeFlow.js +7 -7
- package/dist/gas-flows/DefaultGasFeeFlow.mjs +6 -6
- package/dist/gas-flows/LineaGasFeeFlow.js +8 -8
- package/dist/gas-flows/LineaGasFeeFlow.mjs +7 -7
- package/dist/gas-flows/OptimismLayer1GasFeeFlow.js +10 -0
- package/dist/gas-flows/OptimismLayer1GasFeeFlow.js.map +1 -0
- package/dist/gas-flows/OptimismLayer1GasFeeFlow.mjs +10 -0
- package/dist/gas-flows/OptimismLayer1GasFeeFlow.mjs.map +1 -0
- package/dist/helpers/EtherscanRemoteTransactionSource.js +5 -5
- package/dist/helpers/EtherscanRemoteTransactionSource.mjs +4 -4
- package/dist/helpers/GasFeePoller.js +5 -5
- package/dist/helpers/GasFeePoller.mjs +4 -4
- package/dist/helpers/MultichainTrackingHelper.js +6 -6
- package/dist/helpers/MultichainTrackingHelper.mjs +5 -5
- package/dist/helpers/PendingTransactionTracker.js +1 -1
- package/dist/helpers/PendingTransactionTracker.mjs +1 -1
- package/dist/index.js +24 -20
- package/dist/index.mjs +23 -19
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/TransactionController.d.ts +8 -0
- package/dist/types/TransactionController.d.ts.map +1 -1
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/errors.d.ts +15 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/gas-flows/OptimismLayer1GasFeeFlow.d.ts +10 -0
- package/dist/types/gas-flows/OptimismLayer1GasFeeFlow.d.ts.map +1 -0
- package/dist/types/helpers/GasFeePoller.d.ts +4 -5
- package/dist/types/helpers/GasFeePoller.d.ts.map +1 -1
- package/dist/types/helpers/MultichainTrackingHelper.d.ts +4 -0
- package/dist/types/helpers/MultichainTrackingHelper.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types.d.ts +15 -7
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/layer1-gas-fee-flow.d.ts +11 -2
- package/dist/types/utils/layer1-gas-fee-flow.d.ts.map +1 -1
- package/dist/types/utils/simulation-api.d.ts.map +1 -1
- package/dist/types/utils/simulation.d.ts.map +1 -1
- package/dist/types/utils/transaction-type.d.ts.map +1 -1
- package/dist/types.js +4 -2
- package/dist/types.mjs +3 -1
- package/dist/utils/etherscan.js +3 -3
- package/dist/utils/etherscan.mjs +2 -2
- package/dist/utils/external-transactions.js +1 -1
- package/dist/utils/external-transactions.mjs +1 -1
- package/dist/utils/gas-fees.js +6 -6
- package/dist/utils/gas-fees.mjs +5 -5
- package/dist/utils/gas-flow.js +3 -3
- package/dist/utils/gas-flow.mjs +2 -2
- package/dist/utils/gas.js +3 -3
- package/dist/utils/gas.mjs +2 -2
- package/dist/utils/layer1-gas-fee-flow.js +4 -2
- package/dist/utils/layer1-gas-fee-flow.mjs +3 -1
- package/dist/utils/simulation-api.js +4 -2
- package/dist/utils/simulation-api.mjs +3 -1
- package/dist/utils/simulation.js +5 -4
- package/dist/utils/simulation.mjs +4 -3
- package/dist/utils/swaps.js +4 -4
- package/dist/utils/swaps.mjs +3 -3
- package/dist/utils/transaction-type.js +3 -3
- package/dist/utils/transaction-type.mjs +2 -2
- package/dist/utils/utils.js +1 -1
- package/dist/utils/utils.mjs +1 -1
- package/dist/utils/validation.js +1 -1
- package/dist/utils/validation.mjs +1 -1
- package/package.json +7 -5
- package/dist/chunk-5UL3VDFT.mjs.map +0 -1
- package/dist/chunk-6XMG522E.mjs.map +0 -1
- package/dist/chunk-7BG5XOXJ.js.map +0 -1
- package/dist/chunk-BYBPZUHS.mjs.map +0 -1
- package/dist/chunk-GC77BSQZ.js.map +0 -1
- package/dist/chunk-GE57YNGX.js.map +0 -1
- package/dist/chunk-HS277C77.js.map +0 -1
- package/dist/chunk-I6RY3XOG.mjs.map +0 -1
- package/dist/chunk-ITDY6AIZ.js.map +0 -1
- package/dist/chunk-JRBREX22.mjs.map +0 -1
- package/dist/chunk-KFL2GGZC.mjs.map +0 -1
- package/dist/chunk-NRWEI43Q.js.map +0 -1
- package/dist/chunk-QEX3QMSL.js.map +0 -1
- package/dist/chunk-R7NJVDWN.js.map +0 -1
- package/dist/chunk-VEJ3MIZG.js.map +0 -1
- package/dist/chunk-W57BD6NX.mjs.map +0 -1
- package/dist/chunk-Z3HHSD5I.mjs.map +0 -1
- package/dist/chunk-ZQFMTLZJ.mjs.map +0 -1
- /package/dist/{chunk-PF3UOCRW.js.map → chunk-6V2LR6JL.js.map} +0 -0
- /package/dist/{chunk-PGTV7236.mjs.map → chunk-7HNSDVVO.mjs.map} +0 -0
- /package/dist/{chunk-F3CMU2DM.js.map → chunk-C3UHJPYJ.js.map} +0 -0
- /package/dist/{chunk-RQKICZYP.js.map → chunk-GRQB2ARK.js.map} +0 -0
- /package/dist/{chunk-XKNFL657.mjs.map → chunk-HLG525BC.mjs.map} +0 -0
- /package/dist/{chunk-QRSTF45Q.mjs.map → chunk-KKCD5UMP.mjs.map} +0 -0
- /package/dist/{chunk-5OQ373JS.js.map → chunk-QTQSCTQA.js.map} +0 -0
- /package/dist/{chunk-VEREDMI2.mjs.map → chunk-RIYIJTEU.mjs.map} +0 -0
- /package/dist/{chunk-IZI7FQIN.mjs.map → chunk-RU6NJIUD.mjs.map} +0 -0
- /package/dist/{chunk-3D3SA6PY.mjs.map → chunk-TJXPMOA6.mjs.map} +0 -0
- /package/dist/{chunk-DWHMMJOW.mjs.map → chunk-TWND5SFD.mjs.map} +0 -0
- /package/dist/{chunk-IK55QTGO.mjs.map → chunk-TZEAWUXE.mjs.map} +0 -0
- /package/dist/{chunk-TZTP4JVA.js.map → chunk-UH7FNVKS.js.map} +0 -0
- /package/dist/{chunk-5IHLDAOF.js.map → chunk-UUSYJGGQ.js.map} +0 -0
- /package/dist/{chunk-CXXGL43K.js.map → chunk-VP2DBWOT.js.map} +0 -0
- /package/dist/{chunk-FHG5GY6F.js.map → chunk-XZILQVNW.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/helpers/GasFeePoller.ts"],"names":[],"mappings":"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","sourcesContent":["import EthQuery from '@metamask/eth-query';\nimport type { GasFeeState } from '@metamask/gas-fee-controller';\nimport type { NetworkClientId, Provider } from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\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 { updateTransactionLayer1GasFee } 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 #gasFeeFlows: GasFeeFlow[];\n\n #getGasFeeControllerEstimates: () => Promise<GasFeeState>;\n\n #getProvider: (chainId: Hex, 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.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 gasFeeFlows,\n getGasFeeControllerEstimates,\n getProvider,\n getTransactions,\n layer1GasFeeFlows,\n onStateChange,\n }: {\n gasFeeFlows: GasFeeFlow[];\n getGasFeeControllerEstimates: () => Promise<GasFeeState>;\n getProvider: (chainId: Hex, networkClientId?: NetworkClientId) => Provider;\n getTransactions: () => TransactionMeta[];\n layer1GasFeeFlows: Layer1GasFeeFlow[];\n onStateChange: (listener: () => void) => void;\n }) {\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.#updateTransactionGasFeeEstimates();\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeout = setTimeout(() => this.#onTimeout(), INTERVAL_MILLISECONDS);\n }\n\n async #updateTransactionGasFeeEstimates() {\n const unapprovedTransactions = this.#getUnapprovedTransactions();\n\n log('Found unapproved transactions', {\n count: unapprovedTransactions.length,\n });\n\n await Promise.all(\n unapprovedTransactions.flatMap((tx) => [\n this.#updateTransactionSuggestedFees(tx),\n this.#updateTransactionLayer1GasFee(tx),\n ]),\n );\n }\n\n async #updateTransactionSuggestedFees(transactionMeta: TransactionMeta) {\n const { chainId, networkClientId } = transactionMeta;\n\n const ethQuery = new EthQuery(this.#getProvider(chainId, networkClientId));\n const gasFeeFlow = getGasFeeFlow(transactionMeta, this.#gasFeeFlows);\n\n if (!gasFeeFlow) {\n log('No gas fee flow found', transactionMeta.id);\n } else {\n log(\n 'Found gas fee flow',\n gasFeeFlow.constructor.name,\n transactionMeta.id,\n );\n }\n\n const request: GasFeeFlowRequest = {\n ethQuery,\n getGasFeeControllerEstimates: this.#getGasFeeControllerEstimates,\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;\n }\n\n const updatedTransactionMeta: TransactionMeta = {\n ...transactionMeta,\n gasFeeEstimates,\n gasFeeEstimatesLoaded: true,\n };\n\n this.hub.emit('transaction-updated', updatedTransactionMeta);\n\n log('Updated suggested gas fees', {\n gasFeeEstimates: updatedTransactionMeta.gasFeeEstimates,\n transaction: updatedTransactionMeta.id,\n });\n }\n\n async #updateTransactionLayer1GasFee(transactionMeta: TransactionMeta) {\n const { chainId, networkClientId } = transactionMeta;\n const provider = this.#getProvider(chainId, networkClientId);\n\n await updateTransactionLayer1GasFee({\n provider,\n layer1GasFeeFlows: this.#layer1GasFeeFlows,\n transactionMeta,\n });\n\n if (transactionMeta.layer1GasFee === undefined) {\n return;\n }\n\n this.hub.emit('transaction-updated', transactionMeta);\n }\n\n #getUnapprovedTransactions() {\n return this.#getTransactions().filter(\n (tx) => tx.status === TransactionStatus.unapproved,\n );\n }\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkC3UHJPYJjs = require('./chunk-C3UHJPYJ.js');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var _chunkS6VGOPUYjs = require('./chunk-S6VGOPUY.js');
|
|
@@ -14,7 +14,7 @@ var _chunkZ4BLTVTBjs = require('./chunk-Z4BLTVTB.js');
|
|
|
14
14
|
// src/helpers/MultichainTrackingHelper.ts
|
|
15
15
|
var _ethquery = require('@metamask/eth-query'); var _ethquery2 = _interopRequireDefault(_ethquery);
|
|
16
16
|
var _asyncmutex = require('async-mutex');
|
|
17
|
-
var _isMultichainEnabled, _provider, _nonceTracker, _incomingTransactionOptions, _findNetworkClientIdByChainId, _getNetworkClientById, _getNetworkClientRegistry, _removeIncomingTransactionHelperListeners, _removePendingTransactionTrackerListeners, _createNonceTracker, _createIncomingTransactionHelper, _createPendingTransactionTracker, _nonceMutexesByChainId, _trackingMap, _etherscanRemoteTransactionSourcesMap, _refreshTrackingMap, _stopTrackingByNetworkClientId, stopTrackingByNetworkClientId_fn, _startTrackingByNetworkClientId, startTrackingByNetworkClientId_fn, _refreshEtherscanRemoteTransactionSources;
|
|
17
|
+
var _isMultichainEnabled, _provider, _nonceTracker, _incomingTransactionOptions, _findNetworkClientIdByChainId, _getNetworkClientById, _getNetworkClientRegistry, _removeIncomingTransactionHelperListeners, _removePendingTransactionTrackerListeners, _createNonceTracker, _createIncomingTransactionHelper, _createPendingTransactionTracker, _nonceMutexesByChainId, _trackingMap, _etherscanRemoteTransactionSourcesMap, _refreshTrackingMap, _stopTrackingByNetworkClientId, stopTrackingByNetworkClientId_fn, _startTrackingByNetworkClientId, startTrackingByNetworkClientId_fn, _refreshEtherscanRemoteTransactionSources, _getNetworkClient, getNetworkClient_fn;
|
|
18
18
|
var MultichainTrackingHelper = class {
|
|
19
19
|
constructor({
|
|
20
20
|
isMultichainEnabled,
|
|
@@ -33,6 +33,7 @@ var MultichainTrackingHelper = class {
|
|
|
33
33
|
}) {
|
|
34
34
|
_chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _stopTrackingByNetworkClientId);
|
|
35
35
|
_chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _startTrackingByNetworkClientId);
|
|
36
|
+
_chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getNetworkClient);
|
|
36
37
|
_chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _isMultichainEnabled, void 0);
|
|
37
38
|
_chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _provider, void 0);
|
|
38
39
|
_chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _nonceTracker, void 0);
|
|
@@ -123,30 +124,21 @@ var MultichainTrackingHelper = class {
|
|
|
123
124
|
getEthQuery({
|
|
124
125
|
networkClientId,
|
|
125
126
|
chainId
|
|
127
|
+
} = {}) {
|
|
128
|
+
return new (0, _ethquery2.default)(this.getProvider({ networkClientId, chainId }));
|
|
129
|
+
}
|
|
130
|
+
getProvider({
|
|
131
|
+
networkClientId,
|
|
132
|
+
chainId
|
|
126
133
|
} = {}) {
|
|
127
134
|
if (!_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _isMultichainEnabled)) {
|
|
128
|
-
return
|
|
129
|
-
}
|
|
130
|
-
let networkClient;
|
|
131
|
-
if (networkClientId) {
|
|
132
|
-
try {
|
|
133
|
-
networkClient = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getNetworkClientById).call(this, networkClientId);
|
|
134
|
-
} catch (err) {
|
|
135
|
-
_chunkS6VGOPUYjs.incomingTransactionsLogger.call(void 0, "failed to get network client by networkClientId");
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
if (!networkClient && chainId) {
|
|
139
|
-
try {
|
|
140
|
-
networkClientId = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _findNetworkClientIdByChainId).call(this, chainId);
|
|
141
|
-
networkClient = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getNetworkClientById).call(this, networkClientId);
|
|
142
|
-
} catch (err) {
|
|
143
|
-
_chunkS6VGOPUYjs.incomingTransactionsLogger.call(void 0, "failed to get network client by chainId");
|
|
144
|
-
}
|
|
135
|
+
return _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _provider);
|
|
145
136
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
137
|
+
const networkClient = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getNetworkClient, getNetworkClient_fn).call(this, {
|
|
138
|
+
networkClientId,
|
|
139
|
+
chainId
|
|
140
|
+
});
|
|
141
|
+
return networkClient?.provider || _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _provider);
|
|
150
142
|
}
|
|
151
143
|
/**
|
|
152
144
|
* Gets the mutex intended to guard the nonceTracker for a particular chainId and key .
|
|
@@ -283,7 +275,7 @@ startTrackingByNetworkClientId_fn = function(networkClientId) {
|
|
|
283
275
|
} = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getNetworkClientById).call(this, networkClientId);
|
|
284
276
|
let etherscanRemoteTransactionSource = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _etherscanRemoteTransactionSourcesMap).get(chainId);
|
|
285
277
|
if (!etherscanRemoteTransactionSource) {
|
|
286
|
-
etherscanRemoteTransactionSource = new (0,
|
|
278
|
+
etherscanRemoteTransactionSource = new (0, _chunkC3UHJPYJjs.EtherscanRemoteTransactionSource)({
|
|
287
279
|
includeTokenTransfers: _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _incomingTransactionOptions).includeTokenTransfers
|
|
288
280
|
});
|
|
289
281
|
_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _etherscanRemoteTransactionSourcesMap).set(
|
|
@@ -313,8 +305,31 @@ startTrackingByNetworkClientId_fn = function(networkClientId) {
|
|
|
313
305
|
});
|
|
314
306
|
};
|
|
315
307
|
_refreshEtherscanRemoteTransactionSources = new WeakMap();
|
|
308
|
+
_getNetworkClient = new WeakSet();
|
|
309
|
+
getNetworkClient_fn = function({
|
|
310
|
+
networkClientId,
|
|
311
|
+
chainId
|
|
312
|
+
} = {}) {
|
|
313
|
+
let networkClient;
|
|
314
|
+
if (networkClientId) {
|
|
315
|
+
try {
|
|
316
|
+
networkClient = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getNetworkClientById).call(this, networkClientId);
|
|
317
|
+
} catch (err) {
|
|
318
|
+
_chunkS6VGOPUYjs.incomingTransactionsLogger.call(void 0, "failed to get network client by networkClientId");
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (!networkClient && chainId) {
|
|
322
|
+
try {
|
|
323
|
+
const networkClientIdForChainId = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _findNetworkClientIdByChainId).call(this, chainId);
|
|
324
|
+
networkClient = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getNetworkClientById).call(this, networkClientIdForChainId);
|
|
325
|
+
} catch (err) {
|
|
326
|
+
_chunkS6VGOPUYjs.incomingTransactionsLogger.call(void 0, "failed to get network client by chainId");
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return networkClient;
|
|
330
|
+
};
|
|
316
331
|
|
|
317
332
|
|
|
318
333
|
|
|
319
334
|
exports.MultichainTrackingHelper = MultichainTrackingHelper;
|
|
320
|
-
//# sourceMappingURL=chunk-
|
|
335
|
+
//# sourceMappingURL=chunk-I7VD6IET.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/helpers/MultichainTrackingHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClientId,\n NetworkController,\n NetworkClient,\n BlockTracker,\n Provider,\n NetworkControllerStateChangeEvent,\n} from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport type { NonceLock, NonceTracker } from 'nonce-tracker';\n\nimport { incomingTransactionsLogger as log } from '../logger';\nimport { EtherscanRemoteTransactionSource } from './EtherscanRemoteTransactionSource';\nimport type {\n IncomingTransactionHelper,\n IncomingTransactionOptions,\n} from './IncomingTransactionHelper';\nimport type { PendingTransactionTracker } from './PendingTransactionTracker';\n\n/**\n * Registry of network clients provided by the NetworkController\n */\ntype NetworkClientRegistry = ReturnType<\n NetworkController['getNetworkClientRegistry']\n>;\n\nexport type MultichainTrackingHelperOptions = {\n isMultichainEnabled: boolean;\n provider: Provider;\n nonceTracker: NonceTracker;\n incomingTransactionOptions: IncomingTransactionOptions;\n\n findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n getNetworkClientById: NetworkController['getNetworkClientById'];\n getNetworkClientRegistry: NetworkController['getNetworkClientRegistry'];\n\n removeIncomingTransactionHelperListeners: (\n IncomingTransactionHelper: IncomingTransactionHelper,\n ) => void;\n removePendingTransactionTrackerListeners: (\n pendingTransactionTracker: PendingTransactionTracker,\n ) => void;\n createNonceTracker: (opts: {\n provider: Provider;\n blockTracker: BlockTracker;\n chainId?: Hex;\n }) => NonceTracker;\n createIncomingTransactionHelper: (opts: {\n blockTracker: BlockTracker;\n etherscanRemoteTransactionSource: EtherscanRemoteTransactionSource;\n chainId?: Hex;\n }) => IncomingTransactionHelper;\n createPendingTransactionTracker: (opts: {\n provider: Provider;\n blockTracker: BlockTracker;\n chainId?: Hex;\n }) => PendingTransactionTracker;\n onNetworkStateChange: (\n listener: (\n ...payload: NetworkControllerStateChangeEvent['payload']\n ) => void,\n ) => void;\n};\n\nexport class MultichainTrackingHelper {\n #isMultichainEnabled: boolean;\n\n readonly #provider: Provider;\n\n readonly #nonceTracker: NonceTracker;\n\n readonly #incomingTransactionOptions: IncomingTransactionOptions;\n\n readonly #findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId'];\n\n readonly #getNetworkClientById: NetworkController['getNetworkClientById'];\n\n readonly #getNetworkClientRegistry: NetworkController['getNetworkClientRegistry'];\n\n readonly #removeIncomingTransactionHelperListeners: (\n IncomingTransactionHelper: IncomingTransactionHelper,\n ) => void;\n\n readonly #removePendingTransactionTrackerListeners: (\n pendingTransactionTracker: PendingTransactionTracker,\n ) => void;\n\n readonly #createNonceTracker: (opts: {\n provider: Provider;\n blockTracker: BlockTracker;\n chainId?: Hex;\n }) => NonceTracker;\n\n readonly #createIncomingTransactionHelper: (opts: {\n blockTracker: BlockTracker;\n chainId?: Hex;\n etherscanRemoteTransactionSource: EtherscanRemoteTransactionSource;\n }) => IncomingTransactionHelper;\n\n readonly #createPendingTransactionTracker: (opts: {\n provider: Provider;\n blockTracker: BlockTracker;\n chainId?: Hex;\n }) => PendingTransactionTracker;\n\n readonly #nonceMutexesByChainId = new Map<Hex, Map<string, Mutex>>();\n\n readonly #trackingMap: Map<\n NetworkClientId,\n {\n nonceTracker: NonceTracker;\n pendingTransactionTracker: PendingTransactionTracker;\n incomingTransactionHelper: IncomingTransactionHelper;\n }\n > = new Map();\n\n readonly #etherscanRemoteTransactionSourcesMap: Map<\n Hex,\n EtherscanRemoteTransactionSource\n > = new Map();\n\n constructor({\n isMultichainEnabled,\n provider,\n nonceTracker,\n incomingTransactionOptions,\n findNetworkClientIdByChainId,\n getNetworkClientById,\n getNetworkClientRegistry,\n removeIncomingTransactionHelperListeners,\n removePendingTransactionTrackerListeners,\n createNonceTracker,\n createIncomingTransactionHelper,\n createPendingTransactionTracker,\n onNetworkStateChange,\n }: MultichainTrackingHelperOptions) {\n this.#isMultichainEnabled = isMultichainEnabled;\n this.#provider = provider;\n this.#nonceTracker = nonceTracker;\n this.#incomingTransactionOptions = incomingTransactionOptions;\n\n this.#findNetworkClientIdByChainId = findNetworkClientIdByChainId;\n this.#getNetworkClientById = getNetworkClientById;\n this.#getNetworkClientRegistry = getNetworkClientRegistry;\n\n this.#removeIncomingTransactionHelperListeners =\n removeIncomingTransactionHelperListeners;\n this.#removePendingTransactionTrackerListeners =\n removePendingTransactionTrackerListeners;\n this.#createNonceTracker = createNonceTracker;\n this.#createIncomingTransactionHelper = createIncomingTransactionHelper;\n this.#createPendingTransactionTracker = createPendingTransactionTracker;\n\n onNetworkStateChange((_, patches) => {\n if (this.#isMultichainEnabled) {\n const networkClients = this.#getNetworkClientRegistry();\n patches.forEach(({ op, path }) => {\n if (op === 'remove' && path[0] === 'networkConfigurations') {\n const networkClientId = path[1] as NetworkClientId;\n delete networkClients[networkClientId];\n }\n });\n\n this.#refreshTrackingMap(networkClients);\n }\n });\n }\n\n initialize() {\n if (!this.#isMultichainEnabled) {\n return;\n }\n const networkClients = this.#getNetworkClientRegistry();\n this.#refreshTrackingMap(networkClients);\n }\n\n has(networkClientId: NetworkClientId) {\n return this.#trackingMap.has(networkClientId);\n }\n\n getEthQuery({\n networkClientId,\n chainId,\n }: {\n networkClientId?: NetworkClientId;\n chainId?: Hex;\n } = {}): EthQuery {\n return new EthQuery(this.getProvider({ networkClientId, chainId }));\n }\n\n getProvider({\n networkClientId,\n chainId,\n }: {\n networkClientId?: NetworkClientId;\n chainId?: Hex;\n } = {}): Provider {\n if (!this.#isMultichainEnabled) {\n return this.#provider;\n }\n\n const networkClient = this.#getNetworkClient({\n networkClientId,\n chainId,\n });\n\n return networkClient?.provider || this.#provider;\n }\n\n /**\n * Gets the mutex intended to guard the nonceTracker for a particular chainId and key .\n *\n * @param opts - The options object.\n * @param opts.chainId - The hex chainId.\n * @param opts.key - The hex address (or constant) pertaining to the chainId\n * @returns Mutex instance for the given chainId and key pair\n */\n async acquireNonceLockForChainIdKey({\n chainId,\n key = 'global',\n }: {\n chainId: Hex;\n key?: string;\n }): Promise<() => void> {\n let nonceMutexesForChainId = this.#nonceMutexesByChainId.get(chainId);\n if (!nonceMutexesForChainId) {\n nonceMutexesForChainId = new Map<string, Mutex>();\n this.#nonceMutexesByChainId.set(chainId, nonceMutexesForChainId);\n }\n let nonceMutexForKey = nonceMutexesForChainId.get(key);\n if (!nonceMutexForKey) {\n nonceMutexForKey = new Mutex();\n nonceMutexesForChainId.set(key, nonceMutexForKey);\n }\n\n return await nonceMutexForKey.acquire();\n }\n\n /**\n * Gets the next nonce according to the nonce-tracker.\n * Ensure `releaseLock` is called once processing of the `nonce` value is complete.\n *\n * @param address - The hex string address for the transaction.\n * @param networkClientId - The network client ID for the transaction, used to fetch the correct nonce tracker.\n * @returns object with the `nextNonce` `nonceDetails`, and the releaseLock.\n */\n async getNonceLock(\n address: string,\n networkClientId?: NetworkClientId,\n ): Promise<NonceLock> {\n let releaseLockForChainIdKey: (() => void) | undefined;\n let nonceTracker = this.#nonceTracker;\n if (networkClientId && this.#isMultichainEnabled) {\n const networkClient = this.#getNetworkClientById(networkClientId);\n releaseLockForChainIdKey = await this.acquireNonceLockForChainIdKey({\n chainId: networkClient.configuration.chainId,\n key: address,\n });\n const trackers = this.#trackingMap.get(networkClientId);\n if (!trackers) {\n throw new Error('missing nonceTracker for networkClientId');\n }\n nonceTracker = trackers.nonceTracker;\n }\n\n // Acquires the lock for the chainId + address and the nonceLock from the nonceTracker, then\n // couples them together by replacing the nonceLock's releaseLock method with\n // an anonymous function that calls releases both the original nonceLock and the\n // lock for the chainId.\n try {\n const nonceLock = await nonceTracker.getNonceLock(address);\n return {\n ...nonceLock,\n releaseLock: () => {\n nonceLock.releaseLock();\n releaseLockForChainIdKey?.();\n },\n };\n } catch (err) {\n releaseLockForChainIdKey?.();\n throw err;\n }\n }\n\n startIncomingTransactionPolling(networkClientIds: NetworkClientId[] = []) {\n networkClientIds.forEach((networkClientId) => {\n this.#trackingMap.get(networkClientId)?.incomingTransactionHelper.start();\n });\n }\n\n stopIncomingTransactionPolling(networkClientIds: NetworkClientId[] = []) {\n networkClientIds.forEach((networkClientId) => {\n this.#trackingMap.get(networkClientId)?.incomingTransactionHelper.stop();\n });\n }\n\n stopAllIncomingTransactionPolling() {\n for (const [, trackers] of this.#trackingMap) {\n trackers.incomingTransactionHelper.stop();\n }\n }\n\n async updateIncomingTransactions(networkClientIds: NetworkClientId[] = []) {\n const promises = await Promise.allSettled(\n networkClientIds.map(async (networkClientId) => {\n return await this.#trackingMap\n .get(networkClientId)\n ?.incomingTransactionHelper.update();\n }),\n );\n\n promises\n .filter((result) => result.status === 'rejected')\n .forEach((result) => {\n log(\n 'failed to update incoming transactions',\n (result as PromiseRejectedResult).reason,\n );\n });\n }\n\n checkForPendingTransactionAndStartPolling = () => {\n for (const [, trackers] of this.#trackingMap) {\n trackers.pendingTransactionTracker.startIfPendingTransactions();\n }\n };\n\n stopAllTracking() {\n for (const [networkClientId] of this.#trackingMap) {\n this.#stopTrackingByNetworkClientId(networkClientId);\n }\n }\n\n #refreshTrackingMap = (networkClients: NetworkClientRegistry) => {\n this.#refreshEtherscanRemoteTransactionSources(networkClients);\n\n const networkClientIds = Object.keys(networkClients);\n const existingNetworkClientIds = Array.from(this.#trackingMap.keys());\n\n // Remove tracking for NetworkClientIds that no longer exist\n const networkClientIdsToRemove = existingNetworkClientIds.filter(\n (id) => !networkClientIds.includes(id),\n );\n networkClientIdsToRemove.forEach((id) => {\n this.#stopTrackingByNetworkClientId(id);\n });\n\n // Start tracking new NetworkClientIds from the registry\n const networkClientIdsToAdd = networkClientIds.filter(\n (id) => !existingNetworkClientIds.includes(id),\n );\n networkClientIdsToAdd.forEach((id) => {\n this.#startTrackingByNetworkClientId(id);\n });\n };\n\n #stopTrackingByNetworkClientId(networkClientId: NetworkClientId) {\n const trackers = this.#trackingMap.get(networkClientId);\n if (trackers) {\n trackers.pendingTransactionTracker.stop();\n this.#removePendingTransactionTrackerListeners(\n trackers.pendingTransactionTracker,\n );\n trackers.incomingTransactionHelper.stop();\n this.#removeIncomingTransactionHelperListeners(\n trackers.incomingTransactionHelper,\n );\n this.#trackingMap.delete(networkClientId);\n }\n }\n\n #startTrackingByNetworkClientId(networkClientId: NetworkClientId) {\n const trackers = this.#trackingMap.get(networkClientId);\n if (trackers) {\n return;\n }\n\n const {\n provider,\n blockTracker,\n configuration: { chainId },\n } = this.#getNetworkClientById(networkClientId);\n\n let etherscanRemoteTransactionSource =\n this.#etherscanRemoteTransactionSourcesMap.get(chainId);\n if (!etherscanRemoteTransactionSource) {\n etherscanRemoteTransactionSource = new EtherscanRemoteTransactionSource({\n includeTokenTransfers:\n this.#incomingTransactionOptions.includeTokenTransfers,\n });\n this.#etherscanRemoteTransactionSourcesMap.set(\n chainId,\n etherscanRemoteTransactionSource,\n );\n }\n\n const nonceTracker = this.#createNonceTracker({\n provider,\n blockTracker,\n chainId,\n });\n\n const incomingTransactionHelper = this.#createIncomingTransactionHelper({\n blockTracker,\n etherscanRemoteTransactionSource,\n chainId,\n });\n\n const pendingTransactionTracker = this.#createPendingTransactionTracker({\n provider,\n blockTracker,\n chainId,\n });\n\n this.#trackingMap.set(networkClientId, {\n nonceTracker,\n incomingTransactionHelper,\n pendingTransactionTracker,\n });\n }\n\n #refreshEtherscanRemoteTransactionSources = (\n networkClients: NetworkClientRegistry,\n ) => {\n // this will be prettier when we have consolidated network clients with a single chainId:\n // check if there are still other network clients using the same chainId\n // if not remove the etherscanRemoteTransaction source from the map\n const chainIdsInRegistry = new Set();\n Object.values(networkClients).forEach((networkClient) =>\n chainIdsInRegistry.add(networkClient.configuration.chainId),\n );\n const existingChainIds = Array.from(\n this.#etherscanRemoteTransactionSourcesMap.keys(),\n );\n const chainIdsToRemove = existingChainIds.filter(\n (chainId) => !chainIdsInRegistry.has(chainId),\n );\n\n chainIdsToRemove.forEach((chainId) => {\n this.#etherscanRemoteTransactionSourcesMap.delete(chainId);\n });\n };\n\n #getNetworkClient({\n networkClientId,\n chainId,\n }: {\n networkClientId?: NetworkClientId;\n chainId?: Hex;\n } = {}): NetworkClient | undefined {\n let networkClient: NetworkClient | undefined;\n\n if (networkClientId) {\n try {\n networkClient = this.#getNetworkClientById(networkClientId);\n } catch (err) {\n log('failed to get network client by networkClientId');\n }\n }\n if (!networkClient && chainId) {\n try {\n const networkClientIdForChainId =\n this.#findNetworkClientIdByChainId(chainId);\n networkClient = this.#getNetworkClientById(networkClientIdForChainId);\n } catch (err) {\n log('failed to get network client by chainId');\n }\n }\n return networkClient;\n }\n}\n"]}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CHAIN_IDS
|
|
3
|
+
} from "./chunk-DTMKGTYC.mjs";
|
|
4
|
+
import {
|
|
5
|
+
projectLogger
|
|
6
|
+
} from "./chunk-UQQWZT6C.mjs";
|
|
7
|
+
import {
|
|
8
|
+
__privateAdd,
|
|
9
|
+
__privateMethod
|
|
10
|
+
} from "./chunk-XUI43LEZ.mjs";
|
|
11
|
+
|
|
12
|
+
// src/gas-flows/OptimismLayer1GasFeeFlow.ts
|
|
13
|
+
import { Common, Hardfork } from "@ethereumjs/common";
|
|
14
|
+
import { TransactionFactory } from "@ethereumjs/tx";
|
|
15
|
+
import { Contract } from "@ethersproject/contracts";
|
|
16
|
+
import { Web3Provider } from "@ethersproject/providers";
|
|
17
|
+
import { createModuleLogger, remove0x } from "@metamask/utils";
|
|
18
|
+
import BN from "bn.js";
|
|
19
|
+
import { omit } from "lodash";
|
|
20
|
+
var OPTIMISM_STACK_CHAIN_IDS = [
|
|
21
|
+
CHAIN_IDS.OPTIMISM,
|
|
22
|
+
CHAIN_IDS.OPTIMISM_TESTNET,
|
|
23
|
+
CHAIN_IDS.BASE,
|
|
24
|
+
CHAIN_IDS.BASE_TESTNET,
|
|
25
|
+
CHAIN_IDS.OPBNB,
|
|
26
|
+
CHAIN_IDS.OPBNB_TESTNET,
|
|
27
|
+
CHAIN_IDS.ZORA
|
|
28
|
+
];
|
|
29
|
+
var log = createModuleLogger(projectLogger, "optimisim-layer1-gas-fee-flow");
|
|
30
|
+
var OPTIMISM_GAS_PRICE_ORACLE_ABI = [
|
|
31
|
+
{
|
|
32
|
+
inputs: [{ internalType: "bytes", name: "_data", type: "bytes" }],
|
|
33
|
+
name: "getL1Fee",
|
|
34
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
35
|
+
stateMutability: "view",
|
|
36
|
+
type: "function"
|
|
37
|
+
}
|
|
38
|
+
];
|
|
39
|
+
var OPTIMISM_GAS_PRICE_ORACLE_ADDRESS = "0x420000000000000000000000000000000000000F";
|
|
40
|
+
var _getOptimisimLayer1GasFee, getOptimisimLayer1GasFee_fn, _buildUnserializedTransaction, buildUnserializedTransaction_fn, _buildTransactionParams, buildTransactionParams_fn, _buildTransactionCommon, buildTransactionCommon_fn;
|
|
41
|
+
var OptimismLayer1GasFeeFlow = class {
|
|
42
|
+
constructor() {
|
|
43
|
+
__privateAdd(this, _getOptimisimLayer1GasFee);
|
|
44
|
+
/**
|
|
45
|
+
* Build an unserialized transaction for a transaction.
|
|
46
|
+
*
|
|
47
|
+
* @param transactionMeta - The transaction to build an unserialized transaction for.
|
|
48
|
+
* @returns The unserialized transaction.
|
|
49
|
+
*/
|
|
50
|
+
__privateAdd(this, _buildUnserializedTransaction);
|
|
51
|
+
/**
|
|
52
|
+
* Build transactionParams to be used in the unserialized transaction.
|
|
53
|
+
*
|
|
54
|
+
* @param transactionMeta - The transaction to build transactionParams.
|
|
55
|
+
* @returns The transactionParams for the unserialized transaction.
|
|
56
|
+
*/
|
|
57
|
+
__privateAdd(this, _buildTransactionParams);
|
|
58
|
+
/**
|
|
59
|
+
* This produces a transaction whose information does not completely match an
|
|
60
|
+
* Optimism transaction — for instance, DEFAULT_CHAIN is still 'mainnet' and
|
|
61
|
+
* genesis points to the mainnet genesis, not the Optimism genesis — but
|
|
62
|
+
* considering that all we want to do is serialize a transaction, this works
|
|
63
|
+
* fine for our use case.
|
|
64
|
+
*
|
|
65
|
+
* @param transactionMeta - The transaction to build an unserialized transaction for.
|
|
66
|
+
* @returns The unserialized transaction.
|
|
67
|
+
*/
|
|
68
|
+
__privateAdd(this, _buildTransactionCommon);
|
|
69
|
+
}
|
|
70
|
+
matchesTransaction(transactionMeta) {
|
|
71
|
+
return OPTIMISM_STACK_CHAIN_IDS.includes(transactionMeta.chainId);
|
|
72
|
+
}
|
|
73
|
+
async getLayer1Fee(request) {
|
|
74
|
+
try {
|
|
75
|
+
return await __privateMethod(this, _getOptimisimLayer1GasFee, getOptimisimLayer1GasFee_fn).call(this, request);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
log("Failed to get Optimism layer 1 gas fee due to error", error);
|
|
78
|
+
throw new Error(`Failed to get Optimism layer 1 gas fee`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
_getOptimisimLayer1GasFee = new WeakSet();
|
|
83
|
+
getOptimisimLayer1GasFee_fn = async function(request) {
|
|
84
|
+
const { provider, transactionMeta } = request;
|
|
85
|
+
const contract = new Contract(
|
|
86
|
+
OPTIMISM_GAS_PRICE_ORACLE_ADDRESS,
|
|
87
|
+
OPTIMISM_GAS_PRICE_ORACLE_ABI,
|
|
88
|
+
// Network controller provider type is uncompatible with ethers provider
|
|
89
|
+
new Web3Provider(provider)
|
|
90
|
+
);
|
|
91
|
+
const serializedTransaction = __privateMethod(this, _buildUnserializedTransaction, buildUnserializedTransaction_fn).call(this, transactionMeta).serialize();
|
|
92
|
+
const result = await contract.getL1Fee(serializedTransaction);
|
|
93
|
+
if (result === void 0) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
"Failed to retrieve layer 1 gas fee from Optimism Gas Price Oracle."
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
layer1Fee: result.toHexString()
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
_buildUnserializedTransaction = new WeakSet();
|
|
103
|
+
buildUnserializedTransaction_fn = function(transactionMeta) {
|
|
104
|
+
const txParams = __privateMethod(this, _buildTransactionParams, buildTransactionParams_fn).call(this, transactionMeta);
|
|
105
|
+
const common = __privateMethod(this, _buildTransactionCommon, buildTransactionCommon_fn).call(this, transactionMeta);
|
|
106
|
+
return TransactionFactory.fromTxData(txParams, { common });
|
|
107
|
+
};
|
|
108
|
+
_buildTransactionParams = new WeakSet();
|
|
109
|
+
buildTransactionParams_fn = function(transactionMeta) {
|
|
110
|
+
return {
|
|
111
|
+
...omit(transactionMeta.txParams, "gas"),
|
|
112
|
+
gasLimit: transactionMeta.txParams.gas
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
_buildTransactionCommon = new WeakSet();
|
|
116
|
+
buildTransactionCommon_fn = function(transactionMeta) {
|
|
117
|
+
return Common.custom({
|
|
118
|
+
chainId: new BN(
|
|
119
|
+
remove0x(transactionMeta.chainId),
|
|
120
|
+
16
|
|
121
|
+
),
|
|
122
|
+
// Optimism only supports type-0 transactions; it does not support any of
|
|
123
|
+
// the newer EIPs since EIP-155. Source:
|
|
124
|
+
// <https://github.com/ethereum-optimism/optimism/blob/develop/specs/l2geth/transaction-types.md>
|
|
125
|
+
defaultHardfork: Hardfork.London
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export {
|
|
130
|
+
OptimismLayer1GasFeeFlow
|
|
131
|
+
};
|
|
132
|
+
//# sourceMappingURL=chunk-JW6P2G5A.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/gas-flows/OptimismLayer1GasFeeFlow.ts"],"sourcesContent":["import { Common, Hardfork } from '@ethereumjs/common';\nimport { TransactionFactory } from '@ethereumjs/tx';\nimport { Contract } from '@ethersproject/contracts';\nimport { Web3Provider, type ExternalProvider } from '@ethersproject/providers';\nimport { createModuleLogger, type Hex, remove0x } from '@metamask/utils';\nimport BN from 'bn.js';\nimport { omit } from 'lodash';\n\nimport { CHAIN_IDS } from '../constants';\nimport { projectLogger } from '../logger';\nimport type {\n Layer1GasFeeFlow,\n Layer1GasFeeFlowRequest,\n Layer1GasFeeFlowResponse,\n TransactionMeta,\n} from '../types';\n\n// This gas flow to be used for the following OP stack chains\nconst OPTIMISM_STACK_CHAIN_IDS: Hex[] = [\n CHAIN_IDS.OPTIMISM,\n CHAIN_IDS.OPTIMISM_TESTNET,\n CHAIN_IDS.BASE,\n CHAIN_IDS.BASE_TESTNET,\n CHAIN_IDS.OPBNB,\n CHAIN_IDS.OPBNB_TESTNET,\n CHAIN_IDS.ZORA,\n];\n\nconst log = createModuleLogger(projectLogger, 'optimisim-layer1-gas-fee-flow');\n\n// Snippet of the ABI that we need\n// Should we need more of it at some point, the full ABI can be found here:\n// https://github.com/ethereum-optimism/optimism/blob/develop/gas-oracle/abis/OVM_GasPriceOracle.json\nconst OPTIMISM_GAS_PRICE_ORACLE_ABI = [\n {\n inputs: [{ internalType: 'bytes', name: '_data', type: 'bytes' }],\n name: 'getL1Fee',\n outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n];\n\n// BlockExplorer link: https://optimistic.etherscan.io/address/0x420000000000000000000000000000000000000f#code\nconst OPTIMISM_GAS_PRICE_ORACLE_ADDRESS =\n '0x420000000000000000000000000000000000000F';\n\n/**\n * Optimism layer 1 gas fee flow that obtains gas fee estimate using Optimisim oracle contract.\n */\nexport class OptimismLayer1GasFeeFlow implements Layer1GasFeeFlow {\n matchesTransaction(transactionMeta: TransactionMeta): boolean {\n return OPTIMISM_STACK_CHAIN_IDS.includes(transactionMeta.chainId);\n }\n\n async getLayer1Fee(\n request: Layer1GasFeeFlowRequest,\n ): Promise<Layer1GasFeeFlowResponse> {\n try {\n return await this.#getOptimisimLayer1GasFee(request);\n } catch (error) {\n log('Failed to get Optimism layer 1 gas fee due to error', error);\n throw new Error(`Failed to get Optimism layer 1 gas fee`);\n }\n }\n\n async #getOptimisimLayer1GasFee(\n request: Layer1GasFeeFlowRequest,\n ): Promise<Layer1GasFeeFlowResponse> {\n const { provider, transactionMeta } = request;\n\n const contract = new Contract(\n OPTIMISM_GAS_PRICE_ORACLE_ADDRESS,\n OPTIMISM_GAS_PRICE_ORACLE_ABI,\n // Network controller provider type is uncompatible with ethers provider\n new Web3Provider(provider as unknown as ExternalProvider),\n );\n\n const serializedTransaction =\n this.#buildUnserializedTransaction(transactionMeta).serialize();\n\n const result = await contract.getL1Fee(serializedTransaction);\n\n if (result === undefined) {\n throw new Error(\n 'Failed to retrieve layer 1 gas fee from Optimism Gas Price Oracle.',\n );\n }\n\n return {\n layer1Fee: result.toHexString(),\n };\n }\n\n /**\n * Build an unserialized transaction for a transaction.\n *\n * @param transactionMeta - The transaction to build an unserialized transaction for.\n * @returns The unserialized transaction.\n */\n #buildUnserializedTransaction(transactionMeta: TransactionMeta) {\n const txParams = this.#buildTransactionParams(transactionMeta);\n const common = this.#buildTransactionCommon(transactionMeta);\n return TransactionFactory.fromTxData(txParams, { common });\n }\n\n /**\n * Build transactionParams to be used in the unserialized transaction.\n *\n * @param transactionMeta - The transaction to build transactionParams.\n * @returns The transactionParams for the unserialized transaction.\n */\n #buildTransactionParams(\n transactionMeta: TransactionMeta,\n ): TransactionMeta['txParams'] {\n return {\n ...omit(transactionMeta.txParams, 'gas'),\n gasLimit: transactionMeta.txParams.gas,\n };\n }\n\n /**\n * This produces a transaction whose information does not completely match an\n * Optimism transaction — for instance, DEFAULT_CHAIN is still 'mainnet' and\n * genesis points to the mainnet genesis, not the Optimism genesis — but\n * considering that all we want to do is serialize a transaction, this works\n * fine for our use case.\n *\n * @param transactionMeta - The transaction to build an unserialized transaction for.\n * @returns The unserialized transaction.\n */\n #buildTransactionCommon(transactionMeta: TransactionMeta) {\n return Common.custom({\n chainId: new BN(\n remove0x(transactionMeta.chainId),\n 16,\n ) as unknown as number,\n // Optimism only supports type-0 transactions; it does not support any of\n // the newer EIPs since EIP-155. Source:\n // <https://github.com/ethereum-optimism/optimism/blob/develop/specs/l2geth/transaction-types.md>\n defaultHardfork: Hardfork.London,\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,QAAQ,gBAAgB;AACjC,SAAS,0BAA0B;AACnC,SAAS,gBAAgB;AACzB,SAAS,oBAA2C;AACpD,SAAS,oBAA8B,gBAAgB;AACvD,OAAO,QAAQ;AACf,SAAS,YAAY;AAYrB,IAAM,2BAAkC;AAAA,EACtC,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AACZ;AAEA,IAAM,MAAM,mBAAmB,eAAe,+BAA+B;AAK7E,IAAM,gCAAgC;AAAA,EACpC;AAAA,IACE,QAAQ,CAAC,EAAE,cAAc,SAAS,MAAM,SAAS,MAAM,QAAQ,CAAC;AAAA,IAChE,MAAM;AAAA,IACN,SAAS,CAAC,EAAE,cAAc,WAAW,MAAM,IAAI,MAAM,UAAU,CAAC;AAAA,IAChE,iBAAiB;AAAA,IACjB,MAAM;AAAA,EACR;AACF;AAGA,IAAM,oCACJ;AA7CF;AAkDO,IAAM,2BAAN,MAA2D;AAAA,EAA3D;AAgBL,uBAAM;AAkCN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAhFA,mBAAmB,iBAA2C;AAC5D,WAAO,yBAAyB,SAAS,gBAAgB,OAAO;AAAA,EAClE;AAAA,EAEA,MAAM,aACJ,SACmC;AACnC,QAAI;AACF,aAAO,MAAM,sBAAK,wDAAL,WAA+B;AAAA,IAC9C,SAAS,OAAO;AACd,UAAI,uDAAuD,KAAK;AAChE,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AAAA,EACF;AA+EF;AA7EQ;AAAA,8BAAyB,eAC7B,SACmC;AACnC,QAAM,EAAE,UAAU,gBAAgB,IAAI;AAEtC,QAAM,WAAW,IAAI;AAAA,IACnB;AAAA,IACA;AAAA;AAAA,IAEA,IAAI,aAAa,QAAuC;AAAA,EAC1D;AAEA,QAAM,wBACJ,sBAAK,gEAAL,WAAmC,iBAAiB,UAAU;AAEhE,QAAM,SAAS,MAAM,SAAS,SAAS,qBAAqB;AAE5D,MAAI,WAAW,QAAW;AACxB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,WAAW,OAAO,YAAY;AAAA,EAChC;AACF;AAQA;AAAA,kCAA6B,SAAC,iBAAkC;AAC9D,QAAM,WAAW,sBAAK,oDAAL,WAA6B;AAC9C,QAAM,SAAS,sBAAK,oDAAL,WAA6B;AAC5C,SAAO,mBAAmB,WAAW,UAAU,EAAE,OAAO,CAAC;AAC3D;AAQA;AAAA,4BAAuB,SACrB,iBAC6B;AAC7B,SAAO;AAAA,IACL,GAAG,KAAK,gBAAgB,UAAU,KAAK;AAAA,IACvC,UAAU,gBAAgB,SAAS;AAAA,EACrC;AACF;AAYA;AAAA,4BAAuB,SAAC,iBAAkC;AACxD,SAAO,OAAO,OAAO;AAAA,IACnB,SAAS,IAAI;AAAA,MACX,SAAS,gBAAgB,OAAO;AAAA,MAChC;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAIA,iBAAiB,SAAS;AAAA,EAC5B,CAAC;AACH;","names":[]}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SimulationChainNotSupportedError,
|
|
3
|
+
SimulationError
|
|
4
|
+
} from "./chunk-HQSNKCXI.mjs";
|
|
1
5
|
import {
|
|
2
6
|
projectLogger
|
|
3
7
|
} from "./chunk-UQQWZT6C.mjs";
|
|
@@ -27,7 +31,8 @@ async function simulateTransactions(chainId, request) {
|
|
|
27
31
|
const responseJson = await response.json();
|
|
28
32
|
log("Received response", responseJson);
|
|
29
33
|
if (responseJson.error) {
|
|
30
|
-
|
|
34
|
+
const { code, message } = responseJson.error;
|
|
35
|
+
throw new SimulationError(message, code);
|
|
31
36
|
}
|
|
32
37
|
return responseJson?.result;
|
|
33
38
|
}
|
|
@@ -37,7 +42,7 @@ async function getSimulationUrl(chainId) {
|
|
|
37
42
|
const network = networkData[chainIdDecimal];
|
|
38
43
|
if (!network?.confirmations) {
|
|
39
44
|
log("Chain is not supported", chainId);
|
|
40
|
-
throw new
|
|
45
|
+
throw new SimulationChainNotSupportedError(chainId);
|
|
41
46
|
}
|
|
42
47
|
return getUrl(network.network);
|
|
43
48
|
}
|
|
@@ -53,4 +58,4 @@ function getUrl(subdomain) {
|
|
|
53
58
|
export {
|
|
54
59
|
simulateTransactions
|
|
55
60
|
};
|
|
56
|
-
//# sourceMappingURL=chunk-
|
|
61
|
+
//# sourceMappingURL=chunk-K4KOSAGM.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/simulation-api.ts"],"sourcesContent":["import { convertHexToDecimal } from '@metamask/controller-utils';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\n\nimport { SimulationChainNotSupportedError, SimulationError } from '../errors';\nimport { projectLogger } from '../logger';\n\nconst log = createModuleLogger(projectLogger, 'simulation-api');\n\nconst RPC_METHOD = 'infura_simulateTransactions';\nconst BASE_URL = 'https://tx-sentinel-{0}.api.cx.metamask.io/';\nconst ENDPOINT_NETWORKS = 'networks';\n\n/** Single transaction to simulate in a simulation API request. */\nexport type SimulationRequestTransaction = {\n /** Data to send with the transaction. */\n data?: Hex;\n\n /** Sender of the transaction. */\n from: Hex;\n\n /** Gas limit for the transaction. */\n gas?: Hex;\n\n /** Maximum fee per gas for the transaction. */\n maxFeePerGas?: Hex;\n\n /** Maximum priority fee per gas for the transaction. */\n maxPriorityFeePerGas?: Hex;\n\n /** Recipient of the transaction. */\n to?: Hex;\n\n /** Value to send with the transaction. */\n value?: Hex;\n};\n\n/** Request to the simulation API to simulate transactions. */\nexport type SimulationRequest = {\n /**\n * Transactions to be sequentially simulated.\n * State changes impact subsequent transactions in the list.\n */\n transactions: SimulationRequestTransaction[];\n\n /**\n * Overrides to the state of the blockchain, keyed by smart contract address.\n */\n overrides?: {\n [address: Hex]: {\n /** Overrides to the storage slots for a smart contract account. */\n stateDiff: {\n [slot: Hex]: Hex;\n };\n };\n };\n\n /**\n * Whether to include call traces in the response.\n * Defaults to false.\n */\n withCallTrace?: boolean;\n\n /**\n * Whether to include event logs in the response.\n * Defaults to false.\n */\n withLogs?: boolean;\n};\n\n/** Raw event log emitted by a simulated transaction. */\nexport type SimulationResponseLog = {\n /** Address of the account that created the event. */\n address: Hex;\n\n /** Raw data in the event that is not indexed. */\n data: Hex;\n\n /** Raw indexed data from the event. */\n topics: Hex[];\n};\n\n/** Call trace of a single simulated transaction. */\nexport type SimulationResponseCallTrace = {\n /** Nested calls. */\n calls: SimulationResponseCallTrace[];\n\n /** Raw event logs created by the call. */\n logs: SimulationResponseLog[];\n};\n\n/**\n * Changes to the blockchain state.\n * Keyed by account address.\n */\nexport type SimulationResponseStateDiff = {\n [address: Hex]: {\n /** Native balance of the account. */\n balance?: Hex;\n\n /** Nonce of the account. */\n nonce?: Hex;\n\n /** Storage values per slot. */\n storage?: {\n [slot: Hex]: Hex;\n };\n };\n};\n\n/** Response from the simulation API for a single transaction. */\nexport type SimulationResponseTransaction = {\n /** An error message indicating the transaction could not be simulated. */\n error?: string;\n\n /** Return value of the transaction, such as the balance if calling balanceOf. */\n return: Hex;\n\n /** Hierarchy of call data including nested calls and logs. */\n callTrace?: SimulationResponseCallTrace;\n\n /** Changes to the blockchain state. */\n stateDiff?: {\n /** Initial blockchain state before the transaction. */\n pre?: SimulationResponseStateDiff;\n\n /** Updated blockchain state after the transaction. */\n post?: SimulationResponseStateDiff;\n };\n};\n\n/** Response from the simulation API. */\nexport type SimulationResponse = {\n /** Simulation data for each transaction in the request. */\n transactions: SimulationResponseTransaction[];\n};\n\n/** Data for a network supported by the Simulation API. */\ntype SimulationNetwork = {\n /** Subdomain of the API for the network. */\n network: string;\n\n /** Whether the network supports confirmation simulations. */\n confirmations: boolean;\n};\n\n/** Response from the simulation API containing supported networks. */\ntype SimulationNetworkResponse = {\n [chainIdDecimal: string]: SimulationNetwork;\n};\n\nlet requestIdCounter = 0;\n\n/**\n * Simulate transactions using the transaction simulation API.\n * @param chainId - The chain ID to simulate transactions on.\n * @param request - The request to simulate transactions.\n */\nexport async function simulateTransactions(\n chainId: Hex,\n request: SimulationRequest,\n): Promise<SimulationResponse> {\n const url = await getSimulationUrl(chainId);\n\n log('Sending request', url, request);\n\n const requestId = requestIdCounter;\n requestIdCounter += 1;\n\n const response = await fetch(url, {\n method: 'POST',\n body: JSON.stringify({\n id: String(requestId),\n jsonrpc: '2.0',\n method: RPC_METHOD,\n params: [request],\n }),\n });\n\n const responseJson = await response.json();\n\n log('Received response', responseJson);\n\n if (responseJson.error) {\n const { code, message } = responseJson.error;\n throw new SimulationError(message, code);\n }\n\n return responseJson?.result;\n}\n\n/**\n * Get the URL for the transaction simulation API.\n * @param chainId - The chain ID to get the URL for.\n * @returns The URL for the transaction simulation API.\n */\nasync function getSimulationUrl(chainId: Hex): Promise<string> {\n const networkData = await getNetworkData();\n const chainIdDecimal = convertHexToDecimal(chainId);\n const network = networkData[chainIdDecimal];\n\n if (!network?.confirmations) {\n log('Chain is not supported', chainId);\n throw new SimulationChainNotSupportedError(chainId);\n }\n\n return getUrl(network.network);\n}\n\n/**\n * Retrieve the supported network data from the simulation API.\n */\nasync function getNetworkData(): Promise<SimulationNetworkResponse> {\n const url = `${getUrl('ethereum-mainnet')}${ENDPOINT_NETWORKS}`;\n const response = await fetch(url);\n return response.json();\n}\n\n/**\n * Generate the URL for the specified subdomain in the simulation API.\n * @param subdomain - The subdomain to generate the URL for.\n * @returns The URL for the transaction simulation API.\n */\nfunction getUrl(subdomain: string): string {\n return BASE_URL.replace('{0}', subdomain);\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,2BAA2B;AACpC,SAAS,0BAAoC;AAK7C,IAAM,MAAM,mBAAmB,eAAe,gBAAgB;AAE9D,IAAM,aAAa;AACnB,IAAM,WAAW;AACjB,IAAM,oBAAoB;AA4I1B,IAAI,mBAAmB;AAOvB,eAAsB,qBACpB,SACA,SAC6B;AAC7B,QAAM,MAAM,MAAM,iBAAiB,OAAO;AAE1C,MAAI,mBAAmB,KAAK,OAAO;AAEnC,QAAM,YAAY;AAClB,sBAAoB;AAEpB,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IAChC,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU;AAAA,MACnB,IAAI,OAAO,SAAS;AAAA,MACpB,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ,CAAC,OAAO;AAAA,IAClB,CAAC;AAAA,EACH,CAAC;AAED,QAAM,eAAe,MAAM,SAAS,KAAK;AAEzC,MAAI,qBAAqB,YAAY;AAErC,MAAI,aAAa,OAAO;AACtB,UAAM,EAAE,MAAM,QAAQ,IAAI,aAAa;AACvC,UAAM,IAAI,gBAAgB,SAAS,IAAI;AAAA,EACzC;AAEA,SAAO,cAAc;AACvB;AAOA,eAAe,iBAAiB,SAA+B;AAC7D,QAAM,cAAc,MAAM,eAAe;AACzC,QAAM,iBAAiB,oBAAoB,OAAO;AAClD,QAAM,UAAU,YAAY,cAAc;AAE1C,MAAI,CAAC,SAAS,eAAe;AAC3B,QAAI,0BAA0B,OAAO;AACrC,UAAM,IAAI,iCAAiC,OAAO;AAAA,EACpD;AAEA,SAAO,OAAO,QAAQ,OAAO;AAC/B;AAKA,eAAe,iBAAqD;AAClE,QAAM,MAAM,GAAG,OAAO,kBAAkB,CAAC,GAAG,iBAAiB;AAC7D,QAAM,WAAW,MAAM,MAAM,GAAG;AAChC,SAAO,SAAS,KAAK;AACvB;AAOA,SAAS,OAAO,WAA2B;AACzC,SAAO,SAAS,QAAQ,OAAO,SAAS;AAC1C;","names":[]}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
// src/utils/transaction-type.ts
|
|
2
2
|
import { Interface } from "@ethersproject/abi";
|
|
3
3
|
import { query } from "@metamask/controller-utils";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
abiERC721,
|
|
6
|
+
abiERC20,
|
|
7
|
+
abiERC1155,
|
|
8
|
+
abiFiatTokenV2
|
|
9
|
+
} from "@metamask/metamask-eth-abis";
|
|
5
10
|
var ESTIMATE_GAS_ERROR = "eth_estimateGas rpc method error";
|
|
6
11
|
var ERC20Interface = new Interface(abiERC20);
|
|
7
12
|
var ERC721Interface = new Interface(abiERC721);
|
|
8
13
|
var ERC1155Interface = new Interface(abiERC1155);
|
|
14
|
+
var USDCInterface = new Interface(abiFiatTokenV2);
|
|
9
15
|
async function determineTransactionType(txParams, ethQuery) {
|
|
10
16
|
const { data, to } = txParams;
|
|
11
17
|
if (data && !to) {
|
|
@@ -32,8 +38,11 @@ async function determineTransactionType(txParams, ethQuery) {
|
|
|
32
38
|
"setapprovalforall" /* tokenMethodSetApprovalForAll */,
|
|
33
39
|
"transfer" /* tokenMethodTransfer */,
|
|
34
40
|
"transferfrom" /* tokenMethodTransferFrom */,
|
|
35
|
-
"safetransferfrom" /* tokenMethodSafeTransferFrom
|
|
36
|
-
|
|
41
|
+
"safetransferfrom" /* tokenMethodSafeTransferFrom */,
|
|
42
|
+
"increaseAllowance" /* tokenMethodIncreaseAllowance */
|
|
43
|
+
].find(
|
|
44
|
+
(methodName) => methodName.toLowerCase() === name.toLowerCase()
|
|
45
|
+
);
|
|
37
46
|
if (tokenMethodName) {
|
|
38
47
|
return { type: tokenMethodName, getCodeResponse };
|
|
39
48
|
}
|
|
@@ -55,6 +64,10 @@ function parseStandardTokenTransactionData(data) {
|
|
|
55
64
|
return ERC1155Interface.parseTransaction({ data });
|
|
56
65
|
} catch {
|
|
57
66
|
}
|
|
67
|
+
try {
|
|
68
|
+
return USDCInterface.parseTransaction({ data });
|
|
69
|
+
} catch {
|
|
70
|
+
}
|
|
58
71
|
return void 0;
|
|
59
72
|
}
|
|
60
73
|
async function readAddressAsContract(ethQuery, address) {
|
|
@@ -72,4 +85,4 @@ export {
|
|
|
72
85
|
ESTIMATE_GAS_ERROR,
|
|
73
86
|
determineTransactionType
|
|
74
87
|
};
|
|
75
|
-
//# sourceMappingURL=chunk-
|
|
88
|
+
//# sourceMappingURL=chunk-KG4UW4K4.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/transaction-type.ts"],"sourcesContent":["import type { TransactionDescription } from '@ethersproject/abi';\nimport { Interface } from '@ethersproject/abi';\nimport { query } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport {\n abiERC721,\n abiERC20,\n abiERC1155,\n abiFiatTokenV2,\n} from '@metamask/metamask-eth-abis';\n\nimport type { InferTransactionTypeResult, TransactionParams } from '../types';\nimport { TransactionType } from '../types';\n\nexport const ESTIMATE_GAS_ERROR = 'eth_estimateGas rpc method error';\n\nconst ERC20Interface = new Interface(abiERC20);\nconst ERC721Interface = new Interface(abiERC721);\nconst ERC1155Interface = new Interface(abiERC1155);\nconst USDCInterface = new Interface(abiFiatTokenV2);\n\n/**\n * Determines the type of the transaction by analyzing the txParams.\n * It will never return TRANSACTION_TYPE_CANCEL or TRANSACTION_TYPE_RETRY as these\n * represent specific events that we specify manually at transaction creation.\n *\n * @param txParams - Parameters for the transaction.\n * @param ethQuery - EthQuery instance.\n * @returns A object with the transaction type and the contract code response in Hex.\n */\nexport async function determineTransactionType(\n txParams: TransactionParams,\n ethQuery: EthQuery,\n): Promise<InferTransactionTypeResult> {\n const { data, to } = txParams;\n\n if (data && !to) {\n return { type: TransactionType.deployContract, getCodeResponse: undefined };\n }\n\n const { contractCode: getCodeResponse, isContractAddress } =\n await readAddressAsContract(ethQuery, to);\n\n if (!isContractAddress) {\n return { type: TransactionType.simpleSend, getCodeResponse };\n }\n\n const hasValue = Number(txParams.value ?? '0') !== 0;\n\n const contractInteractionResult = {\n type: TransactionType.contractInteraction,\n getCodeResponse,\n };\n\n if (!data || hasValue) {\n return contractInteractionResult;\n }\n\n const name = parseStandardTokenTransactionData(data)?.name;\n\n if (!name) {\n return contractInteractionResult;\n }\n\n const tokenMethodName = [\n TransactionType.tokenMethodApprove,\n TransactionType.tokenMethodSetApprovalForAll,\n TransactionType.tokenMethodTransfer,\n TransactionType.tokenMethodTransferFrom,\n TransactionType.tokenMethodSafeTransferFrom,\n TransactionType.tokenMethodIncreaseAllowance,\n ].find(\n (methodName) => methodName.toLowerCase() === (name as string).toLowerCase(),\n );\n\n if (tokenMethodName) {\n return { type: tokenMethodName, getCodeResponse };\n }\n\n return contractInteractionResult;\n}\n\n/**\n * Attempts to decode transaction data using ABIs for three different token standards: ERC20, ERC721, ERC1155.\n * The data will decode correctly if the transaction is an interaction with a contract that matches one of these\n * contract standards\n *\n * @param data - Encoded transaction data.\n * @returns A representation of an ethereum contract call.\n */\nfunction parseStandardTokenTransactionData(\n data?: string,\n): TransactionDescription | undefined {\n if (!data) {\n return undefined;\n }\n\n try {\n return ERC20Interface.parseTransaction({ data });\n } catch {\n // ignore and next try to parse with erc721 ABI\n }\n\n try {\n return ERC721Interface.parseTransaction({ data });\n } catch {\n // ignore and next try to parse with erc1155 ABI\n }\n\n try {\n return ERC1155Interface.parseTransaction({ data });\n } catch {\n // ignore and return undefined\n }\n\n try {\n return USDCInterface.parseTransaction({ data });\n } catch {\n // ignore and return undefined\n }\n\n return undefined;\n}\n\n/**\n * Reads an Ethereum address and determines if it is a contract address.\n *\n * @param ethQuery - The Ethereum query object used to interact with the Ethereum blockchain.\n * @param address - The Ethereum address.\n * @returns An object containing the contract code and a boolean indicating if it is a contract address.\n */\nasync function readAddressAsContract(\n ethQuery: EthQuery,\n address?: string,\n): Promise<{\n contractCode: string | null;\n isContractAddress: boolean;\n}> {\n let contractCode;\n try {\n contractCode = await query(ethQuery, 'getCode', [address]);\n } catch (e) {\n contractCode = null;\n }\n\n const isContractAddress = contractCode\n ? contractCode !== '0x' && contractCode !== '0x0'\n : false;\n return { contractCode, isContractAddress };\n}\n"],"mappings":";AACA,SAAS,iBAAiB;AAC1B,SAAS,aAAa;AAEtB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAKA,IAAM,qBAAqB;AAElC,IAAM,iBAAiB,IAAI,UAAU,QAAQ;AAC7C,IAAM,kBAAkB,IAAI,UAAU,SAAS;AAC/C,IAAM,mBAAmB,IAAI,UAAU,UAAU;AACjD,IAAM,gBAAgB,IAAI,UAAU,cAAc;AAWlD,eAAsB,yBACpB,UACA,UACqC;AACrC,QAAM,EAAE,MAAM,GAAG,IAAI;AAErB,MAAI,QAAQ,CAAC,IAAI;AACf,WAAO,EAAE,iDAAsC,iBAAiB,OAAU;AAAA,EAC5E;AAEA,QAAM,EAAE,cAAc,iBAAiB,kBAAkB,IACvD,MAAM,sBAAsB,UAAU,EAAE;AAE1C,MAAI,CAAC,mBAAmB;AACtB,WAAO,EAAE,qCAAkC,gBAAgB;AAAA,EAC7D;AAEA,QAAM,WAAW,OAAO,SAAS,SAAS,GAAG,MAAM;AAEnD,QAAM,4BAA4B;AAAA,IAChC;AAAA,IACA;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ,UAAU;AACrB,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,kCAAkC,IAAI,GAAG;AAEtD,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,QAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxB,EAAE;AAAA,IACA,CAAC,eAAe,WAAW,YAAY,MAAO,KAAgB,YAAY;AAAA,EAC5E;AAEA,MAAI,iBAAiB;AACnB,WAAO,EAAE,MAAM,iBAAiB,gBAAgB;AAAA,EAClD;AAEA,SAAO;AACT;AAUA,SAAS,kCACP,MACoC;AACpC,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,MAAI;AACF,WAAO,eAAe,iBAAiB,EAAE,KAAK,CAAC;AAAA,EACjD,QAAQ;AAAA,EAER;AAEA,MAAI;AACF,WAAO,gBAAgB,iBAAiB,EAAE,KAAK,CAAC;AAAA,EAClD,QAAQ;AAAA,EAER;AAEA,MAAI;AACF,WAAO,iBAAiB,iBAAiB,EAAE,KAAK,CAAC;AAAA,EACnD,QAAQ;AAAA,EAER;AAEA,MAAI;AACF,WAAO,cAAc,iBAAiB,EAAE,KAAK,CAAC;AAAA,EAChD,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AASA,eAAe,sBACb,UACA,SAIC;AACD,MAAI;AACJ,MAAI;AACF,mBAAe,MAAM,MAAM,UAAU,WAAW,CAAC,OAAO,CAAC;AAAA,EAC3D,SAAS,GAAG;AACV,mBAAe;AAAA,EACjB;AAEA,QAAM,oBAAoB,eACtB,iBAAiB,QAAQ,iBAAiB,QAC1C;AACJ,SAAO,EAAE,cAAc,kBAAkB;AAC3C;","names":[]}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
gweiDecimalToWeiHex
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TZEAWUXE.mjs";
|
|
4
4
|
import {
|
|
5
5
|
projectLogger
|
|
6
6
|
} from "./chunk-UQQWZT6C.mjs";
|
|
7
7
|
import {
|
|
8
8
|
GasFeeEstimateLevel
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-YEJJKWT2.mjs";
|
|
10
10
|
import {
|
|
11
11
|
__privateAdd,
|
|
12
12
|
__privateMethod
|
|
@@ -87,4 +87,4 @@ getLegacyLevel_fn = function(gasFeeEstimates, level) {
|
|
|
87
87
|
export {
|
|
88
88
|
DefaultGasFeeFlow
|
|
89
89
|
};
|
|
90
|
-
//# sourceMappingURL=chunk-
|
|
90
|
+
//# sourceMappingURL=chunk-KKCD5UMP.mjs.map
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
var _chunkHMOSP33Fjs = require('./chunk-HMOSP33F.js');
|
|
5
|
+
|
|
6
|
+
|
|
3
7
|
var _chunkS6VGOPUYjs = require('./chunk-S6VGOPUY.js');
|
|
4
8
|
|
|
5
9
|
// src/utils/simulation-api.ts
|
|
@@ -27,7 +31,8 @@ async function simulateTransactions(chainId, request) {
|
|
|
27
31
|
const responseJson = await response.json();
|
|
28
32
|
log("Received response", responseJson);
|
|
29
33
|
if (responseJson.error) {
|
|
30
|
-
|
|
34
|
+
const { code, message } = responseJson.error;
|
|
35
|
+
throw new (0, _chunkHMOSP33Fjs.SimulationError)(message, code);
|
|
31
36
|
}
|
|
32
37
|
return responseJson?.result;
|
|
33
38
|
}
|
|
@@ -37,7 +42,7 @@ async function getSimulationUrl(chainId) {
|
|
|
37
42
|
const network = networkData[chainIdDecimal];
|
|
38
43
|
if (!network?.confirmations) {
|
|
39
44
|
log("Chain is not supported", chainId);
|
|
40
|
-
throw new
|
|
45
|
+
throw new (0, _chunkHMOSP33Fjs.SimulationChainNotSupportedError)(chainId);
|
|
41
46
|
}
|
|
42
47
|
return getUrl(network.network);
|
|
43
48
|
}
|
|
@@ -53,4 +58,4 @@ function getUrl(subdomain) {
|
|
|
53
58
|
|
|
54
59
|
|
|
55
60
|
exports.simulateTransactions = simulateTransactions;
|
|
56
|
-
//# sourceMappingURL=chunk-
|
|
61
|
+
//# sourceMappingURL=chunk-KT6UAKBB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/simulation-api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,SAAS,2BAA2B;AACpC,SAAS,0BAAoC;AAK7C,IAAM,MAAM,mBAAmB,eAAe,gBAAgB;AAE9D,IAAM,aAAa;AACnB,IAAM,WAAW;AACjB,IAAM,oBAAoB;AA4I1B,IAAI,mBAAmB;AAOvB,eAAsB,qBACpB,SACA,SAC6B;AAC7B,QAAM,MAAM,MAAM,iBAAiB,OAAO;AAE1C,MAAI,mBAAmB,KAAK,OAAO;AAEnC,QAAM,YAAY;AAClB,sBAAoB;AAEpB,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IAChC,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU;AAAA,MACnB,IAAI,OAAO,SAAS;AAAA,MACpB,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ,CAAC,OAAO;AAAA,IAClB,CAAC;AAAA,EACH,CAAC;AAED,QAAM,eAAe,MAAM,SAAS,KAAK;AAEzC,MAAI,qBAAqB,YAAY;AAErC,MAAI,aAAa,OAAO;AACtB,UAAM,EAAE,MAAM,QAAQ,IAAI,aAAa;AACvC,UAAM,IAAI,gBAAgB,SAAS,IAAI;AAAA,EACzC;AAEA,SAAO,cAAc;AACvB;AAOA,eAAe,iBAAiB,SAA+B;AAC7D,QAAM,cAAc,MAAM,eAAe;AACzC,QAAM,iBAAiB,oBAAoB,OAAO;AAClD,QAAM,UAAU,YAAY,cAAc;AAE1C,MAAI,CAAC,SAAS,eAAe;AAC3B,QAAI,0BAA0B,OAAO;AACrC,UAAM,IAAI,iCAAiC,OAAO;AAAA,EACpD;AAEA,SAAO,OAAO,QAAQ,OAAO;AAC/B;AAKA,eAAe,iBAAqD;AAClE,QAAM,MAAM,GAAG,OAAO,kBAAkB,CAAC,GAAG,iBAAiB;AAC7D,QAAM,WAAW,MAAM,MAAM,GAAG;AAChC,SAAO,SAAS,KAAK;AACvB;AAOA,SAAS,OAAO,WAA2B;AACzC,SAAO,SAAS,QAAQ,OAAO,SAAS;AAC1C","sourcesContent":["import { convertHexToDecimal } from '@metamask/controller-utils';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\n\nimport { SimulationChainNotSupportedError, SimulationError } from '../errors';\nimport { projectLogger } from '../logger';\n\nconst log = createModuleLogger(projectLogger, 'simulation-api');\n\nconst RPC_METHOD = 'infura_simulateTransactions';\nconst BASE_URL = 'https://tx-sentinel-{0}.api.cx.metamask.io/';\nconst ENDPOINT_NETWORKS = 'networks';\n\n/** Single transaction to simulate in a simulation API request. */\nexport type SimulationRequestTransaction = {\n /** Data to send with the transaction. */\n data?: Hex;\n\n /** Sender of the transaction. */\n from: Hex;\n\n /** Gas limit for the transaction. */\n gas?: Hex;\n\n /** Maximum fee per gas for the transaction. */\n maxFeePerGas?: Hex;\n\n /** Maximum priority fee per gas for the transaction. */\n maxPriorityFeePerGas?: Hex;\n\n /** Recipient of the transaction. */\n to?: Hex;\n\n /** Value to send with the transaction. */\n value?: Hex;\n};\n\n/** Request to the simulation API to simulate transactions. */\nexport type SimulationRequest = {\n /**\n * Transactions to be sequentially simulated.\n * State changes impact subsequent transactions in the list.\n */\n transactions: SimulationRequestTransaction[];\n\n /**\n * Overrides to the state of the blockchain, keyed by smart contract address.\n */\n overrides?: {\n [address: Hex]: {\n /** Overrides to the storage slots for a smart contract account. */\n stateDiff: {\n [slot: Hex]: Hex;\n };\n };\n };\n\n /**\n * Whether to include call traces in the response.\n * Defaults to false.\n */\n withCallTrace?: boolean;\n\n /**\n * Whether to include event logs in the response.\n * Defaults to false.\n */\n withLogs?: boolean;\n};\n\n/** Raw event log emitted by a simulated transaction. */\nexport type SimulationResponseLog = {\n /** Address of the account that created the event. */\n address: Hex;\n\n /** Raw data in the event that is not indexed. */\n data: Hex;\n\n /** Raw indexed data from the event. */\n topics: Hex[];\n};\n\n/** Call trace of a single simulated transaction. */\nexport type SimulationResponseCallTrace = {\n /** Nested calls. */\n calls: SimulationResponseCallTrace[];\n\n /** Raw event logs created by the call. */\n logs: SimulationResponseLog[];\n};\n\n/**\n * Changes to the blockchain state.\n * Keyed by account address.\n */\nexport type SimulationResponseStateDiff = {\n [address: Hex]: {\n /** Native balance of the account. */\n balance?: Hex;\n\n /** Nonce of the account. */\n nonce?: Hex;\n\n /** Storage values per slot. */\n storage?: {\n [slot: Hex]: Hex;\n };\n };\n};\n\n/** Response from the simulation API for a single transaction. */\nexport type SimulationResponseTransaction = {\n /** An error message indicating the transaction could not be simulated. */\n error?: string;\n\n /** Return value of the transaction, such as the balance if calling balanceOf. */\n return: Hex;\n\n /** Hierarchy of call data including nested calls and logs. */\n callTrace?: SimulationResponseCallTrace;\n\n /** Changes to the blockchain state. */\n stateDiff?: {\n /** Initial blockchain state before the transaction. */\n pre?: SimulationResponseStateDiff;\n\n /** Updated blockchain state after the transaction. */\n post?: SimulationResponseStateDiff;\n };\n};\n\n/** Response from the simulation API. */\nexport type SimulationResponse = {\n /** Simulation data for each transaction in the request. */\n transactions: SimulationResponseTransaction[];\n};\n\n/** Data for a network supported by the Simulation API. */\ntype SimulationNetwork = {\n /** Subdomain of the API for the network. */\n network: string;\n\n /** Whether the network supports confirmation simulations. */\n confirmations: boolean;\n};\n\n/** Response from the simulation API containing supported networks. */\ntype SimulationNetworkResponse = {\n [chainIdDecimal: string]: SimulationNetwork;\n};\n\nlet requestIdCounter = 0;\n\n/**\n * Simulate transactions using the transaction simulation API.\n * @param chainId - The chain ID to simulate transactions on.\n * @param request - The request to simulate transactions.\n */\nexport async function simulateTransactions(\n chainId: Hex,\n request: SimulationRequest,\n): Promise<SimulationResponse> {\n const url = await getSimulationUrl(chainId);\n\n log('Sending request', url, request);\n\n const requestId = requestIdCounter;\n requestIdCounter += 1;\n\n const response = await fetch(url, {\n method: 'POST',\n body: JSON.stringify({\n id: String(requestId),\n jsonrpc: '2.0',\n method: RPC_METHOD,\n params: [request],\n }),\n });\n\n const responseJson = await response.json();\n\n log('Received response', responseJson);\n\n if (responseJson.error) {\n const { code, message } = responseJson.error;\n throw new SimulationError(message, code);\n }\n\n return responseJson?.result;\n}\n\n/**\n * Get the URL for the transaction simulation API.\n * @param chainId - The chain ID to get the URL for.\n * @returns The URL for the transaction simulation API.\n */\nasync function getSimulationUrl(chainId: Hex): Promise<string> {\n const networkData = await getNetworkData();\n const chainIdDecimal = convertHexToDecimal(chainId);\n const network = networkData[chainIdDecimal];\n\n if (!network?.confirmations) {\n log('Chain is not supported', chainId);\n throw new SimulationChainNotSupportedError(chainId);\n }\n\n return getUrl(network.network);\n}\n\n/**\n * Retrieve the supported network data from the simulation API.\n */\nasync function getNetworkData(): Promise<SimulationNetworkResponse> {\n const url = `${getUrl('ethereum-mainnet')}${ENDPOINT_NETWORKS}`;\n const response = await fetch(url);\n return response.json();\n}\n\n/**\n * Generate the URL for the specified subdomain in the simulation API.\n * @param subdomain - The subdomain to generate the URL for.\n * @returns The URL for the transaction simulation API.\n */\nfunction getUrl(subdomain: string): string {\n return BASE_URL.replace('{0}', subdomain);\n}\n"]}
|