@subwallet/extension-base 1.1.31-beta.0 → 1.1.32-beta.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 (84) hide show
  1. package/background/KoniTypes.d.ts +1 -0
  2. package/cjs/koni/api/staking/bonding/index.js +2 -0
  3. package/cjs/koni/api/staking/bonding/paraChain.js +6 -3
  4. package/cjs/koni/background/cron.js +0 -28
  5. package/cjs/koni/background/handlers/Extension.js +17 -11
  6. package/cjs/koni/background/handlers/State.js +4 -46
  7. package/cjs/koni/background/subscription.js +0 -155
  8. package/cjs/packageInfo.js +1 -1
  9. package/cjs/services/campaign-service/index.js +19 -0
  10. package/cjs/services/chain-service/constants.js +3 -2
  11. package/cjs/services/earning-service/constants/chains.js +1 -1
  12. package/cjs/services/earning-service/handlers/base.js +9 -6
  13. package/cjs/services/earning-service/handlers/lending/base.js +61 -0
  14. package/cjs/services/earning-service/handlers/lending/interlay.js +3 -2
  15. package/cjs/services/earning-service/handlers/liquid-staking/acala.js +3 -2
  16. package/cjs/services/earning-service/handlers/liquid-staking/base.js +54 -0
  17. package/cjs/services/earning-service/handlers/liquid-staking/bifrost.js +3 -2
  18. package/cjs/services/earning-service/handlers/liquid-staking/parallel.js +3 -2
  19. package/cjs/services/earning-service/handlers/liquid-staking/stella-swap.js +16 -7
  20. package/cjs/services/earning-service/handlers/native-staking/amplitude.js +7 -2
  21. package/cjs/services/earning-service/handlers/native-staking/astar.js +7 -2
  22. package/cjs/services/earning-service/handlers/native-staking/base.js +4 -2
  23. package/cjs/services/earning-service/handlers/native-staking/para-chain.js +7 -2
  24. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +12 -3
  25. package/cjs/services/earning-service/handlers/nomination-pool/index.js +9 -3
  26. package/cjs/services/earning-service/handlers/special.js +57 -67
  27. package/cjs/services/earning-service/service.js +370 -37
  28. package/cjs/services/event-service/index.js +1 -0
  29. package/cjs/services/migration-service/scripts/index.js +1 -2
  30. package/cjs/services/storage-service/DatabaseService.js +15 -0
  31. package/cjs/services/storage-service/db-stores/Campaign.js +9 -3
  32. package/cjs/services/storage-service/db-stores/YieldPositionStore.js +6 -0
  33. package/cjs/services/transaction-service/index.js +15 -1
  34. package/cjs/utils/number.js +3 -1
  35. package/koni/api/staking/bonding/index.d.ts +1 -0
  36. package/koni/api/staking/bonding/index.js +2 -0
  37. package/koni/api/staking/bonding/paraChain.js +6 -3
  38. package/koni/background/cron.d.ts +0 -5
  39. package/koni/background/cron.js +1 -29
  40. package/koni/background/handlers/Extension.js +17 -11
  41. package/koni/background/handlers/State.d.ts +1 -12
  42. package/koni/background/handlers/State.js +4 -46
  43. package/koni/background/subscription.d.ts +1 -11
  44. package/koni/background/subscription.js +2 -157
  45. package/package.json +6 -6
  46. package/packageInfo.js +1 -1
  47. package/services/campaign-service/index.js +19 -0
  48. package/services/chain-service/constants.js +3 -2
  49. package/services/earning-service/constants/chains.js +1 -1
  50. package/services/earning-service/handlers/base.d.ts +1 -0
  51. package/services/earning-service/handlers/base.js +9 -6
  52. package/services/earning-service/handlers/lending/base.d.ts +2 -0
  53. package/services/earning-service/handlers/lending/base.js +61 -0
  54. package/services/earning-service/handlers/lending/interlay.js +4 -3
  55. package/services/earning-service/handlers/liquid-staking/acala.js +4 -3
  56. package/services/earning-service/handlers/liquid-staking/base.d.ts +2 -0
  57. package/services/earning-service/handlers/liquid-staking/base.js +55 -1
  58. package/services/earning-service/handlers/liquid-staking/bifrost.js +4 -3
  59. package/services/earning-service/handlers/liquid-staking/parallel.js +4 -3
  60. package/services/earning-service/handlers/liquid-staking/stella-swap.js +16 -7
  61. package/services/earning-service/handlers/native-staking/amplitude.js +7 -2
  62. package/services/earning-service/handlers/native-staking/astar.js +7 -2
  63. package/services/earning-service/handlers/native-staking/base.js +5 -3
  64. package/services/earning-service/handlers/native-staking/para-chain.js +7 -2
  65. package/services/earning-service/handlers/native-staking/relay-chain.js +12 -3
  66. package/services/earning-service/handlers/nomination-pool/index.js +10 -4
  67. package/services/earning-service/handlers/special.d.ts +0 -1
  68. package/services/earning-service/handlers/special.js +58 -68
  69. package/services/earning-service/service.d.ts +49 -1
  70. package/services/earning-service/service.js +358 -28
  71. package/services/event-service/index.d.ts +1 -0
  72. package/services/event-service/index.js +1 -0
  73. package/services/event-service/types.d.ts +1 -0
  74. package/services/migration-service/scripts/index.js +1 -2
  75. package/services/storage-service/DatabaseService.d.ts +5 -0
  76. package/services/storage-service/DatabaseService.js +15 -0
  77. package/services/storage-service/db-stores/Campaign.js +9 -3
  78. package/services/storage-service/db-stores/YieldPositionStore.d.ts +2 -0
  79. package/services/storage-service/db-stores/YieldPositionStore.js +6 -0
  80. package/services/transaction-service/index.js +15 -1
  81. package/types/yield/actions/join/submit.d.ts +2 -1
  82. package/types/yield/info/account/reward.d.ts +2 -0
  83. package/utils/number.d.ts +1 -0
  84. package/utils/number.js +1 -0
@@ -147,7 +147,8 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
147
147
  status: UnstakingStatus.UNLOCKING
148
148
  });
149
149
  }
150
- const acviteToTotal = new BN(balance).mul(exchangeRate).div(decimals);
150
+ const activeBalance = new BN(balance);
151
+ const acviteToTotal = activeBalance.mul(exchangeRate).div(decimals);
151
152
  const totalBalance = acviteToTotal.add(unlockBalance);
152
153
  const result = {
153
154
  ...this.baseInfo,
@@ -159,7 +160,7 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
159
160
  unstakeBalance: unlockBalance.toString(),
160
161
  isBondedBefore: totalBalance.gt(BN_ZERO),
161
162
  derivativeToken: derivativeTokenSlug,
162
- status: EarningStatus.EARNING_REWARD,
163
+ status: activeBalance.gt(BN_ZERO) ? EarningStatus.EARNING_REWARD : EarningStatus.NOT_EARNING,
163
164
  nominations: [],
164
165
  unstakings
165
166
  };
@@ -222,9 +223,15 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
222
223
 
223
224
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment
224
225
  const depositCall = stakingContract.methods.deposit(params.amount);
225
-
226
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
227
- const estimatedDepositGas = await depositCall.estimateGas();
226
+ let estimatedDepositGas = 0;
227
+ try {
228
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
229
+ estimatedDepositGas = await depositCall.estimateGas({
230
+ from: params.address
231
+ });
232
+ } catch (e) {
233
+ console.error(e);
234
+ }
228
235
  const gasPrice = await evmApi.api.eth.getGasPrice();
229
236
  return {
230
237
  slug: this.feeAssets[0],
@@ -277,7 +284,8 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
277
284
  extrinsicType: ExtrinsicType.TOKEN_APPROVE,
278
285
  extrinsic: transactionObject,
279
286
  txData: _data,
280
- transferNativeAmount: '0'
287
+ transferNativeAmount: '0',
288
+ chainType: ChainType.EVM
281
289
  });
282
290
  }
283
291
  async handleSubmitStep(data, path) {
@@ -313,7 +321,8 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin
313
321
  extrinsicType: ExtrinsicType.MINT_STDOT,
314
322
  extrinsic: transactionObject,
315
323
  txData: data,
316
- transferNativeAmount: '0'
324
+ transferNativeAmount: '0',
325
+ chainType: ChainType.EVM
317
326
  };
318
327
  }
319
328
 
@@ -17,7 +17,7 @@ export default class AmplitudeNativeStakingPoolHandler extends BaseParaNativeSta
17
17
  async subscribePoolInfo(callback) {
18
18
  let cancel = false;
19
19
  const nativeToken = this.nativeToken;
20
- if (!this.isActive) {
20
+ const defaultCallback = async () => {
21
21
  const data = {
22
22
  ...this.baseInfo,
23
23
  type: this.type,
@@ -26,11 +26,16 @@ export default class AmplitudeNativeStakingPoolHandler extends BaseParaNativeSta
26
26
  description: this.getDescription()
27
27
  }
28
28
  };
29
- callback(data);
29
+ const poolInfo = await this.getPoolInfo();
30
+ !poolInfo && callback(data);
31
+ };
32
+ if (!this.isActive) {
33
+ await defaultCallback();
30
34
  return () => {
31
35
  cancel = true;
32
36
  };
33
37
  }
38
+ await defaultCallback();
34
39
  const substrateApi = await this.substrateApi.isReady;
35
40
  const unsub = await substrateApi.api.query.parachainStaking.round(async _round => {
36
41
  if (cancel) {
@@ -49,7 +49,7 @@ export default class AstarNativeStakingPoolHandler extends BaseParaNativeStaking
49
49
  async subscribePoolInfo(callback) {
50
50
  let cancel = false;
51
51
  const nativeToken = this.nativeToken;
52
- if (!this.isActive) {
52
+ const defaultCallback = async () => {
53
53
  const data = {
54
54
  ...this.baseInfo,
55
55
  type: this.type,
@@ -58,11 +58,16 @@ export default class AstarNativeStakingPoolHandler extends BaseParaNativeStaking
58
58
  description: this.getDescription()
59
59
  }
60
60
  };
61
- callback(data);
61
+ const poolInfo = await this.getPoolInfo();
62
+ !poolInfo && callback(data);
63
+ };
64
+ if (!this.isActive) {
65
+ await defaultCallback();
62
66
  return () => {
63
67
  cancel = true;
64
68
  };
65
69
  }
70
+ await defaultCallback();
66
71
  const apyPromise = new Promise(resolve => {
67
72
  fetch(`https://api.astar.network/api/v1/${this.chain}/dapps-staking/apy`, {
68
73
  method: 'GET'
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
- import { BasicTxErrorType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
5
+ import { BasicTxErrorType, ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { YieldPoolType, YieldStepType } from '@subwallet/extension-base/types';
7
7
  import { noop } from '@polkadot/util';
8
8
  import BasePoolHandler from "../base.js";
@@ -59,7 +59,8 @@ export default class BaseNativeStakingPoolHandler extends BasePoolHandler {
59
59
  address: address,
60
60
  group: this.group,
61
61
  blockTimestamp: timeStamp,
62
- amount: item.amount
62
+ amount: item.amount,
63
+ eventIndex: item.event_index
63
64
  };
64
65
  callBack(data);
65
66
  }
@@ -126,7 +127,8 @@ export default class BaseNativeStakingPoolHandler extends BasePoolHandler {
126
127
  extrinsicType: ExtrinsicType.STAKING_BOND,
127
128
  extrinsic,
128
129
  txData: bondingData,
129
- transferNativeAmount: amount
130
+ transferNativeAmount: amount,
131
+ chainType: ChainType.SUBSTRATE
130
132
  };
131
133
  }
132
134
 
@@ -17,7 +17,7 @@ export default class ParaNativeStakingPoolHandler extends BaseParaNativeStakingP
17
17
  let cancel = false;
18
18
  const chainApi = this.substrateApi;
19
19
  const nativeToken = this.nativeToken;
20
- if (!this.isActive) {
20
+ const defaultCallback = async () => {
21
21
  const data = {
22
22
  ...this.baseInfo,
23
23
  type: this.type,
@@ -26,11 +26,16 @@ export default class ParaNativeStakingPoolHandler extends BaseParaNativeStakingP
26
26
  description: this.getDescription()
27
27
  }
28
28
  };
29
- callback(data);
29
+ const poolInfo = await this.getPoolInfo();
30
+ !poolInfo && callback(data);
31
+ };
32
+ if (!this.isActive) {
33
+ await defaultCallback();
30
34
  return () => {
31
35
  cancel = true;
32
36
  };
33
37
  }
38
+ await defaultCallback();
34
39
  await chainApi.isReady;
35
40
  const unsub = await chainApi.api.query.parachainStaking.round(async _round => {
36
41
  var _chainApi$api$consts, _chainApi$api$consts$, _chainApi$api$consts$2;
@@ -10,6 +10,7 @@ import { _STAKING_CHAIN_GROUP } from '@subwallet/extension-base/services/earning
10
10
  import { parseIdentity } from '@subwallet/extension-base/services/earning-service/utils';
11
11
  import { EarningStatus, UnstakingStatus } from '@subwallet/extension-base/types';
12
12
  import { balanceFormatter, formatNumber, reformatAddress } from '@subwallet/extension-base/utils';
13
+ import BigN from 'bignumber.js';
13
14
  import { t } from 'i18next';
14
15
  import { BN, BN_ZERO } from '@polkadot/util';
15
16
  import BaseNativeStakingPoolHandler from "./base.js";
@@ -22,7 +23,7 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
22
23
  const substrateApi = this.substrateApi;
23
24
  const chainInfo = this.chainInfo;
24
25
  const nativeToken = this.nativeToken;
25
- if (!this.isActive) {
26
+ const defaultCallback = async () => {
26
27
  const data = {
27
28
  ...this.baseInfo,
28
29
  type: this.type,
@@ -31,11 +32,16 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
31
32
  description: this.getDescription()
32
33
  }
33
34
  };
34
- callback(data);
35
+ const poolInfo = await this.getPoolInfo();
36
+ !poolInfo && callback(data);
37
+ };
38
+ if (!this.isActive) {
39
+ await defaultCallback();
35
40
  return () => {
36
41
  cancel = true;
37
42
  };
38
43
  }
44
+ await defaultCallback();
39
45
  await substrateApi.isReady;
40
46
  const unsub = await ((_substrateApi$api$que = substrateApi.api.query.staking) === null || _substrateApi$api$que === void 0 ? void 0 : _substrateApi$api$que.currentEra(async _currentEra => {
41
47
  var _substrateApi$api$con, _substrateApi$api$con2, _substrateApi$api$que2, _substrateApi$api$que3, _substrateApi$api$que4, _substrateApi$api$que5, _substrateApi$api$que6;
@@ -127,7 +133,10 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
127
133
  let nominationStatus = EarningStatus.NOT_EARNING;
128
134
  const [[identity], _eraStaker] = await Promise.all([parseIdentity(substrateApi, validatorAddress), substrateApi.api.query.staking.erasStakers(currentEra, validatorAddress)]);
129
135
  const eraStaker = _eraStaker.toPrimitive();
130
- const topNominators = eraStaker.others.map(nominator => {
136
+ const sortedNominators = eraStaker.others.sort((a, b) => {
137
+ return new BigN(b.value).minus(a.value).toNumber();
138
+ });
139
+ const topNominators = sortedNominators.map(nominator => {
131
140
  return nominator.who;
132
141
  });
133
142
  if (!topNominators.includes(reformatAddress(address, _getChainSubstrateAddressPrefix(chainInfo)))) {
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
- import { APIItemState, BasicTxErrorType, ExtrinsicType, StakingTxErrorType, StakingType } from '@subwallet/extension-base/background/KoniTypes';
5
+ import { APIItemState, BasicTxErrorType, ChainType, ExtrinsicType, StakingTxErrorType, StakingType } from '@subwallet/extension-base/background/KoniTypes';
6
6
  import { calculateChainStakedReturn, calculateInflation, getExistUnstakeErrorMessage, getMinStakeErrorMessage, parsePoolStashAddress } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
7
7
  import { _EXPECTED_BLOCK_TIME, _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
8
8
  import { _getChainSubstrateAddressPrefix } from '@subwallet/extension-base/services/chain-service/utils';
@@ -46,7 +46,7 @@ export default class NominationPoolHandler extends BasePoolHandler {
46
46
  const substrateApi = this.substrateApi;
47
47
  const chainInfo = this.chainInfo;
48
48
  const nativeToken = this.nativeToken;
49
- if (!this.isActive) {
49
+ const defaultCallback = async () => {
50
50
  const data = {
51
51
  ...this.baseInfo,
52
52
  type: this.type,
@@ -55,11 +55,16 @@ export default class NominationPoolHandler extends BasePoolHandler {
55
55
  description: this.getDescription()
56
56
  }
57
57
  };
58
- callback(data);
58
+ const poolInfo = await this.getPoolInfo();
59
+ !poolInfo && callback(data);
60
+ };
61
+ if (!this.isActive) {
62
+ await defaultCallback();
59
63
  return () => {
60
64
  cancel = true;
61
65
  };
62
66
  }
67
+ await defaultCallback();
63
68
  await substrateApi.isReady;
64
69
  const unsub = await ((_substrateApi$api$que = substrateApi.api.query.staking) === null || _substrateApi$api$que === void 0 ? void 0 : _substrateApi$api$que.currentEra(async _currentEra => {
65
70
  var _substrateApi$api$que2, _substrateApi$api$que3, _substrateApi$api$que4;
@@ -461,7 +466,8 @@ export default class NominationPoolHandler extends BasePoolHandler {
461
466
  extrinsicType: ExtrinsicType.STAKING_JOIN_POOL,
462
467
  extrinsic,
463
468
  txData: joinPoolData,
464
- transferNativeAmount: amount
469
+ transferNativeAmount: amount,
470
+ chainType: ChainType.SUBSTRATE
465
471
  };
466
472
  }
467
473
 
@@ -57,7 +57,6 @@ export default abstract class BaseSpecialStakingPoolHandler extends BasePoolHand
57
57
  handleXcmStep(data: SubmitYieldJoinData, path: OptimalYieldPath, xcmFee: string): Promise<HandleYieldStepData>;
58
58
  abstract handleSubmitStep(data: SubmitYieldJoinData, path: OptimalYieldPath): Promise<HandleYieldStepData>;
59
59
  handleYieldJoin(data: SubmitYieldJoinData, path: OptimalYieldPath, currentStep: number): Promise<HandleYieldStepData>;
60
- validateYieldLeave(amount: string, address: string, fastLeave: boolean, selectedTarget?: string): Promise<TransactionError[]>;
61
60
  handleYieldUnstake(amount: string, address: string, selectedTarget?: string): Promise<[ExtrinsicType, TransactionData]>;
62
61
  handleYieldCancelUnstake(): Promise<TransactionData>;
63
62
  handleYieldClaimReward(address: string, bondReward?: boolean): Promise<TransactionData>;
@@ -3,7 +3,7 @@
3
3
 
4
4
  import { COMMON_CHAIN_SLUGS } from '@subwallet/chain-list';
5
5
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
6
- import { BasicTxErrorType, ExtrinsicType, StakingTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
6
+ import { BasicTxErrorType, ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
7
7
  import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants';
8
8
  import { createXcmExtrinsic } from '@subwallet/extension-base/koni/api/xcm';
9
9
  import { YIELD_POOL_STAT_REFRESH_INTERVAL } from '@subwallet/extension-base/koni/api/yield/helper/utils';
@@ -55,7 +55,7 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
55
55
  if (!poolInfo || !((_poolInfo$statistic = poolInfo.statistic) !== null && _poolInfo$statistic !== void 0 && _poolInfo$statistic.earningThreshold.join)) {
56
56
  return {
57
57
  passed: false,
58
- errorMessage: 'There\'s a trouble fetching data, please check your internet connection and try again'
58
+ errorMessage: 'There is a problem fetching your data. Check your Internet connection or change the network endpoint and try again.'
59
59
  };
60
60
  }
61
61
  if (request.address === ALL_ACCOUNT_KEY) {
@@ -76,14 +76,13 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
76
76
  const bnMinJoinPool = new BN(poolInfo.statistic.earningThreshold.join);
77
77
  const inputTokenInfo = this.state.chainService.getAssetBySlug(this.inputAsset);
78
78
  const altInputTokenInfo = this.state.chainService.getAssetBySlug(this.altInputAsset);
79
- const minJoinDiv = BN_TEN.pow(new BN(inputAssetInfo.decimals || 0));
80
- const parsedMinJoinPool = bnMinJoinPool.div(minJoinDiv);
81
79
  if (bnInputAssetBalance.add(bnAltInputAssetBalance).lt(bnMinJoinPool)) {
82
80
  const originChain = this.state.getChainInfo(inputTokenInfo.originChain);
83
81
  const altChain = this.state.getChainInfo(altInputTokenInfo.originChain);
82
+ const parsedMinJoinPool = formatNumber(bnMinJoinPool.toString(), inputAssetInfo.decimals || 0);
84
83
  return {
85
84
  passed: false,
86
- errorMessage: `You need at least ${parsedMinJoinPool.toString()} ${inputTokenInfo.symbol} (${originChain.name}) or ${altInputTokenInfo.symbol} (${altChain.name}) to start earning`
85
+ errorMessage: `You need at least ${parsedMinJoinPool} ${inputTokenInfo.symbol} (${originChain.name}) or ${altInputTokenInfo.symbol} (${altChain.name}) to start earning`
87
86
  };
88
87
  }
89
88
  if (this.feeAssets.length === 1) {
@@ -113,24 +112,29 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
113
112
 
114
113
  async subscribePoolInfo(callback) {
115
114
  let cancel = false;
115
+ const _callback = data => {
116
+ !cancel && callback(data);
117
+ };
118
+ const defaultCallback = async () => {
119
+ const data = {
120
+ ...this.baseInfo,
121
+ type: this.type,
122
+ metadata: {
123
+ ...this.metadataInfo,
124
+ description: this.getDescription()
125
+ }
126
+ };
127
+ const poolInfo = await this.getPoolInfo();
128
+ !poolInfo && _callback(data);
129
+ };
116
130
  const getStatInterval = () => {
117
131
  if (!this.isActive) {
118
- if (!cancel) {
119
- const rs = {
120
- ...this.baseInfo,
121
- type: this.type,
122
- metadata: {
123
- ...this.metadataInfo,
124
- description: this.getDescription()
125
- }
126
- };
127
- callback(rs);
128
- }
132
+ defaultCallback().catch(console.error);
129
133
  } else {
130
- this.getPoolStat().then(rs => {
131
- if (!cancel) {
132
- callback(rs);
133
- }
134
+ defaultCallback().then(() => {
135
+ return this.getPoolStat();
136
+ }).then(rs => {
137
+ _callback(rs);
134
138
  }).catch(console.error);
135
139
  }
136
140
  };
@@ -263,6 +267,7 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
263
267
  const bnAmount = new BN(params.amount);
264
268
  const altInputTokenSlug = this.altInputAsset || '';
265
269
  const altInputTokenInfo = this.state.getAssetBySlug(altInputTokenSlug);
270
+ const inputTokenInfo = this.state.getAssetBySlug(this.inputAsset);
266
271
  const altInputTokenBalance = await this.state.balanceService.getTokenFreeBalance(params.address, altInputTokenInfo.originChain, altInputTokenSlug);
267
272
  const missingAmount = bnAmount.sub(bnInputTokenBalance); // TODO: what if input token is not LOCAL ??
268
273
  const xcmFee = new BN(path.totalFee[1].amount || '0');
@@ -273,6 +278,26 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
273
278
  processValidation.failedStep = path.steps[1];
274
279
  processValidation.ok = false;
275
280
  processValidation.status = YieldValidationStatus.NOT_ENOUGH_BALANCE;
281
+ const maxBn = bnInputTokenBalance.add(new BN(altInputTokenBalance.value)).sub(xcmFee).sub(altInputTokenMinAmount);
282
+ const maxValue = formatNumber(maxBn.toString(), inputTokenInfo.decimals || 0);
283
+ const altInputTokenInfo = this.state.getAssetBySlug(altInputTokenSlug);
284
+ const symbol = altInputTokenInfo.symbol;
285
+ const altNetwork = this.state.getChainInfo(altInputTokenInfo.originChain);
286
+ const inputNetworkName = this.chainInfo.name;
287
+ const altNetworkName = altNetwork.name;
288
+ const currentValue = formatNumber(bnInputTokenBalance.toString(), inputTokenInfo.decimals || 0);
289
+ const bnMaxXCM = new BN(altInputTokenBalance.value).sub(xcmFee).sub(altInputTokenMinAmount);
290
+ const maxXCMValue = formatNumber(bnMaxXCM.toString(), inputTokenInfo.decimals || 0);
291
+ processValidation.message = t('You can only enter a maximum of {{maxValue}} {{symbol}}, which is {{currentValue}} {{symbol}} ({{inputNetworkName}}) and {{maxXCMValue}} {{symbol}} ({{altNetworkName}}). Lower your amount and try again.', {
292
+ replace: {
293
+ symbol,
294
+ maxValue,
295
+ inputNetworkName,
296
+ altNetworkName,
297
+ currentValue,
298
+ maxXCMValue
299
+ }
300
+ });
276
301
  return [new TransactionError(YieldValidationStatus.NOT_ENOUGH_BALANCE, processValidation.message, processValidation)];
277
302
  }
278
303
  return [];
@@ -292,6 +317,7 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
292
317
  };
293
318
  const feeTokenSlug = path.totalFee[id].slug;
294
319
  const feeTokenInfo = this.state.getAssetBySlug(feeTokenSlug);
320
+ const inputTokenInfo = this.state.getAssetBySlug(this.inputAsset);
295
321
  const defaultFeeTokenSlug = this.feeAssets[0];
296
322
  const bnAmount = new BN(params.amount);
297
323
  if (this.feeAssets.length === 1 && feeTokenSlug === defaultFeeTokenSlug) {
@@ -317,6 +343,16 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
317
343
  processValidation.failedStep = path.steps[id];
318
344
  processValidation.ok = false;
319
345
  processValidation.status = YieldValidationStatus.NOT_ENOUGH_BALANCE;
346
+ const maxString = formatNumber(bnInputTokenBalance.toString(), inputTokenInfo.decimals || 0);
347
+ if (maxString !== '0') {
348
+ processValidation.message = t('Amount must be equal or less than {{number}}', {
349
+ replace: {
350
+ number: maxString
351
+ }
352
+ });
353
+ } else {
354
+ processValidation.message = t('You need balance greater than 0 to continue');
355
+ }
320
356
  return [new TransactionError(YieldValidationStatus.NOT_ENOUGH_BALANCE, processValidation.message, processValidation)];
321
357
  }
322
358
  return [];
@@ -400,7 +436,8 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
400
436
  extrinsicType: ExtrinsicType.TRANSFER_XCM,
401
437
  extrinsic,
402
438
  txData: xcmData,
403
- transferNativeAmount: bnTotalAmount.toString()
439
+ transferNativeAmount: bnTotalAmount.toString(),
440
+ chainType: ChainType.SUBSTRATE
404
441
  };
405
442
  }
406
443
  handleYieldJoin(data, path, currentStep) {
@@ -426,53 +463,6 @@ export default class BaseSpecialStakingPoolHandler extends BasePoolHandler {
426
463
 
427
464
  /* Leave pool action */
428
465
 
429
- async validateYieldLeave(amount, address, fastLeave, selectedTarget) {
430
- const poolInfo = await this.getPoolInfo();
431
- const poolPosition = await this.getPoolPosition(address);
432
- if (!poolInfo || !poolInfo.statistic || !poolPosition) {
433
- return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
434
- }
435
- if (!this.availableMethod.defaultUnstake && !fastLeave) {
436
- return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
437
- }
438
- if (!this.availableMethod.fastUnstake && fastLeave) {
439
- return [new TransactionError(BasicTxErrorType.INTERNAL_ERROR)];
440
- }
441
- const errors = [];
442
- const bnActiveStake = new BN(poolPosition.activeStake);
443
- const bnAmount = new BN(amount);
444
- const bnRemainingStake = bnActiveStake.sub(bnAmount);
445
- const minStake = new BN(poolInfo.statistic.earningThreshold.join || '0');
446
- const minUnstake = new BN((fastLeave ? poolInfo.statistic.earningThreshold.fastUnstake : poolInfo.statistic.earningThreshold.defaultUnstake) || '0');
447
- const maxUnstakeRequest = poolInfo.statistic.maxWithdrawalRequestPerFarmer;
448
- const derivativeTokenInfo = this.state.getAssetBySlug(this.derivativeAssets[0]);
449
- if (bnAmount.lte(BN_ZERO)) {
450
- return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('Amount must be greater than 0'))];
451
- }
452
- if (bnAmount.lt(minUnstake)) {
453
- const minUnstakeStr = formatNumber(minUnstake.toString(), derivativeTokenInfo.decimals || 0);
454
- errors.push(new TransactionError(StakingTxErrorType.NOT_ENOUGH_MIN_UNSTAKE, t('You need to unstake at least {{amount}} {{token}}', {
455
- replace: {
456
- amount: minUnstakeStr,
457
- token: derivativeTokenInfo.symbol
458
- }
459
- })));
460
- }
461
- if (!fastLeave) {
462
- if (!(bnRemainingStake.isZero() || bnRemainingStake.gte(minStake))) {
463
- errors.push(new TransactionError(StakingTxErrorType.INVALID_ACTIVE_STAKE)); // TODO
464
- }
465
-
466
- if (poolPosition.unstakings.length > maxUnstakeRequest) {
467
- errors.push(new TransactionError(StakingTxErrorType.EXCEED_MAX_UNSTAKING, t('You cannot unstake more than {{number}} times', {
468
- replace: {
469
- number: maxUnstakeRequest
470
- }
471
- })));
472
- }
473
- }
474
- return Promise.resolve(errors);
475
- }
476
466
  handleYieldUnstake(amount, address, selectedTarget) {
477
467
  return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED));
478
468
  }
@@ -1,31 +1,79 @@
1
+ /// <reference types="node" />
1
2
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
2
3
  import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
3
4
  import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
5
+ import { PersistDataServiceInterface, ServiceStatus, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
4
6
  import { EarningRewardHistoryItem, EarningRewardItem, EarningRewardJson, HandleYieldStepData, HandleYieldStepParams, OptimalYieldPath, OptimalYieldPathParams, RequestEarlyValidateYield, RequestStakeCancelWithdrawal, RequestStakeClaimReward, RequestYieldLeave, RequestYieldWithdrawal, ResponseEarlyValidateYield, TransactionData, ValidateYieldProcessParams, YieldPoolInfo, YieldPoolTarget, YieldPositionInfo } from '@subwallet/extension-base/types';
7
+ import { PromiseHandler } from '@subwallet/extension-base/utils';
5
8
  import { BehaviorSubject } from 'rxjs';
6
9
  import { BasePoolHandler } from './handlers';
7
- export default class EarningService {
10
+ export default class EarningService implements StoppableServiceInterface, PersistDataServiceInterface {
8
11
  protected readonly state: KoniState;
9
12
  protected handlers: Record<string, BasePoolHandler>;
10
13
  private earningRewardSubject;
11
14
  private earningRewardHistorySubject;
12
15
  private minAmountPercentSubject;
16
+ readonly yieldPoolInfoSubject: BehaviorSubject<Record<string, YieldPoolInfo>>;
17
+ readonly yieldPositionSubject: BehaviorSubject<Record<string, YieldPositionInfo>>;
18
+ readonly yieldPositionListSubject: BehaviorSubject<YieldPositionInfo[]>;
19
+ private dbService;
20
+ private eventService;
13
21
  constructor(state: KoniState);
14
22
  private initHandlers;
23
+ startPromiseHandler: PromiseHandler<void>;
24
+ stopPromiseHandler: PromiseHandler<void>;
25
+ status: ServiceStatus;
26
+ init(): Promise<void>;
27
+ handleActions(): void;
28
+ loadData(): Promise<void>;
29
+ persistData(): Promise<void>;
30
+ start(): Promise<void>;
31
+ stop(): Promise<void>;
32
+ waitForStarted(): Promise<void>;
33
+ waitForStopped(): Promise<void>;
15
34
  getPoolHandler(slug: string): BasePoolHandler | undefined;
16
35
  isPoolSupportAlternativeFee(slug: string): boolean;
17
36
  subscribeMinAmountPercent(): BehaviorSubject<Record<string, number>>;
18
37
  getMinAmountPercent(): Record<string, number>;
38
+ getYieldPool(slug: string): Promise<YieldPoolInfo | undefined>;
19
39
  subscribePoolsInfo(callback: (rs: YieldPoolInfo) => void): Promise<VoidFunction>;
40
+ private getYieldPoolInfoFromDBAndOnline;
41
+ subscribeYieldPoolInfo(): BehaviorSubject<Record<string, YieldPoolInfo>>;
42
+ getYieldPoolInfo(): Promise<YieldPoolInfo[]>;
43
+ private yieldPoolPersistQueue;
44
+ updateYieldPoolInfo(data: YieldPoolInfo): void;
45
+ private yieldPoolsInfoUnsub;
46
+ runSubscribePoolsInfo(): Promise<void>;
47
+ runUnsubscribePoolsInfo(): void;
48
+ getYieldPosition(address: string, slug: string): Promise<YieldPositionInfo | undefined>;
20
49
  subscribePoolPositions(addresses: string[], callback: (rs: YieldPositionInfo) => void): Promise<VoidFunction>;
50
+ removeYieldPositions(chains?: string[], addresses?: string[]): Promise<void>;
51
+ private getYieldPositionFromDB;
52
+ subscribeYieldPosition(): BehaviorSubject<YieldPositionInfo[]>;
53
+ getYieldPositionInfo(): Promise<YieldPositionInfo[]>;
54
+ yieldPositionPersistQueue: YieldPositionInfo[];
55
+ resetYieldPositionQueue(): void;
56
+ resetYieldPosition(): void;
57
+ private _getYieldPositionKey;
58
+ updateYieldPosition(data: YieldPositionInfo): void;
59
+ reloadEarning(reset?: boolean): Promise<void>;
60
+ private yieldPositionUnsub;
61
+ runSubscribePoolsPosition(): Promise<void>;
62
+ runUnsubscribePoolsPosition(): void;
21
63
  updateEarningReward(stakingRewardData: EarningRewardItem): void;
22
64
  getPoolReward(addresses: string[], callback: (result: EarningRewardItem) => void): Promise<VoidFunction>;
23
65
  subscribeEarningReward(): BehaviorSubject<EarningRewardJson>;
24
66
  getEarningRewards(): EarningRewardJson;
67
+ earningsRewardInterval: NodeJS.Timer | undefined;
68
+ runSubscribeStakingRewardInterval(): void;
69
+ runUnsubscribeStakingRewardInterval(): void;
25
70
  fetchPoolRewardHistory(addresses: string[], callback: (result: EarningRewardHistoryItem) => void): Promise<VoidFunction>;
26
71
  updateEarningRewardHistory(earningRewardHistory: EarningRewardHistoryItem): void;
27
72
  subscribeEarningRewardHistory(): BehaviorSubject<Record<string, EarningRewardHistoryItem>>;
28
73
  getEarningRewardHistory(): Record<string, EarningRewardHistoryItem>;
74
+ earningsRewardHistoryInterval: NodeJS.Timer | undefined;
75
+ runSubscribeEarningRewardHistoryInterval(): void;
76
+ runUnsubscribeEarningRewardHistoryInterval(): void;
29
77
  /**
30
78
  * @async
31
79
  * @function getPoolTargets