From f406414455d2acbad019637fcd6d64146bf2c88c Mon Sep 17 00:00:00 2001 From: PDTnhah Date: Wed, 18 Dec 2024 15:58:08 +0700 Subject: [PATCH 01/14] [Issue-3920] Show well-known tokens on top --- .../src/background/KoniTypes.ts | 5 +++ .../src/koni/background/handlers/Extension.ts | 24 ++++++++++++ .../src/services/chain-service/index.ts | 38 ++++++++++++++++++- .../src/Popup/Home/Tokens/index.tsx | 11 ++++-- .../src/contexts/DataContext.tsx | 3 +- .../src/stores/feature/common/ChainStore.ts | 10 +++++ .../extension-koni-ui/src/stores/types.ts | 1 + .../src/stores/utils/index.ts | 8 ++++ .../extension-koni-ui/src/utils/sort/token.ts | 17 +++++++++ 9 files changed, 112 insertions(+), 5 deletions(-) diff --git a/packages/extension-base/src/background/KoniTypes.ts b/packages/extension-base/src/background/KoniTypes.ts index ff96b76aeb..a2295a55de 100644 --- a/packages/extension-base/src/background/KoniTypes.ts +++ b/packages/extension-base/src/background/KoniTypes.ts @@ -2294,6 +2294,11 @@ export interface KoniRequestSignatures { /* Ledger */ 'pri(ledger.generic.allow)': [null, string[], string[]]; + /* Ledger */ + + /* Popular tokens */ + 'pri(popular.tokens)': [null, string[], string[]]; + /* Popular tokens */ } export interface ApplicationMetadataType { diff --git a/packages/extension-base/src/koni/background/handlers/Extension.ts b/packages/extension-base/src/koni/background/handlers/Extension.ts index 7a33f1698c..ae52b0ce8a 100644 --- a/packages/extension-base/src/koni/background/handlers/Extension.ts +++ b/packages/extension-base/src/koni/background/handlers/Extension.ts @@ -3933,6 +3933,24 @@ export default class KoniExtension { /* Ledger */ + /* Popular tokens */ + + private subscribePopularTokens (id: string, port: chrome.runtime.Port): string[] { + const cb = createSubscription<'pri(popular.tokens)'>(id, port); + + const subscription = this.#koniState.chainService.observablePopularTokens.popularTokens.subscribe(cb); + + this.createUnsubscriptionHandle(id, subscription.unsubscribe); + + port.onDisconnect.addListener((): void => { + this.cancelSubscription(id); + }); + + return this.#koniState.chainService.valuePopularTokens.popularTokens; + } + + /* Popular tokens */ + // -------------------------------------------------------------- // eslint-disable-next-line @typescript-eslint/require-await public async handle (id: string, type: TMessageType, request: RequestTypes[TMessageType], port: chrome.runtime.Port): Promise> { @@ -4543,6 +4561,12 @@ export default class KoniExtension { case 'pri(ledger.generic.allow)': return this.subscribeLedgerGenericAllowChains(id, port); /* Ledger */ + + /* Popular tokens */ + case 'pri(popular.tokens)': + return this.subscribePopularTokens(id, port); + /* Popular tokens */ + // Default default: throw new Error(`Unable to handle message of type ${type}`); diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index 5d5e3f7562..6411ad2fdb 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -92,6 +92,7 @@ export class ChainService { private assetLogoMapSubject = new BehaviorSubject>(AssetLogoMap); private chainLogoMapSubject = new BehaviorSubject>(ChainLogoMap); private ledgerGenericAllowChainsSubject = new BehaviorSubject([]); + private popularTokensSubject = new BehaviorSubject([]); // Todo: Update to new store indexed DB private store: AssetSettingStore = new AssetSettingStore(); @@ -121,7 +122,7 @@ export class ChainService { this.logger = createLogger('chain-service'); } - public get value () { + public get value() { const ledgerGenericAllowChains = this.ledgerGenericAllowChainsSubject; return { @@ -141,6 +142,26 @@ export class ChainService { }; } + public get valuePopularTokens () { + const popularTokens = this.popularTokensSubject; + + return { + get popularTokens () { + return popularTokens.value; + } + }; + } + + public get observablePopularTokens () { + const popularTokens = this.popularTokensSubject; + + return { + get popularTokens () { + return popularTokens.asObservable(); + } + }; + } + public subscribeSwapRefMap () { return this.swapRefMapSubject; } @@ -767,6 +788,11 @@ export class ChainService { this.logger.log('Finished updating latest ledger generic allow chains'); } + handleLatestPopularTokens (latestPopularTokens: string[]) { + this.popularTokensSubject.next(latestPopularTokens); + this.logger.log('Finished updating latest popular tokens'); + } + handleLatestData () { this.fetchLatestChainData().then((latestChainInfo) => { this.lockChainInfoMap = true; // do not need to check current lockChainInfoMap because all remains action is fast enough and don't affect this feature. @@ -786,6 +812,12 @@ export class ChainService { this.handleLatestLedgerGenericAllowChains(latestledgerGenericAllowChains); }) .catch(console.error); + + this.fetchLatestPopularTokens() + .then((latestPopularTokens) => { + this.handleLatestPopularTokens(latestPopularTokens); + }) + .catch(console.error); } private async initApis () { @@ -1088,6 +1120,10 @@ export class ChainService { return await fetchStaticData('chains/ledger-generic-allow-chains') || []; } + private async fetchLatestPopularTokens () { + return await fetchStaticData('chain-assets/popular-tokens') || []; + } + private async initChains () { const storedChainSettings = await this.dbService.getAllChainStore(); const defaultChainInfoMap = filterChainInfoMap(ChainInfoMap, ignoredList); diff --git a/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx b/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx index b60572fc2a..4263e4279f 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx @@ -17,7 +17,7 @@ import { UpperBlock } from '@subwallet/extension-koni-ui/Popup/Home/Tokens/Upper import { RootState } from '@subwallet/extension-koni-ui/stores'; import { AccountAddressItemType, ThemeProps, TransferParams } from '@subwallet/extension-koni-ui/types'; import { TokenBalanceItemType } from '@subwallet/extension-koni-ui/types/balance'; -import { getTransactionFromAccountProxyValue, isAccountAll, sortTokenByValue } from '@subwallet/extension-koni-ui/utils'; +import { getTransactionFromAccountProxyValue, isAccountAll, sortToken } from '@subwallet/extension-koni-ui/utils'; import { isTonAddress } from '@subwallet/keyring'; import { Button, Icon, ModalContext, SwAlert } from '@subwallet/react-ui'; import classNames from 'classnames'; @@ -47,6 +47,9 @@ const Component = (): React.ReactElement => { totalBalanceInfo }, tokenGroupStructure: { sortedTokenGroups } } = useContext(HomeContext); const notify = useNotification(); const { onOpenReceive, receiveModalProps } = useCoreReceiveModalHelper(); + const popularTokens = useSelector((state: RootState) => state.chainStore.popularTokens); + + console.log('tokens', popularTokens); const isZkModeSyncing = useSelector((state: RootState) => state.mantaPay.isSyncing); const zkModeSyncProgress = useSelector((state: RootState) => state.mantaPay.progress); @@ -294,14 +297,16 @@ const Component = (): React.ReactElement => { const tokenGroupBalanceItems = useMemo(() => { const result: TokenBalanceItemType[] = []; + console.log('group',tokenGroupBalanceMap); + sortedTokenGroups.forEach((tokenGroupSlug) => { if (tokenGroupBalanceMap[tokenGroupSlug]) { result.push(tokenGroupBalanceMap[tokenGroupSlug]); } }); - return result.sort(sortTokenByValue); - }, [sortedTokenGroups, tokenGroupBalanceMap]); + return sortToken(result, popularTokens); + }, [sortedTokenGroups, tokenGroupBalanceMap, popularTokens]); useEffect(() => { window.addEventListener('resize', handleResize); diff --git a/packages/extension-koni-ui/src/contexts/DataContext.tsx b/packages/extension-koni-ui/src/contexts/DataContext.tsx index 17b25a68a2..8c9444addd 100644 --- a/packages/extension-koni-ui/src/contexts/DataContext.tsx +++ b/packages/extension-koni-ui/src/contexts/DataContext.tsx @@ -3,7 +3,7 @@ import { ping } from '@subwallet/extension-koni-ui/messaging'; import { persistor, store, StoreName } from '@subwallet/extension-koni-ui/stores'; -import { getMissionPoolData, subscribeAccountsData, subscribeAddressBook, subscribeAssetLogoMaps, subscribeAssetRegistry, subscribeAssetSettings, subscribeAuthorizeRequests, subscribeAuthUrls, subscribeBalance, subscribeBuyServices, subscribeBuyTokens, subscribeCampaignBannerData, subscribeCampaignConfirmationData, subscribeCampaignPopupData, subscribeCampaignPopupVisibility, subscribeChainInfoMap, subscribeChainLogoMaps, subscribeChainStakingMetadata, subscribeChainStateMap, subscribeChainStatusMap, subscribeConfirmationRequests, subscribeConfirmationRequestsTon, subscribeConnectWCRequests, subscribeCrowdloan, subscribeKeyringState, subscribeLedgerGenericAllowNetworks, subscribeMantaPayConfig, subscribeMantaPaySyncingState, subscribeMetadataRequests, subscribeMultiChainAssetMap, subscribeNftCollections, subscribeNftItems, subscribePrice, subscribeProcessingCampaign, subscribeRewardHistory, subscribeSigningRequests, subscribeStaking, subscribeStakingNominatorMetadata, subscribeStakingReward, subscribeSwapPairs, subscribeTransactionRequests, subscribeTxHistory, subscribeUiSettings, subscribeUnreadNotificationCount, subscribeWalletConnectSessions, subscribeWCNotSupportRequests, subscribeXcmRefMap, subscribeYieldMinAmountPercent, subscribeYieldPoolInfo, subscribeYieldPositionInfo, subscribeYieldReward } from '@subwallet/extension-koni-ui/stores/utils'; +import { getMissionPoolData, subscribeAccountsData, subscribeAddressBook, subscribeAssetLogoMaps, subscribeAssetRegistry, subscribeAssetSettings, subscribeAuthorizeRequests, subscribeAuthUrls, subscribeBalance, subscribeBuyServices, subscribeBuyTokens, subscribeCampaignBannerData, subscribeCampaignConfirmationData, subscribeCampaignPopupData, subscribeCampaignPopupVisibility, subscribeChainInfoMap, subscribeChainLogoMaps, subscribeChainStakingMetadata, subscribeChainStateMap, subscribeChainStatusMap, subscribeConfirmationRequests, subscribeConfirmationRequestsTon, subscribeConnectWCRequests, subscribeCrowdloan, subscribeKeyringState, subscribeLedgerGenericAllowNetworks, subscribeMantaPayConfig, subscribeMantaPaySyncingState, subscribeMetadataRequests, subscribeMultiChainAssetMap, subscribeNftCollections, subscribeNftItems, subscribePopularTokens, subscribePrice, subscribeProcessingCampaign, subscribeRewardHistory, subscribeSigningRequests, subscribeStaking, subscribeStakingNominatorMetadata, subscribeStakingReward, subscribeSwapPairs, subscribeTransactionRequests, subscribeTxHistory, subscribeUiSettings, subscribeUnreadNotificationCount, subscribeWalletConnectSessions, subscribeWCNotSupportRequests, subscribeXcmRefMap, subscribeYieldMinAmountPercent, subscribeYieldPoolInfo, subscribeYieldPositionInfo, subscribeYieldReward } from '@subwallet/extension-koni-ui/stores/utils'; import Bowser from 'bowser'; import React from 'react'; import { Provider } from 'react-redux'; @@ -200,6 +200,7 @@ export const DataContextProvider = ({ children }: DataContextProviderProps) => { _DataContext.addHandler({ ...subscribeChainStatusMap, name: 'subscribeChainStatusMap', relatedStores: ['chainStore'], isStartImmediately: true }); _DataContext.addHandler({ ...subscribeChainInfoMap, name: 'subscribeChainInfoMap', relatedStores: ['chainStore'], isStartImmediately: true }); _DataContext.addHandler({ ...subscribeLedgerGenericAllowNetworks, name: 'subscribeLedgerGenericAllowNetworks', relatedStores: ['chainStore'], isStartImmediately: true }); + _DataContext.addHandler({ ...subscribePopularTokens, name: 'subscribePopularTokens', relatedStores: ['chainStore'], isStartImmediately: true }); _DataContext.addHandler({ ...subscribeAssetRegistry, name: 'subscribeAssetRegistry', relatedStores: ['assetRegistry'], isStartImmediately: true }); _DataContext.addHandler({ ...subscribeMultiChainAssetMap, name: 'subscribeMultiChainAssetMap', relatedStores: ['assetRegistry'], isStartImmediately: true }); diff --git a/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts b/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts index 0ad9c2c927..82d4bdca23 100644 --- a/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts +++ b/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts @@ -11,6 +11,7 @@ const initialState: ChainStore = { chainStateMap: {}, chainStatusMap: {}, ledgerGenericAllowNetworks: [], + popularTokens: [], reduxStatus: ReduxStatus.INIT }; @@ -53,6 +54,15 @@ const chainStoreSlice = createSlice({ ledgerGenericAllowNetworks: payload, reduxStatus: ReduxStatus.READY }; + }, + updatePopularTokens (state, action: PayloadAction) { + const { payload } = action; + + return { + ...state, + popularTokens: payload, + reduxStatus: ReduxStatus.READY + }; } } }); diff --git a/packages/extension-koni-ui/src/stores/types.ts b/packages/extension-koni-ui/src/stores/types.ts index f339820298..3aadc4cac1 100644 --- a/packages/extension-koni-ui/src/stores/types.ts +++ b/packages/extension-koni-ui/src/stores/types.ts @@ -126,6 +126,7 @@ export interface ChainStore extends BaseReduxStore { chainStateMap: Record chainStatusMap: Record ledgerGenericAllowNetworks: string[]; + popularTokens: string[]; } export interface BalanceStore extends BaseReduxStore { diff --git a/packages/extension-koni-ui/src/stores/utils/index.ts b/packages/extension-koni-ui/src/stores/utils/index.ts index a0d892c268..613536b557 100644 --- a/packages/extension-koni-ui/src/stores/utils/index.ts +++ b/packages/extension-koni-ui/src/stores/utils/index.ts @@ -508,3 +508,11 @@ export const updateUnreadNotificationCountMap = (data: Record) = export const subscribeUnreadNotificationCount = lazySubscribeMessage('pri(inappNotification.subscribeUnreadNotificationCountMap)', null, updateUnreadNotificationCountMap, updateUnreadNotificationCountMap); /* Notification service */ + +/* Popular tokens */ +export const updatePopularTokens = (data: string[]) => { + store.dispatch({ type: 'chainStore/updatePopularTokens', payload: data }); +}; + +export const subscribePopularTokens = lazySubscribeMessage('pri(popular.tokens)', null, updatePopularTokens, updatePopularTokens); +/* Popular tokens */ diff --git a/packages/extension-koni-ui/src/utils/sort/token.ts b/packages/extension-koni-ui/src/utils/sort/token.ts index 902aab4195..1537d5d70e 100644 --- a/packages/extension-koni-ui/src/utils/sort/token.ts +++ b/packages/extension-koni-ui/src/utils/sort/token.ts @@ -12,3 +12,20 @@ export const sortTokenByValue = (a: TokenBalanceItemType, b: TokenBalanceItemTyp return b.total.value.minus(a.total.value).toNumber(); } }; + +export function sortToken (tokenGroupSlug: TokenBalanceItemType[], popularTokens: string[]) { + return tokenGroupSlug.sort((a, b) => { + const aIsPiorityToken = popularTokens.includes(a.slug); + const bIsPiorityToken = popularTokens.includes(b.slug); + + if (aIsPiorityToken && !bIsPiorityToken) { + return -1; + } else if (!aIsPiorityToken && bIsPiorityToken) { + return 1; + } else if (!aIsPiorityToken && !bIsPiorityToken) { + return sortTokenByValue(a, b); + } else { + return 0; + } + }); +} From 14e192ad0ddb99be67820b04391f0825d0a80a62 Mon Sep 17 00:00:00 2001 From: PDTnhah Date: Wed, 18 Dec 2024 16:01:01 +0700 Subject: [PATCH 02/14] [Issue-3920] fix lint --- packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx b/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx index 4263e4279f..36707d7726 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx @@ -49,8 +49,6 @@ const Component = (): React.ReactElement => { const { onOpenReceive, receiveModalProps } = useCoreReceiveModalHelper(); const popularTokens = useSelector((state: RootState) => state.chainStore.popularTokens); - console.log('tokens', popularTokens); - const isZkModeSyncing = useSelector((state: RootState) => state.mantaPay.isSyncing); const zkModeSyncProgress = useSelector((state: RootState) => state.mantaPay.progress); const [, setStorage] = useLocalStorage(TRANSFER_TRANSACTION, DEFAULT_TRANSFER_PARAMS); @@ -297,8 +295,6 @@ const Component = (): React.ReactElement => { const tokenGroupBalanceItems = useMemo(() => { const result: TokenBalanceItemType[] = []; - console.log('group',tokenGroupBalanceMap); - sortedTokenGroups.forEach((tokenGroupSlug) => { if (tokenGroupBalanceMap[tokenGroupSlug]) { result.push(tokenGroupBalanceMap[tokenGroupSlug]); From 7cc18f59777779a424d0dad4e65c289d2d4d50d7 Mon Sep 17 00:00:00 2001 From: PDTnhah Date: Wed, 18 Dec 2024 16:15:12 +0700 Subject: [PATCH 03/14] [Issue-3920] fix lint --- packages/extension-base/src/services/chain-service/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index 6411ad2fdb..f62cbf7b93 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -122,7 +122,7 @@ export class ChainService { this.logger = createLogger('chain-service'); } - public get value() { + public get value () { const ledgerGenericAllowChains = this.ledgerGenericAllowChainsSubject; return { From 7a273ef0b7f287273de4093b7520e2ec9a9a818f Mon Sep 17 00:00:00 2001 From: PDTnhah Date: Thu, 19 Dec 2024 17:35:17 +0700 Subject: [PATCH 04/14] [Issue-3920] Show well-known tokens on top --- .../extension-base/src/background/KoniTypes.ts | 2 +- .../src/koni/background/handlers/Extension.ts | 2 +- .../src/services/chain-service/index.ts | 6 +++--- .../src/stores/feature/common/ChainStore.ts | 4 ++-- packages/extension-koni-ui/src/stores/types.ts | 2 +- .../extension-koni-ui/src/stores/utils/index.ts | 2 +- packages/extension-koni-ui/src/utils/sort/token.ts | 14 ++++++++++---- 7 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/extension-base/src/background/KoniTypes.ts b/packages/extension-base/src/background/KoniTypes.ts index a2295a55de..77915330cc 100644 --- a/packages/extension-base/src/background/KoniTypes.ts +++ b/packages/extension-base/src/background/KoniTypes.ts @@ -2297,7 +2297,7 @@ export interface KoniRequestSignatures { /* Ledger */ /* Popular tokens */ - 'pri(popular.tokens)': [null, string[], string[]]; + 'pri(popular.tokens)': [null, Record, Record]; /* Popular tokens */ } diff --git a/packages/extension-base/src/koni/background/handlers/Extension.ts b/packages/extension-base/src/koni/background/handlers/Extension.ts index ae52b0ce8a..81dec06f4c 100644 --- a/packages/extension-base/src/koni/background/handlers/Extension.ts +++ b/packages/extension-base/src/koni/background/handlers/Extension.ts @@ -3935,7 +3935,7 @@ export default class KoniExtension { /* Popular tokens */ - private subscribePopularTokens (id: string, port: chrome.runtime.Port): string[] { + private subscribePopularTokens (id: string, port: chrome.runtime.Port): Record { const cb = createSubscription<'pri(popular.tokens)'>(id, port); const subscription = this.#koniState.chainService.observablePopularTokens.popularTokens.subscribe(cb); diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index f62cbf7b93..787148da6e 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -92,7 +92,7 @@ export class ChainService { private assetLogoMapSubject = new BehaviorSubject>(AssetLogoMap); private chainLogoMapSubject = new BehaviorSubject>(ChainLogoMap); private ledgerGenericAllowChainsSubject = new BehaviorSubject([]); - private popularTokensSubject = new BehaviorSubject([]); + private popularTokensSubject = new BehaviorSubject>({}); // Todo: Update to new store indexed DB private store: AssetSettingStore = new AssetSettingStore(); @@ -788,7 +788,7 @@ export class ChainService { this.logger.log('Finished updating latest ledger generic allow chains'); } - handleLatestPopularTokens (latestPopularTokens: string[]) { + handleLatestPopularTokens (latestPopularTokens: Record) { this.popularTokensSubject.next(latestPopularTokens); this.logger.log('Finished updating latest popular tokens'); } @@ -1121,7 +1121,7 @@ export class ChainService { } private async fetchLatestPopularTokens () { - return await fetchStaticData('chain-assets/popular-tokens') || []; + return await fetchStaticData>('chain-assets/popular-tokens') || []; } private async initChains () { diff --git a/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts b/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts index 82d4bdca23..2ee7cc8fce 100644 --- a/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts +++ b/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts @@ -11,7 +11,7 @@ const initialState: ChainStore = { chainStateMap: {}, chainStatusMap: {}, ledgerGenericAllowNetworks: [], - popularTokens: [], + popularTokens: {}, reduxStatus: ReduxStatus.INIT }; @@ -55,7 +55,7 @@ const chainStoreSlice = createSlice({ reduxStatus: ReduxStatus.READY }; }, - updatePopularTokens (state, action: PayloadAction) { + updatePopularTokens (state, action: PayloadAction>) { const { payload } = action; return { diff --git a/packages/extension-koni-ui/src/stores/types.ts b/packages/extension-koni-ui/src/stores/types.ts index 3aadc4cac1..ced5cb83a0 100644 --- a/packages/extension-koni-ui/src/stores/types.ts +++ b/packages/extension-koni-ui/src/stores/types.ts @@ -126,7 +126,7 @@ export interface ChainStore extends BaseReduxStore { chainStateMap: Record chainStatusMap: Record ledgerGenericAllowNetworks: string[]; - popularTokens: string[]; + popularTokens: Record; } export interface BalanceStore extends BaseReduxStore { diff --git a/packages/extension-koni-ui/src/stores/utils/index.ts b/packages/extension-koni-ui/src/stores/utils/index.ts index 613536b557..e091f80d3a 100644 --- a/packages/extension-koni-ui/src/stores/utils/index.ts +++ b/packages/extension-koni-ui/src/stores/utils/index.ts @@ -510,7 +510,7 @@ export const subscribeUnreadNotificationCount = lazySubscribeMessage('pri(inappN /* Notification service */ /* Popular tokens */ -export const updatePopularTokens = (data: string[]) => { +export const updatePopularTokens = (data: Record) => { store.dispatch({ type: 'chainStore/updatePopularTokens', payload: data }); }; diff --git a/packages/extension-koni-ui/src/utils/sort/token.ts b/packages/extension-koni-ui/src/utils/sort/token.ts index 1537d5d70e..b00fb9e7cc 100644 --- a/packages/extension-koni-ui/src/utils/sort/token.ts +++ b/packages/extension-koni-ui/src/utils/sort/token.ts @@ -13,10 +13,12 @@ export const sortTokenByValue = (a: TokenBalanceItemType, b: TokenBalanceItemTyp } }; -export function sortToken (tokenGroupSlug: TokenBalanceItemType[], popularTokens: string[]) { +export function sortToken (tokenGroupSlug: TokenBalanceItemType[], popularTokens: Record) { return tokenGroupSlug.sort((a, b) => { - const aIsPiorityToken = popularTokens.includes(a.slug); - const bIsPiorityToken = popularTokens.includes(b.slug); + const aIsPiorityToken = Object.keys(popularTokens).includes(a.slug); + const bIsPiorityToken = Object.keys(popularTokens).includes(b.slug); + const aPiority = popularTokens[a.slug]; + const bPiority = popularTokens[b.slug]; if (aIsPiorityToken && !bIsPiorityToken) { return -1; @@ -25,7 +27,11 @@ export function sortToken (tokenGroupSlug: TokenBalanceItemType[], popularTokens } else if (!aIsPiorityToken && !bIsPiorityToken) { return sortTokenByValue(a, b); } else { - return 0; + if (aPiority < bPiority) { + return -1; + } else { + return 1; + } } }); } From 17467426f7de430f3a89b4138203b063a45faa44 Mon Sep 17 00:00:00 2001 From: PDTnhah Date: Thu, 19 Dec 2024 19:21:28 +0700 Subject: [PATCH 05/14] [Issue-3920] Refactor code --- .../src/services/chain-service/index.ts | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index 787148da6e..b856c562f8 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -124,38 +124,26 @@ export class ChainService { public get value () { const ledgerGenericAllowChains = this.ledgerGenericAllowChainsSubject; + const popularTokens = this.popularTokensSubject; return { get ledgerGenericAllowChains () { return ledgerGenericAllowChains.value; + }, + get popularTokens () { + return popularTokens.value; } }; } public get observable () { const ledgerGenericAllowChains = this.ledgerGenericAllowChainsSubject; + const popularTokens = this.popularTokensSubject; return { get ledgerGenericAllowChains () { return ledgerGenericAllowChains.asObservable(); - } - }; - } - - public get valuePopularTokens () { - const popularTokens = this.popularTokensSubject; - - return { - get popularTokens () { - return popularTokens.value; - } - }; - } - - public get observablePopularTokens () { - const popularTokens = this.popularTokensSubject; - - return { + }, get popularTokens () { return popularTokens.asObservable(); } From fcafddc32b2d21870b52847482ee52b84ae72333 Mon Sep 17 00:00:00 2001 From: PDTnhah Date: Tue, 31 Dec 2024 19:15:31 +0700 Subject: [PATCH 06/14] [Issue-3920] Show well-known tokens on top --- .../src/background/KoniTypes.ts | 9 ++- .../src/koni/background/handlers/Extension.ts | 8 +- .../src/services/chain-service/index.ts | 8 +- .../ReceiveModalNew/parts/TokenSelector.tsx | 7 +- .../src/stores/feature/common/ChainStore.ts | 3 +- .../extension-koni-ui/src/stores/types.ts | 4 +- .../src/stores/utils/index.ts | 4 +- .../extension-koni-ui/src/utils/sort/token.ts | 75 +++++++++++++++---- 8 files changed, 89 insertions(+), 29 deletions(-) diff --git a/packages/extension-base/src/background/KoniTypes.ts b/packages/extension-base/src/background/KoniTypes.ts index 77915330cc..081afefcf5 100644 --- a/packages/extension-base/src/background/KoniTypes.ts +++ b/packages/extension-base/src/background/KoniTypes.ts @@ -1706,6 +1706,13 @@ export interface RequestAddPspToken { }; } +// Popular tokens + +export interface PopularGroup { + tokens: Record, + piority: number +} + /// WalletConnect // Connect @@ -2297,7 +2304,7 @@ export interface KoniRequestSignatures { /* Ledger */ /* Popular tokens */ - 'pri(popular.tokens)': [null, Record, Record]; + 'pri(popular.tokens)': [null, Record, Record]; /* Popular tokens */ } diff --git a/packages/extension-base/src/koni/background/handlers/Extension.ts b/packages/extension-base/src/koni/background/handlers/Extension.ts index 81dec06f4c..9f81b20d92 100644 --- a/packages/extension-base/src/koni/background/handlers/Extension.ts +++ b/packages/extension-base/src/koni/background/handlers/Extension.ts @@ -7,7 +7,7 @@ import { _AssetRef, _AssetType, _ChainAsset, _ChainInfo, _MultiChainAsset } from import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers'; import { createSubscription } from '@subwallet/extension-base/background/handlers/subscriptions'; -import { AccountExternalError, AddressBookInfo, AmountData, AmountDataWithId, AssetSetting, AssetSettingUpdateReq, BondingOptionParams, BrowserConfirmationType, CampaignBanner, CampaignData, CampaignDataType, ChainType, CronReloadRequest, CrowdloanJson, ExternalRequestPromiseStatus, ExtrinsicType, KeyringState, MantaPayEnableMessage, MantaPayEnableParams, MantaPayEnableResponse, MantaPaySyncState, MetadataItem, NftCollection, NftJson, NftTransactionRequest, NftTransactionResponse, PriceJson, RequestAccountCreateExternalV2, RequestAccountCreateHardwareMultiple, RequestAccountCreateHardwareV2, RequestAccountCreateWithSecretKey, RequestAccountExportPrivateKey, RequestAddInjectedAccounts, RequestApproveConnectWalletSession, RequestApproveWalletConnectNotSupport, RequestAuthorization, RequestAuthorizationBlock, RequestAuthorizationPerAccount, RequestAuthorizationPerSite, RequestAuthorizeApproveV2, RequestBondingSubmit, RequestCameraSettings, RequestCampaignBannerComplete, RequestChangeEnableChainPatrol, RequestChangeLanguage, RequestChangeMasterPassword, RequestChangePriceCurrency, RequestChangeShowBalance, RequestChangeShowZeroBalance, RequestChangeTimeAutoLock, RequestConfirmationComplete, RequestConfirmationCompleteTon, RequestConnectWalletConnect, RequestCrowdloanContributions, RequestDeleteContactAccount, RequestDisconnectWalletConnectSession, RequestEditContactAccount, RequestFindRawMetadata, RequestForgetSite, RequestFreeBalance, RequestGetTransaction, RequestKeyringExportMnemonic, RequestMaxTransferable, RequestMigratePassword, RequestParseEvmContractInput, RequestParseTransactionSubstrate, RequestPassPhishingPage, RequestQrParseRLP, RequestQrSignEvm, RequestQrSignSubstrate, RequestRejectConnectWalletSession, RequestRejectExternalRequest, RequestRejectWalletConnectNotSupport, RequestRemoveInjectedAccounts, RequestResetWallet, RequestResolveExternalRequest, RequestSaveAppConfig, RequestSaveBrowserConfig, RequestSaveOSConfig, RequestSaveRecentAccount, RequestSettingsType, RequestSigningApprovePasswordV2, RequestStakePoolingBonding, RequestStakePoolingUnbonding, RequestSubscribeHistory, RequestSubstrateNftSubmitTransaction, RequestTuringCancelStakeCompound, RequestTuringStakeCompound, RequestUnbondingSubmit, RequestUnlockKeyring, RequestUnlockType, ResolveAddressToDomainRequest, ResolveDomainRequest, ResponseAccountCreateWithSecretKey, ResponseAccountExportPrivateKey, ResponseChangeMasterPassword, ResponseFindRawMetadata, ResponseKeyringExportMnemonic, ResponseMigratePassword, ResponseNftImport, ResponseParseEvmContractInput, ResponseParseTransactionSubstrate, ResponseQrParseRLP, ResponseQrSignEvm, ResponseQrSignSubstrate, ResponseRejectExternalRequest, ResponseResetWallet, ResponseResolveExternalRequest, ResponseSubscribeHistory, ResponseUnlockKeyring, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, StakingType, SufficientMetadata, ThemeNames, TransactionHistoryItem, TransactionResponse, ValidateNetworkRequest, ValidateNetworkResponse, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; +import { AccountExternalError, AddressBookInfo, AmountData, AmountDataWithId, AssetSetting, AssetSettingUpdateReq, BondingOptionParams, BrowserConfirmationType, CampaignBanner, CampaignData, CampaignDataType, ChainType, CronReloadRequest, CrowdloanJson, ExternalRequestPromiseStatus, ExtrinsicType, KeyringState, MantaPayEnableMessage, MantaPayEnableParams, MantaPayEnableResponse, MantaPaySyncState, MetadataItem, NftCollection, NftJson, NftTransactionRequest, NftTransactionResponse, PopularGroup, PriceJson, RequestAccountCreateExternalV2, RequestAccountCreateHardwareMultiple, RequestAccountCreateHardwareV2, RequestAccountCreateWithSecretKey, RequestAccountExportPrivateKey, RequestAddInjectedAccounts, RequestApproveConnectWalletSession, RequestApproveWalletConnectNotSupport, RequestAuthorization, RequestAuthorizationBlock, RequestAuthorizationPerAccount, RequestAuthorizationPerSite, RequestAuthorizeApproveV2, RequestBondingSubmit, RequestCameraSettings, RequestCampaignBannerComplete, RequestChangeEnableChainPatrol, RequestChangeLanguage, RequestChangeMasterPassword, RequestChangePriceCurrency, RequestChangeShowBalance, RequestChangeShowZeroBalance, RequestChangeTimeAutoLock, RequestConfirmationComplete, RequestConfirmationCompleteTon, RequestConnectWalletConnect, RequestCrowdloanContributions, RequestDeleteContactAccount, RequestDisconnectWalletConnectSession, RequestEditContactAccount, RequestFindRawMetadata, RequestForgetSite, RequestFreeBalance, RequestGetTransaction, RequestKeyringExportMnemonic, RequestMaxTransferable, RequestMigratePassword, RequestParseEvmContractInput, RequestParseTransactionSubstrate, RequestPassPhishingPage, RequestQrParseRLP, RequestQrSignEvm, RequestQrSignSubstrate, RequestRejectConnectWalletSession, RequestRejectExternalRequest, RequestRejectWalletConnectNotSupport, RequestRemoveInjectedAccounts, RequestResetWallet, RequestResolveExternalRequest, RequestSaveAppConfig, RequestSaveBrowserConfig, RequestSaveOSConfig, RequestSaveRecentAccount, RequestSettingsType, RequestSigningApprovePasswordV2, RequestStakePoolingBonding, RequestStakePoolingUnbonding, RequestSubscribeHistory, RequestSubstrateNftSubmitTransaction, RequestTuringCancelStakeCompound, RequestTuringStakeCompound, RequestUnbondingSubmit, RequestUnlockKeyring, RequestUnlockType, ResolveAddressToDomainRequest, ResolveDomainRequest, ResponseAccountCreateWithSecretKey, ResponseAccountExportPrivateKey, ResponseChangeMasterPassword, ResponseFindRawMetadata, ResponseKeyringExportMnemonic, ResponseMigratePassword, ResponseNftImport, ResponseParseEvmContractInput, ResponseParseTransactionSubstrate, ResponseQrParseRLP, ResponseQrSignEvm, ResponseQrSignSubstrate, ResponseRejectExternalRequest, ResponseResetWallet, ResponseResolveExternalRequest, ResponseSubscribeHistory, ResponseUnlockKeyring, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, StakingType, SufficientMetadata, ThemeNames, TransactionHistoryItem, TransactionResponse, ValidateNetworkRequest, ValidateNetworkResponse, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; import { AccountAuthType, AuthorizeRequest, MessageTypes, MetadataRequest, RequestAccountExport, RequestAuthorizeCancel, RequestAuthorizeReject, RequestCurrentAccountAddress, RequestMetadataApprove, RequestMetadataReject, RequestSigningApproveSignature, RequestSigningCancel, RequestTypes, ResponseAccountExport, ResponseAuthorizeList, ResponseType, SigningRequest, WindowOpenParams } from '@subwallet/extension-base/background/types'; import { TransactionWarning } from '@subwallet/extension-base/background/warnings/TransactionWarning'; import { ALL_ACCOUNT_KEY, LATEST_SESSION, XCM_FEE_RATIO } from '@subwallet/extension-base/constants'; @@ -3935,10 +3935,10 @@ export default class KoniExtension { /* Popular tokens */ - private subscribePopularTokens (id: string, port: chrome.runtime.Port): Record { + private subscribePopularTokens (id: string, port: chrome.runtime.Port): Record { const cb = createSubscription<'pri(popular.tokens)'>(id, port); - const subscription = this.#koniState.chainService.observablePopularTokens.popularTokens.subscribe(cb); + const subscription = this.#koniState.chainService.observable.popularTokens.subscribe(cb); this.createUnsubscriptionHandle(id, subscription.unsubscribe); @@ -3946,7 +3946,7 @@ export default class KoniExtension { this.cancelSubscription(id); }); - return this.#koniState.chainService.valuePopularTokens.popularTokens; + return this.#koniState.chainService.value.popularTokens; } /* Popular tokens */ diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index b856c562f8..466e46e923 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -3,7 +3,7 @@ import { AssetLogoMap, AssetRefMap, ChainAssetMap, ChainInfoMap, ChainLogoMap, MultiChainAssetMap } from '@subwallet/chain-list'; import { _AssetRef, _AssetRefPath, _AssetType, _ChainAsset, _ChainInfo, _ChainStatus, _EvmInfo, _MultiChainAsset, _SubstrateChainType, _SubstrateInfo, _TonInfo } from '@subwallet/chain-list/types'; -import { AssetSetting, ValidateNetworkResponse } from '@subwallet/extension-base/background/KoniTypes'; +import { AssetSetting, PopularGroup, ValidateNetworkResponse } from '@subwallet/extension-base/background/KoniTypes'; import { _DEFAULT_ACTIVE_CHAINS, _ZK_ASSET_PREFIX, LATEST_CHAIN_DATA_FETCHING_INTERVAL } from '@subwallet/extension-base/services/chain-service/constants'; import { EvmChainHandler } from '@subwallet/extension-base/services/chain-service/handler/EvmChainHandler'; import { MantaPrivateHandler } from '@subwallet/extension-base/services/chain-service/handler/manta/MantaPrivateHandler'; @@ -92,7 +92,7 @@ export class ChainService { private assetLogoMapSubject = new BehaviorSubject>(AssetLogoMap); private chainLogoMapSubject = new BehaviorSubject>(ChainLogoMap); private ledgerGenericAllowChainsSubject = new BehaviorSubject([]); - private popularTokensSubject = new BehaviorSubject>({}); + private popularTokensSubject = new BehaviorSubject>({}); // Todo: Update to new store indexed DB private store: AssetSettingStore = new AssetSettingStore(); @@ -776,7 +776,7 @@ export class ChainService { this.logger.log('Finished updating latest ledger generic allow chains'); } - handleLatestPopularTokens (latestPopularTokens: Record) { + handleLatestPopularTokens (latestPopularTokens: Record) { this.popularTokensSubject.next(latestPopularTokens); this.logger.log('Finished updating latest popular tokens'); } @@ -1109,7 +1109,7 @@ export class ChainService { } private async fetchLatestPopularTokens () { - return await fetchStaticData>('chain-assets/popular-tokens') || []; + return await fetchStaticData>('chain-assets/popular-tokens') || []; } private async initChains () { diff --git a/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx b/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx index 680e886566..0fd7c1ef9c 100644 --- a/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx +++ b/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx @@ -8,7 +8,9 @@ import TokenEmptyList from '@subwallet/extension-koni-ui/components/EmptyList/To import Search from '@subwallet/extension-koni-ui/components/Search'; import { RECEIVE_MODAL_TOKEN_SELECTOR } from '@subwallet/extension-koni-ui/constants'; import { useSelector, useTranslation } from '@subwallet/extension-koni-ui/hooks'; +import { RootState } from '@subwallet/extension-koni-ui/stores'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; +import { sortTokenInGetAddressScreen } from '@subwallet/extension-koni-ui/utils'; import { ModalContext, SwList, SwModal } from '@subwallet/react-ui'; import { SwListSectionRef } from '@subwallet/react-ui/es/sw-list'; import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; @@ -31,6 +33,7 @@ function Component ({ className = '', items, onCancel, onSelectItem }: Props): R const [currentSearchText, setCurrentSearchText] = useState(''); // @ts-ignore const chainInfoMap = useSelector((state) => state.chainStore.chainInfoMap); + const popularTokens = useSelector((state: RootState) => state.chainStore.popularTokens); const listItems = useMemo(() => { const filteredList = items.filter((item) => { @@ -51,10 +54,12 @@ function Component ({ className = '', items, onCancel, onSelectItem }: Props): R } return filteredList; + } else if (currentSearchText.toLowerCase() === '') { + return sortTokenInGetAddressScreen(filteredList, popularTokens); } else { return filteredList; } - }, [chainInfoMap, currentSearchText, items]); + }, [chainInfoMap, currentSearchText, items, popularTokens]); const isActive = checkActive(modalId); diff --git a/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts b/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts index 2ee7cc8fce..29ddf3a8ee 100644 --- a/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts +++ b/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts @@ -3,6 +3,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { _ChainInfo } from '@subwallet/chain-list/types'; +import { PopularGroup } from '@subwallet/extension-base/background/KoniTypes'; import { _ChainApiStatus, _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { ChainStore, ReduxStatus } from '@subwallet/extension-koni-ui/stores/types'; @@ -55,7 +56,7 @@ const chainStoreSlice = createSlice({ reduxStatus: ReduxStatus.READY }; }, - updatePopularTokens (state, action: PayloadAction>) { + updatePopularTokens (state, action: PayloadAction>) { const { payload } = action; return { diff --git a/packages/extension-koni-ui/src/stores/types.ts b/packages/extension-koni-ui/src/stores/types.ts index ced5cb83a0..46a113618c 100644 --- a/packages/extension-koni-ui/src/stores/types.ts +++ b/packages/extension-koni-ui/src/stores/types.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { _AssetRef, _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types'; -import { AddressBookState, AllLogoMap, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationDefinitions, ConfirmationsQueue, ConfirmationsQueueTon, ConfirmationType, CrowdloanItem, KeyringState, LanguageType, MantaPayConfig, NftCollection, NftItem, NominatorMetadata, PriceJson, StakingItem, StakingRewardItem, TransactionHistoryItem, UiSettings, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; +import { AddressBookState, AllLogoMap, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationDefinitions, ConfirmationsQueue, ConfirmationsQueueTon, ConfirmationType, CrowdloanItem, KeyringState, LanguageType, MantaPayConfig, NftCollection, NftItem, NominatorMetadata, PopularGroup, PriceJson, StakingItem, StakingRewardItem, TransactionHistoryItem, UiSettings, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; import { AccountsContext, AuthorizeRequest, MetadataRequest, SigningRequest } from '@subwallet/extension-base/background/types'; import { _ChainApiStatus, _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { AppBannerData, AppConfirmationData, AppPopupData } from '@subwallet/extension-base/services/mkt-campaign-service/types'; @@ -126,7 +126,7 @@ export interface ChainStore extends BaseReduxStore { chainStateMap: Record chainStatusMap: Record ledgerGenericAllowNetworks: string[]; - popularTokens: Record; + popularTokens: Record; } export interface BalanceStore extends BaseReduxStore { diff --git a/packages/extension-koni-ui/src/stores/utils/index.ts b/packages/extension-koni-ui/src/stores/utils/index.ts index e091f80d3a..b00810a04c 100644 --- a/packages/extension-koni-ui/src/stores/utils/index.ts +++ b/packages/extension-koni-ui/src/stores/utils/index.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { _AssetRef, _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types'; -import { AddressBookInfo, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationsQueue, ConfirmationsQueueTon, CrowdloanJson, KeyringState, MantaPayConfig, MantaPaySyncState, NftCollection, NftJson, NominatorMetadata, PriceJson, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, TransactionHistoryItem, UiSettings } from '@subwallet/extension-base/background/KoniTypes'; +import { AddressBookInfo, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationsQueue, ConfirmationsQueueTon, CrowdloanJson, KeyringState, MantaPayConfig, MantaPaySyncState, NftCollection, NftJson, NominatorMetadata, PopularGroup, PriceJson, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, TransactionHistoryItem, UiSettings } from '@subwallet/extension-base/background/KoniTypes'; import { AccountsContext, AuthorizeRequest, ConfirmationRequestBase, MetadataRequest, SigningRequest } from '@subwallet/extension-base/background/types'; import { _ChainApiStatus, _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { AppBannerData, AppConfirmationData, AppPopupData } from '@subwallet/extension-base/services/mkt-campaign-service/types'; @@ -510,7 +510,7 @@ export const subscribeUnreadNotificationCount = lazySubscribeMessage('pri(inappN /* Notification service */ /* Popular tokens */ -export const updatePopularTokens = (data: Record) => { +export const updatePopularTokens = (data: Record) => { store.dispatch({ type: 'chainStore/updatePopularTokens', payload: data }); }; diff --git a/packages/extension-koni-ui/src/utils/sort/token.ts b/packages/extension-koni-ui/src/utils/sort/token.ts index b00fb9e7cc..00950c6057 100644 --- a/packages/extension-koni-ui/src/utils/sort/token.ts +++ b/packages/extension-koni-ui/src/utils/sort/token.ts @@ -1,6 +1,8 @@ // Copyright 2019-2022 @polkadot/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { _ChainAsset } from '@subwallet/chain-list/types'; +import { PopularGroup } from '@subwallet/extension-base/background/KoniTypes'; import { TokenBalanceItemType } from '@subwallet/extension-koni-ui/types'; export const sortTokenByValue = (a: TokenBalanceItemType, b: TokenBalanceItemType): number => { @@ -13,25 +15,70 @@ export const sortTokenByValue = (a: TokenBalanceItemType, b: TokenBalanceItemTyp } }; -export function sortToken (tokenGroupSlug: TokenBalanceItemType[], popularTokens: Record) { - return tokenGroupSlug.sort((a, b) => { - const aIsPiorityToken = Object.keys(popularTokens).includes(a.slug); - const bIsPiorityToken = Object.keys(popularTokens).includes(b.slug); - const aPiority = popularTokens[a.slug]; - const bPiority = popularTokens[b.slug]; +export const sortTokenAlphabetically = (a: string, b: string): number => { + const aSymbol = a.toLowerCase(); + const bSymbol = b.toLowerCase(); + + if (aSymbol < bSymbol) { + return -1; + } else if (aSymbol > bSymbol) { + return 1; + } else { + return 0; + } +}; - if (aIsPiorityToken && !bIsPiorityToken) { +export const sortTokenByPopularity = (a: string, b: string, aIsPiorityToken: boolean, bIsPiorityToken: boolean, aPiority: number, bPiority: number): number => { + if (aIsPiorityToken && !bIsPiorityToken) { + return -1; + } else if (!aIsPiorityToken && bIsPiorityToken) { + return 1; + } else if (!aIsPiorityToken && !bIsPiorityToken) { + return sortTokenAlphabetically(a, b); + } else { + if (aPiority < bPiority) { return -1; - } else if (!aIsPiorityToken && bIsPiorityToken) { + } else if (aPiority > bPiority) { return 1; - } else if (!aIsPiorityToken && !bIsPiorityToken) { + } else { + return 0; + } + } +}; + +export function sortToken (tokenGroupSlug: TokenBalanceItemType[], popularTokens: Record) { + return tokenGroupSlug.sort((a, b) => { + const aIsPiorityGroup = Object.keys(popularTokens).includes(a.slug); + const bIsPiorityGroup = Object.keys(popularTokens).includes(b.slug); + const aPiority = aIsPiorityGroup ? popularTokens[a.slug].piority : 0; + const bPiority = bIsPiorityGroup ? popularTokens[b.slug].piority : 0; + + const aHasBalance = a.total.convertedValue.toNumber() !== 0 || a.total.value.toNumber() !== 0; + const bHasBalance = b.total.convertedValue.toNumber() !== 0 || b.total.value.toNumber() !== 0; + + if (aHasBalance && bHasBalance) { return sortTokenByValue(a, b); + } else if (aHasBalance && !bHasBalance) { + return -1; + } else if (!aHasBalance && bHasBalance) { + return 1; } else { - if (aPiority < bPiority) { - return -1; - } else { - return 1; - } + return sortTokenByPopularity(a.symbol, b.symbol, aIsPiorityGroup, bIsPiorityGroup, aPiority, bPiority); } }); } + +export function sortTokenInGetAddressScreen (tokenGroupSlug: _ChainAsset[], popularTokens: Record) { + return tokenGroupSlug.sort((a, b) => { + const aBelongtoPiorityGroup = a.multiChainAsset ? Object.keys(popularTokens).includes(a.multiChainAsset) : false; + const bBelongtoPiorityGroup = b.multiChainAsset ? Object.keys(popularTokens).includes(b.multiChainAsset) : false; + + const aIsPiorityToken = (aBelongtoPiorityGroup && a.multiChainAsset && Object.keys(popularTokens[a.multiChainAsset].tokens).includes(a.slug)) || Object.keys(popularTokens).includes(a.slug); + const bIsPiorityToken = (bBelongtoPiorityGroup && b.multiChainAsset && Object.keys(popularTokens[b.multiChainAsset].tokens).includes(b.slug)) || Object.keys(popularTokens).includes(b.slug); + + const aPiority = a.multiChainAsset ? aIsPiorityToken ? (popularTokens[a.multiChainAsset].tokens)[a.slug] : 0 : aIsPiorityToken ? popularTokens[a.slug].piority : 0; + const bPiority = b.multiChainAsset ? bIsPiorityToken ? (popularTokens[b.multiChainAsset].tokens)[b.slug] : 0 : bIsPiorityToken ? popularTokens[b.slug].piority : 0; + + return sortTokenByPopularity(a.symbol, b.symbol, aIsPiorityToken, bIsPiorityToken, aPiority, bPiority); + }); +} From 3a9322e644500221c174a3eb6779f30fac22a78a Mon Sep 17 00:00:00 2001 From: PDTnhah Date: Mon, 6 Jan 2025 08:56:39 +0700 Subject: [PATCH 07/14] [Issue-3920] Refactor code --- .../src/Popup/Home/Tokens/index.tsx | 2 +- .../ReceiveModalNew/parts/TokenSelector.tsx | 4 +- .../src/contexts/DataContext.tsx | 2 +- .../extension-koni-ui/src/utils/sort/token.ts | 61 +++++++++---------- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx b/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx index 36707d7726..869e88e043 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx @@ -301,7 +301,7 @@ const Component = (): React.ReactElement => { } }); - return sortToken(result, popularTokens); + return sortToken(result, popularTokens) as TokenBalanceItemType[]; }, [sortedTokenGroups, tokenGroupBalanceMap, popularTokens]); useEffect(() => { diff --git a/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx b/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx index 0fd7c1ef9c..6e678142aa 100644 --- a/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx +++ b/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx @@ -10,7 +10,7 @@ import { RECEIVE_MODAL_TOKEN_SELECTOR } from '@subwallet/extension-koni-ui/const import { useSelector, useTranslation } from '@subwallet/extension-koni-ui/hooks'; import { RootState } from '@subwallet/extension-koni-ui/stores'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; -import { sortTokenInGetAddressScreen } from '@subwallet/extension-koni-ui/utils'; +import { sortToken } from '@subwallet/extension-koni-ui/utils'; import { ModalContext, SwList, SwModal } from '@subwallet/react-ui'; import { SwListSectionRef } from '@subwallet/react-ui/es/sw-list'; import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; @@ -55,7 +55,7 @@ function Component ({ className = '', items, onCancel, onSelectItem }: Props): R return filteredList; } else if (currentSearchText.toLowerCase() === '') { - return sortTokenInGetAddressScreen(filteredList, popularTokens); + return sortToken(filteredList, popularTokens) as _ChainAsset[]; } else { return filteredList; } diff --git a/packages/extension-koni-ui/src/contexts/DataContext.tsx b/packages/extension-koni-ui/src/contexts/DataContext.tsx index 8c9444addd..bdb7ec6f78 100644 --- a/packages/extension-koni-ui/src/contexts/DataContext.tsx +++ b/packages/extension-koni-ui/src/contexts/DataContext.tsx @@ -200,7 +200,7 @@ export const DataContextProvider = ({ children }: DataContextProviderProps) => { _DataContext.addHandler({ ...subscribeChainStatusMap, name: 'subscribeChainStatusMap', relatedStores: ['chainStore'], isStartImmediately: true }); _DataContext.addHandler({ ...subscribeChainInfoMap, name: 'subscribeChainInfoMap', relatedStores: ['chainStore'], isStartImmediately: true }); _DataContext.addHandler({ ...subscribeLedgerGenericAllowNetworks, name: 'subscribeLedgerGenericAllowNetworks', relatedStores: ['chainStore'], isStartImmediately: true }); - _DataContext.addHandler({ ...subscribePopularTokens, name: 'subscribePopularTokens', relatedStores: ['chainStore'], isStartImmediately: true }); + _DataContext.addHandler({ ...subscribePopularTokens, name: 'subscribePopularTokens', relatedStores: ['chainStore'], isStartImmediately: false }); _DataContext.addHandler({ ...subscribeAssetRegistry, name: 'subscribeAssetRegistry', relatedStores: ['assetRegistry'], isStartImmediately: true }); _DataContext.addHandler({ ...subscribeMultiChainAssetMap, name: 'subscribeMultiChainAssetMap', relatedStores: ['assetRegistry'], isStartImmediately: true }); diff --git a/packages/extension-koni-ui/src/utils/sort/token.ts b/packages/extension-koni-ui/src/utils/sort/token.ts index 00950c6057..fec0b1d089 100644 --- a/packages/extension-koni-ui/src/utils/sort/token.ts +++ b/packages/extension-koni-ui/src/utils/sort/token.ts @@ -1,17 +1,27 @@ // Copyright 2019-2022 @polkadot/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { _ChainAsset } from '@subwallet/chain-list/types'; import { PopularGroup } from '@subwallet/extension-base/background/KoniTypes'; -import { TokenBalanceItemType } from '@subwallet/extension-koni-ui/types'; +import { BalanceValueInfo } from '@subwallet/extension-koni-ui/types'; -export const sortTokenByValue = (a: TokenBalanceItemType, b: TokenBalanceItemType): number => { - const convertValue = b.total.convertedValue.minus(a.total.convertedValue).toNumber(); +export interface TokenSort { + slug: string, + symbol: string, + total?: BalanceValueInfo, + multiChainAsset?: string | null +} + +export const sortTokenByValue = (a: TokenSort, b: TokenSort): number => { + if (a.total && b.total) { + const convertValue = b.total.convertedValue.minus(a.total.convertedValue).toNumber(); - if (convertValue) { - return convertValue; + if (convertValue) { + return convertValue; + } else { + return b.total.value.minus(a.total.value).toNumber(); + } } else { - return b.total.value.minus(a.total.value).toNumber(); + return 0; } }; @@ -28,7 +38,7 @@ export const sortTokenAlphabetically = (a: string, b: string): number => { } }; -export const sortTokenByPopularity = (a: string, b: string, aIsPiorityToken: boolean, bIsPiorityToken: boolean, aPiority: number, bPiority: number): number => { +export const sortByTokenPopularity = (a: string, b: string, aIsPiorityToken: boolean, bIsPiorityToken: boolean, aPiority: number, bPiority: number): number => { if (aIsPiorityToken && !bIsPiorityToken) { return -1; } else if (!aIsPiorityToken && bIsPiorityToken) { @@ -46,15 +56,19 @@ export const sortTokenByPopularity = (a: string, b: string, aIsPiorityToken: boo } }; -export function sortToken (tokenGroupSlug: TokenBalanceItemType[], popularTokens: Record) { +export function sortToken (tokenGroupSlug: TokenSort[], popularTokens: Record) { return tokenGroupSlug.sort((a, b) => { - const aIsPiorityGroup = Object.keys(popularTokens).includes(a.slug); - const bIsPiorityGroup = Object.keys(popularTokens).includes(b.slug); - const aPiority = aIsPiorityGroup ? popularTokens[a.slug].piority : 0; - const bPiority = bIsPiorityGroup ? popularTokens[b.slug].piority : 0; + const aBelongtoPiorityGroup = a.multiChainAsset ? Object.keys(popularTokens).includes(a.multiChainAsset) : false; + const bBelongtoPiorityGroup = b.multiChainAsset ? Object.keys(popularTokens).includes(b.multiChainAsset) : false; - const aHasBalance = a.total.convertedValue.toNumber() !== 0 || a.total.value.toNumber() !== 0; - const bHasBalance = b.total.convertedValue.toNumber() !== 0 || b.total.value.toNumber() !== 0; + const aIsPiorityToken = (aBelongtoPiorityGroup && a.multiChainAsset && Object.keys(popularTokens[a.multiChainAsset].tokens).includes(a.slug)) || Object.keys(popularTokens).includes(a.slug); + const bIsPiorityToken = (bBelongtoPiorityGroup && b.multiChainAsset && Object.keys(popularTokens[b.multiChainAsset].tokens).includes(b.slug)) || Object.keys(popularTokens).includes(b.slug); + + const aHasBalance = (a.total && a.total.convertedValue.toNumber() !== 0) || (a.total && a.total.value.toNumber() !== 0); + const bHasBalance = (b.total && b.total.convertedValue.toNumber() !== 0) || (b.total && b.total.value.toNumber() !== 0); + + const aPiority = a.multiChainAsset ? aIsPiorityToken ? (popularTokens[a.multiChainAsset].tokens)[a.slug] : 0 : aIsPiorityToken ? popularTokens[a.slug].piority : 0; + const bPiority = b.multiChainAsset ? bIsPiorityToken ? (popularTokens[b.multiChainAsset].tokens)[b.slug] : 0 : bIsPiorityToken ? popularTokens[b.slug].piority : 0; if (aHasBalance && bHasBalance) { return sortTokenByValue(a, b); @@ -63,22 +77,7 @@ export function sortToken (tokenGroupSlug: TokenBalanceItemType[], popularTokens } else if (!aHasBalance && bHasBalance) { return 1; } else { - return sortTokenByPopularity(a.symbol, b.symbol, aIsPiorityGroup, bIsPiorityGroup, aPiority, bPiority); + return sortByTokenPopularity(a.symbol, b.symbol, aIsPiorityToken, bIsPiorityToken, aPiority, bPiority); } }); } - -export function sortTokenInGetAddressScreen (tokenGroupSlug: _ChainAsset[], popularTokens: Record) { - return tokenGroupSlug.sort((a, b) => { - const aBelongtoPiorityGroup = a.multiChainAsset ? Object.keys(popularTokens).includes(a.multiChainAsset) : false; - const bBelongtoPiorityGroup = b.multiChainAsset ? Object.keys(popularTokens).includes(b.multiChainAsset) : false; - - const aIsPiorityToken = (aBelongtoPiorityGroup && a.multiChainAsset && Object.keys(popularTokens[a.multiChainAsset].tokens).includes(a.slug)) || Object.keys(popularTokens).includes(a.slug); - const bIsPiorityToken = (bBelongtoPiorityGroup && b.multiChainAsset && Object.keys(popularTokens[b.multiChainAsset].tokens).includes(b.slug)) || Object.keys(popularTokens).includes(b.slug); - - const aPiority = a.multiChainAsset ? aIsPiorityToken ? (popularTokens[a.multiChainAsset].tokens)[a.slug] : 0 : aIsPiorityToken ? popularTokens[a.slug].piority : 0; - const bPiority = b.multiChainAsset ? bIsPiorityToken ? (popularTokens[b.multiChainAsset].tokens)[b.slug] : 0 : bIsPiorityToken ? popularTokens[b.slug].piority : 0; - - return sortTokenByPopularity(a.symbol, b.symbol, aIsPiorityToken, bIsPiorityToken, aPiority, bPiority); - }); -} From 29edf3e0cbe694e0989148dab37f9e8fd053c3d2 Mon Sep 17 00:00:00 2001 From: PDTnhah Date: Mon, 6 Jan 2025 17:21:44 +0700 Subject: [PATCH 08/14] [Issue-3920] Rename interface & variables --- .../src/background/KoniTypes.ts | 6 ++-- .../src/koni/background/handlers/Extension.ts | 4 +-- .../src/services/chain-service/index.ts | 8 ++--- .../src/stores/feature/common/ChainStore.ts | 4 +-- .../extension-koni-ui/src/stores/types.ts | 4 +-- .../src/stores/utils/index.ts | 4 +-- .../extension-koni-ui/src/utils/sort/token.ts | 34 +++++++++---------- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/packages/extension-base/src/background/KoniTypes.ts b/packages/extension-base/src/background/KoniTypes.ts index 49c8179023..d67463de7b 100644 --- a/packages/extension-base/src/background/KoniTypes.ts +++ b/packages/extension-base/src/background/KoniTypes.ts @@ -1711,9 +1711,9 @@ export interface RequestAddPspToken { // Popular tokens -export interface PopularGroup { +export interface PrioritizedTokenList { tokens: Record, - piority: number + priority: number } /// WalletConnect @@ -2307,7 +2307,7 @@ export interface KoniRequestSignatures { /* Ledger */ /* Popular tokens */ - 'pri(popular.tokens)': [null, Record, Record]; + 'pri(popular.tokens)': [null, Record, Record]; /* Popular tokens */ } diff --git a/packages/extension-base/src/koni/background/handlers/Extension.ts b/packages/extension-base/src/koni/background/handlers/Extension.ts index 337c2ae718..9d47e98c1f 100644 --- a/packages/extension-base/src/koni/background/handlers/Extension.ts +++ b/packages/extension-base/src/koni/background/handlers/Extension.ts @@ -8,7 +8,7 @@ import { _AssetRef, _AssetType, _ChainAsset, _ChainInfo, _MultiChainAsset } from import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers'; import { createSubscription } from '@subwallet/extension-base/background/handlers/subscriptions'; -import { AccountExternalError, AddressBookInfo, AmountData, AmountDataWithId, AssetSetting, AssetSettingUpdateReq, BondingOptionParams, BrowserConfirmationType, CampaignBanner, CampaignData, CampaignDataType, ChainType, CronReloadRequest, CrowdloanJson, ExternalRequestPromiseStatus, ExtrinsicType, KeyringState, MantaPayEnableMessage, MantaPayEnableParams, MantaPayEnableResponse, MantaPaySyncState, MetadataItem, NftCollection, NftJson, NftTransactionRequest, NftTransactionResponse, PopularGroup, PriceJson, RequestAccountCreateExternalV2, RequestAccountCreateHardwareMultiple, RequestAccountCreateHardwareV2, RequestAccountCreateWithSecretKey, RequestAccountExportPrivateKey, RequestAddInjectedAccounts, RequestApproveConnectWalletSession, RequestApproveWalletConnectNotSupport, RequestAuthorization, RequestAuthorizationBlock, RequestAuthorizationPerAccount, RequestAuthorizationPerSite, RequestAuthorizeApproveV2, RequestBondingSubmit, RequestCameraSettings, RequestCampaignBannerComplete, RequestChangeEnableChainPatrol, RequestChangeLanguage, RequestChangeMasterPassword, RequestChangePriceCurrency, RequestChangeShowBalance, RequestChangeShowZeroBalance, RequestChangeTimeAutoLock, RequestConfirmationComplete, RequestConfirmationCompleteTon, RequestConnectWalletConnect, RequestCrowdloanContributions, RequestDeleteContactAccount, RequestDisconnectWalletConnectSession, RequestEditContactAccount, RequestFindRawMetadata, RequestForgetSite, RequestFreeBalance, RequestGetTransaction, RequestKeyringExportMnemonic, RequestMaxTransferable, RequestMigratePassword, RequestParseEvmContractInput, RequestParseTransactionSubstrate, RequestPassPhishingPage, RequestQrParseRLP, RequestQrSignEvm, RequestQrSignSubstrate, RequestRejectConnectWalletSession, RequestRejectExternalRequest, RequestRejectWalletConnectNotSupport, RequestRemoveInjectedAccounts, RequestResetWallet, RequestResolveExternalRequest, RequestSaveAppConfig, RequestSaveBrowserConfig, RequestSaveOSConfig, RequestSaveRecentAccount, RequestSettingsType, RequestSigningApprovePasswordV2, RequestStakePoolingBonding, RequestStakePoolingUnbonding, RequestSubscribeHistory, RequestSubstrateNftSubmitTransaction, RequestTuringCancelStakeCompound, RequestTuringStakeCompound, RequestUnbondingSubmit, RequestUnlockKeyring, RequestUnlockType, ResolveAddressToDomainRequest, ResolveDomainRequest, ResponseAccountCreateWithSecretKey, ResponseAccountExportPrivateKey, ResponseChangeMasterPassword, ResponseFindRawMetadata, ResponseKeyringExportMnemonic, ResponseMigratePassword, ResponseNftImport, ResponseParseEvmContractInput, ResponseParseTransactionSubstrate, ResponseQrParseRLP, ResponseQrSignEvm, ResponseQrSignSubstrate, ResponseRejectExternalRequest, ResponseResetWallet, ResponseResolveExternalRequest, ResponseSubscribeHistory, ResponseUnlockKeyring, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, StakingType, SufficientMetadata, ThemeNames, TransactionHistoryItem, TransactionResponse, ValidateNetworkRequest, ValidateNetworkResponse, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; +import { AccountExternalError, AddressBookInfo, AmountData, AmountDataWithId, AssetSetting, AssetSettingUpdateReq, BondingOptionParams, BrowserConfirmationType, CampaignBanner, CampaignData, CampaignDataType, ChainType, CronReloadRequest, CrowdloanJson, ExternalRequestPromiseStatus, ExtrinsicType, KeyringState, MantaPayEnableMessage, MantaPayEnableParams, MantaPayEnableResponse, MantaPaySyncState, MetadataItem, NftCollection, NftJson, NftTransactionRequest, NftTransactionResponse, PrioritizedTokenList, PriceJson, RequestAccountCreateExternalV2, RequestAccountCreateHardwareMultiple, RequestAccountCreateHardwareV2, RequestAccountCreateWithSecretKey, RequestAccountExportPrivateKey, RequestAddInjectedAccounts, RequestApproveConnectWalletSession, RequestApproveWalletConnectNotSupport, RequestAuthorization, RequestAuthorizationBlock, RequestAuthorizationPerAccount, RequestAuthorizationPerSite, RequestAuthorizeApproveV2, RequestBondingSubmit, RequestCameraSettings, RequestCampaignBannerComplete, RequestChangeEnableChainPatrol, RequestChangeLanguage, RequestChangeMasterPassword, RequestChangePriceCurrency, RequestChangeShowBalance, RequestChangeShowZeroBalance, RequestChangeTimeAutoLock, RequestConfirmationComplete, RequestConfirmationCompleteTon, RequestConnectWalletConnect, RequestCrowdloanContributions, RequestDeleteContactAccount, RequestDisconnectWalletConnectSession, RequestEditContactAccount, RequestFindRawMetadata, RequestForgetSite, RequestFreeBalance, RequestGetTransaction, RequestKeyringExportMnemonic, RequestMaxTransferable, RequestMigratePassword, RequestParseEvmContractInput, RequestParseTransactionSubstrate, RequestPassPhishingPage, RequestQrParseRLP, RequestQrSignEvm, RequestQrSignSubstrate, RequestRejectConnectWalletSession, RequestRejectExternalRequest, RequestRejectWalletConnectNotSupport, RequestRemoveInjectedAccounts, RequestResetWallet, RequestResolveExternalRequest, RequestSaveAppConfig, RequestSaveBrowserConfig, RequestSaveOSConfig, RequestSaveRecentAccount, RequestSettingsType, RequestSigningApprovePasswordV2, RequestStakePoolingBonding, RequestStakePoolingUnbonding, RequestSubscribeHistory, RequestSubstrateNftSubmitTransaction, RequestTuringCancelStakeCompound, RequestTuringStakeCompound, RequestUnbondingSubmit, RequestUnlockKeyring, RequestUnlockType, ResolveAddressToDomainRequest, ResolveDomainRequest, ResponseAccountCreateWithSecretKey, ResponseAccountExportPrivateKey, ResponseChangeMasterPassword, ResponseFindRawMetadata, ResponseKeyringExportMnemonic, ResponseMigratePassword, ResponseNftImport, ResponseParseEvmContractInput, ResponseParseTransactionSubstrate, ResponseQrParseRLP, ResponseQrSignEvm, ResponseQrSignSubstrate, ResponseRejectExternalRequest, ResponseResetWallet, ResponseResolveExternalRequest, ResponseSubscribeHistory, ResponseUnlockKeyring, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, StakingType, SufficientMetadata, ThemeNames, TransactionHistoryItem, TransactionResponse, ValidateNetworkRequest, ValidateNetworkResponse, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; import { AccountAuthType, AuthorizeRequest, MessageTypes, MetadataRequest, RequestAccountExport, RequestAuthorizeCancel, RequestAuthorizeReject, RequestCurrentAccountAddress, RequestMetadataApprove, RequestMetadataReject, RequestSigningApproveSignature, RequestSigningCancel, RequestTypes, ResponseAccountExport, ResponseAuthorizeList, ResponseType, SigningRequest, WindowOpenParams } from '@subwallet/extension-base/background/types'; import { TransactionWarning } from '@subwallet/extension-base/background/warnings/TransactionWarning'; import { ALL_ACCOUNT_KEY, LATEST_SESSION, XCM_FEE_RATIO } from '@subwallet/extension-base/constants'; @@ -3948,7 +3948,7 @@ export default class KoniExtension { /* Popular tokens */ - private subscribePopularTokens (id: string, port: chrome.runtime.Port): Record { + private subscribePopularTokens (id: string, port: chrome.runtime.Port): Record { const cb = createSubscription<'pri(popular.tokens)'>(id, port); const subscription = this.#koniState.chainService.observable.popularTokens.subscribe(cb); diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index 466e46e923..e376ca7be3 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -3,7 +3,7 @@ import { AssetLogoMap, AssetRefMap, ChainAssetMap, ChainInfoMap, ChainLogoMap, MultiChainAssetMap } from '@subwallet/chain-list'; import { _AssetRef, _AssetRefPath, _AssetType, _ChainAsset, _ChainInfo, _ChainStatus, _EvmInfo, _MultiChainAsset, _SubstrateChainType, _SubstrateInfo, _TonInfo } from '@subwallet/chain-list/types'; -import { AssetSetting, PopularGroup, ValidateNetworkResponse } from '@subwallet/extension-base/background/KoniTypes'; +import { AssetSetting, PrioritizedTokenList, ValidateNetworkResponse } from '@subwallet/extension-base/background/KoniTypes'; import { _DEFAULT_ACTIVE_CHAINS, _ZK_ASSET_PREFIX, LATEST_CHAIN_DATA_FETCHING_INTERVAL } from '@subwallet/extension-base/services/chain-service/constants'; import { EvmChainHandler } from '@subwallet/extension-base/services/chain-service/handler/EvmChainHandler'; import { MantaPrivateHandler } from '@subwallet/extension-base/services/chain-service/handler/manta/MantaPrivateHandler'; @@ -92,7 +92,7 @@ export class ChainService { private assetLogoMapSubject = new BehaviorSubject>(AssetLogoMap); private chainLogoMapSubject = new BehaviorSubject>(ChainLogoMap); private ledgerGenericAllowChainsSubject = new BehaviorSubject([]); - private popularTokensSubject = new BehaviorSubject>({}); + private popularTokensSubject = new BehaviorSubject>({}); // Todo: Update to new store indexed DB private store: AssetSettingStore = new AssetSettingStore(); @@ -776,7 +776,7 @@ export class ChainService { this.logger.log('Finished updating latest ledger generic allow chains'); } - handleLatestPopularTokens (latestPopularTokens: Record) { + handleLatestPopularTokens (latestPopularTokens: Record) { this.popularTokensSubject.next(latestPopularTokens); this.logger.log('Finished updating latest popular tokens'); } @@ -1109,7 +1109,7 @@ export class ChainService { } private async fetchLatestPopularTokens () { - return await fetchStaticData>('chain-assets/popular-tokens') || []; + return await fetchStaticData>('chain-assets/popular-tokens') || []; } private async initChains () { diff --git a/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts b/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts index 29ddf3a8ee..5abfc2fcd3 100644 --- a/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts +++ b/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts @@ -3,7 +3,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { _ChainInfo } from '@subwallet/chain-list/types'; -import { PopularGroup } from '@subwallet/extension-base/background/KoniTypes'; +import { PrioritizedTokenList } from '@subwallet/extension-base/background/KoniTypes'; import { _ChainApiStatus, _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { ChainStore, ReduxStatus } from '@subwallet/extension-koni-ui/stores/types'; @@ -56,7 +56,7 @@ const chainStoreSlice = createSlice({ reduxStatus: ReduxStatus.READY }; }, - updatePopularTokens (state, action: PayloadAction>) { + updatePopularTokens (state, action: PayloadAction>) { const { payload } = action; return { diff --git a/packages/extension-koni-ui/src/stores/types.ts b/packages/extension-koni-ui/src/stores/types.ts index 46a113618c..08956daca0 100644 --- a/packages/extension-koni-ui/src/stores/types.ts +++ b/packages/extension-koni-ui/src/stores/types.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { _AssetRef, _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types'; -import { AddressBookState, AllLogoMap, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationDefinitions, ConfirmationsQueue, ConfirmationsQueueTon, ConfirmationType, CrowdloanItem, KeyringState, LanguageType, MantaPayConfig, NftCollection, NftItem, NominatorMetadata, PopularGroup, PriceJson, StakingItem, StakingRewardItem, TransactionHistoryItem, UiSettings, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; +import { AddressBookState, AllLogoMap, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationDefinitions, ConfirmationsQueue, ConfirmationsQueueTon, ConfirmationType, CrowdloanItem, KeyringState, LanguageType, MantaPayConfig, NftCollection, NftItem, NominatorMetadata, PrioritizedTokenList, PriceJson, StakingItem, StakingRewardItem, TransactionHistoryItem, UiSettings, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; import { AccountsContext, AuthorizeRequest, MetadataRequest, SigningRequest } from '@subwallet/extension-base/background/types'; import { _ChainApiStatus, _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { AppBannerData, AppConfirmationData, AppPopupData } from '@subwallet/extension-base/services/mkt-campaign-service/types'; @@ -126,7 +126,7 @@ export interface ChainStore extends BaseReduxStore { chainStateMap: Record chainStatusMap: Record ledgerGenericAllowNetworks: string[]; - popularTokens: Record; + popularTokens: Record; } export interface BalanceStore extends BaseReduxStore { diff --git a/packages/extension-koni-ui/src/stores/utils/index.ts b/packages/extension-koni-ui/src/stores/utils/index.ts index b00810a04c..461a59c1e4 100644 --- a/packages/extension-koni-ui/src/stores/utils/index.ts +++ b/packages/extension-koni-ui/src/stores/utils/index.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { _AssetRef, _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types'; -import { AddressBookInfo, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationsQueue, ConfirmationsQueueTon, CrowdloanJson, KeyringState, MantaPayConfig, MantaPaySyncState, NftCollection, NftJson, NominatorMetadata, PopularGroup, PriceJson, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, TransactionHistoryItem, UiSettings } from '@subwallet/extension-base/background/KoniTypes'; +import { AddressBookInfo, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationsQueue, ConfirmationsQueueTon, CrowdloanJson, KeyringState, MantaPayConfig, MantaPaySyncState, NftCollection, NftJson, NominatorMetadata, PrioritizedTokenList, PriceJson, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, TransactionHistoryItem, UiSettings } from '@subwallet/extension-base/background/KoniTypes'; import { AccountsContext, AuthorizeRequest, ConfirmationRequestBase, MetadataRequest, SigningRequest } from '@subwallet/extension-base/background/types'; import { _ChainApiStatus, _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { AppBannerData, AppConfirmationData, AppPopupData } from '@subwallet/extension-base/services/mkt-campaign-service/types'; @@ -510,7 +510,7 @@ export const subscribeUnreadNotificationCount = lazySubscribeMessage('pri(inappN /* Notification service */ /* Popular tokens */ -export const updatePopularTokens = (data: Record) => { +export const updatePopularTokens = (data: Record) => { store.dispatch({ type: 'chainStore/updatePopularTokens', payload: data }); }; diff --git a/packages/extension-koni-ui/src/utils/sort/token.ts b/packages/extension-koni-ui/src/utils/sort/token.ts index fec0b1d089..1d84d4b9ea 100644 --- a/packages/extension-koni-ui/src/utils/sort/token.ts +++ b/packages/extension-koni-ui/src/utils/sort/token.ts @@ -1,17 +1,17 @@ // Copyright 2019-2022 @polkadot/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { PopularGroup } from '@subwallet/extension-base/background/KoniTypes'; +import { PrioritizedTokenList } from '@subwallet/extension-base/background/KoniTypes'; import { BalanceValueInfo } from '@subwallet/extension-koni-ui/types'; -export interface TokenSort { +export interface TokenAttributes { slug: string, symbol: string, total?: BalanceValueInfo, multiChainAsset?: string | null } -export const sortTokenByValue = (a: TokenSort, b: TokenSort): number => { +export const sortTokenByValue = (a: TokenAttributes, b: TokenAttributes): number => { if (a.total && b.total) { const convertValue = b.total.convertedValue.minus(a.total.convertedValue).toNumber(); @@ -38,17 +38,17 @@ export const sortTokenAlphabetically = (a: string, b: string): number => { } }; -export const sortByTokenPopularity = (a: string, b: string, aIsPiorityToken: boolean, bIsPiorityToken: boolean, aPiority: number, bPiority: number): number => { - if (aIsPiorityToken && !bIsPiorityToken) { +export const sortByTokenPopularity = (a: string, b: string, aIsPrioritizedToken: boolean, bIsPrioritizedToken: boolean, aPriority: number, bPriority: number): number => { + if (aIsPrioritizedToken && !bIsPrioritizedToken) { return -1; - } else if (!aIsPiorityToken && bIsPiorityToken) { + } else if (!aIsPrioritizedToken && bIsPrioritizedToken) { return 1; - } else if (!aIsPiorityToken && !bIsPiorityToken) { + } else if (!aIsPrioritizedToken && !bIsPrioritizedToken) { return sortTokenAlphabetically(a, b); } else { - if (aPiority < bPiority) { + if (aPriority < bPriority) { return -1; - } else if (aPiority > bPiority) { + } else if (aPriority > bPriority) { return 1; } else { return 0; @@ -56,19 +56,19 @@ export const sortByTokenPopularity = (a: string, b: string, aIsPiorityToken: boo } }; -export function sortToken (tokenGroupSlug: TokenSort[], popularTokens: Record) { +export function sortToken (tokenGroupSlug: TokenAttributes[], popularTokens: Record) { return tokenGroupSlug.sort((a, b) => { - const aBelongtoPiorityGroup = a.multiChainAsset ? Object.keys(popularTokens).includes(a.multiChainAsset) : false; - const bBelongtoPiorityGroup = b.multiChainAsset ? Object.keys(popularTokens).includes(b.multiChainAsset) : false; + const aBelongtoPrioritizedGroup = a.multiChainAsset ? Object.keys(popularTokens).includes(a.multiChainAsset) : false; + const bBelongtoPrioritizedGroup = b.multiChainAsset ? Object.keys(popularTokens).includes(b.multiChainAsset) : false; - const aIsPiorityToken = (aBelongtoPiorityGroup && a.multiChainAsset && Object.keys(popularTokens[a.multiChainAsset].tokens).includes(a.slug)) || Object.keys(popularTokens).includes(a.slug); - const bIsPiorityToken = (bBelongtoPiorityGroup && b.multiChainAsset && Object.keys(popularTokens[b.multiChainAsset].tokens).includes(b.slug)) || Object.keys(popularTokens).includes(b.slug); + const aIsPrioritizedToken = (aBelongtoPrioritizedGroup && a.multiChainAsset && Object.keys(popularTokens[a.multiChainAsset].tokens).includes(a.slug)) || Object.keys(popularTokens).includes(a.slug); + const bIsPrioritizedToken = (bBelongtoPrioritizedGroup && b.multiChainAsset && Object.keys(popularTokens[b.multiChainAsset].tokens).includes(b.slug)) || Object.keys(popularTokens).includes(b.slug); const aHasBalance = (a.total && a.total.convertedValue.toNumber() !== 0) || (a.total && a.total.value.toNumber() !== 0); const bHasBalance = (b.total && b.total.convertedValue.toNumber() !== 0) || (b.total && b.total.value.toNumber() !== 0); - const aPiority = a.multiChainAsset ? aIsPiorityToken ? (popularTokens[a.multiChainAsset].tokens)[a.slug] : 0 : aIsPiorityToken ? popularTokens[a.slug].piority : 0; - const bPiority = b.multiChainAsset ? bIsPiorityToken ? (popularTokens[b.multiChainAsset].tokens)[b.slug] : 0 : bIsPiorityToken ? popularTokens[b.slug].piority : 0; + const aPriority = a.multiChainAsset ? aIsPrioritizedToken ? (popularTokens[a.multiChainAsset].tokens)[a.slug] : 0 : aIsPrioritizedToken ? popularTokens[a.slug].priority : 0; + const bPriority = b.multiChainAsset ? bIsPrioritizedToken ? (popularTokens[b.multiChainAsset].tokens)[b.slug] : 0 : bIsPrioritizedToken ? popularTokens[b.slug].priority : 0; if (aHasBalance && bHasBalance) { return sortTokenByValue(a, b); @@ -77,7 +77,7 @@ export function sortToken (tokenGroupSlug: TokenSort[], popularTokens: Record Date: Mon, 6 Jan 2025 17:57:41 +0700 Subject: [PATCH 09/14] [Issue-3920] Fix lint --- .../extension-base/src/koni/background/handlers/Extension.ts | 2 +- packages/extension-koni-ui/src/stores/types.ts | 2 +- packages/extension-koni-ui/src/stores/utils/index.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/extension-base/src/koni/background/handlers/Extension.ts b/packages/extension-base/src/koni/background/handlers/Extension.ts index 9d47e98c1f..15fd62b932 100644 --- a/packages/extension-base/src/koni/background/handlers/Extension.ts +++ b/packages/extension-base/src/koni/background/handlers/Extension.ts @@ -8,7 +8,7 @@ import { _AssetRef, _AssetType, _ChainAsset, _ChainInfo, _MultiChainAsset } from import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers'; import { createSubscription } from '@subwallet/extension-base/background/handlers/subscriptions'; -import { AccountExternalError, AddressBookInfo, AmountData, AmountDataWithId, AssetSetting, AssetSettingUpdateReq, BondingOptionParams, BrowserConfirmationType, CampaignBanner, CampaignData, CampaignDataType, ChainType, CronReloadRequest, CrowdloanJson, ExternalRequestPromiseStatus, ExtrinsicType, KeyringState, MantaPayEnableMessage, MantaPayEnableParams, MantaPayEnableResponse, MantaPaySyncState, MetadataItem, NftCollection, NftJson, NftTransactionRequest, NftTransactionResponse, PrioritizedTokenList, PriceJson, RequestAccountCreateExternalV2, RequestAccountCreateHardwareMultiple, RequestAccountCreateHardwareV2, RequestAccountCreateWithSecretKey, RequestAccountExportPrivateKey, RequestAddInjectedAccounts, RequestApproveConnectWalletSession, RequestApproveWalletConnectNotSupport, RequestAuthorization, RequestAuthorizationBlock, RequestAuthorizationPerAccount, RequestAuthorizationPerSite, RequestAuthorizeApproveV2, RequestBondingSubmit, RequestCameraSettings, RequestCampaignBannerComplete, RequestChangeEnableChainPatrol, RequestChangeLanguage, RequestChangeMasterPassword, RequestChangePriceCurrency, RequestChangeShowBalance, RequestChangeShowZeroBalance, RequestChangeTimeAutoLock, RequestConfirmationComplete, RequestConfirmationCompleteTon, RequestConnectWalletConnect, RequestCrowdloanContributions, RequestDeleteContactAccount, RequestDisconnectWalletConnectSession, RequestEditContactAccount, RequestFindRawMetadata, RequestForgetSite, RequestFreeBalance, RequestGetTransaction, RequestKeyringExportMnemonic, RequestMaxTransferable, RequestMigratePassword, RequestParseEvmContractInput, RequestParseTransactionSubstrate, RequestPassPhishingPage, RequestQrParseRLP, RequestQrSignEvm, RequestQrSignSubstrate, RequestRejectConnectWalletSession, RequestRejectExternalRequest, RequestRejectWalletConnectNotSupport, RequestRemoveInjectedAccounts, RequestResetWallet, RequestResolveExternalRequest, RequestSaveAppConfig, RequestSaveBrowserConfig, RequestSaveOSConfig, RequestSaveRecentAccount, RequestSettingsType, RequestSigningApprovePasswordV2, RequestStakePoolingBonding, RequestStakePoolingUnbonding, RequestSubscribeHistory, RequestSubstrateNftSubmitTransaction, RequestTuringCancelStakeCompound, RequestTuringStakeCompound, RequestUnbondingSubmit, RequestUnlockKeyring, RequestUnlockType, ResolveAddressToDomainRequest, ResolveDomainRequest, ResponseAccountCreateWithSecretKey, ResponseAccountExportPrivateKey, ResponseChangeMasterPassword, ResponseFindRawMetadata, ResponseKeyringExportMnemonic, ResponseMigratePassword, ResponseNftImport, ResponseParseEvmContractInput, ResponseParseTransactionSubstrate, ResponseQrParseRLP, ResponseQrSignEvm, ResponseQrSignSubstrate, ResponseRejectExternalRequest, ResponseResetWallet, ResponseResolveExternalRequest, ResponseSubscribeHistory, ResponseUnlockKeyring, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, StakingType, SufficientMetadata, ThemeNames, TransactionHistoryItem, TransactionResponse, ValidateNetworkRequest, ValidateNetworkResponse, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; +import { AccountExternalError, AddressBookInfo, AmountData, AmountDataWithId, AssetSetting, AssetSettingUpdateReq, BondingOptionParams, BrowserConfirmationType, CampaignBanner, CampaignData, CampaignDataType, ChainType, CronReloadRequest, CrowdloanJson, ExternalRequestPromiseStatus, ExtrinsicType, KeyringState, MantaPayEnableMessage, MantaPayEnableParams, MantaPayEnableResponse, MantaPaySyncState, MetadataItem, NftCollection, NftJson, NftTransactionRequest, NftTransactionResponse, PriceJson, PrioritizedTokenList, RequestAccountCreateExternalV2, RequestAccountCreateHardwareMultiple, RequestAccountCreateHardwareV2, RequestAccountCreateWithSecretKey, RequestAccountExportPrivateKey, RequestAddInjectedAccounts, RequestApproveConnectWalletSession, RequestApproveWalletConnectNotSupport, RequestAuthorization, RequestAuthorizationBlock, RequestAuthorizationPerAccount, RequestAuthorizationPerSite, RequestAuthorizeApproveV2, RequestBondingSubmit, RequestCameraSettings, RequestCampaignBannerComplete, RequestChangeEnableChainPatrol, RequestChangeLanguage, RequestChangeMasterPassword, RequestChangePriceCurrency, RequestChangeShowBalance, RequestChangeShowZeroBalance, RequestChangeTimeAutoLock, RequestConfirmationComplete, RequestConfirmationCompleteTon, RequestConnectWalletConnect, RequestCrowdloanContributions, RequestDeleteContactAccount, RequestDisconnectWalletConnectSession, RequestEditContactAccount, RequestFindRawMetadata, RequestForgetSite, RequestFreeBalance, RequestGetTransaction, RequestKeyringExportMnemonic, RequestMaxTransferable, RequestMigratePassword, RequestParseEvmContractInput, RequestParseTransactionSubstrate, RequestPassPhishingPage, RequestQrParseRLP, RequestQrSignEvm, RequestQrSignSubstrate, RequestRejectConnectWalletSession, RequestRejectExternalRequest, RequestRejectWalletConnectNotSupport, RequestRemoveInjectedAccounts, RequestResetWallet, RequestResolveExternalRequest, RequestSaveAppConfig, RequestSaveBrowserConfig, RequestSaveOSConfig, RequestSaveRecentAccount, RequestSettingsType, RequestSigningApprovePasswordV2, RequestStakePoolingBonding, RequestStakePoolingUnbonding, RequestSubscribeHistory, RequestSubstrateNftSubmitTransaction, RequestTuringCancelStakeCompound, RequestTuringStakeCompound, RequestUnbondingSubmit, RequestUnlockKeyring, RequestUnlockType, ResolveAddressToDomainRequest, ResolveDomainRequest, ResponseAccountCreateWithSecretKey, ResponseAccountExportPrivateKey, ResponseChangeMasterPassword, ResponseFindRawMetadata, ResponseKeyringExportMnemonic, ResponseMigratePassword, ResponseNftImport, ResponseParseEvmContractInput, ResponseParseTransactionSubstrate, ResponseQrParseRLP, ResponseQrSignEvm, ResponseQrSignSubstrate, ResponseRejectExternalRequest, ResponseResetWallet, ResponseResolveExternalRequest, ResponseSubscribeHistory, ResponseUnlockKeyring, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, StakingType, SufficientMetadata, ThemeNames, TransactionHistoryItem, TransactionResponse, ValidateNetworkRequest, ValidateNetworkResponse, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; import { AccountAuthType, AuthorizeRequest, MessageTypes, MetadataRequest, RequestAccountExport, RequestAuthorizeCancel, RequestAuthorizeReject, RequestCurrentAccountAddress, RequestMetadataApprove, RequestMetadataReject, RequestSigningApproveSignature, RequestSigningCancel, RequestTypes, ResponseAccountExport, ResponseAuthorizeList, ResponseType, SigningRequest, WindowOpenParams } from '@subwallet/extension-base/background/types'; import { TransactionWarning } from '@subwallet/extension-base/background/warnings/TransactionWarning'; import { ALL_ACCOUNT_KEY, LATEST_SESSION, XCM_FEE_RATIO } from '@subwallet/extension-base/constants'; diff --git a/packages/extension-koni-ui/src/stores/types.ts b/packages/extension-koni-ui/src/stores/types.ts index 08956daca0..b0b8f3cd6f 100644 --- a/packages/extension-koni-ui/src/stores/types.ts +++ b/packages/extension-koni-ui/src/stores/types.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { _AssetRef, _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types'; -import { AddressBookState, AllLogoMap, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationDefinitions, ConfirmationsQueue, ConfirmationsQueueTon, ConfirmationType, CrowdloanItem, KeyringState, LanguageType, MantaPayConfig, NftCollection, NftItem, NominatorMetadata, PrioritizedTokenList, PriceJson, StakingItem, StakingRewardItem, TransactionHistoryItem, UiSettings, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; +import { AddressBookState, AllLogoMap, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationDefinitions, ConfirmationsQueue, ConfirmationsQueueTon, ConfirmationType, CrowdloanItem, KeyringState, LanguageType, MantaPayConfig, NftCollection, NftItem, NominatorMetadata, PriceJson, PrioritizedTokenList, StakingItem, StakingRewardItem, TransactionHistoryItem, UiSettings, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; import { AccountsContext, AuthorizeRequest, MetadataRequest, SigningRequest } from '@subwallet/extension-base/background/types'; import { _ChainApiStatus, _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { AppBannerData, AppConfirmationData, AppPopupData } from '@subwallet/extension-base/services/mkt-campaign-service/types'; diff --git a/packages/extension-koni-ui/src/stores/utils/index.ts b/packages/extension-koni-ui/src/stores/utils/index.ts index 461a59c1e4..b2493ea979 100644 --- a/packages/extension-koni-ui/src/stores/utils/index.ts +++ b/packages/extension-koni-ui/src/stores/utils/index.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { _AssetRef, _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types'; -import { AddressBookInfo, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationsQueue, ConfirmationsQueueTon, CrowdloanJson, KeyringState, MantaPayConfig, MantaPaySyncState, NftCollection, NftJson, NominatorMetadata, PrioritizedTokenList, PriceJson, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, TransactionHistoryItem, UiSettings } from '@subwallet/extension-base/background/KoniTypes'; +import { AddressBookInfo, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationsQueue, ConfirmationsQueueTon, CrowdloanJson, KeyringState, MantaPayConfig, MantaPaySyncState, NftCollection, NftJson, NominatorMetadata, PriceJson, PrioritizedTokenList, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, TransactionHistoryItem, UiSettings } from '@subwallet/extension-base/background/KoniTypes'; import { AccountsContext, AuthorizeRequest, ConfirmationRequestBase, MetadataRequest, SigningRequest } from '@subwallet/extension-base/background/types'; import { _ChainApiStatus, _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { AppBannerData, AppConfirmationData, AppPopupData } from '@subwallet/extension-base/services/mkt-campaign-service/types'; From 15d0b1723d1d021714cb9274516f64911256623b Mon Sep 17 00:00:00 2001 From: lw Date: Tue, 7 Jan 2025 15:28:08 +0700 Subject: [PATCH 10/14] [Issue-3920] Refactor code related to priority tokens --- .../src/background/KoniTypes.ts | 8 ++-- .../src/koni/background/handlers/Extension.ts | 18 ++++---- .../src/services/chain-service/index.ts | 30 ++++++------- .../src/Popup/Home/Tokens/index.tsx | 21 +++++---- .../ReceiveModalNew/parts/TokenSelector.tsx | 18 +++++--- .../src/contexts/DataContext.tsx | 4 +- .../src/hooks/common/index.ts | 2 +- .../src/hooks/common/useDebouncedValue.ts | 20 +++++++++ .../src/stores/feature/common/ChainStore.ts | 8 ++-- .../extension-koni-ui/src/stores/types.ts | 4 +- .../src/stores/utils/index.ts | 12 ++--- .../extension-koni-ui/src/utils/sort/token.ts | 44 +++++++++++-------- 12 files changed, 113 insertions(+), 76 deletions(-) create mode 100644 packages/extension-koni-ui/src/hooks/common/useDebouncedValue.ts diff --git a/packages/extension-base/src/background/KoniTypes.ts b/packages/extension-base/src/background/KoniTypes.ts index d67463de7b..c1428b04c6 100644 --- a/packages/extension-base/src/background/KoniTypes.ts +++ b/packages/extension-base/src/background/KoniTypes.ts @@ -1711,9 +1711,9 @@ export interface RequestAddPspToken { // Popular tokens -export interface PrioritizedTokenList { - tokens: Record, - priority: number +export interface TokenPriorityDetails { + priorityTokens: Record, + groupPriority: number } /// WalletConnect @@ -2307,7 +2307,7 @@ export interface KoniRequestSignatures { /* Ledger */ /* Popular tokens */ - 'pri(popular.tokens)': [null, Record, Record]; + 'pri(tokens.subscribePriority)': [null, Record, Record]; /* Popular tokens */ } diff --git a/packages/extension-base/src/koni/background/handlers/Extension.ts b/packages/extension-base/src/koni/background/handlers/Extension.ts index 15fd62b932..991a63cbb2 100644 --- a/packages/extension-base/src/koni/background/handlers/Extension.ts +++ b/packages/extension-base/src/koni/background/handlers/Extension.ts @@ -8,7 +8,7 @@ import { _AssetRef, _AssetType, _ChainAsset, _ChainInfo, _MultiChainAsset } from import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers'; import { createSubscription } from '@subwallet/extension-base/background/handlers/subscriptions'; -import { AccountExternalError, AddressBookInfo, AmountData, AmountDataWithId, AssetSetting, AssetSettingUpdateReq, BondingOptionParams, BrowserConfirmationType, CampaignBanner, CampaignData, CampaignDataType, ChainType, CronReloadRequest, CrowdloanJson, ExternalRequestPromiseStatus, ExtrinsicType, KeyringState, MantaPayEnableMessage, MantaPayEnableParams, MantaPayEnableResponse, MantaPaySyncState, MetadataItem, NftCollection, NftJson, NftTransactionRequest, NftTransactionResponse, PriceJson, PrioritizedTokenList, RequestAccountCreateExternalV2, RequestAccountCreateHardwareMultiple, RequestAccountCreateHardwareV2, RequestAccountCreateWithSecretKey, RequestAccountExportPrivateKey, RequestAddInjectedAccounts, RequestApproveConnectWalletSession, RequestApproveWalletConnectNotSupport, RequestAuthorization, RequestAuthorizationBlock, RequestAuthorizationPerAccount, RequestAuthorizationPerSite, RequestAuthorizeApproveV2, RequestBondingSubmit, RequestCameraSettings, RequestCampaignBannerComplete, RequestChangeEnableChainPatrol, RequestChangeLanguage, RequestChangeMasterPassword, RequestChangePriceCurrency, RequestChangeShowBalance, RequestChangeShowZeroBalance, RequestChangeTimeAutoLock, RequestConfirmationComplete, RequestConfirmationCompleteTon, RequestConnectWalletConnect, RequestCrowdloanContributions, RequestDeleteContactAccount, RequestDisconnectWalletConnectSession, RequestEditContactAccount, RequestFindRawMetadata, RequestForgetSite, RequestFreeBalance, RequestGetTransaction, RequestKeyringExportMnemonic, RequestMaxTransferable, RequestMigratePassword, RequestParseEvmContractInput, RequestParseTransactionSubstrate, RequestPassPhishingPage, RequestQrParseRLP, RequestQrSignEvm, RequestQrSignSubstrate, RequestRejectConnectWalletSession, RequestRejectExternalRequest, RequestRejectWalletConnectNotSupport, RequestRemoveInjectedAccounts, RequestResetWallet, RequestResolveExternalRequest, RequestSaveAppConfig, RequestSaveBrowserConfig, RequestSaveOSConfig, RequestSaveRecentAccount, RequestSettingsType, RequestSigningApprovePasswordV2, RequestStakePoolingBonding, RequestStakePoolingUnbonding, RequestSubscribeHistory, RequestSubstrateNftSubmitTransaction, RequestTuringCancelStakeCompound, RequestTuringStakeCompound, RequestUnbondingSubmit, RequestUnlockKeyring, RequestUnlockType, ResolveAddressToDomainRequest, ResolveDomainRequest, ResponseAccountCreateWithSecretKey, ResponseAccountExportPrivateKey, ResponseChangeMasterPassword, ResponseFindRawMetadata, ResponseKeyringExportMnemonic, ResponseMigratePassword, ResponseNftImport, ResponseParseEvmContractInput, ResponseParseTransactionSubstrate, ResponseQrParseRLP, ResponseQrSignEvm, ResponseQrSignSubstrate, ResponseRejectExternalRequest, ResponseResetWallet, ResponseResolveExternalRequest, ResponseSubscribeHistory, ResponseUnlockKeyring, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, StakingType, SufficientMetadata, ThemeNames, TransactionHistoryItem, TransactionResponse, ValidateNetworkRequest, ValidateNetworkResponse, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; +import { AccountExternalError, AddressBookInfo, AmountData, AmountDataWithId, AssetSetting, AssetSettingUpdateReq, BondingOptionParams, BrowserConfirmationType, CampaignBanner, CampaignData, CampaignDataType, ChainType, CronReloadRequest, CrowdloanJson, ExternalRequestPromiseStatus, ExtrinsicType, KeyringState, MantaPayEnableMessage, MantaPayEnableParams, MantaPayEnableResponse, MantaPaySyncState, MetadataItem, NftCollection, NftJson, NftTransactionRequest, NftTransactionResponse, PriceJson, RequestAccountCreateExternalV2, RequestAccountCreateHardwareMultiple, RequestAccountCreateHardwareV2, RequestAccountCreateWithSecretKey, RequestAccountExportPrivateKey, RequestAddInjectedAccounts, RequestApproveConnectWalletSession, RequestApproveWalletConnectNotSupport, RequestAuthorization, RequestAuthorizationBlock, RequestAuthorizationPerAccount, RequestAuthorizationPerSite, RequestAuthorizeApproveV2, RequestBondingSubmit, RequestCameraSettings, RequestCampaignBannerComplete, RequestChangeEnableChainPatrol, RequestChangeLanguage, RequestChangeMasterPassword, RequestChangePriceCurrency, RequestChangeShowBalance, RequestChangeShowZeroBalance, RequestChangeTimeAutoLock, RequestConfirmationComplete, RequestConfirmationCompleteTon, RequestConnectWalletConnect, RequestCrowdloanContributions, RequestDeleteContactAccount, RequestDisconnectWalletConnectSession, RequestEditContactAccount, RequestFindRawMetadata, RequestForgetSite, RequestFreeBalance, RequestGetTransaction, RequestKeyringExportMnemonic, RequestMaxTransferable, RequestMigratePassword, RequestParseEvmContractInput, RequestParseTransactionSubstrate, RequestPassPhishingPage, RequestQrParseRLP, RequestQrSignEvm, RequestQrSignSubstrate, RequestRejectConnectWalletSession, RequestRejectExternalRequest, RequestRejectWalletConnectNotSupport, RequestRemoveInjectedAccounts, RequestResetWallet, RequestResolveExternalRequest, RequestSaveAppConfig, RequestSaveBrowserConfig, RequestSaveOSConfig, RequestSaveRecentAccount, RequestSettingsType, RequestSigningApprovePasswordV2, RequestStakePoolingBonding, RequestStakePoolingUnbonding, RequestSubscribeHistory, RequestSubstrateNftSubmitTransaction, RequestTuringCancelStakeCompound, RequestTuringStakeCompound, RequestUnbondingSubmit, RequestUnlockKeyring, RequestUnlockType, ResolveAddressToDomainRequest, ResolveDomainRequest, ResponseAccountCreateWithSecretKey, ResponseAccountExportPrivateKey, ResponseChangeMasterPassword, ResponseFindRawMetadata, ResponseKeyringExportMnemonic, ResponseMigratePassword, ResponseNftImport, ResponseParseEvmContractInput, ResponseParseTransactionSubstrate, ResponseQrParseRLP, ResponseQrSignEvm, ResponseQrSignSubstrate, ResponseRejectExternalRequest, ResponseResetWallet, ResponseResolveExternalRequest, ResponseSubscribeHistory, ResponseUnlockKeyring, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, StakingType, SufficientMetadata, ThemeNames, TokenPriorityDetails, TransactionHistoryItem, TransactionResponse, ValidateNetworkRequest, ValidateNetworkResponse, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; import { AccountAuthType, AuthorizeRequest, MessageTypes, MetadataRequest, RequestAccountExport, RequestAuthorizeCancel, RequestAuthorizeReject, RequestCurrentAccountAddress, RequestMetadataApprove, RequestMetadataReject, RequestSigningApproveSignature, RequestSigningCancel, RequestTypes, ResponseAccountExport, ResponseAuthorizeList, ResponseType, SigningRequest, WindowOpenParams } from '@subwallet/extension-base/background/types'; import { TransactionWarning } from '@subwallet/extension-base/background/warnings/TransactionWarning'; import { ALL_ACCOUNT_KEY, LATEST_SESSION, XCM_FEE_RATIO } from '@subwallet/extension-base/constants'; @@ -3948,10 +3948,10 @@ export default class KoniExtension { /* Popular tokens */ - private subscribePopularTokens (id: string, port: chrome.runtime.Port): Record { - const cb = createSubscription<'pri(popular.tokens)'>(id, port); + private subscribePriorityTokens (id: string, port: chrome.runtime.Port): Record { + const cb = createSubscription<'pri(tokens.subscribePriority)'>(id, port); - const subscription = this.#koniState.chainService.observable.popularTokens.subscribe(cb); + const subscription = this.#koniState.chainService.observable.priorityTokens.subscribe(cb); this.createUnsubscriptionHandle(id, subscription.unsubscribe); @@ -3959,7 +3959,7 @@ export default class KoniExtension { this.cancelSubscription(id); }); - return this.#koniState.chainService.value.popularTokens; + return this.#koniState.chainService.value.priorityTokens; } /* Popular tokens */ @@ -4575,10 +4575,10 @@ export default class KoniExtension { return this.subscribeLedgerGenericAllowChains(id, port); /* Ledger */ - /* Popular tokens */ - case 'pri(popular.tokens)': - return this.subscribePopularTokens(id, port); - /* Popular tokens */ + /* Priority tokens */ + case 'pri(tokens.subscribePriority)': + return this.subscribePriorityTokens(id, port); + /* Priority tokens */ // Default default: diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index e376ca7be3..87c85e1384 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -3,7 +3,7 @@ import { AssetLogoMap, AssetRefMap, ChainAssetMap, ChainInfoMap, ChainLogoMap, MultiChainAssetMap } from '@subwallet/chain-list'; import { _AssetRef, _AssetRefPath, _AssetType, _ChainAsset, _ChainInfo, _ChainStatus, _EvmInfo, _MultiChainAsset, _SubstrateChainType, _SubstrateInfo, _TonInfo } from '@subwallet/chain-list/types'; -import { AssetSetting, PrioritizedTokenList, ValidateNetworkResponse } from '@subwallet/extension-base/background/KoniTypes'; +import { AssetSetting, TokenPriorityDetails, ValidateNetworkResponse } from '@subwallet/extension-base/background/KoniTypes'; import { _DEFAULT_ACTIVE_CHAINS, _ZK_ASSET_PREFIX, LATEST_CHAIN_DATA_FETCHING_INTERVAL } from '@subwallet/extension-base/services/chain-service/constants'; import { EvmChainHandler } from '@subwallet/extension-base/services/chain-service/handler/EvmChainHandler'; import { MantaPrivateHandler } from '@subwallet/extension-base/services/chain-service/handler/manta/MantaPrivateHandler'; @@ -92,7 +92,7 @@ export class ChainService { private assetLogoMapSubject = new BehaviorSubject>(AssetLogoMap); private chainLogoMapSubject = new BehaviorSubject>(ChainLogoMap); private ledgerGenericAllowChainsSubject = new BehaviorSubject([]); - private popularTokensSubject = new BehaviorSubject>({}); + private priorityTokensSubject = new BehaviorSubject>({}); // Todo: Update to new store indexed DB private store: AssetSettingStore = new AssetSettingStore(); @@ -124,28 +124,28 @@ export class ChainService { public get value () { const ledgerGenericAllowChains = this.ledgerGenericAllowChainsSubject; - const popularTokens = this.popularTokensSubject; + const priorityTokens = this.priorityTokensSubject; return { get ledgerGenericAllowChains () { return ledgerGenericAllowChains.value; }, - get popularTokens () { - return popularTokens.value; + get priorityTokens () { + return priorityTokens.value; } }; } public get observable () { const ledgerGenericAllowChains = this.ledgerGenericAllowChainsSubject; - const popularTokens = this.popularTokensSubject; + const priorityTokens = this.priorityTokensSubject; return { get ledgerGenericAllowChains () { return ledgerGenericAllowChains.asObservable(); }, - get popularTokens () { - return popularTokens.asObservable(); + get priorityTokens () { + return priorityTokens.asObservable(); } }; } @@ -776,8 +776,8 @@ export class ChainService { this.logger.log('Finished updating latest ledger generic allow chains'); } - handleLatestPopularTokens (latestPopularTokens: Record) { - this.popularTokensSubject.next(latestPopularTokens); + handleLatestPriorityTokens (latestPriorityTokens: Record) { + this.priorityTokensSubject.next(latestPriorityTokens); this.logger.log('Finished updating latest popular tokens'); } @@ -801,9 +801,9 @@ export class ChainService { }) .catch(console.error); - this.fetchLatestPopularTokens() - .then((latestPopularTokens) => { - this.handleLatestPopularTokens(latestPopularTokens); + this.fetchLatestPriorityTokens() + .then((latestPriorityTokens) => { + this.handleLatestPriorityTokens(latestPriorityTokens); }) .catch(console.error); } @@ -1108,8 +1108,8 @@ export class ChainService { return await fetchStaticData('chains/ledger-generic-allow-chains') || []; } - private async fetchLatestPopularTokens () { - return await fetchStaticData>('chain-assets/popular-tokens') || []; + private async fetchLatestPriorityTokens () { + return await fetchStaticData>('chain-assets/priority-tokens') || []; } private async initChains () { diff --git a/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx b/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx index 869e88e043..6b926ff38e 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx @@ -10,14 +10,14 @@ import { TokenGroupBalanceItem } from '@subwallet/extension-koni-ui/components/T import { DEFAULT_SWAP_PARAMS, DEFAULT_TRANSFER_PARAMS, IS_SHOW_TON_CONTRACT_VERSION_WARNING, SWAP_TRANSACTION, TON_ACCOUNT_SELECTOR_MODAL, TON_WALLET_CONTRACT_SELECTOR_MODAL, TRANSFER_TRANSACTION } from '@subwallet/extension-koni-ui/constants'; import { DataContext } from '@subwallet/extension-koni-ui/contexts/DataContext'; import { HomeContext } from '@subwallet/extension-koni-ui/contexts/screen/HomeContext'; -import { useCoreReceiveModalHelper, useGetBannerByScreen, useGetChainSlugsByAccount, useSetCurrentPage } from '@subwallet/extension-koni-ui/hooks'; +import { useCoreReceiveModalHelper, useDebouncedValue, useGetBannerByScreen, useGetChainSlugsByAccount, useSetCurrentPage } from '@subwallet/extension-koni-ui/hooks'; import useNotification from '@subwallet/extension-koni-ui/hooks/common/useNotification'; import useTranslation from '@subwallet/extension-koni-ui/hooks/common/useTranslation'; import { UpperBlock } from '@subwallet/extension-koni-ui/Popup/Home/Tokens/UpperBlock'; import { RootState } from '@subwallet/extension-koni-ui/stores'; import { AccountAddressItemType, ThemeProps, TransferParams } from '@subwallet/extension-koni-ui/types'; import { TokenBalanceItemType } from '@subwallet/extension-koni-ui/types/balance'; -import { getTransactionFromAccountProxyValue, isAccountAll, sortToken } from '@subwallet/extension-koni-ui/utils'; +import { getTransactionFromAccountProxyValue, isAccountAll, sortTokensByStandard } from '@subwallet/extension-koni-ui/utils'; import { isTonAddress } from '@subwallet/keyring'; import { Button, Icon, ModalContext, SwAlert } from '@subwallet/react-ui'; import classNames from 'classnames'; @@ -30,6 +30,7 @@ import styled from 'styled-components'; import { useLocalStorage } from 'usehooks-ts'; type Props = ThemeProps; + const tonWalletContractSelectorModalId = TON_WALLET_CONTRACT_SELECTOR_MODAL; const tonAccountSelectorModalId = TON_ACCOUNT_SELECTOR_MODAL; @@ -47,7 +48,7 @@ const Component = (): React.ReactElement => { totalBalanceInfo }, tokenGroupStructure: { sortedTokenGroups } } = useContext(HomeContext); const notify = useNotification(); const { onOpenReceive, receiveModalProps } = useCoreReceiveModalHelper(); - const popularTokens = useSelector((state: RootState) => state.chainStore.popularTokens); + const priorityTokens = useSelector((state: RootState) => state.chainStore.priorityTokens); const isZkModeSyncing = useSelector((state: RootState) => state.mantaPay.isSyncing); const zkModeSyncProgress = useSelector((state: RootState) => state.mantaPay.progress); @@ -292,17 +293,21 @@ const Component = (): React.ReactElement => { navigate('/transaction/swap'); }, [accountProxies, currentAccountProxy, navigate, notify, setSwapStorage, t]); - const tokenGroupBalanceItems = useMemo(() => { + const debouncedTokenGroupBalanceMap = useDebouncedValue>(tokenGroupBalanceMap, 300); + + const tokenGroupBalanceItems = useMemo((): TokenBalanceItemType[] => { const result: TokenBalanceItemType[] = []; sortedTokenGroups.forEach((tokenGroupSlug) => { - if (tokenGroupBalanceMap[tokenGroupSlug]) { - result.push(tokenGroupBalanceMap[tokenGroupSlug]); + if (debouncedTokenGroupBalanceMap[tokenGroupSlug]) { + result.push(debouncedTokenGroupBalanceMap[tokenGroupSlug]); } }); - return sortToken(result, popularTokens) as TokenBalanceItemType[]; - }, [sortedTokenGroups, tokenGroupBalanceMap, popularTokens]); + sortTokensByStandard(result, priorityTokens); + + return result; + }, [sortedTokenGroups, debouncedTokenGroupBalanceMap, priorityTokens]); useEffect(() => { window.addEventListener('resize', handleResize); diff --git a/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx b/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx index 6e678142aa..0b97ac00a0 100644 --- a/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx +++ b/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx @@ -10,7 +10,7 @@ import { RECEIVE_MODAL_TOKEN_SELECTOR } from '@subwallet/extension-koni-ui/const import { useSelector, useTranslation } from '@subwallet/extension-koni-ui/hooks'; import { RootState } from '@subwallet/extension-koni-ui/stores'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; -import { sortToken } from '@subwallet/extension-koni-ui/utils'; +import { sortTokensByStandard } from '@subwallet/extension-koni-ui/utils'; import { ModalContext, SwList, SwModal } from '@subwallet/react-ui'; import { SwListSectionRef } from '@subwallet/react-ui/es/sw-list'; import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; @@ -33,7 +33,7 @@ function Component ({ className = '', items, onCancel, onSelectItem }: Props): R const [currentSearchText, setCurrentSearchText] = useState(''); // @ts-ignore const chainInfoMap = useSelector((state) => state.chainStore.chainInfoMap); - const popularTokens = useSelector((state: RootState) => state.chainStore.popularTokens); + const priorityTokens = useSelector((state: RootState) => state.chainStore.priorityTokens); const listItems = useMemo(() => { const filteredList = items.filter((item) => { @@ -42,6 +42,12 @@ function Component ({ className = '', items, onCancel, onSelectItem }: Props): R return item.symbol.toLowerCase().includes(currentSearchText.toLowerCase()) || chainName.toLowerCase().includes(currentSearchText.toLowerCase()); }); + if (!currentSearchText) { + sortTokensByStandard(filteredList, priorityTokens); + + return filteredList; + } + if (currentSearchText.toLowerCase() === 'ton') { const tonItemIndex = filteredList.findIndex((item) => item.slug === 'ton-NATIVE-TON'); @@ -53,13 +59,11 @@ function Component ({ className = '', items, onCancel, onSelectItem }: Props): R } } - return filteredList; - } else if (currentSearchText.toLowerCase() === '') { - return sortToken(filteredList, popularTokens) as _ChainAsset[]; - } else { return filteredList; } - }, [chainInfoMap, currentSearchText, items, popularTokens]); + + return filteredList; + }, [chainInfoMap, currentSearchText, items, priorityTokens]); const isActive = checkActive(modalId); diff --git a/packages/extension-koni-ui/src/contexts/DataContext.tsx b/packages/extension-koni-ui/src/contexts/DataContext.tsx index bdb7ec6f78..7c041b71ba 100644 --- a/packages/extension-koni-ui/src/contexts/DataContext.tsx +++ b/packages/extension-koni-ui/src/contexts/DataContext.tsx @@ -3,7 +3,7 @@ import { ping } from '@subwallet/extension-koni-ui/messaging'; import { persistor, store, StoreName } from '@subwallet/extension-koni-ui/stores'; -import { getMissionPoolData, subscribeAccountsData, subscribeAddressBook, subscribeAssetLogoMaps, subscribeAssetRegistry, subscribeAssetSettings, subscribeAuthorizeRequests, subscribeAuthUrls, subscribeBalance, subscribeBuyServices, subscribeBuyTokens, subscribeCampaignBannerData, subscribeCampaignConfirmationData, subscribeCampaignPopupData, subscribeCampaignPopupVisibility, subscribeChainInfoMap, subscribeChainLogoMaps, subscribeChainStakingMetadata, subscribeChainStateMap, subscribeChainStatusMap, subscribeConfirmationRequests, subscribeConfirmationRequestsTon, subscribeConnectWCRequests, subscribeCrowdloan, subscribeKeyringState, subscribeLedgerGenericAllowNetworks, subscribeMantaPayConfig, subscribeMantaPaySyncingState, subscribeMetadataRequests, subscribeMultiChainAssetMap, subscribeNftCollections, subscribeNftItems, subscribePopularTokens, subscribePrice, subscribeProcessingCampaign, subscribeRewardHistory, subscribeSigningRequests, subscribeStaking, subscribeStakingNominatorMetadata, subscribeStakingReward, subscribeSwapPairs, subscribeTransactionRequests, subscribeTxHistory, subscribeUiSettings, subscribeUnreadNotificationCount, subscribeWalletConnectSessions, subscribeWCNotSupportRequests, subscribeXcmRefMap, subscribeYieldMinAmountPercent, subscribeYieldPoolInfo, subscribeYieldPositionInfo, subscribeYieldReward } from '@subwallet/extension-koni-ui/stores/utils'; +import { getMissionPoolData, subscribeAccountsData, subscribeAddressBook, subscribeAssetLogoMaps, subscribeAssetRegistry, subscribeAssetSettings, subscribeAuthorizeRequests, subscribeAuthUrls, subscribeBalance, subscribeBuyServices, subscribeBuyTokens, subscribeCampaignBannerData, subscribeCampaignConfirmationData, subscribeCampaignPopupData, subscribeCampaignPopupVisibility, subscribeChainInfoMap, subscribeChainLogoMaps, subscribeChainStakingMetadata, subscribeChainStateMap, subscribeChainStatusMap, subscribeConfirmationRequests, subscribeConfirmationRequestsTon, subscribeConnectWCRequests, subscribeCrowdloan, subscribeKeyringState, subscribeLedgerGenericAllowNetworks, subscribeMantaPayConfig, subscribeMantaPaySyncingState, subscribeMetadataRequests, subscribeMultiChainAssetMap, subscribeNftCollections, subscribeNftItems, subscribePrice, subscribePriorityTokens, subscribeProcessingCampaign, subscribeRewardHistory, subscribeSigningRequests, subscribeStaking, subscribeStakingNominatorMetadata, subscribeStakingReward, subscribeSwapPairs, subscribeTransactionRequests, subscribeTxHistory, subscribeUiSettings, subscribeUnreadNotificationCount, subscribeWalletConnectSessions, subscribeWCNotSupportRequests, subscribeXcmRefMap, subscribeYieldMinAmountPercent, subscribeYieldPoolInfo, subscribeYieldPositionInfo, subscribeYieldReward } from '@subwallet/extension-koni-ui/stores/utils'; import Bowser from 'bowser'; import React from 'react'; import { Provider } from 'react-redux'; @@ -200,7 +200,7 @@ export const DataContextProvider = ({ children }: DataContextProviderProps) => { _DataContext.addHandler({ ...subscribeChainStatusMap, name: 'subscribeChainStatusMap', relatedStores: ['chainStore'], isStartImmediately: true }); _DataContext.addHandler({ ...subscribeChainInfoMap, name: 'subscribeChainInfoMap', relatedStores: ['chainStore'], isStartImmediately: true }); _DataContext.addHandler({ ...subscribeLedgerGenericAllowNetworks, name: 'subscribeLedgerGenericAllowNetworks', relatedStores: ['chainStore'], isStartImmediately: true }); - _DataContext.addHandler({ ...subscribePopularTokens, name: 'subscribePopularTokens', relatedStores: ['chainStore'], isStartImmediately: false }); + _DataContext.addHandler({ ...subscribePriorityTokens, name: 'subscribePriorityTokens', relatedStores: ['chainStore'], isStartImmediately: false }); _DataContext.addHandler({ ...subscribeAssetRegistry, name: 'subscribeAssetRegistry', relatedStores: ['assetRegistry'], isStartImmediately: true }); _DataContext.addHandler({ ...subscribeMultiChainAssetMap, name: 'subscribeMultiChainAssetMap', relatedStores: ['assetRegistry'], isStartImmediately: true }); diff --git a/packages/extension-koni-ui/src/hooks/common/index.ts b/packages/extension-koni-ui/src/hooks/common/index.ts index aa194a3edf..ee1c5536ac 100644 --- a/packages/extension-koni-ui/src/hooks/common/index.ts +++ b/packages/extension-koni-ui/src/hooks/common/index.ts @@ -12,8 +12,8 @@ export { default as useTranslation } from './useTranslation'; export { default as useUILock } from './useUILock'; export { default as useUnlockChecker } from './useUnlockChecker'; export { default as useAlert } from './useAlert'; -export { default as useGetChainSlugsByCurrentAccount } from './useGetChainSlugsByCurrentAccount'; export { default as useSetSessionLatest } from './useSetSessionLatest'; +export { default as useDebouncedValue } from './useDebouncedValue'; export * from './useSelector'; export * from './useLazyList'; diff --git a/packages/extension-koni-ui/src/hooks/common/useDebouncedValue.ts b/packages/extension-koni-ui/src/hooks/common/useDebouncedValue.ts new file mode 100644 index 0000000000..c86b157297 --- /dev/null +++ b/packages/extension-koni-ui/src/hooks/common/useDebouncedValue.ts @@ -0,0 +1,20 @@ +// Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import { useEffect, useState } from 'react'; + +function useDebouncedValue (value: T, delay: number): T { + const [debouncedValue, setDebouncedValue] = useState(value); + + useEffect(() => { + const timer = setTimeout(() => { + setDebouncedValue(value); + }, delay); + + return () => clearTimeout(timer); + }, [value, delay]); + + return debouncedValue; +} + +export default useDebouncedValue; diff --git a/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts b/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts index 5abfc2fcd3..1f96ffa3db 100644 --- a/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts +++ b/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts @@ -3,7 +3,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { _ChainInfo } from '@subwallet/chain-list/types'; -import { PrioritizedTokenList } from '@subwallet/extension-base/background/KoniTypes'; +import { TokenPriorityDetails } from '@subwallet/extension-base/background/KoniTypes'; import { _ChainApiStatus, _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { ChainStore, ReduxStatus } from '@subwallet/extension-koni-ui/stores/types'; @@ -12,7 +12,7 @@ const initialState: ChainStore = { chainStateMap: {}, chainStatusMap: {}, ledgerGenericAllowNetworks: [], - popularTokens: {}, + priorityTokens: {}, reduxStatus: ReduxStatus.INIT }; @@ -56,12 +56,12 @@ const chainStoreSlice = createSlice({ reduxStatus: ReduxStatus.READY }; }, - updatePopularTokens (state, action: PayloadAction>) { + updatePriorityTokens (state, action: PayloadAction>) { const { payload } = action; return { ...state, - popularTokens: payload, + priorityTokens: payload, reduxStatus: ReduxStatus.READY }; } diff --git a/packages/extension-koni-ui/src/stores/types.ts b/packages/extension-koni-ui/src/stores/types.ts index b0b8f3cd6f..c02af1a54d 100644 --- a/packages/extension-koni-ui/src/stores/types.ts +++ b/packages/extension-koni-ui/src/stores/types.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { _AssetRef, _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types'; -import { AddressBookState, AllLogoMap, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationDefinitions, ConfirmationsQueue, ConfirmationsQueueTon, ConfirmationType, CrowdloanItem, KeyringState, LanguageType, MantaPayConfig, NftCollection, NftItem, NominatorMetadata, PriceJson, PrioritizedTokenList, StakingItem, StakingRewardItem, TransactionHistoryItem, UiSettings, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; +import { AddressBookState, AllLogoMap, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationDefinitions, ConfirmationsQueue, ConfirmationsQueueTon, ConfirmationType, CrowdloanItem, KeyringState, LanguageType, MantaPayConfig, NftCollection, NftItem, NominatorMetadata, PriceJson, StakingItem, StakingRewardItem, TokenPriorityDetails, TransactionHistoryItem, UiSettings, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes'; import { AccountsContext, AuthorizeRequest, MetadataRequest, SigningRequest } from '@subwallet/extension-base/background/types'; import { _ChainApiStatus, _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { AppBannerData, AppConfirmationData, AppPopupData } from '@subwallet/extension-base/services/mkt-campaign-service/types'; @@ -126,7 +126,7 @@ export interface ChainStore extends BaseReduxStore { chainStateMap: Record chainStatusMap: Record ledgerGenericAllowNetworks: string[]; - popularTokens: Record; + priorityTokens: Record; } export interface BalanceStore extends BaseReduxStore { diff --git a/packages/extension-koni-ui/src/stores/utils/index.ts b/packages/extension-koni-ui/src/stores/utils/index.ts index b2493ea979..1a7d27f62c 100644 --- a/packages/extension-koni-ui/src/stores/utils/index.ts +++ b/packages/extension-koni-ui/src/stores/utils/index.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { _AssetRef, _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types'; -import { AddressBookInfo, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationsQueue, ConfirmationsQueueTon, CrowdloanJson, KeyringState, MantaPayConfig, MantaPaySyncState, NftCollection, NftJson, NominatorMetadata, PriceJson, PrioritizedTokenList, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, TransactionHistoryItem, UiSettings } from '@subwallet/extension-base/background/KoniTypes'; +import { AddressBookInfo, AssetSetting, CampaignBanner, ChainStakingMetadata, ConfirmationsQueue, ConfirmationsQueueTon, CrowdloanJson, KeyringState, MantaPayConfig, MantaPaySyncState, NftCollection, NftJson, NominatorMetadata, PriceJson, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, TokenPriorityDetails, TransactionHistoryItem, UiSettings } from '@subwallet/extension-base/background/KoniTypes'; import { AccountsContext, AuthorizeRequest, ConfirmationRequestBase, MetadataRequest, SigningRequest } from '@subwallet/extension-base/background/types'; import { _ChainApiStatus, _ChainState } from '@subwallet/extension-base/services/chain-service/types'; import { AppBannerData, AppConfirmationData, AppPopupData } from '@subwallet/extension-base/services/mkt-campaign-service/types'; @@ -509,10 +509,10 @@ export const updateUnreadNotificationCountMap = (data: Record) = export const subscribeUnreadNotificationCount = lazySubscribeMessage('pri(inappNotification.subscribeUnreadNotificationCountMap)', null, updateUnreadNotificationCountMap, updateUnreadNotificationCountMap); /* Notification service */ -/* Popular tokens */ -export const updatePopularTokens = (data: Record) => { - store.dispatch({ type: 'chainStore/updatePopularTokens', payload: data }); +/* Priority tokens */ +export const updatePriorityTokens = (data: Record) => { + store.dispatch({ type: 'chainStore/updatePriorityTokens', payload: data }); }; -export const subscribePopularTokens = lazySubscribeMessage('pri(popular.tokens)', null, updatePopularTokens, updatePopularTokens); -/* Popular tokens */ +export const subscribePriorityTokens = lazySubscribeMessage('pri(tokens.subscribePriority)', null, updatePriorityTokens, updatePriorityTokens); +/* Priority tokens */ diff --git a/packages/extension-koni-ui/src/utils/sort/token.ts b/packages/extension-koni-ui/src/utils/sort/token.ts index 1d84d4b9ea..9cc296a091 100644 --- a/packages/extension-koni-ui/src/utils/sort/token.ts +++ b/packages/extension-koni-ui/src/utils/sort/token.ts @@ -1,17 +1,17 @@ // Copyright 2019-2022 @polkadot/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { PrioritizedTokenList } from '@subwallet/extension-base/background/KoniTypes'; +import { TokenPriorityDetails } from '@subwallet/extension-base/background/KoniTypes'; import { BalanceValueInfo } from '@subwallet/extension-koni-ui/types'; -export interface TokenAttributes { +export interface SortableTokenItem { slug: string, symbol: string, total?: BalanceValueInfo, multiChainAsset?: string | null } -export const sortTokenByValue = (a: TokenAttributes, b: TokenAttributes): number => { +export const sortTokenByValue = (a: SortableTokenItem, b: SortableTokenItem): number => { if (a.total && b.total) { const convertValue = b.total.convertedValue.minus(a.total.convertedValue).toNumber(); @@ -38,7 +38,7 @@ export const sortTokenAlphabetically = (a: string, b: string): number => { } }; -export const sortByTokenPopularity = (a: string, b: string, aIsPrioritizedToken: boolean, bIsPrioritizedToken: boolean, aPriority: number, bPriority: number): number => { +export const sortTokenByPriority = (a: string, b: string, aIsPrioritizedToken: boolean, bIsPrioritizedToken: boolean, aPriority: number, bPriority: number): number => { if (aIsPrioritizedToken && !bIsPrioritizedToken) { return -1; } else if (!aIsPrioritizedToken && bIsPrioritizedToken) { @@ -56,19 +56,12 @@ export const sortByTokenPopularity = (a: string, b: string, aIsPrioritizedToken: } }; -export function sortToken (tokenGroupSlug: TokenAttributes[], popularTokens: Record) { - return tokenGroupSlug.sort((a, b) => { - const aBelongtoPrioritizedGroup = a.multiChainAsset ? Object.keys(popularTokens).includes(a.multiChainAsset) : false; - const bBelongtoPrioritizedGroup = b.multiChainAsset ? Object.keys(popularTokens).includes(b.multiChainAsset) : false; +export function sortTokensByStandard (targetTokens: SortableTokenItem[], priorityTokenGroups: Record) { + const priorityTokenGroupKeys = Object.keys(priorityTokenGroups); - const aIsPrioritizedToken = (aBelongtoPrioritizedGroup && a.multiChainAsset && Object.keys(popularTokens[a.multiChainAsset].tokens).includes(a.slug)) || Object.keys(popularTokens).includes(a.slug); - const bIsPrioritizedToken = (bBelongtoPrioritizedGroup && b.multiChainAsset && Object.keys(popularTokens[b.multiChainAsset].tokens).includes(b.slug)) || Object.keys(popularTokens).includes(b.slug); - - const aHasBalance = (a.total && a.total.convertedValue.toNumber() !== 0) || (a.total && a.total.value.toNumber() !== 0); - const bHasBalance = (b.total && b.total.convertedValue.toNumber() !== 0) || (b.total && b.total.value.toNumber() !== 0); - - const aPriority = a.multiChainAsset ? aIsPrioritizedToken ? (popularTokens[a.multiChainAsset].tokens)[a.slug] : 0 : aIsPrioritizedToken ? popularTokens[a.slug].priority : 0; - const bPriority = b.multiChainAsset ? bIsPrioritizedToken ? (popularTokens[b.multiChainAsset].tokens)[b.slug] : 0 : bIsPrioritizedToken ? popularTokens[b.slug].priority : 0; + targetTokens.sort((a, b) => { + const aHasBalance = (a.total && (a.total.convertedValue.toNumber() !== 0 || a.total.value.toNumber() !== 0)); + const bHasBalance = (b.total && (b.total.convertedValue.toNumber() !== 0 || b.total.value.toNumber() !== 0)); if (aHasBalance && bHasBalance) { return sortTokenByValue(a, b); @@ -76,8 +69,23 @@ export function sortToken (tokenGroupSlug: TokenAttributes[], popularTokens: Rec return -1; } else if (!aHasBalance && bHasBalance) { return 1; - } else { - return sortByTokenPopularity(a.symbol, b.symbol, aIsPrioritizedToken, bIsPrioritizedToken, aPriority, bPriority); } + + const aMultiChainAsset = a.multiChainAsset; + const bMultiChainAsset = b.multiChainAsset; + + const aSlug = a.slug; + const bSlug = b.slug; + + const aBelongToPrioritizedGroup = aMultiChainAsset ? priorityTokenGroupKeys.includes(aMultiChainAsset) : false; + const bBelongToPrioritizedGroup = bMultiChainAsset ? priorityTokenGroupKeys.includes(bMultiChainAsset) : false; + + const aIsPrioritizedToken = !!(aBelongToPrioritizedGroup && aMultiChainAsset && priorityTokenGroups[aMultiChainAsset].priorityTokens[aSlug]) || priorityTokenGroupKeys.includes(aSlug); + const bIsPrioritizedToken = !!(bBelongToPrioritizedGroup && bMultiChainAsset && priorityTokenGroups[bMultiChainAsset].priorityTokens[bSlug]) || priorityTokenGroupKeys.includes(bSlug); + + const aPriority = aMultiChainAsset ? (aIsPrioritizedToken ? priorityTokenGroups[aMultiChainAsset].priorityTokens[aSlug] : 0) : (aIsPrioritizedToken ? priorityTokenGroups[aSlug].groupPriority : 0); + const bPriority = bMultiChainAsset ? (bIsPrioritizedToken ? priorityTokenGroups[bMultiChainAsset].priorityTokens[bSlug] : 0) : (bIsPrioritizedToken ? priorityTokenGroups[bSlug].groupPriority : 0); + + return sortTokenByPriority(a.symbol, b.symbol, aIsPrioritizedToken, bIsPrioritizedToken, aPriority, bPriority); }); } From 82c50dacc7bb8b9807b0ca474612e4dd89580958 Mon Sep 17 00:00:00 2001 From: PDTnhah Date: Thu, 16 Jan 2025 17:35:56 +0700 Subject: [PATCH 11/14] [Issue-3920] Refactor code for sorting token --- .../Modal/ReceiveModalNew/parts/TokenSelector.tsx | 2 +- packages/extension-koni-ui/src/utils/sort/token.ts | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx b/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx index 0b97ac00a0..0e5392f6ab 100644 --- a/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx +++ b/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx @@ -43,7 +43,7 @@ function Component ({ className = '', items, onCancel, onSelectItem }: Props): R }); if (!currentSearchText) { - sortTokensByStandard(filteredList, priorityTokens); + sortTokensByStandard(filteredList, priorityTokens, true); return filteredList; } diff --git a/packages/extension-koni-ui/src/utils/sort/token.ts b/packages/extension-koni-ui/src/utils/sort/token.ts index 9cc296a091..7099c9d832 100644 --- a/packages/extension-koni-ui/src/utils/sort/token.ts +++ b/packages/extension-koni-ui/src/utils/sort/token.ts @@ -56,7 +56,7 @@ export const sortTokenByPriority = (a: string, b: string, aIsPrioritizedToken: b } }; -export function sortTokensByStandard (targetTokens: SortableTokenItem[], priorityTokenGroups: Record) { +export function sortTokensByStandard (targetTokens: SortableTokenItem[], priorityTokenGroups: Record, useTokenPriority?: boolean) { const priorityTokenGroupKeys = Object.keys(priorityTokenGroups); targetTokens.sort((a, b) => { @@ -83,8 +83,16 @@ export function sortTokensByStandard (targetTokens: SortableTokenItem[], priorit const aIsPrioritizedToken = !!(aBelongToPrioritizedGroup && aMultiChainAsset && priorityTokenGroups[aMultiChainAsset].priorityTokens[aSlug]) || priorityTokenGroupKeys.includes(aSlug); const bIsPrioritizedToken = !!(bBelongToPrioritizedGroup && bMultiChainAsset && priorityTokenGroups[bMultiChainAsset].priorityTokens[bSlug]) || priorityTokenGroupKeys.includes(bSlug); - const aPriority = aMultiChainAsset ? (aIsPrioritizedToken ? priorityTokenGroups[aMultiChainAsset].priorityTokens[aSlug] : 0) : (aIsPrioritizedToken ? priorityTokenGroups[aSlug].groupPriority : 0); - const bPriority = bMultiChainAsset ? (bIsPrioritizedToken ? priorityTokenGroups[bMultiChainAsset].priorityTokens[bSlug] : 0) : (bIsPrioritizedToken ? priorityTokenGroups[bSlug].groupPriority : 0); + let aPriority: number; + let bPriority: number; + + if (useTokenPriority) { + aPriority = aMultiChainAsset ? (aIsPrioritizedToken ? priorityTokenGroups[aMultiChainAsset].priorityTokens[aSlug] : 0) : (aIsPrioritizedToken ? priorityTokenGroups[aSlug].priorityTokens[aSlug] : 0); + bPriority = bMultiChainAsset ? (bIsPrioritizedToken ? priorityTokenGroups[bMultiChainAsset].priorityTokens[bSlug] : 0) : (bIsPrioritizedToken ? priorityTokenGroups[bSlug].priorityTokens[bSlug] : 0); + } else { + aPriority = aMultiChainAsset ? (aIsPrioritizedToken ? priorityTokenGroups[aMultiChainAsset].groupPriority : 0) : (aIsPrioritizedToken ? priorityTokenGroups[aSlug].groupPriority : 0); + bPriority = bMultiChainAsset ? (bIsPrioritizedToken ? priorityTokenGroups[bMultiChainAsset].groupPriority : 0) : (bIsPrioritizedToken ? priorityTokenGroups[bSlug].groupPriority : 0); + } return sortTokenByPriority(a.symbol, b.symbol, aIsPrioritizedToken, bIsPrioritizedToken, aPriority, bPriority); }); From acb25fc18af0ec3a865d23a55a92f8e369974900 Mon Sep 17 00:00:00 2001 From: PDTnhah Date: Thu, 16 Jan 2025 17:43:22 +0700 Subject: [PATCH 12/14] [Issue-3920] fix lint --- packages/extension-base/src/services/chain-service/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index 449f3b115a..5df92ce3db 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -3,7 +3,7 @@ import { AssetLogoMap, AssetRefMap, ChainAssetMap, ChainInfoMap, ChainLogoMap, MultiChainAssetMap } from '@subwallet/chain-list'; import { _AssetRef, _AssetRefPath, _AssetType, _ChainAsset, _ChainInfo, _ChainStatus, _EvmInfo, _MultiChainAsset, _SubstrateChainType, _SubstrateInfo, _TonInfo } from '@subwallet/chain-list/types'; -import { AssetSetting, TokenPriorityDetails, MetadataItem, ValidateNetworkResponse } from '@subwallet/extension-base/background/KoniTypes'; +import { AssetSetting, MetadataItem, TokenPriorityDetails, ValidateNetworkResponse } from '@subwallet/extension-base/background/KoniTypes'; import { _DEFAULT_ACTIVE_CHAINS, _ZK_ASSET_PREFIX, LATEST_CHAIN_DATA_FETCHING_INTERVAL } from '@subwallet/extension-base/services/chain-service/constants'; import { EvmChainHandler } from '@subwallet/extension-base/services/chain-service/handler/EvmChainHandler'; import { MantaPrivateHandler } from '@subwallet/extension-base/services/chain-service/handler/manta/MantaPrivateHandler'; From 28e5e0b5c3c9d4e99a05928010d76450e5694e12 Mon Sep 17 00:00:00 2001 From: PDTnhah Date: Fri, 17 Jan 2025 10:26:16 +0700 Subject: [PATCH 13/14] [Issue-3920] Refactor code for sorting token --- .../src/background/KoniTypes.ts | 6 +-- .../src/koni/background/handlers/Extension.ts | 2 +- .../src/services/chain-service/index.ts | 6 +-- .../src/Popup/Home/Tokens/DetailList.tsx | 9 +++-- .../src/Popup/Home/Tokens/index.tsx | 2 +- .../ReceiveModalNew/parts/TokenSelector.tsx | 2 +- .../src/stores/feature/common/ChainStore.ts | 4 +- .../extension-koni-ui/src/stores/types.ts | 2 +- .../src/stores/utils/index.ts | 2 +- .../extension-koni-ui/src/utils/sort/token.ts | 40 +++++++++---------- 10 files changed, 37 insertions(+), 38 deletions(-) diff --git a/packages/extension-base/src/background/KoniTypes.ts b/packages/extension-base/src/background/KoniTypes.ts index 252d70e58e..20a131b6b5 100644 --- a/packages/extension-base/src/background/KoniTypes.ts +++ b/packages/extension-base/src/background/KoniTypes.ts @@ -1723,8 +1723,8 @@ export interface RequestAddPspToken { // Popular tokens export interface TokenPriorityDetails { - priorityTokens: Record, - groupPriority: number + tokenGroup: Record; + token: Record } /// WalletConnect @@ -2318,7 +2318,7 @@ export interface KoniRequestSignatures { /* Ledger */ /* Popular tokens */ - 'pri(tokens.subscribePriority)': [null, Record, Record]; + 'pri(tokens.subscribePriority)': [null, TokenPriorityDetails, TokenPriorityDetails]; /* Popular tokens */ } diff --git a/packages/extension-base/src/koni/background/handlers/Extension.ts b/packages/extension-base/src/koni/background/handlers/Extension.ts index 78583a6aba..51e5816600 100644 --- a/packages/extension-base/src/koni/background/handlers/Extension.ts +++ b/packages/extension-base/src/koni/background/handlers/Extension.ts @@ -3899,7 +3899,7 @@ export default class KoniExtension { /* Popular tokens */ - private subscribePriorityTokens (id: string, port: chrome.runtime.Port): Record { + private subscribePriorityTokens (id: string, port: chrome.runtime.Port): TokenPriorityDetails { const cb = createSubscription<'pri(tokens.subscribePriority)'>(id, port); const subscription = this.#koniState.chainService.observable.priorityTokens.subscribe(cb); diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index 5df92ce3db..dfb9715853 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -92,7 +92,7 @@ export class ChainService { private assetLogoMapSubject = new BehaviorSubject>(AssetLogoMap); private chainLogoMapSubject = new BehaviorSubject>(ChainLogoMap); private ledgerGenericAllowChainsSubject = new BehaviorSubject([]); - private priorityTokensSubject = new BehaviorSubject>({}); + private priorityTokensSubject = new BehaviorSubject({} as TokenPriorityDetails); // Todo: Update to new store indexed DB private store: AssetSettingStore = new AssetSettingStore(); @@ -776,7 +776,7 @@ export class ChainService { this.logger.log('Finished updating latest ledger generic allow chains'); } - handleLatestPriorityTokens (latestPriorityTokens: Record) { + handleLatestPriorityTokens (latestPriorityTokens: TokenPriorityDetails) { this.priorityTokensSubject.next(latestPriorityTokens); this.logger.log('Finished updating latest popular tokens'); } @@ -1109,7 +1109,7 @@ export class ChainService { } private async fetchLatestPriorityTokens () { - return await fetchStaticData>('chain-assets/priority-tokens') || []; + return await fetchStaticData('chain-assets/priority-tokens') || []; } private async initChains () { diff --git a/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailList.tsx b/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailList.tsx index d7a9ef6a1b..455af0da23 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailList.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailList.tsx @@ -18,7 +18,7 @@ import { DetailUpperBlock } from '@subwallet/extension-koni-ui/Popup/Home/Tokens import { RootState } from '@subwallet/extension-koni-ui/stores'; import { AccountAddressItemType, ThemeProps } from '@subwallet/extension-koni-ui/types'; import { TokenBalanceItemType } from '@subwallet/extension-koni-ui/types/balance'; -import { getTransactionFromAccountProxyValue, isAccountAll, sortTokenByValue } from '@subwallet/extension-koni-ui/utils'; +import { getTransactionFromAccountProxyValue, isAccountAll, sortTokensByStandard } from '@subwallet/extension-koni-ui/utils'; import { isTonAddress } from '@subwallet/keyring'; import { KeypairType } from '@subwallet/keyring/types'; import { ModalContext } from '@subwallet/react-ui'; @@ -72,6 +72,7 @@ function Component (): React.ReactElement { const isAllAccount = useSelector((state: RootState) => state.accountState.isAllAccount); const { tokens } = useSelector((state: RootState) => state.buyService); const swapPairs = useSelector((state) => state.swap.swapPairs); + const priorityTokens = useSelector((root: RootState) => root.chainStore.priorityTokens); const [, setStorage] = useLocalStorage(TRANSFER_TRANSACTION, DEFAULT_TRANSFER_PARAMS); const [, setSwapStorage] = useLocalStorage(SWAP_TRANSACTION, DEFAULT_SWAP_PARAMS); const { banners, dismissBanner, onClickBanner } = useGetBannerByScreen('token_detail', tokenGroupSlug); @@ -190,7 +191,9 @@ function Component (): React.ReactElement { } }); - return items.sort(sortTokenByValue); + sortTokensByStandard(items, priorityTokens, false); + + return items; } if (tokenBalanceMap[tokenGroupSlug]) { @@ -199,7 +202,7 @@ function Component (): React.ReactElement { } return [] as TokenBalanceItemType[]; - }, [tokenGroupSlug, tokenGroupMap, tokenBalanceMap]); + }, [tokenGroupSlug, tokenGroupMap, tokenBalanceMap, priorityTokens]); const isHaveOnlyTonSoloAcc = useMemo(() => { const checkValidAcc = (currentAcc: AccountProxy) => { diff --git a/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx b/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx index 6b926ff38e..018a2d3f2b 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx @@ -304,7 +304,7 @@ const Component = (): React.ReactElement => { } }); - sortTokensByStandard(result, priorityTokens); + sortTokensByStandard(result, priorityTokens, true); return result; }, [sortedTokenGroups, debouncedTokenGroupBalanceMap, priorityTokens]); diff --git a/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx b/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx index 0e5392f6ab..e1dc4f9996 100644 --- a/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx +++ b/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx @@ -43,7 +43,7 @@ function Component ({ className = '', items, onCancel, onSelectItem }: Props): R }); if (!currentSearchText) { - sortTokensByStandard(filteredList, priorityTokens, true); + sortTokensByStandard(filteredList, priorityTokens, false); return filteredList; } diff --git a/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts b/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts index 1f96ffa3db..78c601539d 100644 --- a/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts +++ b/packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts @@ -12,7 +12,7 @@ const initialState: ChainStore = { chainStateMap: {}, chainStatusMap: {}, ledgerGenericAllowNetworks: [], - priorityTokens: {}, + priorityTokens: { tokenGroup: {}, token: {} }, reduxStatus: ReduxStatus.INIT }; @@ -56,7 +56,7 @@ const chainStoreSlice = createSlice({ reduxStatus: ReduxStatus.READY }; }, - updatePriorityTokens (state, action: PayloadAction>) { + updatePriorityTokens (state, action: PayloadAction) { const { payload } = action; return { diff --git a/packages/extension-koni-ui/src/stores/types.ts b/packages/extension-koni-ui/src/stores/types.ts index c02af1a54d..937af918b7 100644 --- a/packages/extension-koni-ui/src/stores/types.ts +++ b/packages/extension-koni-ui/src/stores/types.ts @@ -126,7 +126,7 @@ export interface ChainStore extends BaseReduxStore { chainStateMap: Record chainStatusMap: Record ledgerGenericAllowNetworks: string[]; - priorityTokens: Record; + priorityTokens: TokenPriorityDetails; } export interface BalanceStore extends BaseReduxStore { diff --git a/packages/extension-koni-ui/src/stores/utils/index.ts b/packages/extension-koni-ui/src/stores/utils/index.ts index 1a7d27f62c..9fdade6df0 100644 --- a/packages/extension-koni-ui/src/stores/utils/index.ts +++ b/packages/extension-koni-ui/src/stores/utils/index.ts @@ -510,7 +510,7 @@ export const subscribeUnreadNotificationCount = lazySubscribeMessage('pri(inappN /* Notification service */ /* Priority tokens */ -export const updatePriorityTokens = (data: Record) => { +export const updatePriorityTokens = (data: TokenPriorityDetails) => { store.dispatch({ type: 'chainStore/updatePriorityTokens', payload: data }); }; diff --git a/packages/extension-koni-ui/src/utils/sort/token.ts b/packages/extension-koni-ui/src/utils/sort/token.ts index 7099c9d832..5f5b8709e2 100644 --- a/packages/extension-koni-ui/src/utils/sort/token.ts +++ b/packages/extension-koni-ui/src/utils/sort/token.ts @@ -8,7 +8,6 @@ export interface SortableTokenItem { slug: string, symbol: string, total?: BalanceValueInfo, - multiChainAsset?: string | null } export const sortTokenByValue = (a: SortableTokenItem, b: SortableTokenItem): number => { @@ -56,10 +55,14 @@ export const sortTokenByPriority = (a: string, b: string, aIsPrioritizedToken: b } }; -export function sortTokensByStandard (targetTokens: SortableTokenItem[], priorityTokenGroups: Record, useTokenPriority?: boolean) { - const priorityTokenGroupKeys = Object.keys(priorityTokenGroups); +export function sortTokensByStandard (targetTokens: SortableTokenItem[], priorityTokenGroups: TokenPriorityDetails, isTokenGroup: boolean) { + const priorityTokenGroupKeys = Object.keys(priorityTokenGroups.tokenGroup); + const priorityTokenKeys = Object.keys(priorityTokenGroups.token); targetTokens.sort((a, b) => { + const aSlug = a.slug; + const bSlug = b.slug; + const aHasBalance = (a.total && (a.total.convertedValue.toNumber() !== 0 || a.total.value.toNumber() !== 0)); const bHasBalance = (b.total && (b.total.convertedValue.toNumber() !== 0 || b.total.value.toNumber() !== 0)); @@ -71,29 +74,22 @@ export function sortTokensByStandard (targetTokens: SortableTokenItem[], priorit return 1; } - const aMultiChainAsset = a.multiChainAsset; - const bMultiChainAsset = b.multiChainAsset; + if (isTokenGroup) { + const aBelongToPrioritizedGroup = priorityTokenGroupKeys.includes(aSlug); + const bBelongToPrioritizedGroup = priorityTokenGroupKeys.includes(bSlug); - const aSlug = a.slug; - const bSlug = b.slug; + const aPriority = aBelongToPrioritizedGroup ? priorityTokenGroups.tokenGroup[aSlug] : 0; + const bPriority = bBelongToPrioritizedGroup ? priorityTokenGroups.tokenGroup[bSlug] : 0; - const aBelongToPrioritizedGroup = aMultiChainAsset ? priorityTokenGroupKeys.includes(aMultiChainAsset) : false; - const bBelongToPrioritizedGroup = bMultiChainAsset ? priorityTokenGroupKeys.includes(bMultiChainAsset) : false; - - const aIsPrioritizedToken = !!(aBelongToPrioritizedGroup && aMultiChainAsset && priorityTokenGroups[aMultiChainAsset].priorityTokens[aSlug]) || priorityTokenGroupKeys.includes(aSlug); - const bIsPrioritizedToken = !!(bBelongToPrioritizedGroup && bMultiChainAsset && priorityTokenGroups[bMultiChainAsset].priorityTokens[bSlug]) || priorityTokenGroupKeys.includes(bSlug); + return sortTokenByPriority(a.symbol, b.symbol, aBelongToPrioritizedGroup, bBelongToPrioritizedGroup, aPriority, bPriority); + } else { + const aIsPrioritizedToken = priorityTokenKeys.includes(aSlug); + const bIsPrioritizedToken = priorityTokenKeys.includes(bSlug); - let aPriority: number; - let bPriority: number; + const aPriority = aIsPrioritizedToken ? priorityTokenGroups.token[aSlug] : 0; + const bPriority = bIsPrioritizedToken ? priorityTokenGroups.token[bSlug] : 0; - if (useTokenPriority) { - aPriority = aMultiChainAsset ? (aIsPrioritizedToken ? priorityTokenGroups[aMultiChainAsset].priorityTokens[aSlug] : 0) : (aIsPrioritizedToken ? priorityTokenGroups[aSlug].priorityTokens[aSlug] : 0); - bPriority = bMultiChainAsset ? (bIsPrioritizedToken ? priorityTokenGroups[bMultiChainAsset].priorityTokens[bSlug] : 0) : (bIsPrioritizedToken ? priorityTokenGroups[bSlug].priorityTokens[bSlug] : 0); - } else { - aPriority = aMultiChainAsset ? (aIsPrioritizedToken ? priorityTokenGroups[aMultiChainAsset].groupPriority : 0) : (aIsPrioritizedToken ? priorityTokenGroups[aSlug].groupPriority : 0); - bPriority = bMultiChainAsset ? (bIsPrioritizedToken ? priorityTokenGroups[bMultiChainAsset].groupPriority : 0) : (bIsPrioritizedToken ? priorityTokenGroups[bSlug].groupPriority : 0); + return sortTokenByPriority(a.symbol, b.symbol, aIsPrioritizedToken, bIsPrioritizedToken, aPriority, bPriority); } - - return sortTokenByPriority(a.symbol, b.symbol, aIsPrioritizedToken, bIsPrioritizedToken, aPriority, bPriority); }); } From 75aec1b00c50383fab08e8984973da5063816541 Mon Sep 17 00:00:00 2001 From: PDTnhah Date: Fri, 17 Jan 2025 10:57:10 +0700 Subject: [PATCH 14/14] [Issue-3920] Refactor code for sorting token --- .../extension-base/src/services/chain-service/index.ts | 5 ++++- .../src/Popup/Home/Tokens/DetailList.tsx | 2 +- .../Modal/ReceiveModalNew/parts/TokenSelector.tsx | 2 +- packages/extension-koni-ui/src/utils/sort/token.ts | 8 ++++---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index dfb9715853..4fd95b5048 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -1109,7 +1109,10 @@ export class ChainService { } private async fetchLatestPriorityTokens () { - return await fetchStaticData('chain-assets/priority-tokens') || []; + return await fetchStaticData('chain-assets/priority-tokens') || { + tokenGroup: {}, + token: {} + }; } private async initChains () { diff --git a/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailList.tsx b/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailList.tsx index 455af0da23..8219b65668 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailList.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailList.tsx @@ -191,7 +191,7 @@ function Component (): React.ReactElement { } }); - sortTokensByStandard(items, priorityTokens, false); + sortTokensByStandard(items, priorityTokens); return items; } diff --git a/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx b/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx index e1dc4f9996..0b97ac00a0 100644 --- a/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx +++ b/packages/extension-koni-ui/src/components/Modal/ReceiveModalNew/parts/TokenSelector.tsx @@ -43,7 +43,7 @@ function Component ({ className = '', items, onCancel, onSelectItem }: Props): R }); if (!currentSearchText) { - sortTokensByStandard(filteredList, priorityTokens, false); + sortTokensByStandard(filteredList, priorityTokens); return filteredList; } diff --git a/packages/extension-koni-ui/src/utils/sort/token.ts b/packages/extension-koni-ui/src/utils/sort/token.ts index 5f5b8709e2..624013a4a3 100644 --- a/packages/extension-koni-ui/src/utils/sort/token.ts +++ b/packages/extension-koni-ui/src/utils/sort/token.ts @@ -55,14 +55,11 @@ export const sortTokenByPriority = (a: string, b: string, aIsPrioritizedToken: b } }; -export function sortTokensByStandard (targetTokens: SortableTokenItem[], priorityTokenGroups: TokenPriorityDetails, isTokenGroup: boolean) { +export function sortTokensByStandard (targetTokens: SortableTokenItem[], priorityTokenGroups: TokenPriorityDetails, isTokenGroup = false) { const priorityTokenGroupKeys = Object.keys(priorityTokenGroups.tokenGroup); const priorityTokenKeys = Object.keys(priorityTokenGroups.token); targetTokens.sort((a, b) => { - const aSlug = a.slug; - const bSlug = b.slug; - const aHasBalance = (a.total && (a.total.convertedValue.toNumber() !== 0 || a.total.value.toNumber() !== 0)); const bHasBalance = (b.total && (b.total.convertedValue.toNumber() !== 0 || b.total.value.toNumber() !== 0)); @@ -74,6 +71,9 @@ export function sortTokensByStandard (targetTokens: SortableTokenItem[], priorit return 1; } + const aSlug = a.slug; + const bSlug = b.slug; + if (isTokenGroup) { const aBelongToPrioritizedGroup = priorityTokenGroupKeys.includes(aSlug); const bBelongToPrioritizedGroup = priorityTokenGroupKeys.includes(bSlug);