@toruslabs/ethereum-controllers 5.11.0 → 6.0.1

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 (111) hide show
  1. package/dist/ethereumControllers.cjs.js +80 -431
  2. package/dist/ethereumControllers.esm.js +30 -349
  3. package/dist/ethereumControllers.umd.min.js +1 -1
  4. package/dist/ethereumControllers.umd.min.js.LICENSE.txt +7 -2
  5. package/dist/lib.cjs/Account/AccountTrackerController.js +160 -0
  6. package/dist/lib.cjs/Block/PollingBlockTracker.js +85 -0
  7. package/dist/lib.cjs/Currency/CurrencyController.js +111 -0
  8. package/dist/lib.cjs/Gas/GasFeeController.js +214 -0
  9. package/dist/lib.cjs/Gas/gasUtil.js +148 -0
  10. package/dist/lib.cjs/Keyring/KeyringController.js +93 -0
  11. package/dist/lib.cjs/Message/AbstractMessageController.js +107 -0
  12. package/dist/lib.cjs/Message/AddChainController.js +78 -0
  13. package/dist/lib.cjs/Message/MessageController.js +77 -0
  14. package/dist/lib.cjs/Message/PersonalMessageController.js +77 -0
  15. package/dist/lib.cjs/Message/SwitchChainController.js +78 -0
  16. package/dist/lib.cjs/Message/TypedMessageController.js +81 -0
  17. package/dist/lib.cjs/Message/utils.js +112 -0
  18. package/dist/lib.cjs/Network/NetworkController.js +201 -0
  19. package/dist/lib.cjs/Network/cacheIdentifier.js +112 -0
  20. package/dist/lib.cjs/Network/createEthereumMiddleware.js +302 -0
  21. package/dist/lib.cjs/Network/createJsonRpcClient.js +64 -0
  22. package/dist/lib.cjs/Nfts/NftHandler.js +180 -0
  23. package/dist/lib.cjs/Nfts/NftsController.js +213 -0
  24. package/dist/lib.cjs/Preferences/PreferencesController.js +476 -0
  25. package/dist/lib.cjs/Tokens/TokenHandler.js +51 -0
  26. package/dist/lib.cjs/Tokens/TokenRatesController.js +112 -0
  27. package/dist/lib.cjs/Tokens/TokensController.js +259 -0
  28. package/dist/lib.cjs/Transaction/NonceTracker.js +150 -0
  29. package/dist/lib.cjs/Transaction/PendingTransactionTracker.js +222 -0
  30. package/dist/lib.cjs/Transaction/TransactionController.js +515 -0
  31. package/dist/lib.cjs/Transaction/TransactionGasUtil.js +81 -0
  32. package/dist/lib.cjs/Transaction/TransactionStateHistoryHelper.js +42 -0
  33. package/dist/lib.cjs/Transaction/TransactionStateManager.js +296 -0
  34. package/dist/lib.cjs/Transaction/TransactionUtils.js +341 -0
  35. package/dist/lib.cjs/index.js +171 -0
  36. package/dist/lib.cjs/utils/abis.js +510 -0
  37. package/dist/lib.cjs/utils/constants.js +362 -0
  38. package/dist/lib.cjs/utils/contractAddresses.js +16 -0
  39. package/dist/lib.cjs/utils/conversionUtils.js +232 -0
  40. package/dist/lib.cjs/utils/helpers.js +244 -0
  41. package/dist/lib.cjs/utils/lodashUtils.js +25 -0
  42. package/dist/lib.esm/Account/AccountTrackerController.js +158 -0
  43. package/dist/lib.esm/Block/PollingBlockTracker.js +83 -0
  44. package/dist/lib.esm/Currency/CurrencyController.js +109 -0
  45. package/dist/lib.esm/Gas/GasFeeController.js +212 -0
  46. package/dist/lib.esm/Gas/gasUtil.js +141 -0
  47. package/dist/lib.esm/Keyring/KeyringController.js +91 -0
  48. package/dist/lib.esm/Message/AbstractMessageController.js +105 -0
  49. package/dist/lib.esm/Message/AddChainController.js +76 -0
  50. package/dist/lib.esm/Message/MessageController.js +75 -0
  51. package/dist/lib.esm/Message/PersonalMessageController.js +75 -0
  52. package/dist/lib.esm/Message/SwitchChainController.js +76 -0
  53. package/dist/lib.esm/Message/TypedMessageController.js +79 -0
  54. package/dist/lib.esm/Message/utils.js +105 -0
  55. package/dist/lib.esm/Network/NetworkController.js +199 -0
  56. package/dist/lib.esm/Network/cacheIdentifier.js +107 -0
  57. package/dist/lib.esm/Network/createEthereumMiddleware.js +289 -0
  58. package/dist/lib.esm/Network/createJsonRpcClient.js +60 -0
  59. package/dist/lib.esm/Nfts/NftHandler.js +178 -0
  60. package/dist/lib.esm/Nfts/NftsController.js +211 -0
  61. package/dist/lib.esm/Preferences/PreferencesController.js +474 -0
  62. package/dist/lib.esm/Tokens/TokenHandler.js +49 -0
  63. package/dist/lib.esm/Tokens/TokenRatesController.js +109 -0
  64. package/dist/lib.esm/Tokens/TokensController.js +257 -0
  65. package/dist/lib.esm/Transaction/NonceTracker.js +148 -0
  66. package/dist/lib.esm/Transaction/PendingTransactionTracker.js +220 -0
  67. package/dist/lib.esm/Transaction/TransactionController.js +513 -0
  68. package/dist/lib.esm/Transaction/TransactionGasUtil.js +79 -0
  69. package/dist/lib.esm/Transaction/TransactionStateHistoryHelper.js +38 -0
  70. package/dist/lib.esm/Transaction/TransactionStateManager.js +294 -0
  71. package/dist/lib.esm/Transaction/TransactionUtils.js +326 -0
  72. package/dist/lib.esm/index.js +33 -0
  73. package/dist/lib.esm/utils/abis.js +505 -0
  74. package/dist/lib.esm/utils/constants.js +323 -0
  75. package/dist/lib.esm/utils/contractAddresses.js +14 -0
  76. package/dist/lib.esm/utils/conversionUtils.js +218 -0
  77. package/dist/lib.esm/utils/helpers.js +227 -0
  78. package/dist/lib.esm/utils/lodashUtils.js +21 -0
  79. package/dist/types/Account/AccountTrackerController.d.ts +5 -5
  80. package/dist/types/Block/PollingBlockTracker.d.ts +1 -2
  81. package/dist/types/Currency/CurrencyController.d.ts +1 -1
  82. package/dist/types/Gas/GasFeeController.d.ts +3 -3
  83. package/dist/types/Gas/gasUtil.d.ts +1 -1
  84. package/dist/types/Keyring/KeyringController.d.ts +3 -5
  85. package/dist/types/Message/AbstractMessageController.d.ts +5 -6
  86. package/dist/types/Message/AddChainController.d.ts +4 -4
  87. package/dist/types/Message/MessageController.d.ts +4 -4
  88. package/dist/types/Message/PersonalMessageController.d.ts +4 -4
  89. package/dist/types/Message/SwitchChainController.d.ts +4 -4
  90. package/dist/types/Message/TypedMessageController.d.ts +6 -7
  91. package/dist/types/Message/utils.d.ts +2 -7
  92. package/dist/types/Network/NetworkController.d.ts +4 -4
  93. package/dist/types/Network/cacheIdentifier.d.ts +1 -1
  94. package/dist/types/Network/createEthereumMiddleware.d.ts +2 -18
  95. package/dist/types/Network/createJsonRpcClient.d.ts +2 -2
  96. package/dist/types/Nfts/NftsController.d.ts +2 -2
  97. package/dist/types/Preferences/PreferencesController.d.ts +4 -4
  98. package/dist/types/Tokens/TokensController.d.ts +3 -3
  99. package/dist/types/Transaction/NonceTracker.d.ts +5 -5
  100. package/dist/types/Transaction/PendingTransactionTracker.d.ts +5 -5
  101. package/dist/types/Transaction/TransactionController.d.ts +12 -12
  102. package/dist/types/Transaction/TransactionGasUtil.d.ts +4 -4
  103. package/dist/types/Transaction/TransactionStateManager.d.ts +3 -3
  104. package/dist/types/Transaction/TransactionUtils.d.ts +1 -1
  105. package/dist/types/index.d.ts +12 -14
  106. package/dist/types/utils/constants.d.ts +1 -5
  107. package/dist/types/utils/helpers.d.ts +4 -4
  108. package/dist/types/utils/interfaces.d.ts +43 -23
  109. package/package.json +10 -9
  110. package/dist/types/Message/DecryptMessageController.d.ts +0 -20
  111. package/dist/types/Message/EncryptionPublicKeyController.d.ts +0 -20
@@ -1,3 +1,10 @@
1
+ /*!
2
+ * The buffer module from node.js, for the browser.
3
+ *
4
+ * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
5
+ * @license MIT
6
+ */
7
+
1
8
  /*!
2
9
  * The buffer module from node.js, for the browser.
3
10
  *
@@ -17,8 +24,6 @@
17
24
  * MIT licensed
18
25
  */
19
26
 
20
- /*! https://mths.be/punycode v1.4.1 by @mathias */
21
-
22
27
  /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
23
28
 
24
29
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
@@ -0,0 +1,160 @@
1
+ 'use strict';
2
+
3
+ var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
4
+ var _defineProperty = require('@babel/runtime/helpers/defineProperty');
5
+ var baseControllers = require('@toruslabs/base-controllers');
6
+ var asyncMutex = require('async-mutex');
7
+ var ethers = require('ethers');
8
+ var log = require('loglevel');
9
+ var abis = require('../utils/abis.js');
10
+ var contractAddresses = require('../utils/contractAddresses.js');
11
+
12
+ const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
13
+
14
+ /**
15
+ * Tracks accounts based on blocks.
16
+ * If block tracker provides latest block, we query accounts from it.
17
+ * Preferences state changes also retrigger accounts update.
18
+ * Network state changes also retrigger accounts update.
19
+ */
20
+ class AccountTrackerController extends baseControllers.BaseController {
21
+ constructor({
22
+ config,
23
+ state,
24
+ provider,
25
+ blockTracker,
26
+ getIdentities,
27
+ onPreferencesStateChange,
28
+ getCurrentChainId
29
+ }) {
30
+ super({
31
+ config,
32
+ state
33
+ });
34
+ _defineProperty(this, "provider", void 0);
35
+ _defineProperty(this, "blockTracker", void 0);
36
+ _defineProperty(this, "mutex", new asyncMutex.Mutex());
37
+ _defineProperty(this, "ethersProvider", void 0);
38
+ _defineProperty(this, "getIdentities", void 0);
39
+ _defineProperty(this, "getCurrentChainId", void 0);
40
+ this.defaultState = {
41
+ accounts: {}
42
+ };
43
+ this.initialize();
44
+ this.provider = provider;
45
+ this.blockTracker = blockTracker;
46
+ this.ethersProvider = new ethers.BrowserProvider(this.provider, "any");
47
+ this.getIdentities = getIdentities;
48
+ this.getCurrentChainId = getCurrentChainId;
49
+ onPreferencesStateChange(() => {
50
+ const refreshNeeded = this.syncAccounts();
51
+ if (refreshNeeded) {
52
+ log.info("onPreferencesStateChange called");
53
+ this.refresh();
54
+ }
55
+ });
56
+ this.blockTrackerListener = this.blockTrackerListener.bind(this);
57
+ }
58
+ blockTrackerListener() {
59
+ this.refresh();
60
+ }
61
+ startPolling() {
62
+ this.stopPolling();
63
+ // Initiate block tracker internal tracking.
64
+ if (Object.keys(this.state.accounts).length > 0) {
65
+ // Adding this listener on block tracker triggers it to start polling.
66
+ this.blockTracker.on("latest", this.blockTrackerListener);
67
+ }
68
+ }
69
+ stopPolling() {
70
+ this.blockTracker.removeListener("latest", this.blockTrackerListener);
71
+ }
72
+ syncAccounts() {
73
+ const {
74
+ accounts
75
+ } = this.state;
76
+ const addresses = Object.keys(this.getIdentities());
77
+ const existing = Object.keys(accounts);
78
+ const newAddresses = addresses.filter(address => existing.indexOf(address) === -1);
79
+ const oldAddresses = existing.filter(address => addresses.indexOf(address) === -1);
80
+ let isUpdated = false;
81
+ newAddresses.forEach(address => {
82
+ isUpdated = true;
83
+ accounts[address] = {
84
+ balance: "0x0"
85
+ };
86
+ });
87
+ oldAddresses.forEach(address => {
88
+ isUpdated = true;
89
+ delete accounts[address];
90
+ });
91
+ this.update({
92
+ accounts: _objectSpread({}, accounts)
93
+ });
94
+ return isUpdated;
95
+ }
96
+ async refresh() {
97
+ const releaseLock = await this.mutex.acquire();
98
+ try {
99
+ this._updateAccounts();
100
+ } catch (error) {} finally {
101
+ releaseLock();
102
+ }
103
+ }
104
+ async _updateAccounts() {
105
+ const {
106
+ accounts
107
+ } = this.state;
108
+ const addresses = Object.keys(accounts);
109
+ const chainId = this.getCurrentChainId();
110
+ if (chainId === "loading") return;
111
+ if (addresses.length > 0) {
112
+ if (contractAddresses.SINGLE_CALL_BALANCES_ADDRESSES[chainId]) {
113
+ await this._updateAccountsViaBalanceChecker(addresses, contractAddresses.SINGLE_CALL_BALANCES_ADDRESSES[chainId]);
114
+ return;
115
+ }
116
+ log.info("falling back to ethQuery.getBalance");
117
+ await Promise.all(addresses.map(x => this._updateAccount(x)));
118
+ }
119
+ }
120
+ async _updateAccount(address) {
121
+ const balance = await this.provider.request({
122
+ method: "eth_getBalance",
123
+ params: [address, "latest"]
124
+ });
125
+ const {
126
+ accounts
127
+ } = this.state;
128
+ if (!accounts[address]) return;
129
+ accounts[address] = {
130
+ balance: ethers.toQuantity(balance)
131
+ };
132
+ this.update({
133
+ accounts
134
+ });
135
+ }
136
+ async _updateAccountsViaBalanceChecker(addresses, deployedContractAddress) {
137
+ const ethContract = new ethers.Contract(deployedContractAddress, abis.singleBalanceCheckerAbi, this.ethersProvider);
138
+ try {
139
+ const result = await ethContract.balances(addresses, [ZERO_ADDRESS]);
140
+ const {
141
+ accounts
142
+ } = this.state;
143
+ addresses.forEach((address, index) => {
144
+ const balance = ethers.toQuantity(result[index]);
145
+ if (!accounts[address]) return;
146
+ accounts[address] = {
147
+ balance
148
+ };
149
+ });
150
+ return this.update({
151
+ accounts
152
+ });
153
+ } catch (error) {
154
+ log.warn("Torus - Account Tracker single call balance fetch failed", error);
155
+ return Promise.all(addresses.map(x => this._updateAccount(x)));
156
+ }
157
+ }
158
+ }
159
+
160
+ exports.AccountTrackerController = AccountTrackerController;
@@ -0,0 +1,85 @@
1
+ 'use strict';
2
+
3
+ var baseControllers = require('@toruslabs/base-controllers');
4
+ var log = require('loglevel');
5
+ var helpers = require('../utils/helpers.js');
6
+
7
+ const DEFAULT_POLLING_INTERVAL = 20;
8
+ const DEFAULT_RETRY_TIMEOUT = 2;
9
+ const SEC = 1000;
10
+ class PollingBlockTracker extends baseControllers.BaseBlockTracker {
11
+ constructor({
12
+ config,
13
+ state = {}
14
+ }) {
15
+ if (!config.provider) {
16
+ throw new Error("PollingBlockTracker - no provider specified.");
17
+ }
18
+ super({
19
+ config,
20
+ state
21
+ });
22
+ const pollingInterval = config.pollingInterval || DEFAULT_POLLING_INTERVAL;
23
+ const retryTimeout = config.retryTimeout || DEFAULT_RETRY_TIMEOUT;
24
+
25
+ // merge default + provided config.
26
+ this.defaultConfig = {
27
+ provider: config.provider,
28
+ pollingInterval: pollingInterval * SEC,
29
+ retryTimeout: retryTimeout * SEC,
30
+ setSkipCacheFlag: config.setSkipCacheFlag || false
31
+ };
32
+ this.initialize();
33
+ }
34
+ async checkForLatestBlock() {
35
+ await this._updateLatestBlock();
36
+ return this.getLatestBlock();
37
+ }
38
+
39
+ // overrides the BaseBlockTracker._start method.
40
+ _start() {
41
+ this._synchronize().catch(err => this.emit("error", err));
42
+ }
43
+ async _synchronize() {
44
+ while (this.state._isRunning) {
45
+ if (helpers.idleTimeTracker.checkIfIdle()) return;
46
+ try {
47
+ await this._updateLatestBlock();
48
+ await baseControllers.timeout(this.config.pollingInterval);
49
+ } catch (err) {
50
+ const newErr = new Error(`PollingBlockTracker - encountered an error while attempting to update latest block:\n${err.stack}`);
51
+ try {
52
+ this.emit("error", newErr);
53
+ } catch (emitErr) {
54
+ log.error(newErr);
55
+ }
56
+ await baseControllers.timeout(this.config.retryTimeout);
57
+ }
58
+ }
59
+ }
60
+ async _updateLatestBlock() {
61
+ // fetch + set latest block
62
+ const latestBlock = await this._fetchLatestBlock();
63
+ this._newPotentialLatest(latestBlock);
64
+ }
65
+ async _fetchLatestBlock() {
66
+ try {
67
+ const block = await this.config.provider.request({
68
+ method: "eth_getBlockByNumber",
69
+ params: ["latest", false]
70
+ });
71
+ return {
72
+ blockHash: block.hash,
73
+ idempotencyKey: block.number,
74
+ timestamp: block.timestamp,
75
+ baseFeePerGas: block.baseFeePerGas,
76
+ gasLimit: block.gasLimit
77
+ };
78
+ } catch (error) {
79
+ log.error("Polling Block Tracker: ", error);
80
+ throw new Error(`PollingBlockTracker - encountered error fetching block:\n${error.message}`);
81
+ }
82
+ }
83
+ }
84
+
85
+ exports.PollingBlockTracker = PollingBlockTracker;
@@ -0,0 +1,111 @@
1
+ 'use strict';
2
+
3
+ var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
4
+ var _defineProperty = require('@babel/runtime/helpers/defineProperty');
5
+ var baseControllers = require('@toruslabs/base-controllers');
6
+ var httpHelpers = require('@toruslabs/http-helpers');
7
+ var log = require('loglevel');
8
+ var helpers = require('../utils/helpers.js');
9
+
10
+ class CurrencyController extends baseControllers.BaseCurrencyController {
11
+ constructor({
12
+ config,
13
+ state,
14
+ onNetworkChanged
15
+ }) {
16
+ super({
17
+ config,
18
+ state
19
+ });
20
+ _defineProperty(this, "conversionInterval", void 0);
21
+ this.defaultState = _objectSpread(_objectSpread({}, this.defaultState), {}, {
22
+ commonDenomination: "USD",
23
+ commonDenominatorPrice: 0
24
+ });
25
+ this.initialize();
26
+ onNetworkChanged(networkState => {
27
+ // to be called as (listener) => this.networkController.on('networkDidChange', listener);
28
+ if (networkState.providerConfig.ticker.toUpperCase() !== this.state.nativeCurrency.toUpperCase()) {
29
+ this.setNativeCurrency(networkState.providerConfig.ticker);
30
+ this.updateConversionRate();
31
+ }
32
+ });
33
+ }
34
+ setCommonDenomination(commonDenomination) {
35
+ this.update({
36
+ commonDenomination
37
+ });
38
+ }
39
+ getCommonDenomination() {
40
+ return this.state.commonDenomination;
41
+ }
42
+ setCommonDenominatorPrice(commonDenominatorPrice) {
43
+ this.update({
44
+ commonDenominatorPrice
45
+ });
46
+ }
47
+ getCommonDenominatorPrice() {
48
+ return this.state.commonDenominatorPrice;
49
+ }
50
+
51
+ /**
52
+ * Creates a new poll, using setInterval, to periodically call updateConversionRate. The id of the interval is
53
+ * stored at the controller's conversionInterval property. If it is called and such an id already exists, the
54
+ * previous interval is clear and a new one is created.
55
+ */
56
+ scheduleConversionInterval() {
57
+ if (this.conversionInterval) {
58
+ window.clearInterval(this.conversionInterval);
59
+ }
60
+ this.conversionInterval = window.setInterval(() => {
61
+ if (!helpers.idleTimeTracker.checkIfIdle()) {
62
+ this.updateConversionRate();
63
+ }
64
+ }, this.config.pollInterval);
65
+ }
66
+
67
+ /**
68
+ * Updates the conversionRate and conversionDate properties associated with the currentCurrency. Updated info is
69
+ * fetched from an external API
70
+ */
71
+ async updateConversionRate() {
72
+ const currentCurrency = this.getCurrentCurrency();
73
+ const nativeCurrency = this.getNativeCurrency();
74
+ const commonDenomination = this.getCommonDenomination();
75
+ const conversionRate = await this.retrieveConversionRate(nativeCurrency, currentCurrency, commonDenomination);
76
+ const currentCurrencyRate = Number.parseFloat(conversionRate[currentCurrency.toUpperCase()]);
77
+ const commonDenominationRate = Number.parseFloat(conversionRate[commonDenomination.toUpperCase()]);
78
+ // set conversion rate
79
+ if (currentCurrencyRate || commonDenominationRate) {
80
+ // ETC
81
+ this.setConversionRate(currentCurrencyRate);
82
+ this.setConversionDate(Math.floor(Date.now() / 1000).toString());
83
+ if (currentCurrency.toUpperCase() === commonDenomination.toUpperCase()) {
84
+ this.setCommonDenominatorPrice(currentCurrencyRate);
85
+ } else {
86
+ this.setCommonDenominatorPrice(commonDenominationRate);
87
+ }
88
+ } else {
89
+ this.setConversionRate(0);
90
+ this.setConversionDate("N/A");
91
+ }
92
+ }
93
+ async retrieveConversionRate(fromCurrency, toCurrency, commonDenomination) {
94
+ try {
95
+ let apiUrl = `${this.config.api}/currency?fsym=${fromCurrency.toUpperCase()}&tsyms=${toCurrency.toUpperCase()}`;
96
+ if (commonDenomination && commonDenomination.toUpperCase() !== toCurrency.toUpperCase()) {
97
+ apiUrl += `,${commonDenomination.toUpperCase()}`;
98
+ }
99
+ const parsedResponse = await httpHelpers.get(apiUrl);
100
+ return parsedResponse;
101
+ } catch (error) {
102
+ log.error(error, `CurrencyController - updateCommonDenominatorPrice: Failed to query rate for currency: ${fromCurrency}/ ${toCurrency}`);
103
+ }
104
+ return {
105
+ [toCurrency.toUpperCase()]: "0",
106
+ [commonDenomination.toUpperCase()]: "0"
107
+ };
108
+ }
109
+ }
110
+
111
+ exports.CurrencyController = CurrencyController;
@@ -0,0 +1,214 @@
1
+ 'use strict';
2
+
3
+ var _defineProperty = require('@babel/runtime/helpers/defineProperty');
4
+ var util = require('@ethereumjs/util');
5
+ var baseControllers = require('@toruslabs/base-controllers');
6
+ var log = require('loglevel');
7
+ var constants = require('../utils/constants.js');
8
+ var helpers = require('../utils/helpers.js');
9
+ var gasUtil = require('./gasUtil.js');
10
+
11
+ const GAS_FEE_API = "https://mock-gas-server.herokuapp.com/";
12
+ const LEGACY_GAS_PRICES_API_URL = "https://api.metaswap.codefi.network/gasPrices";
13
+ /**
14
+ * Returns gas prices in dec gwei
15
+ */
16
+ class GasFeeController extends baseControllers.BaseController {
17
+ constructor({
18
+ config,
19
+ state,
20
+ getNetworkIdentifier,
21
+ getProvider,
22
+ fetchGasEstimates = gasUtil.fetchGasEstimates,
23
+ fetchEthGasPriceEstimate = gasUtil.fetchEthGasPriceEstimate,
24
+ fetchLegacyGasPriceEstimates = gasUtil.fetchLegacyGasPriceEstimates,
25
+ fetchGasEstimatesViaEthFeeHistory = gasUtil.fetchGasEstimatesViaEthFeeHistory,
26
+ getCurrentNetworkLegacyGasAPICompatibility,
27
+ getCurrentNetworkEIP1559Compatibility,
28
+ getCurrentAccountEIP1559Compatibility,
29
+ onNetworkStateChange
30
+ }) {
31
+ super({
32
+ config,
33
+ state
34
+ });
35
+ _defineProperty(this, "name", "GasFeeController");
36
+ // https://0x.org/docs/introduction/0x-cheat-sheet#swap-api-endpoints
37
+ _defineProperty(this, "API_SUPPORTED_CHAINIDS", new Set(["0x1", "0x5", "0xa4b1", "0xa86a", "0x2105", "0x38", "0xfa", "0xa", "0x89"]));
38
+ _defineProperty(this, "intervalId", void 0);
39
+ _defineProperty(this, "provider", void 0);
40
+ _defineProperty(this, "currentChainId", void 0);
41
+ _defineProperty(this, "getNetworkIdentifier", void 0);
42
+ _defineProperty(this, "getProvider", void 0);
43
+ _defineProperty(this, "fetchGasEstimates", void 0);
44
+ _defineProperty(this, "fetchGasEstimatesViaEthFeeHistory", void 0);
45
+ _defineProperty(this, "fetchEthGasPriceEstimate", void 0);
46
+ _defineProperty(this, "fetchLegacyGasPriceEstimates", void 0);
47
+ _defineProperty(this, "getCurrentNetworkEIP1559Compatibility", void 0);
48
+ _defineProperty(this, "getCurrentAccountEIP1559Compatibility", void 0);
49
+ _defineProperty(this, "getCurrentNetworkLegacyGasAPICompatibility", void 0);
50
+ this.getNetworkIdentifier = getNetworkIdentifier;
51
+ this.getProvider = getProvider;
52
+ this.fetchGasEstimates = fetchGasEstimates;
53
+ this.fetchEthGasPriceEstimate = fetchEthGasPriceEstimate;
54
+ this.fetchLegacyGasPriceEstimates = fetchLegacyGasPriceEstimates;
55
+ this.getCurrentNetworkEIP1559Compatibility = getCurrentNetworkEIP1559Compatibility;
56
+ this.getCurrentNetworkLegacyGasAPICompatibility = getCurrentNetworkLegacyGasAPICompatibility;
57
+ this.getCurrentAccountEIP1559Compatibility = getCurrentAccountEIP1559Compatibility;
58
+ this.fetchGasEstimatesViaEthFeeHistory = fetchGasEstimatesViaEthFeeHistory;
59
+ this.defaultConfig = {
60
+ interval: 30000,
61
+ legacyAPIEndpoint: LEGACY_GAS_PRICES_API_URL,
62
+ EIP1559APIEndpoint: GAS_FEE_API
63
+ };
64
+ this.defaultState = {
65
+ gasFeeEstimates: {},
66
+ estimatedGasFeeTimeBounds: {},
67
+ gasEstimateType: constants.GAS_ESTIMATE_TYPES.NONE
68
+ };
69
+ // Initialize.
70
+ this.currentChainId = this.getNetworkIdentifier();
71
+ this.provider = this.getProvider();
72
+ this.initialize();
73
+ onNetworkStateChange(() => {
74
+ this.onNetworkStateChange();
75
+ });
76
+ }
77
+ async onNetworkStateChange() {
78
+ this.provider = this.getProvider();
79
+ const newChainId = this.getNetworkIdentifier();
80
+ if (this.currentChainId !== newChainId) {
81
+ this.currentChainId = newChainId;
82
+ await this.fetchGasFeeEstimates();
83
+ }
84
+ }
85
+ async resetPolling() {
86
+ this.stopPolling();
87
+ await this.getGasFeeEstimatesAndStartPolling();
88
+ }
89
+ async fetchGasFeeEstimates() {
90
+ return this._fetchGasFeeEstimateData();
91
+ }
92
+ async getGasFeeEstimatesAndStartPolling() {
93
+ await this._fetchGasFeeEstimateData();
94
+ this._startPolling();
95
+ }
96
+ disconnectPoller() {
97
+ this.stopPolling();
98
+ }
99
+
100
+ /**
101
+ * Prepare to discard this controller.
102
+ *
103
+ * This stops any active polling.
104
+ */
105
+ destroy() {
106
+ this.stopPolling();
107
+ }
108
+ stopPolling() {
109
+ if (this.intervalId) {
110
+ clearInterval(this.intervalId);
111
+ }
112
+ this.resetState();
113
+ }
114
+
115
+ /**
116
+ * Gets and sets gasFeeEstimates in state
117
+ *
118
+ * @returns GasFeeEstimates
119
+ */
120
+ async _fetchGasFeeEstimateData() {
121
+ let isEIP1559Compatible;
122
+ const isLegacyGasAPICompatible = this.getCurrentNetworkLegacyGasAPICompatibility();
123
+ const chainId = this.getNetworkIdentifier();
124
+ if (chainId === "loading") return;
125
+ let chainIdInt;
126
+ if (typeof chainId === "string" && util.isHexString(util.addHexPrefix(chainId))) {
127
+ chainIdInt = Number.parseInt(chainId, 16);
128
+ }
129
+ try {
130
+ isEIP1559Compatible = await this.getEIP1559Compatibility();
131
+ log.info("eip1559 compatible", isEIP1559Compatible);
132
+ } catch (error) {
133
+ log.warn(error);
134
+ isEIP1559Compatible = false;
135
+ }
136
+ let newState = baseControllers.cloneDeep(this.defaultState);
137
+ try {
138
+ if (isEIP1559Compatible) {
139
+ let estimates;
140
+ try {
141
+ if (this.API_SUPPORTED_CHAINIDS.has(chainId)) {
142
+ estimates = await this.fetchGasEstimates(this.config.EIP1559APIEndpoint.replace("<chain_id>", `${chainIdInt}`));
143
+ } else {
144
+ throw new Error("ChainId not supported by api");
145
+ }
146
+ } catch (error) {
147
+ estimates = await this.fetchGasEstimatesViaEthFeeHistory(this.provider);
148
+ }
149
+ const {
150
+ suggestedMaxPriorityFeePerGas,
151
+ suggestedMaxFeePerGas
152
+ } = estimates.medium;
153
+ const estimatedGasFeeTimeBounds = this.getTimeEstimate(suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas);
154
+ newState = {
155
+ gasFeeEstimates: estimates,
156
+ estimatedGasFeeTimeBounds,
157
+ gasEstimateType: constants.GAS_ESTIMATE_TYPES.FEE_MARKET
158
+ };
159
+ } else if (isLegacyGasAPICompatible) {
160
+ const estimates = await this.fetchLegacyGasPriceEstimates(this.config.legacyAPIEndpoint.replace("<chain_id>", `${chainIdInt}`));
161
+ newState = {
162
+ gasFeeEstimates: estimates,
163
+ estimatedGasFeeTimeBounds: {},
164
+ gasEstimateType: constants.GAS_ESTIMATE_TYPES.LEGACY
165
+ };
166
+ } else {
167
+ throw new Error("Main gas fee/price estimation failed. Use fallback");
168
+ }
169
+ } catch {
170
+ try {
171
+ const estimates = await this.fetchEthGasPriceEstimate(this.provider);
172
+ newState = {
173
+ gasFeeEstimates: estimates,
174
+ estimatedGasFeeTimeBounds: {},
175
+ gasEstimateType: constants.GAS_ESTIMATE_TYPES.ETH_GASPRICE
176
+ };
177
+ } catch (error) {
178
+ throw new Error(`Gas fee/price estimation failed. Message: ${error.message}`);
179
+ }
180
+ }
181
+ this.update(newState);
182
+ return newState;
183
+ }
184
+ async _startPolling() {
185
+ this._poll();
186
+ }
187
+ async _poll() {
188
+ if (this.intervalId) {
189
+ window.clearInterval(this.intervalId);
190
+ }
191
+ this.intervalId = window.setInterval(async () => {
192
+ if (!helpers.idleTimeTracker.checkIfIdle()) {
193
+ await this._fetchGasFeeEstimateData();
194
+ }
195
+ }, this.config.interval);
196
+ }
197
+ resetState() {
198
+ this.update(baseControllers.cloneDeep(this.defaultState));
199
+ }
200
+ async getEIP1559Compatibility() {
201
+ var _this$getCurrentAccou, _this$getCurrentAccou2;
202
+ const currentNetworkIsEIP1559Compatible = await this.getCurrentNetworkEIP1559Compatibility();
203
+ const currentAccountIsEIP1559Compatible = (_this$getCurrentAccou = (_this$getCurrentAccou2 = this.getCurrentAccountEIP1559Compatibility) === null || _this$getCurrentAccou2 === void 0 ? void 0 : _this$getCurrentAccou2.call(this)) !== null && _this$getCurrentAccou !== void 0 ? _this$getCurrentAccou : true;
204
+ return currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible;
205
+ }
206
+ getTimeEstimate(maxPriorityFeePerGas, maxFeePerGas) {
207
+ if (!this.state.gasFeeEstimates || this.state.gasEstimateType !== constants.GAS_ESTIMATE_TYPES.FEE_MARKET) {
208
+ return {};
209
+ }
210
+ return gasUtil.calculateTimeEstimate(maxPriorityFeePerGas, maxFeePerGas, this.state.gasFeeEstimates);
211
+ }
212
+ }
213
+
214
+ exports.GasFeeController = GasFeeController;