diff --git a/.github/workflows/explorer/docker-compose.yaml b/.github/workflows/explorer/docker-compose.yaml index dccbe76b0ed..f3cc42b2137 100644 --- a/.github/workflows/explorer/docker-compose.yaml +++ b/.github/workflows/explorer/docker-compose.yaml @@ -4,7 +4,7 @@ services: cardano-node: image: ghcr.io/intersectmbo/cardano-node:8.9.0 volumes: - - /srv/var/cardano/state-sanchonet:/data + - /srv/var/cardano/state-preview:/data environment: - CARDANO_CONFIG=/data/config.json - CARDANO_TOPOLOGY=/data/topology.json @@ -19,14 +19,14 @@ services: hydra-explorer: image: ghcr.io/input-output-hk/hydra-explorer:unstable volumes: - - /srv/var/cardano/state-sanchonet:/data + - /srv/var/cardano/state-preview:/data ports: - "80:8080" command: [ "--node-socket", "/data/node.socket" - , "--testnet-magic", "4" + , "--testnet-magic", "2" , "--api-port", "8080" # NOTE: Block in which current master scripts were published - , "--start-chain-from", "21830575.4fa28d6c6f6541fd5c73d715d69f3dd7751e7b4d7dc1213cb02d30c5a0db609b" + , "--start-chain-from", "45386581.4a362bfca7cf840575c17b6cbb531588bc8e907beb5a6a28890877fb16be1cd3" ] restart: always diff --git a/hydra-explorer/web/.env b/hydra-explorer/web/.env new file mode 100644 index 00000000000..06c56db81e6 --- /dev/null +++ b/hydra-explorer/web/.env @@ -0,0 +1 @@ +NETWORK_URL=preview diff --git a/hydra-explorer/web/next.config.mjs b/hydra-explorer/web/next.config.mjs index 26ed9c6de01..ce9f4fdf6f6 100644 --- a/hydra-explorer/web/next.config.mjs +++ b/hydra-explorer/web/next.config.mjs @@ -1,6 +1,9 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - output: 'export' - }; + output: 'export', + env: { + NETWORK_URL: process.env.NETWORK_URL + }, +}; export default nextConfig; diff --git a/hydra-explorer/web/src/app/page.tsx b/hydra-explorer/web/src/app/page.tsx index d0d30c9e7db..26a187db620 100644 --- a/hydra-explorer/web/src/app/page.tsx +++ b/hydra-explorer/web/src/app/page.tsx @@ -7,9 +7,11 @@ import TickBox from "@/components/TickBox" import HeadsTable from "@/components/HeadsTable" import { HeadsDataProvider } from "@/providers/HeadsDataProvider" import HeadsDashboard from "@/components/HeadsDashboard" +import { CardanoExplorerProvider } from "@/providers/CardanoExplorer" export default function Home() { + return (
@@ -42,16 +44,20 @@ export default function Home() {
-
-
- -
-
- + +
+
+ +
+
+ +
+
+ +
+ -
-
diff --git a/hydra-explorer/web/src/components/HeadDetails/index.tsx b/hydra-explorer/web/src/components/HeadDetails/index.tsx index 0f1deecaf79..36ef2a56402 100644 --- a/hydra-explorer/web/src/components/HeadDetails/index.tsx +++ b/hydra-explorer/web/src/components/HeadDetails/index.tsx @@ -3,6 +3,7 @@ import React, { useState, useEffect } from 'react' import { HeadState, HeadMember } from '@/app/model' import MemberCommitDetails from '../MemberCommitDetails' +import { useCardanoExplorer } from '@/providers/CardanoExplorer' interface HeadDetailsProps { head: HeadState @@ -36,6 +37,8 @@ const HeadDetails: React.FC = ({ head, onClose }) => { } }, [onClose, showMemberCommitDetails]) + const explorer = useCardanoExplorer() + return (
@@ -50,7 +53,7 @@ const HeadDetails: React.FC = ({ head, onClose }) => {

Head ID

- + {head.headId}

@@ -58,9 +61,15 @@ const HeadDetails: React.FC = ({ head, onClose }) => {

Seed Tx In

- - {head.seedTxIn} - + {head.seedTxIn && ( + + {head.seedTxIn} + + )}

@@ -86,7 +95,7 @@ const HeadDetails: React.FC = ({ head, onClose }) => {

Point

- Block Hash: + Block Hash: {head.point.blockHash}
Slot: {head.point.slot} diff --git a/hydra-explorer/web/src/components/HeadsTable/index.tsx b/hydra-explorer/web/src/components/HeadsTable/index.tsx index 690d39d26b0..bdec2cb5e3d 100644 --- a/hydra-explorer/web/src/components/HeadsTable/index.tsx +++ b/hydra-explorer/web/src/components/HeadsTable/index.tsx @@ -5,6 +5,7 @@ import { HeadState } from "@/app/model" import { useHeadsData } from "@/providers/HeadsDataProvider" import HeadDetails from "../HeadDetails" import { totalLovelaceValueLocked } from '@/utils' +import { useCardanoExplorer } from '@/providers/CardanoExplorer' const HeadsTable: React.FC = () => { const { heads, error } = useHeadsData() @@ -14,6 +15,8 @@ const HeadsTable: React.FC = () => { setSelectedHead(head) } + const explorer = useCardanoExplorer() + return (

{error ? ( @@ -36,7 +39,7 @@ const HeadsTable: React.FC = () => { {heads?.sort((a, b) => b.blockNo - a.blockNo).map((head, index) => ( - + {head.headId} @@ -44,7 +47,7 @@ const HeadsTable: React.FC = () => { {head.point.slot} {head.blockNo} - + {head.point.blockHash} diff --git a/hydra-explorer/web/src/components/MemberCommitDetails/index.tsx b/hydra-explorer/web/src/components/MemberCommitDetails/index.tsx index cd55280b67c..ae2216e49e7 100644 --- a/hydra-explorer/web/src/components/MemberCommitDetails/index.tsx +++ b/hydra-explorer/web/src/components/MemberCommitDetails/index.tsx @@ -2,6 +2,7 @@ import React, { useEffect } from 'react' import { HeadMember } from '@/app/model' +import { useCardanoExplorer } from '@/providers/CardanoExplorer' interface MemberCommitDetailsProps { member: HeadMember @@ -23,6 +24,8 @@ const MemberCommitDetails: React.FC = ({ member, onClo } }, [onClose]) + const explorer = useCardanoExplorer() + return (
@@ -50,12 +53,12 @@ const MemberCommitDetails: React.FC = ({ member, onClo return ( - + {txId} #{txIx} - + {commit.address} diff --git a/hydra-explorer/web/src/components/TickBox/index.tsx b/hydra-explorer/web/src/components/TickBox/index.tsx index 9cf28cf8c3f..dfc85209cb5 100644 --- a/hydra-explorer/web/src/components/TickBox/index.tsx +++ b/hydra-explorer/web/src/components/TickBox/index.tsx @@ -2,6 +2,7 @@ import { TickState } from "@/app/model" import useDataFetcher from "@/hooks/DataFetcher" +import { useCardanoExplorer } from "@/providers/CardanoExplorer" import { useState } from "react" const TickBox = () => { @@ -14,6 +15,8 @@ const TickBox = () => { setError, }) + const explorer = useCardanoExplorer() + return (
{error ? ( @@ -33,7 +36,7 @@ const TickBox = () => { {tick?.blockNo} - + {tick?.point.blockHash} diff --git a/hydra-explorer/web/src/providers/CardanoExplorer/index.tsx b/hydra-explorer/web/src/providers/CardanoExplorer/index.tsx new file mode 100644 index 00000000000..a888f5a7a00 --- /dev/null +++ b/hydra-explorer/web/src/providers/CardanoExplorer/index.tsx @@ -0,0 +1,41 @@ +"use client" // This is a client component 👈🏽 + +import React, { PropsWithChildren, useContext } from "react" + +export interface CardanoExplorer { + mintPolicy: (policyId: string) => string + tx: (txIn: string) => string + block: (blockHash: string) => string + address: (addr: string) => string +} + +const CardanoExplorerContext: React.Context = + React.createContext({} as CardanoExplorer) + +export const useCardanoExplorer = () => { + const context = useContext(CardanoExplorerContext) + if (!context) { + throw new Error("useCardanoExplorer must be used within a CardanoExplorerProvider") + } + return context +} + +export type CardanoExplorerProps = { + network: string +} + +export const CardanoExplorerProvider: React.FC> = + ({ network, children }) => { + const cexplorer: CardanoExplorer = { + mintPolicy: (policyId: string) => `https://${network}.cexplorer.io/policy/${policyId}/mint`, + tx: (txIn: string) => `https://${network}.cexplorer.io/tx/${txIn}`, + block: (blockHash: string) => `https://${network}.cexplorer.io/block/${blockHash}`, + address: (addr: string) => `https://${network}.cexplorer.io/address/${addr}` + } + + return ( + + {children} + + ) + } diff --git a/hydra-explorer/web/src/providers/HeadsDataProvider/index.tsx b/hydra-explorer/web/src/providers/HeadsDataProvider/index.tsx index 09d40d3dd70..38e9ce025ce 100644 --- a/hydra-explorer/web/src/providers/HeadsDataProvider/index.tsx +++ b/hydra-explorer/web/src/providers/HeadsDataProvider/index.tsx @@ -12,7 +12,13 @@ export interface HeadsDataService { const HeadsDataContext: React.Context = React.createContext({} as HeadsDataService) -export const useHeadsDataContext = () => useContext(HeadsDataContext) +export const useHeadsDataContext = () => { + const context = useContext(HeadsDataContext) + if (!context) { + throw new Error("useHeadsDataContext must be used within a HeadsDataProvider") + } + return context +} export const HeadsDataProvider: React.FC = ({ children diff --git a/hydra-explorer/web/src/providers/IntervalProvider/index.tsx b/hydra-explorer/web/src/providers/IntervalProvider/index.tsx index d7dadc993a0..48469b26ed7 100644 --- a/hydra-explorer/web/src/providers/IntervalProvider/index.tsx +++ b/hydra-explorer/web/src/providers/IntervalProvider/index.tsx @@ -12,7 +12,13 @@ export interface IntervalSettingService { const IntervalContext: React.Context = React.createContext({} as IntervalSettingService) -export const useIntervalContext = () => useContext(IntervalContext) +export const useIntervalContext = () => { + const context = useContext(IntervalContext) + if (!context) { + throw new Error("useIntervalContext must be used within a IntervalSettingProvider") + } + return context +} const IntervalSettingProvider: React.FC = ({ children diff --git a/hydra-explorer/web/src/utils.tsx b/hydra-explorer/web/src/utils.tsx index 48ac5a60db1..b7e57619e5d 100644 --- a/hydra-explorer/web/src/utils.tsx +++ b/hydra-explorer/web/src/utils.tsx @@ -1,12 +1,14 @@ import { HeadState } from "./app/model" export const totalLovelaceValueLocked = (head: HeadState) => { + if (head.status == "Finalized" || head.status == "Aborted" ) return 0 return (head.members || []).reduce((total, member) => { if (member.commits && Object.keys(member.commits).length > 0) { - return total + Object.values(member.commits).reduce((memberTotal, commit) => { + const memberTotal = Object.values(member.commits).reduce((memberTotal, commit) => { return memberTotal + commit.value.lovelace }, 0) + return total + memberTotal } return total }, 0) -} \ No newline at end of file +}