feat(web3): ready to withdraw toast - fixed JsonRpcSigner ticking

This commit is contained in:
asiaznik
2023-06-21 15:51:45 +02:00
parent 2b0a91d435
commit a04b9cd446
3 changed files with 116 additions and 89 deletions
+14 -7
View File
@@ -11,13 +11,20 @@ export const useBridgeContract = (allowDefaultProvider = false) => {
const { config } = useEthereumConfig();
const logger = localLoggerFactory({ application: 'web3' });
let provider: typeof activeProvider | typeof defaultProvider = activeProvider;
let signer = activeProvider?.getSigner();
if (!activeProvider && allowDefaultProvider) {
logger.info('bridge contract will use default provider');
provider = defaultProvider;
signer = undefined;
}
const provider = useMemo(() => {
if (!activeProvider && allowDefaultProvider) {
logger.info('will use default web3 provider');
return defaultProvider;
}
return activeProvider;
}, [activeProvider, allowDefaultProvider, defaultProvider, logger]);
// this has to be memoized, otherwise it ticks like crazy
const signer = useMemo(() => {
return !activeProvider && allowDefaultProvider
? undefined
: activeProvider?.getSigner();
}, [activeProvider, allowDefaultProvider]);
const contract = useMemo(() => {
if (!provider || !config) {
@@ -23,7 +23,6 @@ export const useGetWithdrawDelay = () => {
const logger = localLoggerFactory({ application: 'web3' });
const getDelay = useCallback(async () => {
// return cached value if still valid
if (delay && Date.now() - delay.ts <= MAX_AGE) {
return delay.value;
}
@@ -8,7 +8,7 @@ import type { Toast } from '@vegaprotocol/ui-toolkit';
import { CLOSE_AFTER } from '@vegaprotocol/ui-toolkit';
import { Button, Intent, Panel, ToastHeading } from '@vegaprotocol/ui-toolkit';
import { useToasts } from '@vegaprotocol/ui-toolkit';
import { useCallback, useEffect } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { t } from '@vegaprotocol/i18n';
import { formatNumber, toBigNum } from '@vegaprotocol/utils';
import { useNavigate } from 'react-router-dom';
@@ -29,20 +29,19 @@ type UseReadyToWithdrawalToastsOptions = {
withdrawalsLink: string;
};
export const useReadyToWithdrawalToasts = ({
withdrawalsLink,
}: UseReadyToWithdrawalToastsOptions) => {
const [setToast, hasToast, updateToast, removeToast] = useToasts((store) => [
store.setToast,
store.hasToast,
store.update,
store.remove,
]);
type TimestampedWithdrawals = {
data: WithdrawalFieldsFragment;
timestamp: number | undefined;
}[];
export const useIncompleteWithdrawals = () => {
const [ready, setReady] = useState<TimestampedWithdrawals>([]);
const [delayed, setDelayed] = useState<TimestampedWithdrawals>([]);
const [thresholds, delay] = useWithdrawDataStore((state) => [
state.thresholds,
state.delay,
]);
const { pubKey, isReadOnly } = useVegaWallet();
const { data } = useDataProvider({
dataProvider: withdrawalProvider,
@@ -50,12 +49,20 @@ export const useReadyToWithdrawalToasts = ({
skip: !pubKey || isReadOnly,
});
const getDelay = useGetWithdrawDelay(); // seconds
const incompleteWithdrawals = data?.filter((w) => !w.txHash);
const assets = uniqBy(
incompleteWithdrawals?.map((w) => w.asset),
(a) => addr(a)
const incompleteWithdrawals = useMemo(
() => data?.filter((w) => !w.txHash),
[data]
);
const assets = useMemo(
() =>
uniqBy(
incompleteWithdrawals?.map((w) => w.asset),
(a) => addr(a)
),
[incompleteWithdrawals]
);
const getThreshold = useGetWithdrawThreshold();
const checkWithdraws = useCallback(async () => {
@@ -68,10 +75,6 @@ export const useReadyToWithdrawalToasts = ({
]);
}, [assets, getDelay, getThreshold]);
const onClose = useCallback(() => {
updateToast(ON_APP_START_TOAST_ID, { hidden: true });
}, [updateToast]);
useEffect(() => {
checkWithdraws().then((retrieved) => {
if (!retrieved || delay.value === undefined || !incompleteWithdrawals) {
@@ -79,7 +82,7 @@ export const useReadyToWithdrawalToasts = ({
}
const timestamped = incompleteWithdrawals.map((w) => {
let timestamp = undefined;
const threshold = thresholds[addr(w.asset)]; // { value: new BigNumber(0) };
const threshold = thresholds[addr(w.asset)];
if (threshold) {
timestamp = 0;
if (new BigNumber(w.amount).isGreaterThan(threshold.value)) {
@@ -97,75 +100,93 @@ export const useReadyToWithdrawalToasts = ({
(item) => item.timestamp != null && Date.now() < item.timestamp
);
const readyToComplete = timestamped?.filter(
const ready = timestamped?.filter(
(item) => item.timestamp != null && Date.now() >= item.timestamp
);
// set on app start toast if there are withdrawals ready to complete
if (readyToComplete && readyToComplete.length > 0) {
// set only once, unless removed
if (!hasToast(ON_APP_START_TOAST_ID)) {
const appStartToast: Toast = {
id: ON_APP_START_TOAST_ID,
intent: Intent.Warning,
content:
readyToComplete.length === 1 ? (
<SingleReadyToWithdrawToastContent
withdrawal={readyToComplete[0].data}
/>
) : (
<MultipleReadyToWithdrawToastContent
count={readyToComplete.length}
withdrawalsLink={withdrawalsLink}
/>
),
onClose,
};
setToast(appStartToast);
}
}
// set toast whenever a withdrawal delay is passed
let interval: NodeJS.Timer;
if (delayed && delayed.length > 0) {
interval = setInterval(() => {
const ready = delayed.filter(
(item) => item.timestamp && Date.now() >= item.timestamp
);
for (const withdrawal of ready) {
const id = `complete-withdrawal-${withdrawal.data.id}`;
const toast: Toast = {
id,
intent: Intent.Warning,
content: (
<SingleReadyToWithdrawToastContent
withdrawal={withdrawal.data}
/>
),
onClose: () => {
// updateToast(id, { hidden: true });
removeToast(id);
},
// closeAfter: CLOSE_AFTER,
};
if (!hasToast(id)) setToast(toast);
}
}, CHECK_INTERVAL);
}
return () => {
clearInterval(interval);
};
setReady(ready);
setDelayed(delayed);
});
}, [checkWithdraws, delay.value, incompleteWithdrawals, thresholds]);
return { ready, delayed };
};
export const useReadyToWithdrawalToasts = ({
withdrawalsLink,
}: UseReadyToWithdrawalToastsOptions) => {
const [setToast, hasToast, updateToast, removeToast] = useToasts((store) => [
store.setToast,
store.hasToast,
store.update,
store.remove,
]);
const { delayed, ready } = useIncompleteWithdrawals();
const onClose = useCallback(() => {
updateToast(ON_APP_START_TOAST_ID, { hidden: true });
}, [updateToast]);
useEffect(() => {
// set on app start toast if there are withdrawals ready to complete
if (ready.length > 0) {
// set only once, unless removed
if (!hasToast(ON_APP_START_TOAST_ID)) {
const appStartToast: Toast = {
id: ON_APP_START_TOAST_ID,
intent: Intent.Warning,
content:
ready.length === 1 ? (
<SingleReadyToWithdrawToastContent withdrawal={ready[0].data} />
) : (
<MultipleReadyToWithdrawToastContent
count={ready.length}
withdrawalsLink={withdrawalsLink}
/>
),
onClose,
};
setToast(appStartToast);
}
}
// set toast whenever a withdrawal delay is passed
let interval: NodeJS.Timer;
if (delayed.length > 0) {
interval = setInterval(() => {
const ready = delayed.filter(
(item) => item.timestamp && Date.now() >= item.timestamp
);
for (const withdrawal of ready) {
const id = `complete-withdrawal-${withdrawal.data.id}`;
const toast: Toast = {
id,
intent: Intent.Warning,
content: (
<SingleReadyToWithdrawToastContent withdrawal={withdrawal.data} />
),
onClose: () => {
// updateToast(id, { hidden: true });
removeToast(id);
},
// closeAfter: CLOSE_AFTER,
};
if (!hasToast(id)) setToast(toast);
}
}, CHECK_INTERVAL);
}
return () => {
clearInterval(interval);
};
}, [
checkWithdraws,
delay,
delayed,
hasToast,
incompleteWithdrawals,
onClose,
ready,
removeToast,
setToast,
thresholds,
withdrawalsLink,
]);
};