@subwallet/extension-base 1.3.46-0 → 1.3.48-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 (119) hide show
  1. package/background/KoniTypes.d.ts +7 -1
  2. package/background/KoniTypes.js +1 -0
  3. package/background/errors/TransactionError.js +4 -0
  4. package/cjs/background/KoniTypes.js +1 -0
  5. package/cjs/background/errors/TransactionError.js +4 -0
  6. package/cjs/core/logic-validation/transfer.js +7 -0
  7. package/cjs/koni/api/nft/config.js +1 -1
  8. package/cjs/koni/api/nft/ordinal_nft/index.js +3 -2
  9. package/cjs/koni/background/handlers/Extension.js +21 -1
  10. package/cjs/koni/background/handlers/State.js +3 -0
  11. package/cjs/packageInfo.js +1 -1
  12. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +8 -14
  13. package/cjs/services/buy-service/index.js +2 -0
  14. package/cjs/services/chain-service/index.js +7 -2
  15. package/cjs/services/chain-service/utils/index.js +3 -0
  16. package/cjs/services/chain-service/utils/patch.js +1 -1
  17. package/cjs/services/earning-service/constants/chains.js +4 -2
  18. package/cjs/services/earning-service/handlers/lending/interlay.js +2 -1
  19. package/cjs/services/earning-service/handlers/liquid-staking/acala.js +2 -1
  20. package/cjs/services/earning-service/handlers/liquid-staking/bifrost.js +2 -1
  21. package/cjs/services/earning-service/handlers/liquid-staking/parallel.js +2 -1
  22. package/cjs/services/earning-service/handlers/liquid-staking/stella-swap.js +2 -1
  23. package/cjs/services/earning-service/handlers/native-staking/amplitude.js +32 -0
  24. package/cjs/services/earning-service/handlers/native-staking/astar.js +20 -1
  25. package/cjs/services/earning-service/handlers/native-staking/base.js +42 -30
  26. package/cjs/services/earning-service/handlers/native-staking/dtao.js +79 -21
  27. package/cjs/services/earning-service/handlers/native-staking/mythos.js +30 -1
  28. package/cjs/services/earning-service/handlers/native-staking/para-chain.js +17 -0
  29. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +49 -6
  30. package/cjs/services/earning-service/handlers/native-staking/tao.js +98 -32
  31. package/cjs/services/earning-service/handlers/nomination-pool/index.js +5 -2
  32. package/cjs/services/earning-service/handlers/special.js +3 -1
  33. package/cjs/services/earning-service/service.js +52 -7
  34. package/cjs/services/history-service/index.js +12 -7
  35. package/cjs/services/subscan-service/index.js +35 -104
  36. package/cjs/services/transaction-service/helpers/index.js +2 -0
  37. package/cjs/services/transaction-service/index.js +15 -0
  38. package/cjs/services/transaction-service/utils.js +10 -1
  39. package/cjs/strategy/api-request-strategy/index.js +1 -0
  40. package/cjs/strategy/api-request-strategy/utils/index.js +2 -2
  41. package/cjs/strategy/api-request-strategy-v2/index.js +138 -0
  42. package/cjs/strategy/api-request-strategy-v2/types.js +1 -0
  43. package/cjs/types/transaction/error.js +1 -0
  44. package/cjs/utils/account/transform.js +3 -2
  45. package/cjs/utils/gear/combine.js +4 -3
  46. package/cjs/utils/gear/vft.js +104 -135
  47. package/core/logic-validation/transfer.js +7 -0
  48. package/koni/api/nft/config.d.ts +1 -1
  49. package/koni/api/nft/config.js +1 -1
  50. package/koni/api/nft/ordinal_nft/index.js +3 -2
  51. package/koni/background/handlers/Extension.d.ts +1 -0
  52. package/koni/background/handlers/Extension.js +21 -1
  53. package/koni/background/handlers/State.js +4 -1
  54. package/package.json +20 -9
  55. package/packageInfo.js +1 -1
  56. package/services/balance-service/helpers/subscribe/substrate/index.js +8 -14
  57. package/services/buy-service/index.js +2 -0
  58. package/services/chain-service/index.js +7 -2
  59. package/services/chain-service/utils/index.js +3 -0
  60. package/services/chain-service/utils/patch.js +1 -1
  61. package/services/earning-service/constants/chains.d.ts +1 -0
  62. package/services/earning-service/constants/chains.js +2 -1
  63. package/services/earning-service/handlers/base.d.ts +5 -3
  64. package/services/earning-service/handlers/lending/interlay.d.ts +1 -1
  65. package/services/earning-service/handlers/lending/interlay.js +2 -1
  66. package/services/earning-service/handlers/liquid-staking/acala.d.ts +1 -1
  67. package/services/earning-service/handlers/liquid-staking/acala.js +2 -1
  68. package/services/earning-service/handlers/liquid-staking/bifrost.d.ts +1 -1
  69. package/services/earning-service/handlers/liquid-staking/bifrost.js +2 -1
  70. package/services/earning-service/handlers/liquid-staking/parallel.d.ts +1 -1
  71. package/services/earning-service/handlers/liquid-staking/parallel.js +2 -1
  72. package/services/earning-service/handlers/liquid-staking/stella-swap.d.ts +1 -1
  73. package/services/earning-service/handlers/liquid-staking/stella-swap.js +2 -1
  74. package/services/earning-service/handlers/native-staking/amplitude.d.ts +1 -0
  75. package/services/earning-service/handlers/native-staking/amplitude.js +32 -0
  76. package/services/earning-service/handlers/native-staking/astar.d.ts +2 -1
  77. package/services/earning-service/handlers/native-staking/astar.js +20 -1
  78. package/services/earning-service/handlers/native-staking/base.d.ts +4 -2
  79. package/services/earning-service/handlers/native-staking/base.js +42 -30
  80. package/services/earning-service/handlers/native-staking/dtao.d.ts +5 -3
  81. package/services/earning-service/handlers/native-staking/dtao.js +80 -22
  82. package/services/earning-service/handlers/native-staking/mythos.d.ts +2 -1
  83. package/services/earning-service/handlers/native-staking/mythos.js +30 -1
  84. package/services/earning-service/handlers/native-staking/para-chain.d.ts +1 -0
  85. package/services/earning-service/handlers/native-staking/para-chain.js +17 -0
  86. package/services/earning-service/handlers/native-staking/relay-chain.d.ts +6 -1
  87. package/services/earning-service/handlers/native-staking/relay-chain.js +50 -7
  88. package/services/earning-service/handlers/native-staking/tao.d.ts +23 -4
  89. package/services/earning-service/handlers/native-staking/tao.js +99 -33
  90. package/services/earning-service/handlers/nomination-pool/index.d.ts +3 -2
  91. package/services/earning-service/handlers/nomination-pool/index.js +5 -2
  92. package/services/earning-service/handlers/special.d.ts +2 -1
  93. package/services/earning-service/handlers/special.js +3 -1
  94. package/services/earning-service/service.d.ts +3 -1
  95. package/services/earning-service/service.js +52 -7
  96. package/services/history-service/index.js +12 -7
  97. package/services/subscan-service/index.d.ts +13 -27
  98. package/services/subscan-service/index.js +26 -95
  99. package/services/transaction-service/helpers/index.js +2 -0
  100. package/services/transaction-service/index.js +15 -0
  101. package/services/transaction-service/utils.js +11 -2
  102. package/strategy/api-request-strategy/context/base.d.ts +2 -6
  103. package/strategy/api-request-strategy/index.js +1 -0
  104. package/strategy/api-request-strategy/types.d.ts +4 -2
  105. package/strategy/api-request-strategy/utils/index.js +2 -2
  106. package/strategy/api-request-strategy-v2/index.d.ts +22 -0
  107. package/strategy/api-request-strategy-v2/index.js +128 -0
  108. package/strategy/api-request-strategy-v2/types.d.ts +11 -0
  109. package/strategy/api-request-strategy-v2/types.js +1 -0
  110. package/types/buy.d.ts +1 -1
  111. package/types/transaction/error.d.ts +2 -1
  112. package/types/transaction/error.js +1 -0
  113. package/types/yield/actions/join/submit.d.ts +10 -1
  114. package/types/yield/info/chain/info.d.ts +2 -0
  115. package/utils/account/transform.js +3 -2
  116. package/utils/gear/combine.d.ts +2 -1
  117. package/utils/gear/combine.js +4 -4
  118. package/utils/gear/vft.d.ts +20 -9
  119. package/utils/gear/vft.js +104 -135
@@ -6,7 +6,7 @@ import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { calculateAlephZeroValidatorReturn, calculateChainStakedReturnV2, calculateInflation, calculateTernoaValidatorReturn, calculateValidatorStakedReturn, getAvgValidatorEraReward, getCommission, getMaxValidatorErrorMessage, getMinStakeErrorMessage, getRelayBlockedValidatorList, getRelayEraRewardMap, getRelayMaxNominations, getRelayTopValidatorByPoints, getRelayValidatorPointsMap, getRelayWaitingValidatorList, getSupportedDaysByHistoryDepth } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
7
7
  import { _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
8
8
  import { _getChainSubstrateAddressPrefix } from '@subwallet/extension-base/services/chain-service/utils';
9
- import { _STAKING_CHAIN_GROUP, MaxEraRewardPointsEras } from '@subwallet/extension-base/services/earning-service/constants';
9
+ import { _STAKING_CHAIN_GROUP, _SUPPORT_CHANGE_VALIDATOR_CHAIN, MaxEraRewardPointsEras } from '@subwallet/extension-base/services/earning-service/constants';
10
10
  import { applyDecimal, parseIdentity } from '@subwallet/extension-base/services/earning-service/utils';
11
11
  import { BasicTxErrorType, EarningStatus, StakingTxErrorType, UnstakingStatus } from '@subwallet/extension-base/types';
12
12
  import { balanceFormatter, formatNumber, reformatAddress } from '@subwallet/extension-base/utils';
@@ -15,6 +15,24 @@ import { t } from 'i18next';
15
15
  import { BN, BN_ZERO } from '@polkadot/util';
16
16
  import BaseNativeStakingPoolHandler from "./base.js";
17
17
  export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPoolHandler {
18
+ availableMethod = {
19
+ join: true,
20
+ defaultUnstake: true,
21
+ fastUnstake: false,
22
+ cancelUnstake: true,
23
+ withdraw: true,
24
+ claimReward: false,
25
+ changeValidator: false
26
+ };
27
+ constructor(state, chain) {
28
+ super(state, chain);
29
+ if (_SUPPORT_CHANGE_VALIDATOR_CHAIN.includes(chain)) {
30
+ this.availableMethod = {
31
+ ...this.availableMethod,
32
+ changeValidator: true
33
+ };
34
+ }
35
+ }
18
36
  /* Subscribe pool info */
19
37
 
20
38
  async subscribePoolInfo(callback) {
@@ -283,6 +301,22 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
283
301
  unsub === null || unsub === void 0 ? void 0 : unsub();
284
302
  };
285
303
  }
304
+ async checkAccountHaveStake(useAddresses) {
305
+ var _substrateApi$api$que22, _substrateApi$api$que23, _substrateApi$api$que24;
306
+ const result = [];
307
+ const substrateApi = await this.substrateApi.isReady;
308
+ const ledgers = await ((_substrateApi$api$que22 = substrateApi.api.query.staking) === null || _substrateApi$api$que22 === void 0 ? void 0 : (_substrateApi$api$que23 = _substrateApi$api$que22.ledger) === null || _substrateApi$api$que23 === void 0 ? void 0 : (_substrateApi$api$que24 = _substrateApi$api$que23.multi) === null || _substrateApi$api$que24 === void 0 ? void 0 : _substrateApi$api$que24.call(_substrateApi$api$que23, useAddresses));
309
+ if (ledgers) {
310
+ for (let i = 0; i < useAddresses.length; i++) {
311
+ const address = useAddresses[i];
312
+ const _ledger = ledgers[i].toPrimitive();
313
+ if (_ledger.total > 0) {
314
+ result.push(address);
315
+ }
316
+ }
317
+ }
318
+ return result;
319
+ }
286
320
 
287
321
  /* Subscribe pool position */
288
322
 
@@ -652,13 +686,11 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
652
686
  const chainApi = await this.substrateApi.isReady;
653
687
  if (chainApi.api.tx.staking.withdrawUnbonded.meta.args.length === 1) {
654
688
  let slashingSpanCount;
655
- if (chainApi.api.query.staking.nominatorSlashInEra) {
656
- const currentEra = await chainApi.api.query.staking.currentEra();
657
- const slashingSpans = (await chainApi.api.query.staking.nominatorSlashInEra(currentEra.toPrimitive(), address)).toPrimitive();
658
- slashingSpanCount = slashingSpans !== null ? slashingSpans.toString() : '0';
659
- } else {
689
+ if (chainApi.api.query.staking.slashingSpans) {
660
690
  const _slashingSpans = (await chainApi.api.query.staking.slashingSpans(address)).toHuman();
661
691
  slashingSpanCount = _slashingSpans !== null ? _slashingSpans.spanIndex : '0';
692
+ } else {
693
+ slashingSpanCount = chainApi.api.consts.staking.historyDepth.toPrimitive();
662
694
  }
663
695
  return chainApi.api.tx.staking.withdrawUnbonded(slashingSpanCount);
664
696
  } else {
@@ -666,6 +698,17 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
666
698
  return chainApi.api.tx.staking.withdrawUnbonded();
667
699
  }
668
700
  }
669
-
701
+ async handleChangeEarningValidator(data) {
702
+ const chainApi = await this.substrateApi.isReady;
703
+ const {
704
+ selectedValidators
705
+ } = data;
706
+ if (!selectedValidators || selectedValidators.length === 0) {
707
+ return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
708
+ }
709
+ const validatorParamList = selectedValidators.map(validator => validator.address);
710
+ const nominateTx = chainApi.api.tx.staking.nominate(validatorParamList);
711
+ return nominateTx;
712
+ }
670
713
  /* Other actions */
671
714
  }
@@ -3,7 +3,7 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
3
3
  import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
4
4
  import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
5
5
  import BaseParaStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/base-para';
6
- import { BaseYieldPositionInfo, OptimalYieldPath, StakeCancelWithdrawalParams, SubmitJoinNativeStaking, TransactionData, UnstakingInfo, ValidatorInfo, YieldPoolInfo, YieldPoolMethodInfo, YieldPositionInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
6
+ import { BaseYieldPositionInfo, OptimalYieldPath, StakeCancelWithdrawalParams, SubmitBittensorChangeValidatorStaking, SubmitJoinNativeStaking, TransactionData, UnstakingInfo, ValidatorInfo, YieldPoolInfo, YieldPoolMethodInfo, YieldPositionInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
7
7
  export interface TaoStakeInfo {
8
8
  hotkey: string;
9
9
  stake: string;
@@ -31,11 +31,27 @@ interface Validator {
31
31
  ss58: string;
32
32
  };
33
33
  name: string;
34
- nominators: number;
34
+ global_nominators: number;
35
+ validator_return_per_day: string;
36
+ nominator_return_per_day: string;
35
37
  stake: string;
36
38
  validator_stake: string;
37
39
  take: string;
38
- apr: string;
40
+ root_stake: string;
41
+ global_weighted_stake: string;
42
+ weighted_root_stake: string;
43
+ global_alpha_stake_as_tao: string;
44
+ }
45
+ interface ValidatorAprResponse {
46
+ data: ValidatorApr[];
47
+ }
48
+ interface ValidatorApr {
49
+ hotkey: {
50
+ ss58: string;
51
+ };
52
+ name: string;
53
+ netuid: number;
54
+ thirty_day_apy: string;
39
55
  }
40
56
  export declare class BittensorCache {
41
57
  private static instance;
@@ -46,9 +62,10 @@ export declare class BittensorCache {
46
62
  static getInstance(): BittensorCache;
47
63
  get(): Promise<ValidatorResponse>;
48
64
  private fetchData;
65
+ fetchApr(netuid: number): Promise<ValidatorAprResponse>;
49
66
  }
50
67
  export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHandler {
51
- protected readonly availableMethod: YieldPoolMethodInfo;
68
+ readonly availableMethod: YieldPoolMethodInfo;
52
69
  private bittensorCache;
53
70
  constructor(state: KoniState, chain: string);
54
71
  handleYieldWithdraw(address: string, unstakingInfo: UnstakingInfo): Promise<TransactionData>;
@@ -57,6 +74,7 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
57
74
  subscribePoolInfo(callback: (data: YieldPoolInfo) => void): Promise<VoidFunction>;
58
75
  parseNominatorMetadata(chainInfo: _ChainInfo, address: string, delegatorState: TaoStakingStakeOption[]): Promise<Omit<YieldPositionInfo, keyof BaseYieldPositionInfo>>;
59
76
  subscribePoolPosition(useAddresses: string[], rsCallback: (rs: YieldPositionInfo) => void): Promise<VoidFunction>;
77
+ checkAccountHaveStake(useAddresses: string[]): Promise<string[]>;
60
78
  private getDevnetPoolTargets;
61
79
  private getMainnetPoolTargets;
62
80
  getPoolTargets(): Promise<ValidatorInfo[]>;
@@ -64,5 +82,6 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
64
82
  validateYieldJoin(data: SubmitJoinNativeStaking, path: OptimalYieldPath): Promise<TransactionError[]>;
65
83
  handleYieldUnstake(amount: string, address: string, selectedTarget?: string): Promise<[ExtrinsicType, TransactionData]>;
66
84
  validateYieldLeave(amount: string, address: string, fastLeave: boolean, selectedTarget?: string, slug?: string, poolInfo?: YieldPoolInfo): Promise<TransactionError[]>;
85
+ handleChangeEarningValidator(data: SubmitBittensorChangeValidatorStaking): Promise<TransactionData>;
67
86
  }
68
87
  export {};
@@ -7,14 +7,12 @@ import { BITTENSOR_REFRESH_STAKE_APY, BITTENSOR_REFRESH_STAKE_INFO } from '@subw
7
7
  import { getEarningStatusByNominations } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
8
8
  import { _getAssetDecimals, _getAssetSymbol } from '@subwallet/extension-base/services/chain-service/utils';
9
9
  import BaseParaStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/base-para';
10
- import { BasicTxErrorType, EarningStatus } from '@subwallet/extension-base/types';
10
+ import { BasicTxErrorType, EarningStatus, StakingTxErrorType } from '@subwallet/extension-base/types';
11
11
  import { ProxyServiceRoute } from '@subwallet/extension-base/types/environment';
12
12
  import { fetchFromProxyService, formatNumber, reformatAddress } from '@subwallet/extension-base/utils';
13
13
  import BigN from 'bignumber.js';
14
14
  import { t } from 'i18next';
15
15
  import { BN, BN_ZERO } from '@polkadot/util';
16
- import { calculateReward } from "../../utils/index.js";
17
- import { DEFAULT_DTAO_MINBOND } from "./dtao.js";
18
16
  /* Fetch data */
19
17
  export class BittensorCache {
20
18
  static instance = null;
@@ -42,7 +40,7 @@ export class BittensorCache {
42
40
  }
43
41
  async fetchData() {
44
42
  try {
45
- const resp = await fetchFromProxyService(ProxyServiceRoute.BITTENSOR, '/validator/latest/v1?limit=50', {
43
+ const resp = await fetchFromProxyService(ProxyServiceRoute.BITTENSOR, '/dtao/validator/latest/v1?limit=100', {
46
44
  method: 'GET',
47
45
  headers: {
48
46
  'Content-Type': 'application/json'
@@ -56,7 +54,7 @@ export class BittensorCache {
56
54
  }
57
55
  const rawData = await resp.json();
58
56
  const data = {
59
- data: rawData.data.filter(validator => parseFloat(validator.apr) > 0.0001)
57
+ data: rawData.data.filter(validator => parseFloat(validator.root_stake) > 0)
60
58
  };
61
59
  this.cache = data;
62
60
  this.promise = null;
@@ -79,6 +77,27 @@ export class BittensorCache {
79
77
  };
80
78
  }
81
79
  }
80
+ async fetchApr(netuid) {
81
+ try {
82
+ const resp = await fetchFromProxyService(ProxyServiceRoute.BITTENSOR, `/dtao/validator/yield/latest/v1?netuid=${netuid}&limit=100&order=thirty_day_apy_desc`, {
83
+ method: 'GET',
84
+ headers: {
85
+ 'Content-Type': 'application/json'
86
+ }
87
+ });
88
+ const rawData = await resp.json();
89
+
90
+ // Some subnets not return data, ensure the structure is consistent by returning an empty array
91
+ return Array.isArray(rawData.data) ? rawData : {
92
+ data: []
93
+ };
94
+ } catch (error) {
95
+ console.error(error);
96
+ return {
97
+ data: []
98
+ };
99
+ }
100
+ }
82
101
  }
83
102
 
84
103
  // export async function fetchTaoDelegateState (address: string): Promise<RawDelegateState> {
@@ -117,7 +136,8 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
117
136
  fastUnstake: false,
118
137
  cancelUnstake: false,
119
138
  withdraw: false,
120
- claimReward: false
139
+ claimReward: false,
140
+ changeValidator: true
121
141
  };
122
142
  constructor(state, chain) {
123
143
  super(state, chain);
@@ -153,23 +173,18 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
153
173
  const minDelegatorStake = (await substrateApi.api.query.subtensorModule.nominatorMinRequiredStake()).toPrimitive() || 0;
154
174
  const maxValidatorPerNominator = (await substrateApi.api.query.subtensorModule.maxAllowedValidators(0)).toPrimitive();
155
175
  const taoIn = (await substrateApi.api.query.subtensorModule.subnetTAO(0)).toPrimitive();
156
- const _topValidator = await this.bittensorCache.get();
176
+ const _topValidator = await this.bittensorCache.fetchApr(0);
157
177
  const validators = _topValidator.data;
158
- let highestApr = validators[0];
159
- for (let i = 1; i < validators.length; i++) {
160
- if (parseFloat(validators[i].apr) > parseFloat(highestApr.apr)) {
161
- highestApr = validators[i];
162
- }
163
- }
178
+ const highestApr = validators[0];
164
179
  const bnTaoIn = new BigN(taoIn);
165
180
  const BNminDelegatorStake = new BigN(minDelegatorStake.toString());
166
- const apr = this.chain === 'bittensor' ? Number(highestApr.apr) * 100 : 0;
181
+ const apr = this.chain === 'bittensor' ? Number(highestApr.thirty_day_apy) * 100 : 0;
167
182
  const data = {
168
183
  ...this.baseInfo,
169
184
  type: this.type,
170
185
  metadata: {
171
186
  ...this.metadataInfo,
172
- description: this.getDescription()
187
+ description: this.getDescription(formatNumber(BNminDelegatorStake, _getAssetDecimals(this.nativeToken)))
173
188
  },
174
189
  statistic: {
175
190
  assetEarning: [{
@@ -380,6 +395,11 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
380
395
  };
381
396
  }
382
397
 
398
+ // Because not have subscan api
399
+ async checkAccountHaveStake(useAddresses) {
400
+ return Promise.resolve([]);
401
+ }
402
+
383
403
  /* Subscribe pool position */
384
404
 
385
405
  /* Get pool targets */
@@ -411,27 +431,32 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
411
431
  const nominatorMinRequiredStake = (await getNominatorMinRequiredStake).toString();
412
432
  const bnMinBond = new BigN(nominatorMinRequiredStake);
413
433
  const validatorList = topValidator.data;
414
- const validatorAddresses = Object.keys(validatorList);
415
- const results = await Promise.all(validatorAddresses.map(i => {
416
- const address = validatorList[i].hotkey.ss58;
417
- const bnTotalStake = new BigN(validatorList[i].stake);
418
- const bnOwnStake = new BigN(validatorList[i].validator_stake);
419
- const otherStake = bnTotalStake.minus(bnOwnStake);
420
- const nominatorCount = validatorList[i].nominators;
421
- const commission = validatorList[i].take;
434
+ const aprResponse = await this.bittensorCache.fetchApr(0);
435
+ const aprMap = {};
436
+ aprResponse.data.forEach(item => {
437
+ aprMap[item.hotkey.ss58] = item.thirty_day_apy;
438
+ });
439
+ const results = await Promise.all(validatorList.map(validator => {
440
+ const address = validator.hotkey.ss58;
441
+ // With bittensor we use total weight, root weight and alpha staked insted of total stake, own stake and other stake
442
+ const bnTotalWeightStake = new BigN(validator.global_weighted_stake);
443
+ const bnRootWeightStake = new BigN(validator.weighted_root_stake);
444
+ const bnAlphaStake = new BigN(validator.global_alpha_stake_as_tao);
445
+ const nominatorCount = validator.global_nominators;
446
+ const commission = validator.take;
422
447
  const roundedCommission = (parseFloat(commission) * 100).toFixed(0);
423
- const apr = (parseFloat(validatorList[i].apr) / 10 ** 9 * 100).toFixed(2);
424
- const apyCalculate = calculateReward(parseFloat(apr));
425
- const name = validatorList[i].name || address;
448
+ const apr = aprMap[address];
449
+ const expectedReturn = apr ? new BigN(apr).multipliedBy(100).toFixed(2) : '0';
450
+ const name = validator.name || address;
426
451
  return {
427
452
  address: address,
428
- totalStake: bnTotalStake.toString(),
429
- ownStake: bnOwnStake.toString(),
430
- otherStake: otherStake.toString(),
453
+ totalStake: bnTotalWeightStake.toString(),
454
+ ownStake: bnRootWeightStake.toString(),
455
+ otherStake: bnAlphaStake.toString(),
431
456
  minBond: bnMinBond.toString(),
432
457
  nominatorCount: nominatorCount,
433
458
  commission: roundedCommission,
434
- expectedReturn: apyCalculate.apy,
459
+ expectedReturn: expectedReturn,
435
460
  blocked: false,
436
461
  isVerified: false,
437
462
  chain: this.chain,
@@ -468,6 +493,8 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
468
493
  amount: '0'
469
494
  }];
470
495
  }
496
+
497
+ // Validate for case stake more
471
498
  async validateYieldJoin(data, path) {
472
499
  const baseErrors = await super.validateYieldJoin(data, path);
473
500
  if (baseErrors.length > 0) {
@@ -476,8 +503,10 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
476
503
  const {
477
504
  amount
478
505
  } = data;
479
- if (new BigN(amount).lt(new BigN(DEFAULT_DTAO_MINBOND))) {
480
- return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t(`Insufficient stake. You need to stake at least ${formatNumber(DEFAULT_DTAO_MINBOND, _getAssetDecimals(this.nativeToken))} ${_getAssetSymbol(this.nativeToken)} to earn rewards`))];
506
+ const minDelegatorStake = (await this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake()).toPrimitive() || 0;
507
+ const bnMinStake = minDelegatorStake.toString();
508
+ if (new BigN(amount).lt(bnMinStake)) {
509
+ return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t(`Insufficient stake. You need to stake at least ${formatNumber(bnMinStake, _getAssetDecimals(this.nativeToken))} ${_getAssetSymbol(this.nativeToken)} to earn rewards`))];
481
510
  }
482
511
  return baseErrors;
483
512
  }
@@ -504,7 +533,8 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
504
533
  if (!poolInfo) {
505
534
  return [new TransactionError(BasicTxErrorType.INVALID_PARAMS)];
506
535
  }
507
- const bnMinUnstake = new BigN(DEFAULT_DTAO_MINBOND);
536
+ const minDelegatorStake = (await this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake()).toPrimitive() || 0;
537
+ const bnMinUnstake = new BigN(minDelegatorStake.toString());
508
538
  if (new BigN(amount).lt(bnMinUnstake)) {
509
539
  return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t(`Amount too low. You need to unstake at least ${formatNumber(bnMinUnstake, _getAssetDecimals(this.nativeToken))} ${_getAssetSymbol(this.nativeToken)}`))];
510
540
  }
@@ -512,4 +542,40 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
512
542
  }
513
543
 
514
544
  /* Leave pool action */
545
+
546
+ /* Change validator */
547
+ async handleChangeEarningValidator(data) {
548
+ const chainApi = await this.substrateApi.isReady;
549
+ const {
550
+ amount,
551
+ maxAmount,
552
+ originValidator,
553
+ selectedValidators: targetValidators
554
+ } = data;
555
+ if (!originValidator) {
556
+ return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
557
+ }
558
+
559
+ // Bittensor only supports changing 1 validator at a time, not multiple
560
+ const selectedValidatorInfo = targetValidators[0];
561
+ const destValidator = selectedValidatorInfo.address;
562
+ if (new BigN(amount).lte(0)) {
563
+ return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('Amount must be greater than 0')));
564
+ }
565
+ if (originValidator === destValidator) {
566
+ return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'From validator is the same with to validator'));
567
+ }
568
+ const minDelegatorStake = (await this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake()).toPrimitive() || 0;
569
+ const bnMinMoveStake = new BigN(minDelegatorStake.toString());
570
+ if (new BigN(maxAmount).lt(bnMinMoveStake)) {
571
+ return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t(`Amount too low. You need to move at least ${formatNumber(bnMinMoveStake, _getAssetDecimals(this.nativeToken))} ${_getAssetSymbol(this.nativeToken)}`)));
572
+ }
573
+
574
+ // Avoid remaining amount too low -> can't do anything with that amount
575
+ if (!(maxAmount === amount) && new BigN(maxAmount).minus(new BigN(amount)).lt(bnMinMoveStake)) {
576
+ return Promise.reject(new TransactionError(StakingTxErrorType.REMAINING_AMOUNT_TOO_LOW, t(`Your remaining stake on the initial validator will fall below minimum active stake and cannot be unstaked if you proceed with the chosen amount. Hit "Move all" to move all ${formatNumber(maxAmount, _getAssetDecimals(this.nativeToken))} ${_getAssetSymbol(this.nativeToken)} to the new validator, or "Cancel" and lower the amount, then try again`)));
577
+ }
578
+ const extrinsic = chainApi.api.tx.subtensorModule.moveStake(originValidator, destValidator, 0, 0, amount);
579
+ return extrinsic;
580
+ }
515
581
  }
@@ -3,7 +3,7 @@ import { ExtrinsicType, UnstakingInfo } from '@subwallet/extension-base/backgrou
3
3
  import { PalletNominationPoolsPoolMember } from '@subwallet/extension-base/core/substrate/types';
4
4
  import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
5
5
  import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
6
- import { BaseYieldPositionInfo, EarningRewardHistoryItem, EarningRewardItem, HandleYieldStepData, NominationPoolInfo, OptimalYieldPath, OptimalYieldPathParams, StakeCancelWithdrawalParams, SubmitJoinNominationPool, SubmitYieldJoinData, TransactionData, YieldPoolInfo, YieldPoolMethodInfo, YieldPoolType, YieldPositionInfo, YieldStepBaseInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
6
+ import { BaseYieldPositionInfo, EarningRewardHistoryItem, EarningRewardItem, HandleYieldStepData, NominationPoolInfo, OptimalYieldPath, OptimalYieldPathParams, StakeCancelWithdrawalParams, SubmitChangeValidatorStaking, SubmitJoinNominationPool, SubmitYieldJoinData, TransactionData, YieldPoolInfo, YieldPoolMethodInfo, YieldPoolType, YieldPositionInfo, YieldStepBaseInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
7
7
  import { DeriveSessionProgress } from '@polkadot/api-derive/types';
8
8
  import BasePoolHandler from '../base';
9
9
  export default class NominationPoolHandler extends BasePoolHandler {
@@ -11,7 +11,7 @@ export default class NominationPoolHandler extends BasePoolHandler {
11
11
  protected readonly name: string;
12
12
  protected readonly shortName: string;
13
13
  slug: string;
14
- protected readonly availableMethod: YieldPoolMethodInfo;
14
+ readonly availableMethod: YieldPoolMethodInfo;
15
15
  static generateSlug(symbol: string, chain: string): string;
16
16
  constructor(state: KoniState, chain: string);
17
17
  protected getDescription(amount?: string): string;
@@ -35,4 +35,5 @@ export default class NominationPoolHandler extends BasePoolHandler {
35
35
  handleYieldCancelUnstake(params: StakeCancelWithdrawalParams): Promise<TransactionData>;
36
36
  handleYieldClaimReward(address: string, bondReward?: boolean): Promise<TransactionData>;
37
37
  handleYieldWithdraw(address: string, unstakingInfo: UnstakingInfo): Promise<TransactionData>;
38
+ handleChangeEarningValidator(data: SubmitChangeValidatorStaking): Promise<TransactionData>;
38
39
  }
@@ -20,7 +20,8 @@ export default class NominationPoolHandler extends BasePoolHandler {
20
20
  fastUnstake: false,
21
21
  cancelUnstake: false,
22
22
  withdraw: true,
23
- claimReward: true
23
+ claimReward: true,
24
+ changeValidator: false
24
25
  };
25
26
  static generateSlug(symbol, chain) {
26
27
  return `${symbol}___nomination_pool___${chain}`;
@@ -575,6 +576,8 @@ export default class NominationPoolHandler extends BasePoolHandler {
575
576
  });
576
577
  }
577
578
  }
578
-
579
+ handleChangeEarningValidator(data) {
580
+ return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED));
581
+ }
579
582
  /* Other actions */
580
583
  }
@@ -2,7 +2,7 @@
2
2
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
3
3
  import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
4
4
  import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
5
- import { BaseYieldStepDetail, HandleYieldStepData, OptimalYieldPath, OptimalYieldPathParams, RequestEarlyValidateYield, ResponseEarlyValidateYield, SpecialYieldPoolInfo, SpecialYieldPoolMetadata, SubmitYieldJoinData, TransactionData, UnstakingInfo, YieldPoolInfo, YieldPoolTarget, YieldPoolType, YieldStepBaseInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
5
+ import { BaseYieldStepDetail, HandleYieldStepData, OptimalYieldPath, OptimalYieldPathParams, RequestEarlyValidateYield, ResponseEarlyValidateYield, SpecialYieldPoolInfo, SpecialYieldPoolMetadata, SubmitChangeValidatorStaking, SubmitYieldJoinData, TransactionData, UnstakingInfo, YieldPoolInfo, YieldPoolTarget, YieldPoolType, YieldStepBaseInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
6
6
  import { BN } from '@polkadot/util';
7
7
  import BasePoolHandler from './base';
8
8
  export default abstract class BaseSpecialStakingPoolHandler extends BasePoolHandler {
@@ -62,4 +62,5 @@ export default abstract class BaseSpecialStakingPoolHandler extends BasePoolHand
62
62
  handleYieldCancelUnstake(): Promise<TransactionData>;
63
63
  handleYieldClaimReward(address: string, bondReward?: boolean): Promise<TransactionData>;
64
64
  handleYieldWithdraw(address: string, unstakingInfo: UnstakingInfo): Promise<TransactionData>;
65
+ handleChangeEarningValidator(data: SubmitChangeValidatorStaking): Promise<TransactionData>;
65
66
  }
@@ -512,6 +512,8 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
512
512
  handleYieldWithdraw(address, unstakingInfo) {
513
513
  return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED));
514
514
  }
515
-
515
+ handleChangeEarningValidator(data) {
516
+ return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED));
517
+ }
516
518
  /* Other actions */
517
519
  }
@@ -3,7 +3,7 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
3
3
  import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
4
4
  import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
5
5
  import { PersistDataServiceInterface, ServiceStatus, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
6
- import { EarningRewardHistoryItem, EarningRewardItem, EarningRewardJson, HandleYieldStepData, HandleYieldStepParams, OptimalYieldPath, OptimalYieldPathParams, RequestEarlyValidateYield, RequestEarningSlippage, RequestStakeCancelWithdrawal, RequestStakeClaimReward, RequestYieldLeave, RequestYieldWithdrawal, ResponseEarlyValidateYield, TransactionData, ValidateYieldProcessParams, YieldPoolInfo, YieldPoolTarget, YieldPositionInfo } from '@subwallet/extension-base/types';
6
+ import { EarningRewardHistoryItem, EarningRewardItem, EarningRewardJson, HandleYieldStepData, HandleYieldStepParams, OptimalYieldPath, OptimalYieldPathParams, RequestEarlyValidateYield, RequestEarningSlippage, RequestStakeCancelWithdrawal, RequestStakeClaimReward, RequestYieldLeave, RequestYieldWithdrawal, ResponseEarlyValidateYield, SubmitChangeValidatorStaking, TransactionData, ValidateYieldProcessParams, YieldPoolInfo, YieldPoolTarget, YieldPositionInfo } from '@subwallet/extension-base/types';
7
7
  import { PromiseHandler } from '@subwallet/extension-base/utils';
8
8
  import { BehaviorSubject } from 'rxjs';
9
9
  import { EarningSlippageResult } from './handlers/native-staking/dtao';
@@ -83,6 +83,7 @@ export default class EarningService implements StoppableServiceInterface, Persis
83
83
  subscribeEarningRewardHistory(): BehaviorSubject<Record<string, EarningRewardHistoryItem>>;
84
84
  getEarningRewardHistory(): Record<string, EarningRewardHistoryItem>;
85
85
  earningsRewardHistoryInterval: NodeJS.Timer | undefined;
86
+ private unSubFetchEarningRewardHistory;
86
87
  runSubscribeEarningRewardHistoryInterval(): void;
87
88
  runUnsubscribeEarningRewardHistoryInterval(): void;
88
89
  /**
@@ -102,5 +103,6 @@ export default class EarningService implements StoppableServiceInterface, Persis
102
103
  handleYieldCancelUnstake(params: RequestStakeCancelWithdrawal): Promise<TransactionData>;
103
104
  handleYieldClaimReward(params: RequestStakeClaimReward): Promise<TransactionData>;
104
105
  yieldGetEarningSlippage(params: RequestEarningSlippage): Promise<EarningSlippageResult>;
106
+ handleYieldChangeValidator(params: SubmitChangeValidatorStaking): Promise<TransactionData>;
105
107
  resetWallet(): Promise<void>;
106
108
  }
@@ -377,7 +377,13 @@ export default class EarningService {
377
377
  delete onlineData[inactiveSlug];
378
378
  }
379
379
  Object.values(onlineData).forEach(item => {
380
- this.updateYieldPoolInfo(item);
380
+ const handler = this.getPoolHandler(item.slug);
381
+ if (!handler) {
382
+ return;
383
+ }
384
+ const updatedItem = structuredClone(item);
385
+ updatedItem.metadata.availableMethod = handler.availableMethod;
386
+ this.updateYieldPoolInfo(updatedItem);
381
387
  });
382
388
  return onlineData;
383
389
  }
@@ -660,18 +666,39 @@ export default class EarningService {
660
666
  if (!addresses.length) {
661
667
  return;
662
668
  }
663
- this.fetchPoolRewardHistory(addresses, result => {
664
- this.updateEarningRewardHistory(result);
665
- }).catch(console.error);
666
- this.earningsRewardHistoryInterval = setInterval(() => {
669
+ let cancel = false;
670
+ let unsub;
671
+ this.unSubFetchEarningRewardHistory = () => {
672
+ if (!cancel) {
673
+ var _unsub2;
674
+ (_unsub2 = unsub) === null || _unsub2 === void 0 ? void 0 : _unsub2();
675
+ cancel = true;
676
+ }
677
+ };
678
+ const fetchData = () => {
667
679
  this.fetchPoolRewardHistory(addresses, result => {
680
+ if (cancel) {
681
+ return;
682
+ }
668
683
  this.updateEarningRewardHistory(result);
684
+ }).then(_unsub => {
685
+ if (!cancel) {
686
+ var _unsub3;
687
+ (_unsub3 = unsub) === null || _unsub3 === void 0 ? void 0 : _unsub3();
688
+ unsub = _unsub;
689
+ }
669
690
  }).catch(console.error);
670
- }, CRON_REFRESH_EARNING_REWARD_HISTORY_INTERVAL);
691
+ };
692
+ if (!cancel) {
693
+ fetchData();
694
+ }
695
+ this.earningsRewardHistoryInterval = setInterval(fetchData, CRON_REFRESH_EARNING_REWARD_HISTORY_INTERVAL);
671
696
  }
672
697
  runUnsubscribeEarningRewardHistoryInterval() {
698
+ var _this$unSubFetchEarni;
673
699
  removeLazy('updateEarningRewardHistory');
674
700
  this.earningRewardHistoryQueue = [];
701
+ (_this$unSubFetchEarni = this.unSubFetchEarningRewardHistory) === null || _this$unSubFetchEarni === void 0 ? void 0 : _this$unSubFetchEarni.call(this);
675
702
  this.earningsRewardHistoryInterval && clearInterval(this.earningsRewardHistoryInterval);
676
703
  }
677
704
 
@@ -693,7 +720,13 @@ export default class EarningService {
693
720
  const handler = this.getPoolHandler(slug);
694
721
  if (!targets.length && handler) {
695
722
  await this.eventService.waitChainReady;
696
- targets = await handler.getPoolTargets();
723
+ const isSubnet = slug.match(/subnet_(\d+)/);
724
+ if (isSubnet) {
725
+ const subnet = Number(isSubnet[1]);
726
+ targets = await handler.getPoolTargets(subnet);
727
+ } else {
728
+ targets = await handler.getPoolTargets();
729
+ }
697
730
  }
698
731
  return targets;
699
732
  }
@@ -836,6 +869,18 @@ export default class EarningService {
836
869
  return Promise.reject(new TransactionError(BasicTxErrorType.INTERNAL_ERROR));
837
870
  }
838
871
  }
872
+ async handleYieldChangeValidator(params) {
873
+ await this.eventService.waitChainReady;
874
+ const {
875
+ slug
876
+ } = params;
877
+ const handler = this.getPoolHandler(slug);
878
+ if (handler) {
879
+ return handler.handleChangeEarningValidator(params);
880
+ } else {
881
+ return Promise.reject(new TransactionError(BasicTxErrorType.INTERNAL_ERROR));
882
+ }
883
+ }
839
884
 
840
885
  /* Other */
841
886
 
@@ -74,7 +74,7 @@ export class HistoryService {
74
74
  /**
75
75
  * @todo: Must improve performance of this function
76
76
  * */
77
- fetchSubscanTransactionHistory(chain, addresses) {
77
+ fetchSubscanTransactionHistory(chain, addresses, groupId) {
78
78
  if (!this.subscanService.checkSupportedSubscanChain(chain) || !addresses.length) {
79
79
  return;
80
80
  }
@@ -87,7 +87,7 @@ export class HistoryService {
87
87
  // However, fetchAllPossibleTransferItems-sent must run after fetchAllPossibleExtrinsicItems,
88
88
  // to avoid "duplicate Extrinsic Hash between items" problem
89
89
 
90
- this.subscanService.fetchAllPossibleExtrinsicItems(chain, address, extrinsicItems => {
90
+ this.subscanService.fetchAllPossibleExtrinsicItems(groupId, chain, address, extrinsicItems => {
91
91
  const result = [];
92
92
  extrinsicItems.forEach(x => {
93
93
  const item = parseSubscanExtrinsicData(address, x, chainInfo);
@@ -105,7 +105,7 @@ export class HistoryService {
105
105
  excludeTransferExtrinsicHash.push(x.extrinsic_hash);
106
106
  }
107
107
  });
108
- this.subscanService.fetchAllPossibleTransferItems(chain, address, 'sent').then(rsMap => {
108
+ this.subscanService.fetchAllPossibleTransferItems(groupId, chain, address, 'sent').then(rsMap => {
109
109
  const result = [];
110
110
  Object.keys(rsMap).forEach(hash => {
111
111
  // only push item that does not have same hash with another item
@@ -125,7 +125,7 @@ export class HistoryService {
125
125
  }).catch(e => {
126
126
  console.log('fetchAllPossibleExtrinsicItems error', e);
127
127
  });
128
- this.subscanService.fetchAllPossibleTransferItems(chain, address, 'received').then(rsMap => {
128
+ this.subscanService.fetchAllPossibleTransferItems(groupId, chain, address, 'received').then(rsMap => {
129
129
  const result = [];
130
130
  Object.keys(rsMap).forEach(hash => {
131
131
  // only push item that does not have same hash with another item
@@ -172,14 +172,19 @@ export class HistoryService {
172
172
  const evmAddresses = getAddressesByChainType(addresses, [ChainType.EVM]);
173
173
  const substrateAddresses = getAddressesByChainType(addresses, [ChainType.SUBSTRATE]);
174
174
  const bitcoinAddresses = getAddressesByChainType(addresses, [ChainType.BITCOIN], chainInfo);
175
+ const groupId = this.subscanService.getGroupId();
175
176
  const subscription = this.historySubject.subscribe(items => {
176
177
  cb(items.filter(filterHistoryItemByAddressAndChain(chain, addresses)));
177
178
  });
179
+ const unsubscribe = () => {
180
+ subscription.unsubscribe();
181
+ this.subscanService.cancelGroupRequest(groupId);
182
+ };
178
183
  if (_isChainSubstrateCompatible(chainInfo)) {
179
184
  if (_isChainEvmCompatible(chainInfo)) {
180
- this.fetchSubscanTransactionHistory(chain, evmAddresses);
185
+ this.fetchSubscanTransactionHistory(chain, evmAddresses, groupId);
181
186
  } else {
182
- this.fetchSubscanTransactionHistory(chain, substrateAddresses);
187
+ this.fetchSubscanTransactionHistory(chain, substrateAddresses, groupId);
183
188
  }
184
189
  } else if (_isChainBitcoinCompatible(chainInfo)) {
185
190
  this.fetchBitcoinTransactionHistory(chain, bitcoinAddresses).catch(e => {
@@ -187,7 +192,7 @@ export class HistoryService {
187
192
  });
188
193
  }
189
194
  return {
190
- unsubscribe: subscription.unsubscribe,
195
+ unsubscribe,
191
196
  value: this.historySubject.getValue().filter(filterHistoryItemByAddressAndChain(chain, addresses))
192
197
  };
193
198
  }