Skip to content

Commit

Permalink
add token search and user asset search
Browse files Browse the repository at this point in the history
  • Loading branch information
walmat committed Mar 22, 2024
1 parent e42e995 commit 9e33d17
Show file tree
Hide file tree
Showing 18 changed files with 507 additions and 164 deletions.
9 changes: 6 additions & 3 deletions src/__swaps__/screens/Swap/components/SearchInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Input } from '@/components/inputs';
import { Bleed, Box, Column, Columns, Text, useColorMode, useForegroundColor } from '@/design-system';
import { LIGHT_SEPARATOR_COLOR, SEPARATOR_COLOR, THICK_BORDER_WIDTH } from '../constants';
import { opacity } from '../utils/swaps';
import { useSwapAssetStore } from '../state/assets';

export const SearchInput = ({
color,
Expand All @@ -23,8 +24,9 @@ export const SearchInput = ({
}) => {
const { isDarkMode } = useColorMode();

const { searchFilter, setSearchFilter } = useSwapAssetStore();

const inputRef = React.useRef<TextInput>(null);
const [query, setQuery] = React.useState('');

const fillTertiary = useForegroundColor('fillTertiary');
const label = useForegroundColor('label');
Expand Down Expand Up @@ -58,9 +60,10 @@ export const SearchInput = ({
<Input
onBlur={() => {
handleExitSearch();
setSearchFilter('');
setIsFocused(false);
}}
onChange={(value: string) => setQuery(value)}
onChangeText={setSearchFilter}
onFocus={() => {
handleFocusSearch();
setIsFocused(true);
Expand All @@ -77,7 +80,7 @@ export const SearchInput = ({
height: 44,
zIndex: 10,
}}
value={query}
value={searchFilter}
/>
</Columns>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import { Bleed, Box, HitSlop, Inline, Separator, Stack, Text, globalColors, useC
import { useAccountAccentColor, useDimensions } from '@/hooks';
import { Network } from '@/networks/types';
import { useTheme } from '@/theme';
import { SwapCoinIcon } from './SwapCoinIcon';
import { EXPANDED_INPUT_HEIGHT, FOCUSED_INPUT_HEIGHT } from '../constants';
import { DAI_ADDRESS, ETH_ADDRESS, USDC_ADDRESS } from '../dummyValues';
import { opacity } from '../utils/swaps';
import { CoinRow } from './CoinRow';
import { SearchInput } from './SearchInput';
import { SwapCoinIcon } from '../SwapCoinIcon';
import { EXPANDED_INPUT_HEIGHT, FOCUSED_INPUT_HEIGHT } from '../../constants';
import { DAI_ADDRESS, ETH_ADDRESS, USDC_ADDRESS } from '../../dummyValues';
import { opacity } from '../../utils/swaps';
import { CoinRow } from '../CoinRow';
import { SearchInput } from '../SearchInput';
import { TokenToSellList } from './TokenToSellList';
import { TokenToBuyList } from './TokenToBuyList';

export const TokenList = ({
color,
Expand Down Expand Up @@ -127,7 +129,7 @@ export const TokenList = ({
</Box>
</Bleed>
<Text color="label" size="15pt" weight="heavy">
My Tokens
My tokens
</Text>
</Inline>
)}
Expand All @@ -145,105 +147,9 @@ export const TokenList = ({
</HitSlop>
</ButtonPressAnimation>
</Inline>
<CoinRow
address={ETH_ADDRESS}
balance="7"
isTrending={output}
name="Ethereum"
nativeBalance="$18,320"
output={output}
symbol="ETH"
/>
<CoinRow
address={USDC_ADDRESS}
balance="2,640"
isTrending={output}
name="USD Coin"
nativeBalance="$2,640"
output={output}
symbol="USDC"
/>
<CoinRow
address={DAI_ADDRESS}
balance="2,800.02"
isTrending={output}
name="Dai"
nativeBalance="$2,800"
output={output}
symbol="DAI"
/>
</Stack>
<Stack space="20px">
{output && (
<Inline alignVertical="center" space="6px">
<Bleed vertical="4px">
<Box alignItems="center" justifyContent="center" width={{ custom: 16 }}>
<Bleed space={isDarkMode ? '16px' : undefined}>
<RNText
style={
isDarkMode
? [
styles.textIconGlow,
{
textShadowColor: opacity(blue, 0.28),
},
]
: undefined
}
>
<Text align="center" color="blue" size="icon 13px" weight="heavy">
􀐫
</Text>
</RNText>
</Bleed>
</Box>
</Bleed>
<Text color="label" size="15pt" weight="heavy">
Recent
</Text>
</Inline>
)}
<CoinRow
address="0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9"
balance="428.25"
name="Aave"
nativeBalance="$1,400"
output={output}
symbol="AAVE"
/>
<CoinRow
address="0x2260fac5e5542a773aa44fbcfedf7c193bc2c599"
balance="0.042819"
name="Wrapped Bitcoin"
nativeBalance="$1,025"
output={output}
symbol="WBTC"
/>
<CoinRow
address="0xc00e94cb662c3520282e6f5717214004a7f26888"
balance="72.2806"
name="Compound"
nativeBalance="$350.04"
output={output}
symbol="COMP"
/>
<CoinRow
address="0x1f9840a85d5af5bf1d1762f925bdaddc4201f984"
balance="62.82"
name="Uniswap"
nativeBalance="$289.52"
output={output}
symbol="UNI"
/>
<CoinRow
address="0x514910771af9ca656af840dff83e8264ecf986ca"
balance="27.259"
name="Chainlink"
nativeBalance="$87.50"
output={output}
symbol="LINK"
/>
</Stack>
{!output && <TokenToSellList />}
{output && <TokenToBuyList />}
</Stack>
</ScrollView>
</Stack>
Expand Down
44 changes: 44 additions & 0 deletions src/__swaps__/screens/Swap/components/TokenList/TokenToBuyList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as i18n from '@/languages';
import React, { useMemo } from 'react';
import { useAssetsToBuySections } from '../../hooks/useAssetsToBuy';
import { TokenToBuySection } from './TokenToBuySection';
import { Box, Stack, Text } from '@/design-system';
import { useSwapAssetStore } from '../../state/assets';
import { isL2Chain } from '../../utils/chains';

export const TokenToBuyList = () => {
const { outputChainId } = useSwapAssetStore();
const sections = useAssetsToBuySections();

const isL2 = useMemo(() => outputChainId && isL2Chain(outputChainId), [outputChainId]);

const assetsCount = useMemo(() => sections?.reduce((count, section) => count + section.data.length, 0), [sections]);

return (
<Stack space="20px">
{sections.map(section => (
<TokenToBuySection key={section.id} section={section} />
))}

{!assetsCount && (
<Box alignItems="center" style={{ paddingTop: 91 }}>
<Box paddingHorizontal="44px">
<Stack space="16px">
<Text color="label" size="26pt" weight="bold" align="center">
{'👻'}
</Text>

<Text color="labelTertiary" size="20pt" weight="semibold" align="center">
{i18n.t(i18n.l.swap.tokens_input.nothing_found)}
</Text>

<Text color="labelQuaternary" size="14px / 19px (Deprecated)" weight="regular" align="center">
{i18n.t(i18n.l.swap.tokens_input[isL2 ? 'nothing_found_description_l2' : 'nothing_found_description'])}
</Text>
</Stack>
</Box>
</Box>
)}
</Stack>
);
};
134 changes: 134 additions & 0 deletions src/__swaps__/screens/Swap/components/TokenList/TokenToBuySection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import * as i18n from '@/languages';
import React, { useCallback, useMemo } from 'react';
import { CoinRow } from '../CoinRow';
import { useSwapAssetStore } from '../../state/assets';
import { SearchAsset } from '../../types/search';
import { Box, Inline, Inset, Stack, Text } from '@/design-system';
import { TextStyle } from 'react-native';
import { AssetToBuySection, AssetToBuySectionId } from '../../hooks/useSearchCurrencyLists';
import { ChainId } from '../../types/chains';
import { BackgroundColor, TextColor } from '@/design-system/color/palettes';

interface SectionProp {
backgroundColor?: BackgroundColor;
gradient?: React.ReactNode;
color: TextStyle['color'];
symbol: string;
title: string;
}

const sectionProps: { [id in AssetToBuySectionId]: SectionProp } = {
favorites: {
title: i18n.t(i18n.l.token_search.section_header.favorites),
symbol: 'star.fill',
color: 'yellow',
gradient: undefined,
backgroundColor: undefined,
},
bridge: {
title: i18n.t(i18n.l.token_search.section_header.bridge),
symbol: 'shuffle',
color: 'label',
gradient: undefined,
backgroundColor: undefined,
},
verified: {
title: i18n.t(i18n.l.token_search.section_header.verified),
symbol: 'checkmark.seal.fill',
color: 'labelTertiary',
// gradient: rainbowGradient,
backgroundColor: undefined,
},
unverified: {
title: i18n.t(i18n.l.token_search.section_header.unverified),
symbol: 'exclamationmark.triangle.fill',
color: 'labelTertiary',
gradient: undefined,
backgroundColor: undefined,
},
other_networks: {
title: i18n.t(i18n.l.token_search.section_header.on_other_networks),
symbol: 'network',
color: 'labelTertiary',
gradient: undefined,
backgroundColor: undefined,
},
};

const bridgeSectionsColorsByChain = {
[ChainId.mainnet]: 'mainnet' as TextStyle['color'],
[ChainId.arbitrum]: 'arbitrum' as TextStyle['color'],
[ChainId.optimism]: 'optimism' as TextStyle['color'],
[ChainId.polygon]: 'polygon' as TextStyle['color'],
[ChainId.base]: 'base' as TextStyle['color'],
[ChainId.zora]: 'zora' as TextStyle['color'],
[ChainId.bsc]: 'bsc' as TextStyle['color'],
[ChainId.avalanche]: 'avalanche' as TextStyle['color'],
};

export const TokenToBuySection = ({ section }: { section: AssetToBuySection }) => {
const { outputChainId, setAssetToBuy } = useSwapAssetStore();

const handleSelectToken = useCallback(
(token: SearchAsset) => {
setAssetToBuy(token);
// TODO: Close the input dropdown and open the output token dropdown
},
[setAssetToBuy]
);

const { backgroundColor, gradient, symbol, title } = sectionProps[section.id];

const color = useMemo(() => {
if (section.id !== 'bridge') {
return sectionProps[section.id].color as TextColor;
}
return bridgeSectionsColorsByChain[outputChainId || ChainId.mainnet] as TextColor;
}, [section.id, outputChainId]);

if (!section.data.length) return null;

return (
<Box key={section.id} testID={`${section.id}-token-to-buy-section`}>
<Stack space="20px">
{section.id === 'other_networks' ? (
<Box borderRadius={12} height={{ custom: 52 }}>
<Inset horizontal="20px" vertical="8px">
<Inline space="8px" alignVertical="center">
{/* <SwapCoinIcon /> */}
<Text size="icon 14px" weight="semibold" color={'labelQuaternary'}>
{i18n.t(i18n.l.swap.tokens_input.nothing_found)}
</Text>
</Inline>
</Inset>
</Box>
) : null}
<Box paddingHorizontal={{ custom: 15 }}>
<Box paddingHorizontal={{ custom: 5 }} width="full">
<Inline space="4px" alignVertical="center">
{/* <Symbol symbol={symbol} color={color} weight="semibold" size={14} gradient={gradient} /> */}
<Box background={backgroundColor} style={{ width: 225 }}>
<Text size="14px / 19px (Deprecated)" weight="semibold" color={color}>
{title}
</Text>
</Box>
</Inline>
</Box>
</Box>

{section.data.map(token => (
<CoinRow
key={token.uniqueId}
address={token.address}
balance={''}
name={token.name}
onPress={() => handleSelectToken(token)}
nativeBalance={''}
output
symbol={token.symbol}
/>
))}
</Stack>
</Box>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React, { useCallback } from 'react';
import { CoinRow } from '../CoinRow';
import { useAssetsToSell } from '../../hooks/useAssetsToSell';
import { ParsedSearchAsset } from '../../types/assets';
import { useSwapAssetStore } from '../../state/assets';
import { Stack } from '@/design-system';
import { useSwapContext } from '../../providers/swap-provider';

export const TokenToSellList = () => {
const { setAssetToSell } = useSwapAssetStore();
const { SwapInputController } = useSwapContext();
const assets = useAssetsToSell();

const handleSelectToken = useCallback(
(token: ParsedSearchAsset) => {
setAssetToSell(token);
SwapInputController.formattedInputAmount;
// TODO: Close the input dropdown and open the output token dropdown
},
[setAssetToSell]
);

return (
<Stack space="20px">
{assets.map((token: ParsedSearchAsset) => (
<CoinRow
key={token.uniqueId}
address={token.address}
balance={token.balance.display}
name={token.name}
onPress={() => handleSelectToken(token)}
nativeBalance={token.native.balance.display}
output={false}
symbol={token.symbol}
/>
))}
</Stack>
);
};
Loading

0 comments on commit 9e33d17

Please sign in to comment.