Skip to content

Commit

Permalink
Merge pull request #393 from WatchItDev/app/refactor/quick-trasnsfer-…
Browse files Browse the repository at this point in the history
…amount

refactor: quick transfers handling and finance components
  • Loading branch information
geolffreym authored Jan 9, 2025
2 parents 1d3b494 + 0528930 commit e1b78fb
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 85 deletions.
2 changes: 1 addition & 1 deletion src/hooks/use-metamask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ export const useMetaMask = () => {
}
};

return { address, connecting, connect };
return { address, connecting, connect, setAddress };
};
4 changes: 2 additions & 2 deletions src/hooks/use-withdraw.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useState } from 'react';
import { useSelector } from 'react-redux';
import { encodeFunctionData, parseUnits } from 'viem';
import { Address, encodeFunctionData, parseUnits } from 'viem';
import LedgerVaultAbi from '@src/config/abi/LedgerVault.json';
import { GLOBAL_CONSTANTS } from '@src/config-global';
import { useWeb3Session } from '@src/hooks/use-web3-session.ts';
import { ERRORS } from '@notifications/errors.ts';

interface WithdrawParams {
recipient: string;
recipient: Address;
amount: number;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ interface FinanceDepositFromMetamaskProps {
const FinanceDepositFromMetamask: FC<FinanceDepositFromMetamaskProps> = ({ onClose }) => {
const sessionData = useSelector((state: any) => state.auth.session);
const depositHook = useDepositMetamask();
const { address, connecting, connect } = useMetaMask();
const { address, connecting, connect, setAddress } = useMetaMask();

if (connecting) return <FinanceMetamaskLoader />;
if (!address) return <FinanceMetamaskButton connect={connect} />;

return <FinanceDeposit address={address} recipient={sessionData?.address} depositHook={depositHook} onClose={onClose} />;
return <FinanceDeposit address={address} recipient={sessionData?.address} depositHook={depositHook} onClose={onClose} onChangeWallet={setAddress} />;
};

export default FinanceDepositFromMetamask;
10 changes: 8 additions & 2 deletions src/sections/finance/components/finance-deposit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ interface FinanceDepositProps {
* Callback for closing the modal / dialog.
*/
onClose: () => void;

/**
* Callback to change the new address.
*/
onChangeWallet?: (address: Address) => void;
}

/**
Expand All @@ -57,7 +62,7 @@ interface FinanceDepositProps {
* - `depositHook` (generic or Metamask deposit hook)
* - `onClose`
*/
const FinanceDeposit: FC<FinanceDepositProps> = ({ address, recipient, depositHook, onClose }) => {
const FinanceDeposit: FC<FinanceDepositProps> = ({ address, recipient, depositHook, onClose, onChangeWallet }) => {
const [amount, setAmount] = useState<number>();
const [helperText, setHelperText] = useState<string>("");
const { balance } = useGetMmcContractBalance(address);
Expand Down Expand Up @@ -152,7 +157,7 @@ const FinanceDeposit: FC<FinanceDepositProps> = ({ address, recipient, depositHo
sx={{ mt: 1 }}
fullWidth
autoFocus
label="Amount to withdraw"
label="Amount to deposit"
type="number"
value={amount}
onChange={handleAmountChange}
Expand All @@ -170,6 +175,7 @@ const FinanceDeposit: FC<FinanceDepositProps> = ({ address, recipient, depositHo
balance={balance ?? 0}
label={'Confirm'}
onConfirmAction={handleConfirmDeposit}
onChangeWallet={onChangeWallet}
onCloseAction={onClose}
/>
</>
Expand Down
40 changes: 25 additions & 15 deletions src/sections/finance/components/finance-quick-transfer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import Box from '@mui/material/Box';
import CardHeader from '@mui/material/CardHeader';
import { CardProps } from '@mui/material/Card';

// Project components
// LOCAL IMPORTS
import { useBoolean } from '@src/hooks/use-boolean';
import Carousel, { CarouselArrows, useCarousel } from '@src/components/carousel';
import NeonPaper from '@src/sections/publication/NeonPaperContainer.tsx';
Expand All @@ -35,7 +35,6 @@ import FinanceSearchProfileModal from '@src/sections/finance/components/finance-

const STEP = 50;
const MIN_AMOUNT = 0;
const AVATAR_SIZE = 40;

interface Props extends CardProps {
title?: string;
Expand Down Expand Up @@ -72,6 +71,7 @@ export default function FinanceQuickTransfer({
const [initialized, setInitialized] = useState(false);
const [list, setList] = useState<Profile[]>(initialList ?? []);
const [amount, setAmount] = useState(0);
const [canContinue, setCanContinue] = useState(true);

const confirm = useBoolean();
const MAX_AMOUNT = balance;
Expand Down Expand Up @@ -107,7 +107,6 @@ export default function FinanceQuickTransfer({
centerMode: true,
swipeToSlide: true,
infinite: true,
focusOnSelect: true,
centerPadding: '0px',
rows: 1,
slidesToShow: list?.length > 7 ? 7 : (list?.length ?? 1),
Expand Down Expand Up @@ -153,7 +152,7 @@ export default function FinanceQuickTransfer({
if (currentProfile?.ownedBy?.address) {
const profileId = currentProfile.id
const address = currentProfile.ownedBy.address;

setWalletAddress(address);
dispatch(storeAddress({ address, profileId }));
}
Expand Down Expand Up @@ -198,25 +197,31 @@ export default function FinanceQuickTransfer({
// Handle changes in the slider
const handleChangeSlider = useCallback((_event: Event, newValue: number | number[]) => {
setAmount(newValue as number);
}, []);
if(newValue < MAX_AMOUNT) {
setCanContinue(true);
}
}, [MAX_AMOUNT]);

// Handle changes in the input for the amount
const handleChangeInput = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
setAmount(Number(event.target.value));

// Send the focus back to the input field, this is a workaround for the slider carousel
setTimeout(() => {
event.target.focus();
}, 25);

if(Number(event.target.value) < MAX_AMOUNT) {
setCanContinue(true);
}else{
setCanContinue(false);
}
}, []);

// Validate the amount on blur
const handleBlur = useCallback(() => {
if(amount < MAX_AMOUNT) {
setCanContinue(true);
}

if (amount < 0) {
setAmount(0);
} else if (amount > MAX_AMOUNT) {
setAmount(MAX_AMOUNT);
setCanContinue(false);
}
}, [amount, MAX_AMOUNT]);

Expand All @@ -228,6 +233,11 @@ export default function FinanceQuickTransfer({
dispatch(storeAddress({ address: '', profileId: '' }));
};

// Handle onClick for carousel items
const handleCarouselClick = (index: number) => {
carousel.setCurrentIndex(index);
};

// If the stored address changes or if we typed a valid custom address, check if it exists in the carousel
useEffect(() => {
// Attempt to match the stored address + profileId
Expand Down Expand Up @@ -318,7 +328,7 @@ export default function FinanceQuickTransfer({
}}
>
{list?.map((profile, index) => (
<Box key={profile.id} sx={{ py: 2 }}>
<Box key={profile.id} sx={{ py: 2 }} onClick={ () => handleCarouselClick(index)}>
<Tooltip
key={profile.id}
title={profile?.metadata?.displayName}
Expand Down Expand Up @@ -368,7 +378,7 @@ export default function FinanceQuickTransfer({
/>

<Slider
color="secondary"
color={canContinue ? 'secondary' : 'warning'}
value={amount ?? 0}
valueLabelDisplay="auto"
step={STEP}
Expand All @@ -389,7 +399,7 @@ export default function FinanceQuickTransfer({
size="large"
color="inherit"
variant="contained"
disabled={amount === 0 || !isValidAddress(walletAddress)}
disabled={amount === 0 || !isValidAddress(walletAddress) || !canContinue}
onClick={confirm.onTrue}
>
Transfer Now
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,23 @@ import { FC } from 'react';

// LOCAL IMPORTS
import { useMetaMask } from '@src/hooks/use-metamask';
import { useWithdrawMetamask } from '@src/hooks/use-withdraw-metamask';
import { useGetVaultBalance } from '@src/hooks/use-get-vault-balance';
import FinanceWithdraw from '@src/sections/finance/components/finance-withdraw';
import FinanceMetamaskLoader from '@src/sections/finance/components/finance-metamask-loader.tsx';
import FinanceMetamaskButton from '@src/sections/finance/components/finance-metamask-button.tsx';
import { useWithdraw } from '@src/hooks/use-withdraw.ts';

interface FinanceWithdrawFromMetamaskProps {
onClose: () => void;
}

const FinanceWithdrawFromMetamask: FC<FinanceWithdrawFromMetamaskProps> = ({ onClose }) => {
const withdrawHook = useWithdrawMetamask();
const { address, connecting, connect } = useMetaMask();
const { balance } = useGetVaultBalance(address);
const withdrawHook = useWithdraw();
const { address, connecting, connect, setAddress } = useMetaMask();

if (connecting) return <FinanceMetamaskLoader />;
if (!address) return <FinanceMetamaskButton connect={connect} />;

return <FinanceWithdraw address={address} withdrawHook={withdrawHook} balance={balance} onClose={onClose} />;
return <FinanceWithdraw address={address} withdrawHook={withdrawHook} onClose={onClose} onChangeWallet={setAddress} />;
};

export default FinanceWithdrawFromMetamask;
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { FC } from 'react';
import { useWithdraw } from '@src/hooks/use-withdraw';
import { useGetBalance } from '@src/hooks/use-get-balance';
import { useSelector } from 'react-redux';
import FinanceWithdraw from './finance-withdraw';

Expand All @@ -11,14 +10,12 @@ interface FinanceWithdrawFromSmartAccountProps {
const FinanceWithdrawFromSmartAccount: FC<FinanceWithdrawFromSmartAccountProps> = ({ onClose }) => {
const sessionData = useSelector((state: any) => state.auth.session);
const userAddress = sessionData?.address;
const { balance } = useGetBalance();
const withdrawHook = useWithdraw();

return (
<FinanceWithdraw
address={userAddress}
withdrawHook={withdrawHook}
balance={balance}
onClose={onClose}
/>
);
Expand Down
64 changes: 10 additions & 54 deletions src/sections/finance/components/finance-withdraw.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// REACT IMPORTS
import { FC, useCallback, useEffect, useState } from 'react';

// VIEM IMPORTS
Expand All @@ -14,7 +15,6 @@ import FinanceDialogsActions from '@src/sections/finance/components/finance-dial
import TextMaxLine from '@src/components/text-max-line';
import { formatBalanceNumber } from '@src/utils/format-number';
import BoxRow from '@src/sections/finance/components/box-row';
import { isValidAddress } from '@src/sections/finance/components/finance-quick-transfer';
import { UseWithdrawHook } from '@src/hooks/use-withdraw.ts';
import { truncateAddress } from '@src/utils/wallet.ts';

Expand All @@ -23,25 +23,25 @@ import { notifyError, notifySuccess, notifyWarning } from '@notifications/intern
import { ERRORS } from '@notifications/errors';
import { WARNING } from '@notifications/warnings';
import { SUCCESS } from '@notifications/success';
import { useGetBalance } from '@src/hooks/use-get-balance.ts';

// ----------------------------------------------------------------------

interface FinanceWithdrawProps {
address?: Address; // The connected wallet address
address: Address; // The connected wallet address
withdrawHook: UseWithdrawHook; // Generic withdraw hook
balance: number | null; // Current user balance
onClose: () => void; // Callback to close the modal/dialog
onChangeWallet?: (address: Address) => void; // Callback to change the new address.
}

// ----------------------------------------------------------------------

const FinanceWithdraw: FC<FinanceWithdrawProps> = ({ address, withdrawHook, balance, onClose }) => {
const FinanceWithdraw: FC<FinanceWithdrawProps> = ({ address, withdrawHook, onClose, onChangeWallet }) => {
const [amount, setAmount] = useState<number>();
const [destinationAddress, setDestinationAddress] = useState('');
const [addressError, setAddressError] = useState(false);
const [amountError, setAmountError] = useState(false);
const [amountHelperText, setAmountHelperText] = useState(''); // Dynamic helper text for amount
const [amountHelperText, setAmountHelperText] = useState('');
const [localLoading, setLocalLoading] = useState(false);
const { balance } = useGetBalance();
const { withdraw, loading: withdrawLoading, error } = withdrawHook;
const RainbowEffect = localLoading || withdrawLoading ? NeonPaper : Box;

Expand All @@ -54,25 +54,21 @@ const FinanceWithdraw: FC<FinanceWithdrawProps> = ({ address, withdrawHook, bala
const handleConfirmWithdraw = useCallback(async () => {
if (!amount) return;

if (!destinationAddress || addressError) {
notifyWarning(WARNING.INVALID_WALLET_ADDRESS);
return;
}
if (amount <= 0 || amount > (balance ?? 0)) {
notifyWarning(WARNING.INVALID_WITHDRAW_AMOUNT);
return;
}
try {
setLocalLoading(true);
await withdraw({ amount, recipient: destinationAddress });
await withdraw({ amount, recipient: address });
notifySuccess(SUCCESS.WITHDRAW_SUCCESSFULLY);
onClose();
} catch (err: any) {
notifyError(ERRORS.WITHDRAW_FAILED_ERROR);
} finally {
setLocalLoading(false);
}
}, [amount, destinationAddress, balance, withdraw, addressError, onClose]);
}, [amount, balance]);

const handleAmountChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = Number(event.target.value);
Expand All @@ -90,12 +86,6 @@ const FinanceWithdraw: FC<FinanceWithdrawProps> = ({ address, withdrawHook, bala
setAmountHelperText(errorMessage);
};

const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.target.value;
setDestinationAddress(value);
setAddressError(!isValidAddress(value));
};

return (
<>
<Stack
Expand Down Expand Up @@ -137,41 +127,6 @@ const FinanceWithdraw: FC<FinanceWithdrawProps> = ({ address, withdrawHook, bala
error={amountError}
helperText={amountHelperText}
/>

<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
position: 'relative',
width: '100%',
my: 2
}}
>
<Box sx={{ background: 'rgba(255,255,255,0.1)', height: '1px', width: '100%' }} />
<Box sx={{
position: 'absolute',
left: 'calc(50% - 1.5rem)',
top: '-22px',
width: '3rem',
padding: '8px',
background: '#212b36',
textAlign: 'center',
color: 'text.secondary'
}}>
to
</Box>
</Box>

<TextField
fullWidth
label="Wallet Address"
value={destinationAddress}
onChange={handleInputChange}
placeholder="Enter wallet address"
error={addressError}
helperText={addressError ? 'Invalid wallet address' : ''}
/>
</Stack>

<FinanceDialogsActions
Expand All @@ -183,6 +138,7 @@ const FinanceWithdraw: FC<FinanceWithdrawProps> = ({ address, withdrawHook, bala
label={'Confirm'}
onConfirmAction={handleConfirmWithdraw}
onCloseAction={onClose}
onChangeWallet={onChangeWallet}
/>
</>
);
Expand Down

0 comments on commit e1b78fb

Please sign in to comment.