Skip to content

Commit

Permalink
fix: native swap (#2120)
Browse files Browse the repository at this point in the history
* fix(HW-759): swap screen issues

* fix(HW-763): added swap finish screen

* feat: added swap tokens sorting

---------

Co-authored-by: iGroza <[email protected]>
  • Loading branch information
iGroza and iGroza authored Oct 7, 2024
1 parent 2c0643d commit ec35327
Show file tree
Hide file tree
Showing 15 changed files with 828 additions and 329 deletions.
330 changes: 169 additions & 161 deletions assets/locales/en/en.json

Large diffs are not rendered by default.

260 changes: 257 additions & 3 deletions src/components/swap/swap-finish.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,259 @@
import React from 'react';

export const SwapFinish = () => {
return <></>;
};
import {observer} from 'mobx-react';
import {View} from 'react-native';

import {Color} from '@app/colors';
import {
Button,
ButtonVariant,
First,
Icon,
IconButton,
IconsName,
LottieWrap,
PopupContainer,
Spacer,
Text,
TextPosition,
TextVariant,
} from '@app/components/ui';
import {createTheme} from '@app/helpers';
import {shortAddress} from '@app/helpers/short-address';
import {I18N, getText} from '@app/i18n';
import {Contracts} from '@app/models/contracts';
import {Provider} from '@app/models/provider';
import {SwapStackParamList, SwapStackRoutes} from '@app/route-types';
import {Balance} from '@app/services/balance';
import {STRINGS} from '@app/variables/common';

import {
SwapRoutePathIcons,
SwapRoutePathIconsType,
} from './swap-route-path-icons';

import {ImageWrapper} from '../image-wrapper';

type SwapFinishProps = {
onPressDone: () => void;
onPressHash: () => void;
testID?: string;
rate: string;
providerFee: Balance;
} & Omit<SwapStackParamList[SwapStackRoutes.Finish], 'txHash'>;

export const SwapFinish = observer(
({
onPressDone,
onPressHash,
testID,
estimateData,
token0,
token1,
isUnwrapTx,
isWrapTx,
rate,
providerFee,
}: SwapFinishProps) => {
return (
<PopupContainer style={styles.container} testID={testID}>
<View style={styles.sub}>
<LottieWrap
source={require('@assets/animations/transaction-finish.json')}
style={styles.image}
autoPlay={true}
loop={false}
/>

<First>
{isWrapTx && (
<Text
variant={TextVariant.t4}
i18n={I18N.swapFinishWrapComplete}
style={styles.title}
position={TextPosition.center}
color={Color.textGreen1}
/>
)}

{isUnwrapTx && (
<Text
variant={TextVariant.t4}
i18n={I18N.swapFinishUnwrapComplete}
style={styles.title}
position={TextPosition.center}
color={Color.textGreen1}
/>
)}

<Text
variant={TextVariant.t4}
i18n={I18N.swapFinishComplete}
style={styles.title}
position={TextPosition.center}
color={Color.textGreen1}
/>
</First>

<Text
variant={TextVariant.t11}
i18n={I18N.swapFinishYouPaid}
color={Color.textBase2}
/>
<View style={styles.tokenContainer}>
<ImageWrapper source={token0?.image!} style={styles.tokenImage} />
<Spacer width={10} />
<Text variant={TextVariant.t3}>
{token0?.value.toBalanceString('auto')}
</Text>
</View>

<Spacer height={4} />
<Icon i24 name={IconsName.swap_vertical} color={Color.graphicBase1} />
<Spacer height={4} />

<Text
variant={TextVariant.t11}
i18n={I18N.swapFinishYouReceived}
color={Color.textBase2}
/>
<View style={styles.tokenContainer}>
<ImageWrapper source={token1?.image!} style={styles.tokenImage} />
<Spacer width={10} />
<Text variant={TextVariant.t3}>
{token1?.value.toBalanceString('auto')}
</Text>
</View>
</View>

<View style={styles.sub}>
<Text variant={TextVariant.t15} color={Color.textBase2}>
{getText(I18N.swapScreenRate)}:{STRINGS.NBSP}
{`1${STRINGS.NBSP}${token0.value.getSymbol()}${STRINGS.NBSP}${
STRINGS.NBSP
}${rate}`}
</Text>

{!isWrapTx && !isUnwrapTx && (
<>
<Spacer height={4} />
<Text variant={TextVariant.t15} color={Color.textBase2}>
{getText(I18N.swapScreenProviderFee)}:{STRINGS.NBSP}
{`${providerFee.toFiat({
useDefaultCurrency: true,
fixed: 6,
})}`}
</Text>
</>
)}

<Spacer height={4} />

<First>
{(isWrapTx || isUnwrapTx) && (
<Text variant={TextVariant.t15} color={Color.textBase2}>
{getText(I18N.swapScreenProviderFee)}:{STRINGS.NBSP}
{`${Contracts.getById(
Provider.selectedProvider.config.wethAddress,
)?.name}${STRINGS.NBSP}${shortAddress(
Provider.selectedProvider.config.wethAddress!,
'•',
true,
)}`}
</Text>
)}
<Text variant={TextVariant.t15} color={Color.textBase2}>
{getText(I18N.swapScreenRoutingSource)}:{STRINGS.NBSP}
{'SwapRouterV3'}
</Text>
</First>

<Spacer height={4} />

<View style={styles.routeContainer}>
<Text variant={TextVariant.t15} color={Color.textBase2}>
{getText(I18N.swapScreenRoute)}:{STRINGS.NBSP}
</Text>
<SwapRoutePathIcons
type={SwapRoutePathIconsType.path}
hexPath={estimateData.route}
/>
</View>
</View>

<View style={styles.buttonContainer}>
<IconButton onPress={onPressHash} style={styles.button}>
<Icon
name={IconsName.block}
color={Color.graphicBase2}
style={styles.buttonIcon}
i24
/>
<Text
variant={TextVariant.t15}
position={TextPosition.center}
i18n={I18N.transactionFinishHash}
color={Color.textBase2}
/>
</IconButton>
<Spacer height={32} />
<Button
style={styles.margin}
variant={ButtonVariant.contained}
i18n={I18N.transactionFinishDone}
onPress={onPressDone}
testID={`${testID}_finish`}
/>
</View>
</PopupContainer>
);
},
);

const styles = createTheme({
buttonContainer: {
width: '100%',
flex: 1,
justifyContent: 'center',
},
routeContainer: {
flexDirection: 'row',
alignItems: 'center',
},
container: {
paddingHorizontal: 20,
justifyContent: 'space-between',
},
sub: {
justifyContent: 'center',
alignItems: 'center',
flex: 2,
},
image: {width: 140, height: 140},
title: {
marginTop: 32,
marginBottom: 34,
},
margin: {marginBottom: 16},
button: {
flex: 1,
marginHorizontal: 6,
paddingHorizontal: 4,
paddingVertical: 12,
backgroundColor: Color.bg8,
borderRadius: 12,
maxHeight: 66,
},
buttonIcon: {
marginBottom: 4,
},
tokenContainer: {
flexDirection: 'row',
alignItems: 'center',
},
tokenImage: {
width: 24,
height: 24,
borderRadius: 12,
},
});
18 changes: 16 additions & 2 deletions src/components/swap/swap-input.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, {useCallback} from 'react';

import {observer} from 'mobx-react';
import {View} from 'react-native';
Expand All @@ -9,6 +9,7 @@ import {useSumAmount} from '@app/hooks';
import {I18N} from '@app/i18n';
import {Balance} from '@app/services/balance';
import {IToken} from '@app/types';
import {WEI_PRECISION} from '@app/variables/common';

import {ImageWrapper} from '../image-wrapper';
import {
Expand Down Expand Up @@ -53,6 +54,19 @@ export const SwapInput = observer(
onPressMax,
...inputProps
}: SwapInputProps) => {
const handleOnChangeText = useCallback(
(text: string) => {
let decimalsOffset = 0;

if (text.startsWith('0.')) {
decimalsOffset = 2;
}

const decimals = (token.decimals || WEI_PRECISION) + decimalsOffset;
amounts.setAmount(text?.trim()?.slice(0, decimals));
},
[amounts, token, availableBalance, currentBalance],
);
return (
<View>
<View style={styles.amountContainer}>
Expand Down Expand Up @@ -84,7 +98,7 @@ export const SwapInput = observer(
errorText={amounts.error}
{...inputProps}
value={amounts.amount}
onChangeText={amounts.setAmount}
onChangeText={handleOnChangeText}
keyboardType="numeric"
inputMode="decimal"
returnKeyType="done"
Expand Down
2 changes: 1 addition & 1 deletion src/components/swap/swap-route-path-icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const SwapRoutePathIcons = observer(
source={{uri: contract.icon!}}
/>
{!isLast && (
<Text variant={TextVariant.t14} color={Color.textBase1}>
<Text variant={TextVariant.t14} color={Color.graphicSecond3}>
{STRINGS.NBSP}
{I18nManager.isRTL ? '←' : '→'}
{STRINGS.NBSP}
Expand Down
22 changes: 18 additions & 4 deletions src/components/swap/swap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,20 +126,34 @@ export const Swap = observer(
const isHeaderButtonsDisabled =
isEstimating || isSwapInProgress || isApproveInProgress;

const isInfussentBalance = useMemo(() => {
return t0Available.compare(t0Current, 'lt');
}, [t0Available, t0Current]);

const isSwapButtonDisabled = useMemo(() => {
return (
isEstimating ||
isSwapInProgress ||
!!amountsIn.error ||
!t0Current.isPositive()
!t0Current.isPositive() ||
isInfussentBalance
);
}, [isEstimating, isSwapInProgress, amountsIn.error, t0Current]);
}, [
isEstimating,
isSwapInProgress,
amountsIn.error,
t0Current,
isInfussentBalance,
]);

const isApproveButtonDisabled = useMemo(() => {
return (
isApproveInProgress || !!amountsIn.error || !t0Current.isPositive()
isApproveInProgress ||
!!amountsIn.error ||
!t0Current.isPositive() ||
isInfussentBalance
);
}, [isApproveInProgress, amountsIn.error, t0Current]);
}, [isApproveInProgress, amountsIn.error, t0Current, isInfussentBalance]);

const rate = useMemo(() => {
const r =
Expand Down
Loading

0 comments on commit ec35327

Please sign in to comment.