Add support for more system instruction types
This commit is contained in:
parent
7eb792a0cc
commit
01b99a0570
|
@ -9,15 +9,25 @@ import {
|
||||||
} from "../providers/transactions";
|
} from "../providers/transactions";
|
||||||
import { fetchDetails } from "providers/transactions/details";
|
import { fetchDetails } from "providers/transactions/details";
|
||||||
import { useCluster, useClusterModal } from "providers/cluster";
|
import { useCluster, useClusterModal } from "providers/cluster";
|
||||||
import { TransactionSignature, SystemInstruction } from "@solana/web3.js";
|
import {
|
||||||
|
TransactionSignature,
|
||||||
|
SystemInstruction,
|
||||||
|
SystemProgram
|
||||||
|
} from "@solana/web3.js";
|
||||||
import ClusterStatusButton from "components/ClusterStatusButton";
|
import ClusterStatusButton from "components/ClusterStatusButton";
|
||||||
import { lamportsToSolString } from "utils";
|
import { lamportsToSolString } from "utils";
|
||||||
import { displayAddress } from "utils/tx";
|
import { displayAddress } from "utils/tx";
|
||||||
import Copyable from "./Copyable";
|
import Copyable from "./Copyable";
|
||||||
import { useHistory, useLocation } from "react-router-dom";
|
import { useHistory, useLocation } from "react-router-dom";
|
||||||
import { TransferDetailsCard } from "./instruction/TransferDetailsCard";
|
import { TransferDetailsCard } from "./instruction/TransferDetailsCard";
|
||||||
|
import { AssignDetailsCard } from "./instruction/AssignDetailsCard";
|
||||||
import { CreateDetailsCard } from "./instruction/CreateDetailsCard";
|
import { CreateDetailsCard } from "./instruction/CreateDetailsCard";
|
||||||
import { RawDetailsCard } from "./instruction/RawDetailsCard";
|
import { CreateWithSeedDetailsCard } from "./instruction/CreateWithSeedDetailsCard";
|
||||||
|
import { UnknownDetailsCard } from "./instruction/UnknownDetailsCard";
|
||||||
|
import { NonceInitializeDetailsCard } from "./instruction/NonceInitializeDetailsCard";
|
||||||
|
import { NonceAdvanceDetailsCard } from "./instruction/NonceAdvanceDetailsCard";
|
||||||
|
import { NonceWithdrawDetailsCard } from "./instruction/NonceWithdrawDetailsCard";
|
||||||
|
import { NonceAuthorizeDetailsCard } from "./instruction/NonceAuthorizeDetailsCard";
|
||||||
|
|
||||||
type Props = { signature: TransactionSignature };
|
type Props = { signature: TransactionSignature };
|
||||||
export default function TransactionDetails({ signature }: Props) {
|
export default function TransactionDetails({ signature }: Props) {
|
||||||
|
@ -288,21 +298,37 @@ function InstructionsSection({ signature }: Props) {
|
||||||
const instructionDetails = transaction.instructions.map((ix, index) => {
|
const instructionDetails = transaction.instructions.map((ix, index) => {
|
||||||
const props = { ix, result, index };
|
const props = { ix, result, index };
|
||||||
|
|
||||||
let instructionType;
|
if (!ix.programId.equals(SystemProgram.programId)) {
|
||||||
try {
|
return <UnknownDetailsCard {...props} />;
|
||||||
instructionType = SystemInstruction.decodeInstructionType(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <RawDetailsCard {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (instructionType) {
|
let systemInstructionType;
|
||||||
case "Transfer":
|
try {
|
||||||
return <TransferDetailsCard {...props} />;
|
systemInstructionType = SystemInstruction.decodeInstructionType(ix);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return <UnknownDetailsCard {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (systemInstructionType) {
|
||||||
case "Create":
|
case "Create":
|
||||||
return <CreateDetailsCard {...props} />;
|
return <CreateDetailsCard {...props} />;
|
||||||
|
case "Assign":
|
||||||
|
return <AssignDetailsCard {...props} />;
|
||||||
|
case "Transfer":
|
||||||
|
return <TransferDetailsCard {...props} />;
|
||||||
|
case "CreateWithSeed":
|
||||||
|
return <CreateWithSeedDetailsCard {...props} />;
|
||||||
|
case "AdvanceNonceAccount":
|
||||||
|
return <NonceAdvanceDetailsCard {...props} />;
|
||||||
|
case "WithdrawNonceAccount":
|
||||||
|
return <NonceWithdrawDetailsCard {...props} />;
|
||||||
|
case "AuthorizeNonceAccount":
|
||||||
|
return <NonceAuthorizeDetailsCard {...props} />;
|
||||||
|
case "InitializeNonceAccount":
|
||||||
|
return <NonceInitializeDetailsCard {...props} />;
|
||||||
default:
|
default:
|
||||||
return <RawDetailsCard {...props} />;
|
return <UnknownDetailsCard {...props} />;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
TransactionInstruction,
|
||||||
|
SystemProgram,
|
||||||
|
SignatureResult,
|
||||||
|
SystemInstruction
|
||||||
|
} from "@solana/web3.js";
|
||||||
|
import { displayAddress } from "utils/tx";
|
||||||
|
import { InstructionCard } from "./InstructionCard";
|
||||||
|
import Copyable from "components/Copyable";
|
||||||
|
import { UnknownDetailsCard } from "./UnknownDetailsCard";
|
||||||
|
|
||||||
|
export function AssignDetailsCard(props: {
|
||||||
|
ix: TransactionInstruction;
|
||||||
|
index: number;
|
||||||
|
result: SignatureResult;
|
||||||
|
}) {
|
||||||
|
const { ix, index, result } = props;
|
||||||
|
|
||||||
|
let params;
|
||||||
|
try {
|
||||||
|
params = SystemInstruction.decodeAssign(ix);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return <UnknownDetailsCard {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const from = params.fromPubkey.toBase58();
|
||||||
|
const [fromMeta] = ix.keys;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InstructionCard
|
||||||
|
ix={ix}
|
||||||
|
index={index}
|
||||||
|
result={result}
|
||||||
|
title="Assign Account"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td>Program</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable bottom text={SystemProgram.programId.toBase58()}>
|
||||||
|
<code>{displayAddress(SystemProgram.programId)}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="mr-2 d-md-inline">From Address</div>
|
||||||
|
{!fromMeta.isWritable && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Readonly</span>
|
||||||
|
)}
|
||||||
|
{fromMeta.isSigner && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Signer</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={from}>
|
||||||
|
<code>{from}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Assigned Owner</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={params.programId.toBase58()}>
|
||||||
|
<code>{displayAddress(params.programId)}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</InstructionCard>
|
||||||
|
);
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import { lamportsToSolString } from "utils";
|
||||||
import { displayAddress } from "utils/tx";
|
import { displayAddress } from "utils/tx";
|
||||||
import { InstructionCard } from "./InstructionCard";
|
import { InstructionCard } from "./InstructionCard";
|
||||||
import Copyable from "components/Copyable";
|
import Copyable from "components/Copyable";
|
||||||
import { RawDetailsCard } from "./RawDetailsCard";
|
import { UnknownDetailsCard } from "./UnknownDetailsCard";
|
||||||
|
|
||||||
export function CreateDetailsCard(props: {
|
export function CreateDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: TransactionInstruction;
|
||||||
|
@ -18,20 +18,25 @@ export function CreateDetailsCard(props: {
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result } = props;
|
||||||
|
|
||||||
let create;
|
let params;
|
||||||
try {
|
try {
|
||||||
create = SystemInstruction.decodeCreateAccount(ix);
|
params = SystemInstruction.decodeCreateAccount(ix);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
return <RawDetailsCard {...props} />;
|
return <UnknownDetailsCard {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const from = create.fromPubkey.toBase58();
|
const from = params.fromPubkey.toBase58();
|
||||||
const newKey = create.newAccountPubkey.toBase58();
|
const newKey = params.newAccountPubkey.toBase58();
|
||||||
const [fromMeta, newMeta] = ix.keys;
|
const [fromMeta, newMeta] = ix.keys;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard index={index} result={result} title="Create Account">
|
<InstructionCard
|
||||||
|
ix={ix}
|
||||||
|
index={index}
|
||||||
|
result={result}
|
||||||
|
title="Create Account"
|
||||||
|
>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Program</td>
|
<td>Program</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
|
@ -77,19 +82,19 @@ export function CreateDetailsCard(props: {
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Transfer Amount (SOL)</td>
|
<td>Transfer Amount (SOL)</td>
|
||||||
<td className="text-right">{lamportsToSolString(create.lamports)}</td>
|
<td className="text-right">{lamportsToSolString(params.lamports)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Allocated Space (Bytes)</td>
|
<td>Allocated Space (Bytes)</td>
|
||||||
<td className="text-right">{create.space}</td>
|
<td className="text-right">{params.space}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Assigned Owner</td>
|
<td>Assigned Owner</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
<Copyable text={create.programId.toBase58()}>
|
<Copyable text={params.programId.toBase58()}>
|
||||||
<code>{displayAddress(create.programId)}</code>
|
<code>{displayAddress(params.programId)}</code>
|
||||||
</Copyable>
|
</Copyable>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
TransactionInstruction,
|
||||||
|
SystemProgram,
|
||||||
|
SignatureResult,
|
||||||
|
SystemInstruction
|
||||||
|
} from "@solana/web3.js";
|
||||||
|
import { lamportsToSolString } from "utils";
|
||||||
|
import { displayAddress } from "utils/tx";
|
||||||
|
import { InstructionCard } from "./InstructionCard";
|
||||||
|
import Copyable from "components/Copyable";
|
||||||
|
import { UnknownDetailsCard } from "./UnknownDetailsCard";
|
||||||
|
|
||||||
|
export function CreateWithSeedDetailsCard(props: {
|
||||||
|
ix: TransactionInstruction;
|
||||||
|
index: number;
|
||||||
|
result: SignatureResult;
|
||||||
|
}) {
|
||||||
|
const { ix, index, result } = props;
|
||||||
|
|
||||||
|
let params;
|
||||||
|
try {
|
||||||
|
params = SystemInstruction.decodeCreateWithSeed(ix);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return <UnknownDetailsCard {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const from = params.fromPubkey.toBase58();
|
||||||
|
const newKey = params.newAccountPubkey.toBase58();
|
||||||
|
const baseKey = params.basePubkey.toBase58();
|
||||||
|
const [fromMeta, newMeta] = ix.keys;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InstructionCard
|
||||||
|
ix={ix}
|
||||||
|
index={index}
|
||||||
|
result={result}
|
||||||
|
title="Create Account w/ Seed"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td>Program</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable bottom text={SystemProgram.programId.toBase58()}>
|
||||||
|
<code>{displayAddress(SystemProgram.programId)}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="mr-2 d-md-inline">From Address</div>
|
||||||
|
{!fromMeta.isWritable && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Readonly</span>
|
||||||
|
)}
|
||||||
|
{fromMeta.isSigner && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Signer</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={from}>
|
||||||
|
<code>{from}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="mr-2 d-md-inline">New Address</div>
|
||||||
|
{!newMeta.isWritable && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Readonly</span>
|
||||||
|
)}
|
||||||
|
{newMeta.isSigner && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Signer</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={newKey}>
|
||||||
|
<code>{newKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="mr-2 d-md-inline">New Address</div>
|
||||||
|
{!newMeta.isWritable && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Readonly</span>
|
||||||
|
)}
|
||||||
|
{newMeta.isSigner && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Signer</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={newKey}>
|
||||||
|
<code>{newKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Base Address</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={baseKey}>
|
||||||
|
<code>{baseKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Seed</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={params.seed}>
|
||||||
|
<code>{params.seed}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Transfer Amount (SOL)</td>
|
||||||
|
<td className="text-right">{lamportsToSolString(params.lamports)}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Allocated Space (Bytes)</td>
|
||||||
|
<td className="text-right">{params.space}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Assigned Owner</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={params.programId.toBase58()}>
|
||||||
|
<code>{displayAddress(params.programId)}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</InstructionCard>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,20 +1,27 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { SignatureResult } from "@solana/web3.js";
|
import { TransactionInstruction, SignatureResult } from "@solana/web3.js";
|
||||||
|
import { RawDetails } from "./RawDetails";
|
||||||
|
|
||||||
type InstructionProps = {
|
type InstructionProps = {
|
||||||
title: string;
|
title: string;
|
||||||
children: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
index: number;
|
index: number;
|
||||||
|
ix: TransactionInstruction;
|
||||||
|
defaultRaw?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function InstructionCard({
|
export function InstructionCard({
|
||||||
title,
|
title,
|
||||||
children,
|
children,
|
||||||
result,
|
result,
|
||||||
index
|
index,
|
||||||
|
ix,
|
||||||
|
defaultRaw
|
||||||
}: InstructionProps) {
|
}: InstructionProps) {
|
||||||
const [resultClass, errorString] = ixResult(result, index);
|
const [resultClass] = ixResult(result, index);
|
||||||
|
const [showRaw, setShowRaw] = React.useState(defaultRaw || false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<div className="card-header">
|
<div className="card-header">
|
||||||
|
@ -24,15 +31,22 @@ export function InstructionCard({
|
||||||
</span>
|
</span>
|
||||||
{title}
|
{title}
|
||||||
</h3>
|
</h3>
|
||||||
<h3 className="mb-0">
|
|
||||||
<span className="badge badge-soft-warning text-monospace">
|
<button
|
||||||
{errorString}
|
className={`btn btn-sm d-flex ${
|
||||||
</span>
|
showRaw ? "btn-dark active" : "btn-white"
|
||||||
</h3>
|
}`}
|
||||||
|
onClick={() => setShowRaw(r => !r)}
|
||||||
|
>
|
||||||
|
<span className="fe fe-code mr-1"></span>
|
||||||
|
Raw
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="table-responsive mb-0">
|
<div className="table-responsive mb-0">
|
||||||
<table className="table table-sm table-nowrap card-table">
|
<table className="table table-sm table-nowrap card-table">
|
||||||
<tbody className="list">{children}</tbody>
|
<tbody className="list">
|
||||||
|
{showRaw ? <RawDetails ix={ix} /> : children}
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
TransactionInstruction,
|
||||||
|
SystemProgram,
|
||||||
|
SignatureResult,
|
||||||
|
SystemInstruction
|
||||||
|
} from "@solana/web3.js";
|
||||||
|
import { displayAddress } from "utils/tx";
|
||||||
|
import { InstructionCard } from "./InstructionCard";
|
||||||
|
import Copyable from "components/Copyable";
|
||||||
|
import { UnknownDetailsCard } from "./UnknownDetailsCard";
|
||||||
|
|
||||||
|
export function NonceAdvanceDetailsCard(props: {
|
||||||
|
ix: TransactionInstruction;
|
||||||
|
index: number;
|
||||||
|
result: SignatureResult;
|
||||||
|
}) {
|
||||||
|
const { ix, index, result } = props;
|
||||||
|
|
||||||
|
let params;
|
||||||
|
try {
|
||||||
|
params = SystemInstruction.decodeNonceAdvance(ix);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return <UnknownDetailsCard {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nonceKey = params.noncePubkey.toBase58();
|
||||||
|
const authorizedKey = params.authorizedPubkey.toBase58();
|
||||||
|
const [nonceMeta, , authorizedMeta] = ix.keys;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InstructionCard
|
||||||
|
ix={ix}
|
||||||
|
index={index}
|
||||||
|
result={result}
|
||||||
|
title="Advance Nonce"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td>Program</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable bottom text={SystemProgram.programId.toBase58()}>
|
||||||
|
<code>{displayAddress(SystemProgram.programId)}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="mr-2 d-md-inline">Nonce Address</div>
|
||||||
|
{!nonceMeta.isWritable && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Readonly</span>
|
||||||
|
)}
|
||||||
|
{nonceMeta.isSigner && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Signer</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={nonceKey}>
|
||||||
|
<code>{nonceKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="mr-2 d-md-inline">Authorized Address</div>
|
||||||
|
{!authorizedMeta.isWritable && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Readonly</span>
|
||||||
|
)}
|
||||||
|
{authorizedMeta.isSigner && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Signer</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={authorizedKey}>
|
||||||
|
<code>{authorizedKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</InstructionCard>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
TransactionInstruction,
|
||||||
|
SystemProgram,
|
||||||
|
SignatureResult,
|
||||||
|
SystemInstruction
|
||||||
|
} from "@solana/web3.js";
|
||||||
|
import { displayAddress } from "utils/tx";
|
||||||
|
import { InstructionCard } from "./InstructionCard";
|
||||||
|
import Copyable from "components/Copyable";
|
||||||
|
import { UnknownDetailsCard } from "./UnknownDetailsCard";
|
||||||
|
|
||||||
|
export function NonceAuthorizeDetailsCard(props: {
|
||||||
|
ix: TransactionInstruction;
|
||||||
|
index: number;
|
||||||
|
result: SignatureResult;
|
||||||
|
}) {
|
||||||
|
const { ix, index, result } = props;
|
||||||
|
|
||||||
|
let params;
|
||||||
|
try {
|
||||||
|
params = SystemInstruction.decodeNonceAuthorize(ix);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return <UnknownDetailsCard {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nonceKey = params.noncePubkey.toBase58();
|
||||||
|
const authorizedKey = params.authorizedPubkey.toBase58();
|
||||||
|
const newAuthorizedKey = params.newAuthorizedPubkey.toBase58();
|
||||||
|
const [nonceMeta, authorizedMeta] = ix.keys;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InstructionCard
|
||||||
|
ix={ix}
|
||||||
|
index={index}
|
||||||
|
result={result}
|
||||||
|
title="Authorize Nonce"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td>Program</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable bottom text={SystemProgram.programId.toBase58()}>
|
||||||
|
<code>{displayAddress(SystemProgram.programId)}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="mr-2 d-md-inline">Nonce Address</div>
|
||||||
|
{!nonceMeta.isWritable && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Readonly</span>
|
||||||
|
)}
|
||||||
|
{nonceMeta.isSigner && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Signer</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={nonceKey}>
|
||||||
|
<code>{nonceKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="mr-2 d-md-inline">Authorized Address</div>
|
||||||
|
{!authorizedMeta.isWritable && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Readonly</span>
|
||||||
|
)}
|
||||||
|
{authorizedMeta.isSigner && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Signer</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={authorizedKey}>
|
||||||
|
<code>{authorizedKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>New Authorized Address</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={newAuthorizedKey}>
|
||||||
|
<code>{newAuthorizedKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</InstructionCard>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
TransactionInstruction,
|
||||||
|
SystemProgram,
|
||||||
|
SignatureResult,
|
||||||
|
SystemInstruction
|
||||||
|
} from "@solana/web3.js";
|
||||||
|
import { displayAddress } from "utils/tx";
|
||||||
|
import { InstructionCard } from "./InstructionCard";
|
||||||
|
import Copyable from "components/Copyable";
|
||||||
|
import { UnknownDetailsCard } from "./UnknownDetailsCard";
|
||||||
|
|
||||||
|
export function NonceInitializeDetailsCard(props: {
|
||||||
|
ix: TransactionInstruction;
|
||||||
|
index: number;
|
||||||
|
result: SignatureResult;
|
||||||
|
}) {
|
||||||
|
const { ix, index, result } = props;
|
||||||
|
|
||||||
|
let params;
|
||||||
|
try {
|
||||||
|
params = SystemInstruction.decodeNonceInitialize(ix);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return <UnknownDetailsCard {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nonceKey = params.noncePubkey.toBase58();
|
||||||
|
const authorizedKey = params.authorizedPubkey.toBase58();
|
||||||
|
const [nonceMeta] = ix.keys;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InstructionCard
|
||||||
|
ix={ix}
|
||||||
|
index={index}
|
||||||
|
result={result}
|
||||||
|
title="Initialize Nonce"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td>Program</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable bottom text={SystemProgram.programId.toBase58()}>
|
||||||
|
<code>{displayAddress(SystemProgram.programId)}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="mr-2 d-md-inline">Nonce Address</div>
|
||||||
|
{!nonceMeta.isWritable && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Readonly</span>
|
||||||
|
)}
|
||||||
|
{nonceMeta.isSigner && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Signer</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={nonceKey}>
|
||||||
|
<code>{nonceKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Authorized Address</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={authorizedKey}>
|
||||||
|
<code>{authorizedKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</InstructionCard>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
TransactionInstruction,
|
||||||
|
SystemProgram,
|
||||||
|
SignatureResult,
|
||||||
|
SystemInstruction
|
||||||
|
} from "@solana/web3.js";
|
||||||
|
import { displayAddress } from "utils/tx";
|
||||||
|
import { lamportsToSolString } from "utils";
|
||||||
|
import { InstructionCard } from "./InstructionCard";
|
||||||
|
import Copyable from "components/Copyable";
|
||||||
|
import { UnknownDetailsCard } from "./UnknownDetailsCard";
|
||||||
|
|
||||||
|
export function NonceWithdrawDetailsCard(props: {
|
||||||
|
ix: TransactionInstruction;
|
||||||
|
index: number;
|
||||||
|
result: SignatureResult;
|
||||||
|
}) {
|
||||||
|
const { ix, index, result } = props;
|
||||||
|
|
||||||
|
let params;
|
||||||
|
try {
|
||||||
|
params = SystemInstruction.decodeNonceWithdraw(ix);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return <UnknownDetailsCard {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nonceKey = params.noncePubkey.toBase58();
|
||||||
|
const toKey = params.toPubkey.toBase58();
|
||||||
|
const authorizedKey = params.authorizedPubkey.toBase58();
|
||||||
|
const lamports = params.lamports;
|
||||||
|
const [nonceMeta, toMeta, , , authorizedMeta] = ix.keys;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InstructionCard
|
||||||
|
ix={ix}
|
||||||
|
index={index}
|
||||||
|
result={result}
|
||||||
|
title="Withdraw Nonce"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td>Program</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable bottom text={SystemProgram.programId.toBase58()}>
|
||||||
|
<code>{displayAddress(SystemProgram.programId)}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="mr-2 d-md-inline">Nonce Address</div>
|
||||||
|
{!nonceMeta.isWritable && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Readonly</span>
|
||||||
|
)}
|
||||||
|
{nonceMeta.isSigner && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Signer</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={nonceKey}>
|
||||||
|
<code>{nonceKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="mr-2 d-md-inline">Authorized Address</div>
|
||||||
|
{!authorizedMeta.isWritable && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Readonly</span>
|
||||||
|
)}
|
||||||
|
{authorizedMeta.isSigner && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Signer</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={authorizedKey}>
|
||||||
|
<code>{authorizedKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="mr-2 d-md-inline">To Address</div>
|
||||||
|
{!toMeta.isWritable && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Readonly</span>
|
||||||
|
)}
|
||||||
|
{toMeta.isSigner && (
|
||||||
|
<span className="badge badge-soft-dark mr-1">Signer</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-right">
|
||||||
|
<Copyable text={toKey}>
|
||||||
|
<code>{toKey}</code>
|
||||||
|
</Copyable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Withdraw Amount (SOL)</td>
|
||||||
|
<td className="text-right">{lamportsToSolString(lamports)}</td>
|
||||||
|
</tr>
|
||||||
|
</InstructionCard>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,21 +1,20 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import bs58 from "bs58";
|
import bs58 from "bs58";
|
||||||
import { TransactionInstruction, SignatureResult } from "@solana/web3.js";
|
import { TransactionInstruction } from "@solana/web3.js";
|
||||||
import { displayAddress } from "utils/tx";
|
import { displayAddress } from "utils/tx";
|
||||||
import { InstructionCard } from "./InstructionCard";
|
|
||||||
import Copyable from "components/Copyable";
|
import Copyable from "components/Copyable";
|
||||||
|
|
||||||
export function RawDetailsCard({
|
function displayData(data: string) {
|
||||||
ix,
|
if (data.length > 50) {
|
||||||
index,
|
return `${data.substring(0, 49)}…`;
|
||||||
result
|
}
|
||||||
}: {
|
return data;
|
||||||
ix: TransactionInstruction;
|
}
|
||||||
index: number;
|
|
||||||
result: SignatureResult;
|
export function RawDetails({ ix }: { ix: TransactionInstruction }) {
|
||||||
}) {
|
const data = bs58.encode(ix.data);
|
||||||
return (
|
return (
|
||||||
<InstructionCard index={index} result={result} title="Raw">
|
<>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Program</td>
|
<td>Program</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
|
@ -47,11 +46,11 @@ export function RawDetailsCard({
|
||||||
<tr>
|
<tr>
|
||||||
<td>Raw Data (Base58)</td>
|
<td>Raw Data (Base58)</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
<Copyable text={bs58.encode(ix.data)}>
|
<Copyable text={data}>
|
||||||
<code>{bs58.encode(ix.data)}</code>
|
<code>{displayData(data)}</code>
|
||||||
</Copyable>
|
</Copyable>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -9,7 +9,7 @@ import { lamportsToSolString } from "utils";
|
||||||
import { displayAddress } from "utils/tx";
|
import { displayAddress } from "utils/tx";
|
||||||
import { InstructionCard } from "./InstructionCard";
|
import { InstructionCard } from "./InstructionCard";
|
||||||
import Copyable from "components/Copyable";
|
import Copyable from "components/Copyable";
|
||||||
import { RawDetailsCard } from "./RawDetailsCard";
|
import { UnknownDetailsCard } from "./UnknownDetailsCard";
|
||||||
|
|
||||||
export function TransferDetailsCard(props: {
|
export function TransferDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: TransactionInstruction;
|
||||||
|
@ -23,14 +23,14 @@ export function TransferDetailsCard(props: {
|
||||||
transfer = SystemInstruction.decodeTransfer(ix);
|
transfer = SystemInstruction.decodeTransfer(ix);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
return <RawDetailsCard {...props} />;
|
return <UnknownDetailsCard {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const from = transfer.fromPubkey.toBase58();
|
const from = transfer.fromPubkey.toBase58();
|
||||||
const to = transfer.toPubkey.toBase58();
|
const to = transfer.toPubkey.toBase58();
|
||||||
const [fromMeta, toMeta] = ix.keys;
|
const [fromMeta, toMeta] = ix.keys;
|
||||||
return (
|
return (
|
||||||
<InstructionCard index={index} result={result} title="Transfer">
|
<InstructionCard ix={ix} index={index} result={result} title="Transfer">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Program</td>
|
<td>Program</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import React from "react";
|
||||||
|
import { TransactionInstruction, SignatureResult } from "@solana/web3.js";
|
||||||
|
import { InstructionCard } from "./InstructionCard";
|
||||||
|
|
||||||
|
export function UnknownDetailsCard({
|
||||||
|
ix,
|
||||||
|
index,
|
||||||
|
result
|
||||||
|
}: {
|
||||||
|
ix: TransactionInstruction;
|
||||||
|
index: number;
|
||||||
|
result: SignatureResult;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<InstructionCard
|
||||||
|
ix={ix}
|
||||||
|
index={index}
|
||||||
|
result={result}
|
||||||
|
title="Unknown"
|
||||||
|
defaultRaw
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue