@subwallet/extension-base 1.3.1 → 1.3.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.
- package/background/KoniTypes.d.ts +5 -1
- package/cjs/constants/index.js +7 -1
- package/cjs/koni/api/nft/assethub_nft/index.js +30 -7
- package/cjs/koni/api/nft/config.js +11 -1
- package/cjs/koni/api/nft/index.js +9 -0
- package/cjs/koni/api/nft/ternoa_nft/index.js +174 -0
- package/cjs/koni/api/staking/bonding/utils.js +1 -1
- package/cjs/koni/background/handlers/Extension.js +67 -32
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +9 -0
- package/cjs/services/chain-service/constants.js +2 -1
- package/cjs/services/chain-service/index.js +11 -14
- package/cjs/services/earning-service/constants/chains.js +2 -1
- package/cjs/services/earning-service/handlers/base.js +2 -1
- package/cjs/services/earning-service/handlers/native-staking/index.js +8 -1
- package/cjs/services/earning-service/handlers/native-staking/tao.js +394 -0
- package/cjs/services/earning-service/service.js +3 -0
- package/cjs/services/earning-service/utils/index.js +2 -0
- package/cjs/services/keyring-service/context/handlers/Modify.js +11 -3
- package/cjs/services/keyring-service/context/state.js +2 -3
- package/cjs/services/keyring-service/index.js +1 -1
- package/cjs/services/swap-service/handler/chainflip-handler.js +13 -5
- package/cjs/services/transaction-service/utils.js +6 -0
- package/cjs/types/swap/index.js +4 -2
- package/cjs/utils/account/derive/info/solo.js +2 -0
- package/cjs/utils/account/derive/info/unified.js +2 -0
- package/cjs/utils/account/transform.js +4 -4
- package/constants/index.d.ts +2 -0
- package/constants/index.js +2 -0
- package/koni/api/nft/assethub_nft/index.d.ts +2 -0
- package/koni/api/nft/assethub_nft/index.js +30 -7
- package/koni/api/nft/config.d.ts +4 -0
- package/koni/api/nft/config.js +6 -0
- package/koni/api/nft/index.js +9 -0
- package/koni/api/nft/ternoa_nft/index.d.ts +32 -0
- package/koni/api/nft/ternoa_nft/index.js +167 -0
- package/koni/api/staking/bonding/utils.js +1 -1
- package/koni/background/handlers/Extension.d.ts +1 -0
- package/koni/background/handlers/Extension.js +38 -3
- package/package.json +16 -6
- package/packageInfo.js +1 -1
- package/services/balance-service/helpers/subscribe/substrate/index.js +9 -0
- package/services/chain-service/constants.d.ts +1 -0
- package/services/chain-service/constants.js +2 -1
- package/services/chain-service/index.js +11 -14
- package/services/earning-service/constants/chains.d.ts +1 -0
- package/services/earning-service/constants/chains.js +2 -1
- package/services/earning-service/handlers/base.js +2 -1
- package/services/earning-service/handlers/native-staking/index.d.ts +1 -0
- package/services/earning-service/handlers/native-staking/index.js +2 -1
- package/services/earning-service/handlers/native-staking/tao.d.ts +49 -0
- package/services/earning-service/handlers/native-staking/tao.js +378 -0
- package/services/earning-service/service.js +4 -1
- package/services/earning-service/utils/index.js +2 -0
- package/services/keyring-service/context/handlers/Modify.js +11 -3
- package/services/keyring-service/context/state.js +2 -3
- package/services/keyring-service/index.d.ts +1 -1
- package/services/keyring-service/index.js +1 -1
- package/services/swap-service/handler/chainflip-handler.js +13 -5
- package/services/transaction-service/utils.js +6 -0
- package/types/swap/index.d.ts +1 -0
- package/types/swap/index.js +2 -1
- package/utils/account/derive/info/solo.js +2 -0
- package/utils/account/derive/info/unified.js +2 -0
- package/utils/account/transform.js +4 -4
|
@@ -198,6 +198,8 @@ const findSoloNextDerive = parentAddress => {
|
|
|
198
198
|
}
|
|
199
199
|
if (deriveIndex === index) {
|
|
200
200
|
index++;
|
|
201
|
+
} else if (currentDepth === 0 && deriveIndex === 0 && index > deriveIndex) {
|
|
202
|
+
// Special case for the first account on the root
|
|
201
203
|
} else {
|
|
202
204
|
break;
|
|
203
205
|
}
|
|
@@ -95,6 +95,8 @@ const findUnifiedNextDerive = (proxyId, accounts) => {
|
|
|
95
95
|
}
|
|
96
96
|
if (deriveIndex === index) {
|
|
97
97
|
index++;
|
|
98
|
+
} else if (currentDepth === 0 && deriveIndex === 0 && index > deriveIndex) {
|
|
99
|
+
// Special case for the first account on the root
|
|
98
100
|
} else {
|
|
99
101
|
break;
|
|
100
102
|
}
|
|
@@ -424,10 +424,10 @@ const _combineAccounts = (accounts, modifyPairs, accountProxies) => {
|
|
|
424
424
|
accountActions.push(_types2.AccountActions.EXPORT_MNEMONIC);
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
-
//
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
427
|
+
// Json
|
|
428
|
+
if (value.accounts.every(account => account.accountActions.includes(_types2.AccountActions.EXPORT_JSON))) {
|
|
429
|
+
accountActions.push(_types2.AccountActions.EXPORT_JSON);
|
|
430
|
+
}
|
|
431
431
|
|
|
432
432
|
// Derive
|
|
433
433
|
if (value.accounts.every(account => account.accountActions.includes(_types2.AccountActions.DERIVE))) {
|
package/constants/index.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export declare const CRON_REFRESH_CHAIN_NOMINATOR_METADATA = 1800000;
|
|
|
18
18
|
export declare const CRON_RECOVER_HISTORY_INTERVAL = 30000;
|
|
19
19
|
export declare const CRON_SYNC_MANTA_PAY = 300000;
|
|
20
20
|
export declare const MANTA_PAY_BALANCE_INTERVAL = 30000;
|
|
21
|
+
export declare const BITTENSOR_REFRESH_STAKE_INFO = 30000;
|
|
22
|
+
export declare const BITTENSOR_REFRESH_STAKE_APY = 300000;
|
|
21
23
|
export declare const CRON_REFRESH_EARNING_REWARD_HISTORY_INTERVAL: number;
|
|
22
24
|
export declare const ALL_ACCOUNT_KEY = "ALL";
|
|
23
25
|
export declare const ALL_NETWORK_KEY = "all";
|
package/constants/index.js
CHANGED
|
@@ -20,6 +20,8 @@ export const CRON_REFRESH_CHAIN_NOMINATOR_METADATA = 1800000;
|
|
|
20
20
|
export const CRON_RECOVER_HISTORY_INTERVAL = 30000;
|
|
21
21
|
export const CRON_SYNC_MANTA_PAY = 300000;
|
|
22
22
|
export const MANTA_PAY_BALANCE_INTERVAL = 30000;
|
|
23
|
+
export const BITTENSOR_REFRESH_STAKE_INFO = 30000;
|
|
24
|
+
export const BITTENSOR_REFRESH_STAKE_APY = 300000;
|
|
23
25
|
export const CRON_REFRESH_EARNING_REWARD_HISTORY_INTERVAL = 15 * BASE_MINUTE_INTERVAL;
|
|
24
26
|
export const ALL_ACCOUNT_KEY = 'ALL';
|
|
25
27
|
export const ALL_NETWORK_KEY = 'all';
|
|
@@ -3,6 +3,8 @@ import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/
|
|
|
3
3
|
export default class AssetHubNftsPalletApi extends BaseNftApi {
|
|
4
4
|
constructor(api: _SubstrateApi | null, addresses: string[], chain: string);
|
|
5
5
|
private getMetadata;
|
|
6
|
+
private processImageUrl;
|
|
7
|
+
private parseTokenInfo;
|
|
6
8
|
/**
|
|
7
9
|
* Retrieve id of NFTs
|
|
8
10
|
*
|
|
@@ -24,6 +24,21 @@ export default class AssetHubNftsPalletApi extends BaseNftApi {
|
|
|
24
24
|
}
|
|
25
25
|
}).then(res => res.json());
|
|
26
26
|
}
|
|
27
|
+
processImageUrl(image, isKodadot, isTokenInfo) {
|
|
28
|
+
if (!image) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
if (isKodadot) {
|
|
32
|
+
return isTokenInfo ? image.replace('ipfs://ipfs/', 'https://image.w.kodadot.xyz/ipfs/') : image.replace('ipfs://', 'https://image.w.kodadot.xyz/ipfs/');
|
|
33
|
+
}
|
|
34
|
+
return this.parseUrl(image);
|
|
35
|
+
}
|
|
36
|
+
parseTokenInfo(tokenInfo, classId) {
|
|
37
|
+
if (classId === '244' && tokenInfo) {
|
|
38
|
+
return JSON.parse(tokenInfo);
|
|
39
|
+
}
|
|
40
|
+
return tokenInfo;
|
|
41
|
+
}
|
|
27
42
|
|
|
28
43
|
/**
|
|
29
44
|
* Retrieve id of NFTs
|
|
@@ -81,8 +96,6 @@ export default class AssetHubNftsPalletApi extends BaseNftApi {
|
|
|
81
96
|
return this.getMetadata(collectionMetadata === null || collectionMetadata === void 0 ? void 0 : collectionMetadata.data);
|
|
82
97
|
}
|
|
83
98
|
async handleNft(address, params) {
|
|
84
|
-
// const start = performance.now();
|
|
85
|
-
|
|
86
99
|
const assetIds = await this.getNfts([address]);
|
|
87
100
|
try {
|
|
88
101
|
if (!assetIds || assetIds.length === 0) {
|
|
@@ -91,18 +104,28 @@ export default class AssetHubNftsPalletApi extends BaseNftApi {
|
|
|
91
104
|
const collectionIds = [];
|
|
92
105
|
const nftIds = [];
|
|
93
106
|
await Promise.all(assetIds.map(async assetId => {
|
|
107
|
+
var _tokenInfo2, _tokenInfo3, _tokenInfo4;
|
|
94
108
|
const parsedClassId = this.parseTokenId(assetId.classId);
|
|
95
109
|
const parsedTokenId = this.parseTokenId(assetId.tokenId);
|
|
96
110
|
if (!collectionIds.includes(parsedClassId)) {
|
|
97
111
|
collectionIds.push(parsedClassId);
|
|
98
112
|
}
|
|
99
113
|
nftIds.push(parsedTokenId);
|
|
100
|
-
|
|
114
|
+
let [tokenInfo, collectionMeta] = await Promise.all([this.getTokenDetails(assetId), this.getCollectionDetail(parseInt(parsedClassId))]);
|
|
115
|
+
const isKodadot = assetId.classId === '244';
|
|
116
|
+
tokenInfo = this.parseTokenInfo(tokenInfo, assetId.classId);
|
|
117
|
+
if (tokenInfo) {
|
|
118
|
+
var _tokenInfo;
|
|
119
|
+
tokenInfo.image = this.processImageUrl((_tokenInfo = tokenInfo) === null || _tokenInfo === void 0 ? void 0 : _tokenInfo.image, isKodadot, true);
|
|
120
|
+
}
|
|
121
|
+
if (collectionMeta) {
|
|
122
|
+
collectionMeta.image = this.processImageUrl(collectionMeta === null || collectionMeta === void 0 ? void 0 : collectionMeta.image, isKodadot, false);
|
|
123
|
+
}
|
|
101
124
|
const parsedNft = {
|
|
102
125
|
id: parsedTokenId,
|
|
103
|
-
name: tokenInfo === null ||
|
|
104
|
-
description: tokenInfo === null ||
|
|
105
|
-
image:
|
|
126
|
+
name: (_tokenInfo2 = tokenInfo) === null || _tokenInfo2 === void 0 ? void 0 : _tokenInfo2.name,
|
|
127
|
+
description: (_tokenInfo3 = tokenInfo) === null || _tokenInfo3 === void 0 ? void 0 : _tokenInfo3.description,
|
|
128
|
+
image: (_tokenInfo4 = tokenInfo) === null || _tokenInfo4 === void 0 ? void 0 : _tokenInfo4.image,
|
|
106
129
|
collectionId: this.parseTokenId(parsedClassId),
|
|
107
130
|
chain: this.chain,
|
|
108
131
|
owner: address,
|
|
@@ -113,7 +136,7 @@ export default class AssetHubNftsPalletApi extends BaseNftApi {
|
|
|
113
136
|
collectionId: parsedClassId,
|
|
114
137
|
chain: this.chain,
|
|
115
138
|
collectionName: collectionMeta === null || collectionMeta === void 0 ? void 0 : collectionMeta.name,
|
|
116
|
-
image: collectionMeta
|
|
139
|
+
image: collectionMeta === null || collectionMeta === void 0 ? void 0 : collectionMeta.image
|
|
117
140
|
};
|
|
118
141
|
params.updateCollection(this.chain, parsedCollection);
|
|
119
142
|
}));
|
package/koni/api/nft/config.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ export declare const IPFS_W3S_LINK = "https://w3s.link/ipfs/";
|
|
|
23
23
|
export declare const GATEWAY_IPFS_IO = "https://gateway.ipfs.io/ipfs/";
|
|
24
24
|
export declare const IPFS_IO = "https://ipfs.io/ipfs/";
|
|
25
25
|
export declare const DWEB_LINK = "https://dweb.link/ipfs/";
|
|
26
|
+
export declare const TERNOA_MAINNET_CLIENT_NFT = "https://indexer-mainnet.ternoa.dev";
|
|
27
|
+
export declare const TERNOA_ALPHANET_CLIENT_NFT = "https://indexer-alphanet.ternoa.dev";
|
|
28
|
+
export declare const TERNOA_MAINNET_GATEWAY = "https://ipfs-mainnet.trnnfr.com/ipfs/";
|
|
29
|
+
export declare const TERNOA_ALPHANET_GATEWAY = "https://ipfs-dev.trnnfr.com/ipfs/";
|
|
26
30
|
export declare const IPFS_GATEWAY_4EVERLAND = "https://4everland.io/ipfs/";
|
|
27
31
|
export declare const IPFS_FLEEK = "https://ipfs.fleek.co/ipfs/";
|
|
28
32
|
export declare const W3S_IPFS = "https://w3s.link/ipfs/";
|
package/koni/api/nft/config.js
CHANGED
|
@@ -48,6 +48,12 @@ export const IPFS_IO = 'https://ipfs.io/ipfs/';
|
|
|
48
48
|
|
|
49
49
|
// XOrigin
|
|
50
50
|
export const DWEB_LINK = 'https://dweb.link/ipfs/';
|
|
51
|
+
|
|
52
|
+
// XOrigin
|
|
53
|
+
export const TERNOA_MAINNET_CLIENT_NFT = 'https://indexer-mainnet.ternoa.dev';
|
|
54
|
+
export const TERNOA_ALPHANET_CLIENT_NFT = 'https://indexer-alphanet.ternoa.dev';
|
|
55
|
+
export const TERNOA_MAINNET_GATEWAY = 'https://ipfs-mainnet.trnnfr.com/ipfs/';
|
|
56
|
+
export const TERNOA_ALPHANET_GATEWAY = 'https://ipfs-dev.trnnfr.com/ipfs/';
|
|
51
57
|
export const IPFS_GATEWAY_4EVERLAND = 'https://4everland.io/ipfs/';
|
|
52
58
|
export const IPFS_FLEEK = 'https://ipfs.fleek.co/ipfs/';
|
|
53
59
|
export const W3S_IPFS = 'https://w3s.link/ipfs/'; // 400
|
package/koni/api/nft/index.js
CHANGED
|
@@ -17,6 +17,7 @@ import { _NFT_CHAIN_GROUP } from '@subwallet/extension-base/services/chain-servi
|
|
|
17
17
|
import { _isChainSupportEvmNft, _isChainSupportNativeNft, _isChainSupportWasmNft, _isSupportOrdinal } from '@subwallet/extension-base/services/chain-service/utils';
|
|
18
18
|
import { categoryAddresses, targetIsWeb } from '@subwallet/extension-base/utils';
|
|
19
19
|
import AssetHubNftsPalletApi from "./assethub_nft/index.js";
|
|
20
|
+
import { TernoaNftApi } from "./ternoa_nft/index.js";
|
|
20
21
|
function createSubstrateNftApi(chain, substrateApi, addresses) {
|
|
21
22
|
const {
|
|
22
23
|
evm: evmAddresses,
|
|
@@ -42,6 +43,8 @@ function createSubstrateNftApi(chain, substrateApi, addresses) {
|
|
|
42
43
|
return [new VaraNftApi(chain, substrateAddresses)];
|
|
43
44
|
} else if (_NFT_CHAIN_GROUP.avail.includes(chain)) {
|
|
44
45
|
return [new BlobInscriptionApi(chain, substrateAddresses)];
|
|
46
|
+
} else if (_NFT_CHAIN_GROUP.ternoa.includes(chain)) {
|
|
47
|
+
return [new TernoaNftApi(substrateApi, substrateAddresses, chain)];
|
|
45
48
|
}
|
|
46
49
|
return null;
|
|
47
50
|
}
|
|
@@ -139,6 +142,12 @@ export class NftHandler {
|
|
|
139
142
|
this.handlers.push(...handlers);
|
|
140
143
|
}
|
|
141
144
|
}
|
|
145
|
+
if (chain === 'ternoa') {
|
|
146
|
+
const handlers = createSubstrateNftApi(chain, this.substrateApiMap[chain], substrateAddresses);
|
|
147
|
+
if (handlers && !!handlers.length) {
|
|
148
|
+
this.handlers.push(...handlers);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
142
151
|
if (_isChainSupportWasmNft(chainInfo)) {
|
|
143
152
|
if (this.substrateApiMap[chain]) {
|
|
144
153
|
const handler = createWasmNftApi(chain, this.substrateApiMap[chain], substrateAddresses);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
|
|
2
|
+
import { BaseNftApi, HandleNftParams } from '../nft';
|
|
3
|
+
interface NftMetadata {
|
|
4
|
+
nftId: string;
|
|
5
|
+
owner: string;
|
|
6
|
+
creator: string;
|
|
7
|
+
collectionId: string;
|
|
8
|
+
offchainData: string;
|
|
9
|
+
}
|
|
10
|
+
interface NftDetail {
|
|
11
|
+
title: string;
|
|
12
|
+
description: string;
|
|
13
|
+
image: string;
|
|
14
|
+
}
|
|
15
|
+
interface CollectionDetail {
|
|
16
|
+
name: string;
|
|
17
|
+
banner_image: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class TernoaNftApi extends BaseNftApi {
|
|
20
|
+
constructor(api: _SubstrateApi | null, addresses: string[], chain: string);
|
|
21
|
+
endpoint: string;
|
|
22
|
+
parseUrl(input: string): string | undefined;
|
|
23
|
+
private static parseNftRequest;
|
|
24
|
+
fetchNftsWithDetail(address: string): Promise<Array<{
|
|
25
|
+
metadata: NftMetadata;
|
|
26
|
+
detail: NftDetail;
|
|
27
|
+
}> | null>;
|
|
28
|
+
getCollectionDetail(collectionId: string): Promise<CollectionDetail | null>;
|
|
29
|
+
handleNfts(params: HandleNftParams): Promise<void>;
|
|
30
|
+
fetchNfts(params: HandleNftParams): Promise<number>;
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// Copyright 2019-2022 @subwallet/extension-koni authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { baseParseIPFSUrl } from '@subwallet/extension-base/utils';
|
|
5
|
+
import { decodeAddress, encodeAddress } from '@polkadot/util-crypto';
|
|
6
|
+
import { TERNOA_MAINNET_CLIENT_NFT, TERNOA_MAINNET_GATEWAY } from "../config.js";
|
|
7
|
+
import { BaseNftApi } from "../nft.js";
|
|
8
|
+
export class TernoaNftApi extends BaseNftApi {
|
|
9
|
+
constructor(api, addresses, chain) {
|
|
10
|
+
super(chain, api, addresses);
|
|
11
|
+
}
|
|
12
|
+
endpoint = TERNOA_MAINNET_CLIENT_NFT;
|
|
13
|
+
parseUrl(input) {
|
|
14
|
+
return baseParseIPFSUrl(input, TERNOA_MAINNET_GATEWAY);
|
|
15
|
+
}
|
|
16
|
+
static parseNftRequest(address) {
|
|
17
|
+
return {
|
|
18
|
+
query: `
|
|
19
|
+
query {
|
|
20
|
+
nftEntities(
|
|
21
|
+
filter: {
|
|
22
|
+
owner: { equalTo: "${address}" }
|
|
23
|
+
}
|
|
24
|
+
) {
|
|
25
|
+
totalCount
|
|
26
|
+
nodes {
|
|
27
|
+
nftId
|
|
28
|
+
owner
|
|
29
|
+
creator
|
|
30
|
+
collectionId
|
|
31
|
+
offchainData
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}`
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* GET NFTs */
|
|
39
|
+
|
|
40
|
+
async fetchNftsWithDetail(address) {
|
|
41
|
+
const query = TernoaNftApi.parseNftRequest(address);
|
|
42
|
+
try {
|
|
43
|
+
const response = await fetch(this.endpoint, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: {
|
|
46
|
+
'Content-Type': 'application/json'
|
|
47
|
+
},
|
|
48
|
+
body: JSON.stringify(query)
|
|
49
|
+
});
|
|
50
|
+
const result = await response.json();
|
|
51
|
+
const nftEntities = result.data.nftEntities.nodes;
|
|
52
|
+
if (!nftEntities) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const nftDetails = await Promise.all(nftEntities.map(async nft => {
|
|
56
|
+
const ipfsUrl = `${TERNOA_MAINNET_GATEWAY}${nft.offchainData}`;
|
|
57
|
+
try {
|
|
58
|
+
const ipfsResponse = await fetch(ipfsUrl);
|
|
59
|
+
const nftDetail = await ipfsResponse.json();
|
|
60
|
+
nftDetail.image = `${TERNOA_MAINNET_GATEWAY}${nftDetail.image}`;
|
|
61
|
+
return {
|
|
62
|
+
metadata: nft,
|
|
63
|
+
detail: nftDetail
|
|
64
|
+
};
|
|
65
|
+
} catch (err) {
|
|
66
|
+
console.error('Error:', err);
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}));
|
|
70
|
+
return nftDetails.filter(nft => nft !== null);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
console.error('Error:', err);
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* GET NFTs */
|
|
78
|
+
|
|
79
|
+
/* GET Collection */
|
|
80
|
+
|
|
81
|
+
async getCollectionDetail(collectionId) {
|
|
82
|
+
if (!this.substrateApi) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
const substrateApi = await this.substrateApi.isReady;
|
|
86
|
+
try {
|
|
87
|
+
const collectionMetadata = (await substrateApi.api.query.nft.collections(parseInt(collectionId))).toHuman();
|
|
88
|
+
if (!(collectionMetadata !== null && collectionMetadata !== void 0 && collectionMetadata.offchainData)) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const ipfsUrl = `${TERNOA_MAINNET_GATEWAY}${collectionMetadata.offchainData}`;
|
|
92
|
+
const ipfsResponse = await fetch(ipfsUrl);
|
|
93
|
+
if (!ipfsResponse.ok) {
|
|
94
|
+
return {
|
|
95
|
+
name: collectionMetadata.offchainData,
|
|
96
|
+
banner_image: ''
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const collectionDetail = await ipfsResponse.json();
|
|
100
|
+
collectionDetail.banner_image = `${TERNOA_MAINNET_GATEWAY}${collectionDetail.banner_image}`;
|
|
101
|
+
return collectionDetail;
|
|
102
|
+
} catch (err) {
|
|
103
|
+
console.error('Error:', err);
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Get Collection */
|
|
109
|
+
|
|
110
|
+
async handleNfts(params) {
|
|
111
|
+
const collectionMap = new Map();
|
|
112
|
+
await Promise.all(this.addresses.map(async address => {
|
|
113
|
+
address = encodeAddress(decodeAddress(address), 42);
|
|
114
|
+
const nftDetails = await this.fetchNftsWithDetail(address);
|
|
115
|
+
if (!nftDetails || nftDetails.length === 0) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
120
|
+
await Promise.all(nftDetails.map(async nft => {
|
|
121
|
+
const {
|
|
122
|
+
detail,
|
|
123
|
+
metadata
|
|
124
|
+
} = nft;
|
|
125
|
+
let collectionId = metadata.collectionId;
|
|
126
|
+
if (!collectionId) {
|
|
127
|
+
collectionId = 'Ternoa_Collection';
|
|
128
|
+
}
|
|
129
|
+
const parsedNft = {
|
|
130
|
+
id: metadata.nftId,
|
|
131
|
+
name: detail.title,
|
|
132
|
+
description: detail.description,
|
|
133
|
+
image: detail.image ? this.parseUrl(detail.image) : undefined,
|
|
134
|
+
collectionId,
|
|
135
|
+
chain: this.chain,
|
|
136
|
+
owner: address
|
|
137
|
+
};
|
|
138
|
+
params.updateItem(this.chain, parsedNft, address);
|
|
139
|
+
if (!collectionMap.has(collectionId)) {
|
|
140
|
+
collectionMap.set(collectionId, true);
|
|
141
|
+
}
|
|
142
|
+
}));
|
|
143
|
+
}));
|
|
144
|
+
for (const collectionId of collectionMap.keys()) {
|
|
145
|
+
const collectionDetail = collectionId !== 'Ternoa_Collection' ? await this.getCollectionDetail(collectionId) : {
|
|
146
|
+
name: 'Ternoa NFTs',
|
|
147
|
+
description: 'Collection for NFTs without a specific collection',
|
|
148
|
+
banner_image: ''
|
|
149
|
+
};
|
|
150
|
+
const parsedCollection = {
|
|
151
|
+
collectionId,
|
|
152
|
+
chain: this.chain,
|
|
153
|
+
collectionName: collectionDetail === null || collectionDetail === void 0 ? void 0 : collectionDetail.name,
|
|
154
|
+
image: collectionDetail !== null && collectionDetail !== void 0 && collectionDetail.banner_image ? this.parseUrl(collectionDetail === null || collectionDetail === void 0 ? void 0 : collectionDetail.banner_image) : undefined
|
|
155
|
+
};
|
|
156
|
+
params.updateCollection(this.chain, parsedCollection);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async fetchNfts(params) {
|
|
160
|
+
try {
|
|
161
|
+
await this.handleNfts(params);
|
|
162
|
+
} catch (e) {
|
|
163
|
+
return 0;
|
|
164
|
+
}
|
|
165
|
+
return 1;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -326,7 +326,7 @@ export function getEarningStatusByNominations(bnTotalActiveStake, nominationList
|
|
|
326
326
|
export function getValidatorLabel(chain) {
|
|
327
327
|
if (_STAKING_CHAIN_GROUP.astar.includes(chain)) {
|
|
328
328
|
return 'dApp';
|
|
329
|
-
} else if (_STAKING_CHAIN_GROUP.relay.includes(chain)) {
|
|
329
|
+
} else if (_STAKING_CHAIN_GROUP.relay.includes(chain) || _STAKING_CHAIN_GROUP.bittensor.includes(chain)) {
|
|
330
330
|
return 'Validator';
|
|
331
331
|
}
|
|
332
332
|
return 'Collator';
|
|
@@ -126,6 +126,7 @@ export default class KoniExtension {
|
|
|
126
126
|
private validateNetwork;
|
|
127
127
|
private resetDefaultNetwork;
|
|
128
128
|
private recoverDotSamaApi;
|
|
129
|
+
private validateERC721Token;
|
|
129
130
|
private upsertCustomToken;
|
|
130
131
|
private deleteCustomAsset;
|
|
131
132
|
private validateCustomAsset;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { Common } from '@ethereumjs/common';
|
|
5
5
|
import { LegacyTransaction } from '@ethereumjs/tx';
|
|
6
|
+
import { _AssetType } from '@subwallet/chain-list/types';
|
|
6
7
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
7
8
|
import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers';
|
|
8
9
|
import { createSubscription } from '@subwallet/extension-base/background/handlers/subscriptions';
|
|
@@ -12,7 +13,7 @@ import { additionalValidateTransfer, additionalValidateXcmTransfer, validateTran
|
|
|
12
13
|
import { _isSnowBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser';
|
|
13
14
|
import { ALLOWED_PATH } from '@subwallet/extension-base/defaults';
|
|
14
15
|
import { getERC20SpendingApprovalTx } from '@subwallet/extension-base/koni/api/contract-handler/evm/web3';
|
|
15
|
-
import { isSnowBridgeGatewayContract } from '@subwallet/extension-base/koni/api/contract-handler/utils';
|
|
16
|
+
import { _ERC721_ABI, isSnowBridgeGatewayContract } from '@subwallet/extension-base/koni/api/contract-handler/utils';
|
|
16
17
|
import { resolveAzeroAddressToDomain, resolveAzeroDomainToAddress } from '@subwallet/extension-base/koni/api/dotsama/domain';
|
|
17
18
|
import { parseSubstrateTransaction } from '@subwallet/extension-base/koni/api/dotsama/parseTransaction';
|
|
18
19
|
import { UNSUPPORTED_TRANSFER_EVM_CHAIN_NAME } from '@subwallet/extension-base/koni/api/nft/config';
|
|
@@ -1410,13 +1411,47 @@ export default class KoniExtension {
|
|
|
1410
1411
|
return false;
|
|
1411
1412
|
}
|
|
1412
1413
|
}
|
|
1414
|
+
async validateERC721Token(data) {
|
|
1415
|
+
var _data$metadata;
|
|
1416
|
+
const evmApi = this.#koniState.getEvmApi(data.originChain);
|
|
1417
|
+
|
|
1418
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1419
|
+
const tokenContract = new evmApi.api.eth.Contract(_ERC721_ABI, (_data$metadata = data.metadata) === null || _data$metadata === void 0 ? void 0 : _data$metadata.contractAddress);
|
|
1420
|
+
try {
|
|
1421
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
1422
|
+
await tokenContract.methods.tokenOfOwnerByIndex('0xB7fdD27a8Df011816205a6e3cAA097DC4D8C2C5d', 1).call();
|
|
1423
|
+
return true;
|
|
1424
|
+
} catch (err) {
|
|
1425
|
+
const error = err;
|
|
1426
|
+
if (error.message.includes('ERC721Enumerable: owner index out of bounds')) {
|
|
1427
|
+
return true;
|
|
1428
|
+
} else {
|
|
1429
|
+
return false;
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1413
1433
|
async upsertCustomToken(data) {
|
|
1414
1434
|
try {
|
|
1435
|
+
if (data.assetType === _AssetType.ERC721) {
|
|
1436
|
+
const isCompatible = await this.validateERC721Token(data);
|
|
1437
|
+
if (!isCompatible) {
|
|
1438
|
+
return {
|
|
1439
|
+
success: false,
|
|
1440
|
+
error: 'incompatibleNFT'
|
|
1441
|
+
};
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1415
1444
|
await this.#koniState.upsertCustomToken(data);
|
|
1416
|
-
return
|
|
1445
|
+
return {
|
|
1446
|
+
success: true,
|
|
1447
|
+
error: ''
|
|
1448
|
+
};
|
|
1417
1449
|
} catch (e) {
|
|
1418
1450
|
console.error(e);
|
|
1419
|
-
return
|
|
1451
|
+
return {
|
|
1452
|
+
success: false,
|
|
1453
|
+
error: 'Error'
|
|
1454
|
+
};
|
|
1420
1455
|
}
|
|
1421
1456
|
}
|
|
1422
1457
|
async deleteCustomAsset(assetSlug) {
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"./cjs/detectPackage.js"
|
|
18
18
|
],
|
|
19
19
|
"type": "module",
|
|
20
|
-
"version": "1.3.
|
|
20
|
+
"version": "1.3.3-0",
|
|
21
21
|
"main": "./cjs/index.js",
|
|
22
22
|
"module": "./index.js",
|
|
23
23
|
"types": "./index.d.ts",
|
|
@@ -388,6 +388,11 @@
|
|
|
388
388
|
"require": "./cjs/koni/api/nft/rmrk_nft/index.js",
|
|
389
389
|
"default": "./koni/api/nft/rmrk_nft/index.js"
|
|
390
390
|
},
|
|
391
|
+
"./koni/api/nft/ternoa_nft": {
|
|
392
|
+
"types": "./koni/api/nft/ternoa_nft/index.d.ts",
|
|
393
|
+
"require": "./cjs/koni/api/nft/ternoa_nft/index.js",
|
|
394
|
+
"default": "./koni/api/nft/ternoa_nft/index.js"
|
|
395
|
+
},
|
|
391
396
|
"./koni/api/nft/transfer": {
|
|
392
397
|
"types": "./koni/api/nft/transfer.d.ts",
|
|
393
398
|
"require": "./cjs/koni/api/nft/transfer.js",
|
|
@@ -996,6 +1001,11 @@
|
|
|
996
1001
|
"require": "./cjs/services/earning-service/handlers/native-staking/relay-chain.js",
|
|
997
1002
|
"default": "./services/earning-service/handlers/native-staking/relay-chain.js"
|
|
998
1003
|
},
|
|
1004
|
+
"./services/earning-service/handlers/native-staking/tao": {
|
|
1005
|
+
"types": "./services/earning-service/handlers/native-staking/tao.d.ts",
|
|
1006
|
+
"require": "./cjs/services/earning-service/handlers/native-staking/tao.js",
|
|
1007
|
+
"default": "./services/earning-service/handlers/native-staking/tao.js"
|
|
1008
|
+
},
|
|
999
1009
|
"./services/earning-service/handlers/nomination-pool": {
|
|
1000
1010
|
"types": "./services/earning-service/handlers/nomination-pool/index.d.ts",
|
|
1001
1011
|
"require": "./cjs/services/earning-service/handlers/nomination-pool/index.js",
|
|
@@ -2371,11 +2381,11 @@
|
|
|
2371
2381
|
"@reduxjs/toolkit": "^1.9.1",
|
|
2372
2382
|
"@sora-substrate/type-definitions": "^1.17.7",
|
|
2373
2383
|
"@substrate/connect": "^0.8.9",
|
|
2374
|
-
"@subwallet/chain-list": "0.2.
|
|
2375
|
-
"@subwallet/extension-base": "^1.3.
|
|
2376
|
-
"@subwallet/extension-chains": "^1.3.
|
|
2377
|
-
"@subwallet/extension-dapp": "^1.3.
|
|
2378
|
-
"@subwallet/extension-inject": "^1.3.
|
|
2384
|
+
"@subwallet/chain-list": "0.2.90",
|
|
2385
|
+
"@subwallet/extension-base": "^1.3.3-0",
|
|
2386
|
+
"@subwallet/extension-chains": "^1.3.3-0",
|
|
2387
|
+
"@subwallet/extension-dapp": "^1.3.3-0",
|
|
2388
|
+
"@subwallet/extension-inject": "^1.3.3-0",
|
|
2379
2389
|
"@subwallet/keyring": "^0.1.8-beta.0",
|
|
2380
2390
|
"@subwallet/ui-keyring": "^0.1.8-beta.0",
|
|
2381
2391
|
"@ton/core": "^0.56.3",
|
package/packageInfo.js
CHANGED
|
@@ -7,5 +7,5 @@ export const packageInfo = {
|
|
|
7
7
|
name: '@subwallet/extension-base',
|
|
8
8
|
path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto',
|
|
9
9
|
type: 'esm',
|
|
10
|
-
version: '1.3.
|
|
10
|
+
version: '1.3.3-0'
|
|
11
11
|
};
|
|
@@ -129,6 +129,13 @@ const subscribeWithSystemAccountPallet = async ({
|
|
|
129
129
|
args: addresses
|
|
130
130
|
});
|
|
131
131
|
}
|
|
132
|
+
let bittensorStakingBalances = new Array(addresses.length).fill(new BigN(0));
|
|
133
|
+
if (['bittensor'].includes(chainInfo.slug)) {
|
|
134
|
+
bittensorStakingBalances = await Promise.all(addresses.map(async address => {
|
|
135
|
+
const TaoTotalStake = await substrateApi.api.query.subtensorModule.totalColdkeyStake(address);
|
|
136
|
+
return new BigN(TaoTotalStake.toString());
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
132
139
|
const subscription = substrateApi.subscribeDataWithMulti(params, rs => {
|
|
133
140
|
const balances = rs[systemAccountKey];
|
|
134
141
|
const poolMemberInfos = rs[poolMembersKey];
|
|
@@ -142,6 +149,8 @@ const subscribeWithSystemAccountPallet = async ({
|
|
|
142
149
|
const nominationPoolBalance = poolMemberInfo ? _getTotalStakeInNominationPool(poolMemberInfo) : BigInt(0);
|
|
143
150
|
totalLockedFromTransfer += nominationPoolBalance;
|
|
144
151
|
}
|
|
152
|
+
const stakeValue = BigInt(bittensorStakingBalances[index].toString());
|
|
153
|
+
totalLockedFromTransfer += stakeValue;
|
|
145
154
|
return {
|
|
146
155
|
address: addresses[index],
|
|
147
156
|
tokenSlug: _getChainNativeTokenSlug(chainInfo),
|
|
@@ -36,6 +36,7 @@ export declare const _NFT_CHAIN_GROUP: {
|
|
|
36
36
|
bitcountry: string[];
|
|
37
37
|
vara: string[];
|
|
38
38
|
avail: string[];
|
|
39
|
+
ternoa: string[];
|
|
39
40
|
};
|
|
40
41
|
export declare const _STAKING_ERA_LENGTH_MAP: Record<string, number>;
|
|
41
42
|
export declare const _EXPECTED_BLOCK_TIME: Record<string, number>;
|
|
@@ -51,7 +51,8 @@ export const _NFT_CHAIN_GROUP = {
|
|
|
51
51
|
unique_evm: ['unique_evm'],
|
|
52
52
|
bitcountry: ['bitcountry', 'pioneer', 'continuum_network'],
|
|
53
53
|
vara: ['vara_network'],
|
|
54
|
-
avail: ['avail_mainnet']
|
|
54
|
+
avail: ['avail_mainnet'],
|
|
55
|
+
ternoa: ['ternoa', 'ternoa_alphanet']
|
|
55
56
|
};
|
|
56
57
|
|
|
57
58
|
// Staking--------------------------------------------------------------------------------------------------------------
|
|
@@ -1573,21 +1573,18 @@ export class ChainService {
|
|
|
1573
1573
|
const assetSettings = await this.getAssetSettings();
|
|
1574
1574
|
const activeChainSlugs = this.getActiveChainSlugs();
|
|
1575
1575
|
const assetRegistry = this.getAssetRegistry();
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
Object.values(assetRegistry).forEach(assetInfo => {
|
|
1579
|
-
const isSettingExisted = (assetInfo.slug in assetSettings);
|
|
1576
|
+
Object.values(assetRegistry).forEach(assetInfo => {
|
|
1577
|
+
const isSettingExisted = (assetInfo.slug in assetSettings);
|
|
1580
1578
|
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
}
|
|
1579
|
+
// Set visible for every enabled chains
|
|
1580
|
+
if (activeChainSlugs.includes(assetInfo.originChain) && !isSettingExisted) {
|
|
1581
|
+
// Setting only exist when set either by chain settings or user
|
|
1582
|
+
assetSettings[assetInfo.slug] = {
|
|
1583
|
+
visible: true
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
});
|
|
1587
|
+
this.setAssetSettings(assetSettings, false);
|
|
1591
1588
|
this.eventService.emit('asset.ready', true);
|
|
1592
1589
|
}
|
|
1593
1590
|
setAssetSettings(assetSettings, emitEvent = true) {
|
|
@@ -16,7 +16,8 @@ export const _STAKING_CHAIN_GROUP = {
|
|
|
16
16
|
liquidStaking: ['bifrost_dot', 'acala', 'parallel', 'moonbeam'],
|
|
17
17
|
lending: ['interlay'],
|
|
18
18
|
krest_network: ['krest_network'],
|
|
19
|
-
manta: ['manta_network']
|
|
19
|
+
manta: ['manta_network'],
|
|
20
|
+
bittensor: ['bittensor', 'bittensor_devnet']
|
|
20
21
|
};
|
|
21
22
|
export const TON_CHAINS = ['ton', 'ton_testnet'];
|
|
22
23
|
export const MaxEraRewardPointsEras = 14;
|
|
@@ -77,7 +77,8 @@ export default class BasePoolHandler {
|
|
|
77
77
|
const decimals = this.nativeToken.decimals || 0;
|
|
78
78
|
const defaultMaintainBalance = new BN(1).mul(BN_TEN.pow(new BN(decimals)));
|
|
79
79
|
const ed = new BN(this.nativeToken.minAmount || '0');
|
|
80
|
-
const
|
|
80
|
+
const calculateMaintainBalance = new BN(15).mul(ed).div(BN_TEN);
|
|
81
|
+
const maintainBalance = ed.gte(defaultMaintainBalance) ? calculateMaintainBalance : defaultMaintainBalance;
|
|
81
82
|
return maintainBalance.toString();
|
|
82
83
|
}
|
|
83
84
|
get metadataInfo() {
|
|
@@ -2,3 +2,4 @@ export { default as AmplitudeNativeStakingPoolHandler } from './amplitude';
|
|
|
2
2
|
export { default as AstarNativeStakingPoolHandler } from './astar';
|
|
3
3
|
export { default as RelayNativeStakingPoolHandler } from './relay-chain';
|
|
4
4
|
export { default as ParaNativeStakingPoolHandler } from './para-chain';
|
|
5
|
+
export { default as TaoNativeStakingPoolHandler } from './tao';
|