feat: show balance and allowance

This commit is contained in:
Matthew Russell
2023-10-26 10:19:52 -07:00
parent 846a3d259d
commit 4be4d089b4
2 changed files with 162 additions and 76 deletions
@@ -20,10 +20,9 @@ export const DepositGetStarted = () => {
);
// Dont show unless still onboarding
// TODO: re add
// if (onboardingDismissed) {
// return null;
// }
if (onboardingDismissed) {
return null;
}
return (
<div className={wrapperClasses}>
+159 -72
View File
@@ -18,6 +18,8 @@ import {
Loader,
TradingButton,
TradingInput,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import { useWeb3React } from '@web3-react/core';
import {
@@ -32,6 +34,7 @@ import { MaxUint256 } from '@ethersproject/constants';
import { useTopTradedMarkets } from '../../lib/hooks/use-top-traded-markets';
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/markets';
import { getAsset } from '@vegaprotocol/markets';
import { CompactNumber } from '@vegaprotocol/react-helpers';
export const Deposit = () => {
return (
@@ -78,6 +81,7 @@ interface DepositState {
asset: AssetFieldsFragment | undefined;
amount: string;
allowance: BigNumber | undefined;
balance: BigNumber | undefined;
}
const DepositFlow = ({
@@ -99,6 +103,7 @@ const DepositFlow = ({
asset,
amount: '',
allowance: undefined,
balance: undefined,
};
});
@@ -127,6 +132,7 @@ const DepositFlow = ({
step: DepositSteps.Asset,
asset: undefined,
allowance: undefined,
balance: undefined,
}));
return;
}
@@ -137,14 +143,25 @@ const DepositFlow = ({
// ethereum wallet connect fetch current allowance and bypass approval
// step if approval already given
let allowance = new BigNumber(0);
let balance = new BigNumber(0);
if (account) {
const signer = provider.getSigner();
const tokenContract = new Token(
asset.source.contractAddress,
signer || provider
);
const res = await tokenContract.allowance(account, bridgeAddress);
allowance = new BigNumber(addDecimal(res.toString(), asset.decimals));
const allowanceRes = await tokenContract.allowance(
account,
bridgeAddress
);
allowance = new BigNumber(
addDecimal(allowanceRes.toString(), asset.decimals)
);
const balanceRes = await tokenContract.balanceOf(account);
balance = new BigNumber(
addDecimal(balanceRes.toString(), asset.decimals)
);
}
const step = allowance.isGreaterThan(0)
@@ -156,6 +173,7 @@ const DepositFlow = ({
step,
asset,
allowance,
balance,
}));
};
@@ -168,6 +186,7 @@ const DepositFlow = ({
assets={assets}
onSelect={handleAssetChanged}
markets={markets}
balance={state.balance}
/>
</StepWrapper>
<StepWrapper>
@@ -184,18 +203,20 @@ const DepositFlow = ({
step={state.step}
asset={state.asset}
allowance={state.allowance}
balance={state.balance}
amount={state.amount}
setAmount={(amount) => setState((curr) => ({ ...curr, amount }))}
/>
</StepWrapper>
</div>
<pre className="fixed bottom-0 right-0 p-2 text-xs text-white bg-vega-pink">
{JSON.stringify(state, null, 2)}
</pre>
</>
);
};
// <pre className="fixed bottom-0 right-0 p-2 text-xs text-white bg-vega-pink">
// {JSON.stringify(state, null, 2)}
// </pre>
const StepWrapper = ({ children }: { children: ReactNode }) => {
return (
<div className="flex flex-col items-start p-4 border-b rounded gap-3 last:border-b-0 border-default">
@@ -209,11 +230,13 @@ const AssetSelector = ({
assets,
onSelect,
markets,
balance,
}: {
asset?: AssetFieldsFragment;
assets: AssetFieldsFragment[];
onSelect: (asset?: AssetFieldsFragment) => void;
markets: MarketMaybeWithDataAndCandles[];
balance: BigNumber | undefined;
}) => {
const [search, setSearch] = useState('');
const getTopMarkets = (a: AssetFieldsFragment) => {
@@ -228,24 +251,32 @@ const AssetSelector = ({
if (asset && isAssetTypeERC20(asset)) {
return (
<div className="flex flex-col w-full gap-2">
<div className="flex items-center gap-2">
<div className="flex gap-2">
<button
onClick={() => onSelect(undefined)}
className="w-5 h-5 border-2 rounded border-vega-clight-600"
className="flex items-center w-5 h-5 border-2 rounded border-vega-clight-600"
>
<div className="block w-4 h-4 border-2 border-white bg-vega-clight-300" />
<VegaIcon name={VegaIconNames.TICK} />
</button>
<div className="flex flex-1 gap-2">
<div className="flex-1">
<p className="block text-lg">
<div className="flex flex-col flex-1 gap-1">
<p className="text-lg">
{asset.symbol}{' '}
<small>({truncateByChars(asset.source.contractAddress)})</small>
<small>{truncateByChars(asset.source.contractAddress)}</small>
</p>
<Markets markets={getTopMarkets(asset)} />
</div>
<TradingButton onClick={() => onSelect(undefined)} size="small">
Change asset
</TradingButton>
<div className="flex flex-col items-end">
{balance && (
<div className="font-mono text-lg">
{balance.toString()}
<small className="ml-1 text-muted">{asset.symbol}</small>
</div>
)}
<TradingButton onClick={() => onSelect(undefined)} size="small">
Change asset
</TradingButton>
</div>
</div>
</div>
</div>
@@ -284,7 +315,7 @@ const AssetSelector = ({
if (!isAssetTypeERC20(asset)) return null;
return (
<div key={asset.id}>
<div className="flex items-center gap-3">
<div className="flex gap-3">
<Radio.Item
id={asset.id}
value={asset.id}
@@ -292,7 +323,7 @@ const AssetSelector = ({
>
<Radio.Indicator className="block w-4 h-4 border-2 border-white bg-vega-clight-300" />
</Radio.Item>
<div className="flex-1">
<div className="flex flex-col flex-1 gap-1">
<label
htmlFor={asset.id}
className="block text-lg cursor-pointer"
@@ -357,43 +388,18 @@ const Approval = ({
}
}, [tx?.status, asset, onApproved]);
// No asset selected, show generic approval title
if (!asset) {
return <h3 className="text-lg">Approval</h3>;
}
if (tx) {
let title = t('Approval');
if (tx.status === EthTxStatus.Confirmed) {
title = t('Approved');
} else if (tx.status === EthTxStatus.Pending) {
title = t('Waiting for approval...');
}
return (
<div className="flex items-center justify-between w-full">
<h3 className="text-lg">{title}</h3>
<TradingButton onClick={handleApprove} size="small">
{t('Re-approve')}
</TradingButton>
<div className="flex gap-2">
<div className="flex items-center w-5 h-5 border-2 rounded border-vega-clight-600" />
<h3 className="text-lg">{t('Approval')}</h3>
</div>
</div>
);
}
if (step !== DepositSteps.Approve) {
if (!allowance) {
return <h3 className="text-lg">Approval</h3>;
}
if (allowance.isGreaterThan(0)) {
return (
<div className="flex items-center justify-between w-full">
<h3 className="text-lg">{t('Approved')}</h3>
<TradingButton onClick={handleApprove} size="small">
{t('Re-approve')}
</TradingButton>
</div>
);
}
}
if (!account) {
return (
<div className="flex items-center justify-between w-full">
@@ -405,13 +411,52 @@ const Approval = ({
);
}
if (!allowance) {
return <h3 className="text-lg">Loading balances...</h3>;
if (tx && tx.status === EthTxStatus.Pending) {
return (
<div className="flex items-center justify-between w-full">
<div className="flex items-center gap-2">
<Loader size="small" />
<h3 className="text-lg">{t('Waiting for approval...')}</h3>
</div>
<TradingButton onClick={handleApprove} size="small">
{t('Re-approve')}
</TradingButton>
</div>
);
}
// APPROVED: show muted re-approve button
if (!allowance || allowance.isGreaterThan(0)) {
return (
<div className="flex items-center justify-between w-full">
<div className="flex gap-2">
<div className="flex items-center w-5 h-5 border-2 rounded border-vega-clight-600">
<VegaIcon name={VegaIconNames.TICK} />
</div>
<h3 className="text-lg">{t('Approved')}</h3>
</div>
<div className="flex flex-col items-end">
{allowance && (
<div className="font-mono text-lg">
<Allowance allowance={allowance} />
<small className="ml-1 text-muted">{asset.symbol}</small>
</div>
)}
<TradingButton onClick={handleApprove} size="small">
{t('Re-approve')}
</TradingButton>
</div>
</div>
);
}
// NOT APPROVED: show primary approve button
return (
<div className="flex items-center justify-between w-full">
<h3 className="text-lg">{t('Deposits not approved')}</h3>
<div className="flex gap-2">
<div className="flex items-center w-5 h-5 border-2 rounded border-vega-clight-600" />
<h3 className="text-lg">{t('Approve deposits')}</h3>
</div>
<TradingButton
onClick={() => {
if (!provider) throw new Error('no provider');
@@ -436,35 +481,67 @@ const Approval = ({
);
};
const Allowance = ({ allowance }: { allowance: BigNumber }) => {
let value = '';
const format = (divisor: string) => {
const result = allowance.dividedBy(divisor);
return result.isInteger() ? result.toString() : result.toFixed(1);
};
if (allowance.isGreaterThan(new BigNumber('1e14'))) {
value = t('>100t');
} else if (allowance.isGreaterThanOrEqualTo(new BigNumber('1e12'))) {
// Trillion
value = `${format('1e12')}t`;
} else if (allowance.isGreaterThanOrEqualTo(new BigNumber('1e9'))) {
// Billion
value = `${format('1e9')}b`;
} else if (allowance.isGreaterThanOrEqualTo(new BigNumber('1e6'))) {
// Million
value = `${format('1e6')}m`;
} else {
value = allowance.toString();
}
return <span>{value}</span>;
};
const SendDeposit = ({
step,
asset,
allowance,
balance,
amount,
setAmount,
}: {
step: Step;
asset: AssetFieldsFragment | undefined;
allowance: BigNumber | undefined;
balance: BigNumber | undefined;
amount: string;
setAmount: (amount: string) => void;
}) => {
const openDialog = useWeb3ConnectStore((store) => store.open);
const { account } = useWeb3React();
const fallback = (
<div className="flex gap-2">
<div className="flex items-center w-5 h-5 border-2 rounded border-vega-clight-600" />
<h3 className="text-lg">{t('Deposit')}</h3>
</div>
);
if (step !== DepositSteps.Deposit) {
return <h3 className="text-lg">Confirm deposit</h3>;
return fallback;
}
if (!asset) {
return <p>Please select asset</p>;
return fallback;
}
if (!allowance) {
return <h3 className="text-lg">Confirm deposit</h3>;
}
if (allowance.isZero()) {
return <h3 className="text-lg">Deposits not approved</h3>;
if (!allowance || allowance.isZero()) {
return fallback;
}
if (!account) {
@@ -477,23 +554,33 @@ const SendDeposit = ({
return (
<div className="flex items-center justify-between w-full">
<h3 className="text-lg">{t('Confirm deposit')}</h3>
<form
className="flex items-center justify-between w-1/2 gap-2"
onSubmit={() => alert('TODO')}
>
<div className="flex-1">
<TradingInput
name="amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="Enter amount"
className="w-full"
/>
<div className="flex gap-2">
<div className="flex items-center w-5 h-5 border-2 rounded border-vega-clight-600" />
<h3 className="text-lg">{t('Deposit')}</h3>
</div>
<form className="w-1/2" onSubmit={() => alert('TODO')}>
<div className="flex items-center justify-between gap-2">
<div className="flex-1">
<TradingInput
name="amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="Enter amount"
className="w-full"
/>
</div>
{balance && (
<TradingButton
size="small"
onClick={() => setAmount(balance.toString())}
>
{t('Use max')}
</TradingButton>
)}
<TradingButton type="submit" size="small" intent={Intent.Success}>
{t('Deposit %s', asset.symbol)}
</TradingButton>
</div>
<TradingButton type="submit" size="small" intent={Intent.Success}>
{t('Deposit %s', asset.symbol)}
</TradingButton>
</form>
</div>
);