Skip to content

[Issue-4187] Asset Hub Migration #4381

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: subwallet-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,14 @@ export function _getChainNativeTokenSlug (chainInfo: _ChainInfo) {
return `${chainInfo.slug}-${_AssetType.NATIVE}-${_getChainNativeTokenBasicInfo(chainInfo).symbol}`;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1000000000000000000000000000000000000

}

export function _getChainSubstrateTokenSymbol (chainInfo: _ChainInfo) {
if (chainInfo.substrateInfo) {
return chainInfo.substrateInfo.symbol || '';
} else {
return '';
}
}

export function _isLocalToken (tokenInfo: _ChainAsset) {
return tokenInfo.assetType === _AssetType.LOCAL;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export default abstract class BaseNativeStakingPoolHandler extends BasePoolHandl
claimReward: false
};

static generateSlug (symbol: string, chain: string): string {
return `${symbol}___native_staking___${chain}`;
}

constructor (state: KoniState, chain: string) {
super(state, chain);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -796,8 +796,18 @@ export default class RelayNativeStakingPoolHandler extends BaseNativeStakingPool
const chainApi = await this.substrateApi.isReady;

if (chainApi.api.tx.staking.withdrawUnbonded.meta.args.length === 1) {
const _slashingSpans = (await chainApi.api.query.staking.slashingSpans(address)).toHuman() as Record<string, any>;
const slashingSpanCount = _slashingSpans !== null ? _slashingSpans.spanIndex as string : '0';
let slashingSpanCount: string | number;

if (chainApi.api.query.staking.nominatorSlashInEra) {
const currentEra = await chainApi.api.query.staking.currentEra();
const slashingSpans = (await chainApi.api.query.staking.nominatorSlashInEra(currentEra.toPrimitive(), address)).toPrimitive() as number;

slashingSpanCount = slashingSpans !== null ? slashingSpans.toString() : '0';
} else {
const _slashingSpans = (await chainApi.api.query.staking.slashingSpans(address)).toHuman() as Record<string, any>;

slashingSpanCount = _slashingSpans !== null ? _slashingSpans.spanIndex as string : '0';
}

return chainApi.api.tx.staking.withdrawUnbonded(slashingSpanCount);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export default class NominationPoolHandler extends BasePoolHandler {
claimReward: true
};

static generateSlug (symbol: string, chain: string): string {
return `${symbol}___nomination_pool___${chain}`;
}

constructor (state: KoniState, chain: string) {
super(state, chain);

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

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

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

Expand Down
54 changes: 47 additions & 7 deletions packages/extension-base/src/services/earning-service/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/K
import { CRON_REFRESH_CHAIN_STAKING_METADATA, CRON_REFRESH_EARNING_REWARD_HISTORY_INTERVAL, CRON_REFRESH_STAKING_REWARD_FAST_INTERVAL } from '@subwallet/extension-base/constants';
import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
import { PersistDataServiceInterface, ServiceStatus, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
import { _isChainEnabled, _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils';
import { _getChainSubstrateTokenSymbol, _isChainEnabled, _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils';
import { _STAKING_CHAIN_GROUP } from '@subwallet/extension-base/services/earning-service/constants';
import BaseLiquidStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/liquid-staking/base';
import MythosNativeStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/mythos';
import { EventService } from '@subwallet/extension-base/services/event-service';
import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService';
import { SWTransactionBase } from '@subwallet/extension-base/services/transaction-service/types';
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';
import { addLazy, createPromiseHandler, getAddressesByChainType, PromiseHandler, removeLazy } from '@subwallet/extension-base/utils';
import { addLazy, createPromiseHandler, fetchStaticData, getAddressesByChainType, PromiseHandler, removeLazy } from '@subwallet/extension-base/utils';
import { fetchStaticCache } from '@subwallet/extension-base/utils/fetchStaticCache';
import { BehaviorSubject } from 'rxjs';

Expand All @@ -27,10 +27,15 @@ const fetchPoolsData = async () => {
return fetchData.data;
};

const fetchAhMapChain = async () => {
return await fetchStaticData<Record<string, string>>('asset-hub-staking-map');
};

export default class EarningService implements StoppableServiceInterface, PersistDataServiceInterface {
protected readonly state: KoniState;
protected handlers: Record<string, BasePoolHandler> = {};
private handlerCache: Map<string, BasePoolHandler | undefined> = new Map();
private inactivePoolSlug: Set<string> = new Set<string>();

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

constructor (state: KoniState) {
this.state = state;
Expand All @@ -66,12 +72,25 @@ export default class EarningService implements StoppableServiceInterface, Persis
}

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

for (const chain of chains) {
const handlers: BasePoolHandler[] = [];
const chainInfo = this.state.getChainInfo(chain);
const symbol = _getChainSubstrateTokenSymbol(chainInfo);

if (_STAKING_CHAIN_GROUP.relay.includes(chain)) {
handlers.push(new RelayNativeStakingPoolHandler(this.state, chain));
const ahChain = ahMapChain[chain];

if (ahChain) {
handlers.push(new RelayNativeStakingPoolHandler(this.state, ahChain));

const relaySlug = RelayNativeStakingPoolHandler.generateSlug(symbol, chain);

this.inactivePoolSlug.add(relaySlug);
} else {
handlers.push(new RelayNativeStakingPoolHandler(this.state, chain));
}
}

if (_STAKING_CHAIN_GROUP.para.includes(chain)) {
Expand All @@ -98,7 +117,17 @@ export default class EarningService implements StoppableServiceInterface, Persis
}

if (_STAKING_CHAIN_GROUP.nominationPool.includes(chain)) {
handlers.push(new NominationPoolHandler(this.state, chain));
const ahChain = ahMapChain[chain];

if (ahChain) {
handlers.push(new NominationPoolHandler(this.state, ahChain));

const relaySlug = NominationPoolHandler.generateSlug(symbol, chain);

this.inactivePoolSlug.add(relaySlug);
} else {
handlers.push(new NominationPoolHandler(this.state, chain));
}
}

if (_STAKING_CHAIN_GROUP.liquidStaking.includes(chain)) {
Expand Down Expand Up @@ -140,6 +169,7 @@ export default class EarningService implements StoppableServiceInterface, Persis
minAmountPercent.default = BaseLiquidStakingPoolHandler.defaultMinAmountPercent;

this.minAmountPercentSubject.next(minAmountPercent);
this.inactivePoolReady.resolve();

// Emit earning ready
this.eventService.emit('earning.ready', true);
Expand All @@ -162,7 +192,7 @@ export default class EarningService implements StoppableServiceInterface, Persis
next: (data) => {
const activeMap = this.state.getActiveChainInfoMap();
const activePositions = Object.values(data).filter((item) => {
return !!activeMap[item.chain];
return !!activeMap[item.chain] && !this.inactivePoolSlug.has(item.slug);
});

this.yieldPositionListSubject.next(Object.values(activePositions));
Expand Down Expand Up @@ -401,7 +431,9 @@ export default class EarningService implements StoppableServiceInterface, Persis
const existedYieldPoolInfo = await this.dbService.getYieldPools();

existedYieldPoolInfo.forEach((info) => {
yieldPoolInfo[info.slug] = info;
if (!this.inactivePoolSlug.has(info.slug)) {
yieldPoolInfo[info.slug] = info;
}
});

this.yieldPoolInfoSubject.next(yieldPoolInfo);
Expand Down Expand Up @@ -447,6 +479,12 @@ export default class EarningService implements StoppableServiceInterface, Persis
private async fetchingPoolsInfoOnline () {
const onlineData = await fetchPoolsData();

await this.inactivePoolReady.promise;

for (const inactiveSlug of this.inactivePoolSlug) {
delete onlineData[inactiveSlug];
}

Object.values(onlineData).forEach((item) => {
this.updateYieldPoolInfo(item);
});
Expand Down Expand Up @@ -566,7 +604,9 @@ export default class EarningService implements StoppableServiceInterface, Persis
const yieldPositionInfo = this.yieldPositionSubject.getValue();

existedYieldPosition.forEach((item) => {
yieldPositionInfo[this._getYieldPositionKey(item.slug, item.address)] = item;
if (!this.inactivePoolSlug.has(item.slug)) {
yieldPositionInfo[this._getYieldPositionKey(item.slug, item.address)] = item;
}
});

this.yieldPositionSubject.next(yieldPositionInfo);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
6 changes: 5 additions & 1 deletion packages/extension-base/src/utils/staticData/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export const blockedActions: Record<string, EnvConfig> = require('./blockedActio
export const oldChainPrefix: Record<string, EnvConfig> = require('./oldChainPrefix.json');
// eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
export const paraSpellChainMap: Record<string, EnvConfig> = require('./paraSpellChainMap.json');
// eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
export const assetHubStakingMap: Record<string, EnvConfig> = require('./assetHubStaking.json');

export enum StaticKey {
BUY_SERVICE_INFOS = 'buy-service-infos',
Expand All @@ -42,6 +44,7 @@ export enum StaticKey {
BLOCKED_ACTIONS = 'blocked-actions',
OLD_CHAIN_PREFIX = 'old-chain-prefix',
PARASPELL_CHAIN_MAP= 'paraspell-chain-map',
ASSET_HUB_STAKING_MAP= 'asset-hub-staking-map',
}

export const staticData = {
Expand All @@ -56,5 +59,6 @@ export const staticData = {
[StaticKey.REMIND_NOTIFICATION_TIME]: remindNotificationTime,
[StaticKey.BLOCKED_ACTIONS]: blockedActions,
[StaticKey.OLD_CHAIN_PREFIX]: oldChainPrefix,
[StaticKey.PARASPELL_CHAIN_MAP]: paraSpellChainMap
[StaticKey.PARASPELL_CHAIN_MAP]: paraSpellChainMap,
[StaticKey.ASSET_HUB_STAKING_MAP]: assetHubStakingMap
};
Loading