@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.
Files changed (65) hide show
  1. package/background/KoniTypes.d.ts +5 -1
  2. package/cjs/constants/index.js +7 -1
  3. package/cjs/koni/api/nft/assethub_nft/index.js +30 -7
  4. package/cjs/koni/api/nft/config.js +11 -1
  5. package/cjs/koni/api/nft/index.js +9 -0
  6. package/cjs/koni/api/nft/ternoa_nft/index.js +174 -0
  7. package/cjs/koni/api/staking/bonding/utils.js +1 -1
  8. package/cjs/koni/background/handlers/Extension.js +67 -32
  9. package/cjs/packageInfo.js +1 -1
  10. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +9 -0
  11. package/cjs/services/chain-service/constants.js +2 -1
  12. package/cjs/services/chain-service/index.js +11 -14
  13. package/cjs/services/earning-service/constants/chains.js +2 -1
  14. package/cjs/services/earning-service/handlers/base.js +2 -1
  15. package/cjs/services/earning-service/handlers/native-staking/index.js +8 -1
  16. package/cjs/services/earning-service/handlers/native-staking/tao.js +394 -0
  17. package/cjs/services/earning-service/service.js +3 -0
  18. package/cjs/services/earning-service/utils/index.js +2 -0
  19. package/cjs/services/keyring-service/context/handlers/Modify.js +11 -3
  20. package/cjs/services/keyring-service/context/state.js +2 -3
  21. package/cjs/services/keyring-service/index.js +1 -1
  22. package/cjs/services/swap-service/handler/chainflip-handler.js +13 -5
  23. package/cjs/services/transaction-service/utils.js +6 -0
  24. package/cjs/types/swap/index.js +4 -2
  25. package/cjs/utils/account/derive/info/solo.js +2 -0
  26. package/cjs/utils/account/derive/info/unified.js +2 -0
  27. package/cjs/utils/account/transform.js +4 -4
  28. package/constants/index.d.ts +2 -0
  29. package/constants/index.js +2 -0
  30. package/koni/api/nft/assethub_nft/index.d.ts +2 -0
  31. package/koni/api/nft/assethub_nft/index.js +30 -7
  32. package/koni/api/nft/config.d.ts +4 -0
  33. package/koni/api/nft/config.js +6 -0
  34. package/koni/api/nft/index.js +9 -0
  35. package/koni/api/nft/ternoa_nft/index.d.ts +32 -0
  36. package/koni/api/nft/ternoa_nft/index.js +167 -0
  37. package/koni/api/staking/bonding/utils.js +1 -1
  38. package/koni/background/handlers/Extension.d.ts +1 -0
  39. package/koni/background/handlers/Extension.js +38 -3
  40. package/package.json +16 -6
  41. package/packageInfo.js +1 -1
  42. package/services/balance-service/helpers/subscribe/substrate/index.js +9 -0
  43. package/services/chain-service/constants.d.ts +1 -0
  44. package/services/chain-service/constants.js +2 -1
  45. package/services/chain-service/index.js +11 -14
  46. package/services/earning-service/constants/chains.d.ts +1 -0
  47. package/services/earning-service/constants/chains.js +2 -1
  48. package/services/earning-service/handlers/base.js +2 -1
  49. package/services/earning-service/handlers/native-staking/index.d.ts +1 -0
  50. package/services/earning-service/handlers/native-staking/index.js +2 -1
  51. package/services/earning-service/handlers/native-staking/tao.d.ts +49 -0
  52. package/services/earning-service/handlers/native-staking/tao.js +378 -0
  53. package/services/earning-service/service.js +4 -1
  54. package/services/earning-service/utils/index.js +2 -0
  55. package/services/keyring-service/context/handlers/Modify.js +11 -3
  56. package/services/keyring-service/context/state.js +2 -3
  57. package/services/keyring-service/index.d.ts +1 -1
  58. package/services/keyring-service/index.js +1 -1
  59. package/services/swap-service/handler/chainflip-handler.js +13 -5
  60. package/services/transaction-service/utils.js +6 -0
  61. package/types/swap/index.d.ts +1 -0
  62. package/types/swap/index.js +2 -1
  63. package/utils/account/derive/info/solo.js +2 -0
  64. package/utils/account/derive/info/unified.js +2 -0
  65. 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
- // // Json
428
- // if (value.accounts.every((account) => account.accountActions.includes(AccountActions.EXPORT_JSON))) {
429
- // accountActions.push(AccountActions.EXPORT_JSON);
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))) {
@@ -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";
@@ -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
- const [tokenInfo, collectionMeta] = await Promise.all([this.getTokenDetails(assetId), this.getCollectionDetail(parseInt(parsedClassId))]);
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 || tokenInfo === void 0 ? void 0 : tokenInfo.name,
104
- description: tokenInfo === null || tokenInfo === void 0 ? void 0 : tokenInfo.description,
105
- image: tokenInfo && tokenInfo.image ? this.parseUrl(tokenInfo === null || tokenInfo === void 0 ? void 0 : tokenInfo.image) : undefined,
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 && collectionMeta.image ? this.parseUrl(collectionMeta === null || collectionMeta === void 0 ? void 0 : collectionMeta.image) : undefined
139
+ image: collectionMeta === null || collectionMeta === void 0 ? void 0 : collectionMeta.image
117
140
  };
118
141
  params.updateCollection(this.chain, parsedCollection);
119
142
  }));
@@ -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/";
@@ -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
@@ -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 true;
1445
+ return {
1446
+ success: true,
1447
+ error: ''
1448
+ };
1417
1449
  } catch (e) {
1418
1450
  console.error(e);
1419
- return false;
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.1",
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.88",
2375
- "@subwallet/extension-base": "^1.3.1",
2376
- "@subwallet/extension-chains": "^1.3.1",
2377
- "@subwallet/extension-dapp": "^1.3.1",
2378
- "@subwallet/extension-inject": "^1.3.1",
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.1'
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
- if (Object.keys(assetSettings).length === 0) {
1577
- // only initiate the first time
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
- // Set visible for every enabled chains
1582
- if (activeChainSlugs.includes(assetInfo.originChain) && !isSettingExisted) {
1583
- // Setting only exist when set either by chain settings or user
1584
- assetSettings[assetInfo.slug] = {
1585
- visible: true
1586
- };
1587
- }
1588
- });
1589
- this.setAssetSettings(assetSettings, false);
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) {
@@ -12,6 +12,7 @@ export declare const _STAKING_CHAIN_GROUP: {
12
12
  lending: string[];
13
13
  krest_network: string[];
14
14
  manta: string[];
15
+ bittensor: string[];
15
16
  };
16
17
  export declare const TON_CHAINS: string[];
17
18
  export declare const MaxEraRewardPointsEras = 14;
@@ -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 maintainBalance = ed.gte(defaultMaintainBalance) ? new BN(15).mul(ed).div(BN_TEN) : defaultMaintainBalance;
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';