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