From a04b9cd4464a63e92c614e47db31b63a3a8cf063 Mon Sep 17 00:00:00 2001 From: asiaznik Date: Wed, 21 Jun 2023 15:51:45 +0200 Subject: [PATCH] feat(web3): ready to withdraw toast - fixed JsonRpcSigner ticking --- libs/web3/src/lib/use-bridge-contract.ts | 21 +- libs/web3/src/lib/use-get-withdraw-delay.ts | 1 - ...se-ready-to-complete-withdrawals-toast.tsx | 183 ++++++++++-------- 3 files changed, 116 insertions(+), 89 deletions(-) diff --git a/libs/web3/src/lib/use-bridge-contract.ts b/libs/web3/src/lib/use-bridge-contract.ts index acbf463ee..e626d0895 100644 --- a/libs/web3/src/lib/use-bridge-contract.ts +++ b/libs/web3/src/lib/use-bridge-contract.ts @@ -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) { diff --git a/libs/web3/src/lib/use-get-withdraw-delay.ts b/libs/web3/src/lib/use-get-withdraw-delay.ts index 4652d1fbd..da6758c5f 100644 --- a/libs/web3/src/lib/use-get-withdraw-delay.ts +++ b/libs/web3/src/lib/use-get-withdraw-delay.ts @@ -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; } diff --git a/libs/withdraws/src/lib/use-ready-to-complete-withdrawals-toast.tsx b/libs/withdraws/src/lib/use-ready-to-complete-withdrawals-toast.tsx index 1f1b0028a..f34e5ac26 100644 --- a/libs/withdraws/src/lib/use-ready-to-complete-withdrawals-toast.tsx +++ b/libs/withdraws/src/lib/use-ready-to-complete-withdrawals-toast.tsx @@ -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([]); + const [delayed, setDelayed] = useState([]); + 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 ? ( - - ) : ( - - ), - 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: ( - - ), - 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 ? ( + + ) : ( + + ), + 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: ( + + ), + 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, ]); };