Skip to content

Commit b634c4b

Browse files
committed
[Issue-4187] Feat: Add logic to handle staking on asset hub
1 parent 703114f commit b634c4b

File tree

6 files changed

+71
-10
lines changed

6 files changed

+71
-10
lines changed

packages/extension-base/src/services/chain-service/utils/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,14 @@ export function _getChainNativeTokenSlug (chainInfo: _ChainInfo) {
348348
return `${chainInfo.slug}-${_AssetType.NATIVE}-${_getChainNativeTokenBasicInfo(chainInfo).symbol}`;
349349
}
350350

351+
export function _getChainSubstrateTokenSymbol (chainInfo: _ChainInfo) {
352+
if (chainInfo.substrateInfo) {
353+
return chainInfo.substrateInfo.symbol || '';
354+
} else {
355+
return '';
356+
}
357+
}
358+
351359
export function _isLocalToken (tokenInfo: _ChainAsset) {
352360
return tokenInfo.assetType === _AssetType.LOCAL;
353361
}

packages/extension-base/src/services/earning-service/handlers/native-staking/base.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ export default abstract class BaseNativeStakingPoolHandler extends BasePoolHandl
2424
claimReward: false
2525
};
2626

27+
static generateSlug (symbol: string, chain: string): string {
28+
return `${symbol}___native_staking___${chain}`;
29+
}
30+
2731
constructor (state: KoniState, chain: string) {
2832
super(state, chain);
2933

packages/extension-base/src/services/earning-service/handlers/nomination-pool/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ export default class NominationPoolHandler extends BasePoolHandler {
3636
claimReward: true
3737
};
3838

39+
static generateSlug (symbol: string, chain: string): string {
40+
return `${symbol}___nomination_pool___${chain}`;
41+
}
42+
3943
constructor (state: KoniState, chain: string) {
4044
super(state, chain);
4145

@@ -108,7 +112,8 @@ export default class NominationPoolHandler extends BasePoolHandler {
108112
const unlockingEras = substrateApi.api.consts.staking.bondingDuration.toString();
109113

110114
const maxSupportedEras = substrateApi.api.consts.staking.historyDepth.toString();
111-
const erasPerDay = 24 / _STAKING_ERA_LENGTH_MAP[chainInfo.slug]; // Can be exactly calculate from epochDuration, blockTime, sessionsPerEra
115+
const eraInHours = _STAKING_ERA_LENGTH_MAP[chainInfo.slug] || _STAKING_ERA_LENGTH_MAP.default; // in hours
116+
const erasPerDay = 24 / eraInHours; // Can be exactly calculate from epochDuration, blockTime, sessionsPerEra
112117

113118
const supportedDays = getSupportedDaysByHistoryDepth(erasPerDay, parseInt(maxSupportedEras), parseInt(currentEra) / erasPerDay);
114119

packages/extension-base/src/services/earning-service/service.ts

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,17 @@ import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/K
66
import { CRON_REFRESH_CHAIN_STAKING_METADATA, CRON_REFRESH_EARNING_REWARD_HISTORY_INTERVAL, CRON_REFRESH_STAKING_REWARD_FAST_INTERVAL } from '@subwallet/extension-base/constants';
77
import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
88
import { PersistDataServiceInterface, ServiceStatus, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
9-
import { _isChainEnabled, _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils';
9+
import { _isChainEnabled, _isChainEvmCompatible, _getChainSubstrateTokenSymbol } from '@subwallet/extension-base/services/chain-service/utils';
1010
import { _STAKING_CHAIN_GROUP } from '@subwallet/extension-base/services/earning-service/constants';
1111
import BaseLiquidStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/liquid-staking/base';
1212
import MythosNativeStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/mythos';
1313
import { EventService } from '@subwallet/extension-base/services/event-service';
1414
import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService';
1515
import { SWTransactionBase } from '@subwallet/extension-base/services/transaction-service/types';
1616
import { BasicTxErrorType, EarningRewardHistoryItem, EarningRewardItem, EarningRewardJson, HandleYieldStepData, HandleYieldStepParams, OptimalYieldPath, OptimalYieldPathParams, RequestEarlyValidateYield, RequestEarningSlippage, RequestStakeCancelWithdrawal, RequestStakeClaimReward, RequestYieldLeave, RequestYieldWithdrawal, ResponseEarlyValidateYield, TransactionData, ValidateYieldProcessParams, YieldPoolInfo, YieldPoolTarget, YieldPoolType, YieldPositionInfo } from '@subwallet/extension-base/types';
17-
import { addLazy, createPromiseHandler, getAddressesByChainType, PromiseHandler, removeLazy } from '@subwallet/extension-base/utils';
17+
import { addLazy, createPromiseHandler, fetchStaticData, getAddressesByChainType, PromiseHandler, removeLazy } from '@subwallet/extension-base/utils';
1818
import { fetchStaticCache } from '@subwallet/extension-base/utils/fetchStaticCache';
1919
import { BehaviorSubject } from 'rxjs';
20-
2120
import { EarningSlippageResult } from './handlers/native-staking/dtao';
2221
import { AcalaLiquidStakingPoolHandler, AmplitudeNativeStakingPoolHandler, AstarNativeStakingPoolHandler, BasePoolHandler, BifrostLiquidStakingPoolHandler, BifrostMantaLiquidStakingPoolHandler, InterlayLendingPoolHandler, NominationPoolHandler, ParallelLiquidStakingPoolHandler, ParaNativeStakingPoolHandler, RelayNativeStakingPoolHandler, StellaSwapLiquidStakingPoolHandler, SubnetTaoStakingPoolHandler, TaoNativeStakingPoolHandler } from './handlers';
2322

@@ -27,10 +26,15 @@ const fetchPoolsData = async () => {
2726
return fetchData.data;
2827
};
2928

29+
const fetchAhMapChain = async () => {
30+
return await fetchStaticData<Record<string, string>>('asset-hub-staking-map');
31+
};
32+
3033
export default class EarningService implements StoppableServiceInterface, PersistDataServiceInterface {
3134
protected readonly state: KoniState;
3235
protected handlers: Record<string, BasePoolHandler> = {};
3336
private handlerCache: Map<string, BasePoolHandler | undefined> = new Map();
37+
private inactivePoolSlug: Set<string> = new Set<string>();
3438

3539
private earningRewardSubject: BehaviorSubject<EarningRewardJson> = new BehaviorSubject<EarningRewardJson>({ ready: false, data: {} });
3640
private earningRewardHistorySubject: BehaviorSubject<Record<string, EarningRewardHistoryItem>> = new BehaviorSubject<Record<string, EarningRewardHistoryItem>>({});
@@ -44,6 +48,7 @@ export default class EarningService implements StoppableServiceInterface, Persis
4448
private dbService: DatabaseService;
4549
private eventService: EventService;
4650
private useOnlineCacheOnly = true;
51+
private inactivePoolReady: PromiseHandler<void> = createPromiseHandler();
4752

4853
constructor (state: KoniState) {
4954
this.state = state;
@@ -66,12 +71,25 @@ export default class EarningService implements StoppableServiceInterface, Persis
6671
}
6772

6873
const minAmountPercent: Record<string, number> = {};
74+
const ahMapChain = await fetchAhMapChain();
6975

7076
for (const chain of chains) {
7177
const handlers: BasePoolHandler[] = [];
78+
const chainInfo = this.state.getChainInfo(chain);
79+
const symbol = _getChainSubstrateTokenSymbol(chainInfo);
7280

7381
if (_STAKING_CHAIN_GROUP.relay.includes(chain)) {
74-
handlers.push(new RelayNativeStakingPoolHandler(this.state, chain));
82+
const ahChain = ahMapChain[chain];
83+
84+
if (ahChain) {
85+
handlers.push(new RelayNativeStakingPoolHandler(this.state, ahChain));
86+
87+
const relaySlug = RelayNativeStakingPoolHandler.generateSlug(symbol, chain);
88+
89+
this.inactivePoolSlug.add(relaySlug);
90+
} else {
91+
handlers.push(new RelayNativeStakingPoolHandler(this.state, chain));
92+
}
7593
}
7694

7795
if (_STAKING_CHAIN_GROUP.para.includes(chain)) {
@@ -98,7 +116,17 @@ export default class EarningService implements StoppableServiceInterface, Persis
98116
}
99117

100118
if (_STAKING_CHAIN_GROUP.nominationPool.includes(chain)) {
101-
handlers.push(new NominationPoolHandler(this.state, chain));
119+
const ahChain = ahMapChain[chain];
120+
121+
if (ahChain) {
122+
handlers.push(new NominationPoolHandler(this.state, ahChain));
123+
124+
const relaySlug = NominationPoolHandler.generateSlug(symbol, chain);
125+
126+
this.inactivePoolSlug.add(relaySlug);
127+
} else {
128+
handlers.push(new NominationPoolHandler(this.state, chain));
129+
}
102130
}
103131

104132
if (_STAKING_CHAIN_GROUP.liquidStaking.includes(chain)) {
@@ -140,6 +168,7 @@ export default class EarningService implements StoppableServiceInterface, Persis
140168
minAmountPercent.default = BaseLiquidStakingPoolHandler.defaultMinAmountPercent;
141169

142170
this.minAmountPercentSubject.next(minAmountPercent);
171+
this.inactivePoolReady.resolve();
143172

144173
// Emit earning ready
145174
this.eventService.emit('earning.ready', true);
@@ -162,7 +191,7 @@ export default class EarningService implements StoppableServiceInterface, Persis
162191
next: (data) => {
163192
const activeMap = this.state.getActiveChainInfoMap();
164193
const activePositions = Object.values(data).filter((item) => {
165-
return !!activeMap[item.chain];
194+
return !!activeMap[item.chain] && !this.inactivePoolSlug.has(item.slug);
166195
});
167196

168197
this.yieldPositionListSubject.next(Object.values(activePositions));
@@ -401,7 +430,9 @@ export default class EarningService implements StoppableServiceInterface, Persis
401430
const existedYieldPoolInfo = await this.dbService.getYieldPools();
402431

403432
existedYieldPoolInfo.forEach((info) => {
404-
yieldPoolInfo[info.slug] = info;
433+
if (!this.inactivePoolSlug.has(info.slug)) {
434+
yieldPoolInfo[info.slug] = info;
435+
}
405436
});
406437

407438
this.yieldPoolInfoSubject.next(yieldPoolInfo);
@@ -447,6 +478,12 @@ export default class EarningService implements StoppableServiceInterface, Persis
447478
private async fetchingPoolsInfoOnline () {
448479
const onlineData = await fetchPoolsData();
449480

481+
await this.inactivePoolReady.promise;
482+
483+
for (const inactiveSlug of this.inactivePoolSlug) {
484+
delete onlineData[inactiveSlug];
485+
}
486+
450487
Object.values(onlineData).forEach((item) => {
451488
this.updateYieldPoolInfo(item);
452489
});
@@ -566,7 +603,9 @@ export default class EarningService implements StoppableServiceInterface, Persis
566603
const yieldPositionInfo = this.yieldPositionSubject.getValue();
567604

568605
existedYieldPosition.forEach((item) => {
569-
yieldPositionInfo[this._getYieldPositionKey(item.slug, item.address)] = item;
606+
if (!this.inactivePoolSlug.has(item.slug)) {
607+
yieldPositionInfo[this._getYieldPositionKey(item.slug, item.address)] = item;
608+
}
570609
});
571610

572611
this.yieldPositionSubject.next(yieldPositionInfo);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

packages/extension-base/src/utils/staticData/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export const blockedActions: Record<string, EnvConfig> = require('./blockedActio
2828
export const oldChainPrefix: Record<string, EnvConfig> = require('./oldChainPrefix.json');
2929
// eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
3030
export const paraSpellChainMap: Record<string, EnvConfig> = require('./paraSpellChainMap.json');
31+
// eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
32+
export const assetHubStakingMap: Record<string, EnvConfig> = require('./assetHubStaking.json');
3133

3234
export enum StaticKey {
3335
BUY_SERVICE_INFOS = 'buy-service-infos',
@@ -42,6 +44,7 @@ export enum StaticKey {
4244
BLOCKED_ACTIONS = 'blocked-actions',
4345
OLD_CHAIN_PREFIX = 'old-chain-prefix',
4446
PARASPELL_CHAIN_MAP= 'paraspell-chain-map',
47+
ASSET_HUB_STAKING_MAP= 'asset-hub-staking-map',
4548
}
4649

4750
export const staticData = {
@@ -56,5 +59,6 @@ export const staticData = {
5659
[StaticKey.REMIND_NOTIFICATION_TIME]: remindNotificationTime,
5760
[StaticKey.BLOCKED_ACTIONS]: blockedActions,
5861
[StaticKey.OLD_CHAIN_PREFIX]: oldChainPrefix,
59-
[StaticKey.PARASPELL_CHAIN_MAP]: paraSpellChainMap
62+
[StaticKey.PARASPELL_CHAIN_MAP]: paraSpellChainMap,
63+
[StaticKey.ASSET_HUB_STAKING_MAP]: assetHubStakingMap
6064
};

0 commit comments

Comments
 (0)