explorer: Update instruction details cards to handle parsed instructions for system, stake, and bpf-loader (#13247)
* update instruction cards to support system, stake, and bpf-loader parsed instructions
This commit is contained in:
@ -0,0 +1,117 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
SignatureResult,
|
||||||
|
ParsedInstruction,
|
||||||
|
ParsedTransaction,
|
||||||
|
BPF_LOADER_PROGRAM_ID,
|
||||||
|
} from "@solana/web3.js";
|
||||||
|
import { InstructionCard } from "../InstructionCard";
|
||||||
|
import { coerce } from "superstruct";
|
||||||
|
import { ParsedInfo } from "validators";
|
||||||
|
import { IX_STRUCTS } from "./types";
|
||||||
|
import { reportError } from "utils/sentry";
|
||||||
|
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
||||||
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
|
type DetailsProps = {
|
||||||
|
tx: ParsedTransaction;
|
||||||
|
ix: ParsedInstruction;
|
||||||
|
index: number;
|
||||||
|
result: SignatureResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function BpfLoaderDetailsCard(props: DetailsProps) {
|
||||||
|
try {
|
||||||
|
const parsed = coerce(props.ix.parsed, ParsedInfo);
|
||||||
|
const info = coerce(parsed.info, IX_STRUCTS[parsed.type]);
|
||||||
|
|
||||||
|
switch (parsed.type) {
|
||||||
|
case "write":
|
||||||
|
return <BpfLoaderWriteDetailsCard info={info} {...props} />;
|
||||||
|
case "finalize":
|
||||||
|
return <BpfLoaderFinalizeDetailsCard info={info} {...props} />;
|
||||||
|
default:
|
||||||
|
return <UnknownDetailsCard {...props} />;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
reportError(error, {
|
||||||
|
signature: props.tx.signatures[0],
|
||||||
|
});
|
||||||
|
return <UnknownDetailsCard {...props} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
ix: ParsedInstruction;
|
||||||
|
index: number;
|
||||||
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function BpfLoaderWriteDetailsCard(props: Props) {
|
||||||
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InstructionCard
|
||||||
|
ix={ix}
|
||||||
|
index={index}
|
||||||
|
result={result}
|
||||||
|
title="BPF Loader 2: Write"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td>Program</td>
|
||||||
|
<td className="text-lg-right">
|
||||||
|
<Address pubkey={BPF_LOADER_PROGRAM_ID} alignRight link />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Account</td>
|
||||||
|
<td className="text-lg-right">
|
||||||
|
<Address pubkey={info.account} alignRight link />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Bytes <span className="text-muted">(base 64)</span>
|
||||||
|
</td>
|
||||||
|
<td className="text-lg-right">
|
||||||
|
<code className="d-inline-block">{info.bytes}</code>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Offset</td>
|
||||||
|
<td className="text-lg-right">{info.offset}</td>
|
||||||
|
</tr>
|
||||||
|
</InstructionCard>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BpfLoaderFinalizeDetailsCard(props: Props) {
|
||||||
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InstructionCard
|
||||||
|
ix={ix}
|
||||||
|
index={index}
|
||||||
|
result={result}
|
||||||
|
title="BPF Loader 2: Finalize"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td>Program</td>
|
||||||
|
<td className="text-lg-right">
|
||||||
|
<Address pubkey={BPF_LOADER_PROGRAM_ID} alignRight link />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Account</td>
|
||||||
|
<td className="text-lg-right">
|
||||||
|
<Address pubkey={info.account} alignRight link />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</InstructionCard>
|
||||||
|
);
|
||||||
|
}
|
24
explorer/src/components/instruction/bpf-loader/types.ts
Normal file
24
explorer/src/components/instruction/bpf-loader/types.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-redeclare */
|
||||||
|
|
||||||
|
import { enums, number, pick, string, StructType } from "superstruct";
|
||||||
|
import { Pubkey } from "validators/pubkey";
|
||||||
|
|
||||||
|
const Write = pick({
|
||||||
|
account: Pubkey,
|
||||||
|
bytes: string(),
|
||||||
|
offset: number(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const Finalize = pick({
|
||||||
|
account: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
export type BpfLoaderInstructionType = StructType<
|
||||||
|
typeof BpfLoaderInstructionType
|
||||||
|
>;
|
||||||
|
export const BpfLoaderInstructionType = enums(["write", "finalize"]);
|
||||||
|
|
||||||
|
export const IX_STRUCTS: { [id: string]: any } = {
|
||||||
|
write: Write,
|
||||||
|
finalize: Finalize,
|
||||||
|
};
|
@ -1,40 +1,19 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
StakeInstruction,
|
|
||||||
StakeProgram,
|
StakeProgram,
|
||||||
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function AuthorizeDetailsCard(props: {
|
export function AuthorizeDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = StakeInstruction.decodeAuthorize(ix);
|
|
||||||
} catch (err) {
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
let authorizationType;
|
|
||||||
switch (params.stakeAuthorizationType.index) {
|
|
||||||
case 0:
|
|
||||||
authorizationType = "Staker";
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
authorizationType = "Withdrawer";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
authorizationType = "Invalid";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -53,27 +32,27 @@ export function AuthorizeDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Stake Address</td>
|
<td>Stake Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.stakePubkey} alignRight link />
|
<Address pubkey={info.stakeAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Old Authority Address</td>
|
<td>Old Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.authorizedPubkey} alignRight link />
|
<Address pubkey={info.authority} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>New Authority Address</td>
|
<td>New Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.newAuthorizedPubkey} alignRight link />
|
<Address pubkey={info.newAuthority} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Authority Type</td>
|
<td>Authority Type</td>
|
||||||
<td className="text-lg-right">{authorizationType}</td>
|
<td className="text-lg-right">{info.authorityType}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
);
|
);
|
||||||
|
@ -1,28 +1,19 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
StakeInstruction,
|
|
||||||
StakeProgram,
|
StakeProgram,
|
||||||
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function DeactivateDetailsCard(props: {
|
export function DeactivateDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = StakeInstruction.decodeDeactivate(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -41,14 +32,14 @@ export function DeactivateDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Stake Address</td>
|
<td>Stake Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.stakePubkey} alignRight link />
|
<Address pubkey={info.stakeAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Authority Address</td>
|
<td>Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.authorizedPubkey} alignRight link />
|
<Address pubkey={info.stakeAuthority} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
|
@ -1,28 +1,19 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
StakeInstruction,
|
|
||||||
StakeProgram,
|
StakeProgram,
|
||||||
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function DelegateDetailsCard(props: {
|
export function DelegateDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = StakeInstruction.decodeDelegate(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -41,21 +32,21 @@ export function DelegateDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Stake Address</td>
|
<td>Stake Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.stakePubkey} alignRight link />
|
<Address pubkey={info.stakeAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Delegated Vote Address</td>
|
<td>Delegated Vote Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.votePubkey} alignRight link />
|
<Address pubkey={info.voteAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Authority Address</td>
|
<td>Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.authorizedPubkey} alignRight link />
|
<Address pubkey={info.stakeAuthority} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
|
@ -1,29 +1,20 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
StakeInstruction,
|
|
||||||
StakeProgram,
|
StakeProgram,
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function InitializeDetailsCard(props: {
|
export function InitializeDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = StakeInstruction.decodeInitialize(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -42,45 +33,45 @@ export function InitializeDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Stake Address</td>
|
<td>Stake Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.stakePubkey} alignRight link />
|
<Address pubkey={info.stakeAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Stake Authority Address</td>
|
<td>Stake Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.authorized.staker} alignRight link />
|
<Address pubkey={info.authorized.staker} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Withdraw Authority Address</td>
|
<td>Withdraw Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.authorized.withdrawer} alignRight link />
|
<Address pubkey={info.authorized.withdrawer} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{params.lockup.epoch > 0 && (
|
{info.lockup.epoch > 0 && (
|
||||||
<tr>
|
<tr>
|
||||||
<td>Lockup Expiry Epoch</td>
|
<td>Lockup Expiry Epoch</td>
|
||||||
<td className="text-lg-right">{params.lockup.epoch}</td>
|
<td className="text-lg-right">{info.lockup.epoch}</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{params.lockup.unixTimestamp > 0 && (
|
{info.lockup.unixTimestamp > 0 && (
|
||||||
<tr>
|
<tr>
|
||||||
<td>Lockup Expiry Timestamp</td>
|
<td>Lockup Expiry Timestamp</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
{new Date(params.lockup.unixTimestamp * 1000).toUTCString()}
|
{new Date(info.lockup.unixTimestamp * 1000).toUTCString()}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!params.lockup.custodian.equals(SystemProgram.programId) && (
|
{!info.lockup.custodian.equals(SystemProgram.programId) && (
|
||||||
<tr>
|
<tr>
|
||||||
<td>Lockup Custodian Address</td>
|
<td>Lockup Custodian Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.lockup.custodian} alignRight link />
|
<Address pubkey={info.lockup.custodian} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
|
@ -1,29 +1,20 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
StakeInstruction,
|
|
||||||
StakeProgram,
|
StakeProgram,
|
||||||
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { lamportsToSolString } from "utils";
|
import { lamportsToSolString } from "utils";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function SplitDetailsCard(props: {
|
export function SplitDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = StakeInstruction.decodeSplit(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard ix={ix} index={index} result={result} title="Split Stake">
|
<InstructionCard ix={ix} index={index} result={result} title="Split Stake">
|
||||||
@ -37,29 +28,27 @@ export function SplitDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Stake Address</td>
|
<td>Stake Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.stakePubkey} alignRight link />
|
<Address pubkey={info.stakeAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Authority Address</td>
|
<td>Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.authorizedPubkey} alignRight link />
|
<Address pubkey={info.stakeAuthority} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>New Stake Address</td>
|
<td>New Stake Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.splitStakePubkey} alignRight link />
|
<Address pubkey={info.newSplitAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Split Amount (SOL)</td>
|
<td>Split Amount (SOL)</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">{lamportsToSolString(info.lamports)}</td>
|
||||||
{lamportsToSolString(params.lamports)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
StakeInstruction,
|
|
||||||
TransactionInstruction,
|
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
|
ParsedTransaction,
|
||||||
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
|
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
||||||
@ -12,36 +12,43 @@ import { AuthorizeDetailsCard } from "./AuthorizeDetailsCard";
|
|||||||
import { SplitDetailsCard } from "./SplitDetailsCard";
|
import { SplitDetailsCard } from "./SplitDetailsCard";
|
||||||
import { WithdrawDetailsCard } from "./WithdrawDetailsCard";
|
import { WithdrawDetailsCard } from "./WithdrawDetailsCard";
|
||||||
import { DeactivateDetailsCard } from "./DeactivateDetailsCard";
|
import { DeactivateDetailsCard } from "./DeactivateDetailsCard";
|
||||||
|
import { ParsedInfo } from "validators";
|
||||||
|
import { reportError } from "utils/sentry";
|
||||||
|
import { coerce } from "superstruct";
|
||||||
|
import { IX_STRUCTS } from "./types";
|
||||||
|
|
||||||
type DetailsProps = {
|
type DetailsProps = {
|
||||||
ix: TransactionInstruction;
|
tx: ParsedTransaction;
|
||||||
|
ix: ParsedInstruction;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
index: number;
|
index: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function StakeDetailsCard(props: DetailsProps) {
|
export function StakeDetailsCard(props: DetailsProps) {
|
||||||
let stakeInstructionType;
|
|
||||||
try {
|
try {
|
||||||
stakeInstructionType = StakeInstruction.decodeInstructionType(props.ix);
|
const parsed = coerce(props.ix.parsed, ParsedInfo);
|
||||||
} catch (err) {
|
const info = coerce(parsed.info, IX_STRUCTS[parsed.type]);
|
||||||
console.error(err);
|
|
||||||
|
switch (parsed.type) {
|
||||||
|
case "initialize":
|
||||||
|
return <InitializeDetailsCard info={info} {...props} />;
|
||||||
|
case "delegate":
|
||||||
|
return <DelegateDetailsCard info={info} {...props} />;
|
||||||
|
case "authorize":
|
||||||
|
return <AuthorizeDetailsCard info={info} {...props} />;
|
||||||
|
case "split":
|
||||||
|
return <SplitDetailsCard info={info} {...props} />;
|
||||||
|
case "withdraw":
|
||||||
|
return <WithdrawDetailsCard info={info} {...props} />;
|
||||||
|
case "deactivate":
|
||||||
|
return <DeactivateDetailsCard info={info} {...props} />;
|
||||||
|
default:
|
||||||
|
return <UnknownDetailsCard {...props} />;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
reportError(error, {
|
||||||
|
signature: props.tx.signatures[0],
|
||||||
|
});
|
||||||
return <UnknownDetailsCard {...props} />;
|
return <UnknownDetailsCard {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (stakeInstructionType) {
|
|
||||||
case "Initialize":
|
|
||||||
return <InitializeDetailsCard {...props} />;
|
|
||||||
case "Delegate":
|
|
||||||
return <DelegateDetailsCard {...props} />;
|
|
||||||
case "Authorize":
|
|
||||||
return <AuthorizeDetailsCard {...props} />;
|
|
||||||
case "Split":
|
|
||||||
return <SplitDetailsCard {...props} />;
|
|
||||||
case "Withdraw":
|
|
||||||
return <WithdrawDetailsCard {...props} />;
|
|
||||||
case "Deactivate":
|
|
||||||
return <DeactivateDetailsCard {...props} />;
|
|
||||||
default:
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,20 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
StakeInstruction,
|
|
||||||
StakeProgram,
|
StakeProgram,
|
||||||
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { lamportsToSolString } from "utils";
|
import { lamportsToSolString } from "utils";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function WithdrawDetailsCard(props: {
|
export function WithdrawDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = StakeInstruction.decodeWithdraw(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -42,29 +33,27 @@ export function WithdrawDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Stake Address</td>
|
<td>Stake Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.stakePubkey} alignRight link />
|
<Address pubkey={info.stakeAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Authority Address</td>
|
<td>Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.authorizedPubkey} alignRight link />
|
<Address pubkey={info.withdrawAuthority} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>To Address</td>
|
<td>To Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.toPubkey} alignRight link />
|
<Address pubkey={info.destination} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Withdraw Amount (SOL)</td>
|
<td>Withdraw Amount (SOL)</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">{lamportsToSolString(info.lamports)}</td>
|
||||||
{lamportsToSolString(params.lamports)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
);
|
);
|
||||||
|
68
explorer/src/components/instruction/stake/types.ts
Normal file
68
explorer/src/components/instruction/stake/types.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-redeclare */
|
||||||
|
|
||||||
|
import { enums, number, pick, string, StructType } from "superstruct";
|
||||||
|
import { Pubkey } from "validators/pubkey";
|
||||||
|
|
||||||
|
const Initialize = pick({
|
||||||
|
stakeAccount: Pubkey,
|
||||||
|
authorized: pick({
|
||||||
|
staker: Pubkey,
|
||||||
|
withdrawer: Pubkey,
|
||||||
|
}),
|
||||||
|
lockup: pick({
|
||||||
|
epoch: number(),
|
||||||
|
unixTimestamp: number(),
|
||||||
|
custodian: Pubkey,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const Delegate = pick({
|
||||||
|
stakeAccount: Pubkey,
|
||||||
|
voteAccount: Pubkey,
|
||||||
|
stakeAuthority: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
const Authorize = pick({
|
||||||
|
authorityType: string(),
|
||||||
|
stakeAccount: Pubkey,
|
||||||
|
authority: Pubkey,
|
||||||
|
newAuthority: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
const Split = pick({
|
||||||
|
stakeAccount: Pubkey,
|
||||||
|
stakeAuthority: Pubkey,
|
||||||
|
newSplitAccount: Pubkey,
|
||||||
|
lamports: number(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const Withdraw = pick({
|
||||||
|
stakeAccount: Pubkey,
|
||||||
|
withdrawAuthority: Pubkey,
|
||||||
|
destination: Pubkey,
|
||||||
|
lamports: number(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const Deactivate = pick({
|
||||||
|
stakeAccount: Pubkey,
|
||||||
|
stakeAuthority: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
export type StakeInstructionType = StructType<typeof StakeInstructionType>;
|
||||||
|
export const StakeInstructionType = enums([
|
||||||
|
"initialize",
|
||||||
|
"delegate",
|
||||||
|
"authorize",
|
||||||
|
"split",
|
||||||
|
"withdraw",
|
||||||
|
"deactivate",
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const IX_STRUCTS: { [id: string]: any } = {
|
||||||
|
initialize: Initialize,
|
||||||
|
delegate: Delegate,
|
||||||
|
authorize: Authorize,
|
||||||
|
split: Split,
|
||||||
|
withdraw: Withdraw,
|
||||||
|
deactivate: Deactivate,
|
||||||
|
};
|
@ -1,28 +1,19 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
SystemInstruction,
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function AllocateDetailsCard(props: {
|
export function AllocateDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = SystemInstruction.decodeAllocate(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -41,13 +32,13 @@ export function AllocateDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Account Address</td>
|
<td>Account Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.accountPubkey} alignRight link />
|
<Address pubkey={info.account} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Allocated Space (Bytes)</td>
|
<td>Allocated Space (Bytes)</td>
|
||||||
<td className="text-lg-right">{params.space}</td>
|
<td className="text-lg-right">{info.space}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
);
|
);
|
||||||
|
@ -1,29 +1,20 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
SystemInstruction,
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { Copyable } from "components/common/Copyable";
|
import { Copyable } from "components/common/Copyable";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function AllocateWithSeedDetailsCard(props: {
|
export function AllocateWithSeedDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = SystemInstruction.decodeAllocateWithSeed(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -42,35 +33,35 @@ export function AllocateWithSeedDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Account Address</td>
|
<td>Account Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.accountPubkey} alignRight link />
|
<Address pubkey={info.account} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Base Address</td>
|
<td>Base Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.basePubkey} alignRight link />
|
<Address pubkey={info.base} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Seed</td>
|
<td>Seed</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Copyable right text={params.seed}>
|
<Copyable right text={info.seed}>
|
||||||
<code>{params.seed}</code>
|
<code>{info.seed}</code>
|
||||||
</Copyable>
|
</Copyable>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Allocated Space (Bytes)</td>
|
<td>Allocated Space (Bytes)</td>
|
||||||
<td className="text-lg-right">{params.space}</td>
|
<td className="text-lg-right">{info.space}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Assigned Owner</td>
|
<td>Assigned Owner</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.programId} alignRight link />
|
<Address pubkey={info.owner} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
|
@ -1,28 +1,19 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
SystemInstruction,
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function AssignDetailsCard(props: {
|
export function AssignDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = SystemInstruction.decodeAssign(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -41,14 +32,14 @@ export function AssignDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Account Address</td>
|
<td>Account Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.accountPubkey} alignRight link />
|
<Address pubkey={info.account} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Assigned Owner</td>
|
<td>Assigned Owner</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.programId} alignRight link />
|
<Address pubkey={info.owner} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
|
@ -1,29 +1,20 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
SystemInstruction,
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { Copyable } from "components/common/Copyable";
|
import { Copyable } from "components/common/Copyable";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function AssignWithSeedDetailsCard(props: {
|
export function AssignWithSeedDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = SystemInstruction.decodeAssignWithSeed(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -42,22 +33,22 @@ export function AssignWithSeedDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Account Address</td>
|
<td>Account Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.accountPubkey} alignRight link />
|
<Address pubkey={info.account} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Base Address</td>
|
<td>Base Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.basePubkey} alignRight link />
|
<Address pubkey={info.base} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Seed</td>
|
<td>Seed</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Copyable right text={params.seed}>
|
<Copyable right text={info.seed}>
|
||||||
<code>{params.seed}</code>
|
<code>{info.seed}</code>
|
||||||
</Copyable>
|
</Copyable>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -65,7 +56,7 @@ export function AssignWithSeedDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Assigned Owner</td>
|
<td>Assigned Owner</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.programId} alignRight link />
|
<Address pubkey={info.owner} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
|
@ -1,29 +1,20 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
SystemInstruction,
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { lamportsToSolString } from "utils";
|
import { lamportsToSolString } from "utils";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function CreateDetailsCard(props: {
|
export function CreateDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = SystemInstruction.decodeCreateAccount(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -42,33 +33,31 @@ export function CreateDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>From Address</td>
|
<td>From Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.fromPubkey} alignRight link />
|
<Address pubkey={info.source} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>New Address</td>
|
<td>New Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.newAccountPubkey} alignRight link />
|
<Address pubkey={info.newAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Transfer Amount (SOL)</td>
|
<td>Transfer Amount (SOL)</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">{lamportsToSolString(info.lamports)}</td>
|
||||||
{lamportsToSolString(params.lamports)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Allocated Space (Bytes)</td>
|
<td>Allocated Space (Bytes)</td>
|
||||||
<td className="text-lg-right">{params.space}</td>
|
<td className="text-lg-right">{info.space}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Assigned Owner</td>
|
<td>Assigned Owner</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.programId} alignRight link />
|
<Address pubkey={info.owner} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
|
@ -1,30 +1,21 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
SystemInstruction,
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { lamportsToSolString } from "utils";
|
import { lamportsToSolString } from "utils";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { Copyable } from "components/common/Copyable";
|
import { Copyable } from "components/common/Copyable";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function CreateWithSeedDetailsCard(props: {
|
export function CreateWithSeedDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = SystemInstruction.decodeCreateWithSeed(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -43,49 +34,47 @@ export function CreateWithSeedDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>From Address</td>
|
<td>From Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.fromPubkey} alignRight link />
|
<Address pubkey={info.source} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>New Address</td>
|
<td>New Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.newAccountPubkey} alignRight link />
|
<Address pubkey={info.newAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Base Address</td>
|
<td>Base Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.basePubkey} alignRight link />
|
<Address pubkey={info.base} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Seed</td>
|
<td>Seed</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Copyable right text={params.seed}>
|
<Copyable right text={info.seed}>
|
||||||
<code>{params.seed}</code>
|
<code>{info.seed}</code>
|
||||||
</Copyable>
|
</Copyable>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Transfer Amount (SOL)</td>
|
<td>Transfer Amount (SOL)</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">{lamportsToSolString(info.lamports)}</td>
|
||||||
{lamportsToSolString(params.lamports)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Allocated Space (Bytes)</td>
|
<td>Allocated Space (Bytes)</td>
|
||||||
<td className="text-lg-right">{params.space}</td>
|
<td className="text-lg-right">{info.space}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Assigned Owner</td>
|
<td>Assigned Owner</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.programId} alignRight link />
|
<Address pubkey={info.owner} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
|
@ -1,28 +1,19 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
SystemInstruction,
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function NonceAdvanceDetailsCard(props: {
|
export function NonceAdvanceDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = SystemInstruction.decodeNonceAdvance(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -41,14 +32,14 @@ export function NonceAdvanceDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Nonce Address</td>
|
<td>Nonce Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.noncePubkey} alignRight link />
|
<Address pubkey={info.nonceAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Authority Address</td>
|
<td>Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.authorizedPubkey} alignRight link />
|
<Address pubkey={info.nonceAuthority} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
|
@ -1,28 +1,19 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
SystemInstruction,
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function NonceAuthorizeDetailsCard(props: {
|
export function NonceAuthorizeDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = SystemInstruction.decodeNonceAuthorize(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -41,21 +32,21 @@ export function NonceAuthorizeDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Nonce Address</td>
|
<td>Nonce Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.noncePubkey} alignRight link />
|
<Address pubkey={info.nonceAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Old Authority Address</td>
|
<td>Old Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.authorizedPubkey} alignRight link />
|
<Address pubkey={info.nonceAuthority} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>New Authority Address</td>
|
<td>New Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.newAuthorizedPubkey} alignRight link />
|
<Address pubkey={info.newAuthorized} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
|
@ -1,28 +1,19 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
SystemInstruction,
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function NonceInitializeDetailsCard(props: {
|
export function NonceInitializeDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = SystemInstruction.decodeNonceInitialize(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -41,14 +32,14 @@ export function NonceInitializeDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Nonce Address</td>
|
<td>Nonce Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.noncePubkey} alignRight link />
|
<Address pubkey={info.nonceAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Authority Address</td>
|
<td>Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.authorizedPubkey} alignRight link />
|
<Address pubkey={info.nonceAuthority} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
|
@ -1,29 +1,20 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
SystemInstruction,
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { lamportsToSolString } from "utils";
|
import { lamportsToSolString } from "utils";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function NonceWithdrawDetailsCard(props: {
|
export function NonceWithdrawDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let params;
|
|
||||||
try {
|
|
||||||
params = SystemInstruction.decodeNonceWithdraw(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard
|
<InstructionCard
|
||||||
@ -42,29 +33,27 @@ export function NonceWithdrawDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Nonce Address</td>
|
<td>Nonce Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.noncePubkey} alignRight link />
|
<Address pubkey={info.nonceAccount} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Authority Address</td>
|
<td>Authority Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.authorizedPubkey} alignRight link />
|
<Address pubkey={info.nonceAuthority} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>To Address</td>
|
<td>To Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={params.toPubkey} alignRight link />
|
<Address pubkey={info.destination} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Withdraw Amount (SOL)</td>
|
<td>Withdraw Amount (SOL)</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">{lamportsToSolString(info.lamports)}</td>
|
||||||
{lamportsToSolString(params.lamports)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
SystemInstruction,
|
|
||||||
TransactionInstruction,
|
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
|
ParsedInstruction,
|
||||||
|
ParsedTransaction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
|
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
||||||
@ -17,46 +17,53 @@ import { NonceInitializeDetailsCard } from "./NonceInitializeDetailsCard";
|
|||||||
import { NonceAdvanceDetailsCard } from "./NonceAdvanceDetailsCard";
|
import { NonceAdvanceDetailsCard } from "./NonceAdvanceDetailsCard";
|
||||||
import { NonceWithdrawDetailsCard } from "./NonceWithdrawDetailsCard";
|
import { NonceWithdrawDetailsCard } from "./NonceWithdrawDetailsCard";
|
||||||
import { NonceAuthorizeDetailsCard } from "./NonceAuthorizeDetailsCard";
|
import { NonceAuthorizeDetailsCard } from "./NonceAuthorizeDetailsCard";
|
||||||
|
import { ParsedInfo } from "validators";
|
||||||
|
import { coerce } from "superstruct";
|
||||||
|
import { reportError } from "utils/sentry";
|
||||||
|
import { IX_STRUCTS } from "./types";
|
||||||
|
|
||||||
type DetailsProps = {
|
type DetailsProps = {
|
||||||
ix: TransactionInstruction;
|
tx: ParsedTransaction;
|
||||||
|
ix: ParsedInstruction;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
index: number;
|
index: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function SystemDetailsCard(props: DetailsProps) {
|
export function SystemDetailsCard(props: DetailsProps) {
|
||||||
let systemInstructionType;
|
|
||||||
try {
|
try {
|
||||||
systemInstructionType = SystemInstruction.decodeInstructionType(props.ix);
|
const parsed = coerce(props.ix.parsed, ParsedInfo);
|
||||||
} catch (err) {
|
const info = coerce(parsed.info, IX_STRUCTS[parsed.type]);
|
||||||
console.error(err);
|
|
||||||
|
switch (parsed.type) {
|
||||||
|
case "createAccount":
|
||||||
|
return <CreateDetailsCard info={info} {...props} />;
|
||||||
|
case "createAccountWithSeed":
|
||||||
|
return <CreateWithSeedDetailsCard info={info} {...props} />;
|
||||||
|
case "allocate":
|
||||||
|
return <AllocateDetailsCard info={info} {...props} />;
|
||||||
|
case "allocateWithSeed":
|
||||||
|
return <AllocateWithSeedDetailsCard info={info} {...props} />;
|
||||||
|
case "assign":
|
||||||
|
return <AssignDetailsCard info={info} {...props} />;
|
||||||
|
case "assignWithSeed":
|
||||||
|
return <AssignWithSeedDetailsCard info={info} {...props} />;
|
||||||
|
case "transfer":
|
||||||
|
return <TransferDetailsCard info={info} {...props} />;
|
||||||
|
case "advanceNonceAccount":
|
||||||
|
return <NonceAdvanceDetailsCard info={info} {...props} />;
|
||||||
|
case "withdrawNonceAccount":
|
||||||
|
return <NonceWithdrawDetailsCard info={info} {...props} />;
|
||||||
|
case "authorizeNonceAccount":
|
||||||
|
return <NonceAuthorizeDetailsCard info={info} {...props} />;
|
||||||
|
case "initializeNonceAccount":
|
||||||
|
return <NonceInitializeDetailsCard info={info} {...props} />;
|
||||||
|
default:
|
||||||
|
return <UnknownDetailsCard {...props} />;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
reportError(error, {
|
||||||
|
signature: props.tx.signatures[0],
|
||||||
|
});
|
||||||
return <UnknownDetailsCard {...props} />;
|
return <UnknownDetailsCard {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (systemInstructionType) {
|
|
||||||
case "Create":
|
|
||||||
return <CreateDetailsCard {...props} />;
|
|
||||||
case "CreateWithSeed":
|
|
||||||
return <CreateWithSeedDetailsCard {...props} />;
|
|
||||||
case "Allocate":
|
|
||||||
return <AllocateDetailsCard {...props} />;
|
|
||||||
case "AllocateWithSeed":
|
|
||||||
return <AllocateWithSeedDetailsCard {...props} />;
|
|
||||||
case "Assign":
|
|
||||||
return <AssignDetailsCard {...props} />;
|
|
||||||
case "AssignWithSeed":
|
|
||||||
return <AssignWithSeedDetailsCard {...props} />;
|
|
||||||
case "Transfer":
|
|
||||||
return <TransferDetailsCard {...props} />;
|
|
||||||
case "AdvanceNonceAccount":
|
|
||||||
return <NonceAdvanceDetailsCard {...props} />;
|
|
||||||
case "WithdrawNonceAccount":
|
|
||||||
return <NonceWithdrawDetailsCard {...props} />;
|
|
||||||
case "AuthorizeNonceAccount":
|
|
||||||
return <NonceAuthorizeDetailsCard {...props} />;
|
|
||||||
case "InitializeNonceAccount":
|
|
||||||
return <NonceInitializeDetailsCard {...props} />;
|
|
||||||
default:
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,20 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
TransactionInstruction,
|
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
SignatureResult,
|
SignatureResult,
|
||||||
SystemInstruction,
|
ParsedInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { lamportsToSolString } from "utils";
|
import { lamportsToSolString } from "utils";
|
||||||
import { InstructionCard } from "../InstructionCard";
|
import { InstructionCard } from "../InstructionCard";
|
||||||
import { UnknownDetailsCard } from "../UnknownDetailsCard";
|
|
||||||
import { Address } from "components/common/Address";
|
import { Address } from "components/common/Address";
|
||||||
|
|
||||||
export function TransferDetailsCard(props: {
|
export function TransferDetailsCard(props: {
|
||||||
ix: TransactionInstruction;
|
ix: ParsedInstruction;
|
||||||
index: number;
|
index: number;
|
||||||
result: SignatureResult;
|
result: SignatureResult;
|
||||||
|
info: any;
|
||||||
}) {
|
}) {
|
||||||
const { ix, index, result } = props;
|
const { ix, index, result, info } = props;
|
||||||
|
|
||||||
let transfer;
|
|
||||||
try {
|
|
||||||
transfer = SystemInstruction.decodeTransfer(ix);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return <UnknownDetailsCard {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstructionCard ix={ix} index={index} result={result} title="Transfer">
|
<InstructionCard ix={ix} index={index} result={result} title="Transfer">
|
||||||
@ -37,22 +28,20 @@ export function TransferDetailsCard(props: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td>From Address</td>
|
<td>From Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={transfer.fromPubkey} alignRight link />
|
<Address pubkey={info.source} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>To Address</td>
|
<td>To Address</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">
|
||||||
<Address pubkey={transfer.toPubkey} alignRight link />
|
<Address pubkey={info.destination} alignRight link />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Transfer Amount (SOL)</td>
|
<td>Transfer Amount (SOL)</td>
|
||||||
<td className="text-lg-right">
|
<td className="text-lg-right">{lamportsToSolString(info.lamports)}</td>
|
||||||
{lamportsToSolString(transfer.lamports)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</InstructionCard>
|
</InstructionCard>
|
||||||
);
|
);
|
||||||
|
115
explorer/src/components/instruction/system/types.ts
Normal file
115
explorer/src/components/instruction/system/types.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-redeclare */
|
||||||
|
|
||||||
|
import { enums, number, pick, string, StructType } from "superstruct";
|
||||||
|
import { Pubkey } from "validators/pubkey";
|
||||||
|
|
||||||
|
const CreateAccount = pick({
|
||||||
|
source: Pubkey,
|
||||||
|
newAccount: Pubkey,
|
||||||
|
lamports: number(),
|
||||||
|
space: number(),
|
||||||
|
owner: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
const Assign = pick({
|
||||||
|
account: Pubkey,
|
||||||
|
owner: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
const Transfer = pick({
|
||||||
|
source: Pubkey,
|
||||||
|
destination: Pubkey,
|
||||||
|
lamports: number(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const CreateAccountWithSeed = pick({
|
||||||
|
source: Pubkey,
|
||||||
|
newAccount: Pubkey,
|
||||||
|
base: Pubkey,
|
||||||
|
seed: string(),
|
||||||
|
lamports: number(),
|
||||||
|
space: number(),
|
||||||
|
owner: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
const AdvanceNonceAccount = pick({
|
||||||
|
nonceAccount: Pubkey,
|
||||||
|
nonceAuthority: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
const WithdrawNonceAccount = pick({
|
||||||
|
nonceAccount: Pubkey,
|
||||||
|
destination: Pubkey,
|
||||||
|
nonceAuthority: Pubkey,
|
||||||
|
lamports: number(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const InitializeNonceAccount = pick({
|
||||||
|
nonceAccount: Pubkey,
|
||||||
|
nonceAuthority: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
const AuthorizeNonceAccount = pick({
|
||||||
|
nonceAccount: Pubkey,
|
||||||
|
nonceAuthority: Pubkey,
|
||||||
|
newAuthorized: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
const Allocate = pick({
|
||||||
|
account: Pubkey,
|
||||||
|
space: number(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const AllocateWithSeed = pick({
|
||||||
|
account: Pubkey,
|
||||||
|
base: Pubkey,
|
||||||
|
seed: string(),
|
||||||
|
space: number(),
|
||||||
|
owner: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
const AssignWithSeed = pick({
|
||||||
|
account: Pubkey,
|
||||||
|
base: Pubkey,
|
||||||
|
seed: string(),
|
||||||
|
owner: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
const TransferWithSeed = pick({
|
||||||
|
source: Pubkey,
|
||||||
|
sourceBase: Pubkey,
|
||||||
|
destination: Pubkey,
|
||||||
|
lamports: number(),
|
||||||
|
sourceSeed: string(),
|
||||||
|
sourceOwner: Pubkey,
|
||||||
|
});
|
||||||
|
|
||||||
|
export type SystemInstructionType = StructType<typeof SystemInstructionType>;
|
||||||
|
export const SystemInstructionType = enums([
|
||||||
|
"createAccount",
|
||||||
|
"createAccountWithSeed",
|
||||||
|
"allocate",
|
||||||
|
"allocateWithSeed",
|
||||||
|
"assign",
|
||||||
|
"assignWithSeed",
|
||||||
|
"transfer",
|
||||||
|
"advanceNonceAccount",
|
||||||
|
"withdrawNonceAccount",
|
||||||
|
"authorizeNonceAccount",
|
||||||
|
"initializeNonceAccount",
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const IX_STRUCTS: { [id: string]: any } = {
|
||||||
|
createAccount: CreateAccount,
|
||||||
|
createAccountWithSeed: CreateAccountWithSeed,
|
||||||
|
allocate: Allocate,
|
||||||
|
allocateWithSeed: AllocateWithSeed,
|
||||||
|
assign: Assign,
|
||||||
|
assignWithSeed: AssignWithSeed,
|
||||||
|
transfer: Transfer,
|
||||||
|
advanceNonceAccount: AdvanceNonceAccount,
|
||||||
|
withdrawNonceAccount: WithdrawNonceAccount,
|
||||||
|
authorizeNonceAccount: AuthorizeNonceAccount,
|
||||||
|
initializeNonceAccount: InitializeNonceAccount,
|
||||||
|
transferWithSeed: TransferWithSeed, // TODO: Add support for transfer with seed
|
||||||
|
};
|
@ -10,13 +10,13 @@ import { useCluster, ClusterStatus } from "providers/cluster";
|
|||||||
import {
|
import {
|
||||||
TransactionSignature,
|
TransactionSignature,
|
||||||
SystemProgram,
|
SystemProgram,
|
||||||
StakeProgram,
|
|
||||||
SystemInstruction,
|
SystemInstruction,
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
import { lamportsToSolString } from "utils";
|
import { lamportsToSolString } from "utils";
|
||||||
import { UnknownDetailsCard } from "components/instruction/UnknownDetailsCard";
|
import { UnknownDetailsCard } from "components/instruction/UnknownDetailsCard";
|
||||||
import { SystemDetailsCard } from "components/instruction/system/SystemDetailsCard";
|
import { SystemDetailsCard } from "components/instruction/system/SystemDetailsCard";
|
||||||
import { StakeDetailsCard } from "components/instruction/stake/StakeDetailsCard";
|
import { StakeDetailsCard } from "components/instruction/stake/StakeDetailsCard";
|
||||||
|
import { BpfLoaderDetailsCard } from "components/instruction/bpf-loader/BpfLoaderDetailsCard";
|
||||||
import { ErrorCard } from "components/common/ErrorCard";
|
import { ErrorCard } from "components/common/ErrorCard";
|
||||||
import { LoadingCard } from "components/common/LoadingCard";
|
import { LoadingCard } from "components/common/LoadingCard";
|
||||||
import { TableCardBody } from "components/common/TableCardBody";
|
import { TableCardBody } from "components/common/TableCardBody";
|
||||||
@ -405,23 +405,55 @@ function InstructionsSection({ signature }: SignatureProps) {
|
|||||||
const instructionDetails = transaction.message.instructions.map(
|
const instructionDetails = transaction.message.instructions.map(
|
||||||
(next, index) => {
|
(next, index) => {
|
||||||
if ("parsed" in next) {
|
if ("parsed" in next) {
|
||||||
if (next.program === "spl-token") {
|
switch (next.program) {
|
||||||
return (
|
case "spl-token":
|
||||||
<TokenDetailsCard
|
return (
|
||||||
key={index}
|
<TokenDetailsCard
|
||||||
tx={transaction}
|
key={index}
|
||||||
ix={next}
|
tx={transaction}
|
||||||
result={result}
|
ix={next}
|
||||||
index={index}
|
result={result}
|
||||||
/>
|
index={index}
|
||||||
);
|
/>
|
||||||
|
);
|
||||||
|
case "bpf-loader":
|
||||||
|
return (
|
||||||
|
<BpfLoaderDetailsCard
|
||||||
|
key={index}
|
||||||
|
tx={transaction}
|
||||||
|
ix={next}
|
||||||
|
result={result}
|
||||||
|
index={index}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case "system":
|
||||||
|
return (
|
||||||
|
<SystemDetailsCard
|
||||||
|
key={index}
|
||||||
|
tx={transaction}
|
||||||
|
ix={next}
|
||||||
|
result={result}
|
||||||
|
index={index}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case "stake":
|
||||||
|
return (
|
||||||
|
<StakeDetailsCard
|
||||||
|
key={index}
|
||||||
|
tx={transaction}
|
||||||
|
ix={next}
|
||||||
|
result={result}
|
||||||
|
index={index}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
const props = { ix: next, result, index };
|
||||||
|
return <UnknownDetailsCard key={index} {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = { ix: next, result, index };
|
|
||||||
return <UnknownDetailsCard key={index} {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ix = intoTransactionInstruction(transaction, index);
|
const ix = intoTransactionInstruction(transaction, index);
|
||||||
|
|
||||||
if (!ix) {
|
if (!ix) {
|
||||||
return (
|
return (
|
||||||
<ErrorCard
|
<ErrorCard
|
||||||
@ -432,11 +464,8 @@ function InstructionsSection({ signature }: SignatureProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const props = { ix, result, index, signature };
|
const props = { ix, result, index, signature };
|
||||||
if (SystemProgram.programId.equals(ix.programId)) {
|
|
||||||
return <SystemDetailsCard key={index} {...props} />;
|
if (isSerumInstruction(ix)) {
|
||||||
} else if (StakeProgram.programId.equals(ix.programId)) {
|
|
||||||
return <StakeDetailsCard key={index} {...props} />;
|
|
||||||
} else if (isSerumInstruction(ix)) {
|
|
||||||
return <SerumDetailsCard key={index} {...props} />;
|
return <SerumDetailsCard key={index} {...props} />;
|
||||||
} else {
|
} else {
|
||||||
return <UnknownDetailsCard key={index} {...props} />;
|
return <UnknownDetailsCard key={index} {...props} />;
|
||||||
|
Reference in New Issue
Block a user