Rename network to cluster
This commit is contained in:
committed by
Michael Vines
parent
c47c3acb10
commit
1d7dbe859a
@ -1,17 +1,17 @@
|
||||
import React from "react";
|
||||
|
||||
import { NetworkProvider } from "./providers/network";
|
||||
import { ClusterProvider } from "./providers/cluster";
|
||||
import { TransactionsProvider } from "./providers/transactions";
|
||||
import NetworkStatusButton from "./components/NetworkStatusButton";
|
||||
import ClusterStatusButton from "./components/ClusterStatusButton";
|
||||
import TransactionsCard from "./components/TransactionsCard";
|
||||
import NetworkModal from "./components/NetworkModal";
|
||||
import ClusterModal from "./components/ClusterModal";
|
||||
import Logo from "./img/logos-solana/light-explorer-logo.svg";
|
||||
|
||||
function App() {
|
||||
const [showModal, setShowModal] = React.useState(false);
|
||||
return (
|
||||
<NetworkProvider>
|
||||
<NetworkModal show={showModal} onClose={() => setShowModal(false)} />
|
||||
<ClusterProvider>
|
||||
<ClusterModal show={showModal} onClose={() => setShowModal(false)} />
|
||||
<div className="main-content">
|
||||
<div className="header">
|
||||
<div className="container">
|
||||
@ -21,7 +21,7 @@ function App() {
|
||||
<img src={Logo} width="250" alt="Solana Explorer" />
|
||||
</div>
|
||||
<div className="col-auto">
|
||||
<NetworkStatusButton onClick={() => setShowModal(true)} />
|
||||
<ClusterStatusButton onClick={() => setShowModal(true)} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -39,7 +39,7 @@ function App() {
|
||||
</div>
|
||||
</div>
|
||||
<Overlay show={showModal} onClick={() => setShowModal(false)} />
|
||||
</NetworkProvider>
|
||||
</ClusterProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
import React from "react";
|
||||
import {
|
||||
useNetwork,
|
||||
useNetworkDispatch,
|
||||
updateNetwork,
|
||||
NetworkStatus,
|
||||
networkUrl,
|
||||
networkName,
|
||||
NETWORKS,
|
||||
Network
|
||||
} from "../providers/network";
|
||||
useCluster,
|
||||
useClusterDispatch,
|
||||
updateCluster,
|
||||
ClusterStatus,
|
||||
clusterUrl,
|
||||
clusterName,
|
||||
CLUSTERS,
|
||||
Cluster
|
||||
} from "../providers/cluster";
|
||||
import { assertUnreachable } from "../utils";
|
||||
|
||||
type Props = {
|
||||
@ -16,7 +16,7 @@ type Props = {
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
function NetworkModal({ show, onClose }: Props) {
|
||||
function ClusterModal({ show, onClose }: Props) {
|
||||
return (
|
||||
<div
|
||||
className={`modal fade fixed-right${show ? " show" : ""}`}
|
||||
@ -31,7 +31,7 @@ function NetworkModal({ show, onClose }: Props) {
|
||||
|
||||
<h2 className="text-center mb-4 mt-4">Choose a Cluster</h2>
|
||||
|
||||
<NetworkToggle />
|
||||
<ClusterToggle />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -40,9 +40,9 @@ function NetworkModal({ show, onClose }: Props) {
|
||||
}
|
||||
|
||||
type InputProps = { activeSuffix: string; active: boolean };
|
||||
function CustomNetworkInput({ activeSuffix, active }: InputProps) {
|
||||
const { customUrl } = useNetwork();
|
||||
const dispatch = useNetworkDispatch();
|
||||
function CustomClusterInput({ activeSuffix, active }: InputProps) {
|
||||
const { customUrl } = useCluster();
|
||||
const dispatch = useClusterDispatch();
|
||||
const [editing, setEditing] = React.useState(false);
|
||||
|
||||
const customClass = (prefix: string) =>
|
||||
@ -53,7 +53,7 @@ function CustomNetworkInput({ activeSuffix, active }: InputProps) {
|
||||
<div
|
||||
className="btn input-group input-group-merge p-0"
|
||||
onClick={() =>
|
||||
!active && updateNetwork(dispatch, Network.Custom, customUrl)
|
||||
!active && updateCluster(dispatch, Cluster.Custom, customUrl)
|
||||
}
|
||||
>
|
||||
<input
|
||||
@ -65,7 +65,7 @@ function CustomNetworkInput({ activeSuffix, active }: InputProps) {
|
||||
onFocus={() => setEditing(true)}
|
||||
onBlur={() => setEditing(false)}
|
||||
onInput={e =>
|
||||
updateNetwork(dispatch, Network.Custom, e.currentTarget.value)
|
||||
updateCluster(dispatch, Cluster.Custom, e.currentTarget.value)
|
||||
}
|
||||
/>
|
||||
<div className="input-group-prepend">
|
||||
@ -77,19 +77,19 @@ function CustomNetworkInput({ activeSuffix, active }: InputProps) {
|
||||
);
|
||||
}
|
||||
|
||||
function NetworkToggle() {
|
||||
const { status, network, customUrl } = useNetwork();
|
||||
const dispatch = useNetworkDispatch();
|
||||
function ClusterToggle() {
|
||||
const { status, cluster, customUrl } = useCluster();
|
||||
const dispatch = useClusterDispatch();
|
||||
|
||||
let activeSuffix = "";
|
||||
switch (status) {
|
||||
case NetworkStatus.Connected:
|
||||
case ClusterStatus.Connected:
|
||||
activeSuffix = "success";
|
||||
break;
|
||||
case NetworkStatus.Connecting:
|
||||
case ClusterStatus.Connecting:
|
||||
activeSuffix = "warning";
|
||||
break;
|
||||
case NetworkStatus.Failure:
|
||||
case ClusterStatus.Failure:
|
||||
activeSuffix = "danger";
|
||||
break;
|
||||
default:
|
||||
@ -98,11 +98,11 @@ function NetworkToggle() {
|
||||
|
||||
return (
|
||||
<div className="btn-group-toggle d-flex flex-wrap mb-4">
|
||||
{NETWORKS.map((net, index) => {
|
||||
const active = net === network;
|
||||
if (net === Network.Custom)
|
||||
{CLUSTERS.map((net, index) => {
|
||||
const active = net === cluster;
|
||||
if (net === Cluster.Custom)
|
||||
return (
|
||||
<CustomNetworkInput
|
||||
<CustomClusterInput
|
||||
key={index}
|
||||
activeSuffix={activeSuffix}
|
||||
active={active}
|
||||
@ -121,11 +121,11 @@ function NetworkToggle() {
|
||||
<input
|
||||
type="radio"
|
||||
checked={active}
|
||||
onChange={() => updateNetwork(dispatch, net, customUrl)}
|
||||
onChange={() => updateCluster(dispatch, net, customUrl)}
|
||||
/>
|
||||
{`${networkName(net)}: `}
|
||||
{`${clusterName(net)}: `}
|
||||
<span className="text-muted d-inline-block">
|
||||
{networkUrl(net, customUrl)}
|
||||
{clusterUrl(net, customUrl)}
|
||||
</span>
|
||||
</label>
|
||||
);
|
||||
@ -134,4 +134,4 @@ function NetworkToggle() {
|
||||
);
|
||||
}
|
||||
|
||||
export default NetworkModal;
|
||||
export default ClusterModal;
|
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import { useNetwork, NetworkStatus, Network } from "../providers/network";
|
||||
import { useCluster, ClusterStatus, Cluster } from "../providers/cluster";
|
||||
|
||||
function NetworkStatusButton({ onClick }: { onClick: () => void }) {
|
||||
function ClusterStatusButton({ onClick }: { onClick: () => void }) {
|
||||
return (
|
||||
<div onClick={onClick}>
|
||||
<Button />
|
||||
@ -10,11 +10,11 @@ function NetworkStatusButton({ onClick }: { onClick: () => void }) {
|
||||
}
|
||||
|
||||
function Button() {
|
||||
const { status, network, name, customUrl } = useNetwork();
|
||||
const statusName = network !== Network.Custom ? `${name}` : `${customUrl}`;
|
||||
const { status, cluster, name, customUrl } = useCluster();
|
||||
const statusName = cluster !== Cluster.Custom ? `${name}` : `${customUrl}`;
|
||||
|
||||
switch (status) {
|
||||
case NetworkStatus.Connected:
|
||||
case ClusterStatus.Connected:
|
||||
return (
|
||||
<span className="btn btn-outline-success lift">
|
||||
<span className="fe fe-check-circle mr-2"></span>
|
||||
@ -22,7 +22,7 @@ function Button() {
|
||||
</span>
|
||||
);
|
||||
|
||||
case NetworkStatus.Connecting:
|
||||
case ClusterStatus.Connecting:
|
||||
return (
|
||||
<span className="btn btn-outline-warning lift">
|
||||
<span
|
||||
@ -34,7 +34,7 @@ function Button() {
|
||||
</span>
|
||||
);
|
||||
|
||||
case NetworkStatus.Failure:
|
||||
case ClusterStatus.Failure:
|
||||
return (
|
||||
<span className="btn btn-outline-danger lift">
|
||||
<span className="fe fe-alert-circle mr-2"></span>
|
||||
@ -44,4 +44,4 @@ function Button() {
|
||||
}
|
||||
}
|
||||
|
||||
export default NetworkStatusButton;
|
||||
export default ClusterStatusButton;
|
@ -9,14 +9,14 @@ import {
|
||||
} from "../providers/transactions";
|
||||
import bs58 from "bs58";
|
||||
import { assertUnreachable } from "../utils";
|
||||
import { useNetwork } from "../providers/network";
|
||||
import { useCluster } from "../providers/cluster";
|
||||
|
||||
function TransactionsCard() {
|
||||
const { transactions, idCounter } = useTransactions();
|
||||
const dispatch = useTransactionsDispatch();
|
||||
const signatureInput = React.useRef<HTMLInputElement>(null);
|
||||
const [error, setError] = React.useState("");
|
||||
const { url } = useNetwork();
|
||||
const { url } = useCluster();
|
||||
|
||||
const onNew = (signature: string) => {
|
||||
if (signature.length === 0) return;
|
||||
@ -115,7 +115,7 @@ const renderTransactionRow = (transaction: Transaction) => {
|
||||
switch (transaction.status) {
|
||||
case Status.CheckFailed:
|
||||
statusClass = "dark";
|
||||
statusText = "Network Error";
|
||||
statusText = "Cluster Error";
|
||||
break;
|
||||
case Status.Checking:
|
||||
statusClass = "info";
|
||||
|
@ -2,35 +2,35 @@ import React from "react";
|
||||
import { testnetChannelEndpoint, Connection } from "@solana/web3.js";
|
||||
import { findGetParameter } from "../utils";
|
||||
|
||||
export enum NetworkStatus {
|
||||
export enum ClusterStatus {
|
||||
Connected,
|
||||
Connecting,
|
||||
Failure
|
||||
}
|
||||
|
||||
export enum Network {
|
||||
export enum Cluster {
|
||||
MainnetBeta,
|
||||
Testnet,
|
||||
Devnet,
|
||||
Custom
|
||||
}
|
||||
|
||||
export const NETWORKS = [
|
||||
Network.MainnetBeta,
|
||||
Network.Testnet,
|
||||
Network.Devnet,
|
||||
Network.Custom
|
||||
export const CLUSTERS = [
|
||||
Cluster.MainnetBeta,
|
||||
Cluster.Testnet,
|
||||
Cluster.Devnet,
|
||||
Cluster.Custom
|
||||
];
|
||||
|
||||
export function networkName(network: Network): string {
|
||||
switch (network) {
|
||||
case Network.MainnetBeta:
|
||||
export function clusterName(cluster: Cluster): string {
|
||||
switch (cluster) {
|
||||
case Cluster.MainnetBeta:
|
||||
return "Mainnet Beta";
|
||||
case Network.Testnet:
|
||||
case Cluster.Testnet:
|
||||
return "Testnet";
|
||||
case Network.Devnet:
|
||||
case Cluster.Devnet:
|
||||
return "Devnet";
|
||||
case Network.Custom:
|
||||
case Cluster.Custom:
|
||||
return "Custom";
|
||||
}
|
||||
}
|
||||
@ -39,39 +39,39 @@ export const MAINNET_BETA_URL = "https://api.mainnet-beta.solana.com";
|
||||
export const TESTNET_URL = "https://testnet.solana.com";
|
||||
export const DEVNET_URL = testnetChannelEndpoint("stable");
|
||||
|
||||
export const DEFAULT_NETWORK = Network.MainnetBeta;
|
||||
export const DEFAULT_CLUSTER = Cluster.MainnetBeta;
|
||||
export const DEFAULT_CUSTOM_URL = "http://localhost:8899";
|
||||
|
||||
interface State {
|
||||
network: Network;
|
||||
cluster: Cluster;
|
||||
customUrl: string;
|
||||
status: NetworkStatus;
|
||||
status: ClusterStatus;
|
||||
}
|
||||
|
||||
interface Connecting {
|
||||
status: NetworkStatus.Connecting;
|
||||
network: Network;
|
||||
status: ClusterStatus.Connecting;
|
||||
cluster: Cluster;
|
||||
customUrl: string;
|
||||
}
|
||||
|
||||
interface Connected {
|
||||
status: NetworkStatus.Connected;
|
||||
status: ClusterStatus.Connected;
|
||||
}
|
||||
|
||||
interface Failure {
|
||||
status: NetworkStatus.Failure;
|
||||
status: ClusterStatus.Failure;
|
||||
}
|
||||
|
||||
type Action = Connected | Connecting | Failure;
|
||||
type Dispatch = (action: Action) => void;
|
||||
|
||||
function networkReducer(state: State, action: Action): State {
|
||||
function clusterReducer(state: State, action: Action): State {
|
||||
switch (action.status) {
|
||||
case NetworkStatus.Connected:
|
||||
case NetworkStatus.Failure: {
|
||||
case ClusterStatus.Connected:
|
||||
case ClusterStatus.Failure: {
|
||||
return Object.assign({}, state, { status: action.status });
|
||||
}
|
||||
case NetworkStatus.Connecting: {
|
||||
case ClusterStatus.Connecting: {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
@ -83,62 +83,62 @@ function initState(): State {
|
||||
const clusterUrlParam =
|
||||
findGetParameter("clusterUrl") || findGetParameter("networkUrl");
|
||||
|
||||
let network;
|
||||
let cluster;
|
||||
let customUrl = DEFAULT_CUSTOM_URL;
|
||||
switch (clusterUrlParam) {
|
||||
case MAINNET_BETA_URL:
|
||||
network = Network.MainnetBeta;
|
||||
cluster = Cluster.MainnetBeta;
|
||||
break;
|
||||
case DEVNET_URL:
|
||||
network = Network.Devnet;
|
||||
cluster = Cluster.Devnet;
|
||||
break;
|
||||
case TESTNET_URL:
|
||||
network = Network.Testnet;
|
||||
cluster = Cluster.Testnet;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (clusterParam) {
|
||||
case "mainnet-beta":
|
||||
network = Network.MainnetBeta;
|
||||
cluster = Cluster.MainnetBeta;
|
||||
break;
|
||||
case "devnet":
|
||||
network = Network.Devnet;
|
||||
cluster = Cluster.Devnet;
|
||||
break;
|
||||
case "testnet":
|
||||
network = Network.Testnet;
|
||||
cluster = Cluster.Testnet;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!network) {
|
||||
if (!cluster) {
|
||||
if (!clusterUrlParam) {
|
||||
network = DEFAULT_NETWORK;
|
||||
cluster = DEFAULT_CLUSTER;
|
||||
} else {
|
||||
network = Network.Custom;
|
||||
cluster = Cluster.Custom;
|
||||
customUrl = clusterUrlParam;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
network,
|
||||
cluster,
|
||||
customUrl,
|
||||
status: NetworkStatus.Connecting
|
||||
status: ClusterStatus.Connecting
|
||||
};
|
||||
}
|
||||
|
||||
const StateContext = React.createContext<State | undefined>(undefined);
|
||||
const DispatchContext = React.createContext<Dispatch | undefined>(undefined);
|
||||
|
||||
type NetworkProviderProps = { children: React.ReactNode };
|
||||
export function NetworkProvider({ children }: NetworkProviderProps) {
|
||||
type ClusterProviderProps = { children: React.ReactNode };
|
||||
export function ClusterProvider({ children }: ClusterProviderProps) {
|
||||
const [state, dispatch] = React.useReducer(
|
||||
networkReducer,
|
||||
clusterReducer,
|
||||
undefined,
|
||||
initState
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
// Connect to network immediately
|
||||
updateNetwork(dispatch, state.network, state.customUrl);
|
||||
// Connect to cluster immediately
|
||||
updateCluster(dispatch, state.cluster, state.customUrl);
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
@ -150,56 +150,56 @@ export function NetworkProvider({ children }: NetworkProviderProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export function networkUrl(network: Network, customUrl: string): string {
|
||||
switch (network) {
|
||||
case Network.Devnet:
|
||||
export function clusterUrl(cluster: Cluster, customUrl: string): string {
|
||||
switch (cluster) {
|
||||
case Cluster.Devnet:
|
||||
return DEVNET_URL;
|
||||
case Network.MainnetBeta:
|
||||
case Cluster.MainnetBeta:
|
||||
return MAINNET_BETA_URL;
|
||||
case Network.Testnet:
|
||||
case Cluster.Testnet:
|
||||
return TESTNET_URL;
|
||||
case Network.Custom:
|
||||
case Cluster.Custom:
|
||||
return customUrl;
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateNetwork(
|
||||
export async function updateCluster(
|
||||
dispatch: Dispatch,
|
||||
network: Network,
|
||||
cluster: Cluster,
|
||||
customUrl: string
|
||||
) {
|
||||
dispatch({
|
||||
status: NetworkStatus.Connecting,
|
||||
network,
|
||||
status: ClusterStatus.Connecting,
|
||||
cluster,
|
||||
customUrl
|
||||
});
|
||||
|
||||
try {
|
||||
const connection = new Connection(networkUrl(network, customUrl));
|
||||
const connection = new Connection(clusterUrl(cluster, customUrl));
|
||||
await connection.getRecentBlockhash();
|
||||
dispatch({ status: NetworkStatus.Connected });
|
||||
dispatch({ status: ClusterStatus.Connected });
|
||||
} catch (error) {
|
||||
console.error("Failed to update network", error);
|
||||
dispatch({ status: NetworkStatus.Failure });
|
||||
console.error("Failed to update cluster", error);
|
||||
dispatch({ status: ClusterStatus.Failure });
|
||||
}
|
||||
}
|
||||
|
||||
export function useNetwork() {
|
||||
export function useCluster() {
|
||||
const context = React.useContext(StateContext);
|
||||
if (!context) {
|
||||
throw new Error(`useNetwork must be used within a NetworkProvider`);
|
||||
throw new Error(`useCluster must be used within a ClusterProvider`);
|
||||
}
|
||||
return {
|
||||
...context,
|
||||
url: networkUrl(context.network, context.customUrl),
|
||||
name: networkName(context.network)
|
||||
url: clusterUrl(context.cluster, context.customUrl),
|
||||
name: clusterName(context.cluster)
|
||||
};
|
||||
}
|
||||
|
||||
export function useNetworkDispatch() {
|
||||
export function useClusterDispatch() {
|
||||
const context = React.useContext(DispatchContext);
|
||||
if (!context) {
|
||||
throw new Error(`useNetworkDispatch must be used within a NetworkProvider`);
|
||||
throw new Error(`useClusterDispatch must be used within a ClusterProvider`);
|
||||
}
|
||||
return context;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import { TransactionSignature, Connection } from "@solana/web3.js";
|
||||
import { findGetParameter, findPathSegment } from "../utils";
|
||||
import { useNetwork } from "../providers/network";
|
||||
import { useCluster } from "../providers/cluster";
|
||||
|
||||
export enum Status {
|
||||
Checking,
|
||||
@ -124,9 +124,9 @@ type TransactionsProviderProps = { children: React.ReactNode };
|
||||
export function TransactionsProvider({ children }: TransactionsProviderProps) {
|
||||
const [state, dispatch] = React.useReducer(reducer, undefined, initState);
|
||||
|
||||
const { status, url } = useNetwork();
|
||||
const { status, url } = useCluster();
|
||||
|
||||
// Check transaction statuses on startup and whenever network updates
|
||||
// Check transaction statuses on startup and whenever cluster updates
|
||||
React.useEffect(() => {
|
||||
Object.values(state.transactions).forEach(tx => {
|
||||
checkTransactionStatus(dispatch, tx.id, tx.signature, url);
|
||||
|
Reference in New Issue
Block a user