@@ -4,6 +4,7 @@ import { useCluster } from '@providers/cluster';
44import { ASSOCIATED_TOKEN_PROGRAM_ID , TOKEN_PROGRAM_ID } from '@solana/spl-token' ;
55import {
66 AddressLookupTableAccount ,
7+ type CompiledInnerInstruction ,
78 ComputeBudgetProgram ,
89 SystemProgram ,
910 TransactionInstruction ,
@@ -15,6 +16,7 @@ import { getProgramName } from '@utils/tx';
1516import React from 'react' ;
1617import { ErrorBoundary } from 'react-error-boundary' ;
1718
19+ import { isTokenBatchInstruction , resolveInnerBatchInstructions , TokenBatchCard } from '@/app/features/token-batch' ;
1820import { useAddressLookupTables } from '@/app/providers/accounts' ;
1921import { FetchStatus } from '@/app/providers/cache' ;
2022
@@ -29,7 +31,15 @@ import { AssociatedTokenDetailsCard } from './associated-token/AssociatedTokenDe
2931import { intoParsedInstruction , intoParsedTransaction } from './into-parsed-data' ;
3032import { UnknownDetailsCard } from './UnknownDetailsCard' ;
3133
32- export function InstructionsSection ( { message } : { message : VersionedMessage } ) {
34+ const INSPECTOR_RESULT = { err : null } ;
35+
36+ export function InstructionsSection ( {
37+ message,
38+ compiledInnerInstructions,
39+ } : {
40+ message : VersionedMessage ;
41+ compiledInnerInstructions ?: CompiledInnerInstruction [ ] ;
42+ } ) {
3343 // Fetch all address lookup tables
3444 const hydratedTables = useAddressLookupTables (
3545 message . addressTableLookups . map ( lookup => lookup . accountKey . toString ( ) ) ,
@@ -59,10 +69,32 @@ export function InstructionsSection({ message }: { message: VersionedMessage })
5969 ) ;
6070 const transactionMessage = TransactionMessage . decompile ( message , { addressLookupTableAccounts } ) ;
6171
72+ const batchByIndex = compiledInnerInstructions
73+ ? resolveInnerBatchInstructions (
74+ compiledInnerInstructions ,
75+ message . getAccountKeys ( { addressLookupTableAccounts } ) ,
76+ message ,
77+ )
78+ : { } ;
79+
6280 return (
6381 < >
6482 { transactionMessage . instructions . map ( ( ix , index ) => {
65- return < InspectorInstructionCard key = { index } { ...{ index, ix, message } } /> ;
83+ const batchInnerCards = batchByIndex [ index ] ?. map ( ( innerIx , childIndex ) => (
84+ < ErrorBoundary key = { childIndex } fallback = { null } >
85+ < TokenBatchCard index = { index } childIndex = { childIndex } ix = { innerIx } result = { INSPECTOR_RESULT } />
86+ </ ErrorBoundary >
87+ ) ) ;
88+
89+ return (
90+ < InspectorInstructionCard
91+ key = { index }
92+ index = { index }
93+ ix = { ix }
94+ message = { message }
95+ innerCards = { batchInnerCards }
96+ />
97+ ) ;
6698 } ) }
6799 </ >
68100 ) ;
@@ -72,10 +104,12 @@ function InspectorInstructionCard({
72104 message,
73105 ix,
74106 index,
107+ innerCards,
75108} : {
76109 message : VersionedMessage ;
77110 ix : TransactionInstruction ;
78111 index : number ;
112+ innerCards ?: React . ReactNode [ ] ;
79113} ) {
80114 const { cluster, url } = useCluster ( ) ;
81115
@@ -91,23 +125,25 @@ function InspectorInstructionCard({
91125 < AnchorDetailsCard
92126 anchorProgram = { anchorProgram . program }
93127 index = { index }
94- // Inner cards and child are not used since we do not know what CPIs
95- // will be called until simulation happens, and even then, all we
96- // get is logs, not the TransactionInstructions
97128 innerCards = { undefined }
98129 ix = { ix }
99- // Always display success since it is too complicated to determine
100- // based on the simulation and pass that result here. Could be added
101- // later if desired, possibly similar to innerCards from parsing tx
102- // sim logs.
103130 result = { { err : null } }
104- // Signature is not needed.
105131 signature = ""
106132 />
107133 </ ErrorBoundary >
108134 ) ;
109135 }
110136
137+ if ( isTokenBatchInstruction ( ix ) ) {
138+ return (
139+ < ErrorBoundary
140+ fallback = { < UnknownDetailsCard key = { index } index = { index } ix = { ix } programName = { programName } /> }
141+ >
142+ < TokenBatchCard index = { index } ix = { ix } result = { INSPECTOR_RESULT } />
143+ </ ErrorBoundary >
144+ ) ;
145+ }
146+
111147 /// Handle program-specific cards here
112148 // - keep signature (empty string as we do not submit anything) for backward compatibility with the data from Transaction
113149 // - result is `err: null` as at this point there should not be errors
@@ -116,8 +152,6 @@ function InspectorInstructionCard({
116152
117153 switch ( ix . programId . toString ( ) ) {
118154 case ASSOCIATED_TOKEN_PROGRAM_ID . toString ( ) : {
119- // NOTE: current limitation is that innerInstructions won't be present at the AssociatedTokenDetailsCard. For that purpose we might need to simulateTransactions to get them.
120-
121155 const asParsedInstruction = intoParsedInstruction ( ix ) ;
122156 return (
123157 < AssociatedTokenDetailsCard
@@ -208,5 +242,5 @@ function InspectorInstructionCard({
208242 }
209243 }
210244
211- return < UnknownDetailsCard key = { index } index = { index } ix = { ix } programName = { programName } /> ;
245+ return < UnknownDetailsCard key = { index } index = { index } ix = { ix } programName = { programName } innerCards = { innerCards } /> ;
212246}
0 commit comments