@toruslabs/ethereum-controllers 7.2.0 → 7.4.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.
@@ -73,7 +73,8 @@ class PreferencesController extends baseControllers.BasePreferencesController {
73
73
  loginMode,
74
74
  sessionPubKey,
75
75
  aaProvider,
76
- eoaAddress
76
+ eoaAddress,
77
+ mainAddress
77
78
  } = params;
78
79
  const {
79
80
  chainId
@@ -89,7 +90,8 @@ class PreferencesController extends baseControllers.BasePreferencesController {
89
90
  network: web3AuthNetwork,
90
91
  eoa_address: eoaAddress,
91
92
  aa_provider: aaProvider,
92
- chain_id: chainId
93
+ chain_id: chainId,
94
+ main_address: mainAddress
93
95
  }
94
96
  });
95
97
  const {
@@ -10,23 +10,6 @@ var constants = require('../utils/constants.js');
10
10
  var contractAddresses = require('../utils/contractAddresses.js');
11
11
  var TokenHandler = require('./TokenHandler.js');
12
12
 
13
- function getObjectFromArrayBasedonKey(oldArray, key) {
14
- return oldArray.reduce((acc, x) => {
15
- const xkey = x[key];
16
- if (typeof xkey === "boolean") return acc;
17
- acc[xkey] = x;
18
- return acc;
19
- }, {});
20
- }
21
- const mergeTokenArrays = (oldArray, newArray) => {
22
- const oldMap = getObjectFromArrayBasedonKey(oldArray || [], "tokenAddress");
23
- const newMap = getObjectFromArrayBasedonKey(newArray || [], "tokenAddress");
24
- const finalArr = newArray;
25
- Object.keys(oldMap).forEach(x => {
26
- if (!newMap[x] && oldMap[x].isEtherScan) finalArr.push(oldMap[x]);
27
- });
28
- return finalArr;
29
- };
30
13
  const DEFAULT_INTERVAL = 180 * 1000;
31
14
  class TokensController extends baseControllers.BaseController {
32
15
  constructor({
@@ -179,45 +162,58 @@ class TokensController extends baseControllers.BaseController {
179
162
  const userAddress = this.userSelectedAddress;
180
163
  if (userAddress === "") return;
181
164
  const oldTokens = [...this.userTokens];
182
- const tokenAddresses = oldTokens.map(x => x.tokenAddress);
183
- const nonZeroTokens = [];
165
+ // - fetch from Etherscan, if failed then fetch from TokenHandler
166
+ // - if there are remaining tokens, fetch either from SingleAddressContract (if failed then use TokenHandler) or TokenHandler
184
167
  try {
168
+ const nonZeroTokens = [];
185
169
  const currentChainId = this.config.chainId;
186
170
  if (constants.ETHERSCAN_SUPPORTED_CHAINS.includes(currentChainId)) {
187
171
  const etherscanBalances = await this.getEtherScanTokens(userAddress, currentChainId, skipCache);
188
172
  nonZeroTokens.push(...etherscanBalances);
189
173
  }
190
- if (tokenAddresses.length > 0) {
174
+
175
+ // only fetch balances for tokens that are not already in the nonZeroTokens array
176
+ const remainingTokens = oldTokens.filter(x => !nonZeroTokens.find(y => {
177
+ var _y$tokenAddress, _x$tokenAddress;
178
+ return ((_y$tokenAddress = y.tokenAddress) === null || _y$tokenAddress === void 0 ? void 0 : _y$tokenAddress.toLocaleLowerCase()) === ((_x$tokenAddress = x.tokenAddress) === null || _x$tokenAddress === void 0 ? void 0 : _x$tokenAddress.toLocaleLowerCase());
179
+ }));
180
+ if (remainingTokens.length > 0) {
181
+ const remainingTokensAddresses = remainingTokens.map(x => x.tokenAddress);
191
182
  const currentSingleCallAddress = contractAddresses.SINGLE_CALL_BALANCES_ADDRESSES[currentChainId];
192
183
  if (currentSingleCallAddress) {
193
184
  const ethContract = new ethers.Contract(currentSingleCallAddress, abis.singleBalanceCheckerAbi, this.ethersProvider);
194
- const result = await ethContract.balances([userAddress], tokenAddresses);
195
- tokenAddresses.forEach((_, index) => {
185
+ const result = await ethContract.balances([userAddress], remainingTokensAddresses);
186
+ remainingTokensAddresses.forEach((_, index) => {
196
187
  const balance = ethers.toQuantity(result[index]);
197
188
  if (balance && balance !== "0x0") {
198
- nonZeroTokens.push(_objectSpread(_objectSpread({}, oldTokens[index]), {}, {
189
+ nonZeroTokens.push(_objectSpread(_objectSpread({}, remainingTokens[index]), {}, {
199
190
  balance,
200
191
  chainId: currentChainId
201
192
  }));
202
193
  }
203
194
  });
204
195
  } else {
205
- this.getTokenBalancesUsingHandler(oldTokens);
196
+ const fetchedRemainingTokens = await this.getTokenBalancesUsingHandler(remainingTokens);
197
+ nonZeroTokens.push(...fetchedRemainingTokens);
206
198
  }
207
199
  }
200
+ this.update({
201
+ tokens: {
202
+ [userAddress]: nonZeroTokens
203
+ }
204
+ });
208
205
  } catch (error) {
209
206
  log.error(error, "unable to fetch token balances using single call balance address");
210
- this.getTokenBalancesUsingHandler(oldTokens);
211
- } finally {
207
+ const fetchedTokens = await this.getTokenBalancesUsingHandler(oldTokens);
212
208
  this.update({
213
209
  tokens: {
214
- [userAddress]: nonZeroTokens
210
+ [userAddress]: fetchedTokens
215
211
  }
216
212
  });
217
213
  }
218
214
  }
219
215
  async getTokenBalancesUsingHandler(customTokens) {
220
- if (!this.userSelectedAddress) return;
216
+ if (!this.userSelectedAddress) return [];
221
217
  const currentNetworkTokens = customTokens;
222
218
  const promiseSettledResult = await Promise.allSettled(currentNetworkTokens.map(async x => {
223
219
  try {
@@ -250,11 +246,7 @@ class TokensController extends baseControllers.BaseController {
250
246
  if (x.status === "fulfilled" && x.value) acc.push(x.value);
251
247
  return acc;
252
248
  }, []);
253
- this.update({
254
- tokens: {
255
- [this.userSelectedAddress]: mergeTokenArrays(this.userTokens, nonZeroTokens)
256
- }
257
- });
249
+ return nonZeroTokens;
258
250
  }
259
251
  }
260
252
 
@@ -71,7 +71,8 @@ class PreferencesController extends BasePreferencesController {
71
71
  loginMode,
72
72
  sessionPubKey,
73
73
  aaProvider,
74
- eoaAddress
74
+ eoaAddress,
75
+ mainAddress
75
76
  } = params;
76
77
  const {
77
78
  chainId
@@ -87,7 +88,8 @@ class PreferencesController extends BasePreferencesController {
87
88
  network: web3AuthNetwork,
88
89
  eoa_address: eoaAddress,
89
90
  aa_provider: aaProvider,
90
- chain_id: chainId
91
+ chain_id: chainId,
92
+ main_address: mainAddress
91
93
  }
92
94
  });
93
95
  const {
@@ -8,23 +8,6 @@ import { ETHERSCAN_SUPPORTED_CHAINS } from '../utils/constants.js';
8
8
  import { SINGLE_CALL_BALANCES_ADDRESSES } from '../utils/contractAddresses.js';
9
9
  import { TokenHandler } from './TokenHandler.js';
10
10
 
11
- function getObjectFromArrayBasedonKey(oldArray, key) {
12
- return oldArray.reduce((acc, x) => {
13
- const xkey = x[key];
14
- if (typeof xkey === "boolean") return acc;
15
- acc[xkey] = x;
16
- return acc;
17
- }, {});
18
- }
19
- const mergeTokenArrays = (oldArray, newArray) => {
20
- const oldMap = getObjectFromArrayBasedonKey(oldArray || [], "tokenAddress");
21
- const newMap = getObjectFromArrayBasedonKey(newArray || [], "tokenAddress");
22
- const finalArr = newArray;
23
- Object.keys(oldMap).forEach(x => {
24
- if (!newMap[x] && oldMap[x].isEtherScan) finalArr.push(oldMap[x]);
25
- });
26
- return finalArr;
27
- };
28
11
  const DEFAULT_INTERVAL = 180 * 1000;
29
12
  class TokensController extends BaseController {
30
13
  constructor({
@@ -177,45 +160,58 @@ class TokensController extends BaseController {
177
160
  const userAddress = this.userSelectedAddress;
178
161
  if (userAddress === "") return;
179
162
  const oldTokens = [...this.userTokens];
180
- const tokenAddresses = oldTokens.map(x => x.tokenAddress);
181
- const nonZeroTokens = [];
163
+ // - fetch from Etherscan, if failed then fetch from TokenHandler
164
+ // - if there are remaining tokens, fetch either from SingleAddressContract (if failed then use TokenHandler) or TokenHandler
182
165
  try {
166
+ const nonZeroTokens = [];
183
167
  const currentChainId = this.config.chainId;
184
168
  if (ETHERSCAN_SUPPORTED_CHAINS.includes(currentChainId)) {
185
169
  const etherscanBalances = await this.getEtherScanTokens(userAddress, currentChainId, skipCache);
186
170
  nonZeroTokens.push(...etherscanBalances);
187
171
  }
188
- if (tokenAddresses.length > 0) {
172
+
173
+ // only fetch balances for tokens that are not already in the nonZeroTokens array
174
+ const remainingTokens = oldTokens.filter(x => !nonZeroTokens.find(y => {
175
+ var _y$tokenAddress, _x$tokenAddress;
176
+ return ((_y$tokenAddress = y.tokenAddress) === null || _y$tokenAddress === void 0 ? void 0 : _y$tokenAddress.toLocaleLowerCase()) === ((_x$tokenAddress = x.tokenAddress) === null || _x$tokenAddress === void 0 ? void 0 : _x$tokenAddress.toLocaleLowerCase());
177
+ }));
178
+ if (remainingTokens.length > 0) {
179
+ const remainingTokensAddresses = remainingTokens.map(x => x.tokenAddress);
189
180
  const currentSingleCallAddress = SINGLE_CALL_BALANCES_ADDRESSES[currentChainId];
190
181
  if (currentSingleCallAddress) {
191
182
  const ethContract = new Contract(currentSingleCallAddress, singleBalanceCheckerAbi, this.ethersProvider);
192
- const result = await ethContract.balances([userAddress], tokenAddresses);
193
- tokenAddresses.forEach((_, index) => {
183
+ const result = await ethContract.balances([userAddress], remainingTokensAddresses);
184
+ remainingTokensAddresses.forEach((_, index) => {
194
185
  const balance = toQuantity(result[index]);
195
186
  if (balance && balance !== "0x0") {
196
- nonZeroTokens.push(_objectSpread(_objectSpread({}, oldTokens[index]), {}, {
187
+ nonZeroTokens.push(_objectSpread(_objectSpread({}, remainingTokens[index]), {}, {
197
188
  balance,
198
189
  chainId: currentChainId
199
190
  }));
200
191
  }
201
192
  });
202
193
  } else {
203
- this.getTokenBalancesUsingHandler(oldTokens);
194
+ const fetchedRemainingTokens = await this.getTokenBalancesUsingHandler(remainingTokens);
195
+ nonZeroTokens.push(...fetchedRemainingTokens);
204
196
  }
205
197
  }
198
+ this.update({
199
+ tokens: {
200
+ [userAddress]: nonZeroTokens
201
+ }
202
+ });
206
203
  } catch (error) {
207
204
  log.error(error, "unable to fetch token balances using single call balance address");
208
- this.getTokenBalancesUsingHandler(oldTokens);
209
- } finally {
205
+ const fetchedTokens = await this.getTokenBalancesUsingHandler(oldTokens);
210
206
  this.update({
211
207
  tokens: {
212
- [userAddress]: nonZeroTokens
208
+ [userAddress]: fetchedTokens
213
209
  }
214
210
  });
215
211
  }
216
212
  }
217
213
  async getTokenBalancesUsingHandler(customTokens) {
218
- if (!this.userSelectedAddress) return;
214
+ if (!this.userSelectedAddress) return [];
219
215
  const currentNetworkTokens = customTokens;
220
216
  const promiseSettledResult = await Promise.allSettled(currentNetworkTokens.map(async x => {
221
217
  try {
@@ -248,11 +244,7 @@ class TokensController extends BaseController {
248
244
  if (x.status === "fulfilled" && x.value) acc.push(x.value);
249
245
  return acc;
250
246
  }, []);
251
- this.update({
252
- tokens: {
253
- [this.userSelectedAddress]: mergeTokenArrays(this.userTokens, nonZeroTokens)
254
- }
255
- });
247
+ return nonZeroTokens;
256
248
  }
257
249
  }
258
250
 
@@ -26,6 +26,7 @@ export declare class PreferencesController extends BasePreferencesController<Ext
26
26
  initPreferences(params: InitPreferencesParams & {
27
27
  eoaAddress?: string;
28
28
  aaProvider?: string;
29
+ mainAddress?: string;
29
30
  }): Promise<void>;
30
31
  getSelectedAddress(): string;
31
32
  sync(address: string): Promise<boolean>;
@@ -37,5 +37,5 @@ export declare class TokensController extends BaseController<EthereumTokensContr
37
37
  restartTokenDetection(): void;
38
38
  detectNewTokens(): void;
39
39
  refreshTokenBalances(skipCache?: boolean): Promise<void>;
40
- getTokenBalancesUsingHandler(customTokens: CustomTokenInfo[]): Promise<void>;
40
+ getTokenBalancesUsingHandler(customTokens: CustomTokenInfo[]): Promise<CustomTokenInfo[]>;
41
41
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toruslabs/ethereum-controllers",
3
- "version": "7.2.0",
3
+ "version": "7.4.0",
4
4
  "homepage": "https://github.com/torusresearch/controllers#readme",
5
5
  "license": "ISC",
6
6
  "sideEffects": false,
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@ethereumjs/util": "^9.1.0",
24
- "@toruslabs/base-controllers": "^7.2.0",
24
+ "@toruslabs/base-controllers": "^7.4.0",
25
25
  "@toruslabs/http-helpers": "^7.0.0",
26
26
  "@web3auth/auth": "^9.6.4",
27
27
  "async-mutex": "^0.5.0",
@@ -63,7 +63,7 @@
63
63
  "publishConfig": {
64
64
  "access": "public"
65
65
  },
66
- "gitHead": "4ff78b7a1aa5861366d0ce28ab48fe178f776f15",
66
+ "gitHead": "ac67368e2bd43af7240fd7633923ed2f5aa3f752",
67
67
  "devDependencies": {
68
68
  "@nomicfoundation/hardhat-chai-matchers": "^2.0.8",
69
69
  "@nomicfoundation/hardhat-ethers": "^3.0.8",