@subwallet/extension-base 1.3.23-0 → 1.3.25-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 (91) hide show
  1. package/background/KoniTypes.d.ts +11 -3
  2. package/background/KoniTypes.js +1 -0
  3. package/background/errors/EvmProviderError.js +4 -0
  4. package/background/errors/ProviderError.d.ts +1 -1
  5. package/background/errors/ProviderError.js +2 -2
  6. package/cjs/background/KoniTypes.js +1 -0
  7. package/cjs/background/errors/EvmProviderError.js +4 -0
  8. package/cjs/background/errors/ProviderError.js +2 -2
  9. package/cjs/constants/environment.js +1 -1
  10. package/cjs/constants/index.js +21 -4
  11. package/cjs/core/logic-validation/transfer.js +23 -8
  12. package/cjs/koni/background/handlers/Extension.js +109 -89
  13. package/cjs/koni/background/handlers/State.js +2 -2
  14. package/cjs/koni/background/handlers/Tabs.js +4 -3
  15. package/cjs/packageInfo.js +1 -1
  16. package/cjs/page/index.js +1 -1
  17. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +3 -3
  18. package/cjs/services/balance-service/transfer/smart-contract.js +24 -3
  19. package/cjs/services/buy-service/constants/token.js +3 -0
  20. package/cjs/services/chain-service/index.js +11 -0
  21. package/cjs/services/earning-service/constants/chains.js +1 -1
  22. package/cjs/services/earning-service/handlers/base.js +11 -5
  23. package/cjs/services/earning-service/handlers/native-staking/base-para.js +7 -6
  24. package/cjs/services/earning-service/handlers/native-staking/base.js +6 -3
  25. package/cjs/services/earning-service/handlers/native-staking/dtao.js +444 -0
  26. package/cjs/services/earning-service/handlers/native-staking/index.js +8 -1
  27. package/cjs/services/earning-service/handlers/native-staking/tao.js +138 -125
  28. package/cjs/services/earning-service/service.js +14 -4
  29. package/cjs/services/fee-service/utils/tokenPayFee.js +151 -0
  30. package/cjs/services/inapp-notification-service/index.js +3 -0
  31. package/cjs/services/request-service/handler/MetadataRequestHandler.js +5 -13
  32. package/cjs/services/request-service/index.js +2 -2
  33. package/cjs/services/transaction-service/index.js +14 -5
  34. package/cjs/types/yield/info/base.js +1 -0
  35. package/cjs/utils/fee/transfer.js +47 -14
  36. package/cjs/utils/fetchEvmChainInfo.js +10 -5
  37. package/constants/environment.js +1 -1
  38. package/constants/index.d.ts +6 -1
  39. package/constants/index.js +14 -1
  40. package/core/logic-validation/transfer.d.ts +1 -1
  41. package/core/logic-validation/transfer.js +25 -10
  42. package/koni/background/handlers/Extension.js +82 -62
  43. package/koni/background/handlers/State.d.ts +1 -1
  44. package/koni/background/handlers/State.js +2 -2
  45. package/koni/background/handlers/Tabs.js +4 -3
  46. package/package.json +16 -6
  47. package/packageInfo.js +1 -1
  48. package/page/index.js +1 -1
  49. package/services/balance-service/helpers/subscribe/substrate/index.js +2 -2
  50. package/services/balance-service/transfer/smart-contract.d.ts +4 -2
  51. package/services/balance-service/transfer/smart-contract.js +24 -3
  52. package/services/buy-service/constants/token.js +3 -0
  53. package/services/chain-service/index.d.ts +1 -0
  54. package/services/chain-service/index.js +12 -1
  55. package/services/earning-service/constants/chains.js +1 -1
  56. package/services/earning-service/handlers/base.d.ts +7 -5
  57. package/services/earning-service/handlers/base.js +11 -7
  58. package/services/earning-service/handlers/native-staking/base-para.d.ts +1 -1
  59. package/services/earning-service/handlers/native-staking/base-para.js +7 -6
  60. package/services/earning-service/handlers/native-staking/base.d.ts +1 -1
  61. package/services/earning-service/handlers/native-staking/base.js +6 -3
  62. package/services/earning-service/handlers/native-staking/dtao.d.ts +64 -0
  63. package/services/earning-service/handlers/native-staking/dtao.js +434 -0
  64. package/services/earning-service/handlers/native-staking/index.d.ts +1 -0
  65. package/services/earning-service/handlers/native-staking/index.js +2 -1
  66. package/services/earning-service/handlers/native-staking/tao.d.ts +16 -4
  67. package/services/earning-service/handlers/native-staking/tao.js +136 -121
  68. package/services/earning-service/service.d.ts +1 -0
  69. package/services/earning-service/service.js +15 -5
  70. package/services/fee-service/interfaces.d.ts +25 -0
  71. package/services/fee-service/utils/tokenPayFee.d.ts +8 -0
  72. package/services/fee-service/utils/tokenPayFee.js +141 -0
  73. package/services/inapp-notification-service/index.js +3 -0
  74. package/services/request-service/handler/MetadataRequestHandler.d.ts +1 -1
  75. package/services/request-service/handler/MetadataRequestHandler.js +5 -13
  76. package/services/request-service/index.d.ts +1 -1
  77. package/services/request-service/index.js +2 -2
  78. package/services/transaction-service/index.js +16 -7
  79. package/types/bridge/index.d.ts +1 -0
  80. package/types/buy.d.ts +1 -1
  81. package/types/fee/option.d.ts +1 -1
  82. package/types/yield/actions/join/step.d.ts +1 -0
  83. package/types/yield/actions/join/submit.d.ts +1 -0
  84. package/types/yield/info/account/info.d.ts +14 -1
  85. package/types/yield/info/base.d.ts +3 -1
  86. package/types/yield/info/base.js +1 -0
  87. package/types/yield/info/chain/info.d.ts +5 -1
  88. package/utils/fee/transfer.d.ts +1 -1
  89. package/utils/fee/transfer.js +46 -13
  90. package/utils/fetchEvmChainInfo.d.ts +1 -1
  91. package/utils/fetchEvmChainInfo.js +10 -5
@@ -49,8 +49,8 @@ export default abstract class BasePoolHandler {
49
49
  createClaimNotification(claimItemInfo: EarningRewardItem, tokenInfo: _ChainAsset): Promise<void>;
50
50
  /** Can mint when haven't enough native token (use input token for fee) */
51
51
  get isPoolSupportAlternativeFee(): boolean;
52
- getPoolInfo(): Promise<YieldPoolInfo | undefined>;
53
- getPoolPosition(address: string): Promise<YieldPositionInfo | undefined>;
52
+ getPoolInfo(slug?: string): Promise<YieldPoolInfo | undefined>;
53
+ getPoolPosition(address: string, slug?: string): Promise<YieldPositionInfo | undefined>;
54
54
  /** Subscribe pool info */
55
55
  abstract subscribePoolInfo(callback: (data: YieldPoolInfo) => void): Promise<VoidFunction>;
56
56
  /** Subscribe pool position */
@@ -99,17 +99,19 @@ export default abstract class BasePoolHandler {
99
99
  /** Create `transaction` to join the pool step-by-step */
100
100
  abstract handleYieldJoin(data: SubmitYieldJoinData, path: OptimalYieldPath, currentStep: number): Promise<HandleYieldStepData>;
101
101
  /** Validate param to leave the pool */
102
- abstract validateYieldLeave(amount: string, address: string, fastLeave: boolean, selectedTarget?: string): Promise<TransactionError[]>;
102
+ abstract validateYieldLeave(amount: string, address: string, fastLeave: boolean, selectedTarget?: string, slug?: string): Promise<TransactionError[]>;
103
103
  /** Create `transaction` to leave the pool normal (default unstake) */
104
- protected abstract handleYieldUnstake(amount: string, address: string, selectedTarget?: string): Promise<[ExtrinsicType, TransactionData]>;
104
+ protected abstract handleYieldUnstake(amount: string, address: string, selectedTarget?: string, netuid?: number): Promise<[ExtrinsicType, TransactionData]>;
105
105
  /** Create `transaction` to leave the pool fast (swap token) */
106
106
  protected abstract handleYieldRedeem(amount: string, address: string, selectedTarget?: string): Promise<[ExtrinsicType, TransactionData]>;
107
107
  /** Create `transaction` to leave the pool */
108
- handleYieldLeave(fastLeave: boolean, amount: string, address: string, selectedTarget?: string): Promise<[ExtrinsicType, TransactionData]>;
108
+ handleYieldLeave(fastLeave: boolean, amount: string, address: string, selectedTarget?: string, netuid?: number): Promise<[ExtrinsicType, TransactionData]>;
109
109
  /** Create `transaction` to withdraw unstaked amount */
110
110
  abstract handleYieldWithdraw(address: string, unstakingInfo: UnstakingInfo): Promise<TransactionData>;
111
111
  /** Create `transaction` to cancel unstake */
112
112
  abstract handleYieldCancelUnstake(params: StakeCancelWithdrawalParams): Promise<TransactionData>;
113
113
  /** Create `transaction` to claim reward */
114
114
  abstract handleYieldClaimReward(address: string, bondReward?: boolean): Promise<TransactionData>;
115
+ /** Check handler can handle slug */
116
+ canHandleSlug(slug: string): boolean;
115
117
  }
@@ -107,12 +107,12 @@ export default class BasePoolHandler {
107
107
  get isPoolSupportAlternativeFee() {
108
108
  return false;
109
109
  }
110
- async getPoolInfo() {
111
- return await this.state.earningService.getYieldPool(this.slug);
110
+ async getPoolInfo(slug = this.slug) {
111
+ return await this.state.earningService.getYieldPool(slug);
112
112
  }
113
- async getPoolPosition(address) {
113
+ async getPoolPosition(address, slug = this.slug) {
114
114
  const originAddress = reformatAddress(address);
115
- return await this.state.earningService.getYieldPosition(originAddress, this.slug);
115
+ return await this.state.earningService.getYieldPosition(originAddress, slug);
116
116
  }
117
117
 
118
118
  /* Subscribe data */
@@ -127,7 +127,7 @@ export default class BasePoolHandler {
127
127
 
128
128
  async earlyValidate(request) {
129
129
  var _poolInfo$statistic, _poolInfo$statistic2, _poolInfo$statistic2$;
130
- const poolInfo = await this.getPoolInfo();
130
+ const poolInfo = await this.getPoolInfo(request.slug);
131
131
  if (!poolInfo || !((_poolInfo$statistic = poolInfo.statistic) !== null && _poolInfo$statistic !== void 0 && _poolInfo$statistic.earningThreshold.join)) {
132
132
  return {
133
133
  passed: false,
@@ -249,11 +249,11 @@ export default class BasePoolHandler {
249
249
  /** Validate param to join the pool */
250
250
 
251
251
  /** Create `transaction` to leave the pool */
252
- async handleYieldLeave(fastLeave, amount, address, selectedTarget) {
252
+ async handleYieldLeave(fastLeave, amount, address, selectedTarget, netuid) {
253
253
  if (fastLeave) {
254
254
  return this.handleYieldRedeem(amount, address, selectedTarget);
255
255
  } else {
256
- return this.handleYieldUnstake(amount, address, selectedTarget);
256
+ return this.handleYieldUnstake(amount, address, selectedTarget, netuid);
257
257
  }
258
258
  }
259
259
 
@@ -263,5 +263,9 @@ export default class BasePoolHandler {
263
263
 
264
264
  /** Create `transaction` to withdraw unstaked amount */
265
265
 
266
+ /** Check handler can handle slug */
267
+ canHandleSlug(slug) {
268
+ return this.slug === slug;
269
+ }
266
270
  /* Other actions */
267
271
  }
@@ -7,5 +7,5 @@ export default abstract class BaseParaNativeStakingPoolHandler extends BaseNativ
7
7
  /**
8
8
  * @todo Recheck
9
9
  * */
10
- validateYieldLeave(amount: string, address: string, fastLeave: boolean, selectedTarget?: string): Promise<TransactionError[]>;
10
+ validateYieldLeave(amount: string, address: string, fastLeave: boolean, selectedTarget?: string, slug?: string): Promise<TransactionError[]>;
11
11
  }
@@ -25,10 +25,11 @@ export default class BaseParaNativeStakingPoolHandler extends BaseNativeStakingP
25
25
  const {
26
26
  address,
27
27
  amount,
28
- selectedValidators
28
+ selectedValidators,
29
+ slug
29
30
  } = data;
30
- const poolInfo = await this.getPoolInfo();
31
- const poolPosition = await this.getPoolPosition(address);
31
+ const poolInfo = await this.getPoolInfo(slug);
32
+ const poolPosition = await this.getPoolPosition(address, slug);
32
33
  const chainInfo = this.chainInfo;
33
34
  const bnAmount = new BN(amount);
34
35
  if (bnAmount.lte(BN_ZERO)) {
@@ -94,10 +95,10 @@ export default class BaseParaNativeStakingPoolHandler extends BaseNativeStakingP
94
95
  /**
95
96
  * @todo Recheck
96
97
  * */
97
- async validateYieldLeave(amount, address, fastLeave, selectedTarget) {
98
+ async validateYieldLeave(amount, address, fastLeave, selectedTarget, slug) {
98
99
  const errors = [];
99
- const poolInfo = await this.getPoolInfo();
100
- const poolPosition = await this.getPoolPosition(address);
100
+ const poolInfo = await this.getPoolInfo(slug);
101
+ const poolPosition = await this.getPoolPosition(address, slug);
101
102
  if (!poolInfo || !poolInfo.statistic || !poolPosition || fastLeave || !selectedTarget) {
102
103
  return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
103
104
  }
@@ -13,7 +13,7 @@ export default abstract class BaseNativeStakingPoolHandler extends BasePoolHandl
13
13
  getPoolReward(useAddresses: string[], callBack: (rs: EarningRewardItem) => void): Promise<VoidFunction>;
14
14
  getPoolRewardHistory(useAddresses: string[], callBack: (rs: EarningRewardHistoryItem) => void): Promise<VoidFunction>;
15
15
  get defaultSubmitStep(): YieldStepBaseInfo;
16
- abstract createJoinExtrinsic(data: SubmitJoinNativeStaking, positionInfo?: YieldPositionInfo, bondDest?: string): Promise<[TransactionData, YieldTokenBaseInfo]>;
16
+ abstract createJoinExtrinsic(data: SubmitJoinNativeStaking, positionInfo?: YieldPositionInfo, bondDest?: string, netuid?: number): Promise<[TransactionData, YieldTokenBaseInfo]>;
17
17
  protected getSubmitStep(params: OptimalYieldPathParams): Promise<YieldStepBaseInfo>;
18
18
  handleYieldJoin(_data: SubmitYieldJoinData, path: OptimalYieldPath, currentStep: number): Promise<HandleYieldStepData>;
19
19
  handleYieldRedeem(amount: string, address: string, selectedTarget?: string): Promise<[ExtrinsicType, TransactionData]>;
@@ -92,6 +92,7 @@ export default class BaseNativeStakingPoolHandler extends BasePoolHandler {
92
92
  const {
93
93
  address,
94
94
  amount,
95
+ netuid,
95
96
  slug,
96
97
  targets
97
98
  } = params;
@@ -100,7 +101,8 @@ export default class BaseNativeStakingPoolHandler extends BasePoolHandler {
100
101
  amount,
101
102
  address,
102
103
  slug,
103
- selectedValidators
104
+ selectedValidators,
105
+ netuid
104
106
  };
105
107
  const positionInfo = await this.getPoolPosition(address);
106
108
  const [, fee] = await this.createJoinExtrinsic(data, positionInfo);
@@ -111,9 +113,10 @@ export default class BaseNativeStakingPoolHandler extends BasePoolHandler {
111
113
  const {
112
114
  address,
113
115
  amount,
114
- selectedValidators
116
+ selectedValidators,
117
+ slug
115
118
  } = data;
116
- const positionInfo = await this.getPoolPosition(address);
119
+ const positionInfo = await this.getPoolPosition(address, slug);
117
120
  const [extrinsic] = await this.createJoinExtrinsic(data, positionInfo);
118
121
  const bondingData = {
119
122
  poolPosition: positionInfo,
@@ -0,0 +1,64 @@
1
+ import { _ChainInfo } from '@subwallet/chain-list/types';
2
+ import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
3
+ import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
4
+ import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
5
+ import BaseParaStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/base-para';
6
+ import { BaseYieldPositionInfo, StakeCancelWithdrawalParams, SubmitJoinNativeStaking, TransactionData, UnstakingInfo, ValidatorInfo, YieldPoolInfo, YieldPoolMethodInfo, YieldPoolType, YieldPositionInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
7
+ import { BigNumber } from 'bignumber.js';
8
+ export interface SubnetData {
9
+ netuid: number;
10
+ name: string;
11
+ symbol: string;
12
+ ownerHotkey: string;
13
+ maxAllowedValidators: number;
14
+ taoIn: number;
15
+ }
16
+ interface TaoStakingStakeOption {
17
+ owner: string;
18
+ amount: string;
19
+ rate?: BigNumber;
20
+ identity?: string;
21
+ }
22
+ export interface RawDelegateState {
23
+ data: Array<{
24
+ hotkey_name: string;
25
+ hotkey: {
26
+ ss58: string;
27
+ };
28
+ stake: string;
29
+ }>;
30
+ }
31
+ declare type Nominators = [Array<[number, number]>];
32
+ export interface TestnetBittensorDelegateInfo {
33
+ delegateSs58: string;
34
+ take: number;
35
+ nominators: Nominators;
36
+ returnPer1000: number;
37
+ }
38
+ export declare const getTaoToAlphaMapping: (substrateApi: _SubstrateApi) => Promise<Record<number, string>>;
39
+ export default class SubnetTaoStakingPoolHandler extends BaseParaStakingPoolHandler {
40
+ handleYieldWithdraw(address: string, unstakingInfo: UnstakingInfo): Promise<TransactionData>;
41
+ handleYieldCancelUnstake(params: StakeCancelWithdrawalParams): Promise<TransactionData>;
42
+ readonly type = YieldPoolType.SUBNET_STAKING;
43
+ slug: string;
44
+ protected name: string;
45
+ protected shortName: string;
46
+ subnetData: SubnetData[];
47
+ private isInit;
48
+ private bittensorCache;
49
+ readonly availableMethod: YieldPoolMethodInfo;
50
+ constructor(state: KoniState, chain: string);
51
+ canHandleSlug(slug: string): boolean;
52
+ get maintainBalance(): string;
53
+ private init;
54
+ protected getDescription(): string;
55
+ subscribePoolInfo(callback: (data: YieldPoolInfo) => void): Promise<VoidFunction>;
56
+ parseNominatorMetadata(chainInfo: _ChainInfo, address: string, delegatorState: TaoStakingStakeOption[]): Promise<Omit<YieldPositionInfo, keyof BaseYieldPositionInfo>>;
57
+ subscribePoolPosition(useAddresses: string[], rsCallback: (rs: YieldPositionInfo) => void): Promise<VoidFunction>;
58
+ private getDevnetPoolTargets;
59
+ private getMainnetPoolTargets;
60
+ getPoolTargets(): Promise<ValidatorInfo[]>;
61
+ createJoinExtrinsic(data: SubmitJoinNativeStaking, positionInfo?: YieldPositionInfo, bondDest?: string): Promise<[TransactionData, YieldTokenBaseInfo]>;
62
+ handleYieldUnstake(amount: string, address: string, selectedTarget?: string, netuid?: number): Promise<[ExtrinsicType, TransactionData]>;
63
+ }
64
+ export {};
@@ -0,0 +1,434 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
+ import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
+ import { BITTENSOR_REFRESH_STAKE_APY, BITTENSOR_REFRESH_STAKE_INFO } from '@subwallet/extension-base/constants';
7
+ import { getEarningStatusByNominations } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
8
+ import BaseParaStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/base-para';
9
+ import { BasicTxErrorType, EarningStatus, YieldPoolType } from '@subwallet/extension-base/types';
10
+ import { reformatAddress } from '@subwallet/extension-base/utils';
11
+ import BigN from 'bignumber.js';
12
+ import { BN, BN_TEN, BN_ZERO } from '@polkadot/util';
13
+ import { calculateReward } from "../../utils/index.js";
14
+ import { BittensorCache } from "./tao.js";
15
+ export const getTaoToAlphaMapping = async substrateApi => {
16
+ const allSubnets = (await substrateApi.api.call.subnetInfoRuntimeApi.getAllDynamicInfo()).toJSON();
17
+ if (!allSubnets) {
18
+ return {};
19
+ }
20
+ return allSubnets.reduce((acc, subnet) => {
21
+ const netuid = subnet === null || subnet === void 0 ? void 0 : subnet.netuid;
22
+ const taoIn = subnet !== null && subnet !== void 0 && subnet.taoIn ? new BigN(subnet.taoIn) : new BigN(0);
23
+ const alphaIn = subnet !== null && subnet !== void 0 && subnet.alphaIn ? new BigN(subnet.alphaIn) : new BigN(0);
24
+ if (netuid === 0) {
25
+ acc[netuid] = '1';
26
+ } else if (alphaIn.gt(0)) {
27
+ acc[netuid] = taoIn.dividedBy(alphaIn).toString();
28
+ } else {
29
+ acc[netuid] = '1';
30
+ }
31
+ return acc;
32
+ }, {});
33
+ };
34
+ export default class SubnetTaoStakingPoolHandler extends BaseParaStakingPoolHandler {
35
+ /* Unimplemented function */
36
+ handleYieldWithdraw(address, unstakingInfo) {
37
+ throw new Error('Method not implemented.');
38
+ }
39
+ handleYieldCancelUnstake(params) {
40
+ throw new Error('Method not implemented.');
41
+ }
42
+ /* Unimplemented function */
43
+
44
+ // @ts-ignore
45
+ type = YieldPoolType.SUBNET_STAKING;
46
+ subnetData = [];
47
+ isInit = false;
48
+ availableMethod = {
49
+ join: true,
50
+ defaultUnstake: true,
51
+ fastUnstake: false,
52
+ cancelUnstake: false,
53
+ withdraw: false,
54
+ claimReward: false
55
+ };
56
+ constructor(state, chain) {
57
+ super(state, chain);
58
+ const _chainAsset = this.nativeToken;
59
+ const _chainInfo = this.chainInfo;
60
+ const symbol = _chainAsset.symbol;
61
+ this.slug = this.slug = `${symbol}___subnet_staking___${_chainInfo.slug}`;
62
+ this.name = 'Subnet Tao Staking';
63
+ this.shortName = 'dTAO Staking';
64
+ this.bittensorCache = BittensorCache.getInstance();
65
+ }
66
+ canHandleSlug(slug) {
67
+ return slug.startsWith(`${this.slug}__`);
68
+ }
69
+ get maintainBalance() {
70
+ const ed = new BN(this.nativeToken.minAmount || '0');
71
+ const calculateMaintainBalance = new BN(15).mul(ed).div(BN_TEN);
72
+ const maintainBalance = calculateMaintainBalance;
73
+ return maintainBalance.toString();
74
+ }
75
+ async init() {
76
+ try {
77
+ const substrateApi = await this.substrateApi.isReady;
78
+ const dynamicInfo = (await substrateApi.api.call.subnetInfoRuntimeApi.getAllDynamicInfo()).toJSON();
79
+ const subnetsInfo = (await substrateApi.api.call.subnetInfoRuntimeApi.getSubnetsInfoV2()).toJSON();
80
+ if (dynamicInfo && subnetsInfo) {
81
+ const mergedData = dynamicInfo.filter(dynInfo => dynInfo.netuid !== 0).map(dynInfo => {
82
+ var _dynInfo$subnetIdenti, _dynInfo$subnetIdenti2;
83
+ const extraInfo = subnetsInfo.find(subnet => subnet.netuid === dynInfo.netuid);
84
+ const nameRaw = ((_dynInfo$subnetIdenti = dynInfo.subnetIdentity) === null || _dynInfo$subnetIdenti === void 0 ? void 0 : _dynInfo$subnetIdenti.subnetName) || String.fromCharCode(...dynInfo.subnetName);
85
+ const identityName = (_dynInfo$subnetIdenti2 = dynInfo.subnetIdentity) !== null && _dynInfo$subnetIdenti2 !== void 0 && _dynInfo$subnetIdenti2.subnetName ? Buffer.from(dynInfo.subnetIdentity.subnetName.slice(2), 'hex').toString('utf-8') : '';
86
+ const formattedIdentityName = identityName ? identityName.charAt(0).toUpperCase() + identityName.slice(1).toLowerCase() : '';
87
+ const name = formattedIdentityName || nameRaw.charAt(0).toUpperCase() + nameRaw.slice(1);
88
+ const symbol = new TextDecoder('utf-8').decode(Uint8Array.from(dynInfo.tokenSymbol));
89
+ return {
90
+ netuid: dynInfo.netuid,
91
+ name,
92
+ symbol,
93
+ ownerHotkey: dynInfo.ownerHotkey,
94
+ maxAllowedValidators: extraInfo ? extraInfo.maxAllowedValidators : 0,
95
+ taoIn: dynInfo.taoIn
96
+ };
97
+ });
98
+ this.subnetData = mergedData;
99
+ this.isInit = true;
100
+ }
101
+ } catch (err) {
102
+ console.error(err);
103
+ this.isInit = false;
104
+ }
105
+ }
106
+ getDescription() {
107
+ return 'Stake TAO to earn yield on dTAO';
108
+ }
109
+
110
+ /* Subscribe pool info */
111
+
112
+ async subscribePoolInfo(callback) {
113
+ if (!this.isInit) {
114
+ await this.init();
115
+ }
116
+ let cancel = false;
117
+ const substrateApi = await this.substrateApi.isReady;
118
+ const updateStakingInfo = async () => {
119
+ try {
120
+ if (cancel) {
121
+ return;
122
+ }
123
+ const minDelegatorStake = (await substrateApi.api.query.subtensorModule.nominatorMinRequiredStake()).toPrimitive() || 0;
124
+ const BNminDelegatorStake = new BigN(minDelegatorStake.toString());
125
+ this.subnetData.forEach(subnet => {
126
+ const netuid = subnet.netuid.toString().padStart(2, '0');
127
+ const subnetSlug = `${this.slug}__subnet_${netuid.padStart(2, '0')}`;
128
+ const subnetName = `${subnet.name || 'Unknown'} ${netuid}`;
129
+ const bnTaoIn = new BN(subnet.taoIn);
130
+ const data = {
131
+ ...this.baseInfo,
132
+ type: this.type,
133
+ slug: subnetSlug,
134
+ metadata: {
135
+ ...this.metadataInfo,
136
+ name: subnetName,
137
+ shortName: subnetName,
138
+ description: this.getDescription(),
139
+ subnetData: {
140
+ netuid: subnet.netuid,
141
+ subnetSymbol: subnet.symbol || 'dTAO'
142
+ }
143
+ },
144
+ statistic: {
145
+ assetEarning: [{
146
+ slug: this.nativeToken.slug
147
+ }],
148
+ maxCandidatePerFarmer: subnet.maxAllowedValidators,
149
+ maxWithdrawalRequestPerFarmer: 1,
150
+ earningThreshold: {
151
+ join: BNminDelegatorStake.toString(),
152
+ defaultUnstake: '0',
153
+ fastUnstake: '0'
154
+ },
155
+ eraTime: 24,
156
+ era: 0,
157
+ unstakingPeriod: 1.2,
158
+ tvl: bnTaoIn.toString()
159
+ }
160
+ };
161
+ callback(data);
162
+ });
163
+ } catch (error) {
164
+ console.error('Error updating staking info:', error);
165
+ }
166
+ };
167
+ const subscribeStakingMetadataInterval = () => {
168
+ updateStakingInfo().catch(console.error);
169
+ };
170
+ await substrateApi.isReady;
171
+ subscribeStakingMetadataInterval();
172
+ const interval = setInterval(subscribeStakingMetadataInterval, BITTENSOR_REFRESH_STAKE_APY);
173
+ return () => {
174
+ cancel = true;
175
+ clearInterval(interval);
176
+ };
177
+ }
178
+
179
+ /* Subscribe pool position */
180
+
181
+ async parseNominatorMetadata(chainInfo, address, delegatorState) {
182
+ const nominationList = [];
183
+ const getMinDelegatorStake = this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake();
184
+ const minDelegatorStake = (await getMinDelegatorStake).toString();
185
+ let allActiveStake = BN_ZERO;
186
+ for (const delegate of delegatorState) {
187
+ const stake = new BigN(delegate.amount);
188
+ const originActiveStake = stake.multipliedBy(delegate.rate || new BigN(1)).toFixed(0).toString();
189
+ const bnActiveStake = new BN(originActiveStake);
190
+ if (bnActiveStake.gt(BN_ZERO)) {
191
+ const delegationStatus = EarningStatus.EARNING_REWARD;
192
+ allActiveStake = allActiveStake.add(bnActiveStake);
193
+ nominationList.push({
194
+ status: delegationStatus,
195
+ chain: chainInfo.slug,
196
+ validatorAddress: delegate.owner,
197
+ activeStake: delegate.amount,
198
+ validatorMinStake: minDelegatorStake,
199
+ originActiveStake: originActiveStake,
200
+ validatorIdentity: delegate.identity
201
+ });
202
+ }
203
+ }
204
+ const stakingStatus = getEarningStatusByNominations(allActiveStake, nominationList);
205
+ return {
206
+ status: stakingStatus,
207
+ balanceToken: this.nativeToken.slug,
208
+ totalStake: allActiveStake.toString(),
209
+ activeStake: allActiveStake.toString(),
210
+ unstakeBalance: '0',
211
+ isBondedBefore: true,
212
+ nominations: nominationList,
213
+ unstakings: []
214
+ };
215
+ }
216
+ async subscribePoolPosition(useAddresses, rsCallback) {
217
+ if (!this.isInit) {
218
+ await this.init();
219
+ }
220
+ let cancel = false;
221
+ const substrateApi = await this.substrateApi.isReady;
222
+ const defaultInfo = this.baseInfo;
223
+ const chainInfo = this.chainInfo;
224
+ const _delegateInfo = await this.bittensorCache.get();
225
+ const getPoolPosition = async () => {
226
+ const rawDelegateStateInfos = await Promise.all(useAddresses.map(async address => (await substrateApi.api.call.stakeInfoRuntimeApi.getStakeInfoForColdkey(address)).toJSON()));
227
+ const price = await getTaoToAlphaMapping(this.substrateApi);
228
+ if (rawDelegateStateInfos && rawDelegateStateInfos.length > 0) {
229
+ rawDelegateStateInfos.forEach((rawDelegateStateInfo, i) => {
230
+ const owner = reformatAddress(useAddresses[i], 42);
231
+ const delegateStateInfo = rawDelegateStateInfo;
232
+ const subnetPositions = {};
233
+ for (const delegate of delegateStateInfo) {
234
+ const hotkey = delegate.hotkey;
235
+ const netuid = delegate.netuid;
236
+ const stake = new BigN(delegate.stake);
237
+ const taoToAlphaPrice = new BigN(price[netuid]);
238
+ if (!subnetPositions[netuid]) {
239
+ subnetPositions[netuid] = {
240
+ delegatorState: [],
241
+ totalBalance: BN_ZERO,
242
+ originalTotalStake: BN_ZERO
243
+ };
244
+ }
245
+ let identity = '';
246
+ if (_delegateInfo) {
247
+ const delegateInfo = _delegateInfo.data.find(info => info.hotkey.ss58 === hotkey);
248
+ identity = delegateInfo ? delegateInfo.name : '';
249
+ }
250
+ subnetPositions[netuid].delegatorState.push({
251
+ owner: hotkey,
252
+ amount: stake.toString(),
253
+ rate: taoToAlphaPrice,
254
+ identity: identity
255
+ });
256
+ subnetPositions[netuid].totalBalance = subnetPositions[netuid].totalBalance.add(new BN(stake.toString()));
257
+ subnetPositions[netuid].originalTotalStake = subnetPositions[netuid].originalTotalStake.add(new BN(stake.toString()));
258
+ }
259
+ Object.values(this.subnetData).forEach(subnet => {
260
+ const netuid = subnet.netuid;
261
+ const subnetSlug = `${this.slug}__subnet_${netuid.toString().padStart(2, '0')}`;
262
+ const subnetName = `${subnet.name || 'Unknown'} ${netuid}`;
263
+ const subnetSymbol = subnet.symbol || 'dTAO';
264
+ const {
265
+ delegatorState = [],
266
+ originalTotalStake = BN_ZERO
267
+ } = subnetPositions[netuid] || {};
268
+ if (delegatorState.length > 0) {
269
+ this.parseNominatorMetadata(chainInfo, owner, delegatorState).then(nominatorMetadata => {
270
+ rsCallback({
271
+ ...defaultInfo,
272
+ ...nominatorMetadata,
273
+ address: owner,
274
+ type: this.type,
275
+ slug: subnetSlug,
276
+ subnetData: {
277
+ subnetSymbol,
278
+ subnetShortName: subnetName,
279
+ originalTotalStake: originalTotalStake.toString()
280
+ }
281
+ });
282
+ }).catch(console.error);
283
+ } else {
284
+ rsCallback({
285
+ ...defaultInfo,
286
+ type: this.type,
287
+ address: owner,
288
+ balanceToken: this.nativeToken.slug,
289
+ totalStake: '0',
290
+ activeStake: '0',
291
+ unstakeBalance: '0',
292
+ status: EarningStatus.NOT_STAKING,
293
+ isBondedBefore: false,
294
+ nominations: [],
295
+ unstakings: [],
296
+ slug: subnetSlug,
297
+ subnetData: {
298
+ subnetSymbol,
299
+ subnetShortName: subnetName,
300
+ originalTotalStake: '0'
301
+ }
302
+ });
303
+ }
304
+ });
305
+ });
306
+ }
307
+ };
308
+ const getStakingPositionInterval = async () => {
309
+ if (cancel) {
310
+ return;
311
+ }
312
+ await getPoolPosition();
313
+ };
314
+ getStakingPositionInterval().catch(console.error);
315
+ const intervalId = setInterval(() => {
316
+ getStakingPositionInterval().catch(console.error);
317
+ }, BITTENSOR_REFRESH_STAKE_INFO);
318
+ return () => {
319
+ cancel = true;
320
+ clearInterval(intervalId);
321
+ };
322
+ }
323
+
324
+ /* Subscribe pool position */
325
+
326
+ /* Get pool targets */
327
+ // eslint-disable-next-line @typescript-eslint/require-await
328
+ async getDevnetPoolTargets() {
329
+ const testnetDelegate = (await this.substrateApi.api.call.delegateInfoRuntimeApi.getDelegates()).toJSON();
330
+ const getNominatorMinRequiredStake = this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake();
331
+ const nominatorMinRequiredStake = (await getNominatorMinRequiredStake).toString();
332
+ const bnMinBond = new BN(nominatorMinRequiredStake);
333
+ const filteredDelegates = testnetDelegate.filter(delegate => {
334
+ return delegate.returnPer1000 !== 0;
335
+ });
336
+ return filteredDelegates.map(delegate => ({
337
+ address: delegate.delegateSs58,
338
+ totalStake: '0',
339
+ ownStake: '0',
340
+ otherStake: '0',
341
+ minBond: bnMinBond.toString(),
342
+ nominatorCount: delegate.nominators.length,
343
+ commission: delegate.take / 1000,
344
+ blocked: false,
345
+ isVerified: false,
346
+ chain: this.chain,
347
+ isCrowded: false
348
+ }));
349
+ }
350
+ async getMainnetPoolTargets() {
351
+ const _topValidator = await this.bittensorCache.get();
352
+ const topValidator = _topValidator;
353
+ const getNominatorMinRequiredStake = this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake();
354
+ const nominatorMinRequiredStake = (await getNominatorMinRequiredStake).toString();
355
+ const bnMinBond = new BN(nominatorMinRequiredStake);
356
+ const validatorList = topValidator.data;
357
+ const validatorAddresses = Object.keys(validatorList);
358
+ const results = await Promise.all(validatorAddresses.map(i => {
359
+ const address = validatorList[i].hotkey.ss58;
360
+ const bnTotalStake = new BN(validatorList[i].stake);
361
+ const bnOwnStake = new BN(validatorList[i].validator_stake);
362
+ const otherStake = bnTotalStake.sub(bnOwnStake);
363
+ const nominatorCount = validatorList[i].nominators;
364
+ const commission = validatorList[i].take;
365
+ const roundedCommission = (parseFloat(commission) * 100).toFixed(0);
366
+ const apr = (parseFloat(validatorList[i].apr) / 10 ** 9 * 100).toFixed(2);
367
+ const apyCalculate = calculateReward(parseFloat(apr));
368
+ const name = validatorList[i].name || address;
369
+ return {
370
+ address: address,
371
+ totalStake: bnTotalStake.toString(),
372
+ ownStake: bnOwnStake.toString(),
373
+ otherStake: otherStake.toString(),
374
+ minBond: bnMinBond.toString(),
375
+ nominatorCount: nominatorCount,
376
+ commission: roundedCommission,
377
+ expectedReturn: apyCalculate.apy,
378
+ blocked: false,
379
+ isVerified: false,
380
+ chain: this.chain,
381
+ isCrowded: false,
382
+ identity: name
383
+ };
384
+ }));
385
+ return results;
386
+ }
387
+ async getPoolTargets() {
388
+ if (!this.isInit) {
389
+ await this.init();
390
+ }
391
+ if (this.chain === 'bittensor') {
392
+ return this.getMainnetPoolTargets();
393
+ } else {
394
+ return this.getDevnetPoolTargets();
395
+ }
396
+ }
397
+
398
+ /* Get pool targets */
399
+
400
+ /* Join pool action */
401
+
402
+ async createJoinExtrinsic(data, positionInfo, bondDest = 'Staked') {
403
+ const {
404
+ amount,
405
+ netuid,
406
+ selectedValidators: targetValidators
407
+ } = data;
408
+ const chainApi = await this.substrateApi.isReady;
409
+ const binaryAmount = new BN(amount);
410
+ const selectedValidatorInfo = targetValidators[0];
411
+ const hotkey = selectedValidatorInfo.address;
412
+ const extrinsic = chainApi.api.tx.subtensorModule.addStake(hotkey, netuid, binaryAmount);
413
+ return [extrinsic, {
414
+ slug: this.nativeToken.slug,
415
+ amount: '0'
416
+ }];
417
+ }
418
+
419
+ /* Join pool action */
420
+
421
+ /* Leave pool action */
422
+
423
+ async handleYieldUnstake(amount, address, selectedTarget, netuid) {
424
+ const apiPromise = await this.substrateApi.isReady;
425
+ const binaryAmount = new BN(amount);
426
+ if (!selectedTarget) {
427
+ return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
428
+ }
429
+ const extrinsic = apiPromise.api.tx.subtensorModule.removeStake(selectedTarget, netuid, binaryAmount);
430
+ return [ExtrinsicType.STAKING_UNBOND, extrinsic];
431
+ }
432
+
433
+ /* Leave pool action */
434
+ }
@@ -3,3 +3,4 @@ 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
5
  export { default as TaoNativeStakingPoolHandler } from './tao';
6
+ export { default as SubnetTaoStakingPoolHandler } from './dtao';
@@ -5,4 +5,5 @@ export { default as AmplitudeNativeStakingPoolHandler } from "./amplitude.js";
5
5
  export { default as AstarNativeStakingPoolHandler } from "./astar.js";
6
6
  export { default as RelayNativeStakingPoolHandler } from "./relay-chain.js";
7
7
  export { default as ParaNativeStakingPoolHandler } from "./para-chain.js";
8
- export { default as TaoNativeStakingPoolHandler } from "./tao.js";
8
+ export { default as TaoNativeStakingPoolHandler } from "./tao.js";
9
+ export { default as SubnetTaoStakingPoolHandler } from "./dtao.js";