@subwallet/extension-base 1.3.51-0 → 1.3.53-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 (60) hide show
  1. package/cjs/constants/environment.js +3 -1
  2. package/cjs/koni/background/handlers/State.js +1 -5
  3. package/cjs/packageInfo.js +1 -1
  4. package/cjs/services/balance-service/index.js +3 -4
  5. package/cjs/services/balance-service/transfer/cardano-transfer.js +43 -11
  6. package/cjs/services/balance-service/transfer/xcm/acrossBridge/index.js +13 -92
  7. package/cjs/services/balance-service/transfer/xcm/index.js +12 -4
  8. package/cjs/services/chain-service/utils/patch.js +3 -2
  9. package/cjs/services/earning-service/handlers/native-staking/dtao.js +28 -301
  10. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +4 -4
  11. package/cjs/services/earning-service/handlers/native-staking/tao.js +174 -148
  12. package/cjs/services/earning-service/handlers/nomination-pool/index.js +11 -5
  13. package/cjs/services/earning-service/service.js +5 -2
  14. package/cjs/services/fee-service/utils/tokenPayFee.js +17 -13
  15. package/cjs/services/keyring-service/context/handlers/Json.js +28 -3
  16. package/cjs/services/price-service/coingecko.js +3 -3
  17. package/cjs/services/swap-service/handler/hydradx-handler.js +19 -13
  18. package/cjs/services/swap-service/index.js +8 -5
  19. package/cjs/services/transaction-service/utils.js +31 -22
  20. package/cjs/services/wallet-connect-service/constants.js +6 -2
  21. package/cjs/services/wallet-connect-service/index.js +62 -45
  22. package/cjs/utils/index.js +12 -0
  23. package/cjs/utils/setup-api-sdk.js +27 -0
  24. package/constants/environment.d.ts +1 -0
  25. package/constants/environment.js +1 -0
  26. package/koni/background/handlers/State.js +3 -7
  27. package/package.json +34 -29
  28. package/packageInfo.js +1 -1
  29. package/services/balance-service/index.js +3 -4
  30. package/services/balance-service/transfer/cardano-transfer.js +42 -10
  31. package/services/balance-service/transfer/xcm/acrossBridge/index.js +14 -93
  32. package/services/balance-service/transfer/xcm/index.js +12 -4
  33. package/services/chain-service/utils/patch.d.ts +1 -0
  34. package/services/chain-service/utils/patch.js +1 -1
  35. package/services/earning-service/handlers/native-staking/dtao.d.ts +4 -36
  36. package/services/earning-service/handlers/native-staking/dtao.js +24 -298
  37. package/services/earning-service/handlers/native-staking/relay-chain.d.ts +1 -2
  38. package/services/earning-service/handlers/native-staking/relay-chain.js +4 -4
  39. package/services/earning-service/handlers/native-staking/tao.d.ts +25 -5
  40. package/services/earning-service/handlers/native-staking/tao.js +169 -149
  41. package/services/earning-service/handlers/nomination-pool/index.d.ts +1 -2
  42. package/services/earning-service/handlers/nomination-pool/index.js +11 -5
  43. package/services/earning-service/service.d.ts +1 -0
  44. package/services/earning-service/service.js +4 -2
  45. package/services/fee-service/utils/tokenPayFee.js +17 -13
  46. package/services/keyring-service/context/handlers/Json.js +28 -3
  47. package/services/price-service/coingecko.js +2 -3
  48. package/services/swap-service/handler/hydradx-handler.js +19 -13
  49. package/services/swap-service/index.js +8 -5
  50. package/services/transaction-service/utils.d.ts +0 -1
  51. package/services/transaction-service/utils.js +31 -21
  52. package/services/wallet-connect-service/constants.d.ts +2 -0
  53. package/services/wallet-connect-service/constants.js +3 -1
  54. package/services/wallet-connect-service/index.js +50 -33
  55. package/types/swap/index.d.ts +1 -1
  56. package/types/yield/info/chain/info.d.ts +1 -0
  57. package/utils/index.d.ts +1 -0
  58. package/utils/index.js +2 -1
  59. package/utils/setup-api-sdk.d.ts +1 -0
  60. package/utils/setup-api-sdk.js +20 -0
@@ -7,12 +7,16 @@ import { BITTENSOR_REFRESH_STAKE_APY, BITTENSOR_REFRESH_STAKE_INFO } from '@subw
7
7
  import { getEarningStatusByNominations } from '@subwallet/extension-base/koni/api/staking/bonding/utils';
8
8
  import { _getAssetDecimals, _getAssetSymbol } from '@subwallet/extension-base/services/chain-service/utils';
9
9
  import BaseParaStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/base-para';
10
- import { BasicTxErrorType, EarningStatus, StakingTxErrorType } from '@subwallet/extension-base/types';
10
+ import { BasicTxErrorType, EarningStatus, StakingTxErrorType, YieldPoolType } from '@subwallet/extension-base/types';
11
11
  import { ProxyServiceRoute } from '@subwallet/extension-base/types/environment';
12
12
  import { fetchFromProxyService, formatNumber, reformatAddress } from '@subwallet/extension-base/utils';
13
13
  import BigN from 'bignumber.js';
14
14
  import { t } from 'i18next';
15
+ import { BehaviorSubject, combineLatest } from 'rxjs';
15
16
  import { BN, BN_ZERO } from '@polkadot/util';
17
+ import { fetchPoolsData } from "../../service.js";
18
+ const DEFAULT_BITTENSOR_SLIPPAGE = 0.005;
19
+ export const DEFAULT_DTAO_MINBOND = '21000000';
16
20
  /* Fetch data */
17
21
  export class BittensorCache {
18
22
  static instance = null;
@@ -129,6 +133,15 @@ export class BittensorCache {
129
133
  // }
130
134
  // };
131
135
 
136
+ export const getAlphaToTaoRate = async (substrateApi, netuid) => {
137
+ const subnetInfo = (await substrateApi.api.call.subnetInfoRuntimeApi.getDynamicInfo(netuid)).toJSON();
138
+ if (!subnetInfo) {
139
+ return '1';
140
+ }
141
+ const taoIn = subnetInfo.taoIn ? new BigN(subnetInfo.taoIn) : new BigN(0);
142
+ const alphaIn = subnetInfo.alphaIn ? new BigN(subnetInfo.alphaIn) : new BigN(0);
143
+ return netuid === 0 || alphaIn.lte(0) ? '1' : taoIn.dividedBy(alphaIn).toString();
144
+ };
132
145
  export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHandler {
133
146
  availableMethod = {
134
147
  join: true,
@@ -139,6 +152,36 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
139
152
  claimReward: false,
140
153
  changeValidator: true
141
154
  };
155
+ async getMinBond(netuid) {
156
+ var _cachedPool$metadata2, _cachedPool$statistic, _cachedPool$statistic2, _onlinePool$metadata2, _onlinePool$statistic, _onlinePool$statistic2;
157
+ // @ts-ignore
158
+ if (this.type === YieldPoolType.SUBNET_STAKING) {
159
+ var _cachedPool$metadata, _onlinePool$metadata;
160
+ if (!netuid) {
161
+ return new BigN(DEFAULT_DTAO_MINBOND);
162
+ }
163
+ const subnetSlug = `${this.slug}__subnet_${netuid.toString().padStart(2, '0')}`;
164
+ const cachedPool = await this.getPoolInfo(subnetSlug);
165
+ if (cachedPool !== null && cachedPool !== void 0 && (_cachedPool$metadata = cachedPool.metadata) !== null && _cachedPool$metadata !== void 0 && _cachedPool$metadata.minValidate) {
166
+ return new BigN(cachedPool.metadata.minValidate);
167
+ }
168
+
169
+ // If can't get from cached -> get data online
170
+ const onlineData = await fetchPoolsData();
171
+ const onlinePool = onlineData[subnetSlug];
172
+ return new BigN((onlinePool === null || onlinePool === void 0 ? void 0 : (_onlinePool$metadata = onlinePool.metadata) === null || _onlinePool$metadata === void 0 ? void 0 : _onlinePool$metadata.minValidate) || DEFAULT_DTAO_MINBOND);
173
+ }
174
+ const cachedPool = await this.getPoolInfo(this.slug);
175
+ if (cachedPool !== null && cachedPool !== void 0 && (_cachedPool$metadata2 = cachedPool.metadata) !== null && _cachedPool$metadata2 !== void 0 && _cachedPool$metadata2.minValidate || cachedPool !== null && cachedPool !== void 0 && (_cachedPool$statistic = cachedPool.statistic) !== null && _cachedPool$statistic !== void 0 && (_cachedPool$statistic2 = _cachedPool$statistic.earningThreshold) !== null && _cachedPool$statistic2 !== void 0 && _cachedPool$statistic2.join) {
176
+ var _cachedPool$metadata3, _cachedPool$statistic3, _cachedPool$statistic4;
177
+ return new BigN(((_cachedPool$metadata3 = cachedPool.metadata) === null || _cachedPool$metadata3 === void 0 ? void 0 : _cachedPool$metadata3.minValidate) || ((_cachedPool$statistic3 = cachedPool.statistic) === null || _cachedPool$statistic3 === void 0 ? void 0 : (_cachedPool$statistic4 = _cachedPool$statistic3.earningThreshold) === null || _cachedPool$statistic4 === void 0 ? void 0 : _cachedPool$statistic4.join) || 0);
178
+ }
179
+
180
+ // If can get from cached -> get data online
181
+ const onlineData = await fetchPoolsData();
182
+ const onlinePool = onlineData[this.slug];
183
+ return new BigN((onlinePool === null || onlinePool === void 0 ? void 0 : (_onlinePool$metadata2 = onlinePool.metadata) === null || _onlinePool$metadata2 === void 0 ? void 0 : _onlinePool$metadata2.minValidate) || (onlinePool === null || onlinePool === void 0 ? void 0 : (_onlinePool$statistic = onlinePool.statistic) === null || _onlinePool$statistic === void 0 ? void 0 : (_onlinePool$statistic2 = _onlinePool$statistic.earningThreshold) === null || _onlinePool$statistic2 === void 0 ? void 0 : _onlinePool$statistic2.join) || 0);
184
+ }
142
185
  constructor(state, chain) {
143
186
  super(state, chain);
144
187
  this.bittensorCache = BittensorCache.getInstance();
@@ -164,83 +207,96 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
164
207
 
165
208
  async subscribePoolInfo(callback) {
166
209
  let cancel = false;
167
- const substrateApi = this.substrateApi;
168
- const updateStakingInfo = async () => {
210
+ const substrateApi = await this.substrateApi.isReady;
211
+ const aprSubject = new BehaviorSubject(0);
212
+ const fetchAPR = async () => {
169
213
  try {
214
+ const _topValidator = await this.bittensorCache.fetchApr(0);
215
+ const validators = _topValidator.data;
216
+ const highestApr = validators === null || validators === void 0 ? void 0 : validators[0];
217
+ const apr = this.chain === 'bittensor' ? Number((highestApr === null || highestApr === void 0 ? void 0 : highestApr.thirty_day_apy) || 0) * 100 : 0;
218
+ aprSubject.next(apr);
219
+ } catch (e) {
220
+ console.error('Fetch APR error:', e);
221
+ }
222
+ };
223
+ await fetchAPR();
224
+ const interval = setInterval(() => {
225
+ fetchAPR().catch(console.error);
226
+ }, BITTENSOR_REFRESH_STAKE_APY);
227
+ const rxSubnetTAO = substrateApi.api.rx.query.subtensorModule.subnetTAO(0);
228
+ const rxMinDelegatorStake = substrateApi.api.rx.query.subtensorModule.nominatorMinRequiredStake();
229
+ const rxMaxValidators = substrateApi.api.rx.query.subtensorModule.maxAllowedValidators(0);
230
+ const subscription = combineLatest([rxMinDelegatorStake, rxMaxValidators, rxSubnetTAO, aprSubject]).subscribe({
231
+ next: ([minDelegatorStake, maxValidators, taoIn, apr]) => {
170
232
  if (cancel) {
171
233
  return;
172
234
  }
173
- const minDelegatorStake = (await substrateApi.api.query.subtensorModule.nominatorMinRequiredStake()).toPrimitive() || 0;
174
- const maxValidatorPerNominator = (await substrateApi.api.query.subtensorModule.maxAllowedValidators(0)).toPrimitive();
175
- const taoIn = (await substrateApi.api.query.subtensorModule.subnetTAO(0)).toPrimitive();
176
- const _topValidator = await this.bittensorCache.fetchApr(0);
177
- const validators = _topValidator.data;
178
- const highestApr = validators[0];
179
- const bnTaoIn = new BigN(taoIn);
180
- const BNminDelegatorStake = new BigN(minDelegatorStake.toString());
181
- const apr = this.chain === 'bittensor' ? Number(highestApr.thirty_day_apy) * 100 : 0;
182
- const data = {
183
- ...this.baseInfo,
184
- type: this.type,
185
- metadata: {
186
- ...this.metadataInfo,
187
- description: this.getDescription(formatNumber(BNminDelegatorStake, _getAssetDecimals(this.nativeToken)))
188
- },
189
- statistic: {
190
- assetEarning: [{
191
- slug: this.nativeToken.slug
192
- }],
193
- maxCandidatePerFarmer: Number(maxValidatorPerNominator),
194
- maxWithdrawalRequestPerFarmer: 1,
195
- earningThreshold: {
196
- join: BNminDelegatorStake.toString(),
197
- defaultUnstake: '0',
198
- fastUnstake: '0'
235
+ try {
236
+ const bnTaoIn = new BigN(taoIn.toString());
237
+ const bnMinStake = new BigN(minDelegatorStake.toString());
238
+ const minStake = bnMinStake.toString();
239
+ const data = {
240
+ ...this.baseInfo,
241
+ type: this.type,
242
+ metadata: {
243
+ ...this.metadataInfo,
244
+ description: this.getDescription(formatNumber(bnMinStake, _getAssetDecimals(this.nativeToken))),
245
+ minValidate: minStake
199
246
  },
200
- eraTime: 24,
201
- era: 0,
202
- unstakingPeriod: 1.2,
203
- tvl: bnTaoIn.toString(),
204
- totalApy: apr
205
- }
206
- };
207
- callback(data);
208
- } catch (error) {
209
- console.log(error);
247
+ statistic: {
248
+ assetEarning: [{
249
+ slug: this.nativeToken.slug
250
+ }],
251
+ maxCandidatePerFarmer: Number(maxValidators.toString()),
252
+ maxWithdrawalRequestPerFarmer: 1,
253
+ earningThreshold: {
254
+ join: minStake,
255
+ defaultUnstake: '0',
256
+ fastUnstake: '0'
257
+ },
258
+ eraTime: 24,
259
+ era: 0,
260
+ unstakingPeriod: 1.2,
261
+ tvl: bnTaoIn.toString(),
262
+ totalApy: apr
263
+ }
264
+ };
265
+ callback(data);
266
+ } catch (err) {
267
+ console.error(err);
268
+ }
210
269
  }
211
- };
212
- const subscribeStakingMetadataInterval = () => {
213
- updateStakingInfo().catch(console.error);
214
- };
215
- await substrateApi.isReady;
216
- subscribeStakingMetadataInterval();
217
- const interval = setInterval(subscribeStakingMetadataInterval, BITTENSOR_REFRESH_STAKE_APY);
270
+ });
218
271
  return () => {
219
272
  cancel = true;
273
+ aprSubject.complete();
274
+ subscription.unsubscribe();
220
275
  clearInterval(interval);
221
276
  };
222
277
  }
223
278
 
224
279
  /* Subscribe pool position */
225
280
 
226
- async parseNominatorMetadata(chainInfo, address, delegatorState) {
281
+ parseNominatorMetadataBase(chainInfo, delegatorState, minBond, applyRate = false) {
227
282
  const nominationList = [];
228
- const getMinDelegatorStake = this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake();
229
- const minDelegatorStake = (await getMinDelegatorStake).toString();
230
283
  let allActiveStake = BN_ZERO;
231
284
  for (const delegate of delegatorState) {
232
- const activeStake = delegate.amount;
233
- const bnActiveStake = new BN(activeStake);
285
+ const stake = new BigN(delegate.amount);
286
+ const originActiveStake = applyRate ? stake.multipliedBy(delegate.rate || 1).toFixed(0) : stake.toFixed(0);
287
+ const bnActiveStake = new BN(originActiveStake);
234
288
  if (bnActiveStake.gt(BN_ZERO)) {
235
- const delegationStatus = EarningStatus.EARNING_REWARD;
236
289
  allActiveStake = allActiveStake.add(bnActiveStake);
237
290
  nominationList.push({
238
- status: delegationStatus,
291
+ status: EarningStatus.EARNING_REWARD,
239
292
  chain: chainInfo.slug,
240
293
  validatorAddress: delegate.owner,
241
- activeStake: activeStake,
242
- validatorMinStake: minDelegatorStake,
243
- validatorIdentity: delegate.identity
294
+ activeStake: delegate.amount,
295
+ validatorMinStake: minBond,
296
+ validatorIdentity: delegate.identity,
297
+ ...(applyRate ? {
298
+ originActiveStake
299
+ } : {})
244
300
  });
245
301
  }
246
302
  }
@@ -256,6 +312,10 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
256
312
  unstakings: []
257
313
  };
258
314
  }
315
+ async parseNominatorMetadata(chainInfo, delegatorState) {
316
+ const bnMinBond = await this.getMinBond();
317
+ return this.parseNominatorMetadataBase(chainInfo, delegatorState, bnMinBond.toString());
318
+ }
259
319
  async subscribePoolPosition(useAddresses, rsCallback) {
260
320
  let cancel = false;
261
321
  const substrateApi = await this.substrateApi.isReady;
@@ -298,7 +358,7 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
298
358
  });
299
359
  }
300
360
  if (delegateStateInfo && delegateStateInfo.length > 0) {
301
- this.parseNominatorMetadata(chainInfo, owner, delegatorState).then(nominatorMetadata => {
361
+ this.parseNominatorMetadata(chainInfo, delegatorState).then(nominatorMetadata => {
302
362
  rsCallback({
303
363
  ...defaultInfo,
304
364
  ...nominatorMetadata,
@@ -324,61 +384,6 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
324
384
  });
325
385
  }
326
386
  };
327
-
328
- // const getMainnetPoolPosition = async () => {
329
- // const rawDelegateStateInfos = await Promise.all(
330
- // useAddresses.map((address) => fetchTaoDelegateState(address))
331
- // );
332
-
333
- // if (rawDelegateStateInfos.length > 0) {
334
- // rawDelegateStateInfos.forEach((rawDelegateStateInfo, i) => {
335
- // const owner = reformatAddress(useAddresses[i], 42);
336
- // const delegatorState: TaoStakingStakeOption[] = [];
337
- // let bnTotalBalance = BN_ZERO;
338
- // const delegateStateInfo = rawDelegateStateInfo.data;
339
-
340
- // for (const delegate of delegateStateInfo) {
341
- // const name = delegate.hotkey_name || delegate.hotkey.ss58;
342
-
343
- // bnTotalBalance = bnTotalBalance.add(new BN(delegate.stake));
344
-
345
- // delegatorState.push({
346
- // owner: delegate.hotkey.ss58,
347
- // amount: delegate.stake,
348
- // identity: name
349
- // });
350
- // }
351
-
352
- // if (delegateStateInfo && delegateStateInfo.length > 0) {
353
- // this.parseNominatorMetadata(chainInfo, owner, delegatorState)
354
- // .then((nominatorMetadata) => {
355
- // rsCallback({
356
- // ...defaultInfo,
357
- // ...nominatorMetadata,
358
- // address: owner,
359
- // type: this.type
360
- // });
361
- // })
362
- // .catch(console.error);
363
- // } else {
364
- // rsCallback({
365
- // ...defaultInfo,
366
- // type: this.type,
367
- // address: owner,
368
- // balanceToken: this.nativeToken.slug,
369
- // totalStake: '0',
370
- // activeStake: '0',
371
- // unstakeBalance: '0',
372
- // status: EarningStatus.NOT_STAKING,
373
- // isBondedBefore: false,
374
- // nominations: [],
375
- // unstakings: []
376
- // });
377
- // }
378
- // });
379
- // }
380
- // };
381
-
382
387
  const getStakingPositionInterval = async () => {
383
388
  if (cancel) {
384
389
  return;
@@ -403,14 +408,14 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
403
408
  /* Subscribe pool position */
404
409
 
405
410
  /* Get pool targets */
406
-
407
411
  // eslint-disable-next-line @typescript-eslint/require-await
408
- async getDevnetPoolTargets() {
412
+ async getDevnetPoolTargets(netuid) {
409
413
  const testnetDelegate = (await this.substrateApi.api.call.delegateInfoRuntimeApi.getDelegates()).toJSON();
410
- const getNominatorMinRequiredStake = this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake();
411
- const nominatorMinRequiredStake = (await getNominatorMinRequiredStake).toString();
412
- const bnMinBond = new BigN(nominatorMinRequiredStake);
413
- return testnetDelegate.map(delegate => ({
414
+ const bnMinBond = await this.getMinBond(netuid);
415
+ const filteredDelegates = testnetDelegate.filter(delegate => {
416
+ return delegate.returnPer1000 !== 0;
417
+ });
418
+ return filteredDelegates.map(delegate => ({
414
419
  address: delegate.delegateSs58,
415
420
  totalStake: '0',
416
421
  ownStake: '0',
@@ -424,14 +429,12 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
424
429
  isCrowded: false
425
430
  }));
426
431
  }
427
- async getMainnetPoolTargets() {
432
+ async getMainnetPoolTargets(netuid) {
428
433
  const _topValidator = await this.bittensorCache.get();
429
434
  const topValidator = _topValidator;
430
- const getNominatorMinRequiredStake = this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake();
431
- const nominatorMinRequiredStake = (await getNominatorMinRequiredStake).toString();
432
- const bnMinBond = new BigN(nominatorMinRequiredStake);
435
+ const bnMinBond = await this.getMinBond();
433
436
  const validatorList = topValidator.data;
434
- const aprResponse = await this.bittensorCache.fetchApr(0);
437
+ const aprResponse = await this.bittensorCache.fetchApr(netuid);
435
438
  const aprMap = {};
436
439
  aprResponse.data.forEach(item => {
437
440
  aprMap[item.hotkey.ss58] = item.thirty_day_apy;
@@ -466,11 +469,11 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
466
469
  }));
467
470
  return results;
468
471
  }
469
- async getPoolTargets() {
472
+ async getPoolTargets(netuid) {
470
473
  if (this.chain === 'bittensor') {
471
- return this.getMainnetPoolTargets();
474
+ return this.getMainnetPoolTargets(netuid !== null && netuid !== void 0 ? netuid : 0);
472
475
  } else {
473
- return this.getDevnetPoolTargets();
476
+ return this.getDevnetPoolTargets(netuid);
474
477
  }
475
478
  }
476
479
 
@@ -479,15 +482,22 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
479
482
  /* Join pool action */
480
483
 
481
484
  async createJoinExtrinsic(data, positionInfo, bondDest = 'Staked') {
485
+ var _subnetData$netuid, _subnetData$slippage;
482
486
  const {
483
487
  amount,
484
- selectedValidators: targetValidators
488
+ selectedValidators: targetValidators,
489
+ subnetData
485
490
  } = data;
486
491
  const chainApi = await this.substrateApi.isReady;
487
492
  const binaryAmount = new BigN(amount);
488
493
  const selectedValidatorInfo = targetValidators[0];
489
494
  const hotkey = selectedValidatorInfo.address;
490
- const extrinsic = chainApi.api.tx.subtensorModule.addStake(hotkey, 0, binaryAmount.toFixed());
495
+ const netuid = (_subnetData$netuid = subnetData === null || subnetData === void 0 ? void 0 : subnetData.netuid) !== null && _subnetData$netuid !== void 0 ? _subnetData$netuid : 0;
496
+ const slippage = (_subnetData$slippage = subnetData === null || subnetData === void 0 ? void 0 : subnetData.slippage) !== null && _subnetData$slippage !== void 0 ? _subnetData$slippage : DEFAULT_BITTENSOR_SLIPPAGE;
497
+ const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid));
498
+ const limitPrice = alphaToTaoPrice.multipliedBy(10 ** _getAssetDecimals(this.nativeToken)).multipliedBy(1 + slippage);
499
+ const BNlimitPrice = new BigN(limitPrice.integerValue(BigN.ROUND_CEIL).toFixed());
500
+ const extrinsic = chainApi.api.tx.subtensorModule.addStakeLimit(hotkey, netuid, binaryAmount.toFixed(), BNlimitPrice.toFixed(), false);
491
501
  return [extrinsic, {
492
502
  slug: this.nativeToken.slug,
493
503
  amount: '0'
@@ -501,10 +511,10 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
501
511
  return baseErrors;
502
512
  }
503
513
  const {
504
- amount
514
+ amount,
515
+ subnetData
505
516
  } = data;
506
- const minDelegatorStake = (await this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake()).toPrimitive() || 0;
507
- const bnMinStake = minDelegatorStake.toString();
517
+ const bnMinStake = await this.getMinBond(subnetData === null || subnetData === void 0 ? void 0 : subnetData.netuid);
508
518
  if (new BigN(amount).lt(bnMinStake)) {
509
519
  return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t(`Insufficient stake. You need to stake at least ${formatNumber(bnMinStake, _getAssetDecimals(this.nativeToken))} ${_getAssetSymbol(this.nativeToken)} to earn rewards`))];
510
520
  }
@@ -515,17 +525,20 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
515
525
 
516
526
  /* Leave pool action */
517
527
 
518
- async handleYieldUnstake(amount, address, selectedTarget) {
528
+ async handleYieldUnstake(amount, address, selectedTarget, netuid = 0, slippage = DEFAULT_BITTENSOR_SLIPPAGE) {
519
529
  const apiPromise = await this.substrateApi.isReady;
520
- const binaryAmount = new BigN(amount);
521
- const poolPosition = await this.getPoolPosition(address);
522
- if (!selectedTarget || !poolPosition) {
530
+ if (!selectedTarget) {
523
531
  return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
524
532
  }
525
- const extrinsic = apiPromise.api.tx.subtensorModule.removeStake(selectedTarget, 0, binaryAmount.toFixed());
533
+ const binaryAmount = new BigN(amount);
534
+ const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid));
535
+ const limitPrice = alphaToTaoPrice.multipliedBy(10 ** _getAssetDecimals(this.nativeToken)).multipliedBy(1 - slippage);
536
+ const BNlimitPrice = new BigN(limitPrice.integerValue(BigN.ROUND_CEIL).toFixed());
537
+ const extrinsic = apiPromise.api.tx.subtensorModule.removeStakeLimit(selectedTarget, netuid, binaryAmount.toFixed(), BNlimitPrice.toFixed(), false);
526
538
  return [ExtrinsicType.STAKING_UNBOND, extrinsic];
527
539
  }
528
540
  async validateYieldLeave(amount, address, fastLeave, selectedTarget, slug, poolInfo) {
541
+ var _poolInfo$metadata$su;
529
542
  const baseErrors = await super.validateYieldLeave(amount, address, fastLeave, selectedTarget, slug);
530
543
  if (baseErrors.length > 0) {
531
544
  return baseErrors;
@@ -533,10 +546,13 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
533
546
  if (!poolInfo) {
534
547
  return [new TransactionError(BasicTxErrorType.INVALID_PARAMS)];
535
548
  }
536
- const minDelegatorStake = (await this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake()).toPrimitive() || 0;
537
- const bnMinUnstake = new BigN(minDelegatorStake.toString());
538
- if (new BigN(amount).lt(bnMinUnstake)) {
539
- return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t(`Amount too low. You need to unstake at least ${formatNumber(bnMinUnstake, _getAssetDecimals(this.nativeToken))} ${_getAssetSymbol(this.nativeToken)}`))];
549
+ const netuid = (_poolInfo$metadata$su = poolInfo.metadata.subnetData) === null || _poolInfo$metadata$su === void 0 ? void 0 : _poolInfo$metadata$su.netuid;
550
+ const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid || 0));
551
+ const minDelegatorStake = await this.getMinBond(netuid);
552
+ const minUnstake = minDelegatorStake.dividedBy(alphaToTaoPrice);
553
+ if (new BigN(amount).lt(minUnstake)) {
554
+ var _poolInfo$metadata$su2;
555
+ return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t(`Amount too low. You need to unstake at least ${formatNumber(minUnstake, _getAssetDecimals(this.nativeToken))} ${((_poolInfo$metadata$su2 = poolInfo.metadata.subnetData) === null || _poolInfo$metadata$su2 === void 0 ? void 0 : _poolInfo$metadata$su2.subnetSymbol) || _getAssetSymbol(this.nativeToken)}`))];
540
556
  }
541
557
  return baseErrors;
542
558
  }
@@ -549,14 +565,15 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
549
565
  const {
550
566
  amount,
551
567
  maxAmount,
568
+ metadata,
552
569
  originValidator,
553
- selectedValidators: targetValidators
570
+ selectedValidators: targetValidators,
571
+ subnetData
554
572
  } = data;
555
573
  if (!originValidator) {
556
574
  return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS));
557
575
  }
558
-
559
- // Bittensor only supports changing 1 validator at a time, not multiple
576
+ const netuid = (subnetData === null || subnetData === void 0 ? void 0 : subnetData.netuid) || 0;
560
577
  const selectedValidatorInfo = targetValidators[0];
561
578
  const destValidator = selectedValidatorInfo.address;
562
579
  if (new BigN(amount).lte(0)) {
@@ -565,17 +582,20 @@ export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHand
565
582
  if (originValidator === destValidator) {
566
583
  return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'From validator is the same with to validator'));
567
584
  }
568
- const minDelegatorStake = (await this.substrateApi.api.query.subtensorModule.nominatorMinRequiredStake()).toPrimitive() || 0;
569
- const bnMinMoveStake = new BigN(minDelegatorStake.toString());
570
- if (new BigN(maxAmount).lt(bnMinMoveStake)) {
571
- return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t(`Amount too low. You need to move at least ${formatNumber(bnMinMoveStake, _getAssetDecimals(this.nativeToken))} ${_getAssetSymbol(this.nativeToken)}`)));
585
+ const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid));
586
+ const bnMinStake = await this.getMinBond(netuid);
587
+ const minUnstake = bnMinStake.dividedBy(alphaToTaoPrice);
588
+ const formattedMinUnstake = minUnstake.dividedBy(1000000).integerValue(BigN.ROUND_CEIL).dividedBy(1000);
589
+ const bnMinMoveStake = formattedMinUnstake.multipliedBy(10 ** _getAssetDecimals(this.nativeToken));
590
+ if (new BigN(amount).lt(bnMinMoveStake)) {
591
+ return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t(`Amount too low. You need to move at least ${formattedMinUnstake.toString()} ${(metadata === null || metadata === void 0 ? void 0 : metadata.subnetSymbol) || ''}`)));
572
592
  }
573
593
 
574
594
  // Avoid remaining amount too low -> can't do anything with that amount
575
595
  if (!(maxAmount === amount) && new BigN(maxAmount).minus(new BigN(amount)).lt(bnMinMoveStake)) {
576
- return Promise.reject(new TransactionError(StakingTxErrorType.REMAINING_AMOUNT_TOO_LOW, t(`Your remaining stake on the initial validator will fall below minimum active stake and cannot be unstaked if you proceed with the chosen amount. Hit "Move all" to move all ${formatNumber(maxAmount, _getAssetDecimals(this.nativeToken))} ${_getAssetSymbol(this.nativeToken)} to the new validator, or "Cancel" and lower the amount, then try again`)));
596
+ return Promise.reject(new TransactionError(StakingTxErrorType.REMAINING_AMOUNT_TOO_LOW, t(`Your remaining stake on the initial validator will fall below minimum active stake and cannot be unstaked if you proceed with the chosen amount. Hit "Move all" to move all ${formatNumber(maxAmount, _getAssetDecimals(this.nativeToken))} ${(metadata === null || metadata === void 0 ? void 0 : metadata.subnetSymbol) || _getAssetSymbol(this.nativeToken)} to the new validator, or "Cancel" and lower the amount, then try again`)));
577
597
  }
578
- const extrinsic = chainApi.api.tx.subtensorModule.moveStake(originValidator, destValidator, 0, 0, amount);
598
+ const extrinsic = chainApi.api.tx.subtensorModule.moveStake(originValidator, destValidator, netuid, netuid, amount);
579
599
  return extrinsic;
580
600
  }
581
601
  }
@@ -4,7 +4,6 @@ import { PalletNominationPoolsPoolMember } from '@subwallet/extension-base/core/
4
4
  import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
5
5
  import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
6
6
  import { BaseYieldPositionInfo, EarningRewardHistoryItem, EarningRewardItem, HandleYieldStepData, NominationPoolInfo, OptimalYieldPath, OptimalYieldPathParams, StakeCancelWithdrawalParams, SubmitChangeValidatorStaking, SubmitJoinNominationPool, SubmitYieldJoinData, TransactionData, YieldPoolInfo, YieldPoolMethodInfo, YieldPoolType, YieldPositionInfo, YieldStepBaseInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types';
7
- import { DeriveSessionProgress } from '@polkadot/api-derive/types';
8
7
  import BasePoolHandler from '../base';
9
8
  export default class NominationPoolHandler extends BasePoolHandler {
10
9
  readonly type = YieldPoolType.NOMINATION_POOL;
@@ -16,7 +15,7 @@ export default class NominationPoolHandler extends BasePoolHandler {
16
15
  constructor(state: KoniState, chain: string);
17
16
  protected getDescription(amount?: string): string;
18
17
  subscribePoolInfo(callback: (data: YieldPoolInfo) => void): Promise<VoidFunction>;
19
- parsePoolMemberMetadata(substrateApi: _SubstrateApi, poolMemberInfo: PalletNominationPoolsPoolMember, currentEra: string, _deriveSessionProgress: DeriveSessionProgress, address: string): Promise<Omit<YieldPositionInfo, keyof BaseYieldPositionInfo>>;
18
+ parsePoolMemberMetadata(substrateApi: _SubstrateApi, poolMemberInfo: PalletNominationPoolsPoolMember, currentEra: string, address: string): Promise<Omit<YieldPositionInfo, keyof BaseYieldPositionInfo>>;
20
19
  subscribePoolPosition(useAddresses: string[], resultCallback: (rs: YieldPositionInfo) => void): Promise<VoidFunction>;
21
20
  getPoolReward(useAddresses: string[], callBack: (rs: EarningRewardItem) => void): Promise<VoidFunction>;
22
21
  getPoolRewardHistory(useAddresses: string[], callBack: (rs: EarningRewardHistoryItem) => void): Promise<VoidFunction>;
@@ -150,7 +150,7 @@ export default class NominationPoolHandler extends BasePoolHandler {
150
150
 
151
151
  /* Subscribe pool position */
152
152
 
153
- async parsePoolMemberMetadata(substrateApi, poolMemberInfo, currentEra, _deriveSessionProgress, address) {
153
+ async parsePoolMemberMetadata(substrateApi, poolMemberInfo, currentEra, address) {
154
154
  const chainInfo = this.chainInfo;
155
155
  const unlimitedNominatorRewarded = substrateApi.api.consts.staking.maxExposurePageSize !== undefined;
156
156
  const _maxNominatorRewardedPerValidator = (substrateApi.api.consts.staking.maxNominatorRewardedPerValidator || 0).toString();
@@ -245,14 +245,13 @@ export default class NominationPoolHandler extends BasePoolHandler {
245
245
  return;
246
246
  }
247
247
  if (ledgers) {
248
- var _substrateApi$api$der, _substrateApi$api$der2;
249
- const [_currentEra, _deriveSessionProgress] = await Promise.all([substrateApi.api.query.staking.currentEra(), (_substrateApi$api$der = substrateApi.api.derive) === null || _substrateApi$api$der === void 0 ? void 0 : (_substrateApi$api$der2 = _substrateApi$api$der.session) === null || _substrateApi$api$der2 === void 0 ? void 0 : _substrateApi$api$der2.progress()]);
248
+ const _currentEra = await substrateApi.api.query.staking.currentEra();
250
249
  const currentEra = _currentEra.toString();
251
250
  await Promise.all(ledgers.map(async (_poolMemberInfo, i) => {
252
251
  const poolMemberInfo = _poolMemberInfo.toPrimitive();
253
252
  const owner = reformatAddress(useAddresses[i], 42);
254
253
  if (poolMemberInfo) {
255
- const nominatorMetadata = await this.parsePoolMemberMetadata(substrateApi, poolMemberInfo, currentEra, _deriveSessionProgress, owner);
254
+ const nominatorMetadata = await this.parsePoolMemberMetadata(substrateApi, poolMemberInfo, currentEra, owner);
256
255
  resultCallback({
257
256
  ...defaultInfo,
258
257
  ...nominatorMetadata,
@@ -565,7 +564,14 @@ export default class NominationPoolHandler extends BasePoolHandler {
565
564
  async handleYieldWithdraw(address, unstakingInfo) {
566
565
  const chainApi = await this.substrateApi.isReady;
567
566
  if (chainApi.api.tx.nominationPools.withdrawUnbonded.meta.args.length === 2) {
568
- const slashingSpanCount = await chainApi.api.call.nominationPoolsApi.memberPendingSlash(address);
567
+ var _chainApi$api$call, _chainApi$api$call$no;
568
+ let slashingSpanCount;
569
+ if ((_chainApi$api$call = chainApi.api.call) !== null && _chainApi$api$call !== void 0 && (_chainApi$api$call$no = _chainApi$api$call.nominationPoolsApi) !== null && _chainApi$api$call$no !== void 0 && _chainApi$api$call$no.memberPendingSlash) {
570
+ slashingSpanCount = await chainApi.api.call.nominationPoolsApi.memberPendingSlash(address);
571
+ } else {
572
+ // Incase api call not exists
573
+ slashingSpanCount = chainApi.api.consts.staking.historyDepth.toPrimitive();
574
+ }
569
575
  return chainApi.api.tx.nominationPools.withdrawUnbonded({
570
576
  Id: address
571
577
  }, slashingSpanCount);
@@ -8,6 +8,7 @@ import { PromiseHandler } from '@subwallet/extension-base/utils';
8
8
  import { BehaviorSubject } from 'rxjs';
9
9
  import { EarningSlippageResult } from './handlers/native-staking/dtao';
10
10
  import { BasePoolHandler } from './handlers';
11
+ export declare const fetchPoolsData: () => Promise<Record<string, YieldPoolInfo>>;
11
12
  export default class EarningService implements StoppableServiceInterface, PersistDataServiceInterface {
12
13
  protected readonly state: KoniState;
13
14
  protected handlers: Record<string, BasePoolHandler>;
@@ -14,7 +14,7 @@ import { addLazy, createPromiseHandler, filterAddressByChainInfo, removeLazy } f
14
14
  import { fetchStaticCache } from '@subwallet/extension-base/utils/fetchStaticCache';
15
15
  import { BehaviorSubject, combineLatest } from 'rxjs';
16
16
  import { AcalaLiquidStakingPoolHandler, AmplitudeNativeStakingPoolHandler, AstarNativeStakingPoolHandler, BifrostLiquidStakingPoolHandler, BifrostMantaLiquidStakingPoolHandler, InterlayLendingPoolHandler, NominationPoolHandler, ParallelLiquidStakingPoolHandler, ParaNativeStakingPoolHandler, RelayNativeStakingPoolHandler, StellaSwapLiquidStakingPoolHandler, SubnetTaoStakingPoolHandler, TaoNativeStakingPoolHandler } from "./handlers/index.js";
17
- const fetchPoolsData = async () => {
17
+ export const fetchPoolsData = async () => {
18
18
  const fetchData = await fetchStaticCache('earning/yield-pools.json', {
19
19
  data: {}
20
20
  });
@@ -350,7 +350,9 @@ export default class EarningService {
350
350
  const unsubList = [];
351
351
  for (const handler of Object.values(this.handlers)) {
352
352
  // Force subscribe onchain data
353
- const forceSubscribe = handler.type === YieldPoolType.LIQUID_STAKING || handler.type === YieldPoolType.LENDING || !onlineData[handler.slug];
353
+ const forceSubscribe = handler.type === YieldPoolType.LIQUID_STAKING || handler.type === YieldPoolType.LENDING ||
354
+ // Skip subscribing for subnet staking handlers because subnet staking slugs are not included in the online cache (only slugs with netuid are cached)
355
+ !onlineData[handler.slug] && handler.type !== YieldPoolType.SUBNET_STAKING;
354
356
  if (!this.useOnlineCacheOnly || forceSubscribe) {
355
357
  handler.subscribePoolInfo(callback).then(unsub => {
356
358
  if (!cancel) {
@@ -4,7 +4,7 @@
4
4
  import { _AssetType } from '@subwallet/chain-list/types';
5
5
  import { _getAssetDecimals, _getAssetPriceId, _getTokenOnChainAssetId } from '@subwallet/extension-base/services/chain-service/utils';
6
6
  import { checkLiquidityForPool, estimateTokensForPool, getReserveForPool } from '@subwallet/extension-base/services/swap-service/handler/asset-hub/utils';
7
- import subwalletApiSdk from '@subwallet/subwallet-api-sdk';
7
+ import subwalletApiSdk from '@subwallet-monorepos/subwallet-services-sdk';
8
8
  import BigN from 'bignumber.js';
9
9
  export async function getAssetHubTokensCanPayFee(request) {
10
10
  const {
@@ -122,20 +122,24 @@ export function batchExtrinsicSetFeeHydration(substrateApi, tx, feeSetting, asse
122
122
  return tx;
123
123
  }
124
124
  export async function getHydrationRate(address, hdx, desToken) {
125
- var _subwalletApiSdk$swap;
126
- const quoteRate = await ((_subwalletApiSdk$swap = subwalletApiSdk.swapApi) === null || _subwalletApiSdk$swap === void 0 ? void 0 : _subwalletApiSdk$swap.getHydrationRate({
127
- address,
128
- pair: {
129
- slug: `${hdx.slug}___${desToken.slug}`,
130
- from: hdx.slug,
131
- to: desToken.slug
132
- }
133
- }));
134
- if (!quoteRate) {
135
- return undefined;
136
- } else {
125
+ let quoteRate;
126
+ try {
127
+ const quote = await subwalletApiSdk.swapApi.getHydrationRate({
128
+ address,
129
+ pair: {
130
+ slug: `${hdx.slug}___${desToken.slug}`,
131
+ from: hdx.slug,
132
+ to: desToken.slug
133
+ }
134
+ });
135
+ quoteRate = quote.rate;
136
+ } catch (error) {
137
+ console.error(`Failed to fetch swap quote: ${error.message}`);
138
+ }
139
+ if (quoteRate) {
137
140
  const hdxDecimal = _getAssetDecimals(hdx);
138
141
  const desTokenDecimal = _getAssetDecimals(desToken);
139
142
  return new BigN(quoteRate).multipliedBy(10 ** (desTokenDecimal - hdxDecimal)).toFixed();
140
143
  }
144
+ return undefined;
141
145
  }