From 0d1f6e1edfca93d07eebaec9f7c013a872fb83e9 Mon Sep 17 00:00:00 2001 From: Eren Yeager Date: Tue, 21 Nov 2023 07:15:17 +0000 Subject: [PATCH] fix(widget): Showing history for selected blockchain if a blockchain selected from main list --- .../usePrepareBlockchainList.constants.ts | 2 +- .../usePrepareBlockchainList.helpers.ts | 44 ++++++++-- .../usePrepareBlockchainList.mock.ts | 60 ++++++++++++++ .../usePrepareBlockchainList.test.ts | 81 ++++++++++++++++++- .../usePrepareBlockchainList.ts | 17 +++- .../usePrepareBlockchainList.types.ts | 7 +- 6 files changed, 195 insertions(+), 16 deletions(-) diff --git a/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.constants.ts b/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.constants.ts index 6c03e39027..e47e83cc94 100644 --- a/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.constants.ts +++ b/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.constants.ts @@ -1 +1 @@ -export const MOST_USED_BLOCKChAINS = ['ETH', 'COSMOS', 'OSMOSIS']; +export const MOST_USED_BLOCKCHAINS = ['ETH', 'COSMOS', 'OSMOSIS']; diff --git a/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.helpers.ts b/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.helpers.ts index 98472b8a53..6844414a92 100644 --- a/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.helpers.ts +++ b/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.helpers.ts @@ -1,13 +1,16 @@ -import type { PrepareListOptions } from './usePrepareBlockchainList.types'; +import type { + PrepareListOptions, + PrepareOutput, +} from './usePrepareBlockchainList.types'; import type { BlockchainMeta } from 'rango-sdk'; -import { MOST_USED_BLOCKChAINS } from './usePrepareBlockchainList.constants'; +import { MOST_USED_BLOCKCHAINS } from './usePrepareBlockchainList.constants'; export function prepare( blockchains: BlockchainMeta[], preferredBlockchains: string[], options?: PrepareListOptions -) { +): PrepareOutput { /* * TODO: * We copying the `blockchains` which can causes performance penalties but we should because we are mutating the original object. @@ -25,17 +28,37 @@ export function prepare( let preferredBlockchainsWithoutMainList = preferredBlockchains; if (preferredBlockchains.length <= options.limit) { - /* - * For first X (limit) numbers, we need to remove them from preferred if exists. + /** + * + * if we want to show 10 items (aka `options.limit`) + * and have these items as our preferred list: [x,y,z] + * and these as our main list: [A, B, C, D, E, F, G, H, I, J] + * the final list will be like this: [...preferred, ...mainList]. + * + * Since we have a limit (e.g. 10) on our list (preferred + mainList), + * we only should check those items from main list that will be in final list. + * + * finalListWithoutLimit = [x,y,z, A, B, C, D, E, F, G, H, I, J] + * finalListWithLimit = [x,y,z, A, B, C, D, E, F, G] + * + * As you can see, [H, I, J] will not be in our list. + * + * The following code only check preffred blockchain + * shouldn't be in first 7 of 10 items in main list. (Since, the last 3 items will not be in the final list and we should check those.) */ - for (let i = 0; i < options.limit; i++) { + const howManyItemsShouldBeCheckedFromMainList = + options.limit - preferredBlockchains.length; + + for (let i = 0; i <= howManyItemsShouldBeCheckedFromMainList; i++) { const blockchain = list[i]; + preferredBlockchainsWithoutMainList = preferredBlockchainsWithoutMainList.filter((preferredBlockchain) => { return blockchain.name !== preferredBlockchain; }); } } + list.sort( generateSortByPreferredBlockchainsFor(preferredBlockchainsWithoutMainList) ); @@ -57,7 +80,7 @@ export function sortByMostUsedBlockchains( a: BlockchainMeta, b: BlockchainMeta ) { - const mostUsed = MOST_USED_BLOCKChAINS; + const mostUsed = MOST_USED_BLOCKCHAINS; const aIndexInMostUsed = mostUsed.findIndex((token) => token === a.name); const bIndexInMostUsed = mostUsed.findIndex((token) => token === b.name); const aIsMostUsed = aIndexInMostUsed > -1; @@ -106,3 +129,10 @@ export function generateSortByPreferredBlockchainsFor( return 0; }; } + +export function isInVisibleList( + blockchain: string, + prepareOutput: PrepareOutput +): boolean { + return !!prepareOutput.list.find((item) => item.name === blockchain); +} diff --git a/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.mock.ts b/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.mock.ts index 3f2d0baad8..48135df7ef 100644 --- a/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.mock.ts +++ b/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.mock.ts @@ -2,6 +2,66 @@ import type { BlockchainMeta } from 'rango-sdk'; import { TransactionType } from 'rango-sdk'; +export const sampleDefaultBlockchainNames = [ + 'ETH', + 'COSMOS', + 'OSMOSIS', + 'BSC', + 'ARBITRUM', + 'POLYGON', + 'ZKSYNC', + 'STARKNET', + 'OPTIMISM', + 'AVAX_CCHAIN', + 'POLYGONZK', + 'LINEA', + 'TRON', + 'BTC', + 'NEUTRON', + 'NOBLE', + 'SOLANA', + 'CRONOS', + 'BNB', + 'AURORA', + 'MAYA', + 'THOR', + 'BOBA', + 'MOONBEAM', + 'MOONRIVER', + 'OKC', + 'BOBA_AVALANCHE', + 'LTC', + 'BCH', + 'HECO', + 'STARGAZE', + 'CRYPTO_ORG', + 'CHIHUAHUA', + 'BANDCHAIN', + 'COMDEX', + 'REGEN', + 'IRIS', + 'EMONEY', + 'JUNO', + 'STRIDE', + 'MARS', + 'TERRA', + 'BITSONG', + 'AKASH', + 'KI', + 'PERSISTENCE', + 'MEDIBLOC', + 'KUJIRA', + 'SENTINEL', + 'INJECTIVE', + 'SECRET', + 'KONSTELLATION', + 'STARNAME', + 'BITCANNA', + 'UMEE', + 'DESMOS', + 'LUMNETWORK', +]; + export const sampleBlockchains: BlockchainMeta[] = [ { name: 'ETH', diff --git a/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.test.ts b/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.test.ts index 69b0ad3f3c..1ed899412b 100644 --- a/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.test.ts +++ b/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.test.ts @@ -2,7 +2,7 @@ import type { BlockchainMeta } from 'rango-sdk'; import { beforeEach, describe, expect, it } from 'vitest'; -import { MOST_USED_BLOCKChAINS } from './usePrepareBlockchainList.constants'; +import { MOST_USED_BLOCKCHAINS } from './usePrepareBlockchainList.constants'; import { generateSortByPreferredBlockchainsFor, prepare, @@ -20,8 +20,8 @@ describe('usePrepareBlockchainList', () => { it('should sort blockchains by most used ones.', () => { const sortedBlockchainsList = sample.sort(sortByMostUsedBlockchains); - const mostUsedCount = MOST_USED_BLOCKChAINS.length; - const expected = MOST_USED_BLOCKChAINS; + const mostUsedCount = MOST_USED_BLOCKCHAINS.length; + const expected = MOST_USED_BLOCKCHAINS; const received = sortedBlockchainsList .map((blockchain) => blockchain.name) .slice(0, mostUsedCount); @@ -270,4 +270,79 @@ describe('usePrepareBlockchainList', () => { ...received.more.map((blockchain) => blockchain.name), ]); }); + + it.only('Last item of the main list should be moved to front if it selected again.', () => { + const listLimit = 10; + const preferredBlockchains = ['AVAX_CCHAIN', 'BTC']; + const expected = [ + 'AVAX_CCHAIN', + 'BTC', + 'ETH', + 'COSMOS', + 'OSMOSIS', + 'BSC', + 'ARBITRUM', + 'POLYGON', + 'ZKSYNC', + 'STARKNET', + 'OPTIMISM', + 'POLYGONZK', + 'LINEA', + 'TRON', + 'NEUTRON', + 'NOBLE', + 'SOLANA', + 'CRONOS', + 'BNB', + 'AURORA', + 'MAYA', + 'THOR', + 'BOBA', + 'MOONBEAM', + 'MOONRIVER', + 'OKC', + 'BOBA_AVALANCHE', + 'LTC', + 'BCH', + 'HECO', + 'STARGAZE', + 'CRYPTO_ORG', + 'CHIHUAHUA', + 'BANDCHAIN', + 'COMDEX', + 'REGEN', + 'IRIS', + 'EMONEY', + 'JUNO', + 'STRIDE', + 'MARS', + 'TERRA', + 'BITSONG', + 'AKASH', + 'KI', + 'PERSISTENCE', + 'MEDIBLOC', + 'KUJIRA', + 'SENTINEL', + 'INJECTIVE', + 'SECRET', + 'KONSTELLATION', + 'STARNAME', + 'BITCANNA', + 'UMEE', + 'DESMOS', + 'LUMNETWORK', + ]; + + const output = prepare(sample, preferredBlockchains, { + limit: listLimit, + }); + + const received = [ + ...output.list.map((blockchain) => blockchain.name), + ...output.more.map((blockchain) => blockchain.name), + ]; + + expect(expected).toEqual(received); + }); }); diff --git a/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.ts b/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.ts index 0fd4ecbc8c..7c5fb1ecb9 100644 --- a/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.ts +++ b/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.ts @@ -1,6 +1,6 @@ import type { PrepareListOptions, - PrepareListOutput, + UsePrepareList, } from './usePrepareBlockchainList.types'; import type { BlockchainMeta } from 'rango-sdk'; @@ -8,7 +8,7 @@ import { useEffect } from 'react'; import { useSettingsStore } from '../../store/settings'; -import { prepare } from './usePrepareBlockchainList.helpers'; +import { isInVisibleList, prepare } from './usePrepareBlockchainList.helpers'; /** * @@ -19,12 +19,21 @@ import { prepare } from './usePrepareBlockchainList.helpers'; export function usePrepareBlockchainList( blockchains: BlockchainMeta[], options?: PrepareListOptions -): PrepareListOutput { +): UsePrepareList { const { preferredBlockchains, addPreferredBlockchain } = useSettingsStore(); useEffect(() => { if (options?.selected) { - addPreferredBlockchain(options?.selected); + const output = prepare(blockchains, preferredBlockchains, options); + + /** + * We only add a new blockchain to preferred when it's not in the main list + * In this way we can guarantee we will be able to regenerate the same list always. + * And also it helps us to avoid jumping for the last item of the main list (e.g. tenth item of our list). + */ + if (!isInVisibleList(options.selected, output)) { + addPreferredBlockchain(options?.selected); + } } }, [options?.selected]); diff --git a/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.types.ts b/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.types.ts index c30bf0aa63..c4469ab52b 100644 --- a/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.types.ts +++ b/widget/embedded/src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.types.ts @@ -5,8 +5,13 @@ export interface PrepareListOptions { selected?: string; } -export interface PrepareListOutput { +export interface PrepareOutput { list: BlockchainMeta[]; more: BlockchainMeta[]; +} + +export interface UsePrepareList { + list: PrepareOutput['list']; + more: PrepareOutput['more']; history: string[]; }