Skip to content

Commit

Permalink
feat: Add decimal accuracy to withdraw, use new loading, success & er…
Browse files Browse the repository at this point in the history
…ror dialogs.
  • Loading branch information
kovipu committed Feb 11, 2025
1 parent f889815 commit 20eecd8
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 73 deletions.
72 changes: 17 additions & 55 deletions src/components/AssetsModal/AssetsModal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Success } from '@components/Alert';
import { CircleButton } from '@components/Button';
import type { SupportedCurrency } from 'currencies';
import { isNil } from 'ramda';
import { useState } from 'react';
import { IoClose as CloseIcon } from 'react-icons/io5';

import { Dialog } from '@components/Dialog';
import { useWallet } from '@contexts/wallet-context';
import type { SupportedCurrency } from 'currencies';
import PositionsView from './PositionsView';
import WithdrawView from './WithdrawView';

Expand All @@ -12,72 +12,34 @@ export type AssetsModalProps = {
onClose: () => void;
};

type WithdrawAlert = {
kind: 'success';
ticker: SupportedCurrency;
amount: string;
};

const AssetsModal = ({ modalId, onClose }: AssetsModalProps) => {
const [tickerToWithdraw, setTickerToWithdraw] = useState<SupportedCurrency | null>(null);
const [alert, setAlert] = useState<WithdrawAlert | null>(null);
const { refetchBalances } = useWallet();

const handleBackClicked = () => setTickerToWithdraw(null);
const [tickerToWithdraw, setTickerToWithdraw] = useState<SupportedCurrency | null>(null);

const handleClose = () => {
const handleBackClicked = () => {
refetchBalances();
setTickerToWithdraw(null);
setAlert(null);
onClose();
};

const handleWithdrawSuccess = (ticker: SupportedCurrency, amount: string) => {
const handleClose = () => {
setTickerToWithdraw(null);
setAlert({ kind: 'success', ticker, amount });
};

const handleAlertClose = () => {
setAlert(null);
onClose();
};

const handleWithdraw = (ticker: SupportedCurrency) => {
setAlert(null);
setTickerToWithdraw(ticker);
};

return (
<dialog id={modalId} className="modal">
<div className="modal-box w-full max-w-full md:w-[800px] p-10 flex flex-col">
{alert ? <WithdrawSuccessAlert onClose={handleAlertClose} ticker={alert.ticker} amount={alert.amount} /> : null}
{isNil(tickerToWithdraw) ? (
<PositionsView onClose={handleClose} onWithdraw={handleWithdraw} />
) : (
<WithdrawView ticker={tickerToWithdraw} onBack={handleBackClicked} onSuccess={handleWithdrawSuccess} />
)}
</div>
<form method="dialog" className="modal-backdrop">
<button type="button" onClick={handleClose}>
close
</button>
</form>
</dialog>
<Dialog modalId={modalId} onClose={onClose}>
{isNil(tickerToWithdraw) ? (
<PositionsView onClose={handleClose} onWithdraw={handleWithdraw} />
) : (
<WithdrawView ticker={tickerToWithdraw} onBack={handleBackClicked} />
)}
</Dialog>
);
};

type WithdrawSuccessAlertProps = {
ticker: SupportedCurrency;
amount: string;
onClose: () => void;
};

const WithdrawSuccessAlert = ({ ticker, amount, onClose }: WithdrawSuccessAlertProps) => (
<Success className="mb-8">
<span>
Successfully withdrew {amount} {ticker}
</span>
<CircleButton onClick={onClose} variant="ghost-dark">
<CloseIcon size="1.4rem" />
</CircleButton>
</Success>
);

export default AssetsModal;
4 changes: 2 additions & 2 deletions src/components/AssetsModal/PositionsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface PositionsViewProps {
const PositionsView = ({ onClose, onWithdraw }: PositionsViewProps) => {
const { positions } = useWallet();
return (
<>
<div className="md:w-[700px]">
<h3 className="text-xl font-bold tracking-tight mb-8">My Assets</h3>
<table className="table">
<thead className="text-base text-grey">
Expand Down Expand Up @@ -42,7 +42,7 @@ const PositionsView = ({ onClose, onWithdraw }: PositionsViewProps) => {
Close
</Button>
</div>
</>
</div>
);
};

Expand Down
60 changes: 44 additions & 16 deletions src/components/AssetsModal/WithdrawView.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
import { Button } from '@components/Button';
import { CryptoAmountSelector } from '@components/CryptoAmountSelector';
import { ErrorDialogContent, LoadingDialogContent, SuccessDialogContent } from '@components/Dialog';
import { Loading } from '@components/Loading';
import { usePools } from '@contexts/pool-context';
import { useWallet } from '@contexts/wallet-context';
import { stroopsToDecimalString } from '@lib/converters';
import { SCALAR_7, toCents } from '@lib/formatting';
import type { SupportedCurrency } from 'currencies';
import { type ChangeEvent, useState } from 'react';
import { useState } from 'react';
import { CURRENCY_BINDINGS } from 'src/currency-bindings';

export interface WithdrawViewProps {
ticker: SupportedCurrency;
onBack: () => void;
onSuccess: (ticker: SupportedCurrency, amount: string) => void;
}

const WithdrawView = ({ ticker, onBack, onSuccess }: WithdrawViewProps) => {
const WithdrawView = ({ ticker, onBack }: WithdrawViewProps) => {
const { name, contractClient } = CURRENCY_BINDINGS[ticker];
const { positions, wallet, signTransaction } = useWallet();
const { pools, prices } = usePools();
const [amount, setAmount] = useState('0');
const [amount, setAmount] = useState(0n);
const [isWithdrawing, setIsWithdrawing] = useState(false);
const [isSuccess, setIsSuccess] = useState(false);
const [error, setError] = useState<Error | null>(null);

const pool = pools?.[ticker];
const price = prices?.[ticker];
Expand All @@ -39,41 +42,66 @@ const WithdrawView = ({ ticker, onBack, onSuccess }: WithdrawViewProps) => {

const totalBalance = (receivable_shares * pool.totalBalanceTokens) / pool.totalBalanceShares;

const max = (totalBalance / SCALAR_7).toString();

const handleAmountChange = (ev: ChangeEvent<HTMLInputElement>) => {
setAmount(ev.target.value);
const handleAmountChange = (stroops: bigint) => {
setAmount(stroops);
};

const handleSelectMax = () => {
setAmount(max);
setAmount(totalBalance);
};

const isWithdrawDisabled = amount === 0n || amount > totalBalance;

const handleWithdrawClick = async () => {
if (!wallet) return;

setIsWithdrawing(true);

const tx = await contractClient.withdraw({
user: wallet.address,
amount: BigInt(amount) * SCALAR_7,
amount,
});
try {
await tx.signAndSend({ signTransaction });
onSuccess(ticker, amount);
setIsSuccess(true);
} catch (err) {
console.error('Error withdrawing', err);
alert('Error withdrawing');
setError(err as Error);
}
setIsWithdrawing(false);
};

if (isWithdrawing) {
return (
<LoadingDialogContent
title="Withdrawing"
subtitle={`Withdrawing ${stroopsToDecimalString(amount)} ${ticker}.`}
buttonText="Back"
onClick={onBack}
/>
);
}

if (isSuccess) {
return (
<SuccessDialogContent
subtitle={`Successfully withdrew ${stroopsToDecimalString(amount)} ${ticker}`}
buttonText="Back"
onClick={onBack}
/>
);
}

if (error) {
return <ErrorDialogContent error={error} onClick={onBack} />;
}

return (
<>
<div className="md:w-[700px]">
<h3 className="text-xl font-bold tracking-tight mb-8">Withdraw {name}</h3>
<p className="text-lg mb-2">Select the amount to withdraw</p>
<CryptoAmountSelector
max={max}
max={totalBalance}
value={amount}
valueCents={valueCents}
ticker={ticker}
Expand All @@ -85,7 +113,7 @@ const WithdrawView = ({ ticker, onBack, onSuccess }: WithdrawViewProps) => {
Back
</Button>
{!isWithdrawing ? (
<Button disabled={amount === '0'} onClick={handleWithdrawClick}>
<Button disabled={isWithdrawDisabled} onClick={handleWithdrawClick}>
Withdraw
</Button>
) : (
Expand All @@ -95,7 +123,7 @@ const WithdrawView = ({ ticker, onBack, onSuccess }: WithdrawViewProps) => {
</Button>
)}
</div>
</>
</div>
);
};

Expand Down

0 comments on commit 20eecd8

Please sign in to comment.