diff --git a/src/frontend/src/lib/derived/tokens.derived.ts b/src/frontend/src/lib/derived/tokens.derived.ts index cedb860e53..091ffd5d33 100644 --- a/src/frontend/src/lib/derived/tokens.derived.ts +++ b/src/frontend/src/lib/derived/tokens.derived.ts @@ -2,6 +2,7 @@ import { enabledBitcoinTokens } from '$btc/derived/tokens.derived'; import { BTC_MAINNET_TOKEN } from '$env/tokens/tokens.btc.env'; import { ETHEREUM_TOKEN } from '$env/tokens/tokens.eth.env'; import { ICP_TOKEN } from '$env/tokens/tokens.icp.env'; +import { SOLANA_TOKEN } from '$env/tokens/tokens.sol.env'; import { erc20Tokens } from '$eth/derived/erc20.derived'; import { enabledEthereumTokens } from '$eth/derived/tokens.derived'; import type { Erc20Token } from '$eth/types/erc20'; @@ -15,16 +16,24 @@ import { filterEnabledTokens, sumMainnetTokensUsdBalancesPerNetwork } from '$lib/utils/tokens.utils'; +import { enabledSolanaTokens } from '$sol/derived/tokens.derived'; import { derived, type Readable } from 'svelte/store'; export const tokens: Readable = derived( - [erc20Tokens, sortedIcrcTokens, enabledEthereumTokens, enabledBitcoinTokens], - ([$erc20Tokens, $icrcTokens, $enabledEthereumTokens, $enabledBitcoinTokens]) => [ + [erc20Tokens, sortedIcrcTokens, enabledEthereumTokens, enabledBitcoinTokens, enabledSolanaTokens], + ([ + $erc20Tokens, + $icrcTokens, + $enabledEthereumTokens, + $enabledBitcoinTokens, + $enabledSolanaTokens + ]) => [ ICP_TOKEN, ...$enabledBitcoinTokens, ...$enabledEthereumTokens, ...$erc20Tokens, - ...$icrcTokens + ...$icrcTokens, + ...$enabledSolanaTokens ] ); @@ -34,6 +43,7 @@ export const tokensToPin: Readable = derived( BTC_MAINNET_TOKEN, ETHEREUM_TOKEN, ICP_TOKEN, + SOLANA_TOKEN, ...$icrcChainFusionDefaultTokens ] ); diff --git a/src/frontend/src/sol/derived/tokens.derived.ts b/src/frontend/src/sol/derived/tokens.derived.ts new file mode 100644 index 0000000000..e230904a57 --- /dev/null +++ b/src/frontend/src/sol/derived/tokens.derived.ts @@ -0,0 +1,22 @@ +import { SOLANA_NETWORK_ENABLED } from '$env/networks/networks.sol.env'; +import { + SOLANA_DEVNET_TOKEN, + SOLANA_LOCAL_TOKEN, + SOLANA_TESTNET_TOKEN, + SOLANA_TOKEN +} from '$env/tokens/tokens.sol.env'; +import { LOCAL } from '$lib/constants/app.constants'; +import { testnets } from '$lib/derived/testnets.derived'; +import type { Token } from '$lib/types/token'; +import { derived, type Readable } from 'svelte/store'; + +export const enabledSolanaTokens: Readable = derived([testnets], ([$testnets]) => + SOLANA_NETWORK_ENABLED + ? [ + SOLANA_TOKEN, + ...($testnets + ? [SOLANA_TESTNET_TOKEN, SOLANA_DEVNET_TOKEN, ...(LOCAL ? [SOLANA_LOCAL_TOKEN] : [])] + : []) + ] + : [] +); diff --git a/src/frontend/src/tests/lib/derived/tokens.derived.spec.ts b/src/frontend/src/tests/lib/derived/tokens.derived.spec.ts index f6287c763c..71bfc906de 100644 --- a/src/frontend/src/tests/lib/derived/tokens.derived.spec.ts +++ b/src/frontend/src/tests/lib/derived/tokens.derived.spec.ts @@ -1,8 +1,14 @@ import * as btcEnv from '$env/networks/networks.btc.env'; import * as ethEnv from '$env/networks/networks.eth.env'; +import * as solEnv from '$env/networks/networks.sol.env'; import { BTC_MAINNET_TOKEN, BTC_TESTNET_TOKEN } from '$env/tokens/tokens.btc.env'; import { ETHEREUM_TOKEN, SEPOLIA_TOKEN } from '$env/tokens/tokens.eth.env'; import { ICP_TOKEN } from '$env/tokens/tokens.icp.env'; +import { + SOLANA_DEVNET_TOKEN, + SOLANA_TESTNET_TOKEN, + SOLANA_TOKEN +} from '$env/tokens/tokens.sol.env'; import { erc20DefaultTokensStore } from '$eth/stores/erc20-default-tokens.store'; import { erc20UserTokensStore } from '$eth/stores/erc20-user-tokens.store'; import type { Erc20Token } from '$eth/types/erc20'; @@ -63,6 +69,8 @@ describe('tokens.derived', () => { vi.spyOn(ethEnv, 'ETH_MAINNET_ENABLED', 'get').mockImplementation(() => true); vi.spyOn(appContants, 'LOCAL', 'get').mockImplementation(() => false); + + vi.spyOn(solEnv, 'SOLANA_NETWORK_ENABLED', 'get').mockImplementation(() => true); }); it('should return all the non-testnet tokens by default', () => { @@ -80,19 +88,20 @@ describe('tokens.derived', () => { { ...mockErc20DefaultToken, enabled: false, version: undefined }, mockEr20UserToken, { ...mockIcrcDefaultToken, enabled: false, version: undefined, id: result[5].id }, - { ...mockIcrcCustomToken, id: result[6].id } + { ...mockIcrcCustomToken, id: result[6].id }, + SOLANA_TOKEN ]); }); it('should return only native tokens when the other token lists are empty', () => { - expect(get(tokens)).toEqual([ICP_TOKEN, BTC_MAINNET_TOKEN, ETHEREUM_TOKEN]); + expect(get(tokens)).toEqual([ICP_TOKEN, BTC_MAINNET_TOKEN, ETHEREUM_TOKEN, SOLANA_TOKEN]); }); - it('should return only ICP when all the token lists are empty (including native tokens)', () => { + it('should return only ICP and SOL when all the token lists are empty (including native tokens)', () => { vi.spyOn(btcEnv, 'BTC_MAINNET_ENABLED', 'get').mockImplementation(() => false); vi.spyOn(ethEnv, 'ETH_MAINNET_ENABLED', 'get').mockImplementation(() => false); - expect(get(tokens)).toEqual([ICP_TOKEN]); + expect(get(tokens)).toEqual([ICP_TOKEN, SOLANA_TOKEN]); }); it('should return all the tokens when testnets are enabled', () => { @@ -103,7 +112,10 @@ describe('tokens.derived', () => { BTC_MAINNET_TOKEN, BTC_TESTNET_TOKEN, ETHEREUM_TOKEN, - SEPOLIA_TOKEN + SEPOLIA_TOKEN, + SOLANA_TOKEN, + SOLANA_TESTNET_TOKEN, + SOLANA_DEVNET_TOKEN ]); }); }); diff --git a/src/frontend/src/tests/sol/derived/tokens.derived.spec.ts b/src/frontend/src/tests/sol/derived/tokens.derived.spec.ts new file mode 100644 index 0000000000..fa75ba0e11 --- /dev/null +++ b/src/frontend/src/tests/sol/derived/tokens.derived.spec.ts @@ -0,0 +1,55 @@ +import * as solEnv from '$env/networks/networks.sol.env'; +import { + SOLANA_DEVNET_TOKEN, + SOLANA_LOCAL_TOKEN, + SOLANA_TESTNET_TOKEN, + SOLANA_TOKEN +} from '$env/tokens/tokens.sol.env'; +import * as appContants from '$lib/constants/app.constants'; +import { testnetsStore } from '$lib/stores/settings.store'; +import { enabledSolanaTokens } from '$sol/derived/tokens.derived'; +import { get } from 'svelte/store'; + +describe('tokens.derived', () => { + describe('enabledSolanaTokens', () => { + beforeEach(() => { + vi.resetAllMocks(); + + testnetsStore.reset({ key: 'testnets' }); + + vi.spyOn(solEnv, 'SOLANA_NETWORK_ENABLED', 'get').mockImplementation(() => true); + }); + + it('should return only mainnet token by default', () => { + expect(get(enabledSolanaTokens)).toEqual([SOLANA_TOKEN]); + }); + + it('should return emtpy array if feature flag false', () => { + vi.spyOn(solEnv, 'SOLANA_NETWORK_ENABLED', 'get').mockImplementation(() => false); + expect(get(enabledSolanaTokens)).toEqual([]); + }); + + it('should return testnet tokens when they are enabled', () => { + testnetsStore.set({ key: 'testnets', value: { enabled: true } }); + vi.spyOn(appContants, 'LOCAL', 'get').mockImplementationOnce(() => false); + + expect(get(enabledSolanaTokens)).toEqual([ + SOLANA_TOKEN, + SOLANA_TESTNET_TOKEN, + SOLANA_DEVNET_TOKEN + ]); + }); + + it('should return localnet token when in local env', () => { + testnetsStore.set({ key: 'testnets', value: { enabled: true } }); + vi.spyOn(appContants, 'LOCAL', 'get').mockImplementationOnce(() => true); + + expect(get(enabledSolanaTokens)).toEqual([ + SOLANA_TOKEN, + SOLANA_TESTNET_TOKEN, + SOLANA_DEVNET_TOKEN, + SOLANA_LOCAL_TOKEN + ]); + }); + }); +});