Skip to content

Commit

Permalink
propagate finalization thresholds throughout the FE correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
0age committed Dec 10, 2024
1 parent ff5ac36 commit 7a6447b
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 191 deletions.
126 changes: 67 additions & 59 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { BalanceDisplay } from './components/BalanceDisplay';
import HealthCheck from './components/HealthCheck';
import { DepositForm } from './components/DepositForm';
import { NotificationProvider } from './context/NotificationProvider';
import { ChainConfigProvider } from './contexts/ChainConfigContext';
import { ChainConfig } from './types/chain';

// Configure supported chains
const projectId = 'YOUR_PROJECT_ID'; // Get from WalletConnect Cloud
Expand Down Expand Up @@ -55,6 +57,7 @@ const customTheme = darkTheme({
function App() {
const [sessionToken, setSessionToken] = useState<string | null>(null);
const [isHealthy, setIsHealthy] = useState(true);
const [chainConfig, setChainConfig] = useState<ChainConfig | null>(null);

const queryClient = useMemo(
() =>
Expand All @@ -74,71 +77,76 @@ function App() {
<QueryClientProvider client={queryClient}>
<RainbowKitProvider theme={customTheme}>
<NotificationProvider>
<div className="h-screen flex flex-col bg-[#0a0a0a]">
<header className="flex-none bg-[#0a0a0a] border-b border-gray-800">
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
<h1 className="text-3xl font-black font-monaco">
<span className="text-white">Sm</span>
<span className="text-[#00ff00]">all</span>
<span className="text-[#00ff00]">ocator</span>
<span className="text-white"> 🤏</span>
</h1>
<div className="flex items-center gap-4">
<a
href="https://github.com/Uniswap/smallocator"
target="_blank"
rel="noopener noreferrer"
className="text-gray-400 hover:text-[#00ff00] transition-colors"
>
<svg
viewBox="0 0 24 24"
width="24"
height="24"
stroke="currentColor"
strokeWidth="2"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
<ChainConfigProvider value={{ chainConfig }}>
<div className="h-screen flex flex-col bg-[#0a0a0a]">
<header className="flex-none bg-[#0a0a0a] border-b border-gray-800">
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
<h1 className="text-3xl font-black font-monaco">
<span className="text-white">Sm</span>
<span className="text-[#00ff00]">all</span>
<span className="text-[#00ff00]">ocator</span>
<span className="text-white"> 🤏</span>
</h1>
<div className="flex items-center gap-4">
<a
href="https://github.com/Uniswap/smallocator"
target="_blank"
rel="noopener noreferrer"
className="text-gray-400 hover:text-[#00ff00] transition-colors"
>
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
</svg>
</a>
<WalletConnect hasSession={!!sessionToken} />
<SessionManager
sessionToken={sessionToken}
onSessionUpdate={setSessionToken}
isServerHealthy={isHealthy}
/>
<svg
viewBox="0 0 24 24"
width="24"
height="24"
stroke="currentColor"
strokeWidth="2"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
</svg>
</a>
<WalletConnect hasSession={!!sessionToken} />
<SessionManager
sessionToken={sessionToken}
onSessionUpdate={setSessionToken}
isServerHealthy={isHealthy}
/>
</div>
</div>
</div>
</header>
</header>

<main className="flex-1 overflow-y-auto">
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div className="space-y-6">
{/* Health Check Status */}
<div className="mx-auto p-4 bg-[#0a0a0a] rounded-lg shadow-xl border border-gray-800">
<HealthCheck onHealthStatusChange={setIsHealthy} />
</div>
<main className="flex-1 overflow-y-auto">
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div className="space-y-6">
{/* Health Check Status */}
<div className="mx-auto p-4 bg-[#0a0a0a] rounded-lg shadow-xl border border-gray-800">
<HealthCheck
onHealthStatusChange={setIsHealthy}
onChainConfigUpdate={setChainConfig}
/>
</div>

{/* Only show these components if the server is healthy */}
{isHealthy && (
<>
{/* Deposit Form */}
{sessionToken && <DepositForm />}
{/* Only show these components if the server is healthy */}
{isHealthy && (
<>
{/* Deposit Form */}
{sessionToken && <DepositForm />}

{/* Balance Display */}
{sessionToken && (
<div className="mx-auto p-6 bg-[#0a0a0a] rounded-lg shadow-xl border border-gray-800">
<BalanceDisplay sessionToken={sessionToken} />
</div>
)}
</>
)}
{/* Balance Display */}
{sessionToken && (
<div className="mx-auto p-6 bg-[#0a0a0a] rounded-lg shadow-xl border border-gray-800">
<BalanceDisplay sessionToken={sessionToken} />
</div>
)}
</>
)}
</div>
</div>
</div>
</main>
</div>
</main>
</div>
</ChainConfigProvider>
</NotificationProvider>
</RainbowKitProvider>
</QueryClientProvider>
Expand Down
31 changes: 3 additions & 28 deletions frontend/src/components/BalanceDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +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';
import { formatTimeRemaining, formatResetPeriod } from '../utils/formatting';

interface BalanceDisplayProps {
sessionToken: string | null;
Expand All @@ -32,32 +32,6 @@ interface EthereumProvider {
request: (args: { method: string; params: unknown[] }) => Promise<unknown>;
}

function formatTimeRemaining(
expiryTimestamp: number,
currentTime: number
): string {
const diff = expiryTimestamp - currentTime;

if (diff <= 0) return 'Ready';

const days = Math.floor(diff / (24 * 60 * 60));
const hours = Math.floor((diff % (24 * 60 * 60)) / (60 * 60));
const minutes = Math.floor((diff % (60 * 60)) / 60);
const seconds = diff % 60;

if (days > 0) return `${days}d ${hours}h ${minutes}m`;
if (hours > 0) return `${hours}h ${minutes}m ${seconds}s`;
if (minutes > 0) return `${minutes}m ${seconds}s`;
return `${seconds}s`;
}

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`;
return `${Math.floor(seconds / 86400)} days`;
};

const chainNames: Record<string, string> = {
'1': 'Ethereum',
'10': 'Optimism',
Expand Down Expand Up @@ -446,7 +420,8 @@ export function BalanceDisplay({
{balance.resourceLock?.resetPeriod &&
balance.resourceLock.resetPeriod > 0 && (
<span className="px-2 py-1 text-xs bg-[#00ff00]/10 text-[#00ff00] rounded">
Reset Period: {formatResetPeriod(balance.resourceLock.resetPeriod)}
Reset Period:{' '}
{formatResetPeriod(balance.resourceLock.resetPeriod)}
</span>
)}
<FinalizationThreshold chainId={parseInt(balance.chainId)} />
Expand Down
18 changes: 18 additions & 0 deletions frontend/src/components/DepositForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { useCompact } from '../hooks/useCompact';
import { useNotification } from '../hooks/useNotification';
import { useERC20 } from '../hooks/useERC20';
import { useAllocatorAPI } from '../hooks/useAllocatorAPI';
import { useChainConfig } from '../hooks/use-chain-config';
import { formatResetPeriod } from '../utils/formatting';
import { ChainConfig } from '../types/chain';

// Chain name mapping
const chainNames: Record<string, string> = {
Expand All @@ -18,6 +21,7 @@ export function DepositForm() {
const { address, isConnected } = useAccount();
const { data: ethBalance } = useBalance({ address });
const chainId = useChainId();
const { chainConfig } = useChainConfig();
const [amount, setAmount] = useState('');
const [tokenType, setTokenType] = useState<TokenType>('native');
const [tokenAddress, setTokenAddress] = useState('');
Expand Down Expand Up @@ -240,6 +244,20 @@ export function DepositForm() {
<p className="mt-1 text-sm text-gray-400">
Deposit Ether or ERC20 tokens into a reusable resource lock.
</p>
{chainConfig && (
<p className="mt-1 text-sm text-gray-400">
Deposits on {chainNames[chainId.toString()] || `Chain ${chainId}`}{' '}
will be considered finalized and available to allocate{' '}
{formatResetPeriod(
chainConfig.supportedChains.find(
(chain: ChainConfig['supportedChains'][0]) =>
chain.chainId === chainId.toString()
)?.finalizationThresholdSeconds ??
chainConfig.defaultFinalizationThresholdSeconds
)}{' '}
after a successful deposit transaction.
</p>
)}
</div>

<div className="space-y-6">
Expand Down
20 changes: 15 additions & 5 deletions frontend/src/components/FinalizationThreshold.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import { useFinalizationThreshold } from '../hooks/useFinalizationThreshold';
import { formatResetPeriod } from './BalanceDisplay';
import { useChainConfig } from '../hooks/use-chain-config';
import { formatResetPeriod } from '../utils/formatting';
import { ChainConfig } from '../types/chain';

interface FinalizationThresholdProps {
chainId: number;
}

export function FinalizationThreshold({ chainId }: FinalizationThresholdProps) {
const { finalizationThreshold } = useFinalizationThreshold(chainId);
const { chainConfig } = useChainConfig();

if (finalizationThreshold === null) return null;
if (!chainConfig) return null;

const chainSpecific = chainConfig.supportedChains.find(
(chain: ChainConfig['supportedChains'][0]) =>
chain.chainId === chainId.toString()
);

const threshold =
chainSpecific?.finalizationThresholdSeconds ??
chainConfig.defaultFinalizationThresholdSeconds;

return (
<span className="px-2 py-1 text-xs bg-[#00ff00]/10 text-[#00ff00] rounded">
Finalization: {formatResetPeriod(finalizationThreshold)}
Finalization: {formatResetPeriod(threshold)}
</span>
);
}
Loading

0 comments on commit 7a6447b

Please sign in to comment.