Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
26 changes: 23 additions & 3 deletions app/entities/instruction-card/__tests__/args.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,22 @@ const KEY = '2W7rVWpiRMzex7sGBnww6sozQp94xFBzCGYUzUKZw2X4';

describe('parseCodamaArgs', () => {
it('should drop the discriminator and the enum and option tag keys', () => {
expect(parseCodamaArgs({ __kind: 'A', __option: 'Some', discriminator: 3 })).toEqual([]);
expect(parseCodamaArgs({ __discriminator: 0, __kind: 'A', __option: 'Some', discriminator: 3 })).toEqual([]);
});

it('should parse a decoded enum as its variant without the discriminator tag', () => {
const [data, scalar] = parseCodamaArgs({
data: { __discriminator: 2, __kind: 'Lamports', value: 2 },
scalar: { __discriminator: 1, __kind: 'Burning' },
});

expect(scalar).toEqual(textLeaf('scalar', 'enum', 'Burning'));
expect(data).toEqual({
children: [textLeaf('value', 'number', '2')],
kind: 'group',
name: 'data',
type: 'Lamports',
});
});

it('should keep field order', () => {
Expand Down Expand Up @@ -102,13 +117,18 @@ describe('parseCodamaArgs', () => {
empty: [],
map: new Map(),
none: none(),
unit: { __kind: 'A' },
}),
).toEqual([
{ kind: 'empty', name: 'empty', type: 'Array[0]' },
{ kind: 'empty', name: 'map', type: 'Map[0]' },
{ kind: 'empty', name: 'none', type: 'Option(None)' },
{ kind: 'empty', name: 'unit', type: 'A' },
]);
});

it('should parse an enum variant without a payload as an enum value', () => {
expect(parseCodamaArgs({ list: [{ __kind: 'Arm' }], unit: { __kind: 'A' } })).toEqual([
{ children: [textLeaf('#0', 'enum', 'Arm')], kind: 'group', name: 'list', type: 'Array[1]' },
textLeaf('unit', 'enum', 'A'),
]);
});

Expand Down
9 changes: 7 additions & 2 deletions app/entities/instruction-card/model/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function parseCodamaArgs(data: unknown): readonly InstructionArg[] {
return parseFields(data).filter(arg => arg.name !== 'discriminator');
}

const TAG_KEYS = new Set(['__kind', '__option']);
const TAG_KEYS = new Set(['__discriminator', '__kind', '__option']);

function parseFields(struct: Record<string, unknown>): InstructionArg[] {
return Object.entries(struct)
Expand All @@ -34,7 +34,12 @@ function parseArg(name: string, value: unknown): InstructionArg {
return parseItems({ items: entries, name, type: `Map[${value.size}]` });
}
if (isStruct(value)) {
return group({ children: parseFields(value), name, type: groupType(value) });
const children = parseFields(value);
// An enum variant without a payload is a plain value.
if (typeof value.__kind === 'string' && children.length === 0) {
return { kind: 'leaf', name, type: 'enum', value: { kind: 'text', value: value.__kind } };
}
return group({ children, name, type: groupType(value) });
}
if (typeof value === 'string') {
return isAddress(value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { AccountRole, isSignerRole, isWritableRole } from '@solana/kit';
import { PublicKey, TransactionInstruction } from '@solana/web3.js';
import { fireEvent, render, screen, within } from '@testing-library/react';
import {
enumEmptyVariantTypeNode,
enumStructVariantTypeNode,
enumTypeNode,
fieldDiscriminatorNode,
type InstructionAccountNode,
instructionAccountNode,
Expand Down Expand Up @@ -78,6 +81,26 @@ const COUNTER_IDL = rootNode(
discriminator: 3,
name: 'configure',
}),
counterInstruction({
arguments: [
instructionArgumentNode({
name: 'mode',
type: enumTypeNode([enumEmptyVariantTypeNode('locking'), enumEmptyVariantTypeNode('burning')]),
}),
instructionArgumentNode({
name: 'limit',
type: enumTypeNode([
enumEmptyVariantTypeNode('unlimited'),
enumStructVariantTypeNode(
'capped',
structTypeNode([structFieldTypeNode({ name: 'max', type: numberTypeNode('u8') })]),
),
]),
}),
],
discriminator: 4,
name: 'setMode',
}),
],
name: 'counter',
publicKey: PROGRAM.toBase58(),
Expand Down Expand Up @@ -173,6 +196,20 @@ describe('CodamaInstructionCard', () => {
expect(screen.getByText('Expand')).toBeInTheDocument();
});

it('should render decoded enums by their variant names', async () => {
await renderBuilt(client.methods.setMode({ limit: { __kind: 'Capped', max: 7 }, mode: 'burning' }));

expect(screen.getByTestId('ix-args-0-0')).toHaveTextContent('modeenumBurning');
expect(screen.getByTestId('ix-args-0-1')).toHaveTextContent('limit');
expect(screen.getByTestId('ix-args-0-1')).toHaveTextContent('Capped');

fireEvent.click(screen.getByText('Expand'));

expect(screen.getByTestId('ix-args-1-0')).toHaveTextContent('max');
expect(screen.getByTestId('ix-args-1-0')).toHaveTextContent('7');
expect(screen.queryByText('__discriminator')).not.toBeInTheDocument();
});

it('should render the Unknown card when the parse does not start at a root node', () => {
renderCard({
accounts: [],
Expand Down
26 changes: 13 additions & 13 deletions bench/BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
| Static | `/` | 140 kB | 550 kB |
| Static | `/_not-found` | 0 B | 420 kB |
| Dynamic | `/address/[address]` | 470 kB | 890 kB |
| Dynamic | `/address/[address]/account-data` | 480 kB | 900 kB |
| Dynamic | `/address/[address]/account-data` | 480 kB | 890 kB |
| Dynamic | `/address/[address]/anchor-account` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/attestation` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/attributes` | 440 kB | 850 kB |
Expand All @@ -15,20 +15,20 @@
| Dynamic | `/address/[address]/domains` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/entries` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/feature-gate` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/idl` | 550 kB | 970 kB |
| Dynamic | `/address/[address]/idl` | 550 kB | 960 kB |
| Dynamic | `/address/[address]/instructions` | 450 kB | 860 kB |
| Dynamic | `/address/[address]/metadata` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/nftoken-collection-nfts` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/program-multisig` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/rewards` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/security` | 440 kB | 860 kB |
| Dynamic | `/address/[address]/security` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/slot-hashes` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/stake-history` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/subscriptions` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/token-extensions` | 440 kB | 860 kB |
| Dynamic | `/address/[address]/tokens` | 450 kB | 870 kB |
| Dynamic | `/address/[address]/tokens` | 450 kB | 860 kB |
| Dynamic | `/address/[address]/transfers` | 450 kB | 860 kB |
| Dynamic | `/address/[address]/verified-build` | 440 kB | 860 kB |
| Dynamic | `/address/[address]/verified-build` | 440 kB | 850 kB |
| Dynamic | `/address/[address]/vote-history` | 440 kB | 850 kB |
| Dynamic | `/api/ans-domains/[address]` | — | — |
| Dynamic | `/api/domain-info/[domain]` | — | — |
Expand All @@ -50,20 +50,20 @@
| Dynamic | `/api/verification/coingecko/[address]` | — | — |
| Dynamic | `/api/verification/jupiter/[mintAddress]` | — | — |
| Dynamic | `/api/verification/rugcheck/[mintAddress]` | — | — |
| Dynamic | `/block/[slot]` | 170 kB | 590 kB |
| Dynamic | `/block/[slot]/accounts` | 150 kB | 570 kB |
| Dynamic | `/block/[slot]` | 170 kB | 580 kB |
| Dynamic | `/block/[slot]/accounts` | 160 kB | 570 kB |
| Dynamic | `/block/[slot]/programs` | 160 kB | 570 kB |
| Dynamic | `/block/[slot]/rewards` | 160 kB | 580 kB |
| Dynamic | `/block/[slot]/rewards` | 160 kB | 570 kB |
| Dynamic | `/epoch/[epoch]` | 20 kB | 430 kB |
| Static | `/feature-gates` | 50 kB | 470 kB |
| Static | `/feature-gates` | 50 kB | 460 kB |
| Dynamic | `/mcp` | — | — |
| Static | `/mcp/start` | 30 kB | 440 kB |
| Dynamic | `/og/feature-gate/[address]` | — | — |
| Dynamic | `/og/receipt/[signature]` | — | — |
| Dynamic | `/og/tx/[signature]` | — | — |
| Static | `/opengraph-image.png` | — | — |
| Dynamic | `/robots.txt` | — | — |
| Static | `/tos` | 10 kB | 430 kB |
| Dynamic | `/tx/[signature]` | 490 kB | 900 kB |
| Dynamic | `/tx/[signature]/inspect` | 470 kB | 890 kB |
| Static | `/tx/inspector` | 470 kB | 890 kB |
| Static | `/tos` | 10 kB | 420 kB |
| Dynamic | `/tx/[signature]` | 480 kB | 900 kB |
| Dynamic | `/tx/[signature]/inspect` | 470 kB | 880 kB |
| Static | `/tx/inspector` | 470 kB | 880 kB |
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
"vitest:test": "vitest --project specs"
},
"dependencies": {
"@codama/dynamic-client": "0.1.4",
"@codama/dynamic-parsers": "1.3.1",
"@codama/nodes-from-anchor": "1.5.3",
"@codama/dynamic-client": "1.0.0",
"@codama/dynamic-parsers": "1.4.2",
"@codama/nodes-from-anchor": "1.5.6",
"@coral-xyz/anchor": "0.30.1",
"@explorer/decoder-mango": "workspace:*",
"@explorer/decoder-pyth": "workspace:*",
Expand Down Expand Up @@ -107,7 +107,7 @@
"client-only": "0.0.1",
"clsx": "2.1.1",
"cmdk": "1.1.1",
"codama": "1.10.0",
"codama": "1.11.0",
"cross-spawn": "7.0.6",
"date-fns": "4.1.0",
"fuse.js": "7.1.0",
Expand Down
Loading
Loading