Remove clusterUrl url param
This commit is contained in:
parent
03f7d28aff
commit
8b95be0ee4
|
@ -1263,6 +1263,11 @@
|
|||
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
|
||||
"integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw=="
|
||||
},
|
||||
"@react-hook/debounce": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@react-hook/debounce/-/debounce-2.0.5.tgz",
|
||||
"integrity": "sha512-WrwQ1e4vx5lxxxEpGPPliMcs6oUJ8cyEb/GL8OEUPhBW4WL8YRSDW5oPnsOqIPqhHDyQMHgMipXWgj7QVmRMKA=="
|
||||
},
|
||||
"@sheerun/mutationobserver-shim": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz",
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@react-hook/debounce": "^2.0.5",
|
||||
"@solana/web3.js": "^0.56.0",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.3.2",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from "react";
|
||||
import { Link, useLocation, useHistory } from "react-router-dom";
|
||||
import { Link, useHistory, useLocation } from "react-router-dom";
|
||||
import { useDebounceCallback } from "@react-hook/debounce";
|
||||
import { Location } from "history";
|
||||
import {
|
||||
useCluster,
|
||||
|
@ -9,10 +10,12 @@ import {
|
|||
clusterSlug,
|
||||
CLUSTERS,
|
||||
Cluster,
|
||||
useClusterModal
|
||||
useClusterModal,
|
||||
useUpdateCustomUrl
|
||||
} from "../providers/cluster";
|
||||
import { assertUnreachable } from "../utils";
|
||||
import Overlay from "./Overlay";
|
||||
import { useQuery } from "utils/url";
|
||||
|
||||
function ClusterModal() {
|
||||
const [show, setShow] = useClusterModal();
|
||||
|
@ -46,34 +49,35 @@ function ClusterModal() {
|
|||
type InputProps = { activeSuffix: string; active: boolean };
|
||||
function CustomClusterInput({ activeSuffix, active }: InputProps) {
|
||||
const { customUrl } = useCluster();
|
||||
const updateCustomUrl = useUpdateCustomUrl();
|
||||
const [editing, setEditing] = React.useState(false);
|
||||
const query = useQuery();
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
|
||||
const customClass = (prefix: string) =>
|
||||
active ? `${prefix}-${activeSuffix}` : "";
|
||||
|
||||
const clusterLocation = (location: Location, url: string) => {
|
||||
const params = new URLSearchParams(location.search);
|
||||
params.set("clusterUrl", url);
|
||||
params.delete("cluster");
|
||||
const clusterLocation = (location: Location) => {
|
||||
if (customUrl.length > 0) query.set("cluster", "custom");
|
||||
return {
|
||||
...location,
|
||||
search: params.toString()
|
||||
search: query.toString()
|
||||
};
|
||||
};
|
||||
|
||||
const updateCustomUrl = React.useCallback(
|
||||
(url: string) => {
|
||||
history.push(clusterLocation(location, url));
|
||||
},
|
||||
[history, location]
|
||||
);
|
||||
const onUrlInput = useDebounceCallback((url: string) => {
|
||||
updateCustomUrl(url);
|
||||
if (url.length > 0) {
|
||||
query.set("cluster", "custom");
|
||||
history.push({ ...location, search: query.toString() });
|
||||
}
|
||||
}, 500);
|
||||
|
||||
const inputTextClass = editing ? "" : "text-muted";
|
||||
return (
|
||||
<Link
|
||||
to={location => clusterLocation(location, customUrl)}
|
||||
to={location => clusterLocation(location)}
|
||||
className="btn input-group input-group-merge p-0"
|
||||
>
|
||||
<input
|
||||
|
@ -84,7 +88,7 @@ function CustomClusterInput({ activeSuffix, active }: InputProps) {
|
|||
)}`}
|
||||
onFocus={() => setEditing(true)}
|
||||
onBlur={() => setEditing(false)}
|
||||
onInput={e => updateCustomUrl(e.currentTarget.value)}
|
||||
onInput={e => onUrlInput(e.currentTarget.value)}
|
||||
/>
|
||||
<div className="input-group-prepend">
|
||||
<div className={`input-group-text pr-0 ${customClass("border")}`}>
|
||||
|
@ -133,14 +137,10 @@ function ClusterToggle() {
|
|||
const clusterLocation = (location: Location) => {
|
||||
const params = new URLSearchParams(location.search);
|
||||
const slug = clusterSlug(net);
|
||||
if (slug && slug !== "mainnet-beta") {
|
||||
if (slug !== "mainnet-beta") {
|
||||
params.set("cluster", slug);
|
||||
params.delete("clusterUrl");
|
||||
} else {
|
||||
params.delete("cluster");
|
||||
if (slug === "mainnet-beta") {
|
||||
params.delete("clusterUrl");
|
||||
}
|
||||
}
|
||||
return {
|
||||
...location,
|
||||
|
|
|
@ -3,10 +3,9 @@ import {
|
|||
useFetchTransactionStatus,
|
||||
useTransactionStatus,
|
||||
useTransactionDetails,
|
||||
useDetailsDispatch,
|
||||
FetchStatus
|
||||
} from "../providers/transactions";
|
||||
import { fetchDetails } from "providers/transactions/details";
|
||||
import { useFetchTransactionDetails } from "providers/transactions/details";
|
||||
import { useCluster, useClusterModal } from "providers/cluster";
|
||||
import {
|
||||
TransactionSignature,
|
||||
|
@ -206,12 +205,11 @@ function StatusCard({ signature }: Props) {
|
|||
|
||||
function AccountsCard({ signature }: Props) {
|
||||
const details = useTransactionDetails(signature);
|
||||
const dispatch = useDetailsDispatch();
|
||||
const { url } = useCluster();
|
||||
|
||||
const fetchStatus = useFetchTransactionStatus();
|
||||
const fetchDetails = useFetchTransactionDetails();
|
||||
const refreshStatus = () => fetchStatus(signature);
|
||||
const refreshDetails = () => fetchDetails(dispatch, signature, url);
|
||||
const refreshDetails = () => fetchDetails(signature);
|
||||
const transaction = details?.transaction?.transaction;
|
||||
const message = React.useMemo(() => {
|
||||
return transaction?.compileMessage();
|
||||
|
@ -308,9 +306,8 @@ function AccountsCard({ signature }: Props) {
|
|||
function InstructionsSection({ signature }: Props) {
|
||||
const status = useTransactionStatus(signature);
|
||||
const details = useTransactionDetails(signature);
|
||||
const dispatch = useDetailsDispatch();
|
||||
const { url } = useCluster();
|
||||
const refreshDetails = () => fetchDetails(dispatch, signature, url);
|
||||
const fetchDetails = useFetchTransactionDetails();
|
||||
const refreshDetails = () => fetchDetails(signature);
|
||||
|
||||
if (!status || !status.info || !details || !details.transaction) return null;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import { clusterApiUrl, Connection } from "@solana/web3.js";
|
||||
import { useQuery } from "../utils/url";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
|
||||
export enum ClusterStatus {
|
||||
Connected,
|
||||
|
@ -22,7 +23,7 @@ export const CLUSTERS = [
|
|||
Cluster.Custom
|
||||
];
|
||||
|
||||
export function clusterSlug(cluster: Cluster): string | undefined {
|
||||
export function clusterSlug(cluster: Cluster): string {
|
||||
switch (cluster) {
|
||||
case Cluster.MainnetBeta:
|
||||
return "mainnet-beta";
|
||||
|
@ -31,7 +32,7 @@ export function clusterSlug(cluster: Cluster): string | undefined {
|
|||
case Cluster.Devnet:
|
||||
return "devnet";
|
||||
case Cluster.Custom:
|
||||
return undefined;
|
||||
return "custom";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,8 +53,20 @@ export const MAINNET_BETA_URL = clusterApiUrl("mainnet-beta");
|
|||
export const TESTNET_URL = clusterApiUrl("testnet");
|
||||
export const DEVNET_URL = clusterApiUrl("devnet");
|
||||
|
||||
export function clusterUrl(cluster: Cluster, customUrl: string): string {
|
||||
switch (cluster) {
|
||||
case Cluster.Devnet:
|
||||
return DEVNET_URL;
|
||||
case Cluster.MainnetBeta:
|
||||
return MAINNET_BETA_URL;
|
||||
case Cluster.Testnet:
|
||||
return TESTNET_URL;
|
||||
case Cluster.Custom:
|
||||
return customUrl;
|
||||
}
|
||||
}
|
||||
|
||||
export const DEFAULT_CLUSTER = Cluster.MainnetBeta;
|
||||
export const DEFAULT_CUSTOM_URL = "http://localhost:8899";
|
||||
|
||||
interface State {
|
||||
cluster: Cluster;
|
||||
|
@ -88,51 +101,19 @@ function clusterReducer(state: State, action: Action): State {
|
|||
}
|
||||
}
|
||||
|
||||
function parseQuery(
|
||||
query: URLSearchParams
|
||||
): { cluster: Cluster; customUrl: string } {
|
||||
function parseQuery(query: URLSearchParams): Cluster {
|
||||
const clusterParam = query.get("cluster");
|
||||
const clusterUrlParam = query.get("clusterUrl");
|
||||
|
||||
let cluster;
|
||||
let customUrl = DEFAULT_CUSTOM_URL;
|
||||
switch (clusterUrlParam) {
|
||||
case MAINNET_BETA_URL:
|
||||
cluster = Cluster.MainnetBeta;
|
||||
break;
|
||||
case DEVNET_URL:
|
||||
cluster = Cluster.Devnet;
|
||||
break;
|
||||
case TESTNET_URL:
|
||||
cluster = Cluster.Testnet;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (clusterParam) {
|
||||
case "mainnet-beta":
|
||||
cluster = Cluster.MainnetBeta;
|
||||
break;
|
||||
case "custom":
|
||||
return Cluster.Custom;
|
||||
case "devnet":
|
||||
cluster = Cluster.Devnet;
|
||||
break;
|
||||
return Cluster.Devnet;
|
||||
case "testnet":
|
||||
cluster = Cluster.Testnet;
|
||||
break;
|
||||
return Cluster.Testnet;
|
||||
case "mainnet-beta":
|
||||
default:
|
||||
return Cluster.MainnetBeta;
|
||||
}
|
||||
|
||||
if (!cluster) {
|
||||
if (!clusterUrlParam) {
|
||||
cluster = DEFAULT_CLUSTER;
|
||||
} else {
|
||||
cluster = Cluster.Custom;
|
||||
customUrl = clusterUrlParam;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
cluster,
|
||||
customUrl
|
||||
};
|
||||
}
|
||||
|
||||
type SetShowModal = React.Dispatch<React.SetStateAction<boolean>>;
|
||||
|
@ -146,16 +127,28 @@ type ClusterProviderProps = { children: React.ReactNode };
|
|||
export function ClusterProvider({ children }: ClusterProviderProps) {
|
||||
const [state, dispatch] = React.useReducer(clusterReducer, {
|
||||
cluster: DEFAULT_CLUSTER,
|
||||
customUrl: DEFAULT_CUSTOM_URL,
|
||||
customUrl: "",
|
||||
status: ClusterStatus.Connecting
|
||||
});
|
||||
const [showModal, setShowModal] = React.useState(false);
|
||||
const { cluster, customUrl } = parseQuery(useQuery());
|
||||
const query = useQuery();
|
||||
const cluster = parseQuery(query);
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
|
||||
// Reconnect to cluster when it changes
|
||||
// Reconnect to cluster when params change
|
||||
React.useEffect(() => {
|
||||
updateCluster(dispatch, cluster, customUrl);
|
||||
}, [cluster, customUrl]);
|
||||
if (cluster === Cluster.Custom) {
|
||||
// Remove cluster param if custom url has not been set
|
||||
if (state.customUrl.length === 0) {
|
||||
query.delete("cluster");
|
||||
history.push({ ...location, search: query.toString() });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
updateCluster(dispatch, cluster, state.customUrl);
|
||||
}, [cluster, state.customUrl]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<StateContext.Provider value={state}>
|
||||
|
@ -168,19 +161,6 @@ export function ClusterProvider({ children }: ClusterProviderProps) {
|
|||
);
|
||||
}
|
||||
|
||||
export function clusterUrl(cluster: Cluster, customUrl: string): string {
|
||||
switch (cluster) {
|
||||
case Cluster.Devnet:
|
||||
return DEVNET_URL;
|
||||
case Cluster.MainnetBeta:
|
||||
return MAINNET_BETA_URL;
|
||||
case Cluster.Testnet:
|
||||
return TESTNET_URL;
|
||||
case Cluster.Custom:
|
||||
return customUrl;
|
||||
}
|
||||
}
|
||||
|
||||
async function updateCluster(
|
||||
dispatch: Dispatch,
|
||||
cluster: Cluster,
|
||||
|
@ -207,6 +187,17 @@ async function updateCluster(
|
|||
}
|
||||
}
|
||||
|
||||
export function useUpdateCustomUrl() {
|
||||
const dispatch = React.useContext(DispatchContext);
|
||||
if (!dispatch) {
|
||||
throw new Error(`useUpdateCustomUrl must be used within a ClusterProvider`);
|
||||
}
|
||||
|
||||
return (customUrl: string) => {
|
||||
updateCluster(dispatch, Cluster.Custom, customUrl);
|
||||
};
|
||||
}
|
||||
|
||||
export function useCluster() {
|
||||
const context = React.useContext(StateContext);
|
||||
if (!context) {
|
||||
|
|
|
@ -128,7 +128,7 @@ export function DetailsProvider({ children }: DetailsProviderProps) {
|
|||
);
|
||||
}
|
||||
|
||||
export async function fetchDetails(
|
||||
async function fetchDetails(
|
||||
dispatch: Dispatch,
|
||||
signature: TransactionSignature,
|
||||
url: string
|
||||
|
@ -151,3 +151,17 @@ export async function fetchDetails(
|
|||
}
|
||||
dispatch({ type: ActionType.Update, fetchStatus, signature, transaction });
|
||||
}
|
||||
|
||||
export function useFetchTransactionDetails() {
|
||||
const dispatch = React.useContext(DispatchContext);
|
||||
if (!dispatch) {
|
||||
throw new Error(
|
||||
`useFetchTransactionDetails must be used within a TransactionsProvider`
|
||||
);
|
||||
}
|
||||
|
||||
const { url } = useCluster();
|
||||
return (signature: TransactionSignature) => {
|
||||
url && fetchDetails(dispatch, signature, url);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,8 +12,7 @@ import { useQuery } from "../../utils/url";
|
|||
import { useCluster, Cluster, ClusterStatus } from "../cluster";
|
||||
import {
|
||||
DetailsProvider,
|
||||
StateContext as DetailsStateContext,
|
||||
DispatchContext as DetailsDispatchContext
|
||||
StateContext as DetailsStateContext
|
||||
} from "./details";
|
||||
import base58 from "bs58";
|
||||
import { useFetchAccountInfo } from "../accounts";
|
||||
|
@ -308,16 +307,6 @@ export function useTransactionDetails(signature: TransactionSignature) {
|
|||
return context[signature];
|
||||
}
|
||||
|
||||
export function useDetailsDispatch() {
|
||||
const context = React.useContext(DetailsDispatchContext);
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
`useDetailsDispatch must be used within a TransactionsProvider`
|
||||
);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
export function useFetchTransactionStatus() {
|
||||
const dispatch = React.useContext(DispatchContext);
|
||||
if (!dispatch) {
|
||||
|
|
Loading…
Reference in New Issue