diff --git a/packages/extension-base/src/services/earning-service/handlers/base.ts b/packages/extension-base/src/services/earning-service/handlers/base.ts index e32788c7fc6..155ea2c205b 100644 --- a/packages/extension-base/src/services/earning-service/handlers/base.ts +++ b/packages/extension-base/src/services/earning-service/handlers/base.ts @@ -8,7 +8,7 @@ import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants'; import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; import { _EvmApi, _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { DEFAULT_YIELD_FIRST_STEP } from '@subwallet/extension-base/services/earning-service/constants'; -import { createClaimNotification, createWithdrawNotifications } from '@subwallet/extension-base/services/inapp-notification-service/utils'; +import { createWithdrawNotifications } from '@subwallet/extension-base/services/inapp-notification-service/utils'; import { BasePoolInfo, BaseYieldPoolMetadata, EarningRewardHistoryItem, EarningRewardItem, GenStepFunction, HandleYieldStepData, OptimalYieldPath, OptimalYieldPathParams, RequestEarlyValidateYield, ResponseEarlyValidateYield, StakeCancelWithdrawalParams, SubmitYieldJoinData, TransactionData, UnstakingInfo, YieldPoolInfo, YieldPoolMethodInfo, YieldPoolTarget, YieldPoolType, YieldPositionInfo, YieldStepBaseInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types'; import { formatNumber, reformatAddress } from '@subwallet/extension-base/utils'; @@ -131,11 +131,11 @@ export default abstract class BasePoolHandler { await this.state.inappNotificationService.validateAndWriteNotificationsToDB(notifications, address); } - public async createClaimNotification (claimItemInfo: EarningRewardItem, tokenInfo: _ChainAsset) { - const notification = createClaimNotification(claimItemInfo, tokenInfo); - - await this.state.inappNotificationService.validateAndWriteNotificationsToDB([notification], claimItemInfo.address); - } + // public async createClaimNotification (claimItemInfo: EarningRewardItem, tokenInfo: _ChainAsset) { + // const notification = createClaimNotification(claimItemInfo, tokenInfo); + // + // await this.state.inappNotificationService.validateAndWriteNotificationsToDB([notification], claimItemInfo.address); + // } /** Can mint when haven't enough native token (use input token for fee) */ public get isPoolSupportAlternativeFee (): boolean { @@ -159,7 +159,7 @@ export default abstract class BasePoolHandler { /** Subscribe pool position */ public abstract subscribePoolPosition (useAddresses: string[], callback: (rs: YieldPositionInfo) => void): Promise; /** Get pool reward */ - public abstract getPoolReward (useAddresses: string[], callback: (rs: EarningRewardItem) => void): Promise; + public abstract getPoolReward (useAddresses: string[], callback: (rs: EarningRewardItem, tokenInfo: _ChainAsset) => void): Promise; /** Get pool reward history */ public abstract getPoolRewardHistory (useAddresses: string[], callback: (rs: EarningRewardHistoryItem) => void): Promise; /** Get pool target */ diff --git a/packages/extension-base/src/services/earning-service/handlers/native-staking/amplitude.ts b/packages/extension-base/src/services/earning-service/handlers/native-staking/amplitude.ts index 010432971e2..af25ba693a1 100644 --- a/packages/extension-base/src/services/earning-service/handlers/native-staking/amplitude.ts +++ b/packages/extension-base/src/services/earning-service/handlers/native-staking/amplitude.ts @@ -1,7 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-base // SPDX-License-Identifier: Apache-2.0 -import { _ChainInfo } from '@subwallet/chain-list/types'; +import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types'; import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; import { APIItemState, ExtrinsicType, NominationInfo, UnstakingInfo } from '@subwallet/extension-base/background/KoniTypes'; import { getBondedValidators, getEarningStatusByNominations, isUnstakeAll, KrestDelegateState } from '@subwallet/extension-base/koni/api/staking/bonding/utils'; @@ -320,7 +320,7 @@ export default class AmplitudeNativeStakingPoolHandler extends BaseParaNativeSta /* Get pool reward */ - override async getPoolReward (useAddresses: string[], callBack: (rs: EarningRewardItem) => void): Promise { + override async getPoolReward (useAddresses: string[], callBack: (rs: EarningRewardItem, tokenInfo: _ChainAsset) => void): Promise { let cancel = false; const substrateApi = this.substrateApi; @@ -346,8 +346,9 @@ export default class AmplitudeNativeStakingPoolHandler extends BaseParaNativeSta // if (_unclaimedReward.toString() !== '0') { // await this.createClaimNotification(earningRewardItem, this.nativeToken); // } - - callBack(earningRewardItem); + if (_unclaimedReward.toString() !== '0') { + callBack(earningRewardItem, this.nativeToken); + } })); } diff --git a/packages/extension-base/src/services/earning-service/handlers/native-staking/base.ts b/packages/extension-base/src/services/earning-service/handlers/native-staking/base.ts index 8d4734393ab..3b949bd1cc3 100644 --- a/packages/extension-base/src/services/earning-service/handlers/native-staking/base.ts +++ b/packages/extension-base/src/services/earning-service/handlers/native-staking/base.ts @@ -1,6 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-base // SPDX-License-Identifier: Apache-2.0 +import { _ChainAsset } from '@subwallet/chain-list/types'; import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes'; import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; @@ -46,7 +47,7 @@ export default abstract class BaseNativeStakingPoolHandler extends BasePoolHandl /* Get pool reward */ - async getPoolReward (useAddresses: string[], callBack: (rs: EarningRewardItem) => void): Promise { + async getPoolReward (useAddresses: string[], callBack: (rs: EarningRewardItem, tokenInfo: _ChainAsset) => void): Promise { return new Promise((resolve) => resolve(noop)); } diff --git a/packages/extension-base/src/services/earning-service/handlers/native-staking/mythos.ts b/packages/extension-base/src/services/earning-service/handlers/native-staking/mythos.ts index 10f5d4db4dc..a138d3990f6 100644 --- a/packages/extension-base/src/services/earning-service/handlers/native-staking/mythos.ts +++ b/packages/extension-base/src/services/earning-service/handlers/native-staking/mythos.ts @@ -1,7 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-base // SPDX-License-Identifier: Apache-2.0 -import { _ChainInfo } from '@subwallet/chain-list/types'; +import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types'; import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; import { APIItemState, ExtrinsicType, NominationInfo } from '@subwallet/extension-base/background/KoniTypes'; import { getCommission } from '@subwallet/extension-base/koni/api/staking/bonding/utils'; @@ -358,7 +358,7 @@ export default class MythosNativeStakingPoolHandler extends BaseParaStakingPoolH /* Leave pool action */ /* Get pool reward */ - override async getPoolReward (useAddresses: string[], callback: (rs: EarningRewardItem) => void): Promise { + override async getPoolReward (useAddresses: string[], callback: (rs: EarningRewardItem, tokenInfo: _ChainAsset) => void): Promise { let cancel = false; const substrateApi = this.substrateApi; @@ -377,10 +377,9 @@ export default class MythosNativeStakingPoolHandler extends BaseParaStakingPoolH }; if (_unclaimedReward.toString() !== '0') { - await this.createClaimNotification(earningRewardItem, this.nativeToken); + // await this.createClaimNotification(earningRewardItem, this.nativeToken); + callback(earningRewardItem, this.nativeToken); } - - callback(earningRewardItem); } })); } diff --git a/packages/extension-base/src/services/earning-service/handlers/nomination-pool/index.ts b/packages/extension-base/src/services/earning-service/handlers/nomination-pool/index.ts index 01f8ca48a51..6834ec5a2af 100644 --- a/packages/extension-base/src/services/earning-service/handlers/nomination-pool/index.ts +++ b/packages/extension-base/src/services/earning-service/handlers/nomination-pool/index.ts @@ -1,6 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-base // SPDX-License-Identifier: Apache-2.0 +import { _ChainAsset } from '@subwallet/chain-list/types'; import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; import { APIItemState, ChainType, ExtrinsicType, NominationInfo, StakingType, UnstakingInfo } from '@subwallet/extension-base/background/KoniTypes'; import { PalletNominationPoolsPoolMember } from '@subwallet/extension-base/core/substrate/types'; @@ -362,7 +363,7 @@ export default class NominationPoolHandler extends BasePoolHandler { /* Get pool reward */ - async getPoolReward (useAddresses: string[], callBack: (rs: EarningRewardItem) => void): Promise { + async getPoolReward (useAddresses: string[], callBack: (rs: EarningRewardItem, tokenInfo: _ChainAsset) => void): Promise { let cancel = false; const substrateApi = this.substrateApi; @@ -382,11 +383,13 @@ export default class NominationPoolHandler extends BasePoolHandler { state: APIItemState.READY }; + // if (_unclaimedReward.toString() !== '0') { + // await this.createClaimNotification(earningRewardItem, this.nativeToken); + // } + if (_unclaimedReward.toString() !== '0') { - await this.createClaimNotification(earningRewardItem, this.nativeToken); + callBack(earningRewardItem, this.nativeToken); } - - callBack(earningRewardItem); } } } diff --git a/packages/extension-base/src/services/earning-service/service.ts b/packages/extension-base/src/services/earning-service/service.ts index 5d212711054..a0ab2ea49aa 100644 --- a/packages/extension-base/src/services/earning-service/service.ts +++ b/packages/extension-base/src/services/earning-service/service.ts @@ -1,6 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-base // SPDX-License-Identifier: Apache-2.0 +import { _ChainAsset } from '@subwallet/chain-list/types'; import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes'; import { CRON_REFRESH_CHAIN_STAKING_METADATA, CRON_REFRESH_EARNING_REWARD_HISTORY_INTERVAL, CRON_REFRESH_STAKING_REWARD_FAST_INTERVAL } from '@subwallet/extension-base/constants'; @@ -11,6 +12,7 @@ import { _STAKING_CHAIN_GROUP } from '@subwallet/extension-base/services/earning 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 { createClaimNotification } from '@subwallet/extension-base/services/inapp-notification-service/utils'; import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService'; import { SWTransaction } from '@subwallet/extension-base/services/transaction-service/types'; import { BasicTxErrorType, EarningRewardHistoryItem, EarningRewardItem, EarningRewardJson, HandleYieldStepData, HandleYieldStepParams, OptimalYieldPath, OptimalYieldPathParams, RequestEarlyValidateYield, RequestStakeCancelWithdrawal, RequestStakeClaimReward, RequestYieldLeave, RequestYieldWithdrawal, ResponseEarlyValidateYield, TransactionData, ValidateYieldProcessParams, YieldPoolInfo, YieldPoolTarget, YieldPoolType, YieldPositionInfo } from '@subwallet/extension-base/types'; @@ -164,7 +166,6 @@ export default class EarningService implements StoppableServiceInterface, Persis }); this.status = ServiceStatus.INITIALIZED; - await this.start(); this.handleActions(); @@ -663,7 +664,7 @@ export default class EarningService implements StoppableServiceInterface, Persis }); } - public async getPoolReward (addresses: string[], callback: (result: EarningRewardItem) => void): Promise { + public async getPoolReward (addresses: string[], callback: (result: EarningRewardItem, tokenInfo: _ChainAsset) => void): Promise { let cancel = false; await this.eventService.waitChainReady; @@ -720,13 +721,21 @@ export default class EarningService implements StoppableServiceInterface, Persis return; } - this.getPoolReward(addresses, (result: EarningRewardItem) => { + this.getPoolReward(addresses, (result: EarningRewardItem, tokenInfo: _ChainAsset) => { this.updateEarningReward(result); + + const notification = createClaimNotification(result, tokenInfo); + + this.state.inappNotificationService.validateAndWriteNotificationsToDB([notification], result.address).catch(console.error); }).catch(console.error); this.earningsRewardInterval = setInterval(() => { - this.getPoolReward(addresses, (result: EarningRewardItem) => { + this.getPoolReward(addresses, (result: EarningRewardItem, tokenInfo: _ChainAsset) => { this.updateEarningReward(result); + + const notification = createClaimNotification(result, tokenInfo); + + this.state.inappNotificationService.validateAndWriteNotificationsToDB([notification], result.address).catch(console.error); }).catch(console.error); }, CRON_REFRESH_STAKING_REWARD_FAST_INTERVAL); } diff --git a/packages/extension-base/src/services/inapp-notification-service/index.ts b/packages/extension-base/src/services/inapp-notification-service/index.ts index f6c305d7a0c..11e71c5fe90 100644 --- a/packages/extension-base/src/services/inapp-notification-service/index.ts +++ b/packages/extension-base/src/services/inapp-notification-service/index.ts @@ -23,6 +23,7 @@ import { isSubstrateAddress } from '@subwallet/keyring'; export class InappNotificationService implements CronServiceInterface { status: ServiceStatus; private refeshAvailBridgeClaimTimeOut: NodeJS.Timeout | undefined; + private isLockWrite: boolean; constructor ( private readonly dbService: DatabaseService, @@ -31,6 +32,7 @@ export class InappNotificationService implements CronServiceInterface { private readonly chainService: ChainService ) { this.status = ServiceStatus.NOT_INITIALIZED; + this.isLockWrite = false; } async init (): Promise { @@ -181,26 +183,31 @@ export class InappNotificationService implements CronServiceInterface { } async validateAndWriteNotificationsToDB (notifications: _BaseNotificationInfo[], address: string) { - const proxyId = this.keyringService.context.belongUnifiedAccount(address) || address; - const accountName = this.keyringService.context.getCurrentAccountProxyName(proxyId); - const passNotifications: _NotificationInfo[] = []; - const [comparedNotifications, remindTimeConfig] = await Promise.all([ - this.fetchNotificationsByParams({ notificationTab: NotificationTab.ALL, proxyId }), - await fetchLastestRemindNotificationTime() - ]); - - for (const candidateNotification of notifications) { - candidateNotification.title = candidateNotification.title.replace('{{accountName}}', accountName); - - if (this.passValidateNotification(candidateNotification, comparedNotifications, remindTimeConfig)) { - passNotifications.push({ - ...candidateNotification, - proxyId - }); + if (!this.getLockWriteStatus()) { + this.setLockWriteStatus(true); + const proxyId = this.keyringService.context.belongUnifiedAccount(address) || address; + const accountName = this.keyringService.context.getCurrentAccountProxyName(proxyId); + const passNotifications: _NotificationInfo[] = []; + const [comparedNotifications, remindTimeConfig] = await Promise.all([ + this.fetchNotificationsByParams({ notificationTab: NotificationTab.ALL, proxyId }), + await fetchLastestRemindNotificationTime() + ]); + + for (const candidateNotification of notifications) { + candidateNotification.title = candidateNotification.title.replace('{{accountName}}', accountName); + + if (this.passValidateNotification(candidateNotification, comparedNotifications, remindTimeConfig)) { + passNotifications.push({ + ...candidateNotification, + proxyId + }); + } } - } - await this.dbService.upsertNotifications(passNotifications); + await this.dbService.upsertNotifications(passNotifications); + + this.setLockWriteStatus(false); + } } cronCreateBridgeClaimNotification () { @@ -519,4 +526,12 @@ export class InappNotificationService implements CronServiceInterface { migrateNotificationProxyId (proxyIds: string[], newProxyId: string, newName: string) { this.dbService.updateNotificationProxyId(proxyIds, newProxyId, newName); } + + getLockWriteStatus () { + return this.isLockWrite; + } + + setLockWriteStatus (status: boolean) { + this.isLockWrite = status; + } }