@subwallet/extension-base 1.0.1 → 1.0.2-1b

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 (220) hide show
  1. package/background/KoniTypes.d.ts +25 -36
  2. package/background/KoniTypes.js +12 -7
  3. package/background/errors/TransactionError.js +21 -1
  4. package/cjs/background/KoniTypes.js +14 -8
  5. package/cjs/background/errors/TransactionError.js +20 -0
  6. package/cjs/constants/index.js +13 -28
  7. package/cjs/koni/api/dotsama/balance.js +60 -224
  8. package/cjs/koni/api/dotsama/transfer.js +30 -29
  9. package/cjs/koni/api/nft/acala_nft/index.js +4 -1
  10. package/cjs/koni/api/nft/bit.country/index.js +4 -1
  11. package/cjs/koni/api/nft/evm_nft/index.js +7 -3
  12. package/cjs/koni/api/nft/index.js +3 -6
  13. package/cjs/koni/api/nft/karura_nft/index.js +4 -1
  14. package/cjs/koni/api/nft/rmrk_nft/index.js +8 -1
  15. package/cjs/koni/api/nft/statemine_nft/index.js +4 -1
  16. package/cjs/koni/api/nft/unique_nft/index.js +6 -1
  17. package/cjs/koni/api/nft/wasm_nft/index.js +169 -111
  18. package/cjs/koni/api/nft/wasm_nft/utils.js +11 -7
  19. package/cjs/koni/api/staking/bonding/amplitude.js +18 -10
  20. package/cjs/koni/api/staking/bonding/astar.js +37 -238
  21. package/cjs/koni/api/staking/bonding/index.js +26 -14
  22. package/cjs/koni/api/staking/bonding/paraChain.js +100 -11
  23. package/cjs/koni/api/staking/bonding/relayChain.js +174 -16
  24. package/cjs/koni/api/staking/bonding/utils.js +55 -10
  25. package/cjs/koni/api/tokens/wasm/index.js +5 -4
  26. package/cjs/koni/api/tokens/wasm/utils.js +63 -0
  27. package/cjs/koni/api/xcm/index.js +0 -111
  28. package/cjs/koni/api/xcm/polkadotXcm.js +2 -2
  29. package/cjs/koni/api/xcm/utils.js +18 -13
  30. package/cjs/koni/api/xcm/xTokens.js +3 -5
  31. package/cjs/koni/api/xcm/xcmPallet.js +9 -6
  32. package/cjs/koni/background/cron.js +179 -77
  33. package/cjs/koni/background/handlers/Extension.js +231 -195
  34. package/cjs/koni/background/handlers/State.js +147 -111
  35. package/cjs/koni/background/handlers/Tabs.js +48 -39
  36. package/cjs/koni/background/subscription.js +64 -56
  37. package/cjs/packageInfo.js +1 -1
  38. package/cjs/page/index.js +5 -0
  39. package/cjs/services/chain-service/constants.js +1 -11
  40. package/cjs/services/chain-service/handler/SubstrateChainHandler.js +13 -8
  41. package/cjs/services/chain-service/handler/light-client/index.js +2 -0
  42. package/cjs/services/chain-service/index.js +39 -6
  43. package/cjs/services/chain-service/utils.js +4 -0
  44. package/cjs/services/event-service/index.js +75 -0
  45. package/cjs/services/event-service/types.js +11 -0
  46. package/cjs/services/history-service/index.js +46 -21
  47. package/cjs/services/history-service/subsquid-multi-chain-history.js +19 -11
  48. package/cjs/services/keyring-service/index.js +101 -0
  49. package/cjs/services/migration-service/index.js +13 -10
  50. package/cjs/{koni/migration/scripts/RemoveWrongCrowdloan.js → services/migration-service/scripts/AutoEnableChainsTokens.js} +11 -6
  51. package/cjs/services/migration-service/scripts/MigrateNetworkSettings.js +39 -19
  52. package/cjs/services/migration-service/scripts/MigrateSettings.js +31 -0
  53. package/cjs/services/migration-service/scripts/MigrateTransactionHistory.js +72 -0
  54. package/cjs/services/migration-service/scripts/index.js +13 -4
  55. package/cjs/services/price-service/coingecko.js +15 -3
  56. package/cjs/services/price-service/index.js +15 -18
  57. package/cjs/services/request-service/constants.js +8 -2
  58. package/cjs/services/request-service/handler/AuthRequestHandler.js +43 -12
  59. package/cjs/services/request-service/index.js +3 -0
  60. package/cjs/services/storage-service/DatabaseService.js +53 -34
  61. package/cjs/services/storage-service/databases/index.js +1 -1
  62. package/cjs/services/storage-service/db-stores/BaseStoreWithAddressAndChain.js +2 -8
  63. package/cjs/services/storage-service/db-stores/Nft.js +8 -18
  64. package/cjs/services/storage-service/db-stores/Transaction.js +10 -7
  65. package/cjs/services/subscan-service/index.js +107 -0
  66. package/cjs/services/subscan-service/subscan-chain-map.js +74 -0
  67. package/cjs/services/subscan-service/types.js +1 -0
  68. package/cjs/services/transaction-service/event-parser/index.js +20 -48
  69. package/cjs/services/transaction-service/index.js +66 -22
  70. package/cjs/services/transaction-service/utils.js +4 -6
  71. package/cjs/utils/address.js +9 -1
  72. package/cjs/utils/index.js +30 -26
  73. package/constants/index.d.ts +8 -13
  74. package/constants/index.js +8 -13
  75. package/koni/api/dotsama/balance.d.ts +0 -1
  76. package/koni/api/dotsama/balance.js +33 -197
  77. package/koni/api/dotsama/transfer.js +5 -4
  78. package/koni/api/nft/acala_nft/index.js +3 -1
  79. package/koni/api/nft/bit.country/index.js +3 -1
  80. package/koni/api/nft/evm_nft/index.js +6 -3
  81. package/koni/api/nft/index.d.ts +1 -2
  82. package/koni/api/nft/index.js +3 -6
  83. package/koni/api/nft/karura_nft/index.js +3 -1
  84. package/koni/api/nft/nft.d.ts +1 -0
  85. package/koni/api/nft/rmrk_nft/index.js +8 -1
  86. package/koni/api/nft/statemine_nft/index.js +3 -1
  87. package/koni/api/nft/unique_nft/index.js +5 -1
  88. package/koni/api/nft/wasm_nft/index.d.ts +0 -2
  89. package/koni/api/nft/wasm_nft/index.js +167 -109
  90. package/koni/api/nft/wasm_nft/utils.d.ts +7 -5
  91. package/koni/api/nft/wasm_nft/utils.js +7 -5
  92. package/koni/api/staking/bonding/amplitude.d.ts +1 -2
  93. package/koni/api/staking/bonding/amplitude.js +22 -13
  94. package/koni/api/staking/bonding/astar.d.ts +2 -11
  95. package/koni/api/staking/bonding/astar.js +39 -231
  96. package/koni/api/staking/bonding/index.d.ts +5 -2
  97. package/koni/api/staking/bonding/index.js +27 -17
  98. package/koni/api/staking/bonding/paraChain.d.ts +4 -1
  99. package/koni/api/staking/bonding/paraChain.js +101 -14
  100. package/koni/api/staking/bonding/relayChain.d.ts +6 -2
  101. package/koni/api/staking/bonding/relayChain.js +172 -17
  102. package/koni/api/staking/bonding/utils.d.ts +15 -2
  103. package/koni/api/staking/bonding/utils.js +53 -11
  104. package/koni/api/tokens/wasm/index.js +5 -4
  105. package/koni/api/tokens/wasm/utils.d.ts +6 -0
  106. package/koni/api/tokens/wasm/utils.js +54 -0
  107. package/koni/api/xcm/index.js +1 -112
  108. package/koni/api/xcm/polkadotXcm.js +3 -3
  109. package/koni/api/xcm/utils.d.ts +5 -6
  110. package/koni/api/xcm/utils.js +15 -10
  111. package/koni/api/xcm/xTokens.js +5 -7
  112. package/koni/api/xcm/xcmPallet.js +10 -9
  113. package/koni/background/cron.d.ts +6 -1
  114. package/koni/background/cron.js +179 -76
  115. package/koni/background/handlers/Extension.d.ts +2 -2
  116. package/koni/background/handlers/Extension.js +161 -125
  117. package/koni/background/handlers/State.d.ts +21 -20
  118. package/koni/background/handlers/State.js +144 -111
  119. package/koni/background/handlers/Tabs.js +30 -20
  120. package/koni/background/subscription.d.ts +1 -1
  121. package/koni/background/subscription.js +64 -58
  122. package/package.json +63 -18
  123. package/packageInfo.js +1 -1
  124. package/page/index.d.ts +2 -0
  125. package/page/index.js +4 -0
  126. package/services/chain-service/constants.d.ts +0 -1
  127. package/services/chain-service/constants.js +0 -9
  128. package/services/chain-service/handler/SubstrateChainHandler.js +14 -9
  129. package/services/chain-service/handler/light-client/index.d.ts +17 -1
  130. package/services/chain-service/handler/light-client/index.js +1 -1
  131. package/services/chain-service/helper/psp22_abi.json +1041 -881
  132. package/services/chain-service/helper/psp34_abi.json +2963 -1807
  133. package/services/chain-service/index.d.ts +6 -4
  134. package/services/chain-service/index.js +40 -9
  135. package/services/chain-service/utils.d.ts +1 -0
  136. package/services/chain-service/utils.js +3 -0
  137. package/services/event-service/index.d.ts +22 -0
  138. package/services/event-service/index.js +63 -0
  139. package/services/event-service/types.d.ts +28 -0
  140. package/services/event-service/types.js +4 -0
  141. package/services/history-service/index.d.ts +5 -3
  142. package/services/history-service/index.js +46 -21
  143. package/services/history-service/subsquid-multi-chain-history.js +22 -13
  144. package/services/keyring-service/index.d.ts +19 -0
  145. package/services/keyring-service/index.js +93 -0
  146. package/services/migration-service/index.js +11 -9
  147. package/services/migration-service/scripts/AutoEnableChainsTokens.d.ts +4 -0
  148. package/services/migration-service/scripts/AutoEnableChainsTokens.js +13 -0
  149. package/services/migration-service/scripts/MigrateNetworkSettings.js +37 -18
  150. package/services/migration-service/scripts/MigrateSettings.d.ts +4 -0
  151. package/services/migration-service/scripts/MigrateSettings.js +23 -0
  152. package/services/migration-service/scripts/MigrateTransactionHistory.d.ts +4 -0
  153. package/services/migration-service/scripts/MigrateTransactionHistory.js +64 -0
  154. package/services/migration-service/scripts/index.d.ts +1 -0
  155. package/services/migration-service/scripts/index.js +10 -3
  156. package/services/price-service/coingecko.js +15 -3
  157. package/services/price-service/index.d.ts +5 -3
  158. package/services/price-service/index.js +15 -18
  159. package/services/request-service/constants.d.ts +1 -0
  160. package/services/request-service/constants.js +6 -1
  161. package/services/request-service/handler/AuthRequestHandler.d.ts +8 -1
  162. package/services/request-service/handler/AuthRequestHandler.js +44 -13
  163. package/services/request-service/index.d.ts +7 -1
  164. package/services/request-service/index.js +3 -0
  165. package/services/storage-service/DatabaseService.d.ts +1 -0
  166. package/services/storage-service/DatabaseService.js +53 -34
  167. package/services/storage-service/databases/index.js +1 -1
  168. package/services/storage-service/db-stores/BaseStoreWithAddressAndChain.d.ts +1 -1
  169. package/services/storage-service/db-stores/BaseStoreWithAddressAndChain.js +2 -8
  170. package/services/storage-service/db-stores/Nft.d.ts +3 -3
  171. package/services/storage-service/db-stores/Nft.js +8 -17
  172. package/services/storage-service/db-stores/Transaction.js +10 -7
  173. package/services/subscan-service/index.d.ts +20 -0
  174. package/services/subscan-service/index.js +99 -0
  175. package/services/subscan-service/subscan-chain-map.d.ts +5 -0
  176. package/services/subscan-service/subscan-chain-map.js +63 -0
  177. package/services/subscan-service/types.d.ts +27 -0
  178. package/services/subscan-service/types.js +1 -0
  179. package/services/transaction-service/event-parser/index.d.ts +2 -2
  180. package/services/transaction-service/event-parser/index.js +21 -49
  181. package/services/transaction-service/index.d.ts +4 -2
  182. package/services/transaction-service/index.js +66 -22
  183. package/services/transaction-service/utils.js +5 -6
  184. package/utils/address.d.ts +1 -0
  185. package/utils/address.js +9 -2
  186. package/utils/index.d.ts +2 -1
  187. package/utils/index.js +26 -23
  188. package/cjs/background/errors/EvmRpcError.js +0 -21
  189. package/cjs/background/errors/SubWalletProviderError.js +0 -17
  190. package/cjs/constants/ethereum.js +0 -19
  191. package/cjs/errors/SubWalletProviderError.js +0 -17
  192. package/cjs/koni/api/xcm/astar.js +0 -160
  193. package/cjs/koni/api/xcm/moonbeamXcm.js +0 -80
  194. package/cjs/koni/api/xcm/statemintXcm.js +0 -197
  195. package/cjs/koni/api/xcm/substrateXcm.js +0 -213
  196. package/cjs/koni/migration/Base.js +0 -20
  197. package/cjs/koni/migration/index.js +0 -45
  198. package/cjs/koni/migration/scripts/ChangeRouteToHome.js +0 -22
  199. package/cjs/koni/migration/scripts/ClearOldStorage.js +0 -24
  200. package/cjs/koni/migration/scripts/RemoveWrongTransactionHistoriesFromStore.js +0 -36
  201. package/cjs/koni/migration/scripts/ResetTransactionHistoryEventIdx.js +0 -21
  202. package/cjs/koni/migration/scripts/index.js +0 -22
  203. package/cjs/koni/page/index.js +0 -16
  204. package/cjs/services/asset-service/index.js +0 -91
  205. package/cjs/services/storage-service/db-stores/ExtraDelegationInfo.js +0 -17
  206. package/cjs/stores/Balance.js +0 -18
  207. package/cjs/stores/Crowdloan.js +0 -18
  208. package/cjs/stores/CustomEvmToken.js +0 -18
  209. package/cjs/stores/NetworkMap.js +0 -18
  210. package/cjs/stores/Nft.js +0 -18
  211. package/cjs/stores/NftCollection.js +0 -18
  212. package/cjs/stores/Price.js +0 -18
  213. package/cjs/stores/Staking.js +0 -18
  214. package/cjs/stores/StakingReward.js +0 -18
  215. package/cjs/utils/eth/parseTransactionData.js +0 -284
  216. package/koni/page/index.d.ts +0 -2
  217. package/koni/page/index.js +0 -9
  218. /package/cjs/{koni/page → page}/SubWalleEvmProvider.js +0 -0
  219. /package/{koni/page → page}/SubWalleEvmProvider.d.ts +0 -0
  220. /package/{koni/page → page}/SubWalleEvmProvider.js +0 -0
@@ -1,13 +1,86 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- import { StakingType, UnstakingStatus } from '@subwallet/extension-base/background/KoniTypes';
5
- import { getBondedValidators, getParaCurrentInflation, isUnstakeAll, parseIdentity } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
4
+ import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
+ import { BasicTxErrorType, StakingStatus, StakingTxErrorType, StakingType, UnstakingStatus } from '@subwallet/extension-base/background/KoniTypes';
6
+ import { getBondedValidators, getParaCurrentInflation, getStakingStatusByNominations, isUnstakeAll, parseIdentity } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
6
7
  import { _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
7
8
  import { _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils';
8
- import { parseRawNumber, reformatAddress } from '@subwallet/extension-base/utils';
9
+ import { isSameAddress, parseRawNumber, reformatAddress } from '@subwallet/extension-base/utils';
9
10
  import { BN, BN_ZERO } from '@polkadot/util';
10
11
  import { isEthereumAddress } from '@polkadot/util-crypto';
12
+ export function validateParaChainUnbondingCondition(amount, nominatorMetadata, chainStakingMetadata, selectedCollator) {
13
+ const errors = [];
14
+ let targetNomination;
15
+ for (const nomination of nominatorMetadata.nominations) {
16
+ if (isSameAddress(nomination.validatorAddress, selectedCollator)) {
17
+ targetNomination = nomination;
18
+ break;
19
+ }
20
+ }
21
+ if (!targetNomination) {
22
+ errors.push(new TransactionError(BasicTxErrorType.INTERNAL_ERROR));
23
+ return errors;
24
+ }
25
+ const bnActiveStake = new BN(targetNomination.activeStake);
26
+ const bnRemainingStake = bnActiveStake.sub(new BN(amount));
27
+ const bnChainMinStake = new BN(chainStakingMetadata.minStake || '0');
28
+ const bnCollatorMinStake = new BN(targetNomination.validatorMinStake || '0');
29
+ const bnMinStake = bnCollatorMinStake > bnChainMinStake ? bnCollatorMinStake : bnChainMinStake;
30
+ if (targetNomination.hasUnstaking) {
31
+ errors.push(new TransactionError(StakingTxErrorType.EXIST_UNSTAKING_REQUEST));
32
+ }
33
+ if (!(bnRemainingStake.isZero() || bnRemainingStake.gte(bnMinStake))) {
34
+ errors.push(new TransactionError(StakingTxErrorType.INVALID_ACTIVE_STAKE));
35
+ }
36
+ return errors;
37
+ }
38
+ export function validateParaChainBondingCondition(chainInfo, amount, selectedCollators, address, chainStakingMetadata, nominatorMetadata) {
39
+ const errors = [];
40
+ const selectedCollator = selectedCollators[0];
41
+ let bnTotalStake = new BN(amount);
42
+ const bnChainMinStake = new BN(chainStakingMetadata.minStake || '0');
43
+ const bnCollatorMinStake = new BN(selectedCollator.minBond || '0');
44
+ const bnMinStake = bnCollatorMinStake > bnChainMinStake ? bnCollatorMinStake : bnChainMinStake;
45
+ if (!nominatorMetadata) {
46
+ if (!bnTotalStake.gte(bnMinStake)) {
47
+ errors.push(new TransactionError(StakingTxErrorType.NOT_ENOUGH_MIN_STAKE));
48
+ }
49
+ return errors;
50
+ }
51
+ const {
52
+ bondedValidators
53
+ } = getBondedValidators(nominatorMetadata.nominations);
54
+ const parsedSelectedCollatorAddress = reformatAddress(selectedCollator.address, 0);
55
+ if (!bondedValidators.includes(parsedSelectedCollatorAddress)) {
56
+ // new delegation
57
+ if (!bnTotalStake.gte(bnMinStake)) {
58
+ errors.push(new TransactionError(StakingTxErrorType.NOT_ENOUGH_MIN_STAKE));
59
+ }
60
+ const delegationCount = nominatorMetadata.nominations.length + 1;
61
+ if (delegationCount > chainStakingMetadata.maxValidatorPerNominator) {
62
+ errors.push(new TransactionError(StakingTxErrorType.EXCEED_MAX_NOMINATIONS));
63
+ }
64
+ } else {
65
+ let currentDelegationAmount = '0';
66
+ let hasUnstaking = false;
67
+ for (const delegation of nominatorMetadata.nominations) {
68
+ if (reformatAddress(delegation.validatorAddress, 0) === parsedSelectedCollatorAddress) {
69
+ currentDelegationAmount = delegation.activeStake;
70
+ hasUnstaking = !!delegation.hasUnstaking && delegation.hasUnstaking;
71
+ break;
72
+ }
73
+ }
74
+ bnTotalStake = bnTotalStake.add(new BN(currentDelegationAmount));
75
+ if (!bnTotalStake.gte(bnMinStake)) {
76
+ errors.push(new TransactionError(StakingTxErrorType.NOT_ENOUGH_MIN_STAKE));
77
+ }
78
+ if (hasUnstaking) {
79
+ errors.push(new TransactionError(StakingTxErrorType.EXIST_UNSTAKING_REQUEST));
80
+ }
81
+ }
82
+ return errors;
83
+ }
11
84
  export async function getParaChainStakingMetadata(chain, substrateApi) {
12
85
  const chainApi = await substrateApi.isReady;
13
86
  const _round = (await chainApi.api.query.parachainStaking.round()).toHuman();
@@ -61,13 +134,16 @@ export async function getParaChainNominatorMetadata(chainInfo, address, substrat
61
134
  }
62
135
  let bnTotalActiveStake = BN_ZERO;
63
136
  await Promise.all(delegatorState.delegations.map(async delegation => {
64
- const [_delegationScheduledRequests, _identity, _roundInfo] = await Promise.all([chainApi.api.query.parachainStaking.delegationScheduledRequests(delegation.owner), chainApi.api.query.identity.identityOf(delegation.owner), chainApi.api.query.parachainStaking.round()]);
137
+ const [_delegationScheduledRequests, _identity, _roundInfo, _collatorInfo] = await Promise.all([chainApi.api.query.parachainStaking.delegationScheduledRequests(delegation.owner), chainApi.api.query.identity.identityOf(delegation.owner), chainApi.api.query.parachainStaking.round(), chainApi.api.query.parachainStaking.candidateInfo(delegation.owner)]);
138
+ const rawCollatorInfo = _collatorInfo.toHuman();
139
+ const minDelegation = (rawCollatorInfo === null || rawCollatorInfo === void 0 ? void 0 : rawCollatorInfo.lowestTopDelegationAmount).replaceAll(',', '');
65
140
  const identityInfo = _identity.toHuman();
66
141
  const roundInfo = _roundInfo.toPrimitive();
67
142
  const delegationScheduledRequests = _delegationScheduledRequests.toPrimitive();
68
143
  const currentRound = roundInfo.current;
69
144
  const identity = parseIdentity(identityInfo);
70
145
  let hasUnstaking = false;
146
+ let delegationStatus = StakingStatus.NOT_EARNING;
71
147
 
72
148
  // parse unstaking info
73
149
  if (delegationScheduledRequests) {
@@ -94,9 +170,13 @@ export async function getParaChainNominatorMetadata(chainInfo, address, substrat
94
170
  const bnStake = new BN(delegation.amount);
95
171
  const bnUnstakeBalance = unstakingMap[delegation.owner] ? new BN(unstakingMap[delegation.owner].claimable) : BN_ZERO;
96
172
  const bnActiveStake = bnStake.sub(bnUnstakeBalance);
173
+ if (bnActiveStake.gt(BN_ZERO) && bnActiveStake.gte(new BN(minDelegation))) {
174
+ delegationStatus = StakingStatus.EARNING_REWARD;
175
+ }
97
176
  bnTotalActiveStake = bnTotalActiveStake.add(bnActiveStake);
98
177
  nominationList.push({
99
178
  chain,
179
+ status: delegationStatus,
100
180
  validatorAddress: delegation.owner,
101
181
  validatorIdentity: identity,
102
182
  activeStake: bnActiveStake.toString(),
@@ -108,9 +188,11 @@ export async function getParaChainNominatorMetadata(chainInfo, address, substrat
108
188
  const collatorInfo = _collatorInfo.toPrimitive();
109
189
  nomination.validatorMinStake = collatorInfo.lowestTopDelegationAmount.toString();
110
190
  }));
191
+ const stakingStatus = getStakingStatusByNominations(bnTotalActiveStake, nominationList);
111
192
  return {
112
193
  chain,
113
194
  type: StakingType.NOMINATED,
195
+ status: stakingStatus,
114
196
  address: address,
115
197
  activeStake: bnTotalActiveStake.toString(),
116
198
  nominations: nominationList,
@@ -119,15 +201,16 @@ export async function getParaChainNominatorMetadata(chainInfo, address, substrat
119
201
  }
120
202
  export async function getParachainCollatorsInfo(chain, substrateApi) {
121
203
  const apiProps = await substrateApi.isReady;
122
- const allValidators = [];
204
+ const allCollators = [];
123
205
  const [_allCollators, _collatorCommission] = await Promise.all([apiProps.api.query.parachainStaking.candidateInfo.entries(), apiProps.api.query.parachainStaking.collatorCommission()]);
124
206
  const maxDelegationPerCollator = apiProps.api.consts.parachainStaking.maxTopDelegationsPerCandidate.toString();
125
207
  const rawCollatorCommission = _collatorCommission.toHuman();
126
208
  const collatorCommission = parseFloat(rawCollatorCommission.split('%')[0]);
127
209
  for (const collator of _allCollators) {
128
- const collatorAddress = collator[0].toPrimitive();
210
+ const _collatorAddress = collator[0].toHuman();
211
+ const collatorAddress = _collatorAddress[0];
129
212
  const collatorInfo = collator[1].toPrimitive();
130
- allValidators.push({
213
+ allCollators.push({
131
214
  commission: 0,
132
215
  expectedReturn: 0,
133
216
  address: collatorAddress,
@@ -143,9 +226,9 @@ export async function getParachainCollatorsInfo(chain, substrateApi) {
143
226
  });
144
227
  }
145
228
  const extraInfoMap = {};
146
- await Promise.all(allValidators.map(async validator => {
229
+ await Promise.all(allCollators.map(async collator => {
147
230
  var _apiProps$api$query, _apiProps$api$query$i;
148
- const [_info, _identity] = await Promise.all([apiProps.api.query.parachainStaking.candidateInfo(validator.address), (_apiProps$api$query = apiProps.api.query) === null || _apiProps$api$query === void 0 ? void 0 : (_apiProps$api$query$i = _apiProps$api$query.identity) === null || _apiProps$api$query$i === void 0 ? void 0 : _apiProps$api$query$i.identityOf(validator.address) // some chains might not have identity pallet
231
+ const [_info, _identity] = await Promise.all([apiProps.api.query.parachainStaking.candidateInfo(collator.address), (_apiProps$api$query = apiProps.api.query) === null || _apiProps$api$query === void 0 ? void 0 : (_apiProps$api$query$i = _apiProps$api$query.identity) === null || _apiProps$api$query$i === void 0 ? void 0 : _apiProps$api$query$i.identityOf(collator.address) // some chains might not have identity pallet
149
232
  ]);
150
233
  const rawInfo = _info.toHuman();
151
234
  const rawIdentity = _identity ? _identity.toHuman() : null;
@@ -161,7 +244,7 @@ export async function getParachainCollatorsInfo(chain, substrateApi) {
161
244
  isReasonable = rawIdentity.judgements.length > 0;
162
245
  identity = parseIdentity(rawIdentity);
163
246
  }
164
- extraInfoMap[validator.address] = {
247
+ extraInfoMap[collator.address] = {
165
248
  identity,
166
249
  isVerified: isReasonable,
167
250
  bond: bond.toString(),
@@ -170,7 +253,7 @@ export async function getParachainCollatorsInfo(chain, substrateApi) {
170
253
  active
171
254
  };
172
255
  }));
173
- for (const validator of allValidators) {
256
+ for (const validator of allCollators) {
174
257
  validator.minBond = extraInfoMap[validator.address].minDelegation.toString();
175
258
  validator.ownStake = extraInfoMap[validator.address].bond.toString();
176
259
  validator.blocked = !extraInfoMap[validator.address].active;
@@ -181,16 +264,20 @@ export async function getParachainCollatorsInfo(chain, substrateApi) {
181
264
  validator.nominatorCount = extraInfoMap[validator.address].delegationCount;
182
265
  validator.commission = collatorCommission;
183
266
  }
184
- return allValidators;
267
+ return allCollators;
185
268
  }
186
- export async function getParaBondingExtrinsic(nominatorMetadata, chainInfo, substrateApi, amount, selectedCollatorInfo) {
269
+ export async function getParaBondingExtrinsic(chainInfo, substrateApi, amount, selectedCollatorInfo, nominatorMetadata) {
187
270
  const apiPromise = await substrateApi.isReady;
188
271
  const binaryAmount = new BN(amount);
272
+ if (!nominatorMetadata) {
273
+ return apiPromise.api.tx.parachainStaking.delegate(selectedCollatorInfo.address, binaryAmount, new BN(selectedCollatorInfo.nominatorCount), 0);
274
+ }
189
275
  const {
190
276
  bondedValidators,
191
277
  nominationCount
192
278
  } = getBondedValidators(nominatorMetadata.nominations);
193
- if (!bondedValidators.includes(reformatAddress(selectedCollatorInfo.address, 0))) {
279
+ const parsedSelectedCollatorAddress = reformatAddress(selectedCollatorInfo.address, 0);
280
+ if (!bondedValidators.includes(parsedSelectedCollatorAddress)) {
194
281
  return apiPromise.api.tx.parachainStaking.delegate(selectedCollatorInfo.address, binaryAmount, new BN(selectedCollatorInfo.nominatorCount), nominationCount);
195
282
  } else {
196
283
  return apiPromise.api.tx.parachainStaking.delegatorBondMore(selectedCollatorInfo.address, binaryAmount);
@@ -1,4 +1,5 @@
1
1
  import { _ChainInfo } from '@subwallet/chain-list/types';
2
+ import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
2
3
  import { ChainStakingMetadata, NominationPoolInfo, NominatorMetadata, UnstakingInfo, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes';
3
4
  import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
4
5
  export interface PalletStakingNominations {
@@ -17,12 +18,15 @@ export interface PalletStakingStakingLedger {
17
18
  unlocking: UnlockingChunk[];
18
19
  claimedRewards: number[];
19
20
  }
20
- export declare function getRelayChainStakingMetadata(chain: string, substrateApi: _SubstrateApi): Promise<ChainStakingMetadata>;
21
+ export declare function validateRelayUnbondingCondition(amount: string, chainStakingMetadata: ChainStakingMetadata, nominatorMetadata: NominatorMetadata): TransactionError[];
22
+ export declare function validatePoolBondingCondition(chainInfo: _ChainInfo, amount: string, selectedPool: NominationPoolInfo, address: string, chainStakingMetadata: ChainStakingMetadata, nominatorMetadata?: NominatorMetadata): TransactionError[];
23
+ export declare function validateRelayBondingCondition(chainInfo: _ChainInfo, amount: string, selectedValidators: ValidatorInfo[], address: string, chainStakingMetadata: ChainStakingMetadata, nominatorMetadata?: NominatorMetadata): TransactionError[];
24
+ export declare function getRelayChainStakingMetadata(chainInfo: _ChainInfo, substrateApi: _SubstrateApi): Promise<ChainStakingMetadata>;
21
25
  export declare function getRelayChainNominatorMetadata(chainInfo: _ChainInfo, address: string, substrateApi: _SubstrateApi): Promise<NominatorMetadata | undefined>;
22
26
  export declare function getRelayChainPoolMemberMetadata(chainInfo: _ChainInfo, address: string, substrateApi: _SubstrateApi): Promise<NominatorMetadata | undefined>;
23
27
  export declare function getRelayValidatorsInfo(chain: string, substrateApi: _SubstrateApi, decimals: number, chainStakingMetadata: ChainStakingMetadata): Promise<ValidatorInfo[]>;
24
28
  export declare function getRelayPoolsInfo(chain: string, substrateApi: _SubstrateApi): Promise<NominationPoolInfo[]>;
25
- export declare function getRelayBondingExtrinsic(substrateApi: _SubstrateApi, amount: string, targetValidators: ValidatorInfo[], nominatorMetadata: NominatorMetadata, chainInfo: _ChainInfo, bondDest?: string): Promise<import("@polkadot/api-base/types").SubmittableExtrinsic<"promise", import("@polkadot/types/types").ISubmittableResult>>;
29
+ export declare function getRelayBondingExtrinsic(substrateApi: _SubstrateApi, amount: string, targetValidators: ValidatorInfo[], chainInfo: _ChainInfo, address: string, nominatorMetadata?: NominatorMetadata, bondDest?: string): Promise<import("@polkadot/api-base/types").SubmittableExtrinsic<"promise", import("@polkadot/types/types").ISubmittableResult>>;
26
30
  export declare function getRelayUnbondingExtrinsic(substrateApi: _SubstrateApi, amount: string, nominatorMetadata: NominatorMetadata): Promise<import("@polkadot/api-base/types").SubmittableExtrinsic<"promise", import("@polkadot/types/types").ISubmittableResult>>;
27
31
  export declare function getRelayWithdrawalExtrinsic(substrateApi: _SubstrateApi, address: string): Promise<import("@polkadot/api-base/types").SubmittableExtrinsic<"promise", import("@polkadot/types/types").ISubmittableResult>>;
28
32
  export declare function getRelayCancelWithdrawalExtrinsic(substrateApi: _SubstrateApi, selectedUnstaking: UnstakingInfo): Promise<import("@polkadot/api-base/types").SubmittableExtrinsic<"promise", import("@polkadot/types/types").ISubmittableResult>>;
@@ -1,21 +1,99 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- import { StakingType, UnstakingStatus } from '@subwallet/extension-base/background/KoniTypes';
5
- import { calculateAlephZeroValidatorReturn, calculateChainStakedReturn, calculateInflation, calculateValidatorStakedReturn, getCommission, parseIdentity, transformPoolName } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
4
+ import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
+ import { StakingStatus, StakingTxErrorType, StakingType, UnstakingStatus } from '@subwallet/extension-base/background/KoniTypes';
6
+ import { calculateAlephZeroValidatorReturn, calculateChainStakedReturn, calculateInflation, calculateValidatorStakedReturn, getCommission, parseIdentity, parsePoolStashAddress, transformPoolName } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
6
7
  import { _STAKING_CHAIN_GROUP, _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
8
+ import { _getChainNativeTokenBasicInfo, _getChainSubstrateAddressPrefix } from '@subwallet/extension-base/services/chain-service/utils';
9
+ import { reformatAddress } from '@subwallet/extension-base/utils';
7
10
  import { BN, BN_ZERO } from '@polkadot/util';
8
11
  import { isEthereumAddress } from '@polkadot/util-crypto';
9
- export async function getRelayChainStakingMetadata(chain, substrateApi) {
10
- var _chainApi$api$query$a, _chainApi$api$query, _chainApi$api$query$n;
12
+ export function validateRelayUnbondingCondition(amount, chainStakingMetadata, nominatorMetadata) {
13
+ const errors = [];
14
+ const bnActiveStake = new BN(nominatorMetadata.activeStake);
15
+ const bnRemainingStake = bnActiveStake.sub(new BN(amount));
16
+ const minStake = new BN(chainStakingMetadata.minPoolBonding || '0');
17
+ if (!(bnRemainingStake.isZero() || bnRemainingStake.gte(minStake))) {
18
+ errors.push(new TransactionError(StakingTxErrorType.INVALID_ACTIVE_STAKE));
19
+ }
20
+ if (nominatorMetadata.unstakings.length > chainStakingMetadata.maxWithdrawalRequestPerValidator) {
21
+ errors.push(new TransactionError(StakingTxErrorType.EXCEED_MAX_UNSTAKING));
22
+ }
23
+ return errors;
24
+ }
25
+ export function validatePoolBondingCondition(chainInfo, amount, selectedPool, address, chainStakingMetadata, nominatorMetadata) {
26
+ // cannot stake when unstake all
27
+ // amount >= min stake
28
+ const errors = [];
29
+ let bnTotalStake = new BN(amount);
30
+ const bnMinStake = new BN(chainStakingMetadata.minPoolBonding || '0');
31
+ if (nominatorMetadata) {
32
+ const bnCurrentActiveStake = new BN(nominatorMetadata.activeStake);
33
+ bnTotalStake = bnTotalStake.add(bnCurrentActiveStake);
34
+ if (!bnCurrentActiveStake.gt(BN_ZERO)) {
35
+ errors.push(new TransactionError(StakingTxErrorType.EXIST_UNSTAKING_REQUEST));
36
+ }
37
+ }
38
+ if (!bnTotalStake.gte(bnMinStake)) {
39
+ errors.push(new TransactionError(StakingTxErrorType.NOT_ENOUGH_MIN_STAKE));
40
+ }
41
+ return errors;
42
+ }
43
+ export function validateRelayBondingCondition(chainInfo, amount, selectedValidators, address, chainStakingMetadata, nominatorMetadata) {
44
+ const errors = [];
45
+ let bnTotalStake = new BN(amount);
46
+ const bnMinStake = new BN(chainStakingMetadata.minStake);
47
+ if (!nominatorMetadata) {
48
+ if (!bnTotalStake.gte(bnMinStake)) {
49
+ errors.push(new TransactionError(StakingTxErrorType.NOT_ENOUGH_MIN_STAKE));
50
+ }
51
+ if (selectedValidators.length > chainStakingMetadata.maxValidatorPerNominator) {
52
+ errors.push(new TransactionError(StakingTxErrorType.EXCEED_MAX_NOMINATIONS));
53
+ }
54
+ return errors;
55
+ }
56
+ const bnCurrentActiveStake = new BN(nominatorMetadata.activeStake);
57
+ bnTotalStake = bnTotalStake.add(bnCurrentActiveStake);
58
+ if (!bnTotalStake.gte(bnMinStake)) {
59
+ errors.push(new TransactionError(StakingTxErrorType.NOT_ENOUGH_MIN_STAKE));
60
+ }
61
+ if (selectedValidators.length > chainStakingMetadata.maxValidatorPerNominator) {
62
+ errors.push(new TransactionError(StakingTxErrorType.EXCEED_MAX_NOMINATIONS));
63
+ }
64
+ return errors;
65
+ }
66
+ export async function getRelayChainStakingMetadata(chainInfo, substrateApi) {
67
+ var _chainApi$api$query$a, _chainApi$api$query, _chainApi$api$query$s, _chainApi$api$query2, _chainApi$api$query2$, _chainApi$api$query3, _chainApi$api$query3$;
68
+ const chain = chainInfo.slug;
69
+ const {
70
+ decimals
71
+ } = _getChainNativeTokenBasicInfo(chainInfo);
11
72
  const chainApi = await substrateApi.isReady;
12
73
  const _era = await chainApi.api.query.staking.currentEra();
13
74
  const currentEra = _era.toString();
14
75
  const maxNominations = chainApi.api.consts.staking.maxNominations.toString();
15
76
  const maxUnlockingChunks = chainApi.api.consts.staking.maxUnlockingChunks.toString();
16
77
  const unlockingEras = chainApi.api.consts.staking.bondingDuration.toString();
17
- const [_totalEraStake, _totalIssuance, _auctionCounter, _minimumActiveStake, _minPoolJoin] = await Promise.all([chainApi.api.query.staking.erasTotalStake(parseInt(currentEra)), chainApi.api.query.balances.totalIssuance(), (_chainApi$api$query$a = chainApi.api.query.auctions) === null || _chainApi$api$query$a === void 0 ? void 0 : _chainApi$api$query$a.auctionCounter(), chainApi.api.query.staking.minimumActiveStake(), (_chainApi$api$query = chainApi.api.query) === null || _chainApi$api$query === void 0 ? void 0 : (_chainApi$api$query$n = _chainApi$api$query.nominationPools) === null || _chainApi$api$query$n === void 0 ? void 0 : _chainApi$api$query$n.minJoinBond()]);
18
- const minStake = _minimumActiveStake.toString();
78
+ const [_totalEraStake, _totalIssuance, _auctionCounter, _minimumActiveStake, _minNominatorBond, _minPoolJoin, _eraStakers] = await Promise.all([chainApi.api.query.staking.erasTotalStake(parseInt(currentEra)), chainApi.api.query.balances.totalIssuance(), (_chainApi$api$query$a = chainApi.api.query.auctions) === null || _chainApi$api$query$a === void 0 ? void 0 : _chainApi$api$query$a.auctionCounter(), ((_chainApi$api$query = chainApi.api.query) === null || _chainApi$api$query === void 0 ? void 0 : (_chainApi$api$query$s = _chainApi$api$query.staking) === null || _chainApi$api$query$s === void 0 ? void 0 : _chainApi$api$query$s.minimumActiveStake) && ((_chainApi$api$query2 = chainApi.api.query) === null || _chainApi$api$query2 === void 0 ? void 0 : (_chainApi$api$query2$ = _chainApi$api$query2.staking) === null || _chainApi$api$query2$ === void 0 ? void 0 : _chainApi$api$query2$.minimumActiveStake()), chainApi.api.query.staking.minNominatorBond(), (_chainApi$api$query3 = chainApi.api.query) === null || _chainApi$api$query3 === void 0 ? void 0 : (_chainApi$api$query3$ = _chainApi$api$query3.nominationPools) === null || _chainApi$api$query3$ === void 0 ? void 0 : _chainApi$api$query3$.minJoinBond(), chainApi.api.query.staking.erasStakers.entries(parseInt(currentEra))]);
79
+ const eraStakers = _eraStakers;
80
+ const nominatorList = [];
81
+ for (const item of eraStakers) {
82
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
83
+ const rawValidatorStat = item[1].toHuman();
84
+ const eraNominators = rawValidatorStat.others;
85
+ for (const nominator of eraNominators) {
86
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
87
+ if (!nominatorList.includes(nominator.who)) {
88
+ nominatorList.push(nominator.who);
89
+ }
90
+ }
91
+ }
92
+ const minActiveStake = (_minimumActiveStake === null || _minimumActiveStake === void 0 ? void 0 : _minimumActiveStake.toString()) || '0';
93
+ const minNominatorBond = _minNominatorBond.toString();
94
+ const bnMinActiveStake = new BN(minActiveStake);
95
+ const bnMinNominatorBond = new BN(minNominatorBond);
96
+ const minStake = bnMinActiveStake.gt(bnMinNominatorBond) ? bnMinActiveStake : bnMinNominatorBond;
19
97
  const minPoolJoin = (_minPoolJoin === null || _minPoolJoin === void 0 ? void 0 : _minPoolJoin.toString()) || undefined;
20
98
  const rawTotalEraStake = _totalEraStake.toString();
21
99
  const rawTotalIssuance = _totalIssuance.toString();
@@ -33,23 +111,34 @@ export async function getRelayChainStakingMetadata(chain, substrateApi) {
33
111
  expectedReturn,
34
112
  // in %, annually
35
113
  inflation,
36
- minStake,
114
+ minStake: minStake.toString(),
115
+ minPoolBonding: (10 ** decimals).toString(),
116
+ // default is 1
37
117
  maxValidatorPerNominator: parseInt(maxNominations),
38
118
  maxWithdrawalRequestPerValidator: parseInt(maxUnlockingChunks),
39
119
  allowCancelUnstaking: true,
40
120
  unstakingPeriod: unlockingPeriod,
41
- minJoinNominationPool: minPoolJoin
121
+ minJoinNominationPool: minPoolJoin,
122
+ nominatorCount: nominatorList.length
42
123
  };
43
124
  }
44
125
  export async function getRelayChainNominatorMetadata(chainInfo, address, substrateApi) {
126
+ var _chainApi$api$query4, _chainApi$api$query4$, _chainApi$api$query5, _chainApi$api$query5$, _chainApi$api$query6, _chainApi$api$query6$, _chainApi$api$query7, _chainApi$api$query7$, _chainApi$api$query8, _chainApi$api$query8$, _chainApi$api$query9, _chainApi$api$query9$, _chainApi$api$query10, _chainApi$api$query11;
45
127
  if (isEthereumAddress(address)) {
46
128
  return;
47
129
  }
48
130
  const chain = chainInfo.slug;
49
131
  const chainApi = await substrateApi.isReady;
50
- const [_ledger, _nominations, _currentEra, _bonded] = await Promise.all([chainApi.api.query.staking.ledger(address), chainApi.api.query.staking.nominators(address), chainApi.api.query.staking.currentEra(), chainApi.api.query.staking.bonded(address)]);
51
- const ledger = _ledger.toJSON();
52
- const nominations = _nominations.toJSON();
132
+ const [_ledger, _nominations, _currentEra, _bonded, _minimumActiveStake, _minNominatorBond] = await Promise.all([(_chainApi$api$query4 = chainApi.api.query) === null || _chainApi$api$query4 === void 0 ? void 0 : (_chainApi$api$query4$ = _chainApi$api$query4.staking) === null || _chainApi$api$query4$ === void 0 ? void 0 : _chainApi$api$query4$.ledger(address), (_chainApi$api$query5 = chainApi.api.query) === null || _chainApi$api$query5 === void 0 ? void 0 : (_chainApi$api$query5$ = _chainApi$api$query5.staking) === null || _chainApi$api$query5$ === void 0 ? void 0 : _chainApi$api$query5$.nominators(address), (_chainApi$api$query6 = chainApi.api.query) === null || _chainApi$api$query6 === void 0 ? void 0 : (_chainApi$api$query6$ = _chainApi$api$query6.staking) === null || _chainApi$api$query6$ === void 0 ? void 0 : _chainApi$api$query6$.currentEra(), (_chainApi$api$query7 = chainApi.api.query) === null || _chainApi$api$query7 === void 0 ? void 0 : (_chainApi$api$query7$ = _chainApi$api$query7.staking) === null || _chainApi$api$query7$ === void 0 ? void 0 : _chainApi$api$query7$.bonded(address), ((_chainApi$api$query8 = chainApi.api.query) === null || _chainApi$api$query8 === void 0 ? void 0 : (_chainApi$api$query8$ = _chainApi$api$query8.staking) === null || _chainApi$api$query8$ === void 0 ? void 0 : _chainApi$api$query8$.minimumActiveStake) && ((_chainApi$api$query9 = chainApi.api.query) === null || _chainApi$api$query9 === void 0 ? void 0 : (_chainApi$api$query9$ = _chainApi$api$query9.staking) === null || _chainApi$api$query9$ === void 0 ? void 0 : _chainApi$api$query9$.minimumActiveStake()), (_chainApi$api$query10 = chainApi.api.query) === null || _chainApi$api$query10 === void 0 ? void 0 : (_chainApi$api$query11 = _chainApi$api$query10.staking) === null || _chainApi$api$query11 === void 0 ? void 0 : _chainApi$api$query11.minNominatorBond()]);
133
+ const minActiveStake = (_minimumActiveStake === null || _minimumActiveStake === void 0 ? void 0 : _minimumActiveStake.toString()) || '0';
134
+ const minNominatorBond = _minNominatorBond.toString();
135
+ const bnMinActiveStake = new BN(minActiveStake);
136
+ const bnMinNominatorBond = new BN(minNominatorBond);
137
+ const minStake = bnMinActiveStake.gt(bnMinNominatorBond) ? bnMinActiveStake : bnMinNominatorBond;
138
+ const _maxNominatorRewardedPerValidator = chainApi.api.consts.staking.maxNominatorRewardedPerValidator.toString();
139
+ const maxNominatorRewardedPerValidator = parseInt(_maxNominatorRewardedPerValidator);
140
+ const ledger = _ledger.toPrimitive();
141
+ const nominations = _nominations.toPrimitive();
53
142
  const currentEra = _currentEra.toString();
54
143
  const bonded = _bonded.toHuman();
55
144
  if (!ledger) {
@@ -61,17 +150,47 @@ export async function getRelayChainNominatorMetadata(chainInfo, address, substra
61
150
  if (nominations) {
62
151
  const validatorList = nominations.targets;
63
152
  await Promise.all(validatorList.map(async validatorAddress => {
64
- const identityInfo = (await chainApi.api.query.identity.identityOf(validatorAddress)).toHuman();
153
+ let nominationStatus = StakingStatus.NOT_EARNING;
154
+ const [_identityInfo, _eraStaker] = await Promise.all([chainApi.api.query.identity.identityOf(validatorAddress), chainApi.api.query.staking.erasStakers(currentEra, validatorAddress)]);
155
+ const eraStaker = _eraStaker.toPrimitive();
156
+ const identityInfo = _identityInfo.toHuman();
65
157
  const identity = parseIdentity(identityInfo);
158
+ const topNominators = eraStaker.others.map(nominator => {
159
+ return nominator.who;
160
+ });
161
+ if (!topNominators.includes(reformatAddress(address, _getChainSubstrateAddressPrefix(chainInfo)))) {
162
+ // if nominator has target but not in nominator list
163
+ nominationStatus = StakingStatus.WAITING;
164
+ } else if (topNominators.slice(0, maxNominatorRewardedPerValidator).includes(reformatAddress(address, _getChainSubstrateAddressPrefix(chainInfo)))) {
165
+ // if address in top nominators
166
+ nominationStatus = StakingStatus.EARNING_REWARD;
167
+ }
66
168
  nominationList.push({
67
169
  chain,
68
170
  validatorAddress,
171
+ status: nominationStatus,
69
172
  validatorIdentity: identity,
70
173
  activeStake: '0' // relaychain allocates stake accordingly
71
174
  });
72
175
  }));
73
176
  }
74
177
 
178
+ let stakingStatus = StakingStatus.NOT_EARNING;
179
+ const bnActiveStake = new BN(activeStake);
180
+ let waitingNominationCount = 0;
181
+ if (bnActiveStake.gte(minStake)) {
182
+ for (const nomination of nominationList) {
183
+ if (nomination.status === StakingStatus.EARNING_REWARD) {
184
+ // only need 1 earning nomination to count
185
+ stakingStatus = StakingStatus.EARNING_REWARD;
186
+ } else if (nomination.status === StakingStatus.WAITING) {
187
+ waitingNominationCount += 1;
188
+ }
189
+ }
190
+ if (waitingNominationCount === nominationList.length) {
191
+ stakingStatus = StakingStatus.WAITING;
192
+ }
193
+ }
75
194
  ledger.unlocking.forEach(unlockingChunk => {
76
195
  const isClaimable = unlockingChunk.era - parseInt(currentEra) <= 0;
77
196
  const remainingEra = unlockingChunk.era - (parseInt(currentEra) + 1);
@@ -86,6 +205,7 @@ export async function getRelayChainNominatorMetadata(chainInfo, address, substra
86
205
  return {
87
206
  chain,
88
207
  type: StakingType.NOMINATED,
208
+ status: stakingStatus,
89
209
  address: address,
90
210
  activeStake,
91
211
  nominations: nominationList,
@@ -96,17 +216,39 @@ export async function getRelayChainNominatorMetadata(chainInfo, address, substra
96
216
  export async function getRelayChainPoolMemberMetadata(chainInfo, address, substrateApi) {
97
217
  const chainApi = await substrateApi.isReady;
98
218
  const [_poolMemberInfo, _currentEra] = await Promise.all([chainApi.api.query.nominationPools.poolMembers(address), chainApi.api.query.staking.currentEra()]);
219
+ const _maxNominatorRewardedPerValidator = chainApi.api.consts.staking.maxNominatorRewardedPerValidator.toString();
220
+ const maxNominatorRewardedPerValidator = parseInt(_maxNominatorRewardedPerValidator);
221
+ const poolsPalletId = chainApi.api.consts.nominationPools.palletId.toString();
99
222
  const poolMemberInfo = _poolMemberInfo.toPrimitive();
100
223
  const currentEra = _currentEra.toString();
101
224
  if (!poolMemberInfo) {
102
225
  return;
103
226
  }
227
+ let stakingStatus = StakingStatus.NOT_EARNING;
104
228
  const _poolMetadata = await chainApi.api.query.nominationPools.metadata(poolMemberInfo.poolId);
105
229
  const poolMetadata = _poolMetadata.toPrimitive();
106
230
  const poolName = transformPoolName(poolMetadata.isUtf8 ? poolMetadata.toUtf8() : poolMetadata.toString());
231
+ const poolStashAccount = parsePoolStashAddress(chainApi.api, 0, poolMemberInfo.poolId, poolsPalletId);
232
+ const _nominations = await chainApi.api.query.staking.nominators(poolStashAccount);
233
+ const nominations = _nominations.toJSON();
234
+ if (nominations) {
235
+ const validatorList = nominations.targets;
236
+ await Promise.all(validatorList.map(async validatorAddress => {
237
+ const _eraStaker = await chainApi.api.query.staking.erasStakers(currentEra, validatorAddress);
238
+ const eraStaker = _eraStaker.toPrimitive();
239
+ const topNominators = eraStaker.others.map(nominator => {
240
+ return nominator.who;
241
+ }).slice(0, maxNominatorRewardedPerValidator);
242
+ if (topNominators.includes(reformatAddress(poolStashAccount, _getChainSubstrateAddressPrefix(chainInfo)))) {
243
+ // if address in top nominators
244
+ stakingStatus = StakingStatus.EARNING_REWARD;
245
+ }
246
+ }));
247
+ }
107
248
  const joinedPoolInfo = {
108
249
  activeStake: poolMemberInfo.points.toString(),
109
250
  chain: chainInfo.slug,
251
+ status: stakingStatus,
110
252
  validatorIdentity: poolName,
111
253
  validatorAddress: poolMemberInfo.poolId.toString(),
112
254
  // use poolId
@@ -124,10 +266,15 @@ export async function getRelayChainPoolMemberMetadata(chainInfo, address, substr
124
266
  waitingTime: waitingTime > 0 ? waitingTime : 0
125
267
  });
126
268
  });
269
+ const bnActiveStake = new BN(poolMemberInfo.points.toString());
270
+ if (!bnActiveStake.gt(BN_ZERO)) {
271
+ stakingStatus = StakingStatus.NOT_EARNING;
272
+ }
127
273
  return {
128
274
  chain: chainInfo.slug,
129
275
  type: StakingType.POOLED,
130
276
  address,
277
+ status: stakingStatus,
131
278
  activeStake: poolMemberInfo.points.toString(),
132
279
  nominations: [joinedPoolInfo],
133
280
  // can only join 1 pool at a time
@@ -183,9 +330,9 @@ export async function getRelayValidatorsInfo(chain, substrateApi, decimals, chai
183
330
  }
184
331
  const extraInfoMap = {};
185
332
  await Promise.all(allValidators.map(async address => {
186
- var _chainApi$api$query2, _chainApi$api$query2$, _identityInfo$judgeme;
333
+ var _chainApi$api$query12, _chainApi$api$query13, _identityInfo$judgeme;
187
334
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
188
- const [_commissionInfo, _identityInfo] = await Promise.all([chainApi.api.query.staking.validators(address), (_chainApi$api$query2 = chainApi.api.query) === null || _chainApi$api$query2 === void 0 ? void 0 : (_chainApi$api$query2$ = _chainApi$api$query2.identity) === null || _chainApi$api$query2$ === void 0 ? void 0 : _chainApi$api$query2$.identityOf(address)]);
335
+ const [_commissionInfo, _identityInfo] = await Promise.all([chainApi.api.query.staking.validators(address), (_chainApi$api$query12 = chainApi.api.query) === null || _chainApi$api$query12 === void 0 ? void 0 : (_chainApi$api$query13 = _chainApi$api$query12.identity) === null || _chainApi$api$query13 === void 0 ? void 0 : _chainApi$api$query13.identityOf(address)]);
189
336
  const commissionInfo = _commissionInfo.toHuman();
190
337
  const identityInfo = _identityInfo ? _identityInfo.toHuman() : null;
191
338
  let identity;
@@ -236,22 +383,30 @@ export async function getRelayPoolsInfo(chain, substrateApi) {
236
383
  }));
237
384
  return nominationPools;
238
385
  }
239
- export async function getRelayBondingExtrinsic(substrateApi, amount, targetValidators, nominatorMetadata, chainInfo, bondDest = 'Staked') {
386
+ export async function getRelayBondingExtrinsic(substrateApi, amount, targetValidators, chainInfo, address, nominatorMetadata, bondDest = 'Staked') {
240
387
  const chainApi = await substrateApi.isReady;
241
388
  const binaryAmount = new BN(amount);
242
389
  let bondTx;
243
390
  let nominateTx;
391
+ const validatorParamList = targetValidators.map(validator => {
392
+ return validator.address;
393
+ });
394
+ if (!nominatorMetadata) {
395
+ bondTx = chainApi.api.tx.staking.bond(address, binaryAmount, bondDest);
396
+ nominateTx = chainApi.api.tx.staking.nominate(validatorParamList);
397
+ return chainApi.api.tx.utility.batchAll([bondTx, nominateTx]);
398
+ }
244
399
  if (!nominatorMetadata.isBondedBefore) {
245
400
  // first time
246
401
  bondTx = chainApi.api.tx.staking.bond(nominatorMetadata.address, binaryAmount, bondDest);
247
- nominateTx = chainApi.api.tx.staking.nominate(targetValidators);
402
+ nominateTx = chainApi.api.tx.staking.nominate(validatorParamList);
248
403
  return chainApi.api.tx.utility.batchAll([bondTx, nominateTx]);
249
404
  } else {
250
405
  if (binaryAmount.gt(BN_ZERO)) {
251
406
  bondTx = chainApi.api.tx.staking.bondExtra(binaryAmount);
252
407
  }
253
408
  if (nominatorMetadata.isBondedBefore && targetValidators.length > 0) {
254
- nominateTx = chainApi.api.tx.staking.nominate(targetValidators);
409
+ nominateTx = chainApi.api.tx.staking.nominate(validatorParamList);
255
410
  }
256
411
  }
257
412
  if (bondTx && !nominateTx) {
@@ -1,6 +1,7 @@
1
1
  /// <reference types="bn.js" />
2
- import { NominationInfo, NominatorMetadata, StakingType, UnstakingInfo } from '@subwallet/extension-base/background/KoniTypes';
2
+ import { NominationInfo, NominatorMetadata, StakingStatus, StakingType, UnstakingInfo } from '@subwallet/extension-base/background/KoniTypes';
3
3
  import { _SubstrateInflationParams } from '@subwallet/extension-base/services/chain-service/constants';
4
+ import { ApiPromise } from '@polkadot/api';
4
5
  import { BN } from '@polkadot/util';
5
6
  export interface PalletNominationPoolsPoolMember {
6
7
  poolId: number;
@@ -64,6 +65,15 @@ export interface PalletParachainStakingDelegator {
64
65
  lessTotal: number;
65
66
  status: number;
66
67
  }
68
+ export interface PalletStakingExposureItem {
69
+ who: string;
70
+ value: number;
71
+ }
72
+ export interface PalletStakingExposure {
73
+ total: number;
74
+ own: number;
75
+ others: PalletStakingExposureItem[];
76
+ }
67
77
  export interface PalletIdentityRegistration {
68
78
  judgements: any[];
69
79
  deposit: number;
@@ -92,6 +102,7 @@ export interface Unlocking {
92
102
  remainingEras: BN;
93
103
  value: BN;
94
104
  }
105
+ export declare function parsePoolStashAddress(api: ApiPromise, index: number, poolId: number, poolsPalletId: string): string;
95
106
  export declare function transformPoolName(input: string): string;
96
107
  export declare function parseIdentity(identityInfo: PalletIdentityRegistration | null): string | undefined;
97
108
  export declare function getInflationParams(networkKey: string): _SubstrateInflationParams;
@@ -137,6 +148,8 @@ export declare enum StakingAction {
137
148
  CLAIM_REWARD = "CLAIM_REWARD",
138
149
  CANCEL_UNSTAKE = "CANCEL_UNSTAKE"
139
150
  }
140
- export declare function getStakingAvailableActions(nominatorMetadata: NominatorMetadata): StakingAction[];
151
+ export declare function getStakingAvailableActionsByChain(chain: string, type: StakingType): StakingAction[];
152
+ export declare function getStakingAvailableActionsByNominator(nominatorMetadata: NominatorMetadata, unclaimedReward?: string): StakingAction[];
141
153
  export declare function isActionFromValidator(stakingType: StakingType, chain: string): boolean;
142
154
  export declare function getWithdrawalInfo(nominatorMetadata: NominatorMetadata): UnstakingInfo | undefined;
155
+ export declare function getStakingStatusByNominations(bnTotalActiveStake: BN, nominationList: NominationInfo[]): StakingStatus;