Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Issue-3920] Show well-known tokens on top #3934

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/extension-base/src/background/KoniTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,13 +232,13 @@
externalUrl?: string;
rarity?: string;
description?: string;
properties?: Record<any, any> | null;

Check warning on line 235 in packages/extension-base/src/background/KoniTypes.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unexpected any. Specify a different type

Check warning on line 235 in packages/extension-base/src/background/KoniTypes.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unexpected any. Specify a different type
}

interface NftItemExtraInfo {
type?: _AssetType.ERC721 | _AssetType.PSP34 | RMRK_VER; // for sending
rmrk_ver?: RMRK_VER;
onChainOption?: any; // for sending PSP-34 tokens, should be done better

Check warning on line 241 in packages/extension-base/src/background/KoniTypes.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unexpected any. Specify a different type
assetHubType?: AssetHubNftType // for sending assetHub nft. There're 2 types nft
}

Expand Down Expand Up @@ -543,7 +543,7 @@
[ExtrinsicType.STAKING_COMPOUNDING]: RequestTuringStakeCompound,
[ExtrinsicType.STAKING_CANCEL_COMPOUNDING]: RequestTuringCancelStakeCompound,
[ExtrinsicType.STAKING_CANCEL_UNSTAKE]: RequestStakeCancelWithdrawal,
[ExtrinsicType.STAKING_POOL_WITHDRAW]: any,

Check warning on line 546 in packages/extension-base/src/background/KoniTypes.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unexpected any. Specify a different type

// Yield
[ExtrinsicType.JOIN_YIELD_POOL]: RequestYieldStepSubmit,
Expand Down Expand Up @@ -574,9 +574,9 @@
[ExtrinsicType.CLAIM_BRIDGE]: RequestClaimBridge

[ExtrinsicType.EVM_EXECUTE]: TransactionConfig,
[ExtrinsicType.CROWDLOAN]: any,

Check warning on line 577 in packages/extension-base/src/background/KoniTypes.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unexpected any. Specify a different type
[ExtrinsicType.SWAP]: SwapTxData
[ExtrinsicType.UNKNOWN]: any

Check warning on line 579 in packages/extension-base/src/background/KoniTypes.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unexpected any. Specify a different type
}

export enum ExtrinsicStatus {
Expand Down Expand Up @@ -675,7 +675,7 @@
// : T extends ExtrinsicType.MINT_VDOT
// ? Pick<SubmitBifrostLiquidStaking, 'rewardTokenSlug' | 'estimatedAmountReceived'>
// : undefined;
export interface TransactionHistoryItem<ET extends ExtrinsicType = ExtrinsicType.TRANSFER_BALANCE> {

Check warning on line 678 in packages/extension-base/src/background/KoniTypes.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

'ET' is defined but never used
origin?: 'app' | 'migration' | 'subsquid' | 'subscan', // 'app' or history source
callhash?: string,
signature?: string,
Expand All @@ -700,7 +700,7 @@
tip?: AmountData,
fee?: AmountData,
explorerUrl?: string,
additionalInfo?: any,

Check warning on line 703 in packages/extension-base/src/background/KoniTypes.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unexpected any. Specify a different type
startBlock?: number,
nonce?: number,
addressPrefix?: number
Expand Down Expand Up @@ -931,12 +931,12 @@
recipientAddress: string,

nftItemName?: string, // Use for confirmation view only
params: Record<string, any>,

Check warning on line 934 in packages/extension-base/src/background/KoniTypes.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unexpected any. Specify a different type
nftItem: NftItem
}

export interface EvmNftTransaction extends ValidateTransactionResponse {
tx: Record<string, any> | null;

Check warning on line 939 in packages/extension-base/src/background/KoniTypes.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unexpected any. Specify a different type
}

export interface ValidateNetworkResponse {
Expand Down Expand Up @@ -2294,6 +2294,11 @@

/* Ledger */
'pri(ledger.generic.allow)': [null, string[], string[]];
/* Ledger */

/* Popular tokens */
'pri(popular.tokens)': [null, Record<string, number>, Record<string, number>];
/* Popular tokens */
}

export interface ApplicationMetadataType {
Expand Down
24 changes: 24 additions & 0 deletions packages/extension-base/src/koni/background/handlers/Extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3933,6 +3933,24 @@

/* Ledger */

/* Popular tokens */

private subscribePopularTokens (id: string, port: chrome.runtime.Port): Record<string, number> {
const cb = createSubscription<'pri(popular.tokens)'>(id, port);

const subscription = this.#koniState.chainService.observablePopularTokens.popularTokens.subscribe(cb);

Check failure on line 3941 in packages/extension-base/src/koni/background/handlers/Extension.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unsafe assignment of an `any` value

Check failure on line 3941 in packages/extension-base/src/koni/background/handlers/Extension.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unsafe member access .popularTokens on an `any` value

Check failure on line 3941 in packages/extension-base/src/koni/background/handlers/Extension.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unsafe call of an `any` typed value

this.createUnsubscriptionHandle(id, subscription.unsubscribe);

Check failure on line 3943 in packages/extension-base/src/koni/background/handlers/Extension.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unsafe argument of type `any` assigned to a parameter of type `() => void`

Check failure on line 3943 in packages/extension-base/src/koni/background/handlers/Extension.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unsafe member access .unsubscribe on an `any` value

port.onDisconnect.addListener((): void => {
this.cancelSubscription(id);
});

return this.#koniState.chainService.valuePopularTokens.popularTokens;

Check failure on line 3949 in packages/extension-base/src/koni/background/handlers/Extension.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unsafe return of an `any` typed value

Check failure on line 3949 in packages/extension-base/src/koni/background/handlers/Extension.ts

View workflow job for this annotation

GitHub Actions / Build Development Preview

Unsafe member access .popularTokens on an `any` value
}

/* Popular tokens */

// --------------------------------------------------------------
// eslint-disable-next-line @typescript-eslint/require-await
public async handle<TMessageType extends MessageTypes> (id: string, type: TMessageType, request: RequestTypes[TMessageType], port: chrome.runtime.Port): Promise<ResponseType<TMessageType>> {
Expand Down Expand Up @@ -4543,6 +4561,12 @@
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}`);
Expand Down
24 changes: 24 additions & 0 deletions packages/extension-base/src/services/chain-service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export class ChainService {
private assetLogoMapSubject = new BehaviorSubject<Record<string, string>>(AssetLogoMap);
private chainLogoMapSubject = new BehaviorSubject<Record<string, string>>(ChainLogoMap);
private ledgerGenericAllowChainsSubject = new BehaviorSubject<string[]>([]);
private popularTokensSubject = new BehaviorSubject<Record<string, number>>({});

// Todo: Update to new store indexed DB
private store: AssetSettingStore = new AssetSettingStore();
Expand Down Expand Up @@ -123,20 +124,28 @@ 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();
},
get popularTokens () {
return popularTokens.asObservable();
}
};
}
Expand Down Expand Up @@ -767,6 +776,11 @@ export class ChainService {
this.logger.log('Finished updating latest ledger generic allow chains');
}

handleLatestPopularTokens (latestPopularTokens: Record<string, number>) {
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.
Expand All @@ -786,6 +800,12 @@ export class ChainService {
this.handleLatestLedgerGenericAllowChains(latestledgerGenericAllowChains);
})
.catch(console.error);

this.fetchLatestPopularTokens()
.then((latestPopularTokens) => {
this.handleLatestPopularTokens(latestPopularTokens);
})
.catch(console.error);
}

private async initApis () {
Expand Down Expand Up @@ -1088,6 +1108,10 @@ export class ChainService {
return await fetchStaticData<string[]>('chains/ledger-generic-allow-chains') || [];
}

private async fetchLatestPopularTokens () {
return await fetchStaticData<Record<string, number>>('chain-assets/popular-tokens') || [];
}

private async initChains () {
const storedChainSettings = await this.dbService.getAllChainStore();
const defaultChainInfoMap = filterChainInfoMap(ChainInfoMap, ignoredList);
Expand Down
7 changes: 4 additions & 3 deletions packages/extension-koni-ui/src/Popup/Home/Tokens/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -47,6 +47,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 isZkModeSyncing = useSelector((state: RootState) => state.mantaPay.isSyncing);
const zkModeSyncProgress = useSelector((state: RootState) => state.mantaPay.progress);
Expand Down Expand Up @@ -300,8 +301,8 @@ const Component = (): React.ReactElement => {
}
});

return result.sort(sortTokenByValue);
}, [sortedTokenGroups, tokenGroupBalanceMap]);
return sortToken(result, popularTokens);
}, [sortedTokenGroups, tokenGroupBalanceMap, popularTokens]);

useEffect(() => {
window.addEventListener('resize', handleResize);
Expand Down
3 changes: 2 additions & 1 deletion packages/extension-koni-ui/src/contexts/DataContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 });
Expand Down
10 changes: 10 additions & 0 deletions packages/extension-koni-ui/src/stores/feature/common/ChainStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const initialState: ChainStore = {
chainStateMap: {},
chainStatusMap: {},
ledgerGenericAllowNetworks: [],
popularTokens: {},
reduxStatus: ReduxStatus.INIT
};

Expand Down Expand Up @@ -53,6 +54,15 @@ const chainStoreSlice = createSlice({
ledgerGenericAllowNetworks: payload,
reduxStatus: ReduxStatus.READY
};
},
updatePopularTokens (state, action: PayloadAction<Record<string, number>>) {
const { payload } = action;

return {
...state,
popularTokens: payload,
reduxStatus: ReduxStatus.READY
};
}
}
});
Expand Down
1 change: 1 addition & 0 deletions packages/extension-koni-ui/src/stores/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export interface ChainStore extends BaseReduxStore {
chainStateMap: Record<string, _ChainState>
chainStatusMap: Record<string, _ChainApiStatus>
ledgerGenericAllowNetworks: string[];
popularTokens: Record<string, number>;
}

export interface BalanceStore extends BaseReduxStore {
Expand Down
8 changes: 8 additions & 0 deletions packages/extension-koni-ui/src/stores/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,3 +508,11 @@ export const updateUnreadNotificationCountMap = (data: Record<string, number>) =

export const subscribeUnreadNotificationCount = lazySubscribeMessage('pri(inappNotification.subscribeUnreadNotificationCountMap)', null, updateUnreadNotificationCountMap, updateUnreadNotificationCountMap);
/* Notification service */

/* Popular tokens */
export const updatePopularTokens = (data: Record<string, number>) => {
store.dispatch({ type: 'chainStore/updatePopularTokens', payload: data });
};

export const subscribePopularTokens = lazySubscribeMessage('pri(popular.tokens)', null, updatePopularTokens, updatePopularTokens);
/* Popular tokens */
23 changes: 23 additions & 0 deletions packages/extension-koni-ui/src/utils/sort/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,26 @@ export const sortTokenByValue = (a: TokenBalanceItemType, b: TokenBalanceItemTyp
return b.total.value.minus(a.total.value).toNumber();
}
};

export function sortToken (tokenGroupSlug: TokenBalanceItemType[], popularTokens: Record<string, number>) {
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];

if (aIsPiorityToken && !bIsPiorityToken) {
return -1;
} else if (!aIsPiorityToken && bIsPiorityToken) {
return 1;
} else if (!aIsPiorityToken && !bIsPiorityToken) {
return sortTokenByValue(a, b);
} else {
if (aPiority < bPiority) {
return -1;
} else {
return 1;
}
}
});
}
Loading