From ff5ac3602b840af2b04b393aed8a64f0f58257c5 Mon Sep 17 00:00:00 2001 From: 0age <37939117+0age@users.noreply.github.com> Date: Mon, 9 Dec 2024 23:30:56 -0800 Subject: [PATCH] show finalization thresholds on FE --- frontend/src/components/BalanceDisplay.tsx | 25 ++++----- .../src/components/FinalizationThreshold.tsx | 18 +++++++ frontend/src/hooks/useAllocatorAPI.ts | 7 +++ .../src/hooks/useFinalizationThreshold.ts | 52 +++++++++++++++++++ 4 files changed, 87 insertions(+), 15 deletions(-) create mode 100644 frontend/src/components/FinalizationThreshold.tsx create mode 100644 frontend/src/hooks/useFinalizationThreshold.ts diff --git a/frontend/src/components/BalanceDisplay.tsx b/frontend/src/components/BalanceDisplay.tsx index 4de9fc4..33b782f 100644 --- a/frontend/src/components/BalanceDisplay.tsx +++ b/frontend/src/components/BalanceDisplay.tsx @@ -2,12 +2,14 @@ import { useState, useEffect, useCallback, useMemo } from 'react'; import { useAccount, useChainId } from 'wagmi'; import { useBalances } from '../hooks/useBalances'; import { useResourceLocks } from '../hooks/useResourceLocks'; +import { useFinalizationThreshold } from '../hooks/useFinalizationThreshold'; import { formatUnits } from 'viem'; import { Transfer } from './Transfer'; import { InitiateForcedWithdrawalDialog } from './InitiateForcedWithdrawalDialog'; import { ForcedWithdrawalDialog } from './ForcedWithdrawalDialog'; import { useCompact } from '../hooks/useCompact'; import { useNotification } from '../hooks/useNotification'; +import { FinalizationThreshold } from './FinalizationThreshold'; interface BalanceDisplayProps { sessionToken: string | null; @@ -49,7 +51,7 @@ function formatTimeRemaining( return `${seconds}s`; } -const formatResetPeriod = (seconds: number): string => { +export const formatResetPeriod = (seconds: number): string => { if (seconds < 60) return `${seconds} seconds`; if (seconds < 3600) return `${Math.floor(seconds / 60)} minutes`; if (seconds < 86400) return `${Math.floor(seconds / 3600)} hours`; @@ -444,27 +446,20 @@ export function BalanceDisplay({ {balance.resourceLock?.resetPeriod && balance.resourceLock.resetPeriod > 0 && ( - Reset Period: {balance.resetPeriodFormatted} + Reset Period: {formatResetPeriod(balance.resourceLock.resetPeriod)} )} + {balance.resourceLock?.isMultichain && ( Multichain )} - - {balance.withdrawalStatus === 0 - ? 'Active' - : withdrawableAt <= currentTime - ? 'Forced Withdrawals Enabled' - : `Forced Withdrawals Enabled in ${formatTimeRemaining(withdrawableAt, currentTime)}`} - + {balance.withdrawalStatus === 0 && ( + + Active + + )} {/* Balances Grid */} diff --git a/frontend/src/components/FinalizationThreshold.tsx b/frontend/src/components/FinalizationThreshold.tsx new file mode 100644 index 0000000..34d52d5 --- /dev/null +++ b/frontend/src/components/FinalizationThreshold.tsx @@ -0,0 +1,18 @@ +import { useFinalizationThreshold } from '../hooks/useFinalizationThreshold'; +import { formatResetPeriod } from './BalanceDisplay'; + +interface FinalizationThresholdProps { + chainId: number; +} + +export function FinalizationThreshold({ chainId }: FinalizationThresholdProps) { + const { finalizationThreshold } = useFinalizationThreshold(chainId); + + if (finalizationThreshold === null) return null; + + return ( + + Finalization: {formatResetPeriod(finalizationThreshold)} + + ); +} diff --git a/frontend/src/hooks/useAllocatorAPI.ts b/frontend/src/hooks/useAllocatorAPI.ts index c3df9fa..a75f94f 100644 --- a/frontend/src/hooks/useAllocatorAPI.ts +++ b/frontend/src/hooks/useAllocatorAPI.ts @@ -5,6 +5,13 @@ interface HealthCheckResponse { allocatorAddress: string; signingAddress: string; timestamp: string; + chainConfig: { + defaultFinalizationThresholdSeconds: number; + supportedChains: Array<{ + chainId: string; + finalizationThresholdSeconds: number; + }>; + }; } interface CompactRequest { diff --git a/frontend/src/hooks/useFinalizationThreshold.ts b/frontend/src/hooks/useFinalizationThreshold.ts new file mode 100644 index 0000000..16ac060 --- /dev/null +++ b/frontend/src/hooks/useFinalizationThreshold.ts @@ -0,0 +1,52 @@ +import { useState, useEffect } from 'react'; + +interface ChainConfig { + defaultFinalizationThresholdSeconds: number; + supportedChains: Array<{ + chainId: string; + finalizationThresholdSeconds: number; + }>; +} + +export function useFinalizationThreshold(chainId: number) { + const [finalizationThreshold, setFinalizationThreshold] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchFinalizationThreshold = async () => { + try { + const response = await fetch('/health'); + if (!response.ok) { + throw new Error('Failed to fetch chain configuration'); + } + const data = await response.json(); + const chainConfig: ChainConfig = data.chainConfig; + + // Find the chain-specific threshold or use default + const chainSpecific = chainConfig.supportedChains.find( + chain => chain.chainId === chainId.toString() + ); + + setFinalizationThreshold( + chainSpecific?.finalizationThresholdSeconds ?? + chainConfig.defaultFinalizationThresholdSeconds + ); + setError(null); + } catch (err) { + setError( + err instanceof Error + ? err.message + : 'Failed to fetch finalization threshold' + ); + setFinalizationThreshold(null); + } finally { + setIsLoading(false); + } + }; + + fetchFinalizationThreshold(); + }, [chainId]); + + return { finalizationThreshold, isLoading, error }; +}