Add support for more system instruction types
This commit is contained in:
parent
7eb792a0cc
commit
01b99a0570
|
@ -9,15 +9,25 @@ import {
|
|||
} from "../providers/transactions";
|
||||
import { fetchDetails } from "providers/transactions/details";
|
||||
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 { lamportsToSolString } from "utils";
|
||||
import { displayAddress } from "utils/tx";
|
||||
import Copyable from "./Copyable";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import { TransferDetailsCard } from "./instruction/TransferDetailsCard";
|
||||
import { AssignDetailsCard } from "./instruction/AssignDetailsCard";
|
||||
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 };
|
||||
export default function TransactionDetails({ signature }: Props) {
|
||||
|
@ -288,21 +298,37 @@ function InstructionsSection({ signature }: Props) {
|
|||
const instructionDetails = transaction.instructions.map((ix, index) => {
|
||||
const props = { ix, result, index };
|
||||
|
||||
let instructionType;
|
||||
try {
|
||||
instructionType = SystemInstruction.decodeInstructionType(ix);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return <RawDetailsCard {...props} />;
|
||||
if (!ix.programId.equals(SystemProgram.programId)) {
|
||||
return <UnknownDetailsCard {...props} />;
|
||||
}
|
||||
|
||||
switch (instructionType) {
|
||||
case "Transfer":
|
||||
return <TransferDetailsCard {...props} />;
|
||||
let systemInstructionType;
|
||||
try {
|
||||
systemInstructionType = SystemInstruction.decodeInstructionType(ix);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return <UnknownDetailsCard {...props} />;
|
||||
}
|
||||
|
||||
switch (systemInstructionType) {
|
||||
case "Create":
|
||||
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:
|
||||
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 { InstructionCard } from "./InstructionCard";
|
||||
import Copyable from "components/Copyable";
|
||||
import { RawDetailsCard } from "./RawDetailsCard";
|
||||
import { UnknownDetailsCard } from "./UnknownDetailsCard";
|
||||
|
||||
export function CreateDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
|
@ -18,20 +18,25 @@ export function CreateDetailsCard(props: {
|
|||
}) {
|
||||
const { ix, index, result } = props;
|
||||
|
||||
let create;
|
||||
let params;
|
||||
try {
|
||||
create = SystemInstruction.decodeCreateAccount(ix);
|
||||
params = SystemInstruction.decodeCreateAccount(ix);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return <RawDetailsCard {...props} />;
|
||||
return <UnknownDetailsCard {...props} />;
|
||||
}
|
||||
|
||||
const from = create.fromPubkey.toBase58();
|
||||
const newKey = create.newAccountPubkey.toBase58();
|
||||
const from = params.fromPubkey.toBase58();
|
||||
const newKey = params.newAccountPubkey.toBase58();
|
||||
const [fromMeta, newMeta] = ix.keys;
|
||||
|
||||
return (
|
||||
<InstructionCard index={index} result={result} title="Create Account">
|
||||
<InstructionCard
|
||||
ix={ix}
|
||||
index={index}
|
||||
result={result}
|
||||
title="Create Account"
|
||||
>
|
||||
<tr>
|
||||
<td>Program</td>
|
||||
<td className="text-right">
|
||||
|
@ -77,19 +82,19 @@ export function CreateDetailsCard(props: {
|
|||
|
||||
<tr>
|
||||
<td>Transfer Amount (SOL)</td>
|
||||
<td className="text-right">{lamportsToSolString(create.lamports)}</td>
|
||||
<td className="text-right">{lamportsToSolString(params.lamports)}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Allocated Space (Bytes)</td>
|
||||
<td className="text-right">{create.space}</td>
|
||||
<td className="text-right">{params.space}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Assigned Owner</td>
|
||||
<td className="text-right">
|
||||
<Copyable text={create.programId.toBase58()}>
|
||||
<code>{displayAddress(create.programId)}</code>
|
||||
<Copyable text={params.programId.toBase58()}>
|
||||
<code>{displayAddress(params.programId)}</code>
|
||||
</Copyable>
|
||||
</td>
|
||||
</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 { SignatureResult } from "@solana/web3.js";
|
||||
import { TransactionInstruction, SignatureResult } from "@solana/web3.js";
|
||||
import { RawDetails } from "./RawDetails";
|
||||
|
||||
type InstructionProps = {
|
||||
title: string;
|
||||
children: React.ReactNode;
|
||||
children?: React.ReactNode;
|
||||
result: SignatureResult;
|
||||
index: number;
|
||||
ix: TransactionInstruction;
|
||||
defaultRaw?: boolean;
|
||||
};
|
||||
|
||||
export function InstructionCard({
|
||||
title,
|
||||
children,
|
||||
result,
|
||||
index
|
||||
index,
|
||||
ix,
|
||||
defaultRaw
|
||||
}: InstructionProps) {
|
||||
const [resultClass, errorString] = ixResult(result, index);
|
||||
const [resultClass] = ixResult(result, index);
|
||||
const [showRaw, setShowRaw] = React.useState(defaultRaw || false);
|
||||
|
||||
return (
|
||||
<div className="card">
|
||||
<div className="card-header">
|
||||
|
@ -24,15 +31,22 @@ export function InstructionCard({
|
|||
</span>
|
||||
{title}
|
||||
</h3>
|
||||
<h3 className="mb-0">
|
||||
<span className="badge badge-soft-warning text-monospace">
|
||||
{errorString}
|
||||
</span>
|
||||
</h3>
|
||||
|
||||
<button
|
||||
className={`btn btn-sm d-flex ${
|
||||
showRaw ? "btn-dark active" : "btn-white"
|
||||
}`}
|
||||
onClick={() => setShowRaw(r => !r)}
|
||||
>
|
||||
<span className="fe fe-code mr-1"></span>
|
||||
Raw
|
||||
</button>
|
||||
</div>
|
||||
<div className="table-responsive mb-0">
|
||||
<table className="table table-sm table-nowrap card-table">
|
||||
<tbody className="list">{children}</tbody>
|
||||
<tbody className="list">
|
||||
{showRaw ? <RawDetails ix={ix} /> : children}
|
||||
</tbody>
|
||||
</table>
|
||||
</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 bs58 from "bs58";
|
||||
import { TransactionInstruction, SignatureResult } from "@solana/web3.js";
|
||||
import { TransactionInstruction } from "@solana/web3.js";
|
||||
import { displayAddress } from "utils/tx";
|
||||
import { InstructionCard } from "./InstructionCard";
|
||||
import Copyable from "components/Copyable";
|
||||
|
||||
export function RawDetailsCard({
|
||||
ix,
|
||||
index,
|
||||
result
|
||||
}: {
|
||||
ix: TransactionInstruction;
|
||||
index: number;
|
||||
result: SignatureResult;
|
||||
}) {
|
||||
function displayData(data: string) {
|
||||
if (data.length > 50) {
|
||||
return `${data.substring(0, 49)}…`;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
export function RawDetails({ ix }: { ix: TransactionInstruction }) {
|
||||
const data = bs58.encode(ix.data);
|
||||
return (
|
||||
<InstructionCard index={index} result={result} title="Raw">
|
||||
<>
|
||||
<tr>
|
||||
<td>Program</td>
|
||||
<td className="text-right">
|
||||
|
@ -47,11 +46,11 @@ export function RawDetailsCard({
|
|||
<tr>
|
||||
<td>Raw Data (Base58)</td>
|
||||
<td className="text-right">
|
||||
<Copyable text={bs58.encode(ix.data)}>
|
||||
<code>{bs58.encode(ix.data)}</code>
|
||||
<Copyable text={data}>
|
||||
<code>{displayData(data)}</code>
|
||||
</Copyable>
|
||||
</td>
|
||||
</tr>
|
||||
</InstructionCard>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -9,7 +9,7 @@ import { lamportsToSolString } from "utils";
|
|||
import { displayAddress } from "utils/tx";
|
||||
import { InstructionCard } from "./InstructionCard";
|
||||
import Copyable from "components/Copyable";
|
||||
import { RawDetailsCard } from "./RawDetailsCard";
|
||||
import { UnknownDetailsCard } from "./UnknownDetailsCard";
|
||||
|
||||
export function TransferDetailsCard(props: {
|
||||
ix: TransactionInstruction;
|
||||
|
@ -23,14 +23,14 @@ export function TransferDetailsCard(props: {
|
|||
transfer = SystemInstruction.decodeTransfer(ix);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return <RawDetailsCard {...props} />;
|
||||
return <UnknownDetailsCard {...props} />;
|
||||
}
|
||||
|
||||
const from = transfer.fromPubkey.toBase58();
|
||||
const to = transfer.toPubkey.toBase58();
|
||||
const [fromMeta, toMeta] = ix.keys;
|
||||
return (
|
||||
<InstructionCard index={index} result={result} title="Transfer">
|
||||
<InstructionCard ix={ix} index={index} result={result} title="Transfer">
|
||||
<tr>
|
||||
<td>Program</td>
|
||||
<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