@subwallet/extension-base 1.0.2-2 → 1.0.3-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 (151) hide show
  1. package/background/KoniTypes.d.ts +56 -40
  2. package/background/KoniTypes.js +11 -9
  3. package/background/errors/TransactionError.js +25 -1
  4. package/background/types.d.ts +10 -5
  5. package/cjs/background/KoniTypes.js +11 -9
  6. package/cjs/background/errors/TransactionError.js +24 -0
  7. package/cjs/constants/index.js +8 -26
  8. package/cjs/koni/api/dotsama/balance.js +49 -224
  9. package/cjs/koni/api/dotsama/transfer.js +34 -39
  10. package/cjs/koni/api/nft/acala_nft/index.js +7 -7
  11. package/cjs/koni/api/nft/bit.country/index.js +7 -6
  12. package/cjs/koni/api/nft/evm_nft/index.js +8 -3
  13. package/cjs/koni/api/nft/index.js +3 -6
  14. package/cjs/koni/api/nft/karura_nft/index.js +7 -6
  15. package/cjs/koni/api/nft/rmrk_nft/index.js +11 -1
  16. package/cjs/koni/api/nft/statemine_nft/index.js +7 -6
  17. package/cjs/koni/api/nft/unique_nft/index.js +5 -1
  18. package/cjs/koni/api/nft/wasm_nft/index.js +170 -111
  19. package/cjs/koni/api/nft/wasm_nft/utils.js +11 -7
  20. package/cjs/koni/api/staking/bonding/amplitude.js +13 -9
  21. package/cjs/koni/api/staking/bonding/astar.js +15 -13
  22. package/cjs/koni/api/staking/bonding/index.js +22 -10
  23. package/cjs/koni/api/staking/bonding/paraChain.js +85 -2
  24. package/cjs/koni/api/staking/bonding/relayChain.js +122 -16
  25. package/cjs/koni/api/staking/bonding/utils.js +27 -8
  26. package/cjs/koni/api/tokens/wasm/index.js +5 -4
  27. package/cjs/koni/api/tokens/wasm/utils.js +63 -0
  28. package/cjs/koni/api/xcm/polkadotXcm.js +1 -1
  29. package/cjs/koni/api/xcm/utils.js +18 -13
  30. package/cjs/koni/api/xcm/xTokens.js +1 -1
  31. package/cjs/koni/api/xcm/xcmPallet.js +9 -6
  32. package/cjs/koni/background/cron.js +171 -61
  33. package/cjs/koni/background/handlers/Extension.js +391 -207
  34. package/cjs/koni/background/handlers/State.js +49 -34
  35. package/cjs/koni/background/handlers/Tabs.js +50 -17
  36. package/cjs/koni/background/subscription.js +53 -28
  37. package/cjs/packageInfo.js +1 -1
  38. package/cjs/services/base/types.js +20 -0
  39. package/cjs/services/chain-service/handler/SubstrateChainHandler.js +13 -8
  40. package/cjs/services/chain-service/index.js +73 -49
  41. package/cjs/services/event-service/index.js +5 -1
  42. package/cjs/services/event-service/types.js +11 -1
  43. package/cjs/services/history-service/index.js +101 -50
  44. package/cjs/services/history-service/subsquid-multi-chain-history.js +13 -10
  45. package/cjs/services/keyring-service/index.js +11 -13
  46. package/cjs/services/migration-service/scripts/MigrateImportedToken.js +2 -1
  47. package/cjs/services/price-service/coingecko.js +0 -1
  48. package/cjs/services/price-service/index.js +71 -24
  49. package/cjs/services/request-service/handler/AuthRequestHandler.js +13 -7
  50. package/cjs/services/request-service/handler/EvmRequestHandler.js +8 -12
  51. package/cjs/services/request-service/index.js +14 -5
  52. package/cjs/services/storage-service/DatabaseService.js +66 -34
  53. package/cjs/services/storage-service/db-stores/Nft.js +7 -15
  54. package/cjs/services/storage-service/db-stores/Transaction.js +6 -10
  55. package/cjs/services/transaction-service/event-parser/index.js +20 -48
  56. package/cjs/services/transaction-service/index.js +104 -48
  57. package/cjs/services/transaction-service/utils.js +10 -8
  58. package/cjs/utils/address.js +10 -1
  59. package/cjs/utils/index.js +9 -15
  60. package/cjs/utils/promise.js +26 -0
  61. package/constants/index.d.ts +7 -13
  62. package/constants/index.js +7 -13
  63. package/koni/api/dotsama/balance.d.ts +0 -1
  64. package/koni/api/dotsama/balance.js +22 -197
  65. package/koni/api/dotsama/transfer.js +11 -16
  66. package/koni/api/nft/acala_nft/index.js +7 -7
  67. package/koni/api/nft/bit.country/index.js +7 -6
  68. package/koni/api/nft/evm_nft/index.js +7 -3
  69. package/koni/api/nft/index.d.ts +1 -2
  70. package/koni/api/nft/index.js +3 -6
  71. package/koni/api/nft/karura_nft/index.js +7 -6
  72. package/koni/api/nft/nft.d.ts +1 -0
  73. package/koni/api/nft/rmrk_nft/index.js +11 -1
  74. package/koni/api/nft/statemine_nft/index.js +7 -6
  75. package/koni/api/nft/unique_nft/index.js +5 -1
  76. package/koni/api/nft/wasm_nft/index.d.ts +0 -2
  77. package/koni/api/nft/wasm_nft/index.js +168 -109
  78. package/koni/api/nft/wasm_nft/utils.d.ts +7 -5
  79. package/koni/api/nft/wasm_nft/utils.js +7 -5
  80. package/koni/api/staking/bonding/amplitude.d.ts +0 -1
  81. package/koni/api/staking/bonding/amplitude.js +15 -10
  82. package/koni/api/staking/bonding/astar.js +8 -6
  83. package/koni/api/staking/bonding/index.d.ts +4 -1
  84. package/koni/api/staking/bonding/index.js +23 -13
  85. package/koni/api/staking/bonding/paraChain.d.ts +3 -0
  86. package/koni/api/staking/bonding/paraChain.js +86 -5
  87. package/koni/api/staking/bonding/relayChain.d.ts +5 -1
  88. package/koni/api/staking/bonding/relayChain.js +121 -18
  89. package/koni/api/staking/bonding/utils.d.ts +3 -2
  90. package/koni/api/staking/bonding/utils.js +27 -9
  91. package/koni/api/tokens/wasm/index.js +5 -4
  92. package/koni/api/tokens/wasm/utils.d.ts +6 -0
  93. package/koni/api/tokens/wasm/utils.js +54 -0
  94. package/koni/api/xcm/polkadotXcm.js +2 -2
  95. package/koni/api/xcm/utils.d.ts +5 -6
  96. package/koni/api/xcm/utils.js +15 -10
  97. package/koni/api/xcm/xTokens.js +2 -2
  98. package/koni/api/xcm/xcmPallet.js +10 -9
  99. package/koni/background/cron.d.ts +6 -1
  100. package/koni/background/cron.js +172 -62
  101. package/koni/background/handlers/Extension.d.ts +9 -3
  102. package/koni/background/handlers/Extension.js +306 -126
  103. package/koni/background/handlers/State.d.ts +5 -6
  104. package/koni/background/handlers/State.js +51 -34
  105. package/koni/background/handlers/Tabs.js +50 -17
  106. package/koni/background/subscription.d.ts +2 -0
  107. package/koni/background/subscription.js +51 -29
  108. package/package.json +29 -14
  109. package/packageInfo.js +1 -1
  110. package/services/base/types.d.ts +34 -0
  111. package/services/base/types.js +15 -0
  112. package/services/chain-service/handler/SubstrateChainHandler.js +14 -9
  113. package/services/chain-service/helper/psp22_abi.json +1041 -881
  114. package/services/chain-service/helper/psp34_abi.json +2963 -1807
  115. package/services/chain-service/index.d.ts +5 -2
  116. package/services/chain-service/index.js +68 -45
  117. package/services/chain-service/types.d.ts +1 -0
  118. package/services/event-service/index.js +5 -1
  119. package/services/event-service/types.d.ts +5 -9
  120. package/services/event-service/types.js +4 -1
  121. package/services/history-service/index.d.ts +28 -7
  122. package/services/history-service/index.js +101 -50
  123. package/services/history-service/subsquid-multi-chain-history.js +16 -12
  124. package/services/keyring-service/index.d.ts +4 -2
  125. package/services/keyring-service/index.js +11 -13
  126. package/services/migration-service/scripts/MigrateImportedToken.js +2 -1
  127. package/services/price-service/coingecko.js +0 -1
  128. package/services/price-service/index.d.ts +22 -1
  129. package/services/price-service/index.js +71 -24
  130. package/services/request-service/handler/AuthRequestHandler.d.ts +3 -1
  131. package/services/request-service/handler/AuthRequestHandler.js +13 -7
  132. package/services/request-service/handler/EvmRequestHandler.js +8 -12
  133. package/services/request-service/index.d.ts +3 -1
  134. package/services/request-service/index.js +14 -5
  135. package/services/storage-service/DatabaseService.d.ts +2 -0
  136. package/services/storage-service/DatabaseService.js +66 -34
  137. package/services/storage-service/db-stores/Nft.d.ts +2 -2
  138. package/services/storage-service/db-stores/Nft.js +7 -14
  139. package/services/storage-service/db-stores/Transaction.d.ts +2 -0
  140. package/services/storage-service/db-stores/Transaction.js +6 -10
  141. package/services/transaction-service/event-parser/index.js +21 -49
  142. package/services/transaction-service/index.d.ts +2 -0
  143. package/services/transaction-service/index.js +86 -32
  144. package/services/transaction-service/types.d.ts +2 -0
  145. package/services/transaction-service/utils.js +10 -8
  146. package/utils/address.d.ts +3 -0
  147. package/utils/address.js +8 -1
  148. package/utils/index.d.ts +2 -2
  149. package/utils/index.js +7 -13
  150. package/utils/promise.d.ts +6 -0
  151. package/utils/promise.js +20 -0
@@ -7,12 +7,12 @@ import { ASTAR_REFRESH_BALANCE_INTERVAL, SUB_TOKEN_REFRESH_BALANCE_INTERVAL } fr
7
7
  import { getEVMBalance } from '@subwallet/extension-base/koni/api/tokens/evm/balance';
8
8
  import { getERC20Contract } from '@subwallet/extension-base/koni/api/tokens/evm/web3';
9
9
  import { getPSP22ContractPromise } from '@subwallet/extension-base/koni/api/tokens/wasm';
10
+ import { getDefaultWeightV2 } from '@subwallet/extension-base/koni/api/tokens/wasm/utils';
10
11
  import { state } from '@subwallet/extension-base/koni/background/handlers';
11
- import { _BALANCE_CHAIN_GROUP, _BALANCE_TOKEN_GROUP, _PURE_EVM_CHAINS } from '@subwallet/extension-base/services/chain-service/constants';
12
- import { _checkSmartContractSupportByChain, _getChainNativeTokenSlug, _getContractAddressOfToken, _getTokenOnChainAssetId, _getTokenOnChainInfo, _isChainEvmCompatible, _isNativeToken, _isPureEvmChain, _isSmartContractToken, _isSubstrateRelayChain } from '@subwallet/extension-base/services/chain-service/utils';
12
+ import { _BALANCE_CHAIN_GROUP, _PURE_EVM_CHAINS } from '@subwallet/extension-base/services/chain-service/constants';
13
+ import { _checkSmartContractSupportByChain, _getChainNativeTokenSlug, _getContractAddressOfToken, _getTokenOnChainAssetId, _getTokenOnChainInfo, _isChainEvmCompatible, _isPureEvmChain, _isSubstrateRelayChain } from '@subwallet/extension-base/services/chain-service/utils';
13
14
  import { categoryAddresses, sumBN } from '@subwallet/extension-base/utils';
14
15
  import { BN, BN_ZERO } from '@polkadot/util';
15
- import { isEthereumAddress } from '@polkadot/util-crypto';
16
16
  // main subscription
17
17
  export function subscribeBalance(addresses, chainInfoMap, substrateApiMap, evmApiMap, callback) {
18
18
  const [substrateAddresses, evmAddresses] = categoryAddresses(addresses);
@@ -95,11 +95,16 @@ async function subscribeWithSystemAccountPallet(addresses, chainInfo, networkAPI
95
95
  let pooledStakingBalance = BN_ZERO;
96
96
  if (_isSubstrateRelayChain(chainInfo) && networkAPI.query.nominationPools) {
97
97
  const poolMemberDatas = await networkAPI.query.nominationPools.poolMembers.multi(addresses);
98
- for (const _poolMemberData of poolMemberDatas) {
99
- const poolMemberData = _poolMemberData.toPrimitive();
100
- if (poolMemberData) {
101
- const pooledBalance = new BN(poolMemberData.points.toString());
102
- pooledStakingBalance = pooledStakingBalance.add(pooledBalance);
98
+ if (poolMemberDatas) {
99
+ for (const _poolMemberData of poolMemberDatas) {
100
+ const poolMemberData = _poolMemberData.toPrimitive();
101
+ if (poolMemberData) {
102
+ const pooledBalance = new BN(poolMemberData.points.toString());
103
+ pooledStakingBalance = pooledStakingBalance.add(pooledBalance);
104
+ Object.entries(poolMemberData.unbondingEras).forEach(([, amount]) => {
105
+ pooledStakingBalance = pooledStakingBalance.add(new BN(amount));
106
+ });
107
+ }
103
108
  }
104
109
  }
105
110
  }
@@ -120,7 +125,7 @@ async function subscribeWithSystemAccountPallet(addresses, chainInfo, networkAPI
120
125
  const free = total.sub(locked);
121
126
  callBack({
122
127
  tokenSlug: chainNativeTokenSlug,
123
- free: free.toString(),
128
+ free: free.gte(BN_ZERO) ? free.toString() : '0',
124
129
  locked: locked.toString(),
125
130
  state: APIItemState.READY,
126
131
  substrateInfo: {
@@ -134,79 +139,6 @@ async function subscribeWithSystemAccountPallet(addresses, chainInfo, networkAPI
134
139
  unsub();
135
140
  };
136
141
  }
137
-
138
- // deprecated
139
- // function subscribeDarwiniaBalance (addresses: string[], chainInfo: _ChainInfo, chain: string, networkAPI: ApiPromise, callBack: (rs: BalanceItem) => void) {
140
- // const tokenMap = state.getAssetByChainAndAsset(chain, [_AssetType.LOCAL]);
141
- // const nativeTokenSlug = _getChainNativeTokenSlug(chainInfo);
142
- //
143
- // let totalBalance: BN = new BN(0);
144
- // let freeBalance: BN = new BN(0);
145
- // let miscFrozen: BN = new BN(0);
146
- // let reservedKtonBalance: BN = new BN(0);
147
- // let totalKtonBalance: BN = new BN(0);
148
- //
149
- // const unsubProms = addresses.map((address) => {
150
- // return networkAPI.derive.balances?.all(address, async (balance: DeriveBalancesAll) => {
151
- // // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
152
- // freeBalance = freeBalance.add(balance.availableBalance?.toBn() || new BN(0));
153
- // miscFrozen = miscFrozen.add(balance.lockedBalance?.toBn() || new BN(0));
154
- // totalBalance = totalBalance.add(balance.freeBalance?.toBn() || new BN(0));
155
- //
156
- // const _systemBalance = await networkAPI.query.system.account(address);
157
- // const systemBalance = _systemBalance.toHuman() as unknown as AccountInfo;
158
- //
159
- // // @ts-ignore
160
- // const rawTotalKton = (systemBalance.data?.freeKton as string).replaceAll(',', '');
161
- // // @ts-ignore
162
- // const rawReservedKton = (systemBalance.data?.reservedKton as string).replaceAll(',', '');
163
- //
164
- // // @ts-ignore
165
- // // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
166
- // totalKtonBalance = totalKtonBalance.add(new BN(rawTotalKton) || new BN(0));
167
- // // @ts-ignore
168
- // // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
169
- // reservedKtonBalance = reservedKtonBalance.add(new BN(rawReservedKton) || new BN(0));
170
- //
171
- // if (Object.keys(tokenMap).length > 1) {
172
- // for (const tokenInfo of Object.values(tokenMap)) {
173
- // if (_BALANCE_TOKEN_GROUP.crab.includes(tokenInfo.symbol)) {
174
- // const freeKton = totalKtonBalance.sub(reservedKtonBalance);
175
- //
176
- // callBack({
177
- // free: freeKton.toString(),
178
- // locked: reservedKtonBalance.toString(),
179
- // state: APIItemState.READY,
180
- // tokenSlug: tokenInfo.slug
181
- // });
182
- // break;
183
- // }
184
- // }
185
- // }
186
- //
187
- // const free = totalBalance.sub(miscFrozen);
188
- //
189
- // callBack({
190
- // tokenSlug: nativeTokenSlug,
191
- // free: free.toString(),
192
- // locked: miscFrozen.toString(),
193
- // state: APIItemState.READY,
194
- // substrateInfo: {
195
- // miscFrozen: miscFrozen.toString()
196
- // }
197
- // });
198
- // });
199
- // });
200
- //
201
- // return () => {
202
- // Promise.all(unsubProms).then((unsubs) => {
203
- // unsubs.forEach((unsub) => {
204
- // unsub && unsub();
205
- // });
206
- // }).catch(console.error);
207
- // };
208
- // }
209
-
210
142
  function subscribeERC20Interval(addresses, chain, evmApiMap, callBack) {
211
143
  let tokenList = {};
212
144
  const erc20ContractMap = {};
@@ -250,10 +182,12 @@ function subscribePSP22Balance(addresses, chain, api, callBack) {
250
182
  try {
251
183
  const contract = psp22ContractMap[tokenInfo.slug];
252
184
  const balances = await Promise.all(addresses.map(async address => {
185
+ var _balanceOf$output;
253
186
  const _balanceOf = await contract.query['psp22::balanceOf'](address, {
254
- gasLimit: -1
187
+ gasLimit: getDefaultWeightV2(api)
255
188
  }, address);
256
- return _balanceOf.output ? _balanceOf.output.toString() : '0';
189
+ const balanceObj = _balanceOf === null || _balanceOf === void 0 ? void 0 : (_balanceOf$output = _balanceOf.output) === null || _balanceOf$output === void 0 ? void 0 : _balanceOf$output.toPrimitive();
190
+ return _balanceOf.output ? balanceObj.ok || balanceObj.Ok : '0';
257
191
  }));
258
192
  free = sumBN(balances.map(bal => new BN(bal || 0)));
259
193
  callBack({
@@ -263,10 +197,11 @@ function subscribePSP22Balance(addresses, chain, api, callBack) {
263
197
  state: APIItemState.READY
264
198
  });
265
199
  } catch (err) {
266
- console.log('There is a problem fetching ' + tokenInfo.slug + ' PSP-22 token balance', err);
200
+ console.warn('Problem fetching ' + tokenInfo.slug + ' PSP-22 token balance', err); // TODO: error createType
267
201
  }
268
202
  });
269
203
  };
204
+
270
205
  tokenList = state.getAssetByChainAndAsset(chain, [_AssetType.PSP22]);
271
206
  Object.entries(tokenList).forEach(([slug, tokenInfo]) => {
272
207
  psp22ContractMap[slug] = getPSP22ContractPromise(api, _getContractAddressOfToken(tokenInfo));
@@ -396,11 +331,11 @@ async function subscribeAssetsAccountPallet(addresses, chain, api, callBack) {
396
331
  balances.forEach(b => {
397
332
  // @ts-ignore
398
333
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-assignment
399
- const bdata = b === null || b === void 0 ? void 0 : b.toJSON();
334
+ const bdata = b === null || b === void 0 ? void 0 : b.toHuman();
400
335
  if (bdata) {
401
336
  // @ts-ignore
402
337
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument
403
- const addressBalance = new BN(String(bdata === null || bdata === void 0 ? void 0 : bdata.balance) || '0');
338
+ const addressBalance = new BN(String(bdata === null || bdata === void 0 ? void 0 : bdata.balance).replaceAll(',', '') || '0');
404
339
 
405
340
  // @ts-ignore
406
341
  if (bdata !== null && bdata !== void 0 && bdata.isFrozen) {
@@ -454,114 +389,4 @@ export function subscribeEVMBalance(chain, addresses, evmApiMap, callback, token
454
389
  clearInterval(interval);
455
390
  unsub2 && unsub2();
456
391
  };
457
- }
458
- export async function getFreeBalance(chain, address, substrateApiMap, evmApiMap, tokenSlug) {
459
- const substrateApi = await substrateApiMap[chain].isReady;
460
- const api = substrateApi.api;
461
- const web3Api = evmApiMap[chain];
462
- const tokenInfo = tokenSlug ? state.getAssetBySlug(tokenSlug) : state.getNativeTokenInfo(chain);
463
- const chainInfo = state.getChainInfo(chain);
464
-
465
- // Only EVM Address use with EVM network
466
- if (Boolean(web3Api || _isChainEvmCompatible(chainInfo)) !== isEthereumAddress(address)) {
467
- if (!isEthereumAddress(address)) {
468
- return '0';
469
- }
470
- }
471
-
472
- // web3Api support mean isEthereum Network support
473
- if (web3Api) {
474
- if (_isNativeToken(tokenInfo)) {
475
- var _web3Api$api;
476
- return (await ((_web3Api$api = web3Api.api) === null || _web3Api$api === void 0 ? void 0 : _web3Api$api.eth.getBalance(address))) || '0';
477
- } else {
478
- if (_getContractAddressOfToken(tokenInfo).length > 0) {
479
- return '0';
480
- }
481
- const contract = getERC20Contract(chain, _getContractAddressOfToken(tokenInfo), evmApiMap);
482
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
483
- const free = await contract.methods.balanceOf(address).call();
484
-
485
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-return
486
- return (free === null || free === void 0 ? void 0 : free.toString()) || '0';
487
- }
488
- } else {
489
- var _balance$availableBal, _balance$availableBal2;
490
- if (tokenSlug) {
491
- if (_isSmartContractToken(tokenInfo)) {
492
- if (_getContractAddressOfToken(tokenInfo).length > 0) {
493
- return '0';
494
- }
495
- const contractPromise = getPSP22ContractPromise(api, _getContractAddressOfToken(tokenInfo));
496
- const balanceOf = await contractPromise.query['psp22::balanceOf'](address, {
497
- gasLimit: -1
498
- }, address);
499
- return balanceOf.output ? balanceOf.output.toString() : '0';
500
- } else if (_BALANCE_CHAIN_GROUP.genshiro.includes(chain)) {
501
- var _balance$asPositive;
502
- const onChainInfo = _getTokenOnChainInfo(tokenInfo);
503
- const balance = await api.query.eqBalances.account(address, onChainInfo);
504
-
505
- // @ts-ignore
506
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-return
507
- return ((_balance$asPositive = balance.asPositive) === null || _balance$asPositive === void 0 ? void 0 : _balance$asPositive.toString()) || '0';
508
- } else if (_BALANCE_CHAIN_GROUP.equilibrium_parachain.includes(chain)) {
509
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
510
- const balance = await api.query.system.account(address);
511
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
512
- const balancesData = JSON.parse(balance.data.toString());
513
- const balanceList = balancesData.v0.balance;
514
- let freeTokenBalance;
515
- const assetId = _getTokenOnChainAssetId(tokenInfo);
516
- if (!_isNativeToken(tokenInfo)) {
517
- // @ts-ignore
518
- freeTokenBalance = balanceList.find(data => data[0] === assetId);
519
- } else {
520
- freeTokenBalance = balanceList[0];
521
- }
522
- return freeTokenBalance ? freeTokenBalance[1].positive.toString() : '0';
523
- } else if (_BALANCE_TOKEN_GROUP.crab.includes(tokenInfo.symbol)) {
524
- var _balance$data5, _balance$data5$freeKt;
525
- // @ts-ignore
526
- const balance = await api.query.system.account(address);
527
- return ((_balance$data5 = balance.data) === null || _balance$data5 === void 0 ? void 0 : (_balance$data5$freeKt = _balance$data5.freeKton) === null || _balance$data5$freeKt === void 0 ? void 0 : _balance$data5$freeKt.toString()) || '0';
528
- } else if (!_isNativeToken(tokenInfo) && _BALANCE_CHAIN_GROUP.statemine.includes(chain)) {
529
- var _balanceInfo$balance;
530
- const assetId = _getTokenOnChainAssetId(tokenInfo);
531
- const balanceInfo = (await api.query.assets.account(assetId, address)).toHuman();
532
-
533
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-return
534
- return (balanceInfo === null || balanceInfo === void 0 ? void 0 : (_balanceInfo$balance = balanceInfo.balance) === null || _balanceInfo$balance === void 0 ? void 0 : _balanceInfo$balance.replaceAll(',', '')) || '0';
535
- } else if (!_isNativeToken(tokenInfo) || _BALANCE_CHAIN_GROUP.kintsugi.includes(chain)) {
536
- var _balance$free;
537
- const onChainInfo = _getTokenOnChainInfo(tokenInfo);
538
- // @ts-ignore
539
- const balance = await api.query.tokens.accounts(address, onChainInfo);
540
- return ((_balance$free = balance.free) === null || _balance$free === void 0 ? void 0 : _balance$free.toString()) || '0';
541
- }
542
- }
543
- if (_BALANCE_CHAIN_GROUP.kusama.includes(chain)) {
544
- var _balance$data6, _balance$data7;
545
- // @ts-ignore
546
- const _balance = await api.query.system.account(address);
547
-
548
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment
549
- const balance = _balance.toHuman();
550
-
551
- // @ts-ignore
552
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
553
- const freeBalance = new BN((_balance$data6 = balance.data) === null || _balance$data6 === void 0 ? void 0 : _balance$data6.free.replaceAll(',', ''));
554
-
555
- // @ts-ignore
556
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
557
- const miscFrozen = new BN((_balance$data7 = balance.data) === null || _balance$data7 === void 0 ? void 0 : _balance$data7.miscFrozen.replaceAll(',', ''));
558
- const transferable = freeBalance.sub(miscFrozen);
559
-
560
- // @ts-ignore
561
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-return
562
- return transferable.toString() || '0';
563
- }
564
- const balance = await api.derive.balances.all(address);
565
- return ((_balance$availableBal = balance.availableBalance) === null || _balance$availableBal === void 0 ? void 0 : (_balance$availableBal2 = _balance$availableBal.toBn()) === null || _balance$availableBal2 === void 0 ? void 0 : _balance$availableBal2.toString()) || '0';
566
- }
567
392
  }
@@ -2,6 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { getPSP22ContractPromise } from '@subwallet/extension-base/koni/api/tokens/wasm';
5
+ import { getWasmContractGasLimit } from '@subwallet/extension-base/koni/api/tokens/wasm/utils';
5
6
  import { _BALANCE_TOKEN_GROUP, _TRANSFER_CHAIN_GROUP, _TRANSFER_NOT_SUPPORTED_CHAINS } from '@subwallet/extension-base/services/chain-service/constants';
6
7
  import { _getContractAddressOfToken, _getTokenOnChainAssetId, _getTokenOnChainInfo, _isChainEvmCompatible, _isNativeToken, _isTokenWasmSmartContract } from '@subwallet/extension-base/services/chain-service/utils';
7
8
  import { BN } from '@polkadot/util';
@@ -58,15 +59,17 @@ export async function checkSupportTransfer(networkKey, tokenInfo, substrateApiMa
58
59
  supportTransferAll: true
59
60
  };
60
61
  }
62
+
63
+ // TODO: need review
61
64
  if (_TRANSFER_CHAIN_GROUP.acala.includes(networkKey) && !_isNativeToken(tokenInfo) && isTxCurrenciesSupported) {
62
65
  result.supportTransfer = true;
63
- result.supportTransferAll = false;
66
+ result.supportTransferAll = true;
64
67
  } else if (_TRANSFER_CHAIN_GROUP.kintsugi.includes(networkKey) && !_isNativeToken(tokenInfo) && isTxTokensSupported) {
65
68
  result.supportTransfer = true;
66
69
  result.supportTransferAll = true;
67
70
  } else if (_TRANSFER_CHAIN_GROUP.genshiro.includes(networkKey) && !_isNativeToken(tokenInfo) && isTxEqBalancesSupported) {
68
71
  result.supportTransfer = true;
69
- result.supportTransferAll = false;
72
+ result.supportTransferAll = true;
70
73
  } else if (_TRANSFER_CHAIN_GROUP.crab.includes(networkKey) && _BALANCE_TOKEN_GROUP.crab.includes(tokenInfo.symbol)) {
71
74
  result.supportTransfer = true;
72
75
  result.supportTransferAll = true;
@@ -104,20 +107,16 @@ export const createTransferExtrinsic = async ({
104
107
 
105
108
  if (_isTokenWasmSmartContract(tokenInfo) && api.query.contracts) {
106
109
  const contractPromise = getPSP22ContractPromise(api, _getContractAddressOfToken(tokenInfo));
107
- const transferQuery = await contractPromise.query['psp22::transfer'](from, {
108
- gasLimit: -1
109
- }, to, value, {});
110
- const gasLimit = transferQuery.gasRequired.toString();
110
+ // @ts-ignore
111
+ const gasLimit = await getWasmContractGasLimit(api, from, 'psp22::transfer', contractPromise, {}, [from, value, {}]);
112
+
113
+ // @ts-ignore
111
114
  transfer = contractPromise.tx['psp22::transfer']({
112
115
  gasLimit
113
116
  }, to, value, {});
114
117
  transferAmount = value;
115
118
  } else if (_TRANSFER_CHAIN_GROUP.acala.includes(networkKey) && !_isNativeToken(tokenInfo) && isTxCurrenciesSupported) {
116
- if (transferAll) {
117
- // currently Acala, Karura, Acala testnet do not have transfer all method for sub token
118
- } else if (value) {
119
- transfer = api.tx.currencies.transfer(to, _getTokenOnChainInfo(tokenInfo), value);
120
- }
119
+ transfer = api.tx.currencies.transfer(to, _getTokenOnChainInfo(tokenInfo), value);
121
120
  } else if (_TRANSFER_CHAIN_GROUP.kintsugi.includes(networkKey) && !_isNativeToken(tokenInfo) && isTxTokensSupported) {
122
121
  if (transferAll) {
123
122
  transfer = api.tx.tokens.transferAll(to, _getTokenOnChainInfo(tokenInfo), false);
@@ -125,11 +124,7 @@ export const createTransferExtrinsic = async ({
125
124
  transfer = api.tx.tokens.transfer(to, _getTokenOnChainInfo(tokenInfo), new BN(value));
126
125
  }
127
126
  } else if (_TRANSFER_CHAIN_GROUP.genshiro.includes(networkKey) && !_isNativeToken(tokenInfo) && isTxEqBalancesSupported) {
128
- if (transferAll) {
129
- // currently genshiro_testnet, genshiro, equilibrium_parachain do not have transfer all method for tokens
130
- } else if (value) {
131
- transfer = api.tx.eqBalances.transfer(_getTokenOnChainAssetId(tokenInfo), to, value);
132
- }
127
+ transfer = api.tx.eqBalances.transfer([_getTokenOnChainAssetId(tokenInfo)], to, value);
133
128
  } else if (!_isNativeToken(tokenInfo) && (_TRANSFER_CHAIN_GROUP.crab.includes(networkKey) || _BALANCE_TOKEN_GROUP.crab.includes(tokenInfo.symbol))) {
134
129
  if (transferAll) {
135
130
  transfer = api.tx.kton.transferAll(to, false);
@@ -72,21 +72,21 @@ export class AcalaNftApi extends BaseNftApi {
72
72
  return (await this.substrateApi.api.query.ormlNFT.tokens(assetId.classId, assetId.tokenId)).toHuman();
73
73
  }
74
74
  async handleNft(address, params) {
75
- // const start = performance.now();
76
75
  const assetIds = await this.getNfts([address]);
77
76
  try {
78
77
  if (!assetIds || assetIds.length === 0) {
78
+ params.cleanUpNfts(this.chain, address, [], [], true);
79
79
  return;
80
80
  }
81
- const collectionNftIds = {};
81
+ const collectionIds = [];
82
+ const nftIds = [];
82
83
  await Promise.all(assetIds.map(async assetId => {
83
84
  const parsedClassId = this.parseTokenId(assetId.classId);
84
85
  const parsedTokenId = this.parseTokenId(assetId.tokenId);
85
- if (collectionNftIds[parsedClassId]) {
86
- collectionNftIds[parsedClassId].push(parsedTokenId);
87
- } else {
88
- collectionNftIds[parsedClassId] = [parsedTokenId];
86
+ if (!collectionIds.includes(parsedClassId)) {
87
+ collectionIds.push(parsedClassId);
89
88
  }
89
+ nftIds.push(parsedTokenId);
90
90
  const [tokenInfo, collectionMeta] = await Promise.all([this.getTokenDetails(assetId), this.getCollectionDetails(parseInt(parsedClassId))]);
91
91
  const parsedNft = {
92
92
  id: parsedTokenId,
@@ -110,8 +110,8 @@ export class AcalaNftApi extends BaseNftApi {
110
110
  };
111
111
  params.updateItem(this.chain, parsedNft, address);
112
112
  params.updateCollection(this.chain, parsedCollection);
113
- // params.updateReady(true);
114
113
  }));
114
+ params.cleanUpNfts(this.chain, address, collectionIds, nftIds);
115
115
  } catch (e) {
116
116
  console.error('Failed to fetch acala nft', e);
117
117
  }
@@ -73,17 +73,18 @@ export class BitCountryNftApi extends BaseNftApi {
73
73
  const assetIds = await this.getNfts([address]);
74
74
  try {
75
75
  if (!assetIds || assetIds.length === 0) {
76
+ params.cleanUpNfts(this.chain, address, [], [], true);
76
77
  return;
77
78
  }
78
- const collectionNftIds = {};
79
+ const collectionIds = [];
80
+ const nftIds = [];
79
81
  await Promise.all(assetIds.map(async assetId => {
80
82
  const parsedClassId = this.parseTokenId(assetId.classId);
81
83
  const parsedTokenId = this.parseTokenId(assetId.tokenId);
82
- if (collectionNftIds[parsedClassId]) {
83
- collectionNftIds[parsedClassId].push(parsedTokenId);
84
- } else {
85
- collectionNftIds[parsedClassId] = [parsedTokenId];
84
+ if (!collectionIds.includes(parsedClassId)) {
85
+ collectionIds.push(parsedClassId);
86
86
  }
87
+ nftIds.push(parsedTokenId);
87
88
  const [tokenInfo, collectionMeta] = await Promise.all([this.getTokenDetails(assetId), this.getCollectionDetails(parsedClassId)]);
88
89
  const parsedNft = {
89
90
  id: parsedTokenId,
@@ -107,8 +108,8 @@ export class BitCountryNftApi extends BaseNftApi {
107
108
  };
108
109
  params.updateItem(this.chain, parsedNft, address);
109
110
  params.updateCollection(this.chain, parsedCollection);
110
- // params.updateReady(true);
111
111
  }));
112
+ params.cleanUpNfts(this.chain, address, collectionIds, nftIds);
112
113
  } catch (e) {
113
114
  console.error('Failed to fetch bit.country nft', e);
114
115
  }
@@ -75,6 +75,7 @@ export class EvmNftApi extends BaseNftApi {
75
75
  const contract = new this.evmApi.api.eth.Contract(_ERC721_ABI, smartContract);
76
76
  let ownItem = false;
77
77
  let collectionImage;
78
+ const nftOwnerMap = {};
78
79
  await Promise.all(this.addresses.map(async address => {
79
80
  if (!isEthereumAddress(address)) {
80
81
  return;
@@ -84,6 +85,7 @@ export class EvmNftApi extends BaseNftApi {
84
85
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
85
86
  const balance = await contract.methods.balanceOf(address).call();
86
87
  if (Number(balance) === 0) {
88
+ nftParams.cleanUpNfts(this.chain, address, [smartContract], []);
87
89
  return;
88
90
  }
89
91
  const itemIndexes = [];
@@ -125,8 +127,9 @@ export class EvmNftApi extends BaseNftApi {
125
127
  }
126
128
  }
127
129
  }));
130
+ nftOwnerMap[address] = nftIds;
128
131
  } catch (e) {
129
- console.error('evm nft error', e);
132
+ console.error('EVM NFT error', e);
130
133
  }
131
134
  }));
132
135
  if (ownItem) {
@@ -138,10 +141,11 @@ export class EvmNftApi extends BaseNftApi {
138
141
  originAsset: tokenInfo.slug
139
142
  };
140
143
  nftParams.updateCollection(this.chain, nftCollection);
141
- // nftParams.updateReady(true);
144
+ Object.entries(nftOwnerMap).forEach(([owner, nftIds]) => {
145
+ nftParams.cleanUpNfts(this.chain, owner, [smartContract], nftIds);
146
+ });
142
147
  }
143
148
  }
144
-
145
149
  async handleNfts(params) {
146
150
  if (!this.evmContracts || this.evmContracts.length === 0) {
147
151
  return;
@@ -17,6 +17,5 @@ export declare class NftHandler {
17
17
  setAddresses(addresses: string[]): void;
18
18
  private setupNftContracts;
19
19
  private setupApi;
20
- handleNfts(nftContracts: _ChainAsset[], updateItem: (chain: string, data: NftItem, owner: string) => void, updateCollection: (chain: string, data: NftCollection) => void): Promise<void>;
21
- parseAssetId(id: string): string;
20
+ handleNfts(nftContracts: _ChainAsset[], updateItem: (chain: string, data: NftItem, owner: string) => void, updateCollection: (chain: string, data: NftCollection) => void, cleanUpNfts: (chain: string, owner: string, collectionId: string[], nftIds: string[], ownNothing?: boolean) => void): Promise<void>;
22
21
  }
@@ -124,18 +124,15 @@ export class NftHandler {
124
124
  console.error('error setting up nft handlers', e);
125
125
  }
126
126
  }
127
- async handleNfts(nftContracts, updateItem, updateCollection) {
127
+ async handleNfts(nftContracts, updateItem, updateCollection, cleanUpNfts) {
128
128
  this.setupApi();
129
129
  this.setupNftContracts(nftContracts);
130
130
  await Promise.all(this.handlers.map(async handler => {
131
131
  await handler.fetchNfts({
132
132
  updateItem,
133
- updateCollection
133
+ updateCollection,
134
+ cleanUpNfts
134
135
  });
135
136
  }));
136
137
  }
137
- parseAssetId(id) {
138
- const numberId = parseInt(id);
139
- return numberId.toString();
140
- }
141
138
  }
@@ -82,17 +82,18 @@ export class KaruraNftApi extends BaseNftApi {
82
82
  const assetIds = await this.getNfts([address]);
83
83
  try {
84
84
  if (!assetIds || assetIds.length === 0) {
85
+ params.cleanUpNfts(this.chain, address, [], [], true);
85
86
  return;
86
87
  }
87
- const collectionNftIds = {};
88
+ const collectionIds = [];
89
+ const nftIds = [];
88
90
  await Promise.all(assetIds.map(async assetId => {
89
91
  const parsedClassId = this.parseTokenId(assetId.classId);
90
92
  const parsedTokenId = this.parseTokenId(assetId.tokenId);
91
- if (collectionNftIds[parsedClassId]) {
92
- collectionNftIds[parsedClassId].push(parsedTokenId);
93
- } else {
94
- collectionNftIds[parsedClassId] = [parsedTokenId];
93
+ if (!collectionIds.includes(parsedClassId)) {
94
+ collectionIds.push(parsedClassId);
95
95
  }
96
+ nftIds.push(parsedTokenId);
96
97
  const [tokenInfo, collectionMeta] = await Promise.all([this.getTokenDetails(assetId), this.getCollectionDetails(parseInt(parsedClassId))]);
97
98
  const parsedNft = {
98
99
  id: parsedTokenId,
@@ -114,8 +115,8 @@ export class KaruraNftApi extends BaseNftApi {
114
115
  };
115
116
  params.updateItem(this.chain, parsedNft, address);
116
117
  params.updateCollection(this.chain, parsedCollection);
117
- // params.updateReady(true);
118
118
  }));
119
+ params.cleanUpNfts(this.chain, address, collectionIds, nftIds);
119
120
  } catch (e) {
120
121
  console.error('Failed to fetch karura nft', e);
121
122
  }
@@ -3,6 +3,7 @@ import { _EvmApi, _SubstrateApi } from '@subwallet/extension-base/services/chain
3
3
  export interface HandleNftParams {
4
4
  updateItem: (chain: string, data: NftItem, owner: string) => void;
5
5
  updateCollection: (chain: string, data: NftCollection) => void;
6
+ cleanUpNfts: (chain: string, owner: string, collectionId: string[], nftIds: string[], ownNothing?: boolean) => void;
6
7
  }
7
8
  export declare abstract class BaseNftApi {
8
9
  chain: string;
@@ -132,6 +132,7 @@ export class RmrkNftApi extends BaseNftApi {
132
132
  const kusamaAddress = reformatAddress(address, 2);
133
133
  allNfts = await this.getAllByAccount(kusamaAddress);
134
134
  if (allNfts.length <= 0) {
135
+ params.cleanUpNfts(this.chain, address, [], [], true);
135
136
  return;
136
137
  }
137
138
  const collectionInfoUrl = [];
@@ -231,9 +232,18 @@ export class RmrkNftApi extends BaseNftApi {
231
232
  image: allCollectionMeta[item.collectionId] ? this.parseUrl(allCollectionMeta[item.collectionId].image) : null,
232
233
  chain: this.chain
233
234
  };
235
+ const nftIds = [];
236
+ allNfts.forEach(nft => {
237
+ const nftCollectionId = nft === null || nft === void 0 ? void 0 : nft.collectionId;
238
+ if (nftCollectionId === item.collectionId) {
239
+ nftIds.push(nft === null || nft === void 0 ? void 0 : nft.id);
240
+ }
241
+ });
234
242
  params.updateCollection(this.chain, parsedCollection);
235
- // params.updateReady(true);
236
243
  });
244
+ const allCollectionIds = allCollections.map(item => item.collectionId);
245
+ const allNftIds = allNfts.map(nft => nft === null || nft === void 0 ? void 0 : nft.id);
246
+ params.cleanUpNfts(this.chain, address, allCollectionIds, allNftIds);
237
247
  } catch (e) {
238
248
  console.error('Failed to fetch rmrk nft', e);
239
249
  }
@@ -86,17 +86,18 @@ export default class StatemineNftApi extends BaseNftApi {
86
86
  const assetIds = await this.getNfts([address]);
87
87
  try {
88
88
  if (!assetIds || assetIds.length === 0) {
89
+ params.cleanUpNfts(this.chain, address, [], [], true);
89
90
  return;
90
91
  }
91
- const collectionNftIds = {};
92
+ const collectionIds = [];
93
+ const nftIds = [];
92
94
  await Promise.all(assetIds.map(async assetId => {
93
95
  const parsedClassId = this.parseTokenId(assetId.classId);
94
96
  const parsedTokenId = this.parseTokenId(assetId.tokenId);
95
- if (collectionNftIds[parsedClassId]) {
96
- collectionNftIds[parsedClassId].push(parsedTokenId);
97
- } else {
98
- collectionNftIds[parsedClassId] = [parsedTokenId];
97
+ if (!collectionIds.includes(parsedClassId)) {
98
+ collectionIds.push(parsedClassId);
99
99
  }
100
+ nftIds.push(parsedTokenId);
100
101
  const [tokenInfo, collectionMeta] = await Promise.all([this.getTokenDetails(assetId), this.getCollectionDetail(parseInt(parsedClassId))]);
101
102
  const parsedNft = {
102
103
  id: parsedTokenId,
@@ -115,8 +116,8 @@ export default class StatemineNftApi extends BaseNftApi {
115
116
  image: collectionMeta && collectionMeta.image ? this.parseUrl(collectionMeta === null || collectionMeta === void 0 ? void 0 : collectionMeta.image) : undefined
116
117
  };
117
118
  params.updateCollection(this.chain, parsedCollection);
118
- // params.updateReady(true);
119
119
  }));
120
+ params.cleanUpNfts(this.chain, address, collectionIds, nftIds);
120
121
  } catch (e) {
121
122
  console.error('Failed to fetch statemine nft', e);
122
123
  }
@@ -133,6 +133,8 @@ export default class UniqueNftApi extends BaseNftApi {
133
133
  }
134
134
  }
135
135
  }));
136
+ const collectionIds = [];
137
+ let allNftIds = [];
136
138
  await Promise.all(allCollectionId.map(async collectionId => {
137
139
  const collectionIdStr = collectionId.toString();
138
140
 
@@ -140,6 +142,8 @@ export default class UniqueNftApi extends BaseNftApi {
140
142
  const collection = (await this.substrateApi.api.query.nft.collectionById(collectionId)).toJSON();
141
143
  collectionMap[collectionIdStr] = collection;
142
144
  const nftIds = Object.entries(nftMap).filter(item => item[1] === collectionId).map(item => item[0]);
145
+ collectionIds.push(collectionIdStr);
146
+ allNftIds = allNftIds.concat(nftIds);
143
147
  const parsedCollection = {
144
148
  collectionId: collectionIdStr,
145
149
  chain: this.chain
@@ -166,10 +170,10 @@ export default class UniqueNftApi extends BaseNftApi {
166
170
  }
167
171
  params.updateItem(this.chain, parsedItem, address);
168
172
  params.updateCollection(this.chain, parsedCollection);
169
- // params.updateReady(true);
170
173
  }
171
174
  }));
172
175
  }));
176
+ params.cleanUpNfts(this.chain, address, collectionIds, allNftIds);
173
177
  } catch (e) {
174
178
  console.error('Failed to fetch unique nft', e);
175
179
  }
@@ -8,8 +8,6 @@ export declare class WasmNftApi extends BaseNftApi {
8
8
  private parseFeaturedTokenUri;
9
9
  private parseFeaturedNftImage;
10
10
  private parseFeaturedCollectionImage;
11
- private getCollectionAttributes;
12
- private processOnChainMetadata;
13
11
  private processOffChainMetadata;
14
12
  private getItemsByCollection;
15
13
  fetchNfts(params: HandleNftParams): Promise<number>;