Rename network to cluster

This commit is contained in:
Justin Starry
2020-03-31 14:36:40 +08:00
committed by Michael Vines
parent c47c3acb10
commit 1d7dbe859a
6 changed files with 112 additions and 112 deletions

View File

@ -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>
);
}

View File

@ -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;

View File

@ -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;

View File

@ -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";

View File

@ -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;
}

View File

@ -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);