diff --git a/dashboard/src/components/Contracts.tsx b/dashboard/src/components/Contracts.tsx new file mode 100644 index 00000000..706e8305 --- /dev/null +++ b/dashboard/src/components/Contracts.tsx @@ -0,0 +1,104 @@ +import { + Card, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, +} from '@mui/material'; +import { + Chain, + chainToChainId, + chainToPlatform, + chains, + contracts, + rpc, +} from '@wormhole-foundation/sdk-base'; +import { useEffect, useState } from 'react'; +import { useNetworkContext } from '../contexts/NetworkContext'; +import CollapsibleSection from './CollapsibleSection'; +import { callContractMethod, getMethodId } from '@wormhole-foundation/wormhole-monitor-common'; + +const coreBridgeChains = chains.filter((chain) => contracts.coreBridge.get('Mainnet', chain)); + +function useGetGuardianSet(chain: Chain, address: string | undefined) { + const network = useNetworkContext(); + const [guardianSet, setGuardianSet] = useState<[bigint | null, string | null]>([null, null]); + useEffect(() => { + setGuardianSet([null, null]); + if (!address) return; + let cancelled = false; + if (chainToPlatform(chain) === 'Evm') { + const rpcUrl = rpc.rpcAddress(network.currentNetwork.env, chain); + if (!rpcUrl) return; + (async () => { + try { + const gsi = await callContractMethod( + rpcUrl, + address, + getMethodId('getCurrentGuardianSetIndex()') + ); + if (cancelled) return; + const gs = await callContractMethod( + rpcUrl, + address, + getMethodId('getGuardianSet(uint32)'), + gsi.substring(2) // strip 0x + ); + if (cancelled) return; + setGuardianSet([BigInt(gsi), gs]); + } catch (e) {} + })(); + } + return () => { + cancelled = true; + }; + }, [network.currentNetwork.env, chain, address]); + return guardianSet; +} + +function CoreBridgeInfo({ chain, address }: { chain: Chain; address: string | undefined }) { + const guardianSet = useGetGuardianSet(chain, address); + const guardianSetIndex = guardianSet[0]?.toString(); + if (!address) return null; + return ( + + {chain} + {chainToChainId(chain)} + {address} + {guardianSetIndex} + + ); +} + +function Contracts() { + return ( + + + + + + + Chain Name + Chain ID + Address + Guardian Set Index + + + + {coreBridgeChains.map((chain: Chain) => ( + + ))} + +
+
+
+
+ ); +} +export default Contracts; diff --git a/dashboard/src/components/Main.tsx b/dashboard/src/components/Main.tsx index c1fe3c2c..c704d257 100644 --- a/dashboard/src/components/Main.tsx +++ b/dashboard/src/components/Main.tsx @@ -1,4 +1,9 @@ -import { GitHub } from '@mui/icons-material'; +import { + AnalyticsOutlined, + GitHub, + ReceiptLongOutlined, + SyncAltOutlined, +} from '@mui/icons-material'; import { AppBar, Box, Button, Hidden, IconButton, Toolbar, Typography } from '@mui/material'; import { NavLink, Route, Switch, useLocation } from 'react-router-dom'; import useChainHeartbeats from '../hooks/useChainHeartbeats'; @@ -6,6 +11,7 @@ import useHeartbeats from '../hooks/useHeartbeats'; import useLatestRelease from '../hooks/useLatestRelease'; import WormholeStatsIcon from '../icons/WormholeStatsIcon'; import Alerts from './Alerts'; +import Contracts from './Contracts'; import Home from './Home'; import Metrics from './Metrics'; import NTTMetrics from './NTTMetrics'; @@ -33,21 +39,53 @@ function NavLinks() { - + Dashboard + + + + + + Contracts + + - Metrics + + + + + Metrics + - NTT + + + + + NTT + ); @@ -70,7 +119,7 @@ function Main() { return ( <> - + @@ -100,6 +149,9 @@ function Main() { + + +