@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
@@ -0,0 +1,213 @@
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 deepmerge = require('deepmerge');
7
+ var ethers = require('ethers');
8
+ var log = require('loglevel');
9
+ var constants = require('../utils/constants.js');
10
+ var helpers = require('../utils/helpers.js');
11
+ var NftHandler = require('./NftHandler.js');
12
+
13
+ const DEFAULT_INTERVAL = 180 * 1000;
14
+ class NftsController extends baseControllers.BaseController {
15
+ constructor({
16
+ config,
17
+ state,
18
+ provider,
19
+ getCustomNfts,
20
+ getSimpleHashNfts,
21
+ onPreferencesStateChange,
22
+ onNetworkStateChange
23
+ }) {
24
+ super({
25
+ config,
26
+ state
27
+ });
28
+ _defineProperty(this, "name", "NftsController");
29
+ _defineProperty(this, "provider", void 0);
30
+ _defineProperty(this, "ethersProvider", void 0);
31
+ _defineProperty(this, "_timer", void 0);
32
+ _defineProperty(this, "getCustomNfts", void 0);
33
+ _defineProperty(this, "getSimpleHashNfts", void 0);
34
+ this.provider = provider;
35
+ this.ethersProvider = new ethers.BrowserProvider(this.provider, "any");
36
+ this.getCustomNfts = getCustomNfts;
37
+ this.getSimpleHashNfts = getSimpleHashNfts;
38
+ this.defaultConfig = {
39
+ interval: DEFAULT_INTERVAL,
40
+ selectedAddress: "",
41
+ chainId: ""
42
+ };
43
+ this.defaultState = {
44
+ nfts: {}
45
+ };
46
+ this.initialize();
47
+ onPreferencesStateChange(preferencesState => {
48
+ if (preferencesState.selectedAddress !== this.config.selectedAddress) {
49
+ this.configure({
50
+ selectedAddress: preferencesState.selectedAddress
51
+ });
52
+ this.restartNftDetection();
53
+ }
54
+ });
55
+ onNetworkStateChange(networkState => {
56
+ const {
57
+ chainId
58
+ } = networkState.providerConfig;
59
+ if (chainId !== this.config.chainId) {
60
+ this.configure({
61
+ chainId
62
+ });
63
+ this.restartNftDetection();
64
+ }
65
+ });
66
+ }
67
+ get userSelectedAddress() {
68
+ return this.config.selectedAddress;
69
+ }
70
+ get userNfts() {
71
+ var _this$state$nfts$this;
72
+ if (!this.userSelectedAddress) return [];
73
+ return (_this$state$nfts$this = this.state.nfts[this.userSelectedAddress]) !== null && _this$state$nfts$this !== void 0 ? _this$state$nfts$this : [];
74
+ }
75
+ get interval() {
76
+ return this.config.interval;
77
+ }
78
+ set interval(interval) {
79
+ if (this._timer) window.clearInterval(this._timer);
80
+ if (!interval) {
81
+ return;
82
+ }
83
+ this._timer = window.setInterval(() => {
84
+ if (!helpers.idleTimeTracker.checkIfIdle()) {
85
+ this.detectNewNfts();
86
+ this.refreshNftBalances();
87
+ }
88
+ }, interval);
89
+ }
90
+ startNftDetection(selectedAddress) {
91
+ this.configure({
92
+ selectedAddress
93
+ });
94
+ this.restartNftDetection();
95
+ }
96
+
97
+ /**
98
+ * Restart nft detection polling period and call detectNewNfts
99
+ * in case of address change or user session initialization.
100
+ *
101
+ */
102
+ restartNftDetection() {
103
+ if (!this.userSelectedAddress) {
104
+ return;
105
+ }
106
+ this.detectNewNfts();
107
+ this.refreshNftBalances();
108
+ this.config.interval = DEFAULT_INTERVAL;
109
+ }
110
+ detectNewNfts() {
111
+ const userAddress = this.userSelectedAddress;
112
+ if (!userAddress) return;
113
+ const currentChainId = this.config.chainId;
114
+ const nftsToDetect = []; // object[]
115
+ if (!currentChainId) {
116
+ this.update({
117
+ nfts: {
118
+ [userAddress]: [...nftsToDetect]
119
+ }
120
+ });
121
+ return;
122
+ }
123
+ if (this.getCustomNfts) {
124
+ const customNfts = this.getCustomNfts(userAddress);
125
+ const reducedNfts = customNfts.reduce((acc, x) => {
126
+ // first aggregate by contract address
127
+ if (x.network === currentChainId) {
128
+ const newAsset = {
129
+ description: "",
130
+ image: "",
131
+ name: "",
132
+ tokenBalance: "",
133
+ tokenId: x.nft_id,
134
+ customNftId: x.id.toString()
135
+ };
136
+ if (acc[x.nft_address]) {
137
+ acc[x.nft_address].assets.push(newAsset);
138
+ } else {
139
+ const objToPush = {
140
+ assets: [newAsset],
141
+ chainId: x.network,
142
+ contractAddress: x.nft_address,
143
+ contractName: "",
144
+ contractSymbol: "",
145
+ contractImage: "",
146
+ nftStandard: x.nft_contract_standard,
147
+ contractDescription: ""
148
+ };
149
+ acc[x.nft_address] = objToPush;
150
+ }
151
+ }
152
+ return acc;
153
+ }, {});
154
+ nftsToDetect.push(...Object.values(reducedNfts));
155
+ }
156
+ this.update({
157
+ nfts: {
158
+ [userAddress]: [...nftsToDetect]
159
+ }
160
+ });
161
+ }
162
+ async refreshNftBalances() {
163
+ const userAddress = this.userSelectedAddress;
164
+ if (userAddress === "") return;
165
+ const oldNfts = [...this.userNfts];
166
+ const nonZeroNfts = [];
167
+ try {
168
+ const currentChainId = this.config.chainId;
169
+ if (constants.SIMPLEHASH_SUPPORTED_CHAINS.includes(currentChainId)) {
170
+ const simpleHashBalances = await this.getSimpleHashNfts(userAddress, currentChainId);
171
+ nonZeroNfts.push(...simpleHashBalances);
172
+ this.update({
173
+ nfts: {
174
+ [userAddress]: nonZeroNfts
175
+ }
176
+ });
177
+ }
178
+ if (oldNfts.length > 0) {
179
+ this.getNftBalancesUsingHandler(oldNfts);
180
+ }
181
+ } catch (error) {
182
+ log.error(error, "unable to fetch nft balances");
183
+ }
184
+ }
185
+ async getNftBalancesUsingHandler(customNfts) {
186
+ if (!this.userSelectedAddress) return;
187
+ const userAddress = this.userSelectedAddress;
188
+ const currentNetworkNfts = customNfts;
189
+ const promiseSettledResult = await Promise.allSettled(currentNetworkNfts.map(async x => {
190
+ try {
191
+ const tokenInstance = new NftHandler.NftHandler(_objectSpread(_objectSpread({}, x), {}, {
192
+ provider: this.ethersProvider
193
+ }));
194
+ const contractData = await tokenInstance.getContractMetadata();
195
+ const assetData = await Promise.allSettled(x.assets.map(y => tokenInstance.getNftMetadata(userAddress, y)));
196
+ return _objectSpread(_objectSpread({}, contractData), {}, {
197
+ assets: assetData.filter(z => z.status === "fulfilled").map(z => z.value)
198
+ });
199
+ } catch (error) {
200
+ log.warn("Invalid contract address while fetching", error);
201
+ return undefined;
202
+ }
203
+ }));
204
+ const nonZeroTokens = promiseSettledResult.filter(x => x.status === "fulfilled").map(x => x.value);
205
+ this.update({
206
+ nfts: {
207
+ [userAddress]: deepmerge(this.userNfts, nonZeroTokens)
208
+ }
209
+ });
210
+ }
211
+ }
212
+
213
+ exports.NftsController = NftsController;
@@ -0,0 +1,476 @@
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 asyncMutex = require('async-mutex');
7
+ var log = require('loglevel');
8
+ var constants = require('../utils/constants.js');
9
+ var helpers = require('../utils/helpers.js');
10
+
11
+ class PreferencesController extends baseControllers.BasePreferencesController {
12
+ constructor({
13
+ config,
14
+ state,
15
+ provider,
16
+ signAuthMessage,
17
+ getProviderConfig,
18
+ setProviderConfig,
19
+ validateSignMessage
20
+ }) {
21
+ super({
22
+ config,
23
+ state,
24
+ defaultPreferences: {
25
+ formattedPastTransactions: [],
26
+ fetchedPastTx: [],
27
+ paymentTx: [],
28
+ etherscanTransactions: []
29
+ },
30
+ signAuthMessage,
31
+ validateSignMessage
32
+ });
33
+ _defineProperty(this, "_handle", void 0);
34
+ _defineProperty(this, "_mutex", new asyncMutex.Mutex());
35
+ _defineProperty(this, "getProviderConfig", void 0);
36
+ _defineProperty(this, "setProviderConfig", void 0);
37
+ _defineProperty(this, "provider", void 0);
38
+ this.provider = provider;
39
+ this.getProviderConfig = getProviderConfig;
40
+ this.setProviderConfig = setProviderConfig;
41
+ }
42
+ async poll(interval) {
43
+ var _this$getAddressState;
44
+ const releaseLock = await this._mutex.acquire();
45
+ if (interval) this.configure({
46
+ pollInterval: interval
47
+ });
48
+ if (this._handle) window.clearTimeout(this._handle);
49
+ // call here
50
+ const storeSelectedAddress = this.state.selectedAddress;
51
+ if (!storeSelectedAddress) return;
52
+ if (!((_this$getAddressState = this.getAddressState(storeSelectedAddress)) !== null && _this$getAddressState !== void 0 && _this$getAddressState.jwtToken)) return;
53
+ // This should never throw
54
+ await this.sync(storeSelectedAddress);
55
+ releaseLock();
56
+ this._handle = window.setTimeout(() => {
57
+ this.poll(this.config.pollInterval);
58
+ }, this.config.pollInterval);
59
+ }
60
+ async initPreferences(params) {
61
+ const {
62
+ address,
63
+ jwtToken,
64
+ calledFromEmbed,
65
+ userInfo,
66
+ rehydrate,
67
+ locale = "en",
68
+ type,
69
+ signatures,
70
+ web3AuthClientId,
71
+ web3AuthNetwork,
72
+ loginMode,
73
+ sessionPubKey
74
+ } = params;
75
+ await super.init({
76
+ address,
77
+ userInfo,
78
+ idToken: jwtToken,
79
+ type,
80
+ metadata: {
81
+ email: userInfo.email,
82
+ signatures,
83
+ network: web3AuthNetwork
84
+ }
85
+ });
86
+ const {
87
+ aggregateVerifier,
88
+ verifier,
89
+ verifierId
90
+ } = userInfo || {};
91
+ const userExists = await this.sync(address);
92
+ if (!userExists) {
93
+ const accountState = this.getAddressState(address);
94
+ await this.createUser({
95
+ selectedCurrency: accountState.selectedCurrency,
96
+ theme: accountState.theme,
97
+ verifier: aggregateVerifier || verifier,
98
+ verifierId,
99
+ locale,
100
+ address,
101
+ type,
102
+ web3AuthNetwork
103
+ });
104
+ }
105
+ this.storeUserLogin({
106
+ verifier: aggregateVerifier || verifier,
107
+ verifierId,
108
+ options: {
109
+ calledFromEmbed,
110
+ rehydrate
111
+ },
112
+ address,
113
+ web3AuthClientId,
114
+ web3AuthNetwork,
115
+ sessionPubKey,
116
+ loginMode
117
+ });
118
+ }
119
+ getSelectedAddress() {
120
+ return this.state.selectedAddress;
121
+ }
122
+ async sync(address) {
123
+ try {
124
+ const user = await this.getUser(address);
125
+ if (user) {
126
+ const {
127
+ default_currency: defaultCurrency,
128
+ contacts,
129
+ theme,
130
+ locale,
131
+ public_address: userPublicAddress,
132
+ default_public_address: defaultPublicAddress,
133
+ customNetworks,
134
+ customTokens,
135
+ customNfts,
136
+ account_type: accountType
137
+ } = user || {};
138
+
139
+ // update latest data in state.
140
+ this.updateState({
141
+ contacts,
142
+ theme,
143
+ selectedCurrency: defaultCurrency,
144
+ locale,
145
+ defaultPublicAddress: defaultPublicAddress || userPublicAddress,
146
+ customTokens,
147
+ customNfts,
148
+ customNetworks,
149
+ accountType: accountType
150
+ }, address);
151
+ return true;
152
+ }
153
+ return false;
154
+ } catch (error) {
155
+ if (baseControllers.isUnauthorizedError(error)) {
156
+ throw error;
157
+ }
158
+ log.error(error);
159
+ return false;
160
+ } finally {
161
+ this.getWalletOrders(address).then(walletTx => {
162
+ // eslint-disable-next-line promise/always-return
163
+ if (walletTx && walletTx.length > 0) {
164
+ this.updateState({
165
+ fetchedPastTx: [...walletTx]
166
+ }, address);
167
+ this.calculatePastTx(walletTx, address);
168
+ }
169
+ }).catch(error => log.error(error));
170
+ }
171
+ }
172
+ async patchNewTx(tx, address) {
173
+ var _this$getAddressState2;
174
+ const formattedTx = helpers.formatPastTx({
175
+ transaction: tx,
176
+ blockExplorerUrl: this.getBlockExplorerUrl()
177
+ });
178
+ const storePastTx = ((_this$getAddressState2 = this.getAddressState(address)) === null || _this$getAddressState2 === void 0 ? void 0 : _this$getAddressState2.formattedPastTransactions) || [];
179
+ const duplicateIndex = storePastTx.findIndex(x => x.transaction_hash === tx.transaction_hash && x.chainId === tx.chain_id);
180
+ if (tx.status === baseControllers.TransactionStatus.submitted || tx.status === baseControllers.TransactionStatus.confirmed) {
181
+ if (duplicateIndex === -1) {
182
+ var _tx$to;
183
+ // No duplicate found
184
+
185
+ const finalTx = this.cancelTxCalculate([...storePastTx, formattedTx]);
186
+ tx.is_cancel = formattedTx.is_cancel;
187
+ tx.to = (_tx$to = tx.to) === null || _tx$to === void 0 ? void 0 : _tx$to.toLowerCase();
188
+ tx.from = tx.from.toLowerCase();
189
+ this.updateState({
190
+ formattedPastTransactions: finalTx
191
+ }, address);
192
+ this.postPastTx(tx, address);
193
+ } else {
194
+ // avoid overriding is_cancel
195
+ formattedTx.is_cancel = storePastTx[duplicateIndex].is_cancel;
196
+ storePastTx[duplicateIndex] = formattedTx;
197
+ this.updateState({
198
+ formattedPastTransactions: this.cancelTxCalculate([...storePastTx])
199
+ }, address);
200
+ }
201
+ }
202
+ }
203
+ recalculatePastTx(address) {
204
+ // This triggers store update which calculates past Tx status for that network
205
+ const selectedAddress = address || this.state.selectedAddress;
206
+ const state = this.getAddressState(selectedAddress);
207
+ if (!(state !== null && state !== void 0 && state.fetchedPastTx)) return;
208
+ this.calculatePastTx(state.fetchedPastTx, selectedAddress);
209
+ }
210
+ async refetchEtherscanTx(address) {
211
+ var _this$getAddressState3;
212
+ const selectedAddress = address || this.state.selectedAddress;
213
+ if (!selectedAddress) return [];
214
+ const lowerCaseSelectedAddress = selectedAddress === null || selectedAddress === void 0 ? void 0 : selectedAddress.toLowerCase();
215
+ if ((_this$getAddressState3 = this.getAddressState(selectedAddress)) !== null && _this$getAddressState3 !== void 0 && _this$getAddressState3.jwtToken) {
216
+ const {
217
+ chainId
218
+ } = this.getProviderConfig();
219
+ if (constants.ETHERSCAN_SUPPORTED_CHAINS.includes(chainId)) {
220
+ const etherscanTxn = await this.fetchEtherscanTx({
221
+ selectedAddress,
222
+ chainId: this.getProviderConfig().chainId
223
+ });
224
+ const finalEthScanTxn = await helpers.addEtherscanTransactions({
225
+ txn: etherscanTxn,
226
+ lowerCaseSelectedAddress,
227
+ provider: this.provider,
228
+ chainId,
229
+ blockExplorerUrl: this.getBlockExplorerUrl()
230
+ });
231
+ log.info("Formatted Etherscan Response", finalEthScanTxn);
232
+ this.updateState({
233
+ etherscanTransactions: finalEthScanTxn
234
+ });
235
+ return etherscanTxn;
236
+ }
237
+ }
238
+ }
239
+ async fetchEtherscanTx(parameters) {
240
+ try {
241
+ const response = await this.wsApiClient.authGet(`etherscan?chainId=${parameters.chainId}`, this.authCredentials(parameters.selectedAddress));
242
+ log.info("Etherscan Response API", response);
243
+ return response.success ? response.data : [];
244
+ } catch (error) {
245
+ log.error("unable to fetch etherscan tx", error);
246
+ return [];
247
+ }
248
+ }
249
+ async getEtherScanTokens(address, chainId) {
250
+ const selectedAddress = address;
251
+ const result = await this.wsApiClient.authGet(`tokens?chainId=${chainId}&address=${selectedAddress}`, this.authCredentials());
252
+ return result.data;
253
+ }
254
+ async getSimpleHashNfts(address, chainId) {
255
+ const selectedAddress = address;
256
+ const result = await this.wsApiClient.authGet(`nfts?chainId=${chainId}&address=${selectedAddress}`, this.authCredentials());
257
+ return result.data;
258
+ }
259
+ getCustomTokens(address) {
260
+ var _this$getAddressState4, _this$getAddressState5;
261
+ return (_this$getAddressState4 = (_this$getAddressState5 = this.getAddressState(address)) === null || _this$getAddressState5 === void 0 ? void 0 : _this$getAddressState5.customTokens) !== null && _this$getAddressState4 !== void 0 ? _this$getAddressState4 : [];
262
+ }
263
+ getCustomNfts(address) {
264
+ var _this$getAddressState6, _this$getAddressState7;
265
+ return (_this$getAddressState6 = (_this$getAddressState7 = this.getAddressState(address)) === null || _this$getAddressState7 === void 0 ? void 0 : _this$getAddressState7.customNfts) !== null && _this$getAddressState6 !== void 0 ? _this$getAddressState6 : [];
266
+ }
267
+ isChainIdSupported(address, chainId) {
268
+ const approveChainOptions = this.getChainOptions(address);
269
+ const providerConfig = approveChainOptions.find(x => util.stripHexPrefix(x.chainId) === chainId);
270
+ return !!providerConfig;
271
+ }
272
+ async addChain(network) {
273
+ const approveChainOptions = this.getChainOptions();
274
+ const providerConfig = approveChainOptions.find(x => x.chainId === network.chainId);
275
+ if (providerConfig) return;
276
+ const newNetwork = {
277
+ displayName: network.chainName,
278
+ rpcTarget: network.rpcUrls[0],
279
+ ticker: network.nativeCurrency.symbol,
280
+ chainId: network.chainId,
281
+ blockExplorerUrl: network.blockExplorerUrls[0],
282
+ tickerName: network.nativeCurrency.name,
283
+ logo: network.nativeCurrency.symbol
284
+ };
285
+ const isSuccess = await this.addCustomNetwork({
286
+ network: newNetwork
287
+ });
288
+ if (!isSuccess) throw new Error("unable to add custom network");
289
+ }
290
+ switchChain(data) {
291
+ const chainOptions = this.getChainOptions();
292
+ const providerConfig = chainOptions.find(x => x.chainId === data.chainId);
293
+ if (providerConfig) {
294
+ this.setProviderConfig(providerConfig);
295
+ } else {
296
+ throw new Error(`chainId ${data.chainId} is not supported`);
297
+ }
298
+ }
299
+
300
+ // Custom Network methods
301
+ async addCustomNetwork({
302
+ network
303
+ }) {
304
+ try {
305
+ const {
306
+ selectedAddress
307
+ } = this.state;
308
+ const payload = {
309
+ network_name: network.displayName,
310
+ rpc_url: network.rpcTarget,
311
+ chain_id: network.chainId,
312
+ symbol: network.ticker,
313
+ block_explorer_url: network.blockExplorerUrl || undefined,
314
+ is_testnet: network.isTestnet || false,
315
+ logo: network.logo,
316
+ symbol_name: network.tickerName
317
+ };
318
+ const res = await this.wsApiClient.authPost("customnetwork", payload, this.authCredentials(selectedAddress), {
319
+ useAPIKey: true
320
+ });
321
+ await this.sync(selectedAddress);
322
+ return res.data.id;
323
+ } catch {
324
+ log.error("error adding custom network");
325
+ return null;
326
+ }
327
+ }
328
+ async deleteCustomNetwork(id) {
329
+ try {
330
+ const {
331
+ selectedAddress
332
+ } = this.state;
333
+ await this.wsApiClient.authRemove(`customnetwork/${id}`, {}, this.authCredentials(selectedAddress), {
334
+ useAPIKey: true
335
+ });
336
+ await this.sync(selectedAddress);
337
+ return true;
338
+ } catch {
339
+ log.error("error deleting custom network");
340
+ return false;
341
+ }
342
+ }
343
+ async editCustomNetwork({
344
+ network,
345
+ id
346
+ }) {
347
+ try {
348
+ const {
349
+ selectedAddress
350
+ } = this.state;
351
+ const payload = {
352
+ network_name: network.displayName,
353
+ rpc_url: network.rpcTarget,
354
+ chain_id: network.chainId,
355
+ symbol: network.ticker || undefined,
356
+ block_explorer_url: network.blockExplorerUrl || undefined,
357
+ is_testnet: network.isTestnet || false
358
+ };
359
+ await this.wsApiClient.authPatch(`customnetwork/${id}`, payload, this.authCredentials(selectedAddress), {
360
+ useAPIKey: true
361
+ });
362
+ await this.sync(selectedAddress);
363
+ return true;
364
+ } catch {
365
+ log.error("error editing custom network");
366
+ return false;
367
+ }
368
+ }
369
+ getChainOptions(address = this.state.selectedAddress) {
370
+ var _identities$address$c, _identities$address;
371
+ const {
372
+ identities
373
+ } = this.state;
374
+ const customNetworks = (_identities$address$c = (_identities$address = identities[address]) === null || _identities$address === void 0 ? void 0 : _identities$address.customNetworks) !== null && _identities$address$c !== void 0 ? _identities$address$c : [];
375
+ const custom = Object.values(customNetworks).reduce((chains, network) => {
376
+ const networkItem = {
377
+ blockExplorerUrl: network.block_explorer_url,
378
+ chainId: network.chain_id,
379
+ displayName: network.network_name,
380
+ logo: "eth.svg",
381
+ rpcTarget: network.rpc_url,
382
+ ticker: network.symbol,
383
+ tickerName: network.symbol.toUpperCase(),
384
+ isCustom: true,
385
+ id: network.id
386
+ };
387
+ if (Object.keys(constants.SUPPORTED_NETWORKS).includes(networkItem.chainId)) return chains;
388
+ chains.push(networkItem);
389
+ return chains;
390
+ }, []);
391
+ const supported = Object.values(constants.SUPPORTED_NETWORKS).reduce((chains, network) => {
392
+ chains.push(network);
393
+ return chains;
394
+ }, []);
395
+ return [...supported, ...custom];
396
+ }
397
+ getBlockExplorerUrl() {
398
+ const supportedNetworks = this.getChainOptions();
399
+ const network = supportedNetworks.find(x => x.chainId === this.getProviderConfig().chainId);
400
+ if (!network) return "";
401
+ return `${network.blockExplorerUrl}`;
402
+ }
403
+ async calculatePastTx(txs, address) {
404
+ const pastTx = [];
405
+ const pendingTx = [];
406
+ const lowerCaseSelectedAddress = address.toLowerCase();
407
+ const supportedNetworks = this.getChainOptions(address);
408
+ const supportedNetwork = supportedNetworks.find(x => x.chainId === this.getProviderConfig().chainId);
409
+ for (const x of txs) {
410
+ var _x$to;
411
+ if ((supportedNetwork === null || supportedNetwork === void 0 ? void 0 : supportedNetwork.chainId) === x.chain_id && x.to && x.from && (lowerCaseSelectedAddress === x.from.toLowerCase() || lowerCaseSelectedAddress === ((_x$to = x.to) === null || _x$to === void 0 ? void 0 : _x$to.toLowerCase()))) {
412
+ if (x.status !== "confirmed") {
413
+ pendingTx.push(x);
414
+ } else {
415
+ const finalObject = helpers.formatPastTx({
416
+ transaction: x,
417
+ lowerCaseSelectedAddress,
418
+ blockExplorerUrl: this.getBlockExplorerUrl()
419
+ });
420
+ pastTx.push(finalObject);
421
+ }
422
+ }
423
+ }
424
+ const pendingTxPromises = pendingTx.map(x => helpers.getEthTxStatus(x.transaction_hash, this.provider).catch(error => log.error(error)));
425
+ const resolvedTxStatuses = await Promise.all(pendingTxPromises);
426
+ for (const [index, element] of pendingTx.entries()) {
427
+ const finalObject = helpers.formatPastTx({
428
+ transaction: element,
429
+ lowerCaseSelectedAddress,
430
+ blockExplorerUrl: this.getBlockExplorerUrl()
431
+ });
432
+ finalObject.status = resolvedTxStatuses[index] || baseControllers.TransactionStatus.submitted;
433
+ pastTx.push(finalObject);
434
+ if (lowerCaseSelectedAddress === element.from.toLowerCase() && finalObject.status && finalObject.status !== element.status) this.patchPastTx({
435
+ id: element.id,
436
+ status: finalObject.status
437
+ }, address);
438
+ }
439
+ const finalTx = this.cancelTxCalculate(pastTx);
440
+ this.updateState({
441
+ formattedPastTransactions: [...finalTx]
442
+ }, address);
443
+ }
444
+ cancelTxCalculate(pastTx) {
445
+ const nonceMap = {};
446
+ for (const x of pastTx) {
447
+ if (!nonceMap[x.nonce]) nonceMap[x.nonce] = [x];else {
448
+ nonceMap[x.nonce].push(x);
449
+ }
450
+ }
451
+ for (const [, value] of Object.entries(nonceMap)) {
452
+ // has duplicate
453
+ if (value.length > 1) {
454
+ // get latest and mark it as is_cancel
455
+ const latestTxs = value.sort((a, b) => {
456
+ const aDate = new Date(a.date).getTime();
457
+ const bDate = new Date(b.date).getTime();
458
+ return bDate - aDate;
459
+ });
460
+ const latestCancelTx = latestTxs[0];
461
+ latestCancelTx.is_cancel = true;
462
+ latestTxs.slice(1).forEach(x => {
463
+ x.hasCancel = true;
464
+ x.status = latestCancelTx.status === "confirmed" ? baseControllers.TransactionStatus.cancelled : baseControllers.TransactionStatus.cancelling;
465
+ x.cancelDateInitiated = `${helpers.formatTime(new Date(latestCancelTx.date).getTime())} - ${helpers.formatDate(latestCancelTx.date)}`;
466
+ x.etherscanLink = latestCancelTx.etherscanLink;
467
+ x.cancelGas = latestCancelTx.gas;
468
+ x.cancelGasPrice = latestCancelTx.gasPrice;
469
+ });
470
+ }
471
+ }
472
+ return pastTx;
473
+ }
474
+ }
475
+
476
+ exports.PreferencesController = PreferencesController;