Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added address lookup table instruction renderers #339

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { Address } from '@components/common/Address';
import { ParsedInstruction, ParsedTransaction, PublicKey, SignatureResult } from '@solana/web3.js';
import { camelToTitleCase } from '@utils/index';
import { ParsedInfo } from '@validators/index';
import React from 'react';
import { create, Struct } from 'superstruct';

import { InstructionCard } from '../InstructionCard';
import { UnknownDetailsCard } from '../UnknownDetailsCard';
import {
CloseLookupTableInfo,
CreateLookupTableInfo,
DeactivateLookupTableInfo,
ExtendLookupTableInfo,
FreezeLookupTableInfo,
} from './types';

type DetailsProps = {
tx: ParsedTransaction;
ix: ParsedInstruction;
result: SignatureResult;
index: number;
innerCards?: JSX.Element[];
childIndex?: number;
};

export function AddressLookupTableInstructionDetailsCard(props: DetailsProps) {
try {
const parsed = create(props.ix.parsed, ParsedInfo);
switch (parsed.type) {
case 'createLookupTable': {
return renderDetails<CreateLookupTableInfo>(props, parsed, CreateLookupTableInfo);
}
case 'extendLookupTable': {
return renderDetails<ExtendLookupTableInfo>(props, parsed, ExtendLookupTableInfo);
}
case 'freezeLookupTable': {
return renderDetails<FreezeLookupTableInfo>(props, parsed, FreezeLookupTableInfo);
}
case 'deactivateLookupTable': {
return renderDetails<DeactivateLookupTableInfo>(props, parsed, DeactivateLookupTableInfo);
}
case 'closeLookupTable': {
return renderDetails<CloseLookupTableInfo>(props, parsed, CloseLookupTableInfo);
}
default:
return <UnknownDetailsCard {...props} />;
}
} catch (error) {
console.error(error, {
signature: props.tx.signatures[0],
});
return <UnknownDetailsCard {...props} />;
}
}

function renderDetails<T extends object>(props: DetailsProps, parsed: ParsedInfo, struct: Struct<T>) {
const info = create(parsed.info, struct);

const attributes: JSX.Element[] = [];
for (const entry of Object.entries<any>(info)) {
const key = entry[0];
let value = entry[1];
if (value instanceof PublicKey) {
value = <Address pubkey={value} alignRight link />;
} else if (key === 'newAddresses') {
value = value.map((pubkey: PublicKey, index: number) => (
<Address key={index} pubkey={pubkey} alignRight link />
));
}

attributes.push(
<tr key={key}>
<td>{camelToTitleCase(key)}</td>
<td className="text-lg-end">{value}</td>
</tr>
);
}

return (
<InstructionCard {...props} title={`Address Lookup Table Program: ${camelToTitleCase(parsed.type)}`}>
<tr>
<td>Program</td>
<td className="text-lg-end">
<Address pubkey={props.ix.programId} alignRight link />
</td>
</tr>
{attributes}
</InstructionCard>
);
}
40 changes: 40 additions & 0 deletions app/components/instruction/address-lookup-table/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,47 @@
import { TransactionInstruction } from '@solana/web3.js';
import { PublicKeyFromString } from '@validators/pubkey';
import { array, Infer, number, type } from 'superstruct';

const PROGRAM_ID = 'AddressLookupTab1e1111111111111111111111111';

export type CreateLookupTableInfo = Infer<typeof CreateLookupTableInfo>;
export const CreateLookupTableInfo = type({
bumpSeed: number(),
lookupTableAccount: PublicKeyFromString,
lookupTableAuthority: PublicKeyFromString,
payerAccount: PublicKeyFromString,
recentSlot: number(),
systemProgram: PublicKeyFromString,
});

export type ExtendLookupTableInfo = Infer<typeof ExtendLookupTableInfo>;
export const ExtendLookupTableInfo = type({
lookupTableAccount: PublicKeyFromString,
lookupTableAuthority: PublicKeyFromString,
newAddresses: array(PublicKeyFromString),
payerAccount: PublicKeyFromString,
systemProgram: PublicKeyFromString,
});

export type FreezeLookupTableInfo = Infer<typeof FreezeLookupTableInfo>;
export const FreezeLookupTableInfo = type({
lookupTableAccount: PublicKeyFromString,
lookupTableAuthority: PublicKeyFromString,
});

export type DeactivateLookupTableInfo = Infer<typeof DeactivateLookupTableInfo>;
export const DeactivateLookupTableInfo = type({
lookupTableAccount: PublicKeyFromString,
lookupTableAuthority: PublicKeyFromString,
});

export type CloseLookupTableInfo = Infer<typeof CloseLookupTableInfo>;
export const CloseLookupTableInfo = type({
lookupTableAccount: PublicKeyFromString,
lookupTableAuthority: PublicKeyFromString,
recipient: PublicKeyFromString,
});

const INSTRUCTION_LOOKUP: { [key: number]: string } = {
0: 'Create Lookup Table',
1: 'Freeze Lookup Table',
Expand Down
3 changes: 3 additions & 0 deletions app/components/transaction/InstructionsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { intoTransactionInstruction } from '@utils/tx';
import React from 'react';
import { ErrorBoundary } from 'react-error-boundary';

import { AddressLookupTableInstructionDetailsCard } from '../instruction/address-lookup-table/AddressLookupTableInstructionDetailsCard';
import AnchorDetailsCard from '../instruction/AnchorDetailsCard';
import { isMangoInstruction } from '../instruction/mango/types';

Expand Down Expand Up @@ -181,6 +182,8 @@ function InstructionCard({
<TokenDetailsCard {...props} key={key} />
</ErrorBoundary>
);
case 'address-lookup-table':
return <AddressLookupTableInstructionDetailsCard {...props} key={key} />;
case 'bpf-loader':
return <BpfLoaderDetailsCard {...props} key={key} />;
case 'bpf-upgradeable-loader':
Expand Down
Loading