import { useEffect, useRef, useState } from 'react'; import type { AgGridReact } from 'ag-grid-react'; import { AgGridColumn } from 'ag-grid-react'; import { addDecimalsFormatNumber, convertToCountdownString, getDateTimeFormat, isNumeric, truncateByChars, } from '@vegaprotocol/utils'; import { t } from '@vegaprotocol/i18n'; import { ButtonLink, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, VegaIcon, VegaIconNames, } from '@vegaprotocol/ui-toolkit'; import type { TypedDataAgGrid, VegaICellRendererParams, VegaValueFormatterParams, } from '@vegaprotocol/datagrid'; import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid'; import { EtherscanLink } from '@vegaprotocol/environment'; import type { WithdrawalFieldsFragment } from './__generated__/Withdrawal'; import { useEthWithdrawApprovalsStore, useWithdrawalApprovalDialog, } from '@vegaprotocol/web3'; import * as Schema from '@vegaprotocol/types'; import type { TimestampedWithdrawals } from './use-ready-to-complete-withdrawals-toast'; import classNames from 'classnames'; export const WithdrawalsTable = ( props: TypedDataAgGrid & { ready?: TimestampedWithdrawals; delayed?: TimestampedWithdrawals; } ) => { const gridRef = useRef(null); const createWithdrawApproval = useEthWithdrawApprovalsStore( (store) => store.create ); return ( ) => { return isNumeric(value) && data?.asset ? addDecimalsFormatNumber(value, data.asset.decimals) : ''; }} /> ) => { if (!data) return null; if (!value) return '-'; return truncateByChars(value); }} /> ) => data ? value ? getDateTimeFormat().format(new Date(value)) : '-' : null } /> ) => data ? value ? getDateTimeFormat().format(new Date(value)) : '-' : null } /> { createWithdrawApproval(withdrawal); }, }} cellRendererSelector={({ data, }: VegaICellRendererParams) => ({ component: data?.txHash ? 'EtherscanLinkCell' : 'CompleteCell', })} /> ); }; export type CompleteCellProps = { data: WithdrawalFieldsFragment; complete: (withdrawal: WithdrawalFieldsFragment) => void; }; export const CompleteCell = ({ data, complete }: CompleteCellProps) => { const open = useWithdrawalApprovalDialog((state) => state.open); const ref = useRef(null); if (!data) { return null; } return data.pendingOnForeignChain ? ( '-' ) : (
complete(data)} > {t('Complete withdrawal')} } > { if (data.id) { open(data.id, ref.current, false); } }} > {t('View withdrawal details')}
); }; export const EtherscanLinkCell = ({ value, }: VegaValueFormatterParams) => { if (!value) return '-'; return ( {truncateByChars(value)} ); }; export const StatusCell = ({ data, ready, delayed, }: { data: WithdrawalFieldsFragment; ready?: TimestampedWithdrawals; delayed?: TimestampedWithdrawals; }) => { const READY_TO_COMPLETE = t('Ready to complete'); const DELAYED = (readyIn: string) => t('Delayed (ready in %s)', readyIn); const PENDING = t('Pending'); const COMPLETED = t('Completed'); const REJECTED = t('Rejected'); const FAILED = t('Failed'); const isPending = data.pendingOnForeignChain || !data.txHash; const isReady = ready?.find((w) => w.data.id === data.id); const isDelayed = delayed?.find((w) => w.data.id === data.id); const determineLabel = () => { if (isPending) { if (isReady) { return READY_TO_COMPLETE; } return PENDING; } if (data.status === Schema.WithdrawalStatus.STATUS_FINALIZED) { return COMPLETED; } if (data.status === Schema.WithdrawalStatus.STATUS_REJECTED) { return REJECTED; } return FAILED; }; const [label, setLabel] = useState(determineLabel()); useEffect(() => { // handle countdown for delayed withdrawals let interval: NodeJS.Timer; if (!data || !isDelayed || isDelayed.timestamp == null || !isPending) { return; } // eslint-disable-next-line prefer-const interval = setInterval(() => { if (isDelayed.timestamp == null) return; const remaining = Date.now() - isDelayed.timestamp; if (remaining < 0) { setLabel(DELAYED(convertToCountdownString(remaining, '0:00:00:00'))); } else { setLabel(READY_TO_COMPLETE); } }, 1000); return () => { clearInterval(interval); }; }, [READY_TO_COMPLETE, data, delayed, isDelayed, isPending]); return data ? ( {label} ) : null; }; const RecipientCell = ({ value, valueFormatted, }: VegaICellRendererParams< WithdrawalFieldsFragment, 'details.receiverAddress' >) => { return ( {valueFormatted} ); };