@subwallet/extension-base 1.3.79-1 → 1.3.81-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.
- package/background/KoniTypes.d.ts +13 -3
- package/cjs/core/substrate/system-pallet.js +3 -0
- package/cjs/core/substrate/xcm-parser.js +1 -1
- package/cjs/koni/api/contract-handler/utils/index.js +0 -3
- package/cjs/koni/api/nft/index.js +0 -14
- package/cjs/koni/background/cron.js +0 -17
- package/cjs/koni/background/handlers/Extension.js +15 -7
- package/cjs/koni/background/handlers/State.js +24 -6
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/helpers/process.js +49 -21
- package/cjs/services/balance-service/index.js +2 -2
- package/cjs/services/balance-service/transfer/xcm/index.js +1 -1
- package/cjs/services/balance-service/transfer/xcm/polygonBridge.js +1 -8
- package/cjs/services/chain-service/constants.js +6 -2
- package/cjs/services/chain-service/utils/patch.js +1 -1
- package/cjs/services/earning-service/handlers/special.js +3 -2
- package/cjs/services/fee-service/utils/index.js +2 -4
- package/cjs/services/inapp-notification-service/utils/polygon.js +4 -1
- package/cjs/services/nft-service/index.js +219 -150
- package/cjs/services/nft-service/multi-chain-nft-fetcher.js +145 -0
- package/cjs/services/nft-service/nft-handlers/base-nft-handler.js +28 -0
- package/cjs/services/nft-service/nft-handlers/evm/evm-nft-handler.js +179 -0
- package/cjs/services/nft-service/nft-handlers/registry.js +37 -0
- package/cjs/services/nft-service/nft-handlers/unique/unique-nft-handler.js +187 -0
- package/cjs/services/price-service/coingecko.js +1 -1
- package/cjs/services/storage-service/DatabaseService.js +1 -1
- package/core/substrate/system-pallet.js +3 -0
- package/core/substrate/xcm-parser.js +1 -1
- package/koni/api/contract-handler/utils/index.js +0 -3
- package/koni/api/nft/index.js +1 -15
- package/koni/background/cron.d.ts +0 -1
- package/koni/background/cron.js +1 -18
- package/koni/background/handlers/Extension.d.ts +1 -0
- package/koni/background/handlers/Extension.js +15 -7
- package/koni/background/handlers/State.d.ts +8 -2
- package/koni/background/handlers/State.js +24 -6
- package/package.json +32 -7
- package/packageInfo.js +1 -1
- package/services/balance-service/helpers/process.d.ts +1 -1
- package/services/balance-service/helpers/process.js +48 -21
- package/services/balance-service/index.js +2 -2
- package/services/balance-service/transfer/xcm/index.js +1 -1
- package/services/balance-service/transfer/xcm/polygonBridge.d.ts +0 -2
- package/services/balance-service/transfer/xcm/polygonBridge.js +1 -8
- package/services/chain-service/constants.d.ts +3 -0
- package/services/chain-service/constants.js +3 -0
- package/services/chain-service/utils/patch.d.ts +1 -1
- package/services/chain-service/utils/patch.js +1 -1
- package/services/earning-service/handlers/special.js +4 -3
- package/services/fee-service/utils/index.js +2 -4
- package/services/inapp-notification-service/utils/polygon.js +4 -1
- package/services/nft-service/index.d.ts +42 -6
- package/services/nft-service/index.js +219 -151
- package/services/nft-service/multi-chain-nft-fetcher.d.ts +13 -0
- package/services/nft-service/multi-chain-nft-fetcher.js +138 -0
- package/services/nft-service/nft-handlers/base-nft-handler.d.ts +13 -0
- package/services/nft-service/nft-handlers/base-nft-handler.js +21 -0
- package/services/nft-service/nft-handlers/evm/evm-nft-handler.d.ts +9 -0
- package/services/nft-service/nft-handlers/evm/evm-nft-handler.js +171 -0
- package/services/nft-service/nft-handlers/registry.d.ts +11 -0
- package/services/nft-service/nft-handlers/registry.js +29 -0
- package/services/nft-service/nft-handlers/unique/unique-nft-handler.d.ts +12 -0
- package/services/nft-service/nft-handlers/unique/unique-nft-handler.js +177 -0
- package/services/price-service/coingecko.js +1 -1
- package/services/storage-service/DatabaseService.d.ts +1 -1
- 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;
|
|
@@ -100,7 +100,7 @@ const getPriceMap = async function (priceIds) {
|
|
|
100
100
|
var _response4;
|
|
101
101
|
useBackupApi = true;
|
|
102
102
|
try {
|
|
103
|
-
response = await fetch(
|
|
103
|
+
response = await fetch(`${apiCacheDomain}/api/price/get?ids=${idStr}`);
|
|
104
104
|
} catch (e) {}
|
|
105
105
|
if (((_response4 = response) === null || _response4 === void 0 ? void 0 : _response4.status) !== 200) {
|
|
106
106
|
try {
|
|
@@ -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(
|
|
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) {
|
|
@@ -31,7 +31,7 @@ function getAvailBridgeWarning() {
|
|
|
31
31
|
return 'Cross-chain transfer of this token may take up to 90 minutes, and you’ll need to manually claim the funds on the destination network to complete the transfer. Do you still want to continue?';
|
|
32
32
|
}
|
|
33
33
|
function getPolygonBridgeWarning(originChainInfo) {
|
|
34
|
-
if (originChainInfo.slug === COMMON_CHAIN_SLUGS.
|
|
34
|
+
if (originChainInfo.slug === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA) {
|
|
35
35
|
return 'Cross-chain transfer of this token may take up to 40 minutes. Do you still want to continue?';
|
|
36
36
|
} else {
|
|
37
37
|
return 'Cross-chain transfer of this token may take up to 3 hours, and you’ll need to manually claim the funds on the destination network to complete the transfer. Do you still want to continue?';
|
|
@@ -52,13 +52,10 @@ export function getAvailBridgeGatewayContract(chain) {
|
|
|
52
52
|
export function isAvailBridgeGatewayContract(contractAddress) {
|
|
53
53
|
return [AVAILBRIDGE_GATEWAY_ETHEREUM_CONTRACT_ADDRESS, AVAILBRIDGE_GATEWAY_SEPOLIA_CONTRACT_ADDRESS].includes(contractAddress);
|
|
54
54
|
}
|
|
55
|
-
const POLYGONBRIDGE_GATEWAY_ETHEREUM_CONTRACT_ADDRESS = '0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe';
|
|
56
55
|
const POLYGONBRIDGE_GATEWAY_SEPOLIA_CONTRACT_ADDRESS = '0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582';
|
|
57
56
|
export function getPolygonBridgeContract(chain) {
|
|
58
57
|
if (chain === 'polygonzkEvm_cardona' || chain === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA) {
|
|
59
58
|
return POLYGONBRIDGE_GATEWAY_SEPOLIA_CONTRACT_ADDRESS;
|
|
60
|
-
} else if (chain === 'polygonZkEvm' || chain === COMMON_CHAIN_SLUGS.ETHEREUM) {
|
|
61
|
-
return POLYGONBRIDGE_GATEWAY_ETHEREUM_CONTRACT_ADDRESS;
|
|
62
59
|
}
|
|
63
60
|
throw new Error('Invalid chain');
|
|
64
61
|
}
|
package/koni/api/nft/index.js
CHANGED
|
@@ -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 {
|
|
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;
|
package/koni/background/cron.js
CHANGED
|
@@ -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 {
|
|
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
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { Common } from '@ethereumjs/common';
|
|
5
5
|
import { LegacyTransaction } from '@ethereumjs/tx';
|
|
6
|
+
import { COMMON_CHAIN_SLUGS } from '@subwallet/chain-list';
|
|
6
7
|
import { _AssetType } from '@subwallet/chain-list/types';
|
|
7
8
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
8
9
|
import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers';
|
|
@@ -1150,7 +1151,10 @@ export default class KoniExtension {
|
|
|
1150
1151
|
return this.getNft();
|
|
1151
1152
|
}
|
|
1152
1153
|
async handleGetNftFullList(request) {
|
|
1153
|
-
return this.#koniState.
|
|
1154
|
+
return this.#koniState.nftService.fetchFullListNftOfACollection(request);
|
|
1155
|
+
}
|
|
1156
|
+
async handleGetNftDetail(request) {
|
|
1157
|
+
return this.#koniState.nftService.fetchNftDetail(request);
|
|
1154
1158
|
}
|
|
1155
1159
|
getStakingReward() {
|
|
1156
1160
|
return new Promise((resolve, reject) => {
|
|
@@ -5159,6 +5163,9 @@ export default class KoniExtension {
|
|
|
5159
5163
|
});
|
|
5160
5164
|
}
|
|
5161
5165
|
async getIsClaimedPolygonBridge(data) {
|
|
5166
|
+
if (data.chainslug !== COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA) {
|
|
5167
|
+
throw new Error('Polygon zkEVM Mainnet Beta has sunset. Please use Polygon official Ethereum claim flow.');
|
|
5168
|
+
}
|
|
5162
5169
|
const evmApi = this.#koniState.getEvmApi(data.chainslug);
|
|
5163
5170
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
5164
5171
|
const isClaimed = await isClaimedPolygonBridge(data.chainslug, data.counter, data.sourceNetwork, evmApi);
|
|
@@ -5172,12 +5179,15 @@ export default class KoniExtension {
|
|
|
5172
5179
|
} = data;
|
|
5173
5180
|
const extrinsicType = ExtrinsicType.CLAIM_BRIDGE;
|
|
5174
5181
|
let transaction = null;
|
|
5175
|
-
const evmApi = this.#koniState.getEvmApi(chain);
|
|
5176
5182
|
const metadata = notification.metadata;
|
|
5183
|
+
if (metadata.bridgeType !== 'POS' && chain !== COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA) {
|
|
5184
|
+
throw new Error('Polygon zkEVM Mainnet Beta has sunset. Please use Polygon official Ethereum claim flow.');
|
|
5185
|
+
}
|
|
5186
|
+
const evmApi = this.#koniState.getEvmApi(chain);
|
|
5177
5187
|
const feeInfo = await this.#koniState.feeService.subscribeChainFee(getId(), chain, 'evm');
|
|
5178
5188
|
if (metadata.bridgeType === 'POS') {
|
|
5179
5189
|
transaction = await getClaimPosBridge(chain, notification, evmApi, feeInfo);
|
|
5180
|
-
} else {
|
|
5190
|
+
} else if (chain === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA) {
|
|
5181
5191
|
transaction = await getClaimPolygonBridge(chain, notification, evmApi, feeInfo);
|
|
5182
5192
|
}
|
|
5183
5193
|
const chainType = ChainType.EVM;
|
|
@@ -5657,16 +5667,14 @@ export default class KoniExtension {
|
|
|
5657
5667
|
return this.getCrowdloanContributions(request);
|
|
5658
5668
|
case 'pri(crowdloan.getSubscription)':
|
|
5659
5669
|
return this.subscribeCrowdloan(id, port);
|
|
5660
|
-
case 'pri(nft.getNft)':
|
|
5661
|
-
return await this.getNft();
|
|
5662
5670
|
case 'pri(nft.getSubscription)':
|
|
5663
5671
|
return await this.subscribeNft(id, port);
|
|
5664
|
-
case 'pri(nftCollection.getNftCollection)':
|
|
5665
|
-
return await this.getNftCollection();
|
|
5666
5672
|
case 'pri(nftCollection.getSubscription)':
|
|
5667
5673
|
return await this.subscribeNftCollection(id, port);
|
|
5668
5674
|
case 'pri(nft.getFullList)':
|
|
5669
5675
|
return await this.handleGetNftFullList(request);
|
|
5676
|
+
case 'pri(nft.getNftdetail)':
|
|
5677
|
+
return await this.handleGetNftDetail(request);
|
|
5670
5678
|
case 'pri(staking.getStaking)':
|
|
5671
5679
|
return this.getStaking();
|
|
5672
5680
|
case 'pri(staking.getSubscription)':
|