diff --git a/dashboard/package.json b/dashboard/package.json index c540787a..0f8d3811 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -19,6 +19,7 @@ "@types/react-dom": "^18.0.6", "@wormhole-foundation/sdk-icons": "^0.6.6-beta.1", "axios": "^0.27.2", + "buffer": "^6.0.3", "numeral": "^2.0.6", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/dashboard/src/components/Contracts.tsx b/dashboard/src/components/Contracts.tsx index 706e8305..3cb0cfa0 100644 --- a/dashboard/src/components/Contracts.tsx +++ b/dashboard/src/components/Contracts.tsx @@ -1,4 +1,5 @@ import { + Box, Card, Table, TableBody, @@ -6,6 +7,7 @@ import { TableContainer, TableHead, TableRow, + Typography, } from '@mui/material'; import { Chain, @@ -15,12 +17,17 @@ import { contracts, rpc, } from '@wormhole-foundation/sdk-base'; +import { callContractMethod, getMethodId } from '@wormhole-foundation/wormhole-monitor-common'; +import axios from 'axios'; import { useEffect, useState } from 'react'; import { useNetworkContext } from '../contexts/NetworkContext'; +import { WORMCHAIN_URL } from '../utils/consts'; +import { queryContractSmart } from '../utils/queryContractSmart'; import CollapsibleSection from './CollapsibleSection'; -import { callContractMethod, getMethodId } from '@wormhole-foundation/wormhole-monitor-common'; -const coreBridgeChains = chains.filter((chain) => contracts.coreBridge.get('Mainnet', chain)); +const coreBridgeChains = chains.filter( + (chain) => chain !== 'Aurora' && contracts.coreBridge.get('Mainnet', chain) +); function useGetGuardianSet(chain: Chain, address: string | undefined) { const network = useNetworkContext(); @@ -28,10 +35,12 @@ function useGetGuardianSet(chain: Chain, address: string | undefined) { useEffect(() => { setGuardianSet([null, null]); if (!address) return; + const rpcUrl = + chain === 'Wormchain' ? WORMCHAIN_URL : rpc.rpcAddress(network.currentNetwork.env, chain); + if (!rpcUrl) return; let cancelled = false; - if (chainToPlatform(chain) === 'Evm') { - const rpcUrl = rpc.rpcAddress(network.currentNetwork.env, chain); - if (!rpcUrl) return; + const platform = chainToPlatform(chain); + if (platform === 'Evm') { (async () => { try { const gsi = await callContractMethod( @@ -50,6 +59,61 @@ function useGetGuardianSet(chain: Chain, address: string | undefined) { setGuardianSet([BigInt(gsi), gs]); } catch (e) {} })(); + } else if (platform === 'Cosmwasm') { + (async () => { + try { + const guardianSet = await queryContractSmart(rpcUrl, address, { guardian_set_info: {} }); + if (cancelled) return; + setGuardianSet([ + BigInt(guardianSet.guardian_set_index), + guardianSet.addresses + .map( + (address: { bytes: string }) => + `0x${Buffer.from(address.bytes, 'base64').toString('hex')}` + ) + .join(','), + ]); + } catch (e) {} + })(); + } else if (platform === 'Solana') { + (async () => { + try { + // TODO: test this, move to a cloud function + // let gsi = 0; + // let gsAddress = utils.deriveGuardianSetKey(address, gsi); + // console.log(chain, gsi, gsAddress); + // let gsAccountInfo = await makeRpcCall( + // rpcUrl, + // 'getAccountInfo', + // [gsAddress], + // 'jsonParsed' + // ); + // let ret: [bigint | null, string | null] = [null, null]; + // while (gsAccountInfo !== null) { + // const gs = utils.GuardianSetData.deserialize(Buffer.from(gsAccountInfo, 'base64')); + // ret = [BigInt(gsi), gs.keys.map((k) => `0x${k.toString('hex')}`).join(',')]; + // if (cancelled) return; + // gsi++; + // gsAddress = utils.deriveGuardianSetKey(address, gsi); + // console.log(chain, gsi, gsAddress); + // gsAccountInfo = await makeRpcCall(rpcUrl, 'getAccountInfo', [gsAddress], 'jsonParsed'); + // } + // if (cancelled) return; + // setGuardianSet(ret); + } catch (e) {} + })(); + } else if (platform === 'Algorand') { + // https://developer.algorand.org/docs/rest-apis/algod/#get-v2applicationsapplication-id + (async () => { + try { + const response = await axios.get(`${rpcUrl}/v2/applications/${address}`); + const currentGuardianSetIndexState = response.data.params['global-state'].find( + (s: any) => Buffer.from(s.key, 'base64').toString('ascii') === 'currentGuardianSetIndex' + ); + if (cancelled) return; + setGuardianSet([BigInt(currentGuardianSetIndexState.value.uint), null]); + } catch (e) {} + })(); } return () => { cancelled = true; @@ -73,7 +137,8 @@ function CoreBridgeInfo({ chain, address }: { chain: Chain; address: string | un } function Contracts() { - return ( + const { currentNetwork } = useNetworkContext(); + return currentNetwork.name === 'Mainnet' ? ( @@ -99,6 +164,10 @@ function Contracts() { + ) : ( + + Contract info is currently only supported in Mainnet + ); } export default Contracts; diff --git a/dashboard/src/index.tsx b/dashboard/src/index.tsx index 3087805f..4d6cad7b 100644 --- a/dashboard/src/index.tsx +++ b/dashboard/src/index.tsx @@ -1,3 +1,5 @@ +import { Buffer } from 'buffer'; +globalThis.Buffer = Buffer; import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; diff --git a/package-lock.json b/package-lock.json index a9ce7db9..45e8b4a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -441,6 +441,7 @@ "@types/react-dom": "^18.0.6", "@wormhole-foundation/sdk-icons": "^0.6.6-beta.1", "axios": "^0.27.2", + "buffer": "^6.0.3", "numeral": "^2.0.6", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -8962,6 +8963,8 @@ }, "node_modules/buffer": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -8976,7 +8979,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -24181,6 +24183,7 @@ "@vitejs/plugin-react": "^4.2.1", "@wormhole-foundation/sdk-icons": "^0.6.6-beta.1", "axios": "^0.27.2", + "buffer": "^6.0.3", "numeral": "^2.0.6", "prettier": "^2.3.2", "react": "^18.2.0", @@ -26217,6 +26220,8 @@ }, "buffer": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "requires": { "base64-js": "^1.3.1", "ieee754": "^1.2.1"