Clean up explorer data providers (#11334)
This commit is contained in:
parent
0d8f3139ae
commit
b6ea9f1861
|
@ -19,8 +19,6 @@ import { useFetchAccountHistory } from "providers/accounts/history";
|
|||
|
||||
type Props = { address: string };
|
||||
export default function AccountDetails({ address }: Props) {
|
||||
const fetchAccount = useFetchAccountInfo();
|
||||
|
||||
let pubkey: PublicKey | undefined;
|
||||
try {
|
||||
pubkey = new PublicKey(address);
|
||||
|
@ -29,11 +27,6 @@ export default function AccountDetails({ address }: Props) {
|
|||
// TODO handle bad addresses
|
||||
}
|
||||
|
||||
// Fetch account on load
|
||||
React.useEffect(() => {
|
||||
if (pubkey) fetchAccount(pubkey);
|
||||
}, [address]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<div className="container mt-n3">
|
||||
<div className="header">
|
||||
|
@ -49,10 +42,16 @@ export default function AccountDetails({ address }: Props) {
|
|||
}
|
||||
|
||||
function AccountCards({ pubkey }: { pubkey: PublicKey }) {
|
||||
const fetchAccount = useFetchAccountInfo();
|
||||
const address = pubkey.toBase58();
|
||||
const info = useAccountInfo(address);
|
||||
const refresh = useFetchAccountInfo();
|
||||
|
||||
// Fetch account on load
|
||||
React.useEffect(() => {
|
||||
if (pubkey && !info) fetchAccount(pubkey);
|
||||
}, [address]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
if (!info || info.status === FetchStatus.Fetching) {
|
||||
return <LoadingCard />;
|
||||
} else if (
|
||||
|
|
|
@ -28,13 +28,6 @@ import { isCached } from "providers/transactions/cached";
|
|||
|
||||
type Props = { signature: TransactionSignature };
|
||||
export default function TransactionDetails({ signature }: Props) {
|
||||
const fetchTransaction = useFetchTransactionStatus();
|
||||
|
||||
// Fetch transaction on load
|
||||
React.useEffect(() => {
|
||||
fetchTransaction(signature);
|
||||
}, [signature]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<div className="container mt-n3">
|
||||
<div className="header">
|
||||
|
@ -52,11 +45,17 @@ export default function TransactionDetails({ signature }: Props) {
|
|||
}
|
||||
|
||||
function StatusCard({ signature }: Props) {
|
||||
const fetchStatus = useFetchTransactionStatus();
|
||||
const status = useTransactionStatus(signature);
|
||||
const refresh = useFetchTransactionStatus();
|
||||
const details = useTransactionDetails(signature);
|
||||
const { firstAvailableBlock } = useCluster();
|
||||
|
||||
// Fetch transaction on load
|
||||
React.useEffect(() => {
|
||||
if (!status) fetchStatus(signature);
|
||||
}, [signature]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
if (!status || status.fetchStatus === FetchStatus.Fetching) {
|
||||
return <LoadingCard />;
|
||||
} else if (status?.fetchStatus === FetchStatus.FetchFailed) {
|
||||
|
|
|
@ -19,7 +19,7 @@ type State = { [address: string]: AccountHistory };
|
|||
export enum ActionType {
|
||||
Update,
|
||||
Add,
|
||||
Remove,
|
||||
Clear,
|
||||
}
|
||||
|
||||
interface Update {
|
||||
|
@ -32,38 +32,26 @@ interface Update {
|
|||
|
||||
interface Add {
|
||||
type: ActionType.Add;
|
||||
addresses: string[];
|
||||
address: string;
|
||||
}
|
||||
|
||||
interface Remove {
|
||||
type: ActionType.Remove;
|
||||
addresses: string[];
|
||||
interface Clear {
|
||||
type: ActionType.Clear;
|
||||
}
|
||||
|
||||
type Action = Update | Add | Remove;
|
||||
type Action = Update | Add | Clear;
|
||||
type Dispatch = (action: Action) => void;
|
||||
|
||||
function reducer(state: State, action: Action): State {
|
||||
switch (action.type) {
|
||||
case ActionType.Add: {
|
||||
if (action.addresses.length === 0) return state;
|
||||
const details = { ...state };
|
||||
action.addresses.forEach((address) => {
|
||||
if (!details[address]) {
|
||||
details[address] = {
|
||||
status: FetchStatus.Fetching,
|
||||
};
|
||||
}
|
||||
});
|
||||
return details;
|
||||
}
|
||||
|
||||
case ActionType.Remove: {
|
||||
if (action.addresses.length === 0) return state;
|
||||
const details = { ...state };
|
||||
action.addresses.forEach((address) => {
|
||||
delete details[address];
|
||||
});
|
||||
const address = action.address;
|
||||
if (!details[address]) {
|
||||
details[address] = {
|
||||
status: FetchStatus.Fetching,
|
||||
};
|
||||
}
|
||||
return details;
|
||||
}
|
||||
|
||||
|
@ -87,6 +75,10 @@ function reducer(state: State, action: Action): State {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ActionType.Clear: {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
@ -100,45 +92,33 @@ const DispatchContext = React.createContext<Dispatch | undefined>(undefined);
|
|||
type HistoryProviderProps = { children: React.ReactNode };
|
||||
export function HistoryProvider({ children }: HistoryProviderProps) {
|
||||
const [state, dispatch] = React.useReducer(reducer, {});
|
||||
const { accounts } = useAccounts();
|
||||
const { accounts, lastFetchedAddress } = useAccounts();
|
||||
const { url } = useCluster();
|
||||
|
||||
const manager = React.useRef(new HistoryManager(url));
|
||||
React.useEffect(() => {
|
||||
manager.current = new HistoryManager(url);
|
||||
dispatch({ type: ActionType.Clear });
|
||||
}, [url]);
|
||||
|
||||
// Fetch history for new accounts
|
||||
React.useEffect(() => {
|
||||
const removeAddresses = new Set<string>();
|
||||
const fetchAddresses = new Set<string>();
|
||||
accounts.forEach(({ pubkey, lamports }) => {
|
||||
const address = pubkey.toBase58();
|
||||
if (lamports !== undefined && !state[address])
|
||||
fetchAddresses.add(address);
|
||||
else if (lamports === undefined && state[address])
|
||||
removeAddresses.add(address);
|
||||
});
|
||||
|
||||
const removeList: string[] = [];
|
||||
removeAddresses.forEach((address) => {
|
||||
manager.current.removeAccountHistory(address);
|
||||
removeList.push(address);
|
||||
});
|
||||
dispatch({ type: ActionType.Remove, addresses: removeList });
|
||||
|
||||
const fetchList: string[] = [];
|
||||
fetchAddresses.forEach((s) => fetchList.push(s));
|
||||
dispatch({ type: ActionType.Add, addresses: fetchList });
|
||||
fetchAddresses.forEach((address) => {
|
||||
fetchAccountHistory(
|
||||
dispatch,
|
||||
new PublicKey(address),
|
||||
manager.current,
|
||||
true
|
||||
);
|
||||
});
|
||||
}, [accounts]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
if (lastFetchedAddress) {
|
||||
const infoFetched =
|
||||
accounts[lastFetchedAddress] &&
|
||||
accounts[lastFetchedAddress].lamports !== undefined;
|
||||
const noHistory = !state[lastFetchedAddress];
|
||||
if (infoFetched && noHistory) {
|
||||
dispatch({ type: ActionType.Add, address: lastFetchedAddress });
|
||||
fetchAccountHistory(
|
||||
dispatch,
|
||||
new PublicKey(lastFetchedAddress),
|
||||
manager.current,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
}, [accounts, lastFetchedAddress]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<ManagerContext.Provider value={manager.current}>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React from "react";
|
||||
import { StakeAccount } from "solana-sdk-wasm";
|
||||
import { PublicKey, Connection, StakeProgram } from "@solana/web3.js";
|
||||
import { useQuery } from "../../utils/url";
|
||||
import { useCluster, ClusterStatus } from "../cluster";
|
||||
import { HistoryProvider } from "./history";
|
||||
export { useAccountHistory } from "./history";
|
||||
|
@ -20,7 +19,6 @@ export interface Details {
|
|||
}
|
||||
|
||||
export interface Account {
|
||||
id: number;
|
||||
pubkey: PublicKey;
|
||||
status: FetchStatus;
|
||||
lamports?: number;
|
||||
|
@ -29,13 +27,14 @@ export interface Account {
|
|||
|
||||
type Accounts = { [address: string]: Account };
|
||||
interface State {
|
||||
idCounter: number;
|
||||
accounts: Accounts;
|
||||
lastFetchedAddress: string | undefined;
|
||||
}
|
||||
|
||||
export enum ActionType {
|
||||
Update,
|
||||
Fetch,
|
||||
Clear,
|
||||
}
|
||||
|
||||
interface Update {
|
||||
|
@ -53,7 +52,11 @@ interface Fetch {
|
|||
pubkey: PublicKey;
|
||||
}
|
||||
|
||||
type Action = Update | Fetch;
|
||||
interface Clear {
|
||||
type: ActionType.Clear;
|
||||
}
|
||||
|
||||
type Action = Update | Fetch | Clear;
|
||||
type Dispatch = (action: Action) => void;
|
||||
|
||||
function reducer(state: State, action: Action): State {
|
||||
|
@ -65,23 +68,20 @@ function reducer(state: State, action: Action): State {
|
|||
const accounts = {
|
||||
...state.accounts,
|
||||
[address]: {
|
||||
id: account.id,
|
||||
pubkey: account.pubkey,
|
||||
status: FetchStatus.Fetching,
|
||||
},
|
||||
};
|
||||
return { ...state, accounts };
|
||||
return { ...state, accounts, lastFetchedAddress: address };
|
||||
} else {
|
||||
const idCounter = state.idCounter + 1;
|
||||
const accounts = {
|
||||
...state.accounts,
|
||||
[address]: {
|
||||
id: idCounter,
|
||||
status: FetchStatus.Fetching,
|
||||
pubkey: action.pubkey,
|
||||
},
|
||||
};
|
||||
return { ...state, accounts, idCounter };
|
||||
return { ...state, accounts, lastFetchedAddress: address };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,13 @@ function reducer(state: State, action: Action): State {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ActionType.Clear: {
|
||||
return {
|
||||
...state,
|
||||
accounts: {},
|
||||
};
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
@ -113,40 +120,20 @@ const DispatchContext = React.createContext<Dispatch | undefined>(undefined);
|
|||
type AccountsProviderProps = { children: React.ReactNode };
|
||||
export function AccountsProvider({ children }: AccountsProviderProps) {
|
||||
const [state, dispatch] = React.useReducer(reducer, {
|
||||
idCounter: 0,
|
||||
accounts: {},
|
||||
lastFetchedAddress: undefined,
|
||||
});
|
||||
|
||||
const { status, url } = useCluster();
|
||||
|
||||
// Check account statuses on startup and whenever cluster updates
|
||||
const { status, url } = useCluster();
|
||||
React.useEffect(() => {
|
||||
Object.keys(state.accounts).forEach((address) => {
|
||||
fetchAccountInfo(dispatch, new PublicKey(address), url, status);
|
||||
});
|
||||
if (status === ClusterStatus.Connecting) {
|
||||
dispatch({ type: ActionType.Clear });
|
||||
} else if (status === ClusterStatus.Connected && state.lastFetchedAddress) {
|
||||
fetchAccountInfo(dispatch, new PublicKey(state.lastFetchedAddress), url);
|
||||
}
|
||||
}, [status, url]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const query = useQuery();
|
||||
const values = ACCOUNT_ALIASES.concat(ACCOUNT_ALIASES_PLURAL).map((key) =>
|
||||
query.get(key)
|
||||
);
|
||||
React.useEffect(() => {
|
||||
values
|
||||
.filter((value): value is string => value !== null)
|
||||
.flatMap((value) => value.split(","))
|
||||
// Remove duplicates
|
||||
.filter((item, pos, self) => self.indexOf(item) === pos)
|
||||
.filter((address) => !state.accounts[address])
|
||||
.forEach((address) => {
|
||||
try {
|
||||
fetchAccountInfo(dispatch, new PublicKey(address), url, status);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
// TODO handle bad addresses
|
||||
}
|
||||
});
|
||||
}, [values.toString()]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<StateContext.Provider value={state}>
|
||||
<DispatchContext.Provider value={dispatch}>
|
||||
|
@ -159,17 +146,13 @@ export function AccountsProvider({ children }: AccountsProviderProps) {
|
|||
async function fetchAccountInfo(
|
||||
dispatch: Dispatch,
|
||||
pubkey: PublicKey,
|
||||
url: string,
|
||||
status: ClusterStatus
|
||||
url: string
|
||||
) {
|
||||
dispatch({
|
||||
type: ActionType.Fetch,
|
||||
pubkey,
|
||||
});
|
||||
|
||||
// We will auto-refetch when status is no longer connecting
|
||||
if (status === ClusterStatus.Connecting) return;
|
||||
|
||||
let fetchStatus;
|
||||
let details;
|
||||
let lamports;
|
||||
|
@ -213,12 +196,7 @@ export function useAccounts() {
|
|||
if (!context) {
|
||||
throw new Error(`useAccounts must be used within a AccountsProvider`);
|
||||
}
|
||||
return {
|
||||
idCounter: context.idCounter,
|
||||
accounts: Object.values(context.accounts).sort((a, b) =>
|
||||
a.id <= b.id ? 1 : -1
|
||||
),
|
||||
};
|
||||
return context;
|
||||
}
|
||||
|
||||
export function useAccountInfo(address: string) {
|
||||
|
@ -239,8 +217,8 @@ export function useFetchAccountInfo() {
|
|||
);
|
||||
}
|
||||
|
||||
const { url, status } = useCluster();
|
||||
const { url } = useCluster();
|
||||
return (pubkey: PublicKey) => {
|
||||
fetchAccountInfo(dispatch, pubkey, url, status);
|
||||
fetchAccountInfo(dispatch, pubkey, url);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ type State = { [signature: string]: Details };
|
|||
export enum ActionType {
|
||||
Update,
|
||||
Add,
|
||||
Remove,
|
||||
Clear,
|
||||
}
|
||||
|
||||
interface Update {
|
||||
|
@ -30,39 +30,27 @@ interface Update {
|
|||
|
||||
interface Add {
|
||||
type: ActionType.Add;
|
||||
signatures: TransactionSignature[];
|
||||
signature: TransactionSignature;
|
||||
}
|
||||
|
||||
interface Remove {
|
||||
type: ActionType.Remove;
|
||||
signatures: TransactionSignature[];
|
||||
interface Clear {
|
||||
type: ActionType.Clear;
|
||||
}
|
||||
|
||||
type Action = Update | Add | Remove;
|
||||
type Action = Update | Add | Clear;
|
||||
type Dispatch = (action: Action) => void;
|
||||
|
||||
function reducer(state: State, action: Action): State {
|
||||
switch (action.type) {
|
||||
case ActionType.Add: {
|
||||
if (action.signatures.length === 0) return state;
|
||||
const details = { ...state };
|
||||
action.signatures.forEach((signature) => {
|
||||
if (!details[signature]) {
|
||||
details[signature] = {
|
||||
fetchStatus: FetchStatus.Fetching,
|
||||
transaction: null,
|
||||
};
|
||||
}
|
||||
});
|
||||
return details;
|
||||
}
|
||||
|
||||
case ActionType.Remove: {
|
||||
if (action.signatures.length === 0) return state;
|
||||
const details = { ...state };
|
||||
action.signatures.forEach((signature) => {
|
||||
delete details[signature];
|
||||
});
|
||||
const signature = action.signature;
|
||||
if (!details[signature]) {
|
||||
details[signature] = {
|
||||
fetchStatus: FetchStatus.Fetching,
|
||||
transaction: null,
|
||||
};
|
||||
}
|
||||
return details;
|
||||
}
|
||||
|
||||
|
@ -81,6 +69,10 @@ function reducer(state: State, action: Action): State {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ActionType.Clear: {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
@ -93,32 +85,26 @@ export const DispatchContext = React.createContext<Dispatch | undefined>(
|
|||
type DetailsProviderProps = { children: React.ReactNode };
|
||||
export function DetailsProvider({ children }: DetailsProviderProps) {
|
||||
const [state, dispatch] = React.useReducer(reducer, {});
|
||||
|
||||
const { transactions } = useTransactions();
|
||||
const { transactions, lastFetched } = useTransactions();
|
||||
const { url } = useCluster();
|
||||
|
||||
React.useEffect(() => {
|
||||
dispatch({ type: ActionType.Clear });
|
||||
}, [url]);
|
||||
|
||||
// Filter blocks for current transaction slots
|
||||
React.useEffect(() => {
|
||||
const removeSignatures = new Set<string>();
|
||||
const fetchSignatures = new Set<string>();
|
||||
transactions.forEach(({ signature, info }) => {
|
||||
if (info?.confirmations === "max" && !state[signature])
|
||||
fetchSignatures.add(signature);
|
||||
else if (info?.confirmations !== "max" && state[signature])
|
||||
removeSignatures.add(signature);
|
||||
});
|
||||
|
||||
const removeList: string[] = [];
|
||||
removeSignatures.forEach((s) => removeList.push(s));
|
||||
dispatch({ type: ActionType.Remove, signatures: removeList });
|
||||
|
||||
const fetchList: string[] = [];
|
||||
fetchSignatures.forEach((s) => fetchList.push(s));
|
||||
dispatch({ type: ActionType.Add, signatures: fetchList });
|
||||
fetchSignatures.forEach((signature) => {
|
||||
fetchDetails(dispatch, signature, url);
|
||||
});
|
||||
}, [transactions]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
if (lastFetched) {
|
||||
const confirmed =
|
||||
transactions[lastFetched] &&
|
||||
transactions[lastFetched].info?.confirmations === "max";
|
||||
const noDetails = !state[lastFetched];
|
||||
if (confirmed && noDetails) {
|
||||
dispatch({ type: ActionType.Add, signature: lastFetched });
|
||||
fetchDetails(dispatch, lastFetched, url);
|
||||
}
|
||||
}
|
||||
}, [transactions, lastFetched]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<StateContext.Provider value={state}>
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
PublicKey,
|
||||
sendAndConfirmTransaction,
|
||||
} from "@solana/web3.js";
|
||||
import { useQuery } from "../../utils/url";
|
||||
import { useQuery } from "utils/url";
|
||||
import { useCluster, Cluster, ClusterStatus } from "../cluster";
|
||||
import {
|
||||
DetailsProvider,
|
||||
|
@ -36,7 +36,6 @@ export interface TransactionStatusInfo {
|
|||
}
|
||||
|
||||
export interface TransactionStatus {
|
||||
id: number;
|
||||
fetchStatus: FetchStatus;
|
||||
signature: TransactionSignature;
|
||||
info?: TransactionStatusInfo;
|
||||
|
@ -44,13 +43,14 @@ export interface TransactionStatus {
|
|||
|
||||
type Transactions = { [signature: string]: TransactionStatus };
|
||||
interface State {
|
||||
idCounter: number;
|
||||
transactions: Transactions;
|
||||
lastFetched: TransactionSignature | undefined;
|
||||
}
|
||||
|
||||
export enum ActionType {
|
||||
UpdateStatus,
|
||||
FetchSignature,
|
||||
Clear,
|
||||
}
|
||||
|
||||
interface UpdateStatus {
|
||||
|
@ -65,14 +65,18 @@ interface FetchSignature {
|
|||
signature: TransactionSignature;
|
||||
}
|
||||
|
||||
type Action = UpdateStatus | FetchSignature;
|
||||
interface Clear {
|
||||
type: ActionType.Clear;
|
||||
}
|
||||
|
||||
type Action = UpdateStatus | FetchSignature | Clear;
|
||||
type Dispatch = (action: Action) => void;
|
||||
|
||||
function reducer(state: State, action: Action): State {
|
||||
switch (action.type) {
|
||||
case ActionType.FetchSignature: {
|
||||
const transaction = state.transactions[action.signature];
|
||||
const signature = action.signature;
|
||||
const transaction = state.transactions[signature];
|
||||
if (transaction) {
|
||||
const transactions = {
|
||||
...state.transactions,
|
||||
|
@ -82,18 +86,16 @@ function reducer(state: State, action: Action): State {
|
|||
info: undefined,
|
||||
},
|
||||
};
|
||||
return { ...state, transactions };
|
||||
return { ...state, transactions, lastFetched: signature };
|
||||
} else {
|
||||
const nextId = state.idCounter + 1;
|
||||
const transactions = {
|
||||
...state.transactions,
|
||||
[action.signature]: {
|
||||
id: nextId,
|
||||
signature: action.signature,
|
||||
fetchStatus: FetchStatus.Fetching,
|
||||
},
|
||||
};
|
||||
return { ...state, transactions, idCounter: nextId };
|
||||
return { ...state, transactions, lastFetched: signature };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,6 +114,13 @@ function reducer(state: State, action: Action): State {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ActionType.Clear: {
|
||||
return {
|
||||
...state,
|
||||
transactions: {},
|
||||
};
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
@ -124,8 +133,8 @@ const DispatchContext = React.createContext<Dispatch | undefined>(undefined);
|
|||
type TransactionsProviderProps = { children: React.ReactNode };
|
||||
export function TransactionsProvider({ children }: TransactionsProviderProps) {
|
||||
const [state, dispatch] = React.useReducer(reducer, {
|
||||
idCounter: 0,
|
||||
transactions: {},
|
||||
lastFetched: undefined,
|
||||
});
|
||||
|
||||
const { cluster, status: clusterStatus, url } = useCluster();
|
||||
|
@ -135,9 +144,11 @@ export function TransactionsProvider({ children }: TransactionsProviderProps) {
|
|||
|
||||
// Check transaction statuses whenever cluster updates
|
||||
React.useEffect(() => {
|
||||
Object.keys(state.transactions).forEach((signature) => {
|
||||
fetchTransactionStatus(dispatch, signature, url, clusterStatus);
|
||||
});
|
||||
if (clusterStatus === ClusterStatus.Connecting) {
|
||||
dispatch({ type: ActionType.Clear });
|
||||
} else if (clusterStatus === ClusterStatus.Connected && state.lastFetched) {
|
||||
fetchTransactionStatus(dispatch, state.lastFetched, url);
|
||||
}
|
||||
|
||||
// Create a test transaction
|
||||
if (cluster === Cluster.Devnet && testFlag !== null) {
|
||||
|
@ -145,23 +156,6 @@ export function TransactionsProvider({ children }: TransactionsProviderProps) {
|
|||
}
|
||||
}, [testFlag, cluster, clusterStatus, url]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// Check for transactions in the url params
|
||||
const values = TX_ALIASES.flatMap((key) => [
|
||||
query.get(key),
|
||||
query.get(key + "s"),
|
||||
]);
|
||||
React.useEffect(() => {
|
||||
values
|
||||
.filter((value): value is string => value !== null)
|
||||
.flatMap((value) => value.split(","))
|
||||
// Remove duplicates
|
||||
.filter((item, pos, self) => self.indexOf(item) === pos)
|
||||
.filter((signature) => !state.transactions[signature])
|
||||
.forEach((signature) => {
|
||||
fetchTransactionStatus(dispatch, signature, url, clusterStatus);
|
||||
});
|
||||
}, [values.toString()]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<StateContext.Provider value={state}>
|
||||
<DispatchContext.Provider value={dispatch}>
|
||||
|
@ -189,7 +183,7 @@ async function createTestTransaction(
|
|||
testAccount.publicKey,
|
||||
100000
|
||||
);
|
||||
fetchTransactionStatus(dispatch, signature, url, clusterStatus);
|
||||
fetchTransactionStatus(dispatch, signature, url);
|
||||
fetchAccount(testAccount.publicKey);
|
||||
} catch (error) {
|
||||
console.error("Failed to create test success transaction", error);
|
||||
|
@ -208,7 +202,7 @@ async function createTestTransaction(
|
|||
[testAccount],
|
||||
{ confirmations: 1, skipPreflight: false }
|
||||
);
|
||||
fetchTransactionStatus(dispatch, signature, url, clusterStatus);
|
||||
fetchTransactionStatus(dispatch, signature, url);
|
||||
} catch (error) {
|
||||
console.error("Failed to create test failure transaction", error);
|
||||
}
|
||||
|
@ -217,17 +211,13 @@ async function createTestTransaction(
|
|||
export async function fetchTransactionStatus(
|
||||
dispatch: Dispatch,
|
||||
signature: TransactionSignature,
|
||||
url: string,
|
||||
status: ClusterStatus
|
||||
url: string
|
||||
) {
|
||||
dispatch({
|
||||
type: ActionType.FetchSignature,
|
||||
signature,
|
||||
});
|
||||
|
||||
// We will auto-refetch when status is no longer connecting
|
||||
if (status === ClusterStatus.Connecting) return;
|
||||
|
||||
let fetchStatus;
|
||||
let info: TransactionStatusInfo | undefined;
|
||||
if (isCached(url, signature)) {
|
||||
|
@ -281,12 +271,7 @@ export function useTransactions() {
|
|||
`useTransactions must be used within a TransactionsProvider`
|
||||
);
|
||||
}
|
||||
return {
|
||||
idCounter: context.idCounter,
|
||||
transactions: Object.values(context.transactions).sort((a, b) =>
|
||||
a.id <= b.id ? 1 : -1
|
||||
),
|
||||
};
|
||||
return context;
|
||||
}
|
||||
|
||||
export function useTransactionStatus(signature: TransactionSignature) {
|
||||
|
@ -321,8 +306,8 @@ export function useFetchTransactionStatus() {
|
|||
);
|
||||
}
|
||||
|
||||
const { url, status } = useCluster();
|
||||
const { url } = useCluster();
|
||||
return (signature: TransactionSignature) => {
|
||||
fetchTransactionStatus(dispatch, signature, url, status);
|
||||
fetchTransactionStatus(dispatch, signature, url);
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue