@subwallet/extension-base 1.3.79-1 → 1.3.80-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 (48) hide show
  1. package/background/KoniTypes.d.ts +13 -3
  2. package/cjs/core/substrate/system-pallet.js +3 -0
  3. package/cjs/koni/api/nft/index.js +0 -14
  4. package/cjs/koni/background/cron.js +0 -17
  5. package/cjs/koni/background/handlers/Extension.js +6 -5
  6. package/cjs/koni/background/handlers/State.js +24 -6
  7. package/cjs/packageInfo.js +1 -1
  8. package/cjs/services/balance-service/helpers/process.js +49 -21
  9. package/cjs/services/balance-service/index.js +2 -2
  10. package/cjs/services/chain-service/constants.js +6 -2
  11. package/cjs/services/earning-service/handlers/special.js +3 -2
  12. package/cjs/services/nft-service/index.js +219 -150
  13. package/cjs/services/nft-service/multi-chain-nft-fetcher.js +145 -0
  14. package/cjs/services/nft-service/nft-handlers/base-nft-handler.js +28 -0
  15. package/cjs/services/nft-service/nft-handlers/evm/evm-nft-handler.js +179 -0
  16. package/cjs/services/nft-service/nft-handlers/registry.js +37 -0
  17. package/cjs/services/nft-service/nft-handlers/unique/unique-nft-handler.js +187 -0
  18. package/cjs/services/storage-service/DatabaseService.js +1 -1
  19. package/core/substrate/system-pallet.js +3 -0
  20. package/koni/api/nft/index.js +1 -15
  21. package/koni/background/cron.d.ts +0 -1
  22. package/koni/background/cron.js +1 -18
  23. package/koni/background/handlers/Extension.d.ts +1 -0
  24. package/koni/background/handlers/Extension.js +6 -5
  25. package/koni/background/handlers/State.d.ts +8 -2
  26. package/koni/background/handlers/State.js +24 -6
  27. package/package.json +31 -6
  28. package/packageInfo.js +1 -1
  29. package/services/balance-service/helpers/process.d.ts +1 -1
  30. package/services/balance-service/helpers/process.js +48 -21
  31. package/services/balance-service/index.js +2 -2
  32. package/services/chain-service/constants.d.ts +3 -0
  33. package/services/chain-service/constants.js +3 -0
  34. package/services/earning-service/handlers/special.js +4 -3
  35. package/services/nft-service/index.d.ts +42 -6
  36. package/services/nft-service/index.js +219 -151
  37. package/services/nft-service/multi-chain-nft-fetcher.d.ts +13 -0
  38. package/services/nft-service/multi-chain-nft-fetcher.js +138 -0
  39. package/services/nft-service/nft-handlers/base-nft-handler.d.ts +13 -0
  40. package/services/nft-service/nft-handlers/base-nft-handler.js +21 -0
  41. package/services/nft-service/nft-handlers/evm/evm-nft-handler.d.ts +9 -0
  42. package/services/nft-service/nft-handlers/evm/evm-nft-handler.js +171 -0
  43. package/services/nft-service/nft-handlers/registry.d.ts +11 -0
  44. package/services/nft-service/nft-handlers/registry.js +29 -0
  45. package/services/nft-service/nft-handlers/unique/unique-nft-handler.d.ts +12 -0
  46. package/services/nft-service/nft-handlers/unique/unique-nft-handler.js +177 -0
  47. package/services/storage-service/DatabaseService.d.ts +1 -1
  48. package/services/storage-service/DatabaseService.js +1 -1
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.EvmNftHandler = void 0;
8
+ var _types = require("@subwallet/chain-list/types");
9
+ var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
10
+ var _utils = require("@subwallet/extension-base/services/chain-service/utils");
11
+ var _utils2 = require("@subwallet/extension-base/utils");
12
+ var _subwalletServicesSdk = _interopRequireDefault(require("@subwallet-monorepos/subwallet-services-sdk"));
13
+ var _baseNftHandler = require("../base-nft-handler");
14
+ // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
15
+ // SPDX-License-Identifier: Apache-2.0
16
+
17
+ class EvmNftHandler extends _baseNftHandler.BaseNftHandler {
18
+ filterAddresses(addresses) {
19
+ return (0, _utils2.getAddressesByChainType)(addresses, [_KoniTypes.ChainType.EVM]);
20
+ }
21
+ mapSdkToNftItem(rawInstance, collectionId, owner) {
22
+ var _rawInstance$token_ty, _rawInstance$id;
23
+ const metadata = rawInstance.metadata || {};
24
+ const image = metadata.image || rawInstance.image_url || rawInstance.media_url || '';
25
+ const attributes = Array.isArray(metadata.attributes) ? metadata.attributes : [];
26
+ let rarity;
27
+ const properties = {};
28
+ for (const attr of attributes) {
29
+ try {
30
+ var _attr$trait_type;
31
+ const key = (_attr$trait_type = attr.trait_type) === null || _attr$trait_type === void 0 ? void 0 : _attr$trait_type.trim();
32
+ if (!key) {
33
+ continue;
34
+ }
35
+ let value = attr.value;
36
+ if (typeof value === 'string') {
37
+ const lower = value.toLowerCase();
38
+ if (lower === 'true') {
39
+ value = true;
40
+ }
41
+ if (lower === 'false') {
42
+ value = false;
43
+ }
44
+ }
45
+ properties[key] = value;
46
+ if (key.toLowerCase() === 'rarity') {
47
+ rarity = String(value);
48
+ }
49
+ } catch {
50
+ // ignore
51
+ }
52
+ }
53
+ const normalizedType = (_rawInstance$token_ty = rawInstance.token_type) === null || _rawInstance$token_ty === void 0 ? void 0 : _rawInstance$token_ty.replace('-', '').toUpperCase();
54
+ if (!['ERC721'].includes(normalizedType)) {
55
+ return null;
56
+ }
57
+ return {
58
+ id: ((_rawInstance$id = rawInstance.id) === null || _rawInstance$id === void 0 ? void 0 : _rawInstance$id.toString()) || '',
59
+ chain: this.chain,
60
+ collectionId,
61
+ owner: rawInstance.owner || owner,
62
+ name: metadata.name || `#${rawInstance.id}`,
63
+ image: (0, _utils2.baseParseIPFSUrl)(image),
64
+ externalUrl: rawInstance.external_app_url || undefined,
65
+ rarity,
66
+ description: metadata.description || undefined,
67
+ properties: Object.keys(properties).length > 0 ? properties : null,
68
+ type: normalizedType === 'ERC721' ? _types._AssetType.ERC721 : _types._AssetType.ERC721,
69
+ originAsset: undefined,
70
+ rmrk_ver: undefined,
71
+ onChainOption: undefined,
72
+ assetHubType: undefined
73
+ };
74
+ }
75
+ mapSdkToCollection(raw) {
76
+ var _raw$token_instances;
77
+ const token = raw.token || {};
78
+ return {
79
+ collectionId: token.address_hash,
80
+ chain: this.chain,
81
+ collectionName: token.name || token.symbol || 'Unknown Collection',
82
+ image: token.icon_url || undefined,
83
+ itemCount: Number(raw.amount) || ((_raw$token_instances = raw.token_instances) === null || _raw$token_instances === void 0 ? void 0 : _raw$token_instances.length) || 0,
84
+ externalUrl: undefined,
85
+ originAsset: undefined
86
+ };
87
+ }
88
+
89
+ // ==================== 1. PREVIEW – Used for cron / background ====================
90
+ async fetchPreview(addresses) {
91
+ const items = [];
92
+ const collections = [];
93
+ const api = _subwalletServicesSdk.default.nftDetectionApi;
94
+ if (!(api !== null && api !== void 0 && api.getEvmNftCollectionsByAddress)) {
95
+ console.warn('[EvmNftHandler] Preview API not available');
96
+ return {
97
+ items,
98
+ collections
99
+ };
100
+ }
101
+ for (const address of addresses) {
102
+ try {
103
+ const rawData = await api.getEvmNftCollectionsByAddress(address);
104
+ for (const [chain, sdkCollections] of Object.entries(rawData)) {
105
+ if (chain !== this.chain || !Array.isArray(sdkCollections)) {
106
+ continue;
107
+ }
108
+ for (const col of sdkCollections) {
109
+ const collection = this.mapSdkToCollection(col);
110
+ collections.push(collection);
111
+ if (Array.isArray(col.token_instances)) {
112
+ const mapped = col.token_instances.map(inst => this.mapSdkToNftItem(inst, collection.collectionId, address)).filter(i => i !== null);
113
+ items.push(...mapped);
114
+ }
115
+ }
116
+ }
117
+ } catch (error) {
118
+ console.error(`[EvmNftHandler] Preview failed for ${address}`, error);
119
+ }
120
+ }
121
+ return {
122
+ items: items,
123
+ collections: collections
124
+ };
125
+ }
126
+
127
+ // ==================== 2. FULL – At collection details screen ====================
128
+ async fetchFullListNftOfACollection(request) {
129
+ const items = [];
130
+ const collections = [];
131
+ const {
132
+ chainInfo,
133
+ collectionId,
134
+ owners
135
+ } = request;
136
+ const chainId = (0, _utils._getEvmChainId)(chainInfo);
137
+ if (!collectionId || !owners || !chainId) {
138
+ console.warn('[NftService] missing params for getFullNftInstancesByCollection');
139
+ return {
140
+ items,
141
+ collections
142
+ };
143
+ }
144
+ try {
145
+ const nftDetectionApi = _subwalletServicesSdk.default.nftDetectionApi;
146
+ if (!(nftDetectionApi !== null && nftDetectionApi !== void 0 && nftDetectionApi.getAllNftInstances)) {
147
+ console.warn('[NftService] getAllNftInstances not available');
148
+ return {
149
+ items,
150
+ collections
151
+ };
152
+ }
153
+ const ownerList = Array.isArray(owners) ? owners : [owners];
154
+ for (const eachOwner of ownerList) {
155
+ try {
156
+ const instances = await nftDetectionApi.getAllNftInstances(collectionId, eachOwner, chainId.toString());
157
+ if (!Array.isArray(instances)) {
158
+ continue;
159
+ }
160
+ const mappedItems = instances.map(inst => this.mapSdkToNftItem(inst, collectionId, eachOwner)).filter(i => Boolean(i));
161
+ items.push(...mappedItems);
162
+ } catch (innerErr) {
163
+ console.warn(`[NftService] getAllNftInstances failed for ${eachOwner}`, innerErr);
164
+ }
165
+ }
166
+ } catch (err) {
167
+ console.error(`[NftDetectionService] getFullNftInstancesByCollection error for ${collectionId}`, err);
168
+ return {
169
+ items: [],
170
+ collections: []
171
+ };
172
+ }
173
+ return {
174
+ items: items,
175
+ collections: collections
176
+ };
177
+ }
178
+ }
179
+ exports.EvmNftHandler = EvmNftHandler;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.NFT_HANDLER_REGISTRY = void 0;
7
+ exports.isNftV2Chain = isNftV2Chain;
8
+ var _constants = require("@subwallet/extension-base/services/chain-service/constants");
9
+ var _utils = require("@subwallet/extension-base/services/chain-service/utils");
10
+ var _evmNftHandler = require("@subwallet/extension-base/services/nft-service/nft-handlers/evm/evm-nft-handler");
11
+ var _uniqueNftHandler = require("@subwallet/extension-base/services/nft-service/nft-handlers/unique/unique-nft-handler");
12
+ // Copyright 2019-2022 @subwallet/extension-base authors & contributors
13
+ // SPDX-License-Identifier: Apache-2.0
14
+
15
+ function isNftV2Chain(chainInfo, registry) {
16
+ return registry.some(desc => desc.supports(chainInfo));
17
+ }
18
+
19
+ // todo list: only update into when migration
20
+ const NFT_HANDLER_REGISTRY = [{
21
+ id: 'evm',
22
+ supports: chainInfo => (0, _utils._isChainSupportEvmNft)(chainInfo),
23
+ supportsFetchFullNftList: true,
24
+ create: chain => new _evmNftHandler.EvmNftHandler(chain)
25
+ }, {
26
+ id: 'unique_network',
27
+ supports: chainInfo => _constants.NFT_CHAIN_GROUPS_MIGRATED.unique_network.includes(chainInfo.slug),
28
+ supportsFetchFullNftList: false,
29
+ create: chain => new _uniqueNftHandler.UniqueNftHandler(chain)
30
+ }
31
+ // {
32
+ // id: 'ordinal',
33
+ // supports: (chainInfo) => _isSupportOrdinal(chainInfo.slug),
34
+ // create: (chain, state) => new OrdinalNftHandler(chain, state)
35
+ // }
36
+ ];
37
+ exports.NFT_HANDLER_REGISTRY = NFT_HANDLER_REGISTRY;
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.UniqueNftHandler = void 0;
8
+ var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
9
+ var _utils = require("@subwallet/extension-base/utils");
10
+ var _subwalletServicesSdk = _interopRequireDefault(require("@subwallet-monorepos/subwallet-services-sdk"));
11
+ var _baseNftHandler = require("../base-nft-handler");
12
+ // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
13
+ // SPDX-License-Identifier: Apache-2.0
14
+
15
+ class UniqueNftHandler extends _baseNftHandler.BaseNftHandler {
16
+ filterAddresses(addresses) {
17
+ return (0, _utils.getAddressesByChainType)(addresses, [_KoniTypes.ChainType.SUBSTRATE]);
18
+ }
19
+ mapUniqueCollections(raws) {
20
+ var _raws$collectionCover;
21
+ return {
22
+ collectionId: raws.collectionId.toString(),
23
+ chain: this.chain,
24
+ collectionName: raws.collectionName || 'Unknown Collection',
25
+ image: ((_raws$collectionCover = raws.collectionCover) === null || _raws$collectionCover === void 0 ? void 0 : _raws$collectionCover.url) || undefined,
26
+ externalUrl: undefined,
27
+ originAsset: undefined
28
+ };
29
+ }
30
+ mapUniqueRootNftToItem(raw, owner) {
31
+ return {
32
+ id: raw.tokenId.toString(),
33
+ chain: this.chain,
34
+ collectionId: raw.collectionId.toString(),
35
+ name: raw.name || `#${raw.tokenId}`,
36
+ image: raw.image || undefined,
37
+ description: raw.description || undefined,
38
+ owner: owner,
39
+ isBundle: false,
40
+ properties: null
41
+ };
42
+ }
43
+ mapBundleTreeToNftItem(node, topmostOwner) {
44
+ let level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
45
+ let parentId = arguments.length > 3 ? arguments[3] : undefined;
46
+ const item = {
47
+ id: node.tokenId.toString(),
48
+ chain: this.chain,
49
+ collectionId: node.collectionId.toString(),
50
+ name: node.name || `#${node.tokenId}`,
51
+ image: node.image || undefined,
52
+ description: node.description || undefined,
53
+ owner: topmostOwner,
54
+ isBundle: node.nested && node.nested.length > 0 && level === 0,
55
+ properties: null,
56
+ nestingLevel: level,
57
+ parentId: level > 0 ? parentId : undefined
58
+ };
59
+ if (node.nested && node.nested.length > 0) {
60
+ item.nestingTokens = node.nested.map(child => this.mapBundleTreeToNftItem(child, topmostOwner, level + 1, item.id));
61
+ }
62
+ return item;
63
+ }
64
+ async fetchNftBundle(collectionId, tokenId, topmostOwner) {
65
+ const api = _subwalletServicesSdk.default.uniqueNftDetectionApi;
66
+ if (!api) {
67
+ return null;
68
+ }
69
+ try {
70
+ const treeData = await api.getNftBundleTree(collectionId, tokenId);
71
+ if (!treeData) {
72
+ return null;
73
+ }
74
+ return this.mapBundleTreeToNftItem(treeData, topmostOwner, 0, tokenId);
75
+ } catch (e) {
76
+ console.error('[UniqueNftHandler] Failed to fetch bundle tree', e);
77
+ return null;
78
+ }
79
+ }
80
+
81
+ // ==================== MAIN HANDLER ====================
82
+
83
+ async fetchPreview(addresses) {
84
+ const items = [];
85
+ const collectionsMap = new Map();
86
+ const api = _subwalletServicesSdk.default.uniqueNftDetectionApi;
87
+ if (!api) {
88
+ return {
89
+ items: [],
90
+ collections: []
91
+ };
92
+ }
93
+ try {
94
+ await Promise.all(addresses.map(async address => {
95
+ // 1. Collections
96
+ const sdkCollections = await api.getUniqueCollectionsByTokenOwner(address);
97
+ for (const col of sdkCollections) {
98
+ const collection = this.mapUniqueCollections(col);
99
+ if (!collectionsMap.has(collection.collectionId)) {
100
+ collectionsMap.set(collection.collectionId, collection);
101
+ }
102
+ }
103
+
104
+ // 2. Root NFTs
105
+ const sdkNfts = await api.getAllUniqueRootNfts({
106
+ owner: address
107
+ });
108
+ for (const rootNft of sdkNfts) {
109
+ items.push(this.mapUniqueRootNftToItem(rootNft, address));
110
+ }
111
+ }));
112
+ } catch (e) {
113
+ console.error(`[UniqueNftHandler] Failed to fetch for ${this.chain}`, e);
114
+ }
115
+ return {
116
+ items,
117
+ collections: Array.from(collectionsMap.values())
118
+ };
119
+ }
120
+ async fetchFullListNftOfACollection(request) {
121
+ const items = [];
122
+ const collections = [];
123
+ const {
124
+ collectionId,
125
+ owners,
126
+ tokenIds
127
+ } = request;
128
+ if (!collectionId || !owners || !tokenIds) {
129
+ console.warn('[NftService] missing params for getFullNftInstancesByCollection');
130
+ return {
131
+ items,
132
+ collections
133
+ };
134
+ }
135
+ for (const id of tokenIds) {
136
+ const fullTree = await this.fetchNftBundle(collectionId, id, owners[0]);
137
+ if (fullTree) {
138
+ items.push(fullTree);
139
+ }
140
+ }
141
+ return {
142
+ items: items,
143
+ collections: collections
144
+ };
145
+ }
146
+ async fetchNftDetail(request) {
147
+ const items = [];
148
+ const collections = [];
149
+ const api = _subwalletServicesSdk.default.uniqueNftDetectionApi;
150
+ if (!api) {
151
+ return {
152
+ items: [],
153
+ collections: []
154
+ };
155
+ }
156
+ const {
157
+ collectionId,
158
+ tokenId
159
+ } = request;
160
+ if (!collectionId || !tokenId) {
161
+ return {
162
+ items,
163
+ collections
164
+ };
165
+ }
166
+ try {
167
+ const rawNft = await api.getNftDetail(collectionId, tokenId);
168
+ if (!rawNft) {
169
+ return {
170
+ items: [],
171
+ collections: []
172
+ };
173
+ }
174
+ const nftItem = this.mapUniqueRootNftToItem(rawNft, rawNft.owner);
175
+ return {
176
+ items: [nftItem],
177
+ collections: []
178
+ };
179
+ } catch (e) {
180
+ return {
181
+ items: [],
182
+ collections: []
183
+ };
184
+ }
185
+ }
186
+ }
187
+ exports.UniqueNftHandler = UniqueNftHandler;
@@ -404,7 +404,7 @@ class DatabaseService {
404
404
  return this.stores.nft.removeNfts(chain, address, collectionId, nftIds);
405
405
  }
406
406
  removeNftsByAddress(address) {
407
- return this.stores.nft.removeNftsByAddress([address]);
407
+ return this.stores.nft.removeNftsByAddress(address);
408
408
  }
409
409
 
410
410
  // Chain
@@ -43,6 +43,9 @@ function _getAppliedExistentialDeposit(accountInfo, existentialDeposit, strictMo
43
43
  if (strictMode) {
44
44
  return bnExistentialDeposit;
45
45
  }
46
+ if (accountInfo.data.free.toString() === existentialDeposit) {
47
+ return BigInt(0);
48
+ }
46
49
  return _canAccountBeReaped(accountInfo) ? BigInt(0) : bnExistentialDeposit; // account for ED here will go better with max transfer logic
47
50
  }
48
51
  function _getSystemPalletTransferableV2(accountInfo, existentialDeposit, strictMode) {
@@ -14,7 +14,7 @@ import { UniqueNftApi } from '@subwallet/extension-base/koni/api/nft/unique_netw
14
14
  import { VaraNftApi } from '@subwallet/extension-base/koni/api/nft/vara_nft';
15
15
  import { WasmNftApi } from '@subwallet/extension-base/koni/api/nft/wasm_nft';
16
16
  import { _NFT_CHAIN_GROUP } from '@subwallet/extension-base/services/chain-service/constants';
17
- import { _isChainSupportEvmNft, _isChainSupportNativeNft, _isChainSupportWasmNft, _isSupportOrdinal } from '@subwallet/extension-base/services/chain-service/utils';
17
+ import { _isChainSupportNativeNft, _isChainSupportWasmNft, _isSupportOrdinal } from '@subwallet/extension-base/services/chain-service/utils';
18
18
  import { getAddressesByChainType, targetIsWeb } from '@subwallet/extension-base/utils';
19
19
  import AssetHubNftsPalletApi from "./assethub_nft/index.js";
20
20
  import { RariNftApi } from "./rari/index.js";
@@ -33,8 +33,6 @@ function createSubstrateNftApi(chain, substrateApi, addresses) {
33
33
  return [new AssetHubUniquesPalletApi(substrateApi, substrateAddresses, chain), new AssetHubNftsPalletApi(substrateApi, substrateAddresses, chain)];
34
34
  } else if (_NFT_CHAIN_GROUP.statemint.includes(chain)) {
35
35
  return [new AssetHubUniquesPalletApi(substrateApi, substrateAddresses, chain), new AssetHubNftsPalletApi(substrateApi, substrateAddresses, chain)];
36
- } else if (_NFT_CHAIN_GROUP.unique_network.includes(chain)) {
37
- return [new UniqueNftApi(chain, substrateAddresses)];
38
36
  } else if (_NFT_CHAIN_GROUP.unique_evm.includes(chain)) {
39
37
  return [new UniqueNftApi(chain, evmAddresses)];
40
38
  } else if (_NFT_CHAIN_GROUP.bitcountry.includes(chain)) {
@@ -56,10 +54,6 @@ function createWasmNftApi(chain, apiProps, addresses) {
56
54
  const substrateAddresses = getAddressesByChainType(addresses, [ChainType.SUBSTRATE]);
57
55
  return new WasmNftApi(apiProps, substrateAddresses, chain);
58
56
  }
59
- function createWeb3NftApi(chain, evmApi, addresses) {
60
- const evmAddresses = getAddressesByChainType(addresses, [ChainType.EVM]);
61
- return new EvmNftApi(evmApi, evmAddresses, chain);
62
- }
63
57
  const createOrdinalApi = (chain, subscanChain, addresses) => {
64
58
  return new OrdinalNftApi(addresses, chain, subscanChain);
65
59
  };
@@ -128,14 +122,6 @@ export class NftHandler {
128
122
  }
129
123
  }
130
124
  }
131
- if (_isChainSupportEvmNft(chainInfo)) {
132
- if (this.evmApiMap[chain]) {
133
- const handler = createWeb3NftApi(chain, this.evmApiMap[chain], evmAddresses);
134
- if (handler) {
135
- this.handlers.push(handler);
136
- }
137
- }
138
- }
139
125
  if (chain === 'unique_evm') {
140
126
  const handlers = createSubstrateNftApi(chain, null, evmAddresses);
141
127
  if (handlers && !!handlers.length) {
@@ -29,7 +29,6 @@ export declare class KoniCron {
29
29
  refreshNft: (address: string, apiMap: ApiMap, smartContractNfts: _ChainAsset[], chainInfoMap: Record<string, _ChainInfo>) => () => void;
30
30
  resetNft: (newAddress: string) => void;
31
31
  checkNetworkAvailable: (serviceInfo: ServiceInfo) => boolean;
32
- detectEvmCollectionNft: (address: string) => () => void;
33
32
  reloadNft(): Promise<boolean>;
34
33
  reloadStaking(): Promise<boolean>;
35
34
  private needUpdateNft;
@@ -1,7 +1,7 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- import { CRON_NFT_DETECT_INTERVAL, CRON_REFRESH_CHAIN_STAKING_METADATA, CRON_REFRESH_MKT_CAMPAIGN_INTERVAL, CRON_REFRESH_NFT_INTERVAL, CRON_SYNC_MANTA_PAY } from '@subwallet/extension-base/constants';
4
+ import { CRON_REFRESH_CHAIN_STAKING_METADATA, CRON_REFRESH_MKT_CAMPAIGN_INTERVAL, CRON_REFRESH_NFT_INTERVAL, CRON_SYNC_MANTA_PAY } from '@subwallet/extension-base/constants';
5
5
  import { _isChainSupportEvmNft, _isChainSupportNativeNft, _isChainSupportWasmNft } from '@subwallet/extension-base/services/chain-service/utils';
6
6
  import { waitTimeout } from '@subwallet/extension-base/utils';
7
7
  import { Subject } from 'rxjs';
@@ -87,7 +87,6 @@ export class KoniCron {
87
87
  // NFT
88
88
  (commonReload || needUpdateNft) && this.resetNft(address);
89
89
  (commonReload || needUpdateNft) && this.removeCron('refreshNft');
90
- (commonReload || needUpdateNft) && this.removeCron('detectNft');
91
90
  commonReload && this.removeCron('refreshPoolingStakingReward');
92
91
  if (mktCampaignNeedReload) {
93
92
  this.removeCron('fetchMktCampaignData');
@@ -103,7 +102,6 @@ export class KoniCron {
103
102
  if (this.checkNetworkAvailable(serviceInfo)) {
104
103
  // only add cron jobs if there's at least 1 active network
105
104
  (commonReload || needUpdateNft) && this.addCron('refreshNft', this.refreshNft(address, serviceInfo.chainApiMap, this.state.getSmartContractNfts(), this.state.getActiveChainInfoMap()), CRON_REFRESH_NFT_INTERVAL);
106
- (commonReload || needUpdateNft) && this.addCron('detectNft', this.detectEvmCollectionNft(address), CRON_NFT_DETECT_INTERVAL);
107
105
  reloadMantaPay && this.addCron('syncMantaPay', this.syncMantaPay, CRON_SYNC_MANTA_PAY);
108
106
  }
109
107
  };
@@ -116,8 +114,6 @@ export class KoniCron {
116
114
  if (Object.keys(this.state.getSubstrateApiMap()).length !== 0 || Object.keys(this.state.getEvmApiMap()).length !== 0) {
117
115
  this.resetNft(currentAccountInfo.proxyId);
118
116
  this.addCron('refreshNft', this.refreshNft(currentAccountInfo.proxyId, this.state.getApiMap(), this.state.getSmartContractNfts(), this.state.getActiveChainInfoMap()), CRON_REFRESH_NFT_INTERVAL);
119
- this.addCron('detectNft', this.detectEvmCollectionNft(currentAccountInfo.proxyId), CRON_NFT_DETECT_INTERVAL);
120
- // this.addCron('refreshStakingReward', this.refreshStakingReward(currentAccountInfo.address), CRON_REFRESH_STAKING_REWARD_INTERVAL);
121
117
  this.addCron('syncMantaPay', this.syncMantaPay, CRON_SYNC_MANTA_PAY);
122
118
  }
123
119
  this.status = 'running';
@@ -166,25 +162,12 @@ export class KoniCron {
166
162
  checkNetworkAvailable = serviceInfo => {
167
163
  return Object.keys(serviceInfo.chainApiMap.substrate).length > 0 || Object.keys(serviceInfo.chainApiMap.evm).length > 0;
168
164
  };
169
- detectEvmCollectionNft = address => {
170
- return () => {
171
- let addresses = [];
172
- addresses = this.state.keyringService.context.getDecodedAddresses();
173
- if (!addresses.length) {
174
- console.warn('[Cron] No decoded addresses found for ALL_ACCOUNT_KEY');
175
- return;
176
- }
177
- this.state.nftDetectionService.fetchEvmCollectionsWithPreview(addresses).catch(err => console.warn(`[Cron] NFT detection failed for ${address}:`, err));
178
- };
179
- };
180
165
  async reloadNft() {
181
166
  const address = this.state.keyringService.context.currentAccount.proxyId;
182
167
  const serviceInfo = this.state.getServiceInfo();
183
168
  this.resetNft(address);
184
169
  this.removeCron('refreshNft');
185
- this.removeCron('detectNft');
186
170
  this.addCron('refreshNft', this.refreshNft(address, serviceInfo.chainApiMap, this.state.getSmartContractNfts(), this.state.getActiveChainInfoMap()), CRON_REFRESH_NFT_INTERVAL);
187
- this.addCron('detectNft', this.detectEvmCollectionNft(address), CRON_NFT_DETECT_INTERVAL);
188
171
  await waitTimeout(1800);
189
172
  return true;
190
173
  }
@@ -117,6 +117,7 @@ export default class KoniExtension {
117
117
  private getNft;
118
118
  private subscribeNft;
119
119
  private handleGetNftFullList;
120
+ private handleGetNftDetail;
120
121
  private getStakingReward;
121
122
  private subscribeStakingReward;
122
123
  private getStaking;
@@ -1150,7 +1150,10 @@ export default class KoniExtension {
1150
1150
  return this.getNft();
1151
1151
  }
1152
1152
  async handleGetNftFullList(request) {
1153
- return this.#koniState.nftDetectionService.getFullNftInstancesByCollection(request);
1153
+ return this.#koniState.nftService.fetchFullListNftOfACollection(request);
1154
+ }
1155
+ async handleGetNftDetail(request) {
1156
+ return this.#koniState.nftService.fetchNftDetail(request);
1154
1157
  }
1155
1158
  getStakingReward() {
1156
1159
  return new Promise((resolve, reject) => {
@@ -5657,16 +5660,14 @@ export default class KoniExtension {
5657
5660
  return this.getCrowdloanContributions(request);
5658
5661
  case 'pri(crowdloan.getSubscription)':
5659
5662
  return this.subscribeCrowdloan(id, port);
5660
- case 'pri(nft.getNft)':
5661
- return await this.getNft();
5662
5663
  case 'pri(nft.getSubscription)':
5663
5664
  return await this.subscribeNft(id, port);
5664
- case 'pri(nftCollection.getNftCollection)':
5665
- return await this.getNftCollection();
5666
5665
  case 'pri(nftCollection.getSubscription)':
5667
5666
  return await this.subscribeNftCollection(id, port);
5668
5667
  case 'pri(nft.getFullList)':
5669
5668
  return await this.handleGetNftFullList(request);
5669
+ case 'pri(nft.getNftdetail)':
5670
+ return await this.handleGetNftDetail(request);
5670
5671
  case 'pri(staking.getStaking)':
5671
5672
  return this.getStaking();
5672
5673
  case 'pri(staking.getSubscription)':
@@ -20,7 +20,7 @@ import MigrationService from '@subwallet/extension-base/services/migration-servi
20
20
  import MintCampaignService from '@subwallet/extension-base/services/mint-campaign-service';
21
21
  import MktCampaignService from '@subwallet/extension-base/services/mkt-campaign-service';
22
22
  import { MultisigService } from '@subwallet/extension-base/services/multisig-service';
23
- import NftService from '@subwallet/extension-base/services/nft-service';
23
+ import { NftService } from '@subwallet/extension-base/services/nft-service';
24
24
  import NotificationService from '@subwallet/extension-base/services/notification-service/NotificationService';
25
25
  import OpenGovService from '@subwallet/extension-base/services/open-gov';
26
26
  import { PriceService } from '@subwallet/extension-base/services/price-service';
@@ -48,6 +48,11 @@ export default class KoniState {
48
48
  private externalRequest;
49
49
  private crowdloanMap;
50
50
  private crowdloanSubject;
51
+ /**
52
+ * TODO: Remove this subject once NFT migration to the service layer is completed.
53
+ * The state manager should not handle the internal state of the NFT service.
54
+ * The NFT service will manage its own state independently.
55
+ */
51
56
  private nftSubject;
52
57
  private mantaPayConfigSubject;
53
58
  isMantaPayEnabled: boolean;
@@ -77,7 +82,7 @@ export default class KoniState {
77
82
  readonly mintCampaignService: MintCampaignService;
78
83
  readonly campaignService: CampaignService;
79
84
  readonly mktCampaignService: MktCampaignService;
80
- readonly nftDetectionService: NftService;
85
+ readonly nftService: NftService;
81
86
  readonly buyService: BuyService;
82
87
  readonly earningService: EarningService;
83
88
  readonly feeService: FeeService;
@@ -273,6 +278,7 @@ export default class KoniState {
273
278
  onAccountAdd(): void;
274
279
  onAccountRemove(): void;
275
280
  reloadNft(): Promise<boolean>;
281
+ reloadNftV2(): Promise<void>;
276
282
  reloadStaking(): Promise<boolean>;
277
283
  reloadBalance(): Promise<boolean>;
278
284
  approvePassPhishingPage(_url: string): Promise<boolean>;