@subwallet/extension-base 1.3.61-0 → 1.3.63-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 (73) hide show
  1. package/cjs/koni/api/staking/bonding/utils.js +1 -1
  2. package/cjs/packageInfo.js +1 -1
  3. package/cjs/services/balance-service/transfer/smart-contract.js +14 -10
  4. package/cjs/services/balance-service/transfer/xcm/acrossBridge/index.js +0 -6
  5. package/cjs/services/balance-service/transfer/xcm/utils.js +2 -0
  6. package/cjs/services/chain-service/constants.js +16 -0
  7. package/cjs/services/chain-service/utils/index.js +24 -4
  8. package/cjs/services/chain-service/utils/patch.js +2 -2
  9. package/cjs/services/earning-service/constants/chains.js +8 -3
  10. package/cjs/services/earning-service/handlers/native-staking/base-para.js +6 -3
  11. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +4 -1
  12. package/cjs/services/earning-service/handlers/native-staking/tanssi.js +496 -0
  13. package/cjs/services/earning-service/service.js +4 -0
  14. package/cjs/services/earning-service/utils/index.js +2 -0
  15. package/cjs/services/fee-service/utils/tokenPayFee.js +25 -2
  16. package/cjs/services/migration-service/scripts/DeleteEarningData20251010.js +21 -0
  17. package/cjs/services/migration-service/scripts/index.js +3 -1
  18. package/cjs/services/swap-service/handler/base-handler.js +4 -1
  19. package/cjs/services/swap-service/handler/chainflip-handler.js +1 -17
  20. package/cjs/services/swap-service/handler/optimex-handler.js +421 -0
  21. package/cjs/services/swap-service/handler/simpleswap-handler.js +4 -2
  22. package/cjs/services/swap-service/index.js +38 -140
  23. package/cjs/services/swap-service/utils.js +16 -157
  24. package/cjs/services/transaction-service/helpers/index.js +2 -1
  25. package/cjs/types/service-base.js +0 -1
  26. package/cjs/types/swap/index.js +5 -8
  27. package/cjs/utils/account/common.js +1 -2
  28. package/cjs/utils/fee/transfer.js +9 -1
  29. package/koni/api/staking/bonding/utils.js +2 -2
  30. package/package.json +21 -6
  31. package/packageInfo.js +1 -1
  32. package/services/balance-service/transfer/smart-contract.d.ts +3 -2
  33. package/services/balance-service/transfer/smart-contract.js +35 -29
  34. package/services/balance-service/transfer/xcm/acrossBridge/index.d.ts +0 -4
  35. package/services/balance-service/transfer/xcm/acrossBridge/index.js +0 -4
  36. package/services/balance-service/transfer/xcm/utils.js +2 -0
  37. package/services/chain-service/constants.js +16 -0
  38. package/services/chain-service/utils/index.d.ts +3 -2
  39. package/services/chain-service/utils/index.js +20 -1
  40. package/services/chain-service/utils/patch.d.ts +1 -1
  41. package/services/chain-service/utils/patch.js +2 -2
  42. package/services/earning-service/constants/chains.d.ts +2 -0
  43. package/services/earning-service/constants/chains.js +6 -2
  44. package/services/earning-service/handlers/native-staking/base-para.js +6 -3
  45. package/services/earning-service/handlers/native-staking/relay-chain.js +4 -1
  46. package/services/earning-service/handlers/native-staking/tanssi.d.ts +16 -0
  47. package/services/earning-service/handlers/native-staking/tanssi.js +478 -0
  48. package/services/earning-service/service.js +4 -0
  49. package/services/earning-service/utils/index.js +2 -0
  50. package/services/fee-service/utils/tokenPayFee.js +25 -2
  51. package/services/migration-service/scripts/DeleteEarningData20251010.d.ts +4 -0
  52. package/services/migration-service/scripts/DeleteEarningData20251010.js +13 -0
  53. package/services/migration-service/scripts/index.js +3 -1
  54. package/services/swap-service/handler/base-handler.js +6 -3
  55. package/services/swap-service/handler/chainflip-handler.d.ts +0 -2
  56. package/services/swap-service/handler/chainflip-handler.js +2 -18
  57. package/services/swap-service/handler/optimex-handler.d.ts +43 -0
  58. package/services/swap-service/handler/optimex-handler.js +410 -0
  59. package/services/swap-service/handler/simpleswap-handler.js +5 -3
  60. package/services/swap-service/index.d.ts +0 -1
  61. package/services/swap-service/index.js +21 -123
  62. package/services/swap-service/utils.d.ts +6 -12
  63. package/services/swap-service/utils.js +8 -138
  64. package/services/transaction-service/helpers/index.js +2 -1
  65. package/types/balance/transfer.d.ts +1 -0
  66. package/types/service-base.d.ts +3 -4
  67. package/types/service-base.js +0 -2
  68. package/types/swap/index.d.ts +3 -1
  69. package/types/swap/index.js +7 -6
  70. package/types/yield/info/account/info.d.ts +5 -0
  71. package/utils/account/common.js +2 -3
  72. package/utils/fee/transfer.js +9 -1
  73. package/utils/staticData/assetHubStaking.json +6 -1
@@ -0,0 +1,478 @@
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 { APIItemState, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
6
+ import { BasicTxErrorType, EarningStatus } from '@subwallet/extension-base/types';
7
+ import BigN from 'bignumber.js';
8
+ import { parseIdentity } from "../../utils/index.js";
9
+ import BaseParaNativeStakingPoolHandler from "./base-para.js";
10
+ function perbillToPercentBn(perbill) {
11
+ const raw = new BigN((perbill === null || perbill === void 0 ? void 0 : perbill.toString()) || '0');
12
+ const bnPercent = raw.multipliedBy(new BigN(100)).div(new BigN(1000000000));
13
+ return bnPercent.toNumber();
14
+ }
15
+ async function getOwnStakes(chainApi, candidates, delegator) {
16
+ const queries = [];
17
+ for (const candidate of candidates) {
18
+ // Auto-compounding
19
+ queries.push([candidate, {
20
+ AutoCompoundingShares: {
21
+ delegator
22
+ }
23
+ }]);
24
+ queries.push([candidate, 'AutoCompoundingSharesSupply']);
25
+ queries.push([candidate, 'AutoCompoundingSharesTotalStaked']);
26
+
27
+ // Manual rewards
28
+ queries.push([candidate, {
29
+ ManualRewardsShares: {
30
+ delegator
31
+ }
32
+ }]);
33
+ queries.push([candidate, 'ManualRewardsSharesSupply']);
34
+ queries.push([candidate, 'ManualRewardsSharesTotalStaked']);
35
+
36
+ // Joining
37
+ queries.push([candidate, {
38
+ JoiningShares: {
39
+ delegator
40
+ }
41
+ }]);
42
+ queries.push([candidate, 'JoiningSharesSupply']);
43
+ queries.push([candidate, 'JoiningSharesTotalStaked']);
44
+
45
+ // Leaving
46
+ queries.push([candidate, {
47
+ LeavingShares: {
48
+ delegator
49
+ }
50
+ }]);
51
+ queries.push([candidate, 'LeavingSharesSupply']);
52
+ queries.push([candidate, 'LeavingSharesTotalStaked']);
53
+
54
+ // Claimable reward
55
+ queries.push([candidate, 'ManualRewardsCounter']);
56
+ queries.push([candidate, {
57
+ ManualRewardsCheckpoint: {
58
+ delegator
59
+ }
60
+ }]);
61
+ }
62
+ const results = await chainApi.api.query.pooledStaking.pools.multi(queries);
63
+ const stakes = {};
64
+ const stride = 14;
65
+ for (let i = 0; i < candidates.length; i++) {
66
+ const base = i * stride;
67
+
68
+ // Auto-compounding
69
+ const acShares = new BigN(results[base + 0].toString());
70
+ const acSupply = new BigN(results[base + 1].toString());
71
+ const acTotal = new BigN(results[base + 2].toString());
72
+ const autoCompounding = acSupply.isZero() ? new BigN(0) : acShares.multipliedBy(acTotal).div(acSupply);
73
+
74
+ // Manual rewards
75
+ const mrShares = new BigN(results[base + 3].toString());
76
+ const mrSupply = new BigN(results[base + 4].toString());
77
+ const mrTotal = new BigN(results[base + 5].toString());
78
+ const manualRewards = mrSupply.isZero() ? new BigN(0) : mrShares.multipliedBy(mrTotal).div(mrSupply);
79
+
80
+ // Joining
81
+ const jShares = new BigN(results[base + 6].toString());
82
+ const jSupply = new BigN(results[base + 7].toString());
83
+ const jTotal = new BigN(results[base + 8].toString());
84
+ const joining = jSupply.isZero() ? new BigN(0) : jShares.multipliedBy(jTotal).div(jSupply);
85
+
86
+ // Leaving
87
+ const lShares = new BigN(results[base + 9].toString());
88
+ const lSupply = new BigN(results[base + 10].toString());
89
+ const lTotal = new BigN(results[base + 11].toString());
90
+ const leaving = lSupply.isZero() ? new BigN(0) : lShares.multipliedBy(lTotal).div(lSupply);
91
+
92
+ // Claimable rewards
93
+ const counter = new BigN(results[base + 12].toString());
94
+ const checkpoint = new BigN(results[base + 13].toString());
95
+ const claimable = counter.minus(checkpoint).multipliedBy(mrShares);
96
+
97
+ // Total stake
98
+ const totalStake = autoCompounding.plus(manualRewards).plus(joining).plus(leaving);
99
+ stakes[candidates[i]] = {
100
+ autoCompounding: autoCompounding.toFixed(0),
101
+ autoCompoundingShares: acShares.toFixed(0),
102
+ manualRewards: manualRewards.toFixed(0),
103
+ joining: joining.toFixed(0),
104
+ leaving: leaving.toFixed(0),
105
+ totalStake: totalStake.toFixed(0),
106
+ claimable: claimable.toFixed(0)
107
+ };
108
+ }
109
+ return stakes;
110
+ }
111
+ export default class TanssiNativeStakingPoolHandler extends BaseParaNativeStakingPoolHandler {
112
+ availableMethod = {
113
+ join: true,
114
+ defaultUnstake: true,
115
+ fastUnstake: false,
116
+ cancelUnstake: false,
117
+ withdraw: false,
118
+ claimReward: true,
119
+ changeValidator: false
120
+ };
121
+
122
+ /* Subscribe pool info */
123
+
124
+ async subscribePoolInfo(callback) {
125
+ let cancel = false;
126
+ const defaultCallback = async () => {
127
+ const api = await this.substrateApi.isReady;
128
+ const activeConfig = (await api.api.query.collatorConfiguration.activeConfig()).toPrimitive();
129
+ const maxCollators = activeConfig.maxCollators;
130
+ const data = {
131
+ ...this.baseInfo,
132
+ type: this.type,
133
+ metadata: {
134
+ ...this.metadataInfo,
135
+ description: this.getDescription()
136
+ },
137
+ statistic: {
138
+ assetEarning: [{
139
+ slug: this.nativeToken.slug
140
+ }],
141
+ maxCandidatePerFarmer: maxCollators,
142
+ maxWithdrawalRequestPerFarmer: 1,
143
+ earningThreshold: {
144
+ join: '0',
145
+ defaultUnstake: '0',
146
+ fastUnstake: '0'
147
+ },
148
+ era: 0,
149
+ eraTime: 6 / 3600,
150
+ unstakingPeriod: 12
151
+ }
152
+ };
153
+ if (!cancel) {
154
+ callback(data);
155
+ }
156
+ };
157
+ await defaultCallback();
158
+ return () => {
159
+ cancel = true;
160
+ };
161
+ }
162
+
163
+ /* Subscribe pool info */
164
+
165
+ /* Subscribe pool position */
166
+
167
+ async subscribePoolPosition(useAddresses, onUpdate) {
168
+ const substrateApi = this.substrateApi;
169
+ await substrateApi.isReady;
170
+ let cancel = false;
171
+ const intervalIds = [];
172
+ for (const delegator of useAddresses) {
173
+ const fetchAndUpdate = async () => {
174
+ if (cancel) {
175
+ return;
176
+ }
177
+ const entries = await substrateApi.api.query.pooledStaking.delegatorCandidateSummaries.entries(delegator);
178
+ if (!entries || entries.length === 0) {
179
+ onUpdate({
180
+ ...this.baseInfo,
181
+ type: this.type,
182
+ address: delegator,
183
+ balanceToken: this.nativeToken.slug,
184
+ totalStake: '0',
185
+ activeStake: '0',
186
+ unstakeBalance: '0',
187
+ status: EarningStatus.NOT_STAKING,
188
+ isBondedBefore: false,
189
+ nominations: [],
190
+ unstakings: []
191
+ });
192
+ return;
193
+ }
194
+ const candidates = entries.map(([storageKey]) => storageKey.args[1].toString());
195
+ const ownStakesMap = await getOwnStakes(substrateApi, candidates, delegator);
196
+ const nominations = [];
197
+ let bnTotalStake = new BigN(0);
198
+ let bnActiveStake = new BigN(0);
199
+ let bnUnstakeBalance = new BigN(0);
200
+ let bnJoiningStake = new BigN(0);
201
+ let bnCompoundingStake = new BigN(0);
202
+ let bnManualStake = new BigN(0);
203
+ for (const candidate of candidates) {
204
+ const ownStake = ownStakesMap[candidate];
205
+ if (!ownStake) {
206
+ continue;
207
+ }
208
+ const autoCompounding = new BigN(ownStake.autoCompounding);
209
+ const manualRewards = new BigN(ownStake.manualRewards);
210
+ const joining = new BigN(ownStake.joining);
211
+ const leaving = new BigN(ownStake.leaving);
212
+ const totalStake = new BigN(ownStake.totalStake);
213
+ if (totalStake.isZero()) {
214
+ continue;
215
+ }
216
+ bnTotalStake = bnTotalStake.plus(totalStake);
217
+ bnActiveStake = bnActiveStake.plus(autoCompounding).plus(manualRewards).plus(joining);
218
+ bnUnstakeBalance = bnUnstakeBalance.plus(leaving);
219
+ bnJoiningStake = bnJoiningStake.plus(joining);
220
+ bnCompoundingStake = bnCompoundingStake.plus(autoCompounding);
221
+ bnManualStake = bnManualStake.plus(manualRewards);
222
+ const [identity] = await parseIdentity(this.substrateIdentityApi, candidate);
223
+ nominations.push({
224
+ chain: this.chain,
225
+ status: EarningStatus.EARNING_REWARD,
226
+ validatorAddress: candidate,
227
+ validatorIdentity: identity,
228
+ activeStake: new BigN(autoCompounding).plus(manualRewards).toFixed(),
229
+ hasUnstaking: !leaving.isZero(),
230
+ validatorMinStake: '0'
231
+ });
232
+ }
233
+ onUpdate({
234
+ ...this.baseInfo,
235
+ type: this.type,
236
+ address: delegator,
237
+ balanceToken: this.nativeToken.slug,
238
+ totalStake: bnTotalStake.toString(),
239
+ activeStake: bnActiveStake.toString(),
240
+ unstakeBalance: bnUnstakeBalance.toString(),
241
+ status: nominations.length > 0 ? EarningStatus.EARNING_REWARD : EarningStatus.NOT_STAKING,
242
+ isBondedBefore: nominations.length > 0,
243
+ nominations,
244
+ unstakings: [],
245
+ metadata: {
246
+ pendingStake: bnJoiningStake.toString(),
247
+ compoundingStake: bnCompoundingStake.toString(),
248
+ manualStake: bnManualStake.toString()
249
+ }
250
+ });
251
+ };
252
+ fetchAndUpdate().catch(console.error);
253
+ const intervalId = setInterval(() => {
254
+ fetchAndUpdate().catch(console.error);
255
+ }, 30000);
256
+ intervalIds.push(intervalId);
257
+ }
258
+ return () => {
259
+ cancel = true;
260
+ intervalIds.forEach(id => clearInterval(id));
261
+ };
262
+ }
263
+ async checkAccountHaveStake(addresses) {
264
+ const stakedAddresses = [];
265
+ const api = await this.substrateApi.isReady;
266
+ const candidateSummariesByAddress = await Promise.all(addresses.map(address => api.api.query.pooledStaking.delegatorCandidateSummaries.entries(address)));
267
+ for (let i = 0; i < addresses.length; i++) {
268
+ const candidateSummaries = candidateSummariesByAddress[i];
269
+ if (candidateSummaries && candidateSummaries.length > 0) {
270
+ stakedAddresses.push(addresses[i]);
271
+ }
272
+ }
273
+ return stakedAddresses;
274
+ }
275
+
276
+ /* Subscribe pool position */
277
+
278
+ /* Get pool targets */
279
+
280
+ async getPoolTargets() {
281
+ const chainApi = await this.substrateApi.isReady;
282
+ const commissionRaw = chainApi.api.consts.pooledStaking.rewardsCollatorCommission.toJSON();
283
+ const commission = perbillToPercentBn(commissionRaw);
284
+ const candidates = await chainApi.api.query.pooledStaking.sortedEligibleCandidates();
285
+ const candidateSummaries = await chainApi.api.query.pooledStaking.candidateSummaries.entries();
286
+ const candidateSummariesMap = {};
287
+ candidateSummaries.forEach(([key, summary]) => {
288
+ const address = key.args[0].toString();
289
+ candidateSummariesMap[address] = summary.toJSON();
290
+ });
291
+ const candidateAddresses = candidates.map(c => c.candidate.toString());
292
+ const targets = await Promise.all(candidates.map(async c => {
293
+ const address = c.candidate.toString();
294
+ const totalStake = new BigN(c.stake.toString());
295
+ const candidateInfo = candidateSummariesMap[address];
296
+ const nominatorCount = (candidateInfo === null || candidateInfo === void 0 ? void 0 : candidateInfo.delegators) || 0;
297
+ const ownStakesMap = await getOwnStakes(chainApi, candidateAddresses, address);
298
+ const ownStakeInfo = ownStakesMap[address];
299
+ const ownStake = ownStakeInfo ? new BigN(ownStakeInfo.totalStake) : new BigN(0);
300
+ const otherStake = BigN.max(totalStake.minus(ownStake), 0);
301
+ const [identity, isReasonable] = await parseIdentity(this.substrateApi, address);
302
+ const validator = {
303
+ address,
304
+ chain: this.chain,
305
+ totalStake: totalStake.toFixed(),
306
+ ownStake: ownStake.toFixed(),
307
+ otherStake: otherStake.toFixed(),
308
+ minBond: '0',
309
+ nominatorCount,
310
+ commission,
311
+ blocked: false,
312
+ isVerified: isReasonable,
313
+ isCrowded: false,
314
+ identity
315
+ };
316
+ return validator;
317
+ }));
318
+ return targets;
319
+ }
320
+
321
+ /* Get pool targets */
322
+
323
+ /* Join pool action */
324
+
325
+ async createJoinExtrinsic(data, positionInfo, bondDest, netuid) {
326
+ const {
327
+ amount,
328
+ selectedValidators
329
+ } = data;
330
+ const substrateApi = this.substrateApi;
331
+ const api = await substrateApi.isReady;
332
+ const binaryAmount = new BigN(amount);
333
+ const selectedCollatorInfo = selectedValidators[0];
334
+ const {
335
+ address: selectedCollatorAddress
336
+ } = selectedCollatorInfo;
337
+ const extrinsic = api.api.tx.pooledStaking.requestDelegate(selectedCollatorAddress, 'AutoCompounding',
338
+ // 'ManualRewards'
339
+ binaryAmount.toFixed());
340
+ return [extrinsic, {
341
+ slug: this.nativeToken.slug,
342
+ amount
343
+ }];
344
+ }
345
+
346
+ /* Join pool action */
347
+
348
+ /* Leave pool action */
349
+
350
+ async handleYieldUnstake(amount, address, selectedTarget) {
351
+ if (!selectedTarget) {
352
+ return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
353
+ }
354
+ const substrateApi = await this.substrateApi.isReady;
355
+ const txs = [];
356
+ const stakesMap = await getOwnStakes(substrateApi, [selectedTarget], address);
357
+ const stakeInfo = stakesMap[selectedTarget];
358
+ const manualRewards = new BigN(stakeInfo.manualRewards);
359
+ const autoCompounding = new BigN(stakeInfo.autoCompounding);
360
+ const unstakeAmount = new BigN(amount);
361
+ if (manualRewards.gt(0)) {
362
+ if (unstakeAmount.lte(manualRewards)) {
363
+ txs.push(substrateApi.api.tx.pooledStaking.requestUndelegate(selectedTarget, 'ManualRewards', {
364
+ Stake: unstakeAmount.toFixed()
365
+ }));
366
+ } else {
367
+ txs.push(substrateApi.api.tx.pooledStaking.requestUndelegate(selectedTarget, 'ManualRewards', {
368
+ Stake: manualRewards.toFixed()
369
+ }));
370
+ const remaining = unstakeAmount.minus(manualRewards);
371
+ if (remaining.gt(0)) {
372
+ const acShares = new BigN(stakeInfo.autoCompoundingShares || '0');
373
+ // Unstake all: use Shares to avoid small leftovers as rewards are automatically compounded every 6 seconds
374
+ const isUnstakeAll = remaining.gte(autoCompounding.multipliedBy(0.9999));
375
+ txs.push(substrateApi.api.tx.pooledStaking.requestUndelegate(selectedTarget, 'AutoCompounding', isUnstakeAll ? {
376
+ Shares: acShares.toFixed(0)
377
+ } : {
378
+ Stake: remaining.toFixed(0)
379
+ }));
380
+ }
381
+ }
382
+ } else {
383
+ const acShares = new BigN(stakeInfo.autoCompoundingShares || '0');
384
+ const isUnstakeAll = unstakeAmount.gte(autoCompounding.multipliedBy(0.9999));
385
+ txs.push(substrateApi.api.tx.pooledStaking.requestUndelegate(selectedTarget, 'AutoCompounding', isUnstakeAll ? {
386
+ Shares: acShares.toFixed(0)
387
+ } : {
388
+ Stake: unstakeAmount.toFixed(0)
389
+ }));
390
+ }
391
+ const extrinsic = txs.length === 1 ? txs[0] : substrateApi.api.tx.utility.batchAll(txs);
392
+ return [ExtrinsicType.STAKING_UNBOND, extrinsic];
393
+ }
394
+
395
+ /* Leave pool action */
396
+
397
+ /* Get pool reward */
398
+ async getPoolReward(useAddresses, callback) {
399
+ let cancel = false;
400
+ const substrateApi = this.substrateApi;
401
+ await substrateApi.isReady;
402
+ await Promise.all(useAddresses.map(async address => {
403
+ if (cancel) {
404
+ return;
405
+ }
406
+ const delegatorSummaries = await substrateApi.api.query.pooledStaking.delegatorCandidateSummaries.entries(address);
407
+ if (!delegatorSummaries || delegatorSummaries.length === 0) {
408
+ const earningRewardItem = {
409
+ ...this.baseInfo,
410
+ address,
411
+ type: this.type,
412
+ unclaimedReward: '0',
413
+ state: APIItemState.READY
414
+ };
415
+ callback(earningRewardItem);
416
+ return;
417
+ }
418
+ const candidates = delegatorSummaries.map(([key]) => key.args[1].toString());
419
+ const ownStakesMap = await getOwnStakes(substrateApi, candidates, address);
420
+ let totalClaimable = new BigN(0);
421
+ for (const candidate of candidates) {
422
+ const ownStake = ownStakesMap[candidate];
423
+ if (ownStake) {
424
+ totalClaimable = totalClaimable.plus(ownStake.claimable || 0);
425
+ }
426
+ }
427
+ const _unclaimedReward = totalClaimable.toFixed();
428
+ const earningRewardItem = {
429
+ ...this.baseInfo,
430
+ address,
431
+ type: this.type,
432
+ unclaimedReward: _unclaimedReward,
433
+ state: APIItemState.READY
434
+ };
435
+ if (_unclaimedReward !== '0') {
436
+ await this.createClaimNotification(earningRewardItem, this.nativeToken);
437
+ }
438
+ callback(earningRewardItem);
439
+ }));
440
+ return () => {
441
+ cancel = true;
442
+ };
443
+ }
444
+
445
+ /* Get pool reward */
446
+
447
+ /* Other actions */
448
+
449
+ async handleYieldClaimReward(address, bondReward) {
450
+ const api = await this.substrateApi.isReady;
451
+ const delegatorSummaries = await api.api.query.pooledStaking.delegatorCandidateSummaries.entries(address);
452
+ if (!delegatorSummaries || delegatorSummaries.length === 0) {
453
+ return Promise.reject(new TransactionError(BasicTxErrorType.INTERNAL_ERROR));
454
+ }
455
+ const candidates = delegatorSummaries.map(([key]) => key.args[1].toString());
456
+ const ownStakesMap = await getOwnStakes(api, candidates, address);
457
+ const claimablePairs = [];
458
+ for (const candidate of candidates) {
459
+ const ownStake = ownStakesMap[candidate];
460
+ if (ownStake && new BigN(ownStake.claimable).gt(0)) {
461
+ claimablePairs.push([candidate, address]);
462
+ }
463
+ }
464
+ if (claimablePairs.length === 0) {
465
+ return Promise.reject(new TransactionError(BasicTxErrorType.INTERNAL_ERROR));
466
+ }
467
+ const extrinsic = api.api.tx.pooledStaking.claimManualRewards(claimablePairs);
468
+ return extrinsic;
469
+ }
470
+ handleYieldWithdraw(address, unstakingInfo) {
471
+ throw new Error('Method not implemented.');
472
+ }
473
+ handleYieldCancelUnstake(params) {
474
+ throw new Error('Method not implemented.');
475
+ }
476
+
477
+ /* Other actions */
478
+ }
@@ -13,6 +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 TanssiNativeStakingPoolHandler from "./handlers/native-staking/tanssi.js";
16
17
  import { AcalaLiquidStakingPoolHandler, AmplitudeNativeStakingPoolHandler, AstarNativeStakingPoolHandler, BifrostLiquidStakingPoolHandler, BifrostMantaLiquidStakingPoolHandler, EnergyNativeStakingPoolHandler, InterlayLendingPoolHandler, NominationPoolHandler, ParallelLiquidStakingPoolHandler, ParaNativeStakingPoolHandler, RelayNativeStakingPoolHandler, StellaSwapLiquidStakingPoolHandler, SubnetTaoStakingPoolHandler, TaoNativeStakingPoolHandler } from "./handlers/index.js";
17
18
  export const fetchPoolsData = async () => {
18
19
  const fetchData = await fetchStaticCache('earning/yield-pools.json', {
@@ -100,6 +101,9 @@ export default class EarningService {
100
101
  if (_STAKING_CHAIN_GROUP.energy.includes(chain)) {
101
102
  handlers.push(new EnergyNativeStakingPoolHandler(this.state, chain));
102
103
  }
104
+ if (_STAKING_CHAIN_GROUP.tanssi.includes(chain)) {
105
+ handlers.push(new TanssiNativeStakingPoolHandler(this.state, chain));
106
+ }
103
107
  if (_STAKING_CHAIN_GROUP.nominationPool.includes(chain)) {
104
108
  const ahMigratedChain = ahMigratedChainMap[chain];
105
109
  if (ahMigratedChain) {
@@ -109,6 +109,8 @@ export function isActionFromValidator(stakingType, chain) {
109
109
  return true;
110
110
  } else if (_STAKING_CHAIN_GROUP.energy.includes(chain)) {
111
111
  return true;
112
+ } else if (_STAKING_CHAIN_GROUP.tanssi.includes(chain)) {
113
+ return true;
112
114
  }
113
115
  return false;
114
116
  }
@@ -22,7 +22,18 @@ export async function getAssetHubTokensCanPayFee(request) {
22
22
 
23
23
  // ensure nativeTokenInfo and localTokenInfo have multi-location metadata beforehand to improve performance.
24
24
  const tokensHasBalanceSlug = Object.keys(tokensHasBalanceInfoMap);
25
- const tokenInfos = tokensHasBalanceSlug.map(tokenSlug => chainService.getAssetBySlug(tokenSlug)).filter(token => token.originChain === substrateApi.chainSlug && token.assetType !== _AssetType.NATIVE && token.metadata && token.metadata.multilocation);
25
+ const tokenInfos = tokensHasBalanceSlug.map(tokenSlug => {
26
+ const token = chainService.getAssetBySlug(tokenSlug);
27
+ if (!token) {
28
+ console.error(`[getAssetHubTokensCanPayFee] Token not found for slug: ${tokenSlug}`);
29
+ }
30
+ return token;
31
+ }).filter(token => {
32
+ if (!token) {
33
+ return false;
34
+ }
35
+ return token.originChain === substrateApi.chainSlug && token.assetType !== _AssetType.NATIVE && token.metadata && token.metadata.multilocation;
36
+ });
26
37
  await Promise.all(tokenInfos.map(async tokenInfo => {
27
38
  try {
28
39
  const tokenSlug = tokenInfo.slug;
@@ -70,7 +81,19 @@ export async function getHydrationTokensCanPayFee(request) {
70
81
  if (!nativePriceId) {
71
82
  return tokensList;
72
83
  }
73
- const tokenInfos = Object.keys(tokensHasBalanceInfoMap).map(tokenSlug => chainService.getAssetBySlug(tokenSlug)).filter(token => token.originChain === substrateApi.chainSlug && token.assetType !== _AssetType.NATIVE && !!token.metadata && !!token.metadata.assetId);
84
+ const tokenInfos = Object.keys(tokensHasBalanceInfoMap).map(tokenSlug => {
85
+ const token = chainService.getAssetBySlug(tokenSlug);
86
+ if (!token) {
87
+ console.error(`[getHydrationTokensCanPayFee] Token not found for slug: ${tokenSlug}`);
88
+ }
89
+ return token;
90
+ }).filter(token => {
91
+ var _token$metadata;
92
+ if (!token) {
93
+ return false;
94
+ }
95
+ return token.originChain === substrateApi.chainSlug && token.assetType !== _AssetType.NATIVE && !!((_token$metadata = token.metadata) !== null && _token$metadata !== void 0 && _token$metadata.assetId);
96
+ });
74
97
  await Promise.all(tokenInfos.map(async tokenInfo => {
75
98
  const priceId = _getAssetPriceId(tokenInfo);
76
99
  const rate = await getHydrationRate(address, nativeTokenInfo, tokenInfo);
@@ -0,0 +1,4 @@
1
+ import BaseMigrationJob from '@subwallet/extension-base/services/migration-service/Base';
2
+ export default class DeleteEarningData20251010 extends BaseMigrationJob {
3
+ run(): Promise<void>;
4
+ }
@@ -0,0 +1,13 @@
1
+ // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import BaseMigrationJob from '@subwallet/extension-base/services/migration-service/Base';
5
+ export default class DeleteEarningData20251010 extends BaseMigrationJob {
6
+ async run() {
7
+ try {
8
+ await this.state.dbService.deleteYieldPoolInfo(['KSM___native_staking___kusama', 'KSM___nomination_pool___kusama']);
9
+ } catch (e) {
10
+ console.error(e);
11
+ }
12
+ }
13
+ }
@@ -18,6 +18,7 @@ import MigratePolygonUSDCProvider from "./tokens/MigratePolygonUSDCProvider.js";
18
18
  import DeleteChain from "./DeleteChain.js";
19
19
  import DeleteChainStaking from "./DeleteChainStaking.js";
20
20
  import DeleteEarningData from "./DeleteEarningData.js";
21
+ import DeleteEarningData20251010 from "./DeleteEarningData20251010.js";
21
22
  import DisableZeroBalanceTokens from "./DisableZeroBalanceTokens.js";
22
23
  import EnableVaraChain from "./EnableVaraChain.js";
23
24
  import MigrateAuthUrls from "./MigrateAuthUrls.js";
@@ -67,5 +68,6 @@ export default {
67
68
  // [`${EVERYTIME}-1.1.42-02`]: MigrateTransactionHistoryBySymbol
68
69
  // [`${EVERYTIME}-1`]: AutoEnableChainsTokens
69
70
  '1.3.42-01': MigrateNewUnifiedAccount,
70
- '1.3.54-01': MigrateChainPatrol
71
+ '1.3.54-01': MigrateChainPatrol,
72
+ '1.3.62-01': DeleteEarningData20251010
71
73
  };
@@ -8,10 +8,10 @@ import { _isAccountActive } from '@subwallet/extension-base/core/substrate/syste
8
8
  import { _isAcrossBridgeXcm, _isSnowBridgeXcm, _isXcmWithinSameConsensus } from '@subwallet/extension-base/core/substrate/xcm-parser';
9
9
  import { _isSufficientToken } from '@subwallet/extension-base/core/utils';
10
10
  import { createXcmExtrinsicV2, dryRunXcmExtrinsicV2 } from '@subwallet/extension-base/services/balance-service/transfer/xcm';
11
- import { _isAcrossChainBridge, AcrossErrorMsg } from '@subwallet/extension-base/services/balance-service/transfer/xcm/acrossBridge';
11
+ import { _isAcrossChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/acrossBridge';
12
12
  import { estimateXcmFee } from '@subwallet/extension-base/services/balance-service/transfer/xcm/utils';
13
13
  import { _getAssetDecimals, _getAssetOriginChain, _getAssetSymbol, _getChainNativeTokenSlug, _getTokenMinAmount, _isChainEvmCompatible, _isNativeToken, _isPureBitcoinChain } from '@subwallet/extension-base/services/chain-service/utils';
14
- import { DEFAULT_EXCESS_AMOUNT_WEIGHT, FEE_RATE_MULTIPLIER } from '@subwallet/extension-base/services/swap-service/utils';
14
+ import { DEFAULT_EXCESS_AMOUNT_WEIGHT, DetectedGenOptimalProcessErrMsg, FEE_RATE_MULTIPLIER } from '@subwallet/extension-base/services/swap-service/utils';
15
15
  import { BasicTxErrorType, SwapStepType, TransferTxErrorType } from '@subwallet/extension-base/types';
16
16
  import { CommonStepType, DEFAULT_FIRST_STEP, MOCK_STEP_FEE } from '@subwallet/extension-base/types/service-base';
17
17
  import { DynamicSwapType, SwapErrorType, SwapFeeType } from '@subwallet/extension-base/types/swap';
@@ -56,7 +56,10 @@ export class SwapBaseHandler {
56
56
  return result;
57
57
  } catch (e) {
58
58
  const errorMessage = e.message;
59
- if (errorMessage.toLowerCase().startsWith(AcrossErrorMsg.AMOUNT_TOO_LOW) || errorMessage.toLowerCase().startsWith(AcrossErrorMsg.AMOUNT_TOO_HIGH)) {
59
+ if (errorMessage.toLowerCase().startsWith(DetectedGenOptimalProcessErrMsg.AMOUNT_TOO_LOW) || errorMessage.toLowerCase().startsWith(DetectedGenOptimalProcessErrMsg.AMOUNT_TOO_HIGH)) {
60
+ throw new Error(errorMessage);
61
+ }
62
+ if (errorMessage.toLowerCase().includes(DetectedGenOptimalProcessErrMsg.NOT_ENOUGHT_BITCOIN)) {
60
63
  throw new Error(errorMessage);
61
64
  }
62
65
  return result;
@@ -1,4 +1,3 @@
1
- import { COMMON_ASSETS } from '@subwallet/chain-list';
2
1
  import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
3
2
  import { BalanceService } from '@subwallet/extension-base/services/balance-service';
4
3
  import { ChainService } from '@subwallet/extension-base/services/chain-service';
@@ -15,7 +14,6 @@ export declare class ChainflipSwapHandler implements SwapBaseInterface {
15
14
  get providerInfo(): import("@subwallet/extension-base/types").SwapProvider;
16
15
  get name(): string;
17
16
  get slug(): string;
18
- get intermediaryAssetSlug(): COMMON_ASSETS.USDC_ETHEREUM | COMMON_ASSETS.USDC_SEPOLIA;
19
17
  handleSubmitStep(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
20
18
  handleSwapProcess(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
21
19
  getSubmitStep(params: OptimalSwapPathParamsV2, stepIndex: number): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;