@subwallet/extension-base 1.3.56-0 → 1.3.58-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 (27) hide show
  1. package/cjs/koni/api/staking/bonding/utils.js +2 -0
  2. package/cjs/packageInfo.js +1 -1
  3. package/cjs/services/chain-service/constants.js +11 -6
  4. package/cjs/services/chain-service/utils/patch.js +1 -1
  5. package/cjs/services/earning-service/constants/chains.js +1 -0
  6. package/cjs/services/earning-service/handlers/native-staking/energy.js +394 -0
  7. package/cjs/services/earning-service/handlers/native-staking/index.js +8 -1
  8. package/cjs/services/earning-service/service.js +3 -0
  9. package/cjs/services/earning-service/utils/index.js +2 -0
  10. package/cjs/services/transaction-service/utils.js +6 -0
  11. package/cjs/utils/setup-api-sdk.js +2 -2
  12. package/koni/api/staking/bonding/utils.js +2 -0
  13. package/package.json +11 -6
  14. package/packageInfo.js +1 -1
  15. package/services/chain-service/constants.js +12 -6
  16. package/services/chain-service/utils/patch.d.ts +1 -1
  17. package/services/chain-service/utils/patch.js +1 -1
  18. package/services/earning-service/constants/chains.d.ts +1 -0
  19. package/services/earning-service/constants/chains.js +1 -0
  20. package/services/earning-service/handlers/native-staking/energy.d.ts +30 -0
  21. package/services/earning-service/handlers/native-staking/energy.js +386 -0
  22. package/services/earning-service/handlers/native-staking/index.d.ts +1 -0
  23. package/services/earning-service/handlers/native-staking/index.js +2 -1
  24. package/services/earning-service/service.js +4 -1
  25. package/services/earning-service/utils/index.js +2 -0
  26. package/services/transaction-service/utils.js +6 -0
  27. package/utils/setup-api-sdk.js +2 -2
@@ -249,6 +249,8 @@ function getYieldAvailableActionsByType(yieldPoolInfo) {
249
249
  const chain = yieldPoolInfo.chain;
250
250
  if (_constants2._STAKING_CHAIN_GROUP.para.includes(chain)) {
251
251
  return [YieldAction.STAKE, YieldAction.UNSTAKE, YieldAction.WITHDRAW, YieldAction.CANCEL_UNSTAKE];
252
+ } else if (_constants2._STAKING_CHAIN_GROUP.energy.includes(chain)) {
253
+ return [YieldAction.STAKE, YieldAction.UNSTAKE, YieldAction.WITHDRAW, YieldAction.CANCEL_UNSTAKE];
252
254
  } else if (_constants2._STAKING_CHAIN_GROUP.astar.includes(chain)) {
253
255
  return [YieldAction.STAKE, YieldAction.CLAIM_REWARD, YieldAction.UNSTAKE, YieldAction.WITHDRAW];
254
256
  } else if (_constants2._STAKING_CHAIN_GROUP.amplitude.includes(chain)) {
@@ -13,6 +13,6 @@ const packageInfo = {
13
13
  name: '@subwallet/extension-base',
14
14
  path: typeof __dirname === 'string' ? __dirname : 'auto',
15
15
  type: 'cjs',
16
- version: '1.3.56-0'
16
+ version: '1.3.58-0'
17
17
  };
18
18
  exports.packageInfo = packageInfo;
@@ -40,8 +40,8 @@ const _BALANCE_CHAIN_GROUP = {
40
40
  kintsugi: ['kintsugi', 'interlay', 'kintsugi_test', 'mangatax_para'],
41
41
  genshiro: ['genshiro_testnet', 'genshiro'],
42
42
  equilibrium_parachain: ['equilibrium_parachain'],
43
- bifrost: ['bifrost', 'acala', 'karura', 'acala_testnet', 'pioneer', 'bitcountry', 'bifrost_dot', 'hydradx_main', 'hydradx_rococo', 'pendulum', 'amplitude', 'continuum_network', 'truth_network', 'jamton'],
44
- statemine: ['statemine', 'astar', 'shiden', 'statemint', 'crabParachain', 'darwinia2', 'parallel', 'calamari', 'manta_network', 'rococo_assethub', 'liberlandTest', 'liberland', 'dentnet', 'pangolin', 'crust', 'phala', 'shibuya', 'dbcchain', 'westend_assethub', 'chainflip_assethub', 'origintrail'],
43
+ bifrost: ['bifrost', 'acala', 'karura', 'acala_testnet', 'pioneer', 'bitcountry', 'bifrost_dot', 'hydradx_main', 'hydradx_rococo', 'pendulum', 'amplitude', 'continuum_network', 'truth_network', 'jamton', 'hydradx_hollarnet'],
44
+ statemine: ['statemine', 'astar', 'shiden', 'statemint', 'crabParachain', 'darwinia2', 'parallel', 'calamari', 'manta_network', 'rococo_assethub', 'liberlandTest', 'liberland', 'dentnet', 'pangolin', 'crust', 'phala', 'shibuya', 'dbcchain', 'westend_assethub', 'chainflip_assethub', 'origintrail', 'xode'],
45
45
  kusama: ['kusama', 'kintsugi', 'kintsugi_test', 'interlay', 'acala', 'statemint', 'karura', 'bifrost'],
46
46
  // perhaps there are some runtime updates
47
47
  centrifuge: ['centrifuge'],
@@ -120,7 +120,10 @@ const _STAKING_ERA_LENGTH_MAP = {
120
120
  analog_timechain: 12,
121
121
  muse_testnet: 25 * 6 / 60 / 60,
122
122
  // 25 blocks per session
123
- mythos: 24
123
+ mythos: 24,
124
+ energy_web_x_testnet: 22 * 12 / 3600,
125
+ // 22 blocks per era, 1 block per 12s
126
+ energy_web_x: 7200 * 12 / 3600 // 24 hours, 7200 blocks per era, 1 block per 12s
124
127
  };
125
128
  exports._STAKING_ERA_LENGTH_MAP = _STAKING_ERA_LENGTH_MAP;
126
129
  const _EXPECTED_BLOCK_TIME = {
@@ -156,7 +159,9 @@ const _EXPECTED_BLOCK_TIME = {
156
159
  avail_mainnet: 20,
157
160
  dentnet: 3,
158
161
  muse_testnet: 6,
159
- mythos: 6
162
+ mythos: 6,
163
+ energy_web_x_testnet: 12,
164
+ energy_web_x: 12
160
165
  };
161
166
  exports._EXPECTED_BLOCK_TIME = _EXPECTED_BLOCK_TIME;
162
167
  const _PARACHAIN_INFLATION_DISTRIBUTION = {
@@ -273,11 +278,11 @@ const _TRANSFER_CHAIN_GROUP = {
273
278
  genshiro: ['genshiro_testnet', 'genshiro', 'equilibrium_parachain'],
274
279
  // crab: ['crab', 'pangolin'],
275
280
  bitcountry: ['pioneer', 'bitcountry'],
276
- statemine: ['statemint', 'statemine', 'darwinia2', 'astar', 'shiden', 'shibuya', 'parallel', 'liberland', 'liberlandTest', 'dentnet', 'dbcchain', 'westend_assethub', 'chainflip_assethub', 'origintrail'],
281
+ statemine: ['statemint', 'statemine', 'darwinia2', 'astar', 'shiden', 'shibuya', 'parallel', 'liberland', 'liberlandTest', 'dentnet', 'dbcchain', 'westend_assethub', 'chainflip_assethub', 'origintrail', 'xode'],
277
282
  riochain: ['riochain'],
278
283
  sora_substrate: ['sora_substrate'],
279
284
  avail: ['kate', 'goldberg_testnet'],
280
- pendulum: ['pendulum', 'amplitude', 'amplitude_test', 'hydradx_main', 'bifrost', 'bifrost_dot', 'jamton'],
285
+ pendulum: ['pendulum', 'amplitude', 'amplitude_test', 'hydradx_main', 'bifrost', 'bifrost_dot', 'jamton', 'hydradx_hollarnet'],
281
286
  centrifuge: ['centrifuge'],
282
287
  disable_transfer: ['crab', 'pangolin'],
283
288
  truth: ['truth_network']
@@ -12,7 +12,7 @@ const PRODUCTION_BRANCHES = ['master', 'webapp', 'webapp-dev'];
12
12
  const branchName = process.env.BRANCH_NAME || 'subwallet-dev';
13
13
  const fetchDomain = process.env.PATCH_CHAIN_LIST_URL || (PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'https://chain-list-assets.subwallet.app' : 'https://dev.sw-chain-list-assets.pages.dev');
14
14
  const fetchFile = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'list.json' : 'preview.json';
15
- const ChainListVersion = '0.2.114'; // update this when build chain-list
15
+ const ChainListVersion = '0.2.115'; // update this when build chain-list
16
16
 
17
17
  // todo: move this interface to chainlist
18
18
  exports.ChainListVersion = ChainListVersion;
@@ -24,6 +24,7 @@ const _STAKING_CHAIN_GROUP = {
24
24
  krest_network: ['krest_network'],
25
25
  manta: ['manta_network'],
26
26
  bittensor: ['bittensor', 'bittensor_testnet'],
27
+ energy: ['energy_web_x_testnet', 'energy_web_x'],
27
28
  mythos: ['mythos', 'muse_testnet']
28
29
  };
29
30
  exports._STAKING_CHAIN_GROUP = _STAKING_CHAIN_GROUP;
@@ -0,0 +1,394 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _TransactionError = require("@subwallet/extension-base/background/errors/TransactionError");
9
+ var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
10
+ var _utils = require("@subwallet/extension-base/koni/api/staking/bonding/utils");
11
+ var _constants = require("@subwallet/extension-base/services/chain-service/constants");
12
+ var _utils2 = require("@subwallet/extension-base/services/earning-service/utils");
13
+ var _types = require("@subwallet/extension-base/types");
14
+ var _utils3 = require("@subwallet/extension-base/utils");
15
+ var _util = require("@polkadot/util");
16
+ var _basePara = _interopRequireDefault(require("./base-para"));
17
+ // Copyright 2019-2022 @subwallet/extension-base
18
+ // SPDX-License-Identifier: Apache-2.0
19
+
20
+ class EnergyNativeStakingPoolHandler extends _basePara.default {
21
+ /* Subscribe pool info */
22
+
23
+ async subscribePoolInfo(callback) {
24
+ let cancel = false;
25
+ const chainApi = this.substrateApi;
26
+ const nativeToken = this.nativeToken;
27
+ const defaultCallback = async () => {
28
+ const data = {
29
+ ...this.baseInfo,
30
+ type: this.type,
31
+ metadata: {
32
+ ...this.metadataInfo,
33
+ description: this.getDescription()
34
+ }
35
+ };
36
+ const poolInfo = await this.getPoolInfo();
37
+ !poolInfo && callback(data);
38
+ };
39
+ if (!this.isActive) {
40
+ await defaultCallback();
41
+ return () => {
42
+ cancel = true;
43
+ };
44
+ }
45
+ await defaultCallback();
46
+ await chainApi.isReady;
47
+ const unsub = await chainApi.api.query.parachainStaking.era(async _era => {
48
+ var _chainApi$api$consts, _chainApi$api$consts$, _chainApi$api$consts$2, _chainApi$api$consts$3, _chainApi$api$query$p;
49
+ if (cancel) {
50
+ unsub();
51
+ return;
52
+ }
53
+ const eraObj = _era.toHuman();
54
+ const era = (0, _utils3.parseRawNumber)(eraObj.current);
55
+ const maxNominations = (_chainApi$api$consts = chainApi.api.consts) === null || _chainApi$api$consts === void 0 ? void 0 : (_chainApi$api$consts$ = _chainApi$api$consts.parachainStaking) === null || _chainApi$api$consts$ === void 0 ? void 0 : (_chainApi$api$consts$2 = _chainApi$api$consts$.maxNominationsPerNominator) === null || _chainApi$api$consts$2 === void 0 ? void 0 : _chainApi$api$consts$2.toString();
56
+ const maxTopNominatorsPerCollator = (_chainApi$api$consts$3 = chainApi.api.consts.parachainStaking.maxTopNominationsPerCandidate) === null || _chainApi$api$consts$3 === void 0 ? void 0 : _chainApi$api$consts$3.toPrimitive();
57
+ const [_totalStake, unstakingDelay] = await Promise.all([(_chainApi$api$query$p = chainApi.api.query.parachainStaking) === null || _chainApi$api$query$p === void 0 ? void 0 : _chainApi$api$query$p.staked(era), chainApi.api.query.parachainStaking.delay()]);
58
+ const totalStake = _totalStake ? new _util.BN(_totalStake.toString()) : _util.BN_ZERO;
59
+ const eraTime = _constants._STAKING_ERA_LENGTH_MAP[this.chain] || _constants._STAKING_ERA_LENGTH_MAP.default; // in hours
60
+ const unstakingPeriod = parseInt(unstakingDelay.toString()) * eraTime;
61
+ const minStake = '0';
62
+ const minToHuman = (0, _utils3.formatNumber)(minStake.toString(), nativeToken.decimals || 0, _utils3.balanceFormatter);
63
+ const data = {
64
+ ...this.baseInfo,
65
+ type: this.type,
66
+ metadata: {
67
+ ...this.metadataInfo,
68
+ description: this.getDescription(minToHuman)
69
+ },
70
+ statistic: {
71
+ assetEarning: [{
72
+ slug: this.nativeToken.slug
73
+ }],
74
+ maxCandidatePerFarmer: parseInt(maxNominations),
75
+ maxWithdrawalRequestPerFarmer: 1,
76
+ // by default
77
+ earningThreshold: {
78
+ join: minStake.toString(),
79
+ defaultUnstake: '0',
80
+ fastUnstake: '0'
81
+ },
82
+ farmerCount: 0,
83
+ // TODO recheck
84
+ era,
85
+ eraTime,
86
+ totalApy: undefined,
87
+ // not have
88
+ tvl: totalStake.toString(),
89
+ unstakingPeriod: unstakingPeriod
90
+ },
91
+ maxPoolMembers: maxTopNominatorsPerCollator
92
+ };
93
+ callback(data);
94
+ });
95
+ return () => {
96
+ cancel = true;
97
+ unsub();
98
+ };
99
+ }
100
+
101
+ /* Subscribe pool info */
102
+
103
+ /* Subscribe pool position */
104
+
105
+ async parseNominatorMetadata(chainInfo, address, substrateApi, nominatorState) {
106
+ const nominationList = [];
107
+ const unstakingMap = {};
108
+ const substrateIdentityApi = this.substrateIdentityApi;
109
+ let bnTotalActiveStake = _util.BN_ZERO;
110
+ let bnTotalStake = _util.BN_ZERO;
111
+ let bnTotalUnstaking = _util.BN_ZERO;
112
+ const _eraInfo = await substrateApi.api.query.parachainStaking.era();
113
+ const roundInfo = _eraInfo.toPrimitive();
114
+ const currentRound = roundInfo.current;
115
+ await Promise.all(nominatorState.nominations.map(async nomination => {
116
+ const [_nominationScheduledRequests, [identity], _collatorInfo, _currentBlock, _currentTimestamp] = await Promise.all([substrateApi.api.query.parachainStaking.nominationScheduledRequests(nomination.owner), (0, _utils2.parseIdentity)(substrateIdentityApi, nomination.owner), substrateApi.api.query.parachainStaking.candidateInfo(nomination.owner), substrateApi.api.query.system.number(), substrateApi.api.query.timestamp.now()]);
117
+ const currentBlock = _currentBlock.toPrimitive();
118
+ const currentTimestamp = _currentTimestamp.toPrimitive();
119
+ const collatorInfo = _collatorInfo.toPrimitive();
120
+ const minNomination = collatorInfo === null || collatorInfo === void 0 ? void 0 : collatorInfo.lowestTopNominationAmount.toString();
121
+ const nominationScheduledRequests = _nominationScheduledRequests.toPrimitive();
122
+ let hasUnstaking = false;
123
+ let nominationStatus = _types.EarningStatus.NOT_EARNING;
124
+
125
+ // parse unstaking info
126
+ if (nominationScheduledRequests) {
127
+ for (const scheduledRequest of nominationScheduledRequests) {
128
+ if ((0, _utils3.reformatAddress)(scheduledRequest.nominator, 0) === (0, _utils3.reformatAddress)(address, 0)) {
129
+ // add network prefix
130
+ const isClaimable = scheduledRequest.whenExecutable - parseInt(currentRound) <= 0;
131
+ const remainingEra = scheduledRequest.whenExecutable - parseInt(currentRound);
132
+ const waitingTime = remainingEra * _constants._STAKING_ERA_LENGTH_MAP[chainInfo.slug];
133
+ const claimable = Object.values(scheduledRequest.action)[0];
134
+
135
+ // noted: target timestamp in parachainStaking easily volatile if block time volatile
136
+ const targetBlock = remainingEra * parseInt(roundInfo.length) + parseInt(roundInfo.first);
137
+ const remainingBlock = targetBlock - currentBlock;
138
+ const targetTimestampMs = remainingBlock * _constants._EXPECTED_BLOCK_TIME[chainInfo.slug] * 1000 + currentTimestamp;
139
+ unstakingMap[nomination.owner] = {
140
+ chain: chainInfo.slug,
141
+ status: isClaimable ? _types.UnstakingStatus.CLAIMABLE : _types.UnstakingStatus.UNLOCKING,
142
+ validatorAddress: nomination.owner,
143
+ claimable: claimable.toString(),
144
+ waitingTime,
145
+ targetTimestampMs: targetTimestampMs
146
+ };
147
+ hasUnstaking = true;
148
+ break; // only handle 1 scheduledRequest per collator
149
+ }
150
+ }
151
+ }
152
+
153
+ const bnStake = new _util.BN(nomination.amount);
154
+ const bnUnstakeBalance = unstakingMap[nomination.owner] ? new _util.BN(unstakingMap[nomination.owner].claimable) : _util.BN_ZERO;
155
+ const bnActiveStake = bnStake.sub(bnUnstakeBalance);
156
+ if (bnActiveStake.gt(_util.BN_ZERO) && bnActiveStake.gte(new _util.BN(minNomination))) {
157
+ nominationStatus = _types.EarningStatus.EARNING_REWARD;
158
+ }
159
+ bnTotalActiveStake = bnTotalActiveStake.add(bnActiveStake);
160
+ bnTotalStake = bnTotalStake.add(bnStake);
161
+ bnTotalUnstaking = bnTotalUnstaking.add(bnUnstakeBalance);
162
+ nominationList.push({
163
+ chain: chainInfo.slug,
164
+ status: nominationStatus,
165
+ validatorAddress: nomination.owner,
166
+ validatorIdentity: identity,
167
+ activeStake: bnActiveStake.toString(),
168
+ hasUnstaking,
169
+ validatorMinStake: collatorInfo.lowestTopNominationAmount.toString()
170
+ });
171
+ }));
172
+ const stakingStatus = (0, _utils.getEarningStatusByNominations)(bnTotalActiveStake, nominationList);
173
+ const totalStake = bnTotalStake.toString();
174
+ const activeStake = bnTotalActiveStake.toString();
175
+ const unstakingBalance = bnTotalUnstaking.toString();
176
+ const tokenInfo = this.state.chainService.getAssetBySlug(this.nativeToken.slug);
177
+ await this.createWithdrawNotifications(Object.values(unstakingMap), tokenInfo, address);
178
+ return {
179
+ status: stakingStatus,
180
+ totalStake,
181
+ balanceToken: this.nativeToken.slug,
182
+ activeStake: activeStake,
183
+ unstakeBalance: unstakingBalance,
184
+ isBondedBefore: !!nominationList.length,
185
+ nominations: nominationList,
186
+ unstakings: Object.values(unstakingMap)
187
+ };
188
+ }
189
+ async subscribePoolPosition(useAddresses, resultCallback) {
190
+ let cancel = false;
191
+ const substrateApi = this.substrateApi;
192
+ const defaultInfo = this.baseInfo;
193
+ const chainInfo = this.chainInfo;
194
+ await substrateApi.isReady;
195
+ const unsub = await substrateApi.api.query.parachainStaking.nominatorState.multi(useAddresses, async ledgers => {
196
+ if (cancel) {
197
+ unsub();
198
+ return;
199
+ }
200
+ if (ledgers) {
201
+ await Promise.all(ledgers.map(async (_nominatorState, i) => {
202
+ const nominatorState = _nominatorState.toPrimitive();
203
+ const owner = (0, _utils3.reformatAddress)(useAddresses[i], 42);
204
+ if (nominatorState) {
205
+ const nominatorMetadata = await this.parseNominatorMetadata(chainInfo, owner, substrateApi, nominatorState);
206
+ resultCallback({
207
+ ...defaultInfo,
208
+ ...nominatorMetadata,
209
+ address: owner,
210
+ type: this.type
211
+ });
212
+ } else {
213
+ resultCallback({
214
+ ...defaultInfo,
215
+ type: this.type,
216
+ address: owner,
217
+ balanceToken: this.nativeToken.slug,
218
+ totalStake: '0',
219
+ activeStake: '0',
220
+ unstakeBalance: '0',
221
+ status: _types.EarningStatus.NOT_STAKING,
222
+ isBondedBefore: false,
223
+ nominations: [],
224
+ unstakings: []
225
+ });
226
+ }
227
+ }));
228
+ }
229
+ });
230
+ return () => {
231
+ cancel = true;
232
+ unsub();
233
+ };
234
+ }
235
+ async checkAccountHaveStake(useAddresses) {
236
+ var _substrateApi$api$que, _substrateApi$api$que2, _substrateApi$api$que3;
237
+ const result = [];
238
+ const substrateApi = await this.substrateApi.isReady;
239
+ const ledgers = await ((_substrateApi$api$que = substrateApi.api.query.parachainStaking) === null || _substrateApi$api$que === void 0 ? void 0 : (_substrateApi$api$que2 = _substrateApi$api$que.nominatorState) === null || _substrateApi$api$que2 === void 0 ? void 0 : (_substrateApi$api$que3 = _substrateApi$api$que2.multi) === null || _substrateApi$api$que3 === void 0 ? void 0 : _substrateApi$api$que3.call(_substrateApi$api$que2, useAddresses));
240
+ if (!ledgers) {
241
+ return [];
242
+ }
243
+ for (let i = 0; i < useAddresses.length; i++) {
244
+ const owner = useAddresses[i];
245
+ const nominatorState = ledgers[i].toPrimitive();
246
+ if (nominatorState && nominatorState.total > 0) {
247
+ result.push(owner);
248
+ }
249
+ }
250
+ return result;
251
+ }
252
+
253
+ /* Subscribe pool position */
254
+
255
+ /* Get pool targets */
256
+ async getPoolTargets() {
257
+ const apiProps = await this.substrateApi.isReady;
258
+ const substrateIdentityApi = this.substrateIdentityApi;
259
+ const allCollators = [];
260
+ const [_allCollators, _selectedCandidates] = await Promise.all([apiProps.api.query.parachainStaking.candidateInfo.entries(),
261
+ // use it when energy support collatorCommission
262
+ // apiProps.api.query.parachainStaking.collatorCommission(),
263
+ apiProps.api.query.parachainStaking.selectedCandidates()]);
264
+ const maxNominationPerCollator = apiProps.api.consts.parachainStaking.maxTopNominationsPerCandidate.toString();
265
+ const selectedCollators = _selectedCandidates.toPrimitive();
266
+ for (const collator of _allCollators) {
267
+ const _collatorAddress = collator[0].toHuman();
268
+ const collatorAddress = _collatorAddress[0];
269
+ const collatorInfo = collator[1].toPrimitive();
270
+ const bnTotalStake = new _util.BN(collatorInfo.totalCounted);
271
+ const bnOwnStake = new _util.BN(collatorInfo.bond);
272
+ const bnOtherStake = bnTotalStake.sub(bnOwnStake);
273
+ const bnMinBond = new _util.BN(collatorInfo.lowestTopNominationAmount);
274
+ const maxNominatorRewarded = parseInt(maxNominationPerCollator);
275
+ if (selectedCollators.includes(collatorAddress)) {
276
+ allCollators.push({
277
+ commission: 0,
278
+ expectedReturn: 0,
279
+ address: collatorAddress,
280
+ totalStake: bnTotalStake.toString(),
281
+ ownStake: bnOwnStake.toString(),
282
+ otherStake: bnOtherStake.toString(),
283
+ nominatorCount: collatorInfo.nominationCount,
284
+ blocked: false,
285
+ isVerified: false,
286
+ minBond: bnMinBond.toString(),
287
+ chain: this.chain,
288
+ isCrowded: collatorInfo.nominationCount >= maxNominatorRewarded
289
+ });
290
+ }
291
+ }
292
+ const extraInfoMap = {};
293
+ await Promise.all(allCollators.map(async collator => {
294
+ const [_info, [identity, isReasonable]] = await Promise.all([apiProps.api.query.parachainStaking.candidateInfo(collator.address), (0, _utils2.parseIdentity)(substrateIdentityApi, collator.address)]);
295
+ const rawInfo = _info.toHuman();
296
+ const active = (rawInfo === null || rawInfo === void 0 ? void 0 : rawInfo.status) === 'Active';
297
+ extraInfoMap[collator.address] = {
298
+ identity,
299
+ isVerified: isReasonable,
300
+ active
301
+ };
302
+ }));
303
+ for (const validator of allCollators) {
304
+ validator.blocked = !extraInfoMap[validator.address].active;
305
+ validator.identity = extraInfoMap[validator.address].identity;
306
+ validator.isVerified = extraInfoMap[validator.address].isVerified;
307
+ }
308
+ return allCollators;
309
+ }
310
+
311
+ /* Get pool targets */
312
+
313
+ /* Join pool action */
314
+
315
+ async createJoinExtrinsic(data, positionInfo) {
316
+ const {
317
+ amount,
318
+ selectedValidators
319
+ } = data;
320
+ const apiPromise = await this.substrateApi.isReady;
321
+ const binaryAmount = new _util.BN(amount);
322
+ const selectedCollatorInfo = selectedValidators[0];
323
+ const {
324
+ address: selectedCollatorAddress,
325
+ nominatorCount: selectedCollatorNominatorCount
326
+ } = selectedCollatorInfo;
327
+ const compoundResult = extrinsic => {
328
+ return Promise.resolve([extrinsic, {
329
+ slug: this.nativeToken.slug,
330
+ amount: '0'
331
+ }]);
332
+ };
333
+ if (!positionInfo) {
334
+ const extrinsic = apiPromise.api.tx.parachainStaking.nominate(selectedCollatorAddress, binaryAmount, new _util.BN(selectedCollatorNominatorCount), 0);
335
+ return compoundResult(extrinsic);
336
+ }
337
+ const {
338
+ bondedValidators,
339
+ nominationCount
340
+ } = (0, _utils.getBondedValidators)(positionInfo.nominations);
341
+ const parsedSelectedCollatorAddress = (0, _utils3.reformatAddress)(selectedCollatorInfo.address, 0);
342
+ if (!bondedValidators.includes(parsedSelectedCollatorAddress)) {
343
+ const extrinsic = apiPromise.api.tx.parachainStaking.nominate(selectedCollatorAddress, binaryAmount, new _util.BN(selectedCollatorNominatorCount), nominationCount);
344
+ return compoundResult(extrinsic);
345
+ } else {
346
+ const extrinsic = apiPromise.api.tx.parachainStaking.bondExtra(selectedCollatorAddress, binaryAmount);
347
+ return compoundResult(extrinsic);
348
+ }
349
+ }
350
+
351
+ /* Join pool action */
352
+
353
+ /* Leave pool action */
354
+
355
+ async handleYieldUnstake(amount, address, selectedTarget) {
356
+ const apiPromise = await this.substrateApi.isReady;
357
+ const binaryAmount = new _util.BN(amount);
358
+ const poolPosition = await this.getPoolPosition(address);
359
+ if (!selectedTarget || !poolPosition) {
360
+ return Promise.reject(new _TransactionError.TransactionError(_types.BasicTxErrorType.INVALID_PARAMS));
361
+ }
362
+ const unstakeAll = (0, _utils.isUnstakeAll)(selectedTarget, poolPosition.nominations, amount);
363
+ let extrinsic;
364
+ if (!unstakeAll) {
365
+ extrinsic = apiPromise.api.tx.parachainStaking.scheduleNominatorUnbond(selectedTarget, binaryAmount);
366
+ } else {
367
+ extrinsic = apiPromise.api.tx.parachainStaking.scheduleRevokeNomination(selectedTarget);
368
+ }
369
+ return [_KoniTypes.ExtrinsicType.STAKING_UNBOND, extrinsic];
370
+ }
371
+
372
+ /* Leave pool action */
373
+
374
+ /* Other action */
375
+
376
+ async handleYieldCancelUnstake(params) {
377
+ const {
378
+ selectedUnstaking
379
+ } = params;
380
+ const chainApi = await this.substrateApi.isReady;
381
+ return chainApi.api.tx.parachainStaking.cancelNominationRequest(selectedUnstaking.validatorAddress);
382
+ }
383
+ async handleYieldWithdraw(address, unstakingInfo) {
384
+ const collatorAddress = unstakingInfo.validatorAddress;
385
+ if (!collatorAddress) {
386
+ return Promise.reject(new _TransactionError.TransactionError(_types.BasicTxErrorType.INVALID_PARAMS));
387
+ }
388
+ const chainApi = await this.substrateApi.isReady;
389
+ return chainApi.api.tx.parachainStaking.executeNominationRequest(address, collatorAddress);
390
+ }
391
+
392
+ /* Other actions */
393
+ }
394
+ exports.default = EnergyNativeStakingPoolHandler;
@@ -16,6 +16,12 @@ Object.defineProperty(exports, "AstarNativeStakingPoolHandler", {
16
16
  return _astar.default;
17
17
  }
18
18
  });
19
+ Object.defineProperty(exports, "EnergyNativeStakingPoolHandler", {
20
+ enumerable: true,
21
+ get: function () {
22
+ return _energy.default;
23
+ }
24
+ });
19
25
  Object.defineProperty(exports, "ParaNativeStakingPoolHandler", {
20
26
  enumerable: true,
21
27
  get: function () {
@@ -45,4 +51,5 @@ var _astar = _interopRequireDefault(require("./astar"));
45
51
  var _relayChain = _interopRequireDefault(require("./relay-chain"));
46
52
  var _paraChain = _interopRequireDefault(require("./para-chain"));
47
53
  var _tao = _interopRequireDefault(require("./tao"));
48
- var _dtao = _interopRequireDefault(require("./dtao"));
54
+ var _dtao = _interopRequireDefault(require("./dtao"));
55
+ var _energy = _interopRequireDefault(require("./energy"));
@@ -100,6 +100,9 @@ class EarningService {
100
100
  if (_constants2._STAKING_CHAIN_GROUP.mythos.includes(chain)) {
101
101
  handlers.push(new _mythos.default(this.state, chain));
102
102
  }
103
+ if (_constants2._STAKING_CHAIN_GROUP.energy.includes(chain)) {
104
+ handlers.push(new _handlers.EnergyNativeStakingPoolHandler(this.state, chain));
105
+ }
103
106
  if (_constants2._STAKING_CHAIN_GROUP.nominationPool.includes(chain)) {
104
107
  const ahChain = ahMapChain[chain];
105
108
  if (ahChain) {
@@ -120,6 +120,8 @@ function isActionFromValidator(stakingType, chain) {
120
120
  return true;
121
121
  } else if (_constants._STAKING_CHAIN_GROUP.mythos.includes(chain)) {
122
122
  return true;
123
+ } else if (_constants._STAKING_CHAIN_GROUP.energy.includes(chain)) {
124
+ return true;
123
125
  }
124
126
  return false;
125
127
  }
@@ -124,6 +124,9 @@ function getExplorerLink(chainInfo, value, type) {
124
124
  const address = (0, _util.u8aToHex)((0, _utilCrypto.decodeAddress)(value));
125
125
  return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}${route}/${address}`;
126
126
  }
127
+ if (chainInfo.slug === 'xode') {
128
+ return undefined;
129
+ }
127
130
  return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}${route}/${value}`;
128
131
  }
129
132
  if (explorerLink && (0, _util.isHex)((0, _util.hexAddPrefix)(value))) {
@@ -131,6 +134,9 @@ function getExplorerLink(chainInfo, value, type) {
131
134
  if (chainInfo.slug === 'tangle') {
132
135
  return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}extrinsic/${value}${route}/${value}`;
133
136
  }
137
+ if (chainInfo.slug === 'xode') {
138
+ return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}polkadot-chain-transaction?search=${value}`;
139
+ }
134
140
  if (chainInfo.slug === 'truth_network') {
135
141
  // getTransactionId(value)
136
142
  // .then((transactionId) => {
@@ -6,18 +6,18 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.setupApiSDK = setupApiSDK;
8
8
  var _constants = require("@subwallet/extension-base/constants");
9
- var _utils = require("@subwallet/extension-base/services/chain-service/utils");
10
9
  var _subwalletServicesSdk = _interopRequireDefault(require("@subwallet-monorepos/subwallet-services-sdk"));
11
10
  var _environment = require("./environment");
12
11
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
13
12
  // SPDX-License-Identifier: Apache-2.0
14
13
 
14
+ const CHAIN_LIST_VERSION = process.env.CHAIN_LIST_VERSION;
15
15
  function setupApiSDK() {
16
16
  _subwalletServicesSdk.default.updateConfig({
17
17
  appVersion: _constants.APP_VERSION,
18
18
  baseUrl: _constants.BACKEND_API_URL,
19
19
  platform: _environment.TARGET_ENV,
20
- chainListVersion: _utils.ChainListVersion
20
+ chainListVersion: CHAIN_LIST_VERSION
21
21
  });
22
22
 
23
23
  // Custom the price history API with other different base URL
@@ -206,6 +206,8 @@ export function getYieldAvailableActionsByType(yieldPoolInfo) {
206
206
  const chain = yieldPoolInfo.chain;
207
207
  if (_STAKING_CHAIN_GROUP.para.includes(chain)) {
208
208
  return [YieldAction.STAKE, YieldAction.UNSTAKE, YieldAction.WITHDRAW, YieldAction.CANCEL_UNSTAKE];
209
+ } else if (_STAKING_CHAIN_GROUP.energy.includes(chain)) {
210
+ return [YieldAction.STAKE, YieldAction.UNSTAKE, YieldAction.WITHDRAW, YieldAction.CANCEL_UNSTAKE];
209
211
  } else if (_STAKING_CHAIN_GROUP.astar.includes(chain)) {
210
212
  return [YieldAction.STAKE, YieldAction.CLAIM_REWARD, YieldAction.UNSTAKE, YieldAction.WITHDRAW];
211
213
  } else if (_STAKING_CHAIN_GROUP.amplitude.includes(chain)) {
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "./cjs/detectPackage.js"
18
18
  ],
19
19
  "type": "module",
20
- "version": "1.3.56-0",
20
+ "version": "1.3.58-0",
21
21
  "main": "./cjs/index.js",
22
22
  "module": "./index.js",
23
23
  "types": "./index.d.ts",
@@ -1171,6 +1171,11 @@
1171
1171
  "require": "./cjs/services/earning-service/handlers/native-staking/dtao.js",
1172
1172
  "default": "./services/earning-service/handlers/native-staking/dtao.js"
1173
1173
  },
1174
+ "./services/earning-service/handlers/native-staking/energy": {
1175
+ "types": "./services/earning-service/handlers/native-staking/energy.d.ts",
1176
+ "require": "./cjs/services/earning-service/handlers/native-staking/energy.js",
1177
+ "default": "./services/earning-service/handlers/native-staking/energy.js"
1178
+ },
1174
1179
  "./services/earning-service/handlers/native-staking/mythos": {
1175
1180
  "types": "./services/earning-service/handlers/native-staking/mythos.d.ts",
1176
1181
  "require": "./cjs/services/earning-service/handlers/native-staking/mythos.js",
@@ -2873,11 +2878,11 @@
2873
2878
  "@sora-substrate/type-definitions": "^1.17.7",
2874
2879
  "@substrate/connect": "^0.8.9",
2875
2880
  "@subwallet-monorepos/subwallet-services-sdk": "^0.1.8",
2876
- "@subwallet/chain-list": "0.2.114",
2877
- "@subwallet/extension-base": "^1.3.56-0",
2878
- "@subwallet/extension-chains": "^1.3.56-0",
2879
- "@subwallet/extension-dapp": "^1.3.56-0",
2880
- "@subwallet/extension-inject": "^1.3.56-0",
2881
+ "@subwallet/chain-list": "0.2.115",
2882
+ "@subwallet/extension-base": "^1.3.58-0",
2883
+ "@subwallet/extension-chains": "^1.3.58-0",
2884
+ "@subwallet/extension-dapp": "^1.3.58-0",
2885
+ "@subwallet/extension-inject": "^1.3.58-0",
2881
2886
  "@subwallet/keyring": "^0.1.13",
2882
2887
  "@subwallet/ui-keyring": "^0.1.13",
2883
2888
  "@ton/core": "^0.56.3",
package/packageInfo.js CHANGED
@@ -7,5 +7,5 @@ export const packageInfo = {
7
7
  name: '@subwallet/extension-base',
8
8
  path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto',
9
9
  type: 'esm',
10
- version: '1.3.56-0'
10
+ version: '1.3.58-0'
11
11
  };
@@ -29,8 +29,8 @@ export const _BALANCE_CHAIN_GROUP = {
29
29
  kintsugi: ['kintsugi', 'interlay', 'kintsugi_test', 'mangatax_para'],
30
30
  genshiro: ['genshiro_testnet', 'genshiro'],
31
31
  equilibrium_parachain: ['equilibrium_parachain'],
32
- bifrost: ['bifrost', 'acala', 'karura', 'acala_testnet', 'pioneer', 'bitcountry', 'bifrost_dot', 'hydradx_main', 'hydradx_rococo', 'pendulum', 'amplitude', 'continuum_network', 'truth_network', 'jamton'],
33
- statemine: ['statemine', 'astar', 'shiden', 'statemint', 'crabParachain', 'darwinia2', 'parallel', 'calamari', 'manta_network', 'rococo_assethub', 'liberlandTest', 'liberland', 'dentnet', 'pangolin', 'crust', 'phala', 'shibuya', 'dbcchain', 'westend_assethub', 'chainflip_assethub', 'origintrail'],
32
+ bifrost: ['bifrost', 'acala', 'karura', 'acala_testnet', 'pioneer', 'bitcountry', 'bifrost_dot', 'hydradx_main', 'hydradx_rococo', 'pendulum', 'amplitude', 'continuum_network', 'truth_network', 'jamton', 'hydradx_hollarnet'],
33
+ statemine: ['statemine', 'astar', 'shiden', 'statemint', 'crabParachain', 'darwinia2', 'parallel', 'calamari', 'manta_network', 'rococo_assethub', 'liberlandTest', 'liberland', 'dentnet', 'pangolin', 'crust', 'phala', 'shibuya', 'dbcchain', 'westend_assethub', 'chainflip_assethub', 'origintrail', 'xode'],
34
34
  kusama: ['kusama', 'kintsugi', 'kintsugi_test', 'interlay', 'acala', 'statemint', 'karura', 'bifrost'],
35
35
  // perhaps there are some runtime updates
36
36
  centrifuge: ['centrifuge'],
@@ -107,8 +107,12 @@ export const _STAKING_ERA_LENGTH_MAP = {
107
107
  analog_timechain: 12,
108
108
  muse_testnet: 25 * 6 / 60 / 60,
109
109
  // 25 blocks per session
110
- mythos: 24
110
+ mythos: 24,
111
+ energy_web_x_testnet: 22 * 12 / 3600,
112
+ // 22 blocks per era, 1 block per 12s
113
+ energy_web_x: 7200 * 12 / 3600 // 24 hours, 7200 blocks per era, 1 block per 12s
111
114
  };
115
+
112
116
  export const _EXPECTED_BLOCK_TIME = {
113
117
  // in seconds
114
118
  alephTest: 1,
@@ -142,7 +146,9 @@ export const _EXPECTED_BLOCK_TIME = {
142
146
  avail_mainnet: 20,
143
147
  dentnet: 3,
144
148
  muse_testnet: 6,
145
- mythos: 6
149
+ mythos: 6,
150
+ energy_web_x_testnet: 12,
151
+ energy_web_x: 12
146
152
  };
147
153
  export const _PARACHAIN_INFLATION_DISTRIBUTION = {
148
154
  moonbeam: {
@@ -255,11 +261,11 @@ export const _TRANSFER_CHAIN_GROUP = {
255
261
  genshiro: ['genshiro_testnet', 'genshiro', 'equilibrium_parachain'],
256
262
  // crab: ['crab', 'pangolin'],
257
263
  bitcountry: ['pioneer', 'bitcountry'],
258
- statemine: ['statemint', 'statemine', 'darwinia2', 'astar', 'shiden', 'shibuya', 'parallel', 'liberland', 'liberlandTest', 'dentnet', 'dbcchain', 'westend_assethub', 'chainflip_assethub', 'origintrail'],
264
+ statemine: ['statemint', 'statemine', 'darwinia2', 'astar', 'shiden', 'shibuya', 'parallel', 'liberland', 'liberlandTest', 'dentnet', 'dbcchain', 'westend_assethub', 'chainflip_assethub', 'origintrail', 'xode'],
259
265
  riochain: ['riochain'],
260
266
  sora_substrate: ['sora_substrate'],
261
267
  avail: ['kate', 'goldberg_testnet'],
262
- pendulum: ['pendulum', 'amplitude', 'amplitude_test', 'hydradx_main', 'bifrost', 'bifrost_dot', 'jamton'],
268
+ pendulum: ['pendulum', 'amplitude', 'amplitude_test', 'hydradx_main', 'bifrost', 'bifrost_dot', 'jamton', 'hydradx_hollarnet'],
263
269
  centrifuge: ['centrifuge'],
264
270
  disable_transfer: ['crab', 'pangolin'],
265
271
  truth: ['truth_network']
@@ -1,5 +1,5 @@
1
1
  import { _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types';
2
- export declare const ChainListVersion = "0.2.114";
2
+ export declare const ChainListVersion = "0.2.115";
3
3
  export interface PatchInfo {
4
4
  patchVersion: string;
5
5
  appliedVersion: string;
@@ -5,7 +5,7 @@ const PRODUCTION_BRANCHES = ['master', 'webapp', 'webapp-dev'];
5
5
  const branchName = process.env.BRANCH_NAME || 'subwallet-dev';
6
6
  const fetchDomain = process.env.PATCH_CHAIN_LIST_URL || (PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'https://chain-list-assets.subwallet.app' : 'https://dev.sw-chain-list-assets.pages.dev');
7
7
  const fetchFile = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'list.json' : 'preview.json';
8
- export const ChainListVersion = '0.2.114'; // update this when build chain-list
8
+ export const ChainListVersion = '0.2.115'; // update this when build chain-list
9
9
 
10
10
  // todo: move this interface to chainlist
11
11
 
@@ -13,6 +13,7 @@ export declare const _STAKING_CHAIN_GROUP: {
13
13
  krest_network: string[];
14
14
  manta: string[];
15
15
  bittensor: string[];
16
+ energy: string[];
16
17
  mythos: string[];
17
18
  };
18
19
  export declare const TON_CHAINS: string[];
@@ -18,6 +18,7 @@ export const _STAKING_CHAIN_GROUP = {
18
18
  krest_network: ['krest_network'],
19
19
  manta: ['manta_network'],
20
20
  bittensor: ['bittensor', 'bittensor_testnet'],
21
+ energy: ['energy_web_x_testnet', 'energy_web_x'],
21
22
  mythos: ['mythos', 'muse_testnet']
22
23
  };
23
24
  export const TON_CHAINS = ['ton', 'ton_testnet'];
@@ -0,0 +1,30 @@
1
+ import { _ChainInfo } from '@subwallet/chain-list/types';
2
+ import { ExtrinsicType, UnstakingInfo } from '@subwallet/extension-base/background/KoniTypes';
3
+ import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
4
+ import { BaseYieldPositionInfo, PalletParachainStakingDelegationInfo, PalletParachainStakingRequestType, StakeCancelWithdrawalParams, SubmitJoinNativeStaking, TransactionData, ValidatorInfo, YieldPoolInfo, YieldPositionInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
5
+ import BaseParaNativeStakingPoolHandler from './base-para';
6
+ declare type PalletEnergyStakingNominationInfo = PalletParachainStakingDelegationInfo;
7
+ interface PalletEnergyStakingNominator {
8
+ id: string;
9
+ nominations: PalletEnergyStakingNominationInfo[];
10
+ total: number;
11
+ lessTotal: number;
12
+ status: number;
13
+ }
14
+ export interface PalletEnergyStakingNominationRequestsScheduledRequest {
15
+ nominator: string;
16
+ whenExecutable: number;
17
+ action: Record<PalletParachainStakingRequestType, number>;
18
+ }
19
+ export default class EnergyNativeStakingPoolHandler extends BaseParaNativeStakingPoolHandler {
20
+ subscribePoolInfo(callback: (data: YieldPoolInfo) => void): Promise<VoidFunction>;
21
+ parseNominatorMetadata(chainInfo: _ChainInfo, address: string, substrateApi: _SubstrateApi, nominatorState: PalletEnergyStakingNominator): Promise<Omit<YieldPositionInfo, keyof BaseYieldPositionInfo>>;
22
+ subscribePoolPosition(useAddresses: string[], resultCallback: (rs: YieldPositionInfo) => void): Promise<VoidFunction>;
23
+ checkAccountHaveStake(useAddresses: string[]): Promise<string[]>;
24
+ getPoolTargets(): Promise<ValidatorInfo[]>;
25
+ createJoinExtrinsic(data: SubmitJoinNativeStaking, positionInfo?: YieldPositionInfo): Promise<[TransactionData, YieldTokenBaseInfo]>;
26
+ handleYieldUnstake(amount: string, address: string, selectedTarget?: string): Promise<[ExtrinsicType, TransactionData]>;
27
+ handleYieldCancelUnstake(params: StakeCancelWithdrawalParams): Promise<TransactionData>;
28
+ handleYieldWithdraw(address: string, unstakingInfo: UnstakingInfo): Promise<TransactionData>;
29
+ }
30
+ export {};
@@ -0,0 +1,386 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
5
+ import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
+ import { getBondedValidators, getEarningStatusByNominations, isUnstakeAll } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
7
+ import { _EXPECTED_BLOCK_TIME, _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants';
8
+ import { parseIdentity } from '@subwallet/extension-base/services/earning-service/utils';
9
+ import { BasicTxErrorType, EarningStatus, UnstakingStatus } from '@subwallet/extension-base/types';
10
+ import { balanceFormatter, formatNumber, parseRawNumber, reformatAddress } from '@subwallet/extension-base/utils';
11
+ import { BN, BN_ZERO } from '@polkadot/util';
12
+ import BaseParaNativeStakingPoolHandler from "./base-para.js";
13
+ export default class EnergyNativeStakingPoolHandler extends BaseParaNativeStakingPoolHandler {
14
+ /* Subscribe pool info */
15
+
16
+ async subscribePoolInfo(callback) {
17
+ let cancel = false;
18
+ const chainApi = this.substrateApi;
19
+ const nativeToken = this.nativeToken;
20
+ const defaultCallback = async () => {
21
+ const data = {
22
+ ...this.baseInfo,
23
+ type: this.type,
24
+ metadata: {
25
+ ...this.metadataInfo,
26
+ description: this.getDescription()
27
+ }
28
+ };
29
+ const poolInfo = await this.getPoolInfo();
30
+ !poolInfo && callback(data);
31
+ };
32
+ if (!this.isActive) {
33
+ await defaultCallback();
34
+ return () => {
35
+ cancel = true;
36
+ };
37
+ }
38
+ await defaultCallback();
39
+ await chainApi.isReady;
40
+ const unsub = await chainApi.api.query.parachainStaking.era(async _era => {
41
+ var _chainApi$api$consts, _chainApi$api$consts$, _chainApi$api$consts$2, _chainApi$api$consts$3, _chainApi$api$query$p;
42
+ if (cancel) {
43
+ unsub();
44
+ return;
45
+ }
46
+ const eraObj = _era.toHuman();
47
+ const era = parseRawNumber(eraObj.current);
48
+ const maxNominations = (_chainApi$api$consts = chainApi.api.consts) === null || _chainApi$api$consts === void 0 ? void 0 : (_chainApi$api$consts$ = _chainApi$api$consts.parachainStaking) === null || _chainApi$api$consts$ === void 0 ? void 0 : (_chainApi$api$consts$2 = _chainApi$api$consts$.maxNominationsPerNominator) === null || _chainApi$api$consts$2 === void 0 ? void 0 : _chainApi$api$consts$2.toString();
49
+ const maxTopNominatorsPerCollator = (_chainApi$api$consts$3 = chainApi.api.consts.parachainStaking.maxTopNominationsPerCandidate) === null || _chainApi$api$consts$3 === void 0 ? void 0 : _chainApi$api$consts$3.toPrimitive();
50
+ const [_totalStake, unstakingDelay] = await Promise.all([(_chainApi$api$query$p = chainApi.api.query.parachainStaking) === null || _chainApi$api$query$p === void 0 ? void 0 : _chainApi$api$query$p.staked(era), chainApi.api.query.parachainStaking.delay()]);
51
+ const totalStake = _totalStake ? new BN(_totalStake.toString()) : BN_ZERO;
52
+ const eraTime = _STAKING_ERA_LENGTH_MAP[this.chain] || _STAKING_ERA_LENGTH_MAP.default; // in hours
53
+ const unstakingPeriod = parseInt(unstakingDelay.toString()) * eraTime;
54
+ const minStake = '0';
55
+ const minToHuman = formatNumber(minStake.toString(), nativeToken.decimals || 0, balanceFormatter);
56
+ const data = {
57
+ ...this.baseInfo,
58
+ type: this.type,
59
+ metadata: {
60
+ ...this.metadataInfo,
61
+ description: this.getDescription(minToHuman)
62
+ },
63
+ statistic: {
64
+ assetEarning: [{
65
+ slug: this.nativeToken.slug
66
+ }],
67
+ maxCandidatePerFarmer: parseInt(maxNominations),
68
+ maxWithdrawalRequestPerFarmer: 1,
69
+ // by default
70
+ earningThreshold: {
71
+ join: minStake.toString(),
72
+ defaultUnstake: '0',
73
+ fastUnstake: '0'
74
+ },
75
+ farmerCount: 0,
76
+ // TODO recheck
77
+ era,
78
+ eraTime,
79
+ totalApy: undefined,
80
+ // not have
81
+ tvl: totalStake.toString(),
82
+ unstakingPeriod: unstakingPeriod
83
+ },
84
+ maxPoolMembers: maxTopNominatorsPerCollator
85
+ };
86
+ callback(data);
87
+ });
88
+ return () => {
89
+ cancel = true;
90
+ unsub();
91
+ };
92
+ }
93
+
94
+ /* Subscribe pool info */
95
+
96
+ /* Subscribe pool position */
97
+
98
+ async parseNominatorMetadata(chainInfo, address, substrateApi, nominatorState) {
99
+ const nominationList = [];
100
+ const unstakingMap = {};
101
+ const substrateIdentityApi = this.substrateIdentityApi;
102
+ let bnTotalActiveStake = BN_ZERO;
103
+ let bnTotalStake = BN_ZERO;
104
+ let bnTotalUnstaking = BN_ZERO;
105
+ const _eraInfo = await substrateApi.api.query.parachainStaking.era();
106
+ const roundInfo = _eraInfo.toPrimitive();
107
+ const currentRound = roundInfo.current;
108
+ await Promise.all(nominatorState.nominations.map(async nomination => {
109
+ const [_nominationScheduledRequests, [identity], _collatorInfo, _currentBlock, _currentTimestamp] = await Promise.all([substrateApi.api.query.parachainStaking.nominationScheduledRequests(nomination.owner), parseIdentity(substrateIdentityApi, nomination.owner), substrateApi.api.query.parachainStaking.candidateInfo(nomination.owner), substrateApi.api.query.system.number(), substrateApi.api.query.timestamp.now()]);
110
+ const currentBlock = _currentBlock.toPrimitive();
111
+ const currentTimestamp = _currentTimestamp.toPrimitive();
112
+ const collatorInfo = _collatorInfo.toPrimitive();
113
+ const minNomination = collatorInfo === null || collatorInfo === void 0 ? void 0 : collatorInfo.lowestTopNominationAmount.toString();
114
+ const nominationScheduledRequests = _nominationScheduledRequests.toPrimitive();
115
+ let hasUnstaking = false;
116
+ let nominationStatus = EarningStatus.NOT_EARNING;
117
+
118
+ // parse unstaking info
119
+ if (nominationScheduledRequests) {
120
+ for (const scheduledRequest of nominationScheduledRequests) {
121
+ if (reformatAddress(scheduledRequest.nominator, 0) === reformatAddress(address, 0)) {
122
+ // add network prefix
123
+ const isClaimable = scheduledRequest.whenExecutable - parseInt(currentRound) <= 0;
124
+ const remainingEra = scheduledRequest.whenExecutable - parseInt(currentRound);
125
+ const waitingTime = remainingEra * _STAKING_ERA_LENGTH_MAP[chainInfo.slug];
126
+ const claimable = Object.values(scheduledRequest.action)[0];
127
+
128
+ // noted: target timestamp in parachainStaking easily volatile if block time volatile
129
+ const targetBlock = remainingEra * parseInt(roundInfo.length) + parseInt(roundInfo.first);
130
+ const remainingBlock = targetBlock - currentBlock;
131
+ const targetTimestampMs = remainingBlock * _EXPECTED_BLOCK_TIME[chainInfo.slug] * 1000 + currentTimestamp;
132
+ unstakingMap[nomination.owner] = {
133
+ chain: chainInfo.slug,
134
+ status: isClaimable ? UnstakingStatus.CLAIMABLE : UnstakingStatus.UNLOCKING,
135
+ validatorAddress: nomination.owner,
136
+ claimable: claimable.toString(),
137
+ waitingTime,
138
+ targetTimestampMs: targetTimestampMs
139
+ };
140
+ hasUnstaking = true;
141
+ break; // only handle 1 scheduledRequest per collator
142
+ }
143
+ }
144
+ }
145
+
146
+ const bnStake = new BN(nomination.amount);
147
+ const bnUnstakeBalance = unstakingMap[nomination.owner] ? new BN(unstakingMap[nomination.owner].claimable) : BN_ZERO;
148
+ const bnActiveStake = bnStake.sub(bnUnstakeBalance);
149
+ if (bnActiveStake.gt(BN_ZERO) && bnActiveStake.gte(new BN(minNomination))) {
150
+ nominationStatus = EarningStatus.EARNING_REWARD;
151
+ }
152
+ bnTotalActiveStake = bnTotalActiveStake.add(bnActiveStake);
153
+ bnTotalStake = bnTotalStake.add(bnStake);
154
+ bnTotalUnstaking = bnTotalUnstaking.add(bnUnstakeBalance);
155
+ nominationList.push({
156
+ chain: chainInfo.slug,
157
+ status: nominationStatus,
158
+ validatorAddress: nomination.owner,
159
+ validatorIdentity: identity,
160
+ activeStake: bnActiveStake.toString(),
161
+ hasUnstaking,
162
+ validatorMinStake: collatorInfo.lowestTopNominationAmount.toString()
163
+ });
164
+ }));
165
+ const stakingStatus = getEarningStatusByNominations(bnTotalActiveStake, nominationList);
166
+ const totalStake = bnTotalStake.toString();
167
+ const activeStake = bnTotalActiveStake.toString();
168
+ const unstakingBalance = bnTotalUnstaking.toString();
169
+ const tokenInfo = this.state.chainService.getAssetBySlug(this.nativeToken.slug);
170
+ await this.createWithdrawNotifications(Object.values(unstakingMap), tokenInfo, address);
171
+ return {
172
+ status: stakingStatus,
173
+ totalStake,
174
+ balanceToken: this.nativeToken.slug,
175
+ activeStake: activeStake,
176
+ unstakeBalance: unstakingBalance,
177
+ isBondedBefore: !!nominationList.length,
178
+ nominations: nominationList,
179
+ unstakings: Object.values(unstakingMap)
180
+ };
181
+ }
182
+ async subscribePoolPosition(useAddresses, resultCallback) {
183
+ let cancel = false;
184
+ const substrateApi = this.substrateApi;
185
+ const defaultInfo = this.baseInfo;
186
+ const chainInfo = this.chainInfo;
187
+ await substrateApi.isReady;
188
+ const unsub = await substrateApi.api.query.parachainStaking.nominatorState.multi(useAddresses, async ledgers => {
189
+ if (cancel) {
190
+ unsub();
191
+ return;
192
+ }
193
+ if (ledgers) {
194
+ await Promise.all(ledgers.map(async (_nominatorState, i) => {
195
+ const nominatorState = _nominatorState.toPrimitive();
196
+ const owner = reformatAddress(useAddresses[i], 42);
197
+ if (nominatorState) {
198
+ const nominatorMetadata = await this.parseNominatorMetadata(chainInfo, owner, substrateApi, nominatorState);
199
+ resultCallback({
200
+ ...defaultInfo,
201
+ ...nominatorMetadata,
202
+ address: owner,
203
+ type: this.type
204
+ });
205
+ } else {
206
+ resultCallback({
207
+ ...defaultInfo,
208
+ type: this.type,
209
+ address: owner,
210
+ balanceToken: this.nativeToken.slug,
211
+ totalStake: '0',
212
+ activeStake: '0',
213
+ unstakeBalance: '0',
214
+ status: EarningStatus.NOT_STAKING,
215
+ isBondedBefore: false,
216
+ nominations: [],
217
+ unstakings: []
218
+ });
219
+ }
220
+ }));
221
+ }
222
+ });
223
+ return () => {
224
+ cancel = true;
225
+ unsub();
226
+ };
227
+ }
228
+ async checkAccountHaveStake(useAddresses) {
229
+ var _substrateApi$api$que, _substrateApi$api$que2, _substrateApi$api$que3;
230
+ const result = [];
231
+ const substrateApi = await this.substrateApi.isReady;
232
+ const ledgers = await ((_substrateApi$api$que = substrateApi.api.query.parachainStaking) === null || _substrateApi$api$que === void 0 ? void 0 : (_substrateApi$api$que2 = _substrateApi$api$que.nominatorState) === null || _substrateApi$api$que2 === void 0 ? void 0 : (_substrateApi$api$que3 = _substrateApi$api$que2.multi) === null || _substrateApi$api$que3 === void 0 ? void 0 : _substrateApi$api$que3.call(_substrateApi$api$que2, useAddresses));
233
+ if (!ledgers) {
234
+ return [];
235
+ }
236
+ for (let i = 0; i < useAddresses.length; i++) {
237
+ const owner = useAddresses[i];
238
+ const nominatorState = ledgers[i].toPrimitive();
239
+ if (nominatorState && nominatorState.total > 0) {
240
+ result.push(owner);
241
+ }
242
+ }
243
+ return result;
244
+ }
245
+
246
+ /* Subscribe pool position */
247
+
248
+ /* Get pool targets */
249
+ async getPoolTargets() {
250
+ const apiProps = await this.substrateApi.isReady;
251
+ const substrateIdentityApi = this.substrateIdentityApi;
252
+ const allCollators = [];
253
+ const [_allCollators, _selectedCandidates] = await Promise.all([apiProps.api.query.parachainStaking.candidateInfo.entries(),
254
+ // use it when energy support collatorCommission
255
+ // apiProps.api.query.parachainStaking.collatorCommission(),
256
+ apiProps.api.query.parachainStaking.selectedCandidates()]);
257
+ const maxNominationPerCollator = apiProps.api.consts.parachainStaking.maxTopNominationsPerCandidate.toString();
258
+ const selectedCollators = _selectedCandidates.toPrimitive();
259
+ for (const collator of _allCollators) {
260
+ const _collatorAddress = collator[0].toHuman();
261
+ const collatorAddress = _collatorAddress[0];
262
+ const collatorInfo = collator[1].toPrimitive();
263
+ const bnTotalStake = new BN(collatorInfo.totalCounted);
264
+ const bnOwnStake = new BN(collatorInfo.bond);
265
+ const bnOtherStake = bnTotalStake.sub(bnOwnStake);
266
+ const bnMinBond = new BN(collatorInfo.lowestTopNominationAmount);
267
+ const maxNominatorRewarded = parseInt(maxNominationPerCollator);
268
+ if (selectedCollators.includes(collatorAddress)) {
269
+ allCollators.push({
270
+ commission: 0,
271
+ expectedReturn: 0,
272
+ address: collatorAddress,
273
+ totalStake: bnTotalStake.toString(),
274
+ ownStake: bnOwnStake.toString(),
275
+ otherStake: bnOtherStake.toString(),
276
+ nominatorCount: collatorInfo.nominationCount,
277
+ blocked: false,
278
+ isVerified: false,
279
+ minBond: bnMinBond.toString(),
280
+ chain: this.chain,
281
+ isCrowded: collatorInfo.nominationCount >= maxNominatorRewarded
282
+ });
283
+ }
284
+ }
285
+ const extraInfoMap = {};
286
+ await Promise.all(allCollators.map(async collator => {
287
+ const [_info, [identity, isReasonable]] = await Promise.all([apiProps.api.query.parachainStaking.candidateInfo(collator.address), parseIdentity(substrateIdentityApi, collator.address)]);
288
+ const rawInfo = _info.toHuman();
289
+ const active = (rawInfo === null || rawInfo === void 0 ? void 0 : rawInfo.status) === 'Active';
290
+ extraInfoMap[collator.address] = {
291
+ identity,
292
+ isVerified: isReasonable,
293
+ active
294
+ };
295
+ }));
296
+ for (const validator of allCollators) {
297
+ validator.blocked = !extraInfoMap[validator.address].active;
298
+ validator.identity = extraInfoMap[validator.address].identity;
299
+ validator.isVerified = extraInfoMap[validator.address].isVerified;
300
+ }
301
+ return allCollators;
302
+ }
303
+
304
+ /* Get pool targets */
305
+
306
+ /* Join pool action */
307
+
308
+ async createJoinExtrinsic(data, positionInfo) {
309
+ const {
310
+ amount,
311
+ selectedValidators
312
+ } = data;
313
+ const apiPromise = await this.substrateApi.isReady;
314
+ const binaryAmount = new BN(amount);
315
+ const selectedCollatorInfo = selectedValidators[0];
316
+ const {
317
+ address: selectedCollatorAddress,
318
+ nominatorCount: selectedCollatorNominatorCount
319
+ } = selectedCollatorInfo;
320
+ const compoundResult = extrinsic => {
321
+ return Promise.resolve([extrinsic, {
322
+ slug: this.nativeToken.slug,
323
+ amount: '0'
324
+ }]);
325
+ };
326
+ if (!positionInfo) {
327
+ const extrinsic = apiPromise.api.tx.parachainStaking.nominate(selectedCollatorAddress, binaryAmount, new BN(selectedCollatorNominatorCount), 0);
328
+ return compoundResult(extrinsic);
329
+ }
330
+ const {
331
+ bondedValidators,
332
+ nominationCount
333
+ } = getBondedValidators(positionInfo.nominations);
334
+ const parsedSelectedCollatorAddress = reformatAddress(selectedCollatorInfo.address, 0);
335
+ if (!bondedValidators.includes(parsedSelectedCollatorAddress)) {
336
+ const extrinsic = apiPromise.api.tx.parachainStaking.nominate(selectedCollatorAddress, binaryAmount, new BN(selectedCollatorNominatorCount), nominationCount);
337
+ return compoundResult(extrinsic);
338
+ } else {
339
+ const extrinsic = apiPromise.api.tx.parachainStaking.bondExtra(selectedCollatorAddress, binaryAmount);
340
+ return compoundResult(extrinsic);
341
+ }
342
+ }
343
+
344
+ /* Join pool action */
345
+
346
+ /* Leave pool action */
347
+
348
+ async handleYieldUnstake(amount, address, selectedTarget) {
349
+ const apiPromise = await this.substrateApi.isReady;
350
+ const binaryAmount = new BN(amount);
351
+ const poolPosition = await this.getPoolPosition(address);
352
+ if (!selectedTarget || !poolPosition) {
353
+ return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
354
+ }
355
+ const unstakeAll = isUnstakeAll(selectedTarget, poolPosition.nominations, amount);
356
+ let extrinsic;
357
+ if (!unstakeAll) {
358
+ extrinsic = apiPromise.api.tx.parachainStaking.scheduleNominatorUnbond(selectedTarget, binaryAmount);
359
+ } else {
360
+ extrinsic = apiPromise.api.tx.parachainStaking.scheduleRevokeNomination(selectedTarget);
361
+ }
362
+ return [ExtrinsicType.STAKING_UNBOND, extrinsic];
363
+ }
364
+
365
+ /* Leave pool action */
366
+
367
+ /* Other action */
368
+
369
+ async handleYieldCancelUnstake(params) {
370
+ const {
371
+ selectedUnstaking
372
+ } = params;
373
+ const chainApi = await this.substrateApi.isReady;
374
+ return chainApi.api.tx.parachainStaking.cancelNominationRequest(selectedUnstaking.validatorAddress);
375
+ }
376
+ async handleYieldWithdraw(address, unstakingInfo) {
377
+ const collatorAddress = unstakingInfo.validatorAddress;
378
+ if (!collatorAddress) {
379
+ return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
380
+ }
381
+ const chainApi = await this.substrateApi.isReady;
382
+ return chainApi.api.tx.parachainStaking.executeNominationRequest(address, collatorAddress);
383
+ }
384
+
385
+ /* Other actions */
386
+ }
@@ -4,3 +4,4 @@ export { default as RelayNativeStakingPoolHandler } from './relay-chain';
4
4
  export { default as ParaNativeStakingPoolHandler } from './para-chain';
5
5
  export { default as TaoNativeStakingPoolHandler } from './tao';
6
6
  export { default as SubnetTaoStakingPoolHandler } from './dtao';
7
+ export { default as EnergyNativeStakingPoolHandler } from './energy';
@@ -6,4 +6,5 @@ export { default as AstarNativeStakingPoolHandler } from "./astar.js";
6
6
  export { default as RelayNativeStakingPoolHandler } from "./relay-chain.js";
7
7
  export { default as ParaNativeStakingPoolHandler } from "./para-chain.js";
8
8
  export { default as TaoNativeStakingPoolHandler } from "./tao.js";
9
- export { default as SubnetTaoStakingPoolHandler } from "./dtao.js";
9
+ export { default as SubnetTaoStakingPoolHandler } from "./dtao.js";
10
+ export { default as EnergyNativeStakingPoolHandler } from "./energy.js";
@@ -13,7 +13,7 @@ import { BasicTxErrorType, YieldPoolType } from '@subwallet/extension-base/types
13
13
  import { addLazy, createPromiseHandler, filterAddressByChainInfo, removeLazy } from '@subwallet/extension-base/utils';
14
14
  import { fetchStaticCache } from '@subwallet/extension-base/utils/fetchStaticCache';
15
15
  import { BehaviorSubject, combineLatest } from 'rxjs';
16
- import { AcalaLiquidStakingPoolHandler, AmplitudeNativeStakingPoolHandler, AstarNativeStakingPoolHandler, BifrostLiquidStakingPoolHandler, BifrostMantaLiquidStakingPoolHandler, InterlayLendingPoolHandler, NominationPoolHandler, ParallelLiquidStakingPoolHandler, ParaNativeStakingPoolHandler, RelayNativeStakingPoolHandler, StellaSwapLiquidStakingPoolHandler, SubnetTaoStakingPoolHandler, TaoNativeStakingPoolHandler } from "./handlers/index.js";
16
+ import { AcalaLiquidStakingPoolHandler, AmplitudeNativeStakingPoolHandler, AstarNativeStakingPoolHandler, BifrostLiquidStakingPoolHandler, BifrostMantaLiquidStakingPoolHandler, EnergyNativeStakingPoolHandler, InterlayLendingPoolHandler, NominationPoolHandler, ParallelLiquidStakingPoolHandler, ParaNativeStakingPoolHandler, RelayNativeStakingPoolHandler, StellaSwapLiquidStakingPoolHandler, SubnetTaoStakingPoolHandler, TaoNativeStakingPoolHandler } from "./handlers/index.js";
17
17
  export const fetchPoolsData = async () => {
18
18
  const fetchData = await fetchStaticCache('earning/yield-pools.json', {
19
19
  data: {}
@@ -92,6 +92,9 @@ export default class EarningService {
92
92
  if (_STAKING_CHAIN_GROUP.mythos.includes(chain)) {
93
93
  handlers.push(new MythosNativeStakingPoolHandler(this.state, chain));
94
94
  }
95
+ if (_STAKING_CHAIN_GROUP.energy.includes(chain)) {
96
+ handlers.push(new EnergyNativeStakingPoolHandler(this.state, chain));
97
+ }
95
98
  if (_STAKING_CHAIN_GROUP.nominationPool.includes(chain)) {
96
99
  const ahChain = ahMapChain[chain];
97
100
  if (ahChain) {
@@ -107,6 +107,8 @@ export function isActionFromValidator(stakingType, chain) {
107
107
  return true;
108
108
  } else if (_STAKING_CHAIN_GROUP.mythos.includes(chain)) {
109
109
  return true;
110
+ } else if (_STAKING_CHAIN_GROUP.energy.includes(chain)) {
111
+ return true;
110
112
  }
111
113
  return false;
112
114
  }
@@ -116,6 +116,9 @@ export function getExplorerLink(chainInfo, value, type) {
116
116
  const address = u8aToHex(decodeAddress(value));
117
117
  return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}${route}/${address}`;
118
118
  }
119
+ if (chainInfo.slug === 'xode') {
120
+ return undefined;
121
+ }
119
122
  return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}${route}/${value}`;
120
123
  }
121
124
  if (explorerLink && isHex(hexAddPrefix(value))) {
@@ -123,6 +126,9 @@ export function getExplorerLink(chainInfo, value, type) {
123
126
  if (chainInfo.slug === 'tangle') {
124
127
  return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}extrinsic/${value}${route}/${value}`;
125
128
  }
129
+ if (chainInfo.slug === 'xode') {
130
+ return `${explorerLink}${explorerLink.endsWith('/') ? '' : '/'}polkadot-chain-transaction?search=${value}`;
131
+ }
126
132
  if (chainInfo.slug === 'truth_network') {
127
133
  // getTransactionId(value)
128
134
  // .then((transactionId) => {
@@ -2,15 +2,15 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { APP_VERSION, BACKEND_API_URL, BACKEND_PRICE_HISTORY_URL } from '@subwallet/extension-base/constants';
5
- import { ChainListVersion } from '@subwallet/extension-base/services/chain-service/utils';
6
5
  import subwalletApiSdk from '@subwallet-monorepos/subwallet-services-sdk';
7
6
  import { TARGET_ENV } from "./environment.js";
7
+ const CHAIN_LIST_VERSION = process.env.CHAIN_LIST_VERSION;
8
8
  export function setupApiSDK() {
9
9
  subwalletApiSdk.updateConfig({
10
10
  appVersion: APP_VERSION,
11
11
  baseUrl: BACKEND_API_URL,
12
12
  platform: TARGET_ENV,
13
- chainListVersion: ChainListVersion
13
+ chainListVersion: CHAIN_LIST_VERSION
14
14
  });
15
15
 
16
16
  // Custom the price history API with other different base URL