Skip to content

Commit

Permalink
feat: update filter tokens interface in widget
Browse files Browse the repository at this point in the history
  • Loading branch information
mikasackermn committed Dec 30, 2023
1 parent fdd1e3a commit 5d22bef
Show file tree
Hide file tree
Showing 16 changed files with 382 additions and 115 deletions.
51 changes: 17 additions & 34 deletions widget/embedded/src/hooks/useSyncStoresWithConfig.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import type { Asset } from 'rango-sdk';

import { useEffect, useLayoutEffect, useMemo, useRef } from 'react';
import { useEffect, useLayoutEffect, useRef } from 'react';

import { useAppStore } from '../store/AppStore';
import { useQuoteStore } from '../store/quote';
import {
isBlockchainExcludedInConfig,
isTokenExcludedInConfig,
} from '../utils/configs';
import { tokensAreEqual } from '../utils/wallets';

export function useSyncStoresWithConfig() {
Expand All @@ -27,22 +31,10 @@ export function useSyncStoresWithConfig() {
const { setAffiliateRef, setAffiliatePercent, setAffiliateWallets } =
useAppStore();

const fromTokensConfig = useMemo(
() => config?.from?.tokens,
[config?.from?.tokens]
);
const fromBlockchainsConfig = useMemo(
() => config?.from?.blockchains,
[config?.from?.blockchains]
);
const toTokensConfig = useMemo(
() => config?.to?.tokens,
[config?.to?.tokens]
);
const toBlockchainsConfig = useMemo(
() => config?.to?.blockchains,
[config?.to?.blockchains]
);
const fromTokensConfig = config?.from?.tokens;
const fromBlockchainsConfig = config?.from?.blockchains;
const toTokensConfig = config?.to?.tokens;
const toBlockchainsConfig = config?.to?.blockchains;
const prevConfigFromToken = useRef<Asset | undefined>(undefined);
const prevConfigToToken = useRef<Asset | undefined>(undefined);
const prevConfigFromBlockchain = useRef<string | undefined>(undefined);
Expand Down Expand Up @@ -90,30 +82,21 @@ export function useSyncStoresWithConfig() {
]);

useEffect(() => {
if (fromToken && fromTokensConfig) {
if (!fromTokensConfig.some((token) => tokensAreEqual(token, fromToken))) {
setFromToken({ token: null });
}
if (isTokenExcludedInConfig(fromToken, fromTokensConfig)) {
setFromToken({ token: null });
}

if (fromBlockchain && fromBlockchainsConfig) {
if (!fromBlockchainsConfig.includes(fromBlockchain.name)) {
setFromBlockchain(null);
}
if (isBlockchainExcludedInConfig(fromBlockchain, fromBlockchainsConfig)) {
setFromBlockchain(null);
}
}, [fromTokensConfig, fromBlockchainsConfig]);

useEffect(() => {
if (toToken && toTokensConfig) {
if (!toTokensConfig.some((token) => tokensAreEqual(token, toToken))) {
setToToken({ token: null });
}
if (isTokenExcludedInConfig(toToken, toTokensConfig)) {
setFromToken({ token: null });
}

if (toBlockchain && toBlockchainsConfig) {
if (!toBlockchainsConfig.includes(toBlockchain.name)) {
setToBlockchain(null);
}
if (isBlockchainExcludedInConfig(toBlockchain, toBlockchainsConfig)) {
setToBlockchain(null);
}
}, [toTokensConfig, toBlockchainsConfig]);

Expand Down
2 changes: 2 additions & 0 deletions widget/embedded/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { WidgetProps } from './containers/Widget';
import type { ConnectedWallet } from './store/wallets';
import type {
BlockchainAndTokenConfig,
Tokens,
WidgetColors,
WidgetColorsKeys,
WidgetConfig,
Expand Down Expand Up @@ -86,6 +87,7 @@ export type {
StepOutputRevealedEvent,
HandleWalletsUpdate,
ConnectedWallet,
Tokens,
};
export {
Widget,
Expand Down
12 changes: 5 additions & 7 deletions widget/embedded/src/store/slices/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { StateCreator } from 'zustand';

import { httpService as sdk } from '../../services/httpService';
import { containsText } from '../../utils/common';
import { isTokenExcludedInConfig } from '../../utils/configs';
import { sortLiquiditySourcesByGroupTitle } from '../../utils/settings';
import { tokensAreEqual } from '../../utils/wallets';

Expand Down Expand Up @@ -81,21 +82,18 @@ export const createDataSlice: StateCreator<
}

const config = get().config;
const supportedTokensFromConfig =
const supportedTokensConfig =
(options.type === 'source' ? config.from?.tokens : config.to?.tokens) ??
[];
{};
const blockchains = get().blockchains({
type: options.type,
});

const list = tokensFromState
.filter((token) => {
// If there is a list of tokens in config, we only keep them.
if (
supportedTokensFromConfig.length > 0 &&
!supportedTokensFromConfig.some((asset) => {
return tokensAreEqual(asset, token);
})
supportedTokensConfig &&
isTokenExcludedInConfig(token, supportedTokensConfig)
) {
return false;
}
Expand Down
19 changes: 16 additions & 3 deletions widget/embedded/src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ export type WidgetAffiliate = {
wallets?: { [key: string]: string };
};

/**
* `Tokens`
*
* @property {boolean} isExcluded - This is a boolean property capable of removing tokens from all or a blockchain.
* @property {Asset[]} tokens - The `tokens` property is an array of `Asset` objects that
* you could use that to limit tokens to some limited ones.
*/

export type Tokens = {
isExcluded: boolean;
tokens: Asset[];
};

/**
* `BlockchainAndTokenConfig`
*
Expand All @@ -75,17 +88,17 @@ export type WidgetAffiliate = {
* which is selected. e.g. {blockchain: 'BSC', symbol: 'BNB', address: null}
* @property {string[]} blockchains - An optional array of strings representing the supported
* blockchains. e.g. ['BSC','ETHEREUM']
* @property {Asset[]} tokens - The `tokens` property is an optional array of `Asset` objects that
* you could use that to limit tokens to some limited ones.
* @property {Asset[] |{ [blockchain: string]: Tokens }} tokens - The `tokens` property is an optional object of `blockchain` objects or array of `Asset` objects
* that you could use that to limit tokens to some limited ones.
* @property {Asset} pinnedTokens - The `pinnedTokens` property is an optional array of `Asset` objects that
* you could use to pin tokens of your choice to the top of the token list.
*/
export type BlockchainAndTokenConfig = {
blockchain?: string;
token?: Asset;
blockchains?: string[];
tokens?: Asset[];
pinnedTokens?: Asset[];
tokens?: Asset[] | { [blockchain: string]: Tokens };
};

/**
Expand Down
41 changes: 41 additions & 0 deletions widget/embedded/src/utils/configs.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import type { Tokens } from '../types';
import type { Asset, BlockchainMeta, Token } from 'rango-sdk';

import { RANGO_PUBLIC_API_KEY } from '../constants';

import { tokensAreEqual } from './wallets';

export interface Configs {
API_KEY: string;
BASE_URL?: string;
}

type TokensConfig =
| Asset[]
| {
[blockchain: string]: Tokens;
};

let configs: Configs = {
API_KEY: RANGO_PUBLIC_API_KEY,
};
Expand Down Expand Up @@ -38,3 +49,33 @@ export const DEFAULT_SECONDARY_RADIUS = 25;
export const DEFAULT_FONT_FAMILY = 'Roboto';

export const THEME_CLASS_NAME_PREFIX = `theme-widget`;

export const isTokenExcludedInConfig = (
token: Token | null,
tokensConfig?: TokensConfig
) => {
let result = false;
if (tokensConfig && token) {
if (Array.isArray(tokensConfig)) {
result = !tokensConfig.some((asset) => tokensAreEqual(asset, token));
} else if (!Array.isArray(tokensConfig) && tokensConfig[token.blockchain]) {
result = tokensConfig[token.blockchain].tokens.some((asset) =>
tokensAreEqual(asset, token)
);
const isExcluded = tokensConfig[token.blockchain].isExcluded;
return (!isExcluded && !result) || (isExcluded && result);
}
}
return result;
};

export const isBlockchainExcludedInConfig = (
blockchain: BlockchainMeta | null,
blockchainsConfig?: string[]
) => {
return (
blockchain &&
blockchainsConfig &&
!blockchainsConfig.includes(blockchain.name)
);
};
11 changes: 9 additions & 2 deletions widget/playground/src/components/MultiList/MultiList.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,15 @@ export const SelectButton = styled('div', {
});

export const SelectDeselectText = styled(Typography, {
'&:hover': {
color: '$secondary500',
variants: {
disabled: {
true: {},
false: {
'&:hover': {
color: '$secondary500',
},
},
},
},
});
export const CheckList = styled('div', {
Expand Down
1 change: 1 addition & 0 deletions widget/playground/src/components/MultiList/MultiList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ export function MultiList(props: MultiListPropTypes) {
<SelectDeselectText
variant="label"
size="medium"
disabled={false}
color="neutral700">
{isAllCategorySelected ? 'Deselect all' : 'Select all'}
</SelectDeselectText>
Expand Down
3 changes: 2 additions & 1 deletion widget/playground/src/components/MultiSelect/MultiSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function MultiSelect(props: MuliSelectPropTypes) {
<Chip label={`+${value.length - MAX_CHIPS}`} variant="outlined" />
)}
</div>
<ChevronRightIcon size={12} />
<ChevronRightIcon size={12} color="gray" />
</div>
</Select>
{showNextModal && (
Expand All @@ -87,6 +87,7 @@ export function MultiSelect(props: MuliSelectPropTypes) {
) : (
<TokensPanel
list={list}
tokensConfig={props.tokensConfig}
onChange={(selectedTokens, pinnedTokens) => {
props.onChange(selectedTokens, pinnedTokens);
onBack();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { TokenType } from '../TokensPanel/TokensPanel.types';
import type { Tokens } from '@rango-dev/widget-embedded';

export interface CommonListProps {
type: 'Blockchains' | 'Bridges' | 'DEXs' | 'Wallets';
Expand All @@ -11,7 +12,11 @@ interface TokensListProps {
type: 'Tokens';
list: TokenType[];
selectedBlockchains: string[];
onChange: (selectedTokens?: TokenType[], pinnedTokens?: TokenType[]) => void;
onChange: (
selectedTokens?: { [blockchain: string]: Tokens },
pinnedTokens?: TokenType[]
) => void;
tokensConfig: { [blockchain: string]: Tokens };
}
export type MuliSelectPropTypes = (TokensListProps | CommonListProps) & {
value?: string[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export function TokensList(props: TokensListProps) {
showSelectedTokens,
setShowSelectedTokens,
isAllSelected,
isExcluded,
} = props;
const [searchValue, setSearchValue] = useState('');
const [virtualList, setVirtualList] = useState(list);
Expand Down Expand Up @@ -123,13 +124,14 @@ export function TokensList(props: TokensListProps) {
<SelectDeselectText
variant="label"
size="medium"
disabled={false}
color="neutral900">
{isAllSelected ? 'Deselect all' : 'Select all'}
</SelectDeselectText>
</SelectButton>
<div className="select_tokens">
<Typography size="medium" variant="label" color="neutral900">
Selected Tokens
{isExcluded ? 'Excluded' : 'Included'} Tokens
</Typography>
<Divider direction="horizontal" size={4} />
<Switch
Expand Down Expand Up @@ -165,9 +167,11 @@ export function TokensList(props: TokensListProps) {
onClick={() => toggleTokenSelection(virtualList[index])}
end={
<>
{virtualList[index].checked && (
{((virtualList[index].checked && !isExcluded) ||
(!virtualList[index].checked && isExcluded)) && (
<>
<IconButton
style={{ padding: 0 }}
variant="ghost"
onClick={(e) => {
e.stopPropagation();
Expand Down
Loading

0 comments on commit 5d22bef

Please sign in to comment.