@subwallet/extension-base 1.1.6-0 → 1.1.6-2

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 (51) hide show
  1. package/background/KoniTypes.d.ts +2 -0
  2. package/cjs/koni/api/nft/config.js +1 -1
  3. package/cjs/koni/api/staking/bonding/amplitude.js +18 -17
  4. package/cjs/koni/api/staking/bonding/paraChain.js +11 -17
  5. package/cjs/koni/background/handlers/Extension.js +16 -3
  6. package/cjs/koni/background/handlers/Tabs.js +1 -5
  7. package/cjs/packageInfo.js +1 -1
  8. package/cjs/page/SubWalleEvmProvider.js +18 -7
  9. package/cjs/services/chain-service/constants.js +5 -3
  10. package/cjs/services/chain-service/handler/AbstractChainHandler.js +25 -11
  11. package/cjs/services/chain-service/handler/EvmApi.js +15 -5
  12. package/cjs/services/chain-service/handler/EvmChainHandler.js +2 -2
  13. package/cjs/services/chain-service/handler/SubstrateApi.js +36 -17
  14. package/cjs/services/chain-service/handler/SubstrateChainHandler.js +5 -5
  15. package/cjs/services/chain-service/index.js +12 -6
  16. package/cjs/services/migration-service/scripts/MigrateWalletReference.js +31 -0
  17. package/cjs/services/migration-service/scripts/index.js +3 -1
  18. package/cjs/services/setting-service/constants.js +2 -1
  19. package/cjs/services/storage-service/db-stores/Nft.js +2 -2
  20. package/cjs/services/storage-service/db-stores/Staking.js +2 -2
  21. package/koni/api/nft/config.d.ts +1 -1
  22. package/koni/api/nft/config.js +1 -1
  23. package/koni/api/staking/bonding/amplitude.js +18 -17
  24. package/koni/api/staking/bonding/paraChain.js +11 -17
  25. package/koni/api/staking/bonding/utils.d.ts +3 -3
  26. package/koni/background/handlers/Extension.d.ts +1 -0
  27. package/koni/background/handlers/Extension.js +16 -3
  28. package/koni/background/handlers/Tabs.js +1 -5
  29. package/package.json +12 -6
  30. package/packageInfo.js +1 -1
  31. package/page/SubWalleEvmProvider.d.ts +2 -1
  32. package/page/SubWalleEvmProvider.js +18 -7
  33. package/services/chain-service/constants.js +5 -3
  34. package/services/chain-service/handler/AbstractChainHandler.d.ts +5 -5
  35. package/services/chain-service/handler/AbstractChainHandler.js +24 -9
  36. package/services/chain-service/handler/EvmApi.d.ts +4 -2
  37. package/services/chain-service/handler/EvmApi.js +15 -5
  38. package/services/chain-service/handler/EvmChainHandler.js +2 -2
  39. package/services/chain-service/handler/SubstrateApi.d.ts +5 -2
  40. package/services/chain-service/handler/SubstrateApi.js +36 -17
  41. package/services/chain-service/handler/SubstrateChainHandler.js +6 -6
  42. package/services/chain-service/handler/types.d.ts +2 -1
  43. package/services/chain-service/index.d.ts +1 -0
  44. package/services/chain-service/index.js +12 -6
  45. package/services/chain-service/types.d.ts +1 -0
  46. package/services/migration-service/scripts/MigrateWalletReference.d.ts +4 -0
  47. package/services/migration-service/scripts/MigrateWalletReference.js +23 -0
  48. package/services/migration-service/scripts/index.js +3 -1
  49. package/services/setting-service/constants.js +2 -1
  50. package/services/storage-service/db-stores/Nft.js +2 -2
  51. package/services/storage-service/db-stores/Staking.js +2 -2
@@ -320,6 +320,7 @@ export interface UiSettings {
320
320
  camera: boolean;
321
321
  timeAutoLock: number;
322
322
  enableChainPatrol: boolean;
323
+ walletReference: string;
323
324
  }
324
325
  export declare type RequestSettingsType = UiSettings;
325
326
  export declare type RequestCameraSettings = {
@@ -1532,6 +1533,7 @@ export interface KoniRequestSignatures {
1532
1533
  'pri(chainService.upsertChain)': [_NetworkUpsertParams, boolean];
1533
1534
  'pri(chainService.enableChains)': [EnableMultiChainParams, boolean];
1534
1535
  'pri(chainService.enableChain)': [EnableChainParams, boolean];
1536
+ 'pri(chainService.reconnectChain)': [string, boolean];
1535
1537
  'pri(chainService.disableChains)': [string[], boolean];
1536
1538
  'pri(chainService.disableChain)': [string, boolean];
1537
1539
  'pri(chainService.removeChain)': [string, boolean];
@@ -53,7 +53,7 @@ const IPFS_GATEWAY_4EVERLAND = 'https://4everland.io/ipfs/';
53
53
  exports.IPFS_GATEWAY_4EVERLAND = IPFS_GATEWAY_4EVERLAND;
54
54
  const IPFS_FLEEK = 'https://ipfs.fleek.co/ipfs/';
55
55
  exports.IPFS_FLEEK = IPFS_FLEEK;
56
- const IPFS_HARDBIN = 'https://hardbin.com/ipfs';
56
+ const IPFS_HARDBIN = 'https://hardbin.com/ipfs/';
57
57
  exports.IPFS_HARDBIN = IPFS_HARDBIN;
58
58
  let SUPPORTED_NFT_NETWORKS;
59
59
  exports.SUPPORTED_NFT_NETWORKS = SUPPORTED_NFT_NETWORKS;
@@ -213,23 +213,24 @@ async function getAmplitudeCollatorsInfo(chain, substrateApi) {
213
213
  const delegatorReturn = parseFloat(rawDelegatorReturn.split('%')[0]);
214
214
  const allCollators = [];
215
215
  for (const _collator of _allCollators) {
216
- const collatorInfo = _collator[1].toHuman();
217
- if (typeof collatorInfo.status === 'string' && collatorInfo.status.toLowerCase() === 'active') {
218
- allCollators.push({
219
- address: collatorInfo.id,
220
- totalStake: (0, _utils2.parseRawNumber)(collatorInfo.total).toString(),
221
- ownStake: (0, _utils2.parseRawNumber)(collatorInfo.stake).toString(),
222
- otherStake: ((0, _utils2.parseRawNumber)(collatorInfo.total) - (0, _utils2.parseRawNumber)(collatorInfo.stake)).toString(),
223
- nominatorCount: collatorInfo.delegators.length,
224
- commission: 0,
225
- expectedReturn: delegatorReturn,
226
- blocked: false,
227
- isVerified: false,
228
- minBond: '0',
229
- chain,
230
- isCrowded: collatorInfo.delegators.length >= parseInt(maxDelegatorsPerCollator)
231
- });
232
- }
216
+ const collatorInfo = _collator[1].toPrimitive();
217
+ const bnTotalStake = new _util.BN(collatorInfo.total);
218
+ const bnOwnStake = new _util.BN(collatorInfo.stake);
219
+ const bnOtherStake = bnTotalStake.sub(bnOwnStake);
220
+ allCollators.push({
221
+ address: collatorInfo.id,
222
+ totalStake: bnTotalStake.toString(),
223
+ ownStake: bnOwnStake.toString(),
224
+ otherStake: bnOtherStake.toString(),
225
+ nominatorCount: collatorInfo.delegators.length,
226
+ commission: 0,
227
+ expectedReturn: delegatorReturn,
228
+ blocked: false,
229
+ isVerified: false,
230
+ minBond: '0',
231
+ chain,
232
+ isCrowded: collatorInfo.delegators.length >= parseInt(maxDelegatorsPerCollator)
233
+ });
233
234
  }
234
235
  return allCollators;
235
236
  }
@@ -44,7 +44,7 @@ function validateParaChainUnbondingCondition(amount, nominatorMetadata, chainSta
44
44
  const bnRemainingStake = bnActiveStake.sub(new _util.BN(amount));
45
45
  const bnChainMinStake = new _util.BN(chainStakingMetadata.minStake || '0');
46
46
  const bnCollatorMinStake = new _util.BN(targetNomination.validatorMinStake || '0');
47
- const bnMinStake = bnCollatorMinStake > bnChainMinStake ? bnCollatorMinStake : bnChainMinStake;
47
+ const bnMinStake = _util.BN.max(bnCollatorMinStake, bnChainMinStake);
48
48
  if (targetNomination.hasUnstaking) {
49
49
  errors.push(new _TransactionError.TransactionError(_KoniTypes.StakingTxErrorType.EXIST_UNSTAKING_REQUEST));
50
50
  }
@@ -101,9 +101,10 @@ function validateParaChainBondingCondition(chainInfo, amount, selectedCollators,
101
101
  }
102
102
  function subscribeParaChainStakingMetadata(chain, substrateApi, callback) {
103
103
  return substrateApi.api.query.parachainStaking.round(_round => {
104
+ var _substrateApi$api$con, _substrateApi$api$con2, _substrateApi$api$con3;
104
105
  const roundObj = _round.toHuman();
105
106
  const round = (0, _utils3.parseRawNumber)(roundObj.current);
106
- const maxDelegations = substrateApi.api.consts.parachainStaking.maxDelegationsPerDelegator.toString();
107
+ const maxDelegations = (_substrateApi$api$con = substrateApi.api.consts) === null || _substrateApi$api$con === void 0 ? void 0 : (_substrateApi$api$con2 = _substrateApi$api$con.parachainStaking) === null || _substrateApi$api$con2 === void 0 ? void 0 : (_substrateApi$api$con3 = _substrateApi$api$con2.maxDelegationsPerDelegator) === null || _substrateApi$api$con3 === void 0 ? void 0 : _substrateApi$api$con3.toString();
107
108
  const unstakingDelay = substrateApi.api.consts.parachainStaking.delegationBondLessDelay.toString();
108
109
  const unstakingPeriod = parseInt(unstakingDelay) * (_constants._STAKING_ERA_LENGTH_MAP[chain] || _constants._STAKING_ERA_LENGTH_MAP.default);
109
110
  callback(chain, {
@@ -332,17 +333,21 @@ async function getParachainCollatorsInfo(chain, substrateApi) {
332
333
  const _collatorAddress = collator[0].toHuman();
333
334
  const collatorAddress = _collatorAddress[0];
334
335
  const collatorInfo = collator[1].toPrimitive();
336
+ const bnTotalStake = new _util.BN(collatorInfo.totalCounted);
337
+ const bnOwnStake = new _util.BN(collatorInfo.bond);
338
+ const bnOtherStake = bnTotalStake.sub(bnOwnStake);
339
+ const bnMinBond = new _util.BN(collatorInfo.lowestTopDelegationAmount);
335
340
  allCollators.push({
336
341
  commission: 0,
337
342
  expectedReturn: 0,
338
343
  address: collatorAddress,
339
- totalStake: collatorInfo.totalCounted.toString(),
340
- ownStake: collatorInfo.bond.toString(),
341
- otherStake: (collatorInfo.totalCounted - collatorInfo.bond).toString(),
344
+ totalStake: bnTotalStake.toString(),
345
+ ownStake: bnOwnStake.toString(),
346
+ otherStake: bnOtherStake.toString(),
342
347
  nominatorCount: collatorInfo.delegationCount,
343
348
  blocked: false,
344
349
  isVerified: false,
345
- minBond: collatorInfo.lowestTopDelegationAmount.toString(),
350
+ minBond: bnMinBond.toString(),
346
351
  chain,
347
352
  isCrowded: parseInt(maxDelegationPerCollator) > 0
348
353
  });
@@ -354,10 +359,6 @@ async function getParachainCollatorsInfo(chain, substrateApi) {
354
359
  ]);
355
360
  const rawInfo = _info.toHuman();
356
361
  const rawIdentity = _identity ? _identity.toHuman() : null;
357
- const rawBond = rawInfo === null || rawInfo === void 0 ? void 0 : rawInfo.bond;
358
- const bond = new _util.BN(rawBond.replaceAll(',', ''));
359
- const delegationCount = (0, _utils3.parseRawNumber)(rawInfo === null || rawInfo === void 0 ? void 0 : rawInfo.delegationCount);
360
- const minDelegation = (0, _utils3.parseRawNumber)(rawInfo === null || rawInfo === void 0 ? void 0 : rawInfo.lowestTopDelegationAmount);
361
362
  const active = (rawInfo === null || rawInfo === void 0 ? void 0 : rawInfo.status) === 'Active';
362
363
  let isReasonable = false;
363
364
  let identity;
@@ -369,21 +370,14 @@ async function getParachainCollatorsInfo(chain, substrateApi) {
369
370
  extraInfoMap[collator.address] = {
370
371
  identity,
371
372
  isVerified: isReasonable,
372
- bond: bond.toString(),
373
- minDelegation: minDelegation.toString(),
374
- delegationCount,
375
373
  active
376
374
  };
377
375
  }));
378
376
  for (const validator of allCollators) {
379
- validator.minBond = extraInfoMap[validator.address].minDelegation.toString();
380
- validator.ownStake = extraInfoMap[validator.address].bond.toString();
381
377
  validator.blocked = !extraInfoMap[validator.address].active;
382
378
  validator.identity = extraInfoMap[validator.address].identity;
383
379
  validator.isVerified = extraInfoMap[validator.address].isVerified;
384
380
  // @ts-ignore
385
- validator.otherStake = (validator.totalStake - validator.ownStake).toString();
386
- validator.nominatorCount = extraInfoMap[validator.address].delegationCount;
387
381
  validator.commission = collatorCommission;
388
382
  }
389
383
  return allCollators;
@@ -1423,12 +1423,20 @@ class KoniExtension {
1423
1423
  async subscribeHistory(id, port) {
1424
1424
  const cb = (0, _subscriptions.createSubscription)(id, port);
1425
1425
  const historySubject = await this.#koniState.historyService.getHistorySubject();
1426
- historySubject.subscribe(cb);
1427
- this.createUnsubscriptionHandle(id, historySubject.unsubscribe);
1426
+ const subscription = historySubject.subscribe(histories => {
1427
+ const addresses = _uiKeyring.keyring.getAccounts().map(a => a.address.toLowerCase());
1428
+
1429
+ // Re-filter
1430
+ cb(histories.filter(item => addresses.includes(item.address.toLowerCase())));
1431
+ });
1432
+ this.createUnsubscriptionHandle(id, subscription.unsubscribe);
1428
1433
  port.onDisconnect.addListener(() => {
1429
1434
  this.cancelSubscription(id);
1430
1435
  });
1431
- return historySubject.getValue();
1436
+ const addresses = _uiKeyring.keyring.getAccounts().map(a => a.address.toLowerCase());
1437
+
1438
+ // Re-filter
1439
+ return historySubject.getValue().filter(item => addresses.includes(item.address.toLowerCase()));
1432
1440
  }
1433
1441
 
1434
1442
  // Save address to contact
@@ -1726,6 +1734,9 @@ class KoniExtension {
1726
1734
  } = _ref43;
1727
1735
  return await this.#koniState.enableChain(chainSlug, enableTokens);
1728
1736
  }
1737
+ async reconnectChain(chainSlug) {
1738
+ return this.#koniState.chainService.reconnectChain(chainSlug);
1739
+ }
1729
1740
  async validateNetwork(_ref44) {
1730
1741
  let {
1731
1742
  existedChainSlug,
@@ -3702,6 +3713,8 @@ class KoniExtension {
3702
3713
  return this.getSupportedSmartContractTypes();
3703
3714
  case 'pri(chainService.enableChain)':
3704
3715
  return await this.enableChain(request);
3716
+ case 'pri(chainService.reconnectChain)':
3717
+ return await this.reconnectChain(request);
3705
3718
  case 'pri(chainService.disableChain)':
3706
3719
  return await this.disableChain(request);
3707
3720
  case 'pri(chainService.removeChain)':
@@ -894,11 +894,7 @@ class KoniTabs {
894
894
  return true;
895
895
  }
896
896
  isEvmPublicRequest(type, request) {
897
- if (type === 'evm(request)' && ['eth_chainId', 'net_version'].includes(request === null || request === void 0 ? void 0 : request.method)) {
898
- return true;
899
- } else {
900
- return false;
901
- }
897
+ return type === 'evm(request)' && ['eth_chainId', 'net_version'].includes(request === null || request === void 0 ? void 0 : request.method);
902
898
  }
903
899
  async addPspToken(id, url, _ref22) {
904
900
  let {
@@ -13,6 +13,6 @@ const packageInfo = {
13
13
  name: '@subwallet/extension-base',
14
14
  path: typeof __dirname === 'string' ? __dirname : 'auto',
15
15
  type: 'cjs',
16
- version: '1.1.6-0'
16
+ version: '1.1.6-2'
17
17
  };
18
18
  exports.packageInfo = packageInfo;
@@ -9,11 +9,11 @@ var _safeEventEmitter = _interopRequireDefault(require("@metamask/safe-event-emi
9
9
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
10
10
  // SPDX-License-Identifier: Apache-2.0
11
11
 
12
+ let subscribeFlag = false;
12
13
  class SubWalletEvmProvider extends _safeEventEmitter.default {
13
14
  isSubWallet = true;
14
15
  isMetaMask = false;
15
16
  _connected = false;
16
- _subscribed = false;
17
17
  constructor(sendMessage, version) {
18
18
  super();
19
19
  this.version = version;
@@ -27,7 +27,7 @@ class SubWalletEvmProvider extends _safeEventEmitter.default {
27
27
  return this._connected;
28
28
  }
29
29
  subscribeExtensionEvents() {
30
- if (this._subscribed) {
30
+ if (subscribeFlag) {
31
31
  return;
32
32
  }
33
33
  this.sendMessage('evm(events.subscribe)', null, _ref => {
@@ -49,19 +49,33 @@ class SubWalletEvmProvider extends _safeEventEmitter.default {
49
49
  console.warn('Can not handle event', type, payload);
50
50
  }
51
51
  }).then(done => {
52
- this._subscribed = true;
53
- }).catch(console.error);
52
+ subscribeFlag = true;
53
+ }).catch(() => {
54
+ subscribeFlag = false;
55
+ });
56
+ subscribeFlag = true;
54
57
  }
55
58
  async enable() {
56
59
  return this.request({
57
60
  method: 'eth_requestAccounts'
58
61
  });
59
62
  }
63
+ on(eventName, listener) {
64
+ this.subscribeExtensionEvents();
65
+ super.on(eventName, listener);
66
+ return this;
67
+ }
68
+ once(eventName, listener) {
69
+ this.subscribeExtensionEvents();
70
+ super.once(eventName, listener);
71
+ return this;
72
+ }
60
73
  request(_ref2) {
61
74
  let {
62
75
  method,
63
76
  params
64
77
  } = _ref2;
78
+ // Subscribe events
65
79
  switch (method) {
66
80
  case 'eth_requestAccounts':
67
81
  return new Promise((resolve, reject) => {
@@ -70,9 +84,6 @@ class SubWalletEvmProvider extends _safeEventEmitter.default {
70
84
  origin,
71
85
  accountAuthType: 'evm'
72
86
  }).then(() => {
73
- // Subscribe event
74
- this.subscribeExtensionEvents();
75
-
76
87
  // Return account list
77
88
  this.request({
78
89
  method: 'eth_accounts'
@@ -61,13 +61,13 @@ const _NFT_CHAIN_GROUP = {
61
61
  // Staking--------------------------------------------------------------------------------------------------------------
62
62
  exports._NFT_CHAIN_GROUP = _NFT_CHAIN_GROUP;
63
63
  const _STAKING_CHAIN_GROUP = {
64
- relay: ['polkadot', 'kusama', 'aleph', 'polkadex', 'ternoa', 'ternoa_alphanet', 'alephTest', 'polkadexTest', 'westend'],
64
+ relay: ['polkadot', 'kusama', 'aleph', 'polkadex', 'ternoa', 'ternoa_alphanet', 'alephTest', 'polkadexTest', 'westend', 'kate', 'edgeware'],
65
65
  para: ['moonbeam', 'moonriver', 'moonbase', 'turing', 'turingStaging', 'bifrost', 'bifrost_testnet', 'calamari_test', 'calamari'],
66
66
  astar: ['astar', 'shiden', 'shibuya'],
67
67
  amplitude: ['amplitude', 'amplitude_test', 'kilt', 'kilt_peregrine', 'pendulum'],
68
68
  // amplitude and kilt only share some common logic
69
69
  kilt: ['kilt', 'kilt_peregrine'],
70
- nominationPool: ['polkadot', 'kusama', 'westend', 'alephTest', 'aleph'],
70
+ nominationPool: ['polkadot', 'kusama', 'westend', 'alephTest', 'aleph', 'kate'],
71
71
  bifrost: ['bifrost', 'bifrost_testnet'],
72
72
  aleph: ['aleph', 'alephTest'],
73
73
  // A0 has distinct tokenomics
@@ -100,7 +100,9 @@ const _STAKING_ERA_LENGTH_MAP = {
100
100
  amplitude_test: 2,
101
101
  pendulum: 2,
102
102
  kilt: 2,
103
- kilt_peregrine: 2
103
+ kilt_peregrine: 2,
104
+ edgeware: 6,
105
+ kate: 6
104
106
  };
105
107
  exports._STAKING_ERA_LENGTH_MAP = _STAKING_ERA_LENGTH_MAP;
106
108
  const _PARACHAIN_INFLATION_DISTRIBUTION = {
@@ -3,18 +3,18 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.SHORT_RETRY_TIME = exports.LONG_RETRY_TIME = exports.FIRST_RECONNECT_TIME = exports.AbstractChainHandler = void 0;
6
+ exports.SHORT_RETRY_TIME = exports.FIRST_RECONNECT_TIME = exports.AbstractChainHandler = void 0;
7
+ var _types = require("@subwallet/extension-base/services/chain-service/types");
7
8
  var _rxjs = require("rxjs");
8
9
  // Copyright 2019-2022 @subwallet/extension-base authors & contributors
9
10
  // SPDX-License-Identifier: Apache-2.0
10
11
 
11
- const SHORT_RECOVER_RETRY = 3;
12
+ const MAX_RECOVER_RETRY = 6;
12
13
  const FIRST_RECONNECT_TIME = 3000;
13
14
  exports.FIRST_RECONNECT_TIME = FIRST_RECONNECT_TIME;
14
- const SHORT_RETRY_TIME = 15000;
15
+ const SHORT_RETRY_TIME = 20000;
16
+ // export const LONG_RETRY_TIME = 60000;
15
17
  exports.SHORT_RETRY_TIME = SHORT_RETRY_TIME;
16
- const LONG_RETRY_TIME = 60000;
17
- exports.LONG_RETRY_TIME = LONG_RETRY_TIME;
18
18
  class AbstractChainHandler {
19
19
  apiStateMapSubject = new _rxjs.BehaviorSubject({});
20
20
  // Recover retry times
@@ -24,20 +24,26 @@ class AbstractChainHandler {
24
24
  this.parent = parent;
25
25
  this.recoverMap = {};
26
26
  }
27
- handleConnect(chain, isConnected) {
27
+ handleConnection(chain, newStatus) {
28
+ let forceRecover = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
28
29
  const currentMap = this.apiStateMapSubject.getValue();
29
- const currentStatus = currentMap[chain];
30
+ const oldStatus = currentMap[chain];
30
31
 
31
32
  // Update api state
32
- if (currentStatus !== isConnected) {
33
+ if (oldStatus !== newStatus) {
33
34
  this.apiStateMapSubject.next({
34
35
  ...currentMap,
35
- [chain]: isConnected
36
+ [chain]: newStatus
36
37
  });
37
38
  }
38
39
 
40
+ // Reset retry when connected is successful
41
+ if (newStatus === _types._ChainConnectionStatus.CONNECTED) {
42
+ this.cancelRecover(chain);
43
+ }
44
+
39
45
  // Handle connection change
40
- if (!isConnected) {
46
+ if ((!this.isRecovering(chain) || forceRecover) && newStatus === _types._ChainConnectionStatus.DISCONNECTED) {
41
47
  this.handleRecover(chain);
42
48
  }
43
49
  }
@@ -57,8 +63,13 @@ class AbstractChainHandler {
57
63
  };
58
64
  clearTimeout(retryRecord.timeout);
59
65
  const retryTimes = retryRecord.retryTimes;
66
+ if (retryTimes >= MAX_RECOVER_RETRY) {
67
+ this.handleConnection(chain, _types._ChainConnectionStatus.UNSTABLE);
68
+ this.cancelRecover(chain); // Need manual recover
69
+ }
70
+
60
71
  // Slow down recover frequency if increasing recover times
61
- const retryTimeout = retryTimes === 0 ? FIRST_RECONNECT_TIME : retryTimes >= SHORT_RECOVER_RETRY ? LONG_RETRY_TIME : SHORT_RETRY_TIME;
72
+ const retryTimeout = retryTimes === 0 ? FIRST_RECONNECT_TIME : SHORT_RETRY_TIME;
62
73
 
63
74
  // Recover api after retry timeout
64
75
  const timeout = setTimeout(() => {
@@ -77,6 +88,9 @@ class AbstractChainHandler {
77
88
  timeout
78
89
  };
79
90
  }
91
+ isRecovering(chain) {
92
+ return !!this.recoverMap[chain];
93
+ }
80
94
  cancelRecover(chain) {
81
95
  const retryRecord = this.recoverMap[chain];
82
96
  if (retryRecord) {
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.EvmApi = void 0;
8
8
  require("@polkadot/types-augment");
9
+ var _types = require("@subwallet/extension-base/services/chain-service/types");
9
10
  var _promise = require("@subwallet/extension-base/utils/promise");
10
11
  var _rxjs = require("rxjs");
11
12
  var _web = _interopRequireDefault(require("web3"));
@@ -15,15 +16,23 @@ var _web = _interopRequireDefault(require("web3"));
15
16
  class EvmApi {
16
17
  apiRetry = 0;
17
18
  isApiConnectedSubject = new _rxjs.BehaviorSubject(false);
19
+ connectionStatusSubject = new _rxjs.BehaviorSubject(_types._ChainConnectionStatus.DISCONNECTED);
18
20
  isApiReady = false;
19
21
  isApiReadyOnce = false;
20
22
  get isApiConnected() {
21
23
  return this.isApiConnectedSubject.getValue();
22
24
  }
23
- updateConnectedStatus(isConnected) {
25
+ get connectionStatus() {
26
+ return this.connectionStatusSubject.getValue();
27
+ }
28
+ updateConnectionStatus(status) {
29
+ const isConnected = status === _types._ChainConnectionStatus.CONNECTED;
24
30
  if (isConnected !== this.isApiConnectedSubject.value) {
25
31
  this.isApiConnectedSubject.next(isConnected);
26
32
  }
33
+ if (status !== this.connectionStatusSubject.value) {
34
+ this.connectionStatusSubject.next(status);
35
+ }
27
36
  }
28
37
  get isReady() {
29
38
  return this.isReadyHandler.promise;
@@ -80,6 +89,7 @@ class EvmApi {
80
89
  // For websocket provider, connect it
81
90
  const wsProvider = this.provider;
82
91
  wsProvider.connect && wsProvider.connect();
92
+ this.updateConnectionStatus(_types._ChainConnectionStatus.CONNECTING);
83
93
  // Check if api is ready
84
94
  this.api.eth.net.isListening().then(() => {
85
95
  this.isApiReadyOnce = true;
@@ -88,7 +98,7 @@ class EvmApi {
88
98
  this.isApiReadyOnce = false;
89
99
  this.isApiReady = false;
90
100
  this.isReadyHandler.reject(error);
91
- this.updateConnectedStatus(false);
101
+ this.updateConnectionStatus(_types._ChainConnectionStatus.DISCONNECTED);
92
102
  console.warn(`Can not connect to ${this.chainSlug} (EVM) at ${this.apiUrl}`);
93
103
  });
94
104
 
@@ -102,7 +112,7 @@ class EvmApi {
102
112
  // For websocket provider, disconnect it
103
113
  const wsProvider = this.provider;
104
114
  wsProvider.disconnect && wsProvider.disconnect();
105
- this.updateConnectedStatus(false);
115
+ this.updateConnectionStatus(_types._ChainConnectionStatus.DISCONNECTED);
106
116
  return Promise.resolve();
107
117
  }
108
118
  destroy() {
@@ -117,10 +127,10 @@ class EvmApi {
117
127
  this.isReadyHandler.resolve(this);
118
128
  }
119
129
  }
120
- this.updateConnectedStatus(true);
130
+ this.updateConnectionStatus(_types._ChainConnectionStatus.CONNECTED);
121
131
  }
122
132
  onDisconnect() {
123
- this.updateConnectedStatus(false);
133
+ this.updateConnectionStatus(_types._ChainConnectionStatus.DISCONNECTED);
124
134
  if (this.isApiConnected) {
125
135
  console.warn(`Disconnected from ${this.chainSlug} of ${this.apiUrl} (EVM)`);
126
136
  this.isApiReady = false;
@@ -46,8 +46,8 @@ class EvmChainHandler extends _AbstractChainHandler.AbstractChainHandler {
46
46
  const apiObject = new _EvmApi2.EvmApi(chainSlug, apiUrl, {
47
47
  providerName
48
48
  });
49
- apiObject.isApiConnectedSubject.subscribe(this.handleConnect.bind(this, chainSlug));
50
- apiObject.isApiConnectedSubject.subscribe(onUpdateStatus);
49
+ apiObject.connectionStatusSubject.subscribe(this.handleConnection.bind(this, chainSlug));
50
+ apiObject.connectionStatusSubject.subscribe(onUpdateStatus);
51
51
  return Promise.resolve(apiObject);
52
52
  }
53
53
  async recoverApi(chainSlug) {
@@ -10,6 +10,7 @@ var _types = require("@oak-foundation/types");
10
10
  var _constants = require("@subwallet/extension-base/services/chain-service/constants");
11
11
  var _lightClient = require("@subwallet/extension-base/services/chain-service/handler/light-client");
12
12
  var _SubstrateChainHandler = require("@subwallet/extension-base/services/chain-service/handler/SubstrateChainHandler");
13
+ var _types2 = require("@subwallet/extension-base/services/chain-service/types");
13
14
  var _promise = require("@subwallet/extension-base/utils/promise");
14
15
  var _availJsSdk = require("avail-js-sdk");
15
16
  var _rxjs = require("rxjs");
@@ -26,13 +27,22 @@ class SubstrateApi {
26
27
  isApiReady = false;
27
28
  isApiReadyOnce = false;
28
29
  isApiConnectedSubject = new _rxjs.BehaviorSubject(false);
30
+ connectionStatusSubject = new _rxjs.BehaviorSubject(_types2._ChainConnectionStatus.DISCONNECTED);
29
31
  get isApiConnected() {
30
32
  return this.isApiConnectedSubject.getValue();
31
33
  }
32
- updateConnectedStatus(isConnected) {
34
+ substrateRetry = 0;
35
+ get connectionStatus() {
36
+ return this.connectionStatusSubject.getValue();
37
+ }
38
+ updateConnectionStatus(status) {
39
+ const isConnected = status === _types2._ChainConnectionStatus.CONNECTED;
33
40
  if (isConnected !== this.isApiConnectedSubject.value) {
34
41
  this.isApiConnectedSubject.next(isConnected);
35
42
  }
43
+ if (status !== this.connectionStatusSubject.value) {
44
+ this.connectionStatusSubject.next(status);
45
+ }
36
46
  }
37
47
  specName = '';
38
48
  specVersion = '';
@@ -60,12 +70,14 @@ class SubstrateApi {
60
70
  [`${metadata.genesisHash}-${metadata.specVersion}`]: metadata.hexValue
61
71
  };
62
72
  }
73
+ this.updateConnectionStatus(_types2._ChainConnectionStatus.CONNECTING);
74
+ let api;
63
75
  if (_constants._API_OPTIONS_CHAIN_GROUP.acala.includes(this.chainSlug)) {
64
- return new _api2.ApiPromise((0, _api.options)({
76
+ api = new _api2.ApiPromise((0, _api.options)({
65
77
  provider
66
78
  }));
67
79
  } else if (_constants._API_OPTIONS_CHAIN_GROUP.turing.includes(this.chainSlug)) {
68
- return new _api2.ApiPromise({
80
+ api = new _api2.ApiPromise({
69
81
  provider,
70
82
  rpc: _types.rpc,
71
83
  types: _types.types
@@ -78,8 +90,13 @@ class SubstrateApi {
78
90
  signedExtensions: _availJsSdk.spec.signedExtensions
79
91
  });
80
92
  } else {
81
- return new _api2.ApiPromise(apiOption);
93
+ api = new _api2.ApiPromise(apiOption);
82
94
  }
95
+ api.on('ready', this.onReady.bind(this));
96
+ api.on('connected', this.onConnect.bind(this));
97
+ api.on('disconnected', this.onDisconnect.bind(this));
98
+ api.on('error', this.onError.bind(this));
99
+ return api;
83
100
  }
84
101
  constructor(chainSlug, apiUrl) {
85
102
  let {
@@ -95,10 +112,6 @@ class SubstrateApi {
95
112
  this.provider = this.createProvider(apiUrl);
96
113
  this.api = externalApiPromise || this.createApi(this.provider);
97
114
  this.handleApiReady = (0, _promise.createPromiseHandler)();
98
- this.api.on('ready', this.onReady.bind(this));
99
- this.api.on('connected', this.onConnect.bind(this));
100
- this.api.on('disconnected', this.onDisconnect.bind(this));
101
- this.api.on('error', this.onError.bind(this));
102
115
  }
103
116
  get isReady() {
104
117
  return this.handleApiReady.promise;
@@ -120,17 +133,16 @@ class SubstrateApi {
120
133
  this.apiUrl = apiUrl;
121
134
  this.provider = this.createProvider(apiUrl);
122
135
  this.api = this.createApi(this.provider);
123
- this.api.on('ready', this.onReady.bind(this));
124
- this.api.on('connected', this.onConnect.bind(this));
125
- this.api.on('disconnected', this.onDisconnect.bind(this));
126
- this.api.on('error', this.onError.bind(this));
127
136
  }
128
137
  connect() {
129
138
  if (this.api.isConnected) {
130
- this.updateConnectedStatus(true);
139
+ this.updateConnectionStatus(_types2._ChainConnectionStatus.CONNECTED);
131
140
  } else {
141
+ this.updateConnectionStatus(_types2._ChainConnectionStatus.CONNECTING);
132
142
  this.api.connect().then(() => {
133
- this.updateConnectedStatus(true);
143
+ this.api.isReady.then(() => {
144
+ this.updateConnectionStatus(_types2._ChainConnectionStatus.CONNECTED);
145
+ }).catch(console.error);
134
146
  }).catch(console.error);
135
147
  }
136
148
  }
@@ -140,7 +152,7 @@ class SubstrateApi {
140
152
  } catch (e) {
141
153
  console.error(e);
142
154
  }
143
- this.updateConnectedStatus(false);
155
+ this.updateConnectionStatus(_types2._ChainConnectionStatus.DISCONNECTED);
144
156
  }
145
157
  async recoverConnect() {
146
158
  await this.disconnect();
@@ -162,7 +174,8 @@ class SubstrateApi {
162
174
  });
163
175
  }
164
176
  onConnect() {
165
- this.updateConnectedStatus(true);
177
+ this.updateConnectionStatus(_types2._ChainConnectionStatus.CONNECTED);
178
+ this.substrateRetry = 0;
166
179
  console.log(`Connected to ${this.chainSlug || ''} at ${this.apiUrl}`);
167
180
  if (this.isApiReadyOnce) {
168
181
  this.handleApiReady.resolve(this);
@@ -171,8 +184,14 @@ class SubstrateApi {
171
184
  onDisconnect() {
172
185
  this.isApiReady = false;
173
186
  console.log(`Disconnected from ${this.chainSlug} at ${this.apiUrl}`);
174
- this.updateConnectedStatus(false);
187
+ this.updateConnectionStatus(_types2._ChainConnectionStatus.DISCONNECTED);
175
188
  this.handleApiReady = (0, _promise.createPromiseHandler)();
189
+ this.substrateRetry += 1;
190
+ if (this.substrateRetry > 9) {
191
+ this.disconnect().then(() => {
192
+ this.updateConnectionStatus(_types2._ChainConnectionStatus.UNSTABLE);
193
+ }).catch(console.error);
194
+ }
176
195
  }
177
196
  onError(e) {
178
197
  console.warn(`${this.chainSlug} connection got error`, e);
@@ -41,12 +41,12 @@ class SubstrateChainHandler extends _AbstractChainHandler.AbstractChainHandler {
41
41
 
42
42
  // Not found substrateInterface mean it active with evm interface
43
43
  if (api) {
44
- api === null || api === void 0 ? void 0 : api.connect();
44
+ api.connect();
45
45
  if (!api.useLightClient) {
46
46
  // Manual fire handle connect to avoid some chain can not reconnect
47
47
  setTimeout(() => {
48
- this.handleConnect(chain, api.isApiConnected);
49
- }, _AbstractChainHandler.SHORT_RETRY_TIME);
48
+ this.handleConnection(chain, api.connectionStatus);
49
+ }, 10000);
50
50
  }
51
51
  }
52
52
  }
@@ -202,8 +202,8 @@ class SubstrateChainHandler extends _AbstractChainHandler.AbstractChainHandler {
202
202
  metadata,
203
203
  externalApiPromise
204
204
  });
205
- apiObject.isApiConnectedSubject.subscribe(this.handleConnect.bind(this, chainSlug));
206
- onUpdateStatus && apiObject.isApiConnectedSubject.subscribe(onUpdateStatus);
205
+ apiObject.connectionStatusSubject.subscribe(this.handleConnection.bind(this, chainSlug));
206
+ onUpdateStatus && apiObject.connectionStatusSubject.subscribe(onUpdateStatus);
207
207
 
208
208
  // Update metadata to database with async methods
209
209
  apiObject.isReady.then(api => {