Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SWAPS V2]: Add token search logic and ability to select assets #5547

Merged
merged 32 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
52e52cc
initial useSwapAssets work
walmat Mar 22, 2024
b1cf1d6
remove unused chainid ref
walmat Mar 22, 2024
e42e995
comment out favorites until I can match the types
walmat Mar 22, 2024
9e33d17
add token search and user asset search
walmat Mar 22, 2024
59b8ce4
replace a bunch of dummy values with actual color values / balances
walmat Mar 25, 2024
d0932e1
some cleanup
walmat Mar 25, 2024
79de904
undo type change and fix lint
walmat Mar 25, 2024
99feb1a
some cleanup
walmat Mar 26, 2024
dd5ffc0
fix some bugs
walmat Mar 26, 2024
11f51e6
some more optimizations
walmat Mar 27, 2024
f2c4c8a
Merge branch 'develop' into @matthew/APP-1247
walmat Mar 27, 2024
3cce241
touches
walmat Mar 27, 2024
e3b683c
add display prop to animated styles
walmat Mar 27, 2024
dc62a88
merge develop
walmat Mar 28, 2024
761ef47
more prop splitting
walmat Mar 28, 2024
1b71aab
replaced stuff with reanimated stuff
walmat Mar 29, 2024
ea74875
this is fucked
walmat Mar 29, 2024
4277572
moving over some reanimated stuff
walmat Mar 29, 2024
cf9bca0
swap action button colors working
walmat Mar 29, 2024
a610b71
more progress on reanimated conversion
walmat Mar 30, 2024
203c6f9
ya
walmat Apr 2, 2024
f86cc4e
fix token flipping
walmat Apr 2, 2024
459545e
fix https://github.com/rainbow-me/browser-extension/pull/1453/files
walmat Apr 2, 2024
1cb57d7
fix empty acitivity list
walmat Apr 2, 2024
cb2bfae
search + asset lists working
walmat Apr 3, 2024
32c11ab
fix swapbackground linear not using reanimated values
walmat Apr 3, 2024
60732c3
limit buy sections to first 5 assets
walmat Apr 3, 2024
34497fd
perf improvements
walmat Apr 3, 2024
a57ee70
Merge branch 'develop' into @matthew/APP-1247
walmat Apr 3, 2024
7f306d0
fix padding on output asset coin row
walmat Apr 3, 2024
04bb1ae
Merge branch 'develop' into @matthew/APP-1247
walmat Apr 3, 2024
87deb2d
fix lint
walmat Apr 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/__swaps__/components/animations/AnimatedSpinner.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import React from 'react';
import Animated, { Easing, useAnimatedReaction, useAnimatedStyle, useSharedValue, withRepeat, withTiming } from 'react-native-reanimated';
import Animated, {
Easing,
SharedValue,
useAnimatedReaction,
useAnimatedStyle,
useSharedValue,
withRepeat,
withTiming,
} from 'react-native-reanimated';
import { useForegroundColor } from '@/design-system';
import styled from '@/styled-thing';
import { ImgixImage } from '@/components/images';
Expand Down Expand Up @@ -27,14 +35,15 @@ const StyledSpinner = styled(ImgixImage).attrs(({ color, size, src }: { color: s
width: ({ size }: { size?: number }) => size,
});

// TODO: We should also accept a regular boolean as a state variable
export const AnimatedSpinner = ({
isLoading,
color,
scaleInFrom = 0,
size = 28,
src = Spinner,
}: {
isLoading: boolean;
isLoading: SharedValue<boolean>;
color?: string;
scaleInFrom?: number;
size?: number;
Expand All @@ -46,7 +55,7 @@ export const AnimatedSpinner = ({
const spinnerScale = useSharedValue(0);

useAnimatedReaction(
() => isLoading,
() => isLoading.value,
(isLoadingCurrent, isLoadingPrevious) => {
if (isLoadingCurrent !== isLoadingPrevious) {
if (isLoadingCurrent) {
Expand Down
20 changes: 10 additions & 10 deletions src/__swaps__/screens/Swap/Swap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { SwapInputAsset } from './components/controls/SwapInputAsset';
import { SwapOutputAsset } from './components/controls/SwapOutputAsset';
import { SwapNavbar } from './components/SwapNavbar';
import { SwapAmountInputs } from './components/controls/SwapAmountInputs';
import { safeAreaInsetValues } from '@/utils';
import { navbarHeight } from '@/components/navbar/Navbar';

/** README
* This prototype is largely driven by Reanimated and Gesture Handler, which
Expand Down Expand Up @@ -56,15 +58,14 @@ export function SwapScreen() {
return (
<SheetGestureBlocker>
<Box as={Page} style={styles.rootViewBackground} testID="swap-screen" width="full">
<SwapBackground>
<Box alignItems="center" height="full" paddingTop={{ custom: 29 }} width="full">
<SwapInputAsset />
<FlipButton />
<SwapOutputAsset />
<ExchangeRateBubble />
<SwapAmountInputs />
</Box>
</SwapBackground>
<SwapBackground />
<Box alignItems="center" height="full" paddingTop={{ custom: safeAreaInsetValues.top + (navbarHeight - 12) + 29 }} width="full">
<SwapInputAsset />
<FlipButton />
<SwapOutputAsset />
<ExchangeRateBubble />
<SwapAmountInputs />
</Box>
<SwapNavbar />
</Box>
</SheetGestureBlocker>
Expand All @@ -73,7 +74,6 @@ export function SwapScreen() {

export const styles = StyleSheet.create({
rootViewBackground: {
backgroundColor: 'transparent',
borderRadius: IS_ANDROID ? 20 : ScreenCornerRadius,
flex: 1,
overflow: 'hidden',
Expand Down
22 changes: 13 additions & 9 deletions src/__swaps__/screens/Swap/components/BalanceBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
/* eslint-disable no-nested-ternary */
import React from 'react';
import { Bleed, Box, Text, useColorMode } from '@/design-system';
import { AnimatedText, Bleed, Box, useColorMode } from '@/design-system';
import { TextColor } from '@/design-system/color/palettes';
import { TextWeight } from '@/design-system/components/Text/Text';
import { LIGHT_SEPARATOR_COLOR, SEPARATOR_COLOR, THICK_BORDER_WIDTH } from '../constants';
import { DerivedValue, useAnimatedStyle } from 'react-native-reanimated';

export const BalanceBadge = ({ color, label, weight }: { color?: TextColor; label: string; weight?: TextWeight }) => {
export const BalanceBadge = ({ color, label, weight }: { color?: TextColor; label: DerivedValue<string>; weight?: TextWeight }) => {
const { isDarkMode } = useColorMode();

const labelTextStyle = useAnimatedStyle(() => {
return {
opacity: label.value === 'No Balance' ? (isDarkMode ? 0.6 : 0.75) : undefined,
};
});

return (
<Bleed vertical={{ custom: 5.5 }}>
<Box
Expand All @@ -21,17 +28,14 @@ export const BalanceBadge = ({ color, label, weight }: { color?: TextColor; labe
borderWidth: THICK_BORDER_WIDTH,
}}
>
<Text
<AnimatedText
align="center"
color={color || 'labelQuaternary'}
size="13pt"
style={{
opacity: label === 'No Balance' ? (isDarkMode ? 0.6 : 0.75) : undefined,
}}
text={label}
style={labelTextStyle}
weight={weight || 'bold'}
>
{label}
</Text>
/>
</Box>
</Bleed>
);
Expand Down
56 changes: 48 additions & 8 deletions src/__swaps__/screens/Swap/components/CoinRow.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,53 @@
import React, { useMemo } from 'react';
import { Address } from 'viem';
import { ButtonPressAnimation } from '@/components/animations';
import { Box, HitSlop, Inline, Stack, Text } from '@/design-system';
import { TextColor } from '@/design-system/color/palettes';
import { Network } from '@/networks/types';
import { useTheme } from '@/theme';
import { SwapCoinIcon } from './SwapCoinIcon';
import { CoinRowButton } from './CoinRowButton';
import { BalancePill } from './BalancePill';
import { ChainId } from '../types/chains';
import { ethereumUtils } from '@/utils';
import { toggleFavorite, useFavorites } from '@/resources/favorites';
import { ETH_ADDRESS } from '@/references';

export const CoinRow = ({
address,
mainnetAddress,
chainId,
balance,
isTrending,
name,
nativeBalance,
color,
iconUrl,
onPress,
output,
symbol,
}: {
address: Address | 'eth';
address: string;
mainnetAddress: string;
chainId: ChainId;
balance: string;
isTrending?: boolean;
name: string;
nativeBalance: string;
color: string | undefined;
iconUrl: string | undefined;
onPress?: () => void;
output?: boolean;
symbol: string;
}) => {
const theme = useTheme();
const { favoritesMetadata } = useFavorites();

const favorites = Object.values(favoritesMetadata);

const isFavorite = (address: string) => {
return favorites.find(fav =>
fav.address === ETH_ADDRESS ? '0x0000000000000000000000000000000000000000' === address : fav.address === address
);
};

const percentChange = useMemo(() => {
if (isTrending) {
Expand All @@ -43,18 +62,34 @@ export const CoinRow = ({
}, [isTrending]);

return (
<ButtonPressAnimation onPress={onPress} scaleTo={0.95}>
<ButtonPressAnimation disallowInterruption onPress={onPress} scaleTo={0.95}>
<HitSlop vertical="10px">
<Box alignItems="center" flexDirection="row" justifyContent="space-between" width="full">
<Box
alignItems="center"
paddingVertical={'10px'}
paddingHorizontal={'20px'}
flexDirection="row"
justifyContent="space-between"
width="full"
>
<Inline alignVertical="center" space="10px">
<SwapCoinIcon address={address} large network={Network.mainnet} symbol={symbol} theme={theme} />
<SwapCoinIcon
iconUrl={iconUrl}
address={address}
mainnetAddress={mainnetAddress}
large
network={ethereumUtils.getNetworkFromChainId(chainId)}
symbol={symbol}
theme={theme}
color={color}
/>
<Stack space="10px">
<Text color="label" size="17pt" weight="semibold">
{name}
</Text>
<Inline alignVertical="center" space={{ custom: 5 }}>
<Text color="labelTertiary" size="13pt" weight="semibold">
{output ? symbol : `${balance} ${symbol}`}
{output ? symbol : `${balance}`}
</Text>
{isTrending && percentChange && (
<Inline alignVertical="center" space={{ custom: 1 }}>
Expand All @@ -72,7 +107,12 @@ export const CoinRow = ({
{output ? (
<Inline space="8px">
<CoinRowButton icon="􀅳" outline size="icon 14px" />
<CoinRowButton icon="􀋃" weight="black" />
<CoinRowButton
color={isFavorite(address) ? '#FFCB0F' : undefined}
onPress={() => toggleFavorite(address)}
icon="􀋃"
weight="black"
/>
</Inline>
) : (
<BalancePill balance={nativeBalance} />
Expand Down
18 changes: 13 additions & 5 deletions src/__swaps__/screens/Swap/components/CoinRowButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import { LIGHT_SEPARATOR_COLOR, SEPARATOR_COLOR, THICK_BORDER_WIDTH } from '../c
import { opacity } from '../utils/swaps';

export const CoinRowButton = ({
color,
icon,
onPress,
outline,
size,
weight,
}: {
color?: string;
icon: string;
onPress?: () => void;
outline?: boolean;
Expand All @@ -26,23 +28,29 @@ export const CoinRowButton = ({
const separatorTertiary = useForegroundColor('separatorTertiary');

return (
<ButtonPressAnimation onPress={onPress} scaleTo={0.8}>
<ButtonPressAnimation disallowInterruption onPress={onPress} scaleTo={0.8}>
<Box
alignItems="center"
borderRadius={14}
height={{ custom: 28 }}
justifyContent="center"
style={{
backgroundColor: outline ? 'transparent' : isDarkMode ? fillQuaternary : opacity(fillTertiary, 0.04),
borderColor: outline ? (isDarkMode ? SEPARATOR_COLOR : LIGHT_SEPARATOR_COLOR) : separatorTertiary,
backgroundColor: outline
? 'transparent'
: color
? opacity(color, 0.25)
: isDarkMode
? fillQuaternary
: opacity(fillTertiary, 0.04),
borderColor: outline ? (isDarkMode ? SEPARATOR_COLOR : LIGHT_SEPARATOR_COLOR) : color ? opacity(color, 0.1) : separatorTertiary,
borderWidth: THICK_BORDER_WIDTH,
}}
width={{ custom: 28 }}
>
<TextIcon
color="labelQuaternary"
color={color ? { custom: color } : 'labelQuaternary'}
containerSize={28}
opacity={isDarkMode ? 0.6 : 0.75}
opacity={isDarkMode ? 1 : 0.75}
size={size || 'icon 12px'}
weight={weight || 'heavy'}
>
Expand Down
43 changes: 34 additions & 9 deletions src/__swaps__/screens/Swap/components/ExchangeRateBubble.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
import React from 'react';
import { Box, Inline, Text, TextIcon, useColorMode, useForegroundColor } from '@/design-system';
import { AnimatedText, Box, Inline, TextIcon, useColorMode, useForegroundColor } from '@/design-system';
import { LIGHT_SEPARATOR_COLOR, SEPARATOR_COLOR, THICK_BORDER_WIDTH } from '../constants';
import { opacity } from '../utils/swaps';
import { ButtonPressAnimation } from '@/components/animations';
import Animated from 'react-native-reanimated';
import Animated, { useDerivedValue } from 'react-native-reanimated';
import { useSwapContext } from '../providers/swap-provider';

export const ExchangeRateBubble = () => {
const { isDarkMode } = useColorMode();
const { AnimatedSwapStyles } = useSwapContext();
const { AnimatedSwapStyles, SwapInputController } = useSwapContext();

const fillTertiary = useForegroundColor('fillTertiary');

const assetToSellLabel = useDerivedValue(() => {
if (!SwapInputController?.assetToSell.value) return '';
return `1 ${SwapInputController?.assetToSell.value?.symbol}`;
});

const assetToBuyLabel = useDerivedValue(() => {
if (!SwapInputController.assetToBuy.value) return '';
return `1,624.04 ${SwapInputController.assetToBuy.value?.symbol}`;
});

// TODO: Do proper exchange rate calculation once we receive the quote

// TODO: This doesn't work when assets change, figure out why...
if (!assetToSellLabel.value || !assetToBuyLabel.value) return null;

return (
<ButtonPressAnimation scaleTo={0.925} style={{ marginTop: 4 }}>
<Box
Expand All @@ -31,9 +46,14 @@ export const ExchangeRateBubble = () => {
style={{ borderColor: isDarkMode ? SEPARATOR_COLOR : LIGHT_SEPARATOR_COLOR, borderWidth: THICK_BORDER_WIDTH }}
>
<Inline alignHorizontal="center" alignVertical="center" space="6px" wrap={false}>
<Text align="center" color="labelQuaternary" size="13pt" style={{ opacity: isDarkMode ? 0.6 : 0.75 }} weight="heavy">
1 ETH
</Text>
<AnimatedText
align="center"
color="labelQuaternary"
size="13pt"
style={{ opacity: isDarkMode ? 0.6 : 0.75 }}
weight="heavy"
text={assetToSellLabel}
/>
<Box
borderRadius={10}
height={{ custom: 20 }}
Expand All @@ -45,9 +65,14 @@ export const ExchangeRateBubble = () => {
􀄭
</TextIcon>
</Box>
<Text align="center" color="labelQuaternary" size="13pt" style={{ opacity: isDarkMode ? 0.6 : 0.75 }} weight="heavy">
1,624.04 USDC
</Text>
<AnimatedText
align="center"
color="labelQuaternary"
size="13pt"
style={{ opacity: isDarkMode ? 0.6 : 0.75 }}
weight="heavy"
text={assetToBuyLabel}
/>
</Inline>
</Box>
</Box>
Expand Down
Loading
Loading