Skip to content

Commit

Permalink
Add anchor details to instruction card on tx inspector (#341)
Browse files Browse the repository at this point in the history
When possible, use the anchor description card instead of the default
instruction card on the tx simulation page. 

Before:
<img width="1238" alt="Screen Shot 2024-05-19 at 1 01 28 PM"
src="https://github.com/solana-labs/explorer/assets/1320260/f11c902e-3fd1-4b30-8ecc-f79f103c1935">

After:
<img width="1273" alt="Screen Shot 2024-05-19 at 1 01 47 PM"
src="https://github.com/solana-labs/explorer/assets/1320260/2733821e-e807-41be-91a0-50d58d9e7851">
  • Loading branch information
brittcyr authored Aug 6, 2024
1 parent 1ac3288 commit f99560d
Showing 1 changed file with 52 additions and 2 deletions.
54 changes: 52 additions & 2 deletions app/components/inspector/InstructionsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import { HexData } from '@components/common/HexData';
import { TableCardBody } from '@components/common/TableCardBody';
import { useCluster } from '@providers/cluster';
import { useScrollAnchor } from '@providers/scroll-anchor';
import { MessageCompiledInstruction, VersionedMessage } from '@solana/web3.js';
import { AccountMeta, MessageCompiledInstruction, PublicKey, TransactionInstruction, VersionedMessage } from '@solana/web3.js';
import getInstructionCardScrollAnchorId from '@utils/get-instruction-card-scroll-anchor-id';
import { getProgramName } from '@utils/tx';
import React from 'react';

import { useAnchorProgram } from '@/app/providers/anchor';

import AnchorDetailsCard from '../instruction/AnchorDetailsCard';
import { AddressFromLookupTableWithContext, AddressWithContext, programValidator } from './AddressWithContext';

export function InstructionsSection({ message }: { message: VersionedMessage }) {
Expand All @@ -29,7 +32,7 @@ function InstructionCard({
index: number;
}) {
const [expanded, setExpanded] = React.useState(false);
const { cluster } = useCluster();
const { cluster, url } = useCluster();
const programId = message.staticAccountKeys[ix.programIdIndex];
const programName = getProgramName(programId.toBase58(), cluster);
const scrollAnchorRef = useScrollAnchor(getInstructionCardScrollAnchorId([index + 1]));
Expand All @@ -47,6 +50,53 @@ function InstructionCard({
}))
),
];
const anchorProgram = useAnchorProgram(programId.toString(), url);

if (anchorProgram) {
const accountMetas = ix.accountKeyIndexes.map((accountIndex, _index) => {
let lookup: PublicKey;
if (accountIndex >= message.staticAccountKeys.length) {
const lookupIndex = accountIndex - message.staticAccountKeys.length;
lookup = lookupsForAccountKeyIndex[lookupIndex].lookupTableKey;
} else {
lookup = message.staticAccountKeys[accountIndex];
}

const isSigner = accountIndex < message.header.numRequiredSignatures;
const isWritable = message.isAccountWritable(accountIndex);
const accountMeta: AccountMeta = {
isSigner,
isWritable,
pubkey: lookup,
};
return accountMeta;
});

const transactionInstruction: TransactionInstruction = new TransactionInstruction({
data: Buffer.from(message.compiledInstructions[index].data),
keys: accountMetas,
programId: programId,
});

return AnchorDetailsCard({
anchorProgram: anchorProgram,
childIndex: undefined,
index: index,
// Inner cards and child are not used since we do not know what CPIs
// will be called until simulation happens, and even then, all we
// get is logs, not the TransactionInstructions
innerCards: undefined,
ix: transactionInstruction,
// Always display success since it is too complicated to determine
// based on the simulation and pass that result here. Could be added
// later if desired, possibly similar to innerCards from parsing tx
// sim logs.
result: { err: null},
// Signature is not needed.
signature: '',
});
}

return (
<div className="card" key={index} ref={scrollAnchorRef}>
<div className={`card-header${!expanded ? ' border-bottom-none' : ''}`}>
Expand Down

0 comments on commit f99560d

Please sign in to comment.