import React from "react";
import {
Connection,
VersionedMessage,
VersionedTransaction,
} from "@solana/web3.js";
import { useCluster } from "providers/cluster";
import { InstructionLogs, parseProgramLogs } from "utils/program-logs";
import { ProgramLogsCardBody } from "components/ProgramLogsCardBody";
export function SimulatorCard({ message }: { message: VersionedMessage }) {
const { cluster, url } = useCluster();
const {
simulate,
simulating,
simulationLogs: logs,
simulationError,
} = useSimulator(message);
if (simulating) {
return (
Transaction Simulation
Simulating
);
} else if (!logs) {
return (
Transaction Simulation
{simulationError ? (
<>
Simulation Failure:
{simulationError}
>
) : (
-
Simulation is free and will run this transaction against the
latest confirmed ledger state.
-
No state changes will be persisted and all signature checks will
be disabled.
)}
);
}
return (
Transaction Simulation
);
}
function useSimulator(message: VersionedMessage) {
const { cluster, url } = useCluster();
const [simulating, setSimulating] = React.useState(false);
const [logs, setLogs] = React.useState | null>(null);
const [error, setError] = React.useState();
React.useEffect(() => {
setLogs(null);
setSimulating(false);
setError(undefined);
}, [url]);
const onClick = React.useCallback(() => {
if (simulating) return;
setError(undefined);
setSimulating(true);
const connection = new Connection(url, "confirmed");
(async () => {
try {
// Simulate without signers to skip signer verification
const resp = await connection.simulateTransaction(
new VersionedTransaction(message),
{ replaceRecentBlockhash: true }
);
if (resp.value.logs === null) {
throw new Error("Expected to receive logs from simulation");
}
if (
resp.value.logs.length === 0 &&
typeof resp.value.err === "string"
) {
setLogs(null);
setError(resp.value.err);
} else {
// Prettify logs
setLogs(parseProgramLogs(resp.value.logs, resp.value.err, cluster));
}
} catch (err) {
console.error(err);
setLogs(null);
if (err instanceof Error) {
setError(err.message);
}
} finally {
setSimulating(false);
}
})();
}, [cluster, url, message, simulating]);
return {
simulate: onClick,
simulating,
simulationLogs: logs,
simulationError: error,
};
}