Skip to content

Commit

Permalink
feat: improve transaction fee selection with radio group
Browse files Browse the repository at this point in the history
  • Loading branch information
nelitow committed Feb 4, 2025
1 parent 2073308 commit 30033aa
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 20 deletions.
3 changes: 2 additions & 1 deletion packages/app/src/systems/Core/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,9 @@ export const styles = {
padding: '$0 $4 $4 $4',
flex: 1,
'&[data-scrollable=true]:not([data-noborder])': {
padding: '$0',
padding: '$0 $0 $4 $4',
...coreStyles.scrollable(),
overflowY: 'scroll !important',
},
'&[data-noborder]': {
padding: '$0',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const styles = {

'.fuel_Dialog-description': {
flex: 1,
overflowY: 'auto',
overflowY: 'auto !important',
height: '100%',
},
'.fuel_Dialog-heading': {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { Box, Card, HStack, RadioGroupItem, Text } from '@fuel-ui/react';
import { type BN, DEFAULT_PRECISION } from 'fuels';
import { type FC, useEffect, useMemo, useState } from 'react';

import { cssObj } from '@fuel-ui/css';
import type { AssetFuelData } from '@fuel-wallet/types';
import { AssetsCache } from '~/systems/Asset/cache/AssetsCache';
import { convertToUsd } from '~/systems/Core/utils/convertToUsd';
import { useProvider } from '~/systems/Network/hooks/useProvider';
import { formatTip } from '../TxFeeOptions/TxFeeOptions.utils';
import { TxFee } from './TxFee';
import { TxFeeLoader } from './TxFeeLoader';
import { styles } from './styles';

export type TxFeeRadioProps = {
fee?: BN;
checked?: boolean;
title: string;
};

type TxFeeRadioComponent = FC<TxFeeRadioProps>;

export const TxFeeRadio: TxFeeRadioComponent = ({
fee,
checked,
title,
}: TxFeeRadioProps) => {
const [_flag, setFlag] = useState(false);
const provider = useProvider();
const [baseAsset, setBaseAsset] = useState<AssetFuelData | undefined>();
useEffect(() => {
let abort = false;
const getBaseAsset = async () => {
const [baseAssetId, chainId] = await Promise.all([
provider?.getBaseAssetId(),
provider?.getChainId(),
]);
if (abort || baseAssetId == null || chainId == null) return;
const baseAsset = await AssetsCache.getInstance().getAsset({
chainId: chainId,
assetId: baseAssetId,
dbAssets: [],
save: false,
});
if (abort) return;
setBaseAsset(baseAsset);
};
getBaseAsset();
return () => {
abort = true;
};
}, [provider]);

const feeInUsd = useMemo(() => {
if (baseAsset?.rate == null || fee == null) return '$0';

return convertToUsd(fee, baseAsset.decimals, baseAsset.rate).formatted;
}, [baseAsset, fee]);

const ready = !!fee && !!feeInUsd;

// Horrible workaround to force re-render of this section.
useEffect(() => {
setTimeout(() => {
setFlag((prev) => !prev);
}, 500);
}, [ready]);

if (!ready) return <TxFee.Loader />;

return (
<Box.Flex key={title} css={styles.option}>
<RadioGroupItem
value={title}
checked={checked}
label={title}
labelCSS={styles.optionLabel}
/>

<Text css={styles.optionContent}>
{fee
? `${fee.format({
minPrecision: DEFAULT_PRECISION,
precision: DEFAULT_PRECISION,
})} ETH`
: '--'}
</Text>
</Box.Flex>
);
};

TxFee.Loader = TxFeeLoader;
25 changes: 25 additions & 0 deletions packages/app/src/systems/Transaction/components/TxFee/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,29 @@ export const styles = {
wordWrap: 'break-word',
minWidth: 0,
}),
option: cssObj({
alignItems: 'center',
backgroundColor: '$white',
border: '1px solid #e0e0e0',
borderRadius: '10px',
color: '#646464',
cursor: 'pointer',
fontSize: '13px',
gap: '$3',
justifyContent: 'space-between',
padding: '$3',
transition: 'all 0.2s ease',

'&:hover': {
backgroundColor: '#f0f0f0',
},
}),
optionContent: cssObj({
color: '#202020',
}),
optionLabel: cssObj({
color: '#202020',
fontSize: '13px',
fontWeight: '$medium',
}),
};
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import { cssObj } from '@fuel-ui/css';
import { Box, Button, Form, HStack, Input, Text, VStack } from '@fuel-ui/react';
import {
Box,
Button,
Form,
HStack,
Input,
RadioGroup,
RadioGroupItem,
Text,
VStack,
} from '@fuel-ui/react';
import { AnimatePresence } from 'framer-motion';
import { type BN, bn } from 'fuels';
import { type BN, DEFAULT_PRECISION, bn } from 'fuels';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useController, useFormContext } from 'react-hook-form';
import { MotionFlex, MotionStack, animations } from '~/systems/Core';
import { createAmount } from '~/systems/Core/components/InputAmount/InputAmount';
import { isAmountAllowed } from '~/systems/Core/components/InputAmount/InputAmount.utils';
import type { SendFormValues } from '~/systems/Send/hooks';
import { TxFee } from '../TxFee';
import { TxFeeRadio } from '../TxFee/TxFeeRadio';
import {
DECIMAL_UNITS,
formatTip,
Expand Down Expand Up @@ -178,22 +189,29 @@ export const TxFeeOptions = ({
</MotionStack>
) : (
<MotionStack {...animations.slideInTop()} key="regular" gap="$2">
{options.map((option) => (
<TxFee
key={option.name}
fee={option.fee}
title={option.name}
checked={option.tip.eq(tip.value.amount)}
onChecked={() => {
previousDefaultTip.current = option.tip;
setValue('fees.tip', {
amount: option.tip,
text: formatTip(option.tip),
});
onRecalculate?.(option.tip);
}}
/>
))}
<RadioGroup
value={options.find((o) => o.tip.eq(tip.value.amount))?.name}
onValueChange={(value) => {
const option = options.find((o) => o.name === value);
if (!option) return;

previousDefaultTip.current = option.tip;
setValue('fees.tip', {
amount: option.tip,
text: formatTip(option.tip),
});
onRecalculate?.(option.tip);
}}
>
{options.map((option) => (
<TxFeeRadio
key={option.name}
fee={option.fee}
title={option.name}
checked={option.tip.eq(tip.value.amount)}
/>
))}
</RadioGroup>
</MotionStack>
)}
<MotionFlex
Expand Down

0 comments on commit 30033aa

Please sign in to comment.