diff --git a/packages/app/src/features/landing/sections/BalanceSheetSection.tsx b/packages/app/src/features/landing/sections/BalanceSheetSection.tsx index 6ed8bee..29ccd0e 100644 --- a/packages/app/src/features/landing/sections/BalanceSheetSection.tsx +++ b/packages/app/src/features/landing/sections/BalanceSheetSection.tsx @@ -3,47 +3,17 @@ import { Cell, Pie, PieChart, ResponsiveContainer } from 'recharts'; import { BalanceItem } from '@/components/ui/BalanceItem'; import { OpticianSans } from '@/fonts'; - -interface BalanceData { - title: string; - subtitle: string; - value: number; - color: string; - [key: string]: string | number; -} - -const BALANCE_DATA: BalanceData[] = [ - { - title: 'HYPE (SPOT)', - subtitle: 'Hypercore', - value: 49.42, - color: '#18edeb', - }, - { - title: 'HYPE (1x SHORT)', - subtitle: 'Hypercore', - value: 49.42, - color: '#e24e76', - }, - { - title: 'USDC (EXTRA MARGIN)', - subtitle: 'Hypercore', - value: 1.15, - color: '#0085ff', - }, - { - title: 'USDC (TO BE ALLOCATED)', - subtitle: 'HYPEREVM', - value: 1.01, - color: '#7f99ff', - }, -]; +import { useBalanceSheet } from '@/hooks'; interface BalanceSheetSectionProps { id?: string; } -export const BalanceSheetSection: React.FC = ({ id }) => { +export const BalanceSheetSection: React.FC = ({ + id, +}) => { + const { balanceData } = useBalanceSheet(); + return ( balance SHEET @@ -52,7 +22,7 @@ export const BalanceSheetSection: React.FC = ({ id }) = ({ id }) dataKey="value" stroke="none" > - {BALANCE_DATA.map((entry, index) => ( + {balanceData.map((entry, index) => ( ))} @@ -73,7 +43,7 @@ export const BalanceSheetSection: React.FC = ({ id }) - {BALANCE_DATA.map((item, index) => ( + {balanceData.map((item, index) => ( { + // Get total assets from Accountant + const { data: totalAssets } = useReadContract({ + address: Contracts.Crest.Accountant, + abi: CrestAccountantAbi, + functionName: 'getTotalAssets', + }); + + // Get positions from Manager + const { data: positions } = useReadContract({ + address: Contracts.Crest.Manager, + abi: CrestManagerAbi, + functionName: 'getPositions', + }); + + // Get Core position value + const { data: corePositionValue } = useReadContract({ + address: Contracts.Crest.Manager, + abi: CrestManagerAbi, + functionName: 'estimatePositionValue', + }); + + // Calculate balance sheet data + const balanceData: BalanceData[] = []; + const totalAssetsFormatted = totalAssets && typeof totalAssets === 'bigint' + ? Number(formatUnits(totalAssets, 6)) + : 0; + const coreValueFormatted = corePositionValue && typeof corePositionValue === 'bigint' + ? Number(formatUnits(corePositionValue, 6)) + : 0; + + if (positions && Array.isArray(positions) && totalAssetsFormatted > 0) { + const [spotPosition, perpPosition] = positions; + + // Calculate spot position value (approximate) + const spotSizeFormatted = spotPosition.size ? Number(formatUnits(BigInt(spotPosition.size), 8)) : 0; + const spotEntryPrice = spotPosition.entryPrice ? Number(formatUnits(BigInt(spotPosition.entryPrice), 8)) : 0; + const spotValue = spotSizeFormatted * spotEntryPrice; + const spotPercentage = totalAssetsFormatted > 0 ? (spotValue / totalAssetsFormatted) * 100 : 0; + + // Calculate perp position value (approximate) + const perpSizeFormatted = perpPosition.size ? Number(formatUnits(BigInt(perpPosition.size), 8)) : 0; + const perpEntryPrice = perpPosition.entryPrice ? Number(formatUnits(BigInt(perpPosition.entryPrice), 8)) : 0; + const perpValue = perpSizeFormatted * perpEntryPrice; + const perpPercentage = totalAssetsFormatted > 0 ? (perpValue / totalAssetsFormatted) * 100 : 0; + + // Remaining USDC (vault balance + other assets) + const remainingValue = totalAssetsFormatted - spotValue - Math.abs(perpValue); + const remainingPercentage = totalAssetsFormatted > 0 ? (remainingValue / totalAssetsFormatted) * 100 : 0; + + // Add positions to balance data + if (spotPosition.size > 0) { + balanceData.push({ + title: `SPOT ${spotPosition.isLong ? 'LONG' : 'SHORT'}`, + subtitle: 'Hyperliquid Core', + value: Math.max(0, spotPercentage), + color: spotPosition.isLong ? '#18edeb' : '#e24e76', + }); + } + + if (perpPosition.size > 0) { + balanceData.push({ + title: `PERP ${perpPosition.isLong ? 'LONG' : 'SHORT'}`, + subtitle: 'Hyperliquid Core', + value: Math.max(0, perpPercentage), + color: perpPosition.isLong ? '#18edeb' : '#e24e76', + }); + } + + // Add remaining USDC + if (remainingValue > 0) { + balanceData.push({ + title: 'USDC (AVAILABLE)', + subtitle: 'Vault Balance', + value: Math.max(0, remainingPercentage), + color: '#0085ff', + }); + } + + // Add allocation buffer if needed + const totalPercentage = balanceData.reduce((sum, item) => sum + item.value, 0); + if (totalPercentage < 100) { + balanceData.push({ + title: 'USDC (TO BE ALLOCATED)', + subtitle: 'Vault Reserve', + value: Math.max(0, 100 - totalPercentage), + color: '#7f99ff', + }); + } + } + + // Fallback to static data if no positions or data + if (balanceData.length === 0) { + balanceData.push( + { + title: 'USDC (AVAILABLE)', + subtitle: 'Vault Balance', + value: 98.85, + color: '#0085ff', + }, + { + title: 'USDC (TO BE ALLOCATED)', + subtitle: 'Vault Reserve', + value: 1.15, + color: '#7f99ff', + } + ); + } + + return { + balanceData, + totalAssets: totalAssetsFormatted, + corePositionValue: coreValueFormatted, + positions, + }; +}; \ No newline at end of file