@subwallet/extension-base 1.2.15-0 → 1.2.17-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.
Files changed (65) hide show
  1. package/background/KoniTypes.d.ts +6 -1
  2. package/cjs/constants/staking.js +2 -1
  3. package/cjs/koni/api/staking/bonding/utils.js +15 -0
  4. package/cjs/koni/background/handlers/Extension.js +33 -7
  5. package/cjs/koni/background/handlers/State.js +11 -1
  6. package/cjs/packageInfo.js +1 -1
  7. package/cjs/services/balance-service/helpers/subscribe/index.js +1 -1
  8. package/cjs/services/balance-service/helpers/subscribe/substrate/gear.js +135 -0
  9. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +9 -62
  10. package/cjs/services/balance-service/transfer/token.js +4 -3
  11. package/cjs/services/chain-service/handler/SubstrateApi.js +3 -1
  12. package/cjs/services/chain-service/handler/SubstrateChainHandler.js +21 -26
  13. package/cjs/services/chain-service/index.js +48 -3
  14. package/cjs/services/chain-service/types.js +1 -1
  15. package/cjs/services/chain-service/utils/index.js +18 -12
  16. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +38 -4
  17. package/cjs/services/earning-service/service.js +3 -0
  18. package/cjs/services/migration-service/scripts/databases/ClearMetadataDatabase.js +16 -0
  19. package/cjs/services/migration-service/scripts/index.js +7 -7
  20. package/cjs/services/transaction-service/index.js +12 -7
  21. package/cjs/utils/gear/combine.js +28 -0
  22. package/cjs/utils/gear/grc20.js +56 -49
  23. package/cjs/utils/gear/index.js +22 -0
  24. package/cjs/utils/gear/vft.js +173 -0
  25. package/cjs/utils/metadata.js +45 -34
  26. package/constants/staking.js +2 -1
  27. package/koni/api/staking/bonding/utils.d.ts +1 -0
  28. package/koni/api/staking/bonding/utils.js +14 -0
  29. package/koni/background/handlers/Extension.d.ts +2 -0
  30. package/koni/background/handlers/Extension.js +25 -1
  31. package/koni/background/handlers/State.d.ts +2 -0
  32. package/koni/background/handlers/State.js +11 -1
  33. package/package.json +24 -8
  34. package/packageInfo.js +1 -1
  35. package/services/balance-service/helpers/subscribe/index.js +1 -1
  36. package/services/balance-service/helpers/subscribe/substrate/gear.d.ts +4 -0
  37. package/services/balance-service/helpers/subscribe/substrate/gear.js +123 -0
  38. package/services/balance-service/helpers/subscribe/substrate/index.js +10 -61
  39. package/services/balance-service/transfer/token.js +5 -4
  40. package/services/chain-service/handler/SubstrateApi.d.ts +1 -1
  41. package/services/chain-service/handler/SubstrateApi.js +3 -1
  42. package/services/chain-service/handler/SubstrateChainHandler.d.ts +1 -0
  43. package/services/chain-service/handler/SubstrateChainHandler.js +22 -27
  44. package/services/chain-service/index.d.ts +4 -0
  45. package/services/chain-service/index.js +49 -4
  46. package/services/chain-service/types.d.ts +1 -0
  47. package/services/chain-service/types.js +1 -1
  48. package/services/chain-service/utils/index.d.ts +1 -0
  49. package/services/chain-service/utils/index.js +16 -12
  50. package/services/earning-service/handlers/native-staking/relay-chain.js +39 -5
  51. package/services/earning-service/service.js +3 -0
  52. package/services/migration-service/scripts/databases/ClearMetadataDatabase.js +16 -0
  53. package/services/migration-service/scripts/index.js +7 -7
  54. package/services/transaction-service/index.js +13 -8
  55. package/types/metadata.d.ts +9 -2
  56. package/utils/gear/combine.d.ts +10 -0
  57. package/utils/gear/combine.js +18 -0
  58. package/utils/gear/grc20.d.ts +18 -20
  59. package/utils/gear/grc20.js +53 -45
  60. package/utils/gear/index.d.ts +2 -0
  61. package/utils/gear/index.js +3 -1
  62. package/utils/gear/vft.d.ts +36 -0
  63. package/utils/gear/vft.js +162 -0
  64. package/utils/metadata.d.ts +7 -2
  65. package/utils/metadata.js +41 -31
@@ -1,7 +1,6 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-base
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- import { GearApi } from '@gear-js/api';
5
4
  import { _AssetType } from '@subwallet/chain-list/types';
6
5
  import { APIItemState } from '@subwallet/extension-base/background/KoniTypes';
7
6
  import { SUB_TOKEN_REFRESH_BALANCE_INTERVAL } from '@subwallet/extension-base/constants';
@@ -12,13 +11,13 @@ import { getPSP22ContractPromise } from '@subwallet/extension-base/koni/api/cont
12
11
  import { getDefaultWeightV2 } from '@subwallet/extension-base/koni/api/contract-handler/wasm/utils';
13
12
  import { _BALANCE_CHAIN_GROUP, _MANTA_ZK_CHAIN_GROUP, _ZK_ASSET_PREFIX } from '@subwallet/extension-base/services/chain-service/constants';
14
13
  import { _checkSmartContractSupportByChain, _getChainExistentialDeposit, _getChainNativeTokenSlug, _getContractAddressOfToken, _getTokenOnChainAssetId, _getTokenOnChainInfo, _getTokenTypesSupportedByChain, _getXcmAssetMultilocation, _isBridgedToken, _isChainEvmCompatible, _isSubstrateRelayChain } from '@subwallet/extension-base/services/chain-service/utils';
15
- import { filterAssetsByChainAndType, getGRC20ContractPromise } from '@subwallet/extension-base/utils';
14
+ import { filterAssetsByChainAndType } from '@subwallet/extension-base/utils';
16
15
  import BigN from 'bignumber.js';
17
16
  import { combineLatest, Observable } from 'rxjs';
18
- import { BN, BN_ZERO, noop, u8aToHex } from '@polkadot/util';
19
- import { decodeAddress } from '@polkadot/util-crypto';
17
+ import { BN, BN_ZERO } from '@polkadot/util';
20
18
  import { subscribeERC20Interval } from "../evm.js";
21
19
  import { subscribeEquilibriumTokenBalance } from "./equilibrium.js";
20
+ import { subscribeGRC20Balance, subscribeVftBalance } from "./gear.js";
22
21
  export const subscribeSubstrateBalance = async (addresses, chainInfo, assetMap, substrateApi, evmApi, callback, extrinsicType) => {
23
22
  let unsubNativeToken;
24
23
  let unsubLocalToken;
@@ -26,6 +25,7 @@ export const subscribeSubstrateBalance = async (addresses, chainInfo, assetMap,
26
25
  let unsubWasmContractToken;
27
26
  let unsubBridgedToken;
28
27
  let unsubGrcToken;
28
+ let unsubVftToken;
29
29
  const chain = chainInfo.slug;
30
30
  const baseParams = {
31
31
  addresses,
@@ -82,17 +82,22 @@ export const subscribeSubstrateBalance = async (addresses, chainInfo, assetMap,
82
82
  // Get sub-token for substrate-based chains
83
83
  unsubGrcToken = subscribeGRC20Balance(substrateParams);
84
84
  }
85
+ if (_checkSmartContractSupportByChain(chainInfo, _AssetType.VFT)) {
86
+ // Get sub-token for substrate-based chains
87
+ unsubVftToken = subscribeVftBalance(substrateParams);
88
+ }
85
89
  } catch (err) {
86
90
  console.warn(err);
87
91
  }
88
92
  return () => {
89
- var _unsubGrcToken;
93
+ var _unsubGrcToken, _unsubVftToken;
90
94
  unsubNativeToken && unsubNativeToken();
91
95
  unsubLocalToken && unsubLocalToken();
92
96
  unsubEvmContractToken && unsubEvmContractToken();
93
97
  unsubWasmContractToken && unsubWasmContractToken();
94
98
  unsubBridgedToken && unsubBridgedToken();
95
99
  (_unsubGrcToken = unsubGrcToken) === null || _unsubGrcToken === void 0 ? void 0 : _unsubGrcToken();
100
+ (_unsubVftToken = unsubVftToken) === null || _unsubVftToken === void 0 ? void 0 : _unsubVftToken();
96
101
  };
97
102
  };
98
103
 
@@ -421,60 +426,4 @@ const subscribeOrmlTokensPallet = async ({
421
426
  }).catch(console.error);
422
427
  });
423
428
  };
424
- };
425
- const subscribeGRC20Balance = ({
426
- addresses,
427
- assetMap,
428
- callback,
429
- chainInfo,
430
- substrateApi
431
- }) => {
432
- if (!(substrateApi instanceof GearApi)) {
433
- console.warn('Cannot subscribe VFT balance without GearApi instance');
434
- return noop;
435
- }
436
- const chain = chainInfo.slug;
437
- const psp22ContractMap = {};
438
- const tokenList = filterAssetsByChainAndType(assetMap, chain, [_AssetType.GRC20]);
439
- Object.entries(tokenList).forEach(([slug, tokenInfo]) => {
440
- psp22ContractMap[slug] = getGRC20ContractPromise(substrateApi, _getContractAddressOfToken(tokenInfo));
441
- });
442
- const getTokenBalances = () => {
443
- Object.values(tokenList).map(async tokenInfo => {
444
- try {
445
- const contract = psp22ContractMap[tokenInfo.slug];
446
- const balances = await Promise.all(addresses.map(async address => {
447
- try {
448
- const actor = u8aToHex(decodeAddress(address));
449
- const _balanceOf = await contract.balanceOf(actor, address);
450
- return {
451
- address: address,
452
- tokenSlug: tokenInfo.slug,
453
- free: _balanceOf.toString(10),
454
- locked: '0',
455
- state: APIItemState.READY
456
- };
457
- } catch (err) {
458
- console.error(`Error on get balance of account ${address} for token ${tokenInfo.slug}`, err);
459
- return {
460
- address: address,
461
- tokenSlug: tokenInfo.slug,
462
- free: '0',
463
- locked: '0',
464
- state: APIItemState.READY
465
- };
466
- }
467
- }));
468
- callback(balances);
469
- } catch (err) {
470
- console.warn(tokenInfo.slug, err); // TODO: error createType
471
- }
472
- });
473
- };
474
-
475
- getTokenBalances();
476
- const interval = setInterval(getTokenBalances, SUB_TOKEN_REFRESH_BALANCE_INTERVAL);
477
- return () => {
478
- clearInterval(interval);
479
- };
480
429
  };
@@ -2,12 +2,13 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { GearApi } from '@gear-js/api';
5
+ import { _AssetType } from '@subwallet/chain-list/types';
5
6
  import { getPSP22ContractPromise } from '@subwallet/extension-base/koni/api/contract-handler/wasm';
6
7
  import { getWasmContractGasLimit } from '@subwallet/extension-base/koni/api/contract-handler/wasm/utils';
7
8
  import { _TRANSFER_CHAIN_GROUP } from '@subwallet/extension-base/services/chain-service/constants';
8
9
  import { _getContractAddressOfToken, _getTokenOnChainAssetId, _getTokenOnChainInfo, _getXcmAssetMultilocation, _isBridgedToken, _isChainEvmCompatible, _isNativeToken, _isTokenGearSmartContract, _isTokenTransferredByEvm, _isTokenWasmSmartContract } from '@subwallet/extension-base/services/chain-service/utils';
9
10
  import { calculateGasFeeParams } from '@subwallet/extension-base/services/fee-service/utils';
10
- import { getGRC20ContractPromise } from '@subwallet/extension-base/utils';
11
+ import { getGRC20ContractPromise, getVFTContractPromise } from '@subwallet/extension-base/utils';
11
12
  import BigN from 'bignumber.js';
12
13
  import { BN, u8aToHex } from '@polkadot/util';
13
14
  import { decodeAddress } from '@polkadot/util-crypto';
@@ -53,12 +54,12 @@ export const createTransferExtrinsic = async ({
53
54
  }, to, value, {});
54
55
  transferAmount = value;
55
56
  } else if (_isTokenGearSmartContract(tokenInfo) && api instanceof GearApi) {
56
- const contractPromise = getGRC20ContractPromise(api, _getContractAddressOfToken(tokenInfo));
57
- const transaction = await contractPromise.transfer(u8aToHex(decodeAddress(to)), BigInt(value)) // Create transfer transaction
57
+ const contractPromise = tokenInfo.assetType === _AssetType.GRC20 ? getGRC20ContractPromise(api, _getContractAddressOfToken(tokenInfo)) : getVFTContractPromise(api, _getContractAddressOfToken(tokenInfo));
58
+ const transaction = await contractPromise.service.transfer(u8aToHex(decodeAddress(to)), value) // Create transfer transaction
58
59
  .withAccount(from) // Set sender account
59
60
  .calculateGas(); // Add account arg to extrinsic
60
61
 
61
- transfer = transaction.tx;
62
+ transfer = transaction.extrinsic;
62
63
  transferAmount = value;
63
64
  } else if (_TRANSFER_CHAIN_GROUP.acala.includes(networkKey)) {
64
65
  if (!_isNativeToken(tokenInfo)) {
@@ -39,7 +39,7 @@ export declare class SubstrateApi implements _SubstrateApi {
39
39
  constructor(chainSlug: string, apiUrl: string, { externalApiPromise, metadata, providerName }?: _ApiOptions);
40
40
  get isReady(): Promise<_SubstrateApi>;
41
41
  updateApiUrl(apiUrl: string): Promise<void>;
42
- connect(): void;
42
+ connect(_callbackUpdateMetadata?: (substrateApi: _SubstrateApi) => void): void;
43
43
  disconnect(): Promise<void>;
44
44
  recoverConnect(): Promise<void>;
45
45
  destroy(): Promise<void>;
@@ -159,14 +159,16 @@ export class SubstrateApi {
159
159
  this.provider = this.createProvider(apiUrl);
160
160
  this.api = this.createApi(this.provider);
161
161
  }
162
- connect() {
162
+ connect(_callbackUpdateMetadata) {
163
163
  if (this.api.isConnected) {
164
164
  this.updateConnectionStatus(_ChainConnectionStatus.CONNECTED);
165
+ _callbackUpdateMetadata === null || _callbackUpdateMetadata === void 0 ? void 0 : _callbackUpdateMetadata(this);
165
166
  } else {
166
167
  this.updateConnectionStatus(_ChainConnectionStatus.CONNECTING);
167
168
  this.api.connect().then(() => {
168
169
  this.api.isReady.then(() => {
169
170
  this.updateConnectionStatus(_ChainConnectionStatus.CONNECTED);
171
+ _callbackUpdateMetadata === null || _callbackUpdateMetadata === void 0 ? void 0 : _callbackUpdateMetadata(this);
170
172
  }).catch(console.error);
171
173
  }).catch(console.error);
172
174
  }
@@ -19,6 +19,7 @@ export declare class SubstrateChainHandler extends AbstractChainHandler {
19
19
  private getPsp22TokenInfo;
20
20
  private getPsp34TokenInfo;
21
21
  private getGrc20TokenInfo;
22
+ private getVftTokenInfo;
22
23
  getSubstrateContractTokenInfo(contractAddress: string, tokenType: _AssetType, originChain: string, contractCaller?: string): Promise<_SmartContractTokenInfo>;
23
24
  setSubstrateApi(chainSlug: string, substrateApi: SubstrateApi): void;
24
25
  destroySubstrateApi(chainSlug: string): void;
@@ -6,9 +6,8 @@ import { _AssetType } from '@subwallet/chain-list/types';
6
6
  import { getDefaultWeightV2 } from '@subwallet/extension-base/koni/api/contract-handler/wasm/utils';
7
7
  import { AbstractChainHandler } from '@subwallet/extension-base/services/chain-service/handler/AbstractChainHandler';
8
8
  import { SubstrateApi } from '@subwallet/extension-base/services/chain-service/handler/SubstrateApi';
9
- import { DEFAULT_GEAR_ADDRESS, getGRC20ContractPromise } from '@subwallet/extension-base/utils';
9
+ import { cacheMetadata, GEAR_DEFAULT_ADDRESS, getGRC20ContractPromise, getVFTContractPromise } from '@subwallet/extension-base/utils';
10
10
  import { ContractPromise } from '@polkadot/api-contract';
11
- import { getSpecExtensions, getSpecTypes } from '@polkadot/types-known';
12
11
  import { BN } from '@polkadot/util';
13
12
  import { logger as createLogger } from '@polkadot/util/logger';
14
13
  import { _PSP22_ABI, _PSP34_ABI } from "../../../koni/api/contract-handler/utils/index.js";
@@ -137,12 +136,26 @@ export class SubstrateChainHandler extends AbstractChainHandler {
137
136
  }
138
137
  async getGrc20TokenInfo(apiPromise, contractAddress) {
139
138
  if (!(apiPromise instanceof GearApi)) {
140
- console.warn('Cannot subscribe VFT balance without GearApi instance');
139
+ console.warn('Cannot subscribe GRC20 balance without GearApi instance');
141
140
  return ['', -1, '', true];
142
141
  }
143
142
  let contractError = false;
144
143
  const tokenContract = getGRC20ContractPromise(apiPromise, contractAddress);
145
- const [nameRes, symbolRes, decimalsRes] = await Promise.all([tokenContract.name(DEFAULT_GEAR_ADDRESS.ALICE), tokenContract.symbol(DEFAULT_GEAR_ADDRESS.ALICE), tokenContract.decimals(DEFAULT_GEAR_ADDRESS.ALICE)]);
144
+ const [nameRes, symbolRes, decimalsRes] = await Promise.all([tokenContract.service.name(GEAR_DEFAULT_ADDRESS), tokenContract.service.symbol(GEAR_DEFAULT_ADDRESS), tokenContract.service.decimals(GEAR_DEFAULT_ADDRESS)]);
145
+ const decimals = typeof decimalsRes === 'string' ? parseInt(decimalsRes) : decimalsRes;
146
+ if (!nameRes || !symbolRes) {
147
+ contractError = true;
148
+ }
149
+ return [nameRes, decimals, symbolRes, contractError];
150
+ }
151
+ async getVftTokenInfo(apiPromise, contractAddress) {
152
+ if (!(apiPromise instanceof GearApi)) {
153
+ console.warn('Cannot subscribe VFT balance without GearApi instance');
154
+ return ['', -1, '', true];
155
+ }
156
+ let contractError = false;
157
+ const tokenContract = getVFTContractPromise(apiPromise, contractAddress);
158
+ const [nameRes, symbolRes, decimalsRes] = await Promise.all([tokenContract.service.name(GEAR_DEFAULT_ADDRESS), tokenContract.service.symbol(GEAR_DEFAULT_ADDRESS), tokenContract.service.decimals(GEAR_DEFAULT_ADDRESS)]);
146
159
  const decimals = typeof decimalsRes === 'string' ? parseInt(decimalsRes) : decimalsRes;
147
160
  if (!nameRes || !symbolRes) {
148
161
  contractError = true;
@@ -168,6 +181,9 @@ export class SubstrateChainHandler extends AbstractChainHandler {
168
181
  case _AssetType.GRC20:
169
182
  [name, decimals, symbol, contractError] = await this.getGrc20TokenInfo(apiPromise, contractAddress);
170
183
  break;
184
+ case _AssetType.VFT:
185
+ [name, decimals, symbol, contractError] = await this.getVftTokenInfo(apiPromise, contractAddress);
186
+ break;
171
187
  }
172
188
  return {
173
189
  name,
@@ -199,31 +215,9 @@ export class SubstrateChainHandler extends AbstractChainHandler {
199
215
  } = {}) {
200
216
  var _this$parent2;
201
217
  const existed = this.substrateApiMap[chainSlug];
202
- const metadata = await ((_this$parent2 = this.parent) === null || _this$parent2 === void 0 ? void 0 : _this$parent2.getMetadata(chainSlug));
203
218
  const updateMetadata = substrateApi => {
204
219
  // Update metadata to database with async methods
205
- substrateApi.api.isReady.then(async api => {
206
- var _this$parent3;
207
- const currentSpecVersion = api.runtimeVersion.specVersion.toString();
208
- const genesisHash = api.genesisHash.toHex();
209
-
210
- // Avoid date existed metadata
211
- if (metadata && metadata.specVersion === currentSpecVersion && metadata.genesisHash === genesisHash) {
212
- return;
213
- }
214
- const systemChain = await api.rpc.system.chain();
215
- // const _metadata: Option<OpaqueMetadata> = await api.call.metadata.metadataAtVersion(15);
216
- // const metadataHex = _metadata.isSome ? _metadata.unwrap().toHex().slice(2) : ''; // Need unwrap to create metadata object
217
-
218
- (_this$parent3 = this.parent) === null || _this$parent3 === void 0 ? void 0 : _this$parent3.upsertMetadata(chainSlug, {
219
- chain: chainSlug,
220
- genesisHash: genesisHash,
221
- specVersion: currentSpecVersion,
222
- hexValue: api.runtimeMetadata.toHex(),
223
- types: getSpecTypes(api.registry, systemChain, api.runtimeVersion.specName, api.runtimeVersion.specVersion),
224
- userExtensions: getSpecExtensions(api.registry, systemChain, api.runtimeVersion.specName)
225
- }).catch(console.error);
226
- }).catch(console.error);
220
+ cacheMetadata(chainSlug, substrateApi, this.parent);
227
221
  };
228
222
 
229
223
  // Return existed to avoid re-init metadata
@@ -237,6 +231,7 @@ export class SubstrateChainHandler extends AbstractChainHandler {
237
231
  updateMetadata(existed);
238
232
  return existed;
239
233
  }
234
+ const metadata = await ((_this$parent2 = this.parent) === null || _this$parent2 === void 0 ? void 0 : _this$parent2.getMetadata(chainSlug));
240
235
  const apiObject = new SubstrateApi(chainSlug, apiUrl, {
241
236
  providerName,
242
237
  metadata,
@@ -7,6 +7,7 @@ import { EventService } from '@subwallet/extension-base/services/event-service';
7
7
  import { IMetadataItem } from '@subwallet/extension-base/services/storage-service/databases';
8
8
  import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService';
9
9
  import { BehaviorSubject, Subject } from 'rxjs';
10
+ import { ExtraInfo } from '@polkadot-api/merkleize-metadata';
10
11
  export declare class ChainService {
11
12
  private dataMap;
12
13
  private dbService;
@@ -141,6 +142,9 @@ export declare class ChainService {
141
142
  getMetadata(chain: string): import("dexie").PromiseExtended<IMetadataItem | undefined>;
142
143
  upsertMetadata(chain: string, metadata: IMetadataItem): import("dexie").PromiseExtended<unknown>;
143
144
  getMetadataByHash(hash: string): import("dexie").PromiseExtended<IMetadataItem | undefined>;
145
+ getExtraInfo(chain: string): Omit<ExtraInfo, 'specVersion' | 'specName'>;
146
+ calculateMetadataHash(chain: string): Promise<string | undefined>;
147
+ shortenMetadata(chain: string, txBlob: string): Promise<string | undefined>;
144
148
  getSubscanChainMap(reverse?: boolean): Record<string, string>;
145
149
  get detectBalanceChainSlugMap(): Record<string, string>;
146
150
  getFeeTokensByChain(chainSlug: string): string[];
@@ -11,14 +11,14 @@ import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chai
11
11
  import { _ChainConnectionStatus, _CUSTOM_PREFIX, _NFT_CONTRACT_STANDARDS, _SMART_CONTRACT_STANDARDS } from '@subwallet/extension-base/services/chain-service/types';
12
12
  import { _isAssetAutoEnable, _isAssetCanPayTxFee, _isAssetFungibleToken, _isChainEnabled, _isCustomAsset, _isCustomChain, _isCustomProvider, _isEqualContractAddress, _isEqualSmartContractAsset, _isMantaZkAsset, _isPureEvmChain, _isPureSubstrateChain, _parseAssetRefKey, fetchPatchData, randomizeProvider, updateLatestChainInfo } from '@subwallet/extension-base/services/chain-service/utils';
13
13
  import AssetSettingStore from '@subwallet/extension-base/stores/AssetSetting';
14
- import { addLazy, fetchStaticData, filterAssetsByChainAndType, MODULE_SUPPORT } from '@subwallet/extension-base/utils';
14
+ import { addLazy, calculateMetadataHash, fetchStaticData, filterAssetsByChainAndType, getShortMetadata, MODULE_SUPPORT } from '@subwallet/extension-base/utils';
15
15
  import { BehaviorSubject, Subject } from 'rxjs';
16
16
  import Web3 from 'web3';
17
17
  import { logger as createLogger } from '@polkadot/util/logger';
18
18
  const filterChainInfoMap = (data, ignoredChains) => {
19
19
  return Object.fromEntries(Object.entries(data).filter(([slug, info]) => !info.bitcoinInfo && !ignoredChains.includes(slug)));
20
20
  };
21
- const ignoredList = ['bevm', 'bevmTest', 'bevm_testnet', 'layerEdge_testnet', 'merlinEvm', 'botanixEvmTest', 'syscoin_evm', 'syscoin_evm_testnet', 'rollux_evm', 'rollux_testnet', 'boolAlpha', 'boolBeta_testnet'];
21
+ const ignoredList = ['bevm', 'bevmTest', 'bevm_testnet', 'layerEdge_testnet', 'merlinEvm', 'botanixEvmTest', 'syscoin_evm', 'syscoin_evm_testnet', 'rollux_evm', 'rollux_testnet', 'boolAlpha', 'boolBeta_testnet', 'core', 'satoshivm', 'satoshivm_testnet'];
22
22
  const filterAssetInfoMap = (chainInfo, assets) => {
23
23
  return Object.fromEntries(Object.entries(assets).filter(([, info]) => chainInfo[info.originChain]));
24
24
  };
@@ -233,7 +233,7 @@ export class ChainService {
233
233
  return Object.entries(this.dataMap.chainStateMap).filter(([, chainState]) => _isChainEnabled(chainState)).map(([key]) => key);
234
234
  }
235
235
  getSupportedSmartContractTypes() {
236
- return [_AssetType.ERC20, _AssetType.ERC721, _AssetType.PSP22, _AssetType.PSP34, _AssetType.GRC20, _AssetType.GRC721];
236
+ return [_AssetType.ERC20, _AssetType.ERC721, _AssetType.PSP22, _AssetType.PSP34, _AssetType.GRC20, _AssetType.GRC721, _AssetType.VFT];
237
237
  }
238
238
  getActiveChainInfoMap() {
239
239
  const result = {};
@@ -1449,7 +1449,7 @@ export class ChainService {
1449
1449
  async getSmartContractTokenInfo(contractAddress, tokenType, originChain, contractCaller) {
1450
1450
  if ([_AssetType.ERC721, _AssetType.ERC20].includes(tokenType)) {
1451
1451
  return await this.evmChainHandler.getEvmContractTokenInfo(contractAddress, tokenType, originChain);
1452
- } else if ([_AssetType.PSP34, _AssetType.PSP22, _AssetType.GRC20].includes(tokenType)) {
1452
+ } else if ([_AssetType.PSP34, _AssetType.PSP22, _AssetType.GRC20, _AssetType.VFT].includes(tokenType)) {
1453
1453
  return await this.substrateChainHandler.getSubstrateContractTokenInfo(contractAddress, tokenType, originChain, contractCaller);
1454
1454
  }
1455
1455
  return {
@@ -1667,6 +1667,9 @@ export class ChainService {
1667
1667
  this.deleteCustomAssets(customToken);
1668
1668
  }
1669
1669
  }
1670
+
1671
+ /* Metadata */
1672
+
1670
1673
  getMetadata(chain) {
1671
1674
  return this.dbService.stores.metadata.getMetadata(chain);
1672
1675
  }
@@ -1676,6 +1679,48 @@ export class ChainService {
1676
1679
  getMetadataByHash(hash) {
1677
1680
  return this.dbService.stores.metadata.getMetadataByGenesisHash(hash);
1678
1681
  }
1682
+ getExtraInfo(chain) {
1683
+ var _chainInfo$substrateI2, _chainInfo$substrateI3, _chainInfo$substrateI4, _chainInfo$substrateI5, _chainInfo$substrateI6, _chainInfo$substrateI7;
1684
+ const chainInfo = this.getChainInfoByKey(chain);
1685
+ return {
1686
+ decimals: (_chainInfo$substrateI2 = (_chainInfo$substrateI3 = chainInfo.substrateInfo) === null || _chainInfo$substrateI3 === void 0 ? void 0 : _chainInfo$substrateI3.decimals) !== null && _chainInfo$substrateI2 !== void 0 ? _chainInfo$substrateI2 : 0,
1687
+ tokenSymbol: (_chainInfo$substrateI4 = (_chainInfo$substrateI5 = chainInfo.substrateInfo) === null || _chainInfo$substrateI5 === void 0 ? void 0 : _chainInfo$substrateI5.symbol) !== null && _chainInfo$substrateI4 !== void 0 ? _chainInfo$substrateI4 : 'Unit',
1688
+ base58Prefix: (_chainInfo$substrateI6 = (_chainInfo$substrateI7 = chainInfo.substrateInfo) === null || _chainInfo$substrateI7 === void 0 ? void 0 : _chainInfo$substrateI7.addressPrefix) !== null && _chainInfo$substrateI6 !== void 0 ? _chainInfo$substrateI6 : 42
1689
+ };
1690
+ }
1691
+ async calculateMetadataHash(chain) {
1692
+ const metadata = await this.getMetadata(chain);
1693
+ if (!metadata || !metadata.hexV15) {
1694
+ return undefined;
1695
+ }
1696
+ const extraInfo = this.getExtraInfo(chain);
1697
+ const specVersion = parseInt(metadata.specVersion);
1698
+ const specName = metadata.specName;
1699
+ const hexV15 = metadata.hexV15;
1700
+ return calculateMetadataHash({
1701
+ ...extraInfo,
1702
+ specVersion,
1703
+ specName
1704
+ }, hexV15);
1705
+ }
1706
+ async shortenMetadata(chain, txBlob) {
1707
+ const metadata = await this.getMetadata(chain);
1708
+ if (!metadata || !metadata.hexV15) {
1709
+ return undefined;
1710
+ }
1711
+ const extraInfo = this.getExtraInfo(chain);
1712
+ const specVersion = parseInt(metadata.specVersion);
1713
+ const specName = metadata.specName;
1714
+ const hexV15 = metadata.hexV15;
1715
+ return getShortMetadata(txBlob, {
1716
+ ...extraInfo,
1717
+ specVersion,
1718
+ specName
1719
+ }, hexV15);
1720
+ }
1721
+
1722
+ /* Metadata */
1723
+
1679
1724
  getSubscanChainMap(reverse) {
1680
1725
  const result = {};
1681
1726
  const chainInfoMap = this.getChainInfoMap();
@@ -71,6 +71,7 @@ export interface _SubstrateApiState {
71
71
  export interface _SubstrateApi extends _SubstrateApiState, _ChainBaseApi {
72
72
  api: ApiPromise;
73
73
  isReady: Promise<_SubstrateApi>;
74
+ connect: (_callbackUpdateMetadata?: (substrateApi: _SubstrateApi) => void) => void;
74
75
  specName: string;
75
76
  specVersion: string;
76
77
  systemChain: string;
@@ -12,6 +12,6 @@ export let _ChainConnectionStatus;
12
12
  _ChainConnectionStatus["CONNECTING"] = "CONNECTING";
13
13
  })(_ChainConnectionStatus || (_ChainConnectionStatus = {}));
14
14
  export const _CUSTOM_PREFIX = 'custom-';
15
- export const _FUNGIBLE_CONTRACT_STANDARDS = [_AssetType.ERC20, _AssetType.PSP22, _AssetType.GRC20];
15
+ export const _FUNGIBLE_CONTRACT_STANDARDS = [_AssetType.ERC20, _AssetType.PSP22, _AssetType.GRC20, _AssetType.VFT];
16
16
  export const _NFT_CONTRACT_STANDARDS = [_AssetType.PSP34, _AssetType.ERC721];
17
17
  export const _SMART_CONTRACT_STANDARDS = [..._FUNGIBLE_CONTRACT_STANDARDS, ..._NFT_CONTRACT_STANDARDS];
@@ -48,6 +48,7 @@ export declare function _isChainSupportWasmNft(chainInfo: _ChainInfo): boolean;
48
48
  export declare function _isChainSupportEvmERC20(chainInfo: _ChainInfo): boolean;
49
49
  export declare function _isChainSupportWasmPSP22(chainInfo: _ChainInfo): boolean;
50
50
  export declare function _isChainSupportGRC20(chainInfo: _ChainInfo): boolean;
51
+ export declare function _isChainSupportVFT(chainInfo: _ChainInfo): boolean;
51
52
  export declare const _isSupportOrdinal: (chain: string) => boolean;
52
53
  export declare function _getNftTypesSupportedByChain(chainInfo: _ChainInfo): _AssetType[];
53
54
  export declare function _getTokenTypesSupportedByChain(chainInfo: _ChainInfo): _AssetType[];
@@ -181,6 +181,10 @@ export function _isChainSupportGRC20(chainInfo) {
181
181
  var _chainInfo$substrateI12, _chainInfo$substrateI13;
182
182
  return ((_chainInfo$substrateI12 = chainInfo.substrateInfo) === null || _chainInfo$substrateI12 === void 0 ? void 0 : (_chainInfo$substrateI13 = _chainInfo$substrateI12.supportSmartContract) === null || _chainInfo$substrateI13 === void 0 ? void 0 : _chainInfo$substrateI13.includes(_AssetType.GRC20)) || false;
183
183
  }
184
+ export function _isChainSupportVFT(chainInfo) {
185
+ var _chainInfo$substrateI14, _chainInfo$substrateI15;
186
+ return ((_chainInfo$substrateI14 = chainInfo.substrateInfo) === null || _chainInfo$substrateI14 === void 0 ? void 0 : (_chainInfo$substrateI15 = _chainInfo$substrateI14.supportSmartContract) === null || _chainInfo$substrateI15 === void 0 ? void 0 : _chainInfo$substrateI15.includes(_AssetType.VFT)) || false;
187
+ }
184
188
  export const _isSupportOrdinal = chain => {
185
189
  const chains = ['polkadot', 'astar', 'bifrost_dot', 'moonbeam'];
186
190
  return chains.includes(chain);
@@ -207,7 +211,7 @@ export function _getTokenTypesSupportedByChain(chainInfo) {
207
211
  const result = [];
208
212
  if (chainInfo.substrateInfo && chainInfo.substrateInfo.supportSmartContract) {
209
213
  chainInfo.substrateInfo.supportSmartContract.forEach(assetType => {
210
- if ([_AssetType.PSP22, _AssetType.GRC20].includes(assetType)) {
214
+ if ([_AssetType.PSP22, _AssetType.GRC20, _AssetType.VFT].includes(assetType)) {
211
215
  result.push(assetType);
212
216
  }
213
217
  });
@@ -264,7 +268,7 @@ export function _isAssetSmartContractNft(assetInfo) {
264
268
  return [_AssetType.PSP34, _AssetType.ERC721].includes(assetInfo.assetType);
265
269
  }
266
270
  export function _isTokenGearSmartContract(tokenInfo) {
267
- return [_AssetType.GRC20, _AssetType.GRC721].includes(tokenInfo.assetType);
271
+ return [_AssetType.GRC20, _AssetType.GRC721, _AssetType.VFT].includes(tokenInfo.assetType);
268
272
  }
269
273
  export function _parseAssetRefKey(originTokenSlug, destinationTokenSlug) {
270
274
  return `${originTokenSlug}___${destinationTokenSlug}`;
@@ -296,12 +300,12 @@ export function _isRelayChain(chainInfo) {
296
300
  return _isSubstrateRelayChain(chainInfo) || _isPureEvmChain(chainInfo);
297
301
  }
298
302
  export function _isSubstrateRelayChain(chainInfo) {
299
- var _chainInfo$substrateI14;
300
- return ((_chainInfo$substrateI14 = chainInfo.substrateInfo) === null || _chainInfo$substrateI14 === void 0 ? void 0 : _chainInfo$substrateI14.chainType) === _SubstrateChainType.RELAYCHAIN;
303
+ var _chainInfo$substrateI16;
304
+ return ((_chainInfo$substrateI16 = chainInfo.substrateInfo) === null || _chainInfo$substrateI16 === void 0 ? void 0 : _chainInfo$substrateI16.chainType) === _SubstrateChainType.RELAYCHAIN;
301
305
  }
302
306
  export function _isSubstrateParaChain(chainInfo) {
303
- var _chainInfo$substrateI15;
304
- return chainInfo.substrateInfo !== null && chainInfo.substrateInfo.paraId !== null && ((_chainInfo$substrateI15 = chainInfo.substrateInfo) === null || _chainInfo$substrateI15 === void 0 ? void 0 : _chainInfo$substrateI15.chainType) === _SubstrateChainType.PARACHAIN;
307
+ var _chainInfo$substrateI17;
308
+ return chainInfo.substrateInfo !== null && chainInfo.substrateInfo.paraId !== null && ((_chainInfo$substrateI17 = chainInfo.substrateInfo) === null || _chainInfo$substrateI17 === void 0 ? void 0 : _chainInfo$substrateI17.chainType) === _SubstrateChainType.PARACHAIN;
305
309
  }
306
310
  export function _getEvmAbiExplorer(chainInfo) {
307
311
  var _chainInfo$evmInfo4;
@@ -346,8 +350,8 @@ export function _getBlockExplorerFromChain(chainInfo) {
346
350
  var _chainInfo$evmInfo5;
347
351
  blockExplorer = chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$evmInfo5 = chainInfo.evmInfo) === null || _chainInfo$evmInfo5 === void 0 ? void 0 : _chainInfo$evmInfo5.blockExplorer;
348
352
  } else {
349
- var _chainInfo$substrateI16;
350
- blockExplorer = chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI16 = chainInfo.substrateInfo) === null || _chainInfo$substrateI16 === void 0 ? void 0 : _chainInfo$substrateI16.blockExplorer;
353
+ var _chainInfo$substrateI18;
354
+ blockExplorer = chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI18 = chainInfo.substrateInfo) === null || _chainInfo$substrateI18 === void 0 ? void 0 : _chainInfo$substrateI18.blockExplorer;
351
355
  }
352
356
  if (!blockExplorer) {
353
357
  return undefined;
@@ -373,8 +377,8 @@ export const _isAssetAutoEnable = chainAsset => {
373
377
  return chainAsset.metadata ? !!chainAsset.metadata.autoEnable : false;
374
378
  };
375
379
  export function _getCrowdloanUrlFromChain(chainInfo) {
376
- var _chainInfo$substrateI17;
377
- return (chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI17 = chainInfo.substrateInfo) === null || _chainInfo$substrateI17 === void 0 ? void 0 : _chainInfo$substrateI17.crowdloanUrl) || '';
380
+ var _chainInfo$substrateI19;
381
+ return (chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI19 = chainInfo.substrateInfo) === null || _chainInfo$substrateI19 === void 0 ? void 0 : _chainInfo$substrateI19.crowdloanUrl) || '';
378
382
  }
379
383
  export function _isCustomProvider(providerKey) {
380
384
  return providerKey.startsWith(_CUSTOM_PREFIX);
@@ -410,8 +414,8 @@ export function _isMantaZkAsset(chainAsset) {
410
414
  return _MANTA_ZK_CHAIN_GROUP.includes(chainAsset.originChain) && chainAsset.symbol.startsWith(_ZK_ASSET_PREFIX);
411
415
  }
412
416
  export function _getChainExistentialDeposit(chainInfo) {
413
- var _chainInfo$substrateI18;
414
- return (chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI18 = chainInfo.substrateInfo) === null || _chainInfo$substrateI18 === void 0 ? void 0 : _chainInfo$substrateI18.existentialDeposit) || '0';
417
+ var _chainInfo$substrateI20;
418
+ return (chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI20 = chainInfo.substrateInfo) === null || _chainInfo$substrateI20 === void 0 ? void 0 : _chainInfo$substrateI20.existentialDeposit) || '0';
415
419
  }
416
420
  export function randomizeProvider(providers, excludedKeys) {
417
421
  if (Object.keys(providers).length === 0) {
@@ -3,7 +3,7 @@
3
3
 
4
4
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
5
  import { BasicTxErrorType, ExtrinsicType, StakingTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
6
- import { calculateAlephZeroValidatorReturn, calculateChainStakedReturnV2, calculateInflation, calculateTernoaValidatorReturn, calculateValidatorStakedReturn, getAvgValidatorEraReward, getCommission, getMaxValidatorErrorMessage, getMinStakeErrorMessage, getRelayBlockedValidatorList, getRelayEraRewardMap, getRelayMaxNominations, getRelayTopValidatorByPoints, getRelayValidatorPointsMap, getSupportedDaysByHistoryDepth } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
6
+ import { calculateAlephZeroValidatorReturn, calculateChainStakedReturnV2, calculateInflation, calculateTernoaValidatorReturn, calculateValidatorStakedReturn, getAvgValidatorEraReward, getCommission, getMaxValidatorErrorMessage, getMinStakeErrorMessage, getRelayBlockedValidatorList, getRelayEraRewardMap, getRelayMaxNominations, getRelayTopValidatorByPoints, getRelayValidatorPointsMap, getRelayWaitingValidatorList, getSupportedDaysByHistoryDepth } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
7
7
  import { _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
8
8
  import { _getChainSubstrateAddressPrefix } from '@subwallet/extension-base/services/chain-service/utils';
9
9
  import { _STAKING_CHAIN_GROUP, _UPDATED_RUNTIME_STAKING_GROUP, MaxEraRewardPointsEras } from '@subwallet/extension-base/services/earning-service/constants';
@@ -313,11 +313,20 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
313
313
  const topValidatorList = getRelayTopValidatorByPoints(validatorPointsMap);
314
314
  const validators = _validators;
315
315
  const blockedValidatorList = getRelayBlockedValidatorList(validators);
316
+ const waitingValidatorList = getRelayWaitingValidatorList(validators);
317
+ const _waitingValidatorLedger = await chainApi.api.query.staking.ledger.multi(waitingValidatorList);
318
+ const waitingValidatorLedger = {};
319
+ if (_waitingValidatorLedger) {
320
+ waitingValidatorList.forEach((validator, i) => {
321
+ const validatorLedger = _waitingValidatorLedger[i].toPrimitive();
322
+ waitingValidatorLedger[validator] = new BigN(validatorLedger.total).toFixed();
323
+ });
324
+ }
316
325
  const unlimitedNominatorRewarded = chainApi.api.consts.staking.maxExposurePageSize !== undefined;
317
326
  const maxNominatorRewarded = (chainApi.api.consts.staking.maxNominatorRewardedPerValidator || 0).toString();
318
327
  const bnTotalEraStake = new BN(_totalEraStake.toString());
319
328
  const minBond = _minBond.toPrimitive();
320
- const [totalStakeMap, allValidatorAddresses, validatorInfoList] = this.parseEraStakerData(_eraStakers, blockedValidatorList, topValidatorList, validatorPointsMap, minBond, maxNominatorRewarded, unlimitedNominatorRewarded);
329
+ const [totalStakeMap, allValidatorAddresses, validatorInfoList] = this.parseEraStakerData(_eraStakers, blockedValidatorList, waitingValidatorLedger, topValidatorList, validatorPointsMap, minBond, maxNominatorRewarded, unlimitedNominatorRewarded);
321
330
  const extraInfoMap = {};
322
331
  await Promise.all(allValidatorAddresses.map(async address => {
323
332
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
@@ -352,11 +361,15 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
352
361
  const validatorStake = applyDecimal(totalStakeMap[validator.address], decimals).toNumber();
353
362
  return calculateTernoaValidatorReturn(rewardPerValidator.toNumber(), validatorStake, commission);
354
363
  } else {
355
- const bnValidatorStake = applyDecimal(totalStakeMap[validator.address], decimals);
356
- return calculateValidatorStakedReturn(totalApy, bnValidatorStake, bnAvgStake, commission);
364
+ if (!totalStakeMap[validator.address]) {
365
+ return totalApy;
366
+ } else {
367
+ const bnValidatorStake = applyDecimal(totalStakeMap[validator.address], decimals);
368
+ return calculateValidatorStakedReturn(totalApy, bnValidatorStake, bnAvgStake, commission);
369
+ }
357
370
  }
358
371
  }
359
- parseEraStakerData(_eraStakers, blockedValidatorList, topValidatorList, validatorPointsMap, minBond, maxNominatorRewarded, unlimitedNominatorRewarded) {
372
+ parseEraStakerData(_eraStakers, blockedValidatorList, waitingValidatorList, topValidatorList, validatorPointsMap, minBond, maxNominatorRewarded, unlimitedNominatorRewarded) {
360
373
  const totalStakeMap = {};
361
374
  const allValidatorAddresses = [];
362
375
  const validatorInfoList = [];
@@ -406,6 +419,27 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
406
419
  });
407
420
  }
408
421
  }
422
+ for (const waitingValidator of Object.keys(waitingValidatorList)) {
423
+ if (!allValidatorAddresses.includes(waitingValidator)) {
424
+ allValidatorAddresses.push(waitingValidator);
425
+ validatorInfoList.push({
426
+ address: waitingValidator,
427
+ totalStake: waitingValidatorList[waitingValidator],
428
+ ownStake: waitingValidatorList[waitingValidator],
429
+ otherStake: '0',
430
+ nominatorCount: 0,
431
+ // to be added later
432
+ commission: 0,
433
+ expectedReturn: 0,
434
+ blocked: false,
435
+ isVerified: false,
436
+ minBond: minBond.toString(),
437
+ isCrowded: false,
438
+ eraRewardPoint: '0',
439
+ topQuartile: false
440
+ });
441
+ }
442
+ }
409
443
  return [totalStakeMap, allValidatorAddresses, validatorInfoList];
410
444
  }
411
445
  /* Get pool targets */
@@ -137,6 +137,9 @@ export default class EarningService {
137
137
  if (event.type === 'account.remove') {
138
138
  removedAddresses.push(event.data[0]);
139
139
  }
140
+ if (event.type === 'account.add') {
141
+ delayReload = true;
142
+ }
140
143
  if (event.type === 'chain.updateState') {
141
144
  const chainState = this.state.getChainStateByKey(event.data[0]);
142
145
  if (chainState && !_isChainEnabled(chainState)) {
@@ -2,10 +2,26 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import BaseMigrationJob from '@subwallet/extension-base/services/migration-service/Base';
5
+ import { cacheMetadata, waitTimeout } from '@subwallet/extension-base/utils';
5
6
  export default class ClearMetadataDatabase extends BaseMigrationJob {
6
7
  async run() {
7
8
  // Clear all old metadata data
8
9
  await this.state.dbService.stores.metadata.clear();
10
+ const activeChains = this.state.chainService.getActiveChains();
11
+ const chainInfoMap = this.state.chainService.getChainInfoMap();
12
+ const reloadChains = activeChains.filter(chain => {
13
+ var _chainInfoMap$chain$s;
14
+ return !!((_chainInfoMap$chain$s = chainInfoMap[chain].substrateInfo) !== null && _chainInfoMap$chain$s !== void 0 && _chainInfoMap$chain$s.genesisHash);
15
+ });
16
+ for (const chain of reloadChains) {
17
+ const substrateApi = this.state.chainService.getSubstrateApi(chain);
18
+ const callback = substrateApi => {
19
+ cacheMetadata(chain, substrateApi, this.state.chainService);
20
+ };
21
+ Promise.race([substrateApi.isReady, waitTimeout(2000)]).finally(() => {
22
+ substrateApi === null || substrateApi === void 0 ? void 0 : substrateApi.connect(callback);
23
+ });
24
+ }
9
25
  return Promise.resolve();
10
26
  }
11
27
  }