Skip to content

Commit

Permalink
feat(frontend): include Solana in the tokens derived (#3955)
Browse files Browse the repository at this point in the history
# Motivation

We include the Solana tokens in the list of the derived tokens, pinning
it among the native ones.

# Changes

- Create derived tokens list store for Solana.
- Add the new store to the current list of tokens.
- Include Solana mainnet token among the pinned ones.

# Tests

Created some tests. But here there is the result.

![Screenshot 2024-12-11 at 20 53
52](https://github.com/user-attachments/assets/b69940dc-7446-429f-8208-f7f5cd933db9)
![Screenshot 2024-12-11 at 20 54
10](https://github.com/user-attachments/assets/18716702-45e2-44c0-8e03-4e4b16879c89)
![Screenshot 2024-12-11 at 20 54
18](https://github.com/user-attachments/assets/5fbd518c-2aa6-4324-ae01-faae60ec5ba3)

---------

Co-authored-by: Robert Schlittler <robert.schlittler@inacta.ch>
  • Loading branch information
AntonioVentilii and loki344 authored Dec 16, 2024
1 parent f5bd040 commit 54a396a
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 8 deletions.
16 changes: 13 additions & 3 deletions src/frontend/src/lib/derived/tokens.derived.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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<Token[]> = 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
]
);

Expand All @@ -34,6 +43,7 @@ export const tokensToPin: Readable<TokenToPin[]> = derived(
BTC_MAINNET_TOKEN,
ETHEREUM_TOKEN,
ICP_TOKEN,
SOLANA_TOKEN,
...$icrcChainFusionDefaultTokens
]
);
Expand Down
22 changes: 22 additions & 0 deletions src/frontend/src/sol/derived/tokens.derived.ts
Original file line number Diff line number Diff line change
@@ -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<Token[]> = derived([testnets], ([$testnets]) =>
SOLANA_NETWORK_ENABLED
? [
SOLANA_TOKEN,
...($testnets
? [SOLANA_TESTNET_TOKEN, SOLANA_DEVNET_TOKEN, ...(LOCAL ? [SOLANA_LOCAL_TOKEN] : [])]
: [])
]
: []
);
22 changes: 17 additions & 5 deletions src/frontend/src/tests/lib/derived/tokens.derived.spec.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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', () => {
Expand All @@ -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', () => {
Expand All @@ -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
]);
});
});
Expand Down
55 changes: 55 additions & 0 deletions src/frontend/src/tests/sol/derived/tokens.derived.spec.ts
Original file line number Diff line number Diff line change
@@ -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
]);
});
});
});

0 comments on commit 54a396a

Please sign in to comment.