Skip to content

Commit

Permalink
refactor: swap qa changes
Browse files Browse the repository at this point in the history
  • Loading branch information
fbwoolf committed Oct 6, 2023
1 parent 4db30df commit 8817459
Show file tree
Hide file tree
Showing 36 changed files with 318 additions and 238 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
"@noble/secp256k1": "2.0.0",
"@radix-ui/colors": "2.1.0",
"@radix-ui/react-accessible-icon": "1.0.3",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-switch": "1.0.3",
"@radix-ui/react-tabs": "1.0.4",
"@radix-ui/themes": "1.1.2",
Expand Down Expand Up @@ -168,7 +169,7 @@
"@typescript-eslint/eslint-plugin": "6.7.4",
"@vkontakte/vk-qr": "2.0.13",
"@zondax/ledger-stacks": "1.0.4",
"alex-sdk": "^0.1.22",
"alex-sdk": "0.1.22",
"are-passive-events-supported": "1.1.1",
"argon2-browser": "1.18.0",
"assert": "2.0.0",
Expand Down
2 changes: 1 addition & 1 deletion src/app/common/hooks/use-bitcoin-contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export function useBitcoinContracts() {
const txMoney = createMoneyFromDecimal(bitcoinValue, 'BTC');
const txFiatValue = i18nFormatCurrency(calculateFiatValue(txMoney)).toString();
const txFiatValueSymbol = bitcoinMarketData.price.symbol;
const txLink = { blockchain: 'bitcoin', txid: txId };
const txLink = { blockchain: 'bitcoin', txId };

return {
txId,
Expand Down
7 changes: 5 additions & 2 deletions src/app/common/math/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import BigNumber from 'bignumber.js';

export function initBigNumber(num: string | number | BigNumber) {
return BigNumber.isBigNumber(num) ? num : new BigNumber(num);
import { isBigInt } from '@shared/utils';

export function initBigNumber(num: string | number | BigNumber | bigint) {
if (BigNumber.isBigNumber(num)) return num;
return isBigInt(num) ? new BigNumber(num.toString()) : new BigNumber(num);
}

export function sumNumbers(nums: number[]) {
Expand Down
10 changes: 3 additions & 7 deletions src/app/common/money/calculate-money.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { BigNumber } from 'bignumber.js';

import { MarketData, formatMarketPair } from '@shared/models/market.model';
import { Money, NumType, createMoney } from '@shared/models/money.model';
import { isBigInt, isNumber } from '@shared/utils';
import { isNumber } from '@shared/utils';

import { sumNumbers } from '../math/helpers';
import { initBigNumber, sumNumbers } from '../math/helpers';
import { formatMoney } from './format-money';
import { isMoney } from './is-money';

Expand Down Expand Up @@ -36,11 +36,7 @@ export function convertToMoneyTypeWithDefaultOfZero(
num?: NumType,
decimals?: number
) {
return createMoney(
isBigInt(num) ? new BigNumber(num.toString()) : new BigNumber(num ?? 0),
symbol.toUpperCase(),
decimals
);
return createMoney(initBigNumber(num ?? 0), symbol.toUpperCase(), decimals);
}

// ts-unused-exports:disable-next-line
Expand Down
15 changes: 0 additions & 15 deletions src/app/components/icons/dot-icon.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/app/components/icons/swap-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function SwapIcon(props: React.SVGProps<SVGSVGElement>) {
<g clipPath="url(#clip0_5842_83269)">
<path
d="M1.94727 4.50229H13.2596M10.7086 7.59746L13.7987 4.50229L10.7086 1.41211M13.9934 11.4964H2.756M5.30702 8.4012L2.21185 11.4964L5.30702 14.5865"
stroke="#12100F"
stroke="currentColor"
strokeWidth="2"
strokeMiterlimit="10"
/>
Expand Down
2 changes: 1 addition & 1 deletion src/app/pages/rpc-sign-psbt/use-rpc-sign-psbt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export function useRpcSignPsbt() {
txId: txid,
txLink: {
blockchain: 'bitcoin',
txid: txid || '',
txId: txid || '',
},
txValue: formatMoney(transferTotalAsMoney),
};
Expand Down
29 changes: 7 additions & 22 deletions src/app/pages/swap/components/selected-asset-field.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import { Field } from 'formik';
import { Box, Flex, HStack, styled } from 'leather-styles/jsx';

import { Flag } from '@app/components/layout/flag';
import { Box, Flex, HStack } from 'leather-styles/jsx';

interface SelectedAssetFieldProps {
contentLeft: React.JSX.Element;
contentRight: React.JSX.Element;
icon?: string;

name: string;
}
export function SelectedAssetField({
contentLeft,
contentRight,
icon,
name,
}: SelectedAssetFieldProps) {
export function SelectedAssetField({ contentLeft, contentRight, name }: SelectedAssetFieldProps) {
return (
<Flex
alignItems="center"
Expand All @@ -29,18 +22,10 @@ export function SelectedAssetField({
>
<Box width="100%">
<Field as="div" name={name}>
<Flag
align="middle"
img={
icon ? <styled.img src={icon} width="24px" height="24px" alt="Swap asset" /> : null
}
spacing="tight"
>
<HStack alignItems="center" justifyContent="space-between">
{contentLeft}
{contentRight}
</HStack>
</Flag>
<HStack alignItems="center" justifyContent="space-between">
{contentLeft}
{contentRight}
</HStack>
</Field>
</Box>
</Flex>
Expand Down
67 changes: 39 additions & 28 deletions src/app/pages/swap/components/swap-amount-field.tsx
Original file line number Diff line number Diff line change
@@ -1,62 +1,73 @@
import { ChangeEvent } from 'react';

import { Input, Stack, color } from '@stacks/ui';
import { useField, useFormikContext } from 'formik';
import { Stack, styled } from 'leather-styles/jsx';

import { isDefined, isUndefined } from '@shared/utils';

import { useShowFieldError } from '@app/common/form-utils';
import { Caption } from '@app/components/typography';

import { SwapFormValues } from '../hooks/use-swap';
import { SwapFormValues } from '../hooks/use-swap-form';
import { useSwapContext } from '../swap.context';

function getPlaceholderValue(name: string, values: SwapFormValues) {
if (name === 'swapAmountFrom' && isDefined(values.swapAssetFrom)) return '0';
if (name === 'swapAmountTo' && isDefined(values.swapAssetTo)) return '0';
return '-';
}

interface SwapAmountFieldProps {
amountAsFiat: string;
isDisabled?: boolean;
name: string;
}
export function SwapAmountField({ amountAsFiat, isDisabled, name }: SwapAmountFieldProps) {
const { fetchToAmount } = useSwapContext();
const { setFieldValue, values } = useFormikContext<SwapFormValues>();
const { fetchToAmount, onSetIsSendingMax } = useSwapContext();
const { setErrors, setFieldValue, values } = useFormikContext<SwapFormValues>();
const [field] = useField(name);
const showError = useShowFieldError(name);
const showError = useShowFieldError(name) && name === 'swapAmountFrom' && values.swapAssetTo;

async function onChange(event: ChangeEvent<HTMLInputElement>) {
field.onChange(event);
const value = event.currentTarget.value;
const { swapAssetFrom, swapAssetTo } = values;
if (swapAssetFrom != null && swapAssetTo && !isNaN(Number(value))) {
await setFieldValue('swapAmountTo', '');
const toAmount = await fetchToAmount(swapAssetFrom, swapAssetTo, value);
await setFieldValue('swapAmountTo', toAmount);
}
if (isUndefined(swapAssetFrom) || isUndefined(swapAssetTo)) return;
onSetIsSendingMax(false);
const value = event.currentTarget.value;
const toAmount = await fetchToAmount(swapAssetFrom, swapAssetTo, value);
await setFieldValue('swapAmountTo', Number(toAmount));
field.onChange(event);
setErrors({});
}

return (
<Stack alignItems="flex-end" spacing="extra-tight" width="50%">
<Caption as="label" hidden htmlFor={name}>
<Stack alignItems="flex-end" gap="space.01" width="50%">
<styled.label hidden htmlFor={name}>
{name}
</Caption>
<Input
_disabled={{ border: 'none', color: color('text-caption') }}
_focus={{ border: 'none' }}
</styled.label>
<styled.input
_disabled={{
bg: 'transparent',
border: 'none',
color: 'accent.text-subdued',
}}
autoComplete="off"
border="none"
color={showError ? color('feedback-error') : 'unset'}
color={showError ? 'error' : 'accent.text-primary'}
display="block"
fontSize="20px"
height="28px"
isDisabled={isDisabled}
disabled={isDisabled}
p="0px"
placeholder="0"
placeholder={getPlaceholderValue(name, values)}
ring="none"
textAlign="right"
type="number"
textStyle="heading.05"
width="100%"
{...field}
onChange={onChange}
/>
<Caption color={showError ? color('feedback-error') : color('text-caption')}>
{amountAsFiat}
</Caption>
{amountAsFiat ? (
<styled.span color={showError ? 'error' : 'accent.text-subdued'} textStyle="caption.02">
{amountAsFiat}
</styled.span>
) : null}
</Stack>
);
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { useNavigate } from 'react-router-dom';

import { useFormikContext } from 'formik';

import { logger } from '@shared/logger';
import { RouteUrls } from '@shared/route-urls';
import { isUndefined } from '@shared/utils';

import { SwapFormValues } from '../../hooks/use-swap';
import { SwapFormValues } from '../../hooks/use-swap-form';
import { SwapAssetItemLayout } from './swap-asset-item.layout';
import { SwapAssetsPairLayout } from './swap-assets-pair.layout';

export function SwapAssetsPair() {
const { values } = useFormikContext<SwapFormValues>();
const { swapAmountFrom, swapAmountTo, swapAssetFrom, swapAssetTo } = values;
const navigate = useNavigate();

if (isUndefined(swapAssetFrom) || isUndefined(swapAssetTo)) {
logger.error('No asset selected to swap');
navigate(RouteUrls.Swap, { replace: true });
return null;
}

Expand Down
4 changes: 2 additions & 2 deletions src/app/pages/swap/components/swap-content.layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export function SwapContentLayout({ children }: HasChildren) {
flexDirection="column"
maxHeight={['calc(100vh - 116px)', 'calc(85vh - 116px)']}
overflowY="auto"
pb={['120px', '48px']}
pt={['space.04', '48px']}
pb={['60px', 'unset']}
pt="space.02"
px="space.05"
width="100%"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ export function SwapDetailLayout({ title, tooltipLabel, value }: SwapDetailLayou
return (
<HStack alignItems="center" justifyContent="space-between" ml="space.04" width="100%">
<HStack alignItems="center" gap="space.01">
<styled.span textStyle="caption.01">{title}</styled.span>
<styled.span textStyle="body.02">{title}</styled.span>
{tooltipLabel ? (
<Tooltip label={tooltipLabel} maxWidth="160px" placement="bottom">
<Box _hover={{ cursor: 'pointer' }} color="accent.text-subdued" ml="space.01">
<Box _hover={{ cursor: 'pointer' }} color="accent.text-subdued">
<InfoIcon />
</Box>
</Tooltip>
) : null}
</HStack>
<styled.span textStyle="label.01">{value}</styled.span>
<styled.span textStyle="label.02">{value}</styled.span>
</HStack>
);
}
26 changes: 10 additions & 16 deletions src/app/pages/swap/components/swap-details/swap-details.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { isUndefined } from '@shared/utils';

import { convertToMoneyTypeWithDefaultOfZero } from '@app/common/money/calculate-money';
import { formatMoney } from '@app/common/money/format-money';
import { getEstimatedConfirmationTime } from '@app/common/transactions/stacks/transaction.utils';
import { useSwapContext } from '@app/pages/swap/swap.context';
import { useStacksBlockTime } from '@app/query/stacks/info/info.hooks';
Expand All @@ -24,37 +22,33 @@ export function SwapDetails() {

return (
<SwapDetailsLayout>
<SwapDetailLayout title="Protocol" value={swapSubmissionData.protocol} />
<SwapDetailLayout
title="Route"
value={swapSubmissionData.router.map(x => x.name).join(' > ')}
/>
<SwapDetailLayout
title="Transaction fees"
value={formatMoney(
convertToMoneyTypeWithDefaultOfZero('STX', Number(swapSubmissionData.fee))
)}
/>
<SwapDetailLayout
title="Estimated confirmation time"
value={getEstimatedConfirmationTime(isTestnet, blockTime)}
title="Minimum Received"
value={`${Number(swapSubmissionData.swapAmountTo) * (1 - swapSubmissionData.slippage)} ${
swapSubmissionData.swapAssetTo.name
}`}
/>
<SwapDetailLayout
title="Slippage Tolerance"
value={`${swapSubmissionData.slippage * 100}%`}
/>
<SwapDetailLayout title="Protocol" value={swapSubmissionData.protocol} />
<SwapDetailLayout
title="Liquidity Provider Fee"
tooltipLabel="To receive a share of these fees, become a Liquidity Provider through 'Pool'"
value={`${swapSubmissionData.liquidityFee} ${swapSubmissionData.swapAssetFrom.name}`}
/>

{/* Alex transactions are sponsored */}
<SwapDetailLayout title="Transaction fees" value="Sponsored" />
<SwapDetailLayout
title="Minimum Received"
value={`${Number(swapSubmissionData.swapAmountTo) * (1 - swapSubmissionData.slippage)} ${
swapSubmissionData.swapAssetTo.name
}`}
title="Estimated confirmation time"
value={getEstimatedConfirmationTime(isTestnet, blockTime)}
/>
<SwapDetailLayout title="Nonce" value={swapSubmissionData.nonce?.toString() ?? 'Unknown'} />
</SwapDetailsLayout>
);
}
5 changes: 2 additions & 3 deletions src/app/pages/swap/components/swap-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@ import { noop } from '@shared/utils';

import { HasChildren } from '@app/common/has-children';

import { useSwap } from '../hooks/use-swap';
import { useSwapForm } from '../hooks/use-swap-form';

export function SwapForm({ children }: HasChildren) {
const { initialValues, validationSchema } = useSwap();
const { initialValues, validationSchema } = useSwapForm();

return (
<Formik
initialValues={initialValues}
onSubmit={noop}
validateOnChange={false}
validateOnMount={false}
validationSchema={validationSchema}
>
<Box width="100%">
Expand Down
Loading

0 comments on commit 8817459

Please sign in to comment.