solanaInstructionDecoder was built with instructions it can’t decode soundly: an instruction that
is not one of its program’s instructions, a program with an empty address, an instruction with no
discriminator or with more than one, discriminators of mixed widths across the decoder
(d1/d2/d4/d8), or two instructions sharing a discriminator. A decoder covers a single program
— its address, its own instructions, one width, distinct discriminators — because Anchor
discriminators are program-independent: a discriminator alone does not say which program an
instruction came from.
Fix — pass the program’s typegen module as program and take every entry from
program.instructions. Give each instruction exactly one discriminator, keep a single width per
decoder, and give every other program its own solanaInstructionDecoder(). If the mixed widths really
do belong to one program — an ABI whose extension instructions carry a wider discriminator than its
base ones — split it by width instead: one decoder per width, the same program.
Wrong — an instruction of another program. TypeScript rejects it when the two instructions differ
in type, and the decoder refuses it at start in any case:
programId: [jupiter.programId, raydium.programId] in place of program, the
decoder checks only the discriminators: this example starts, and Raydium’s on-chain swap, whose
discriminator Anchor derives from sha256("global:swap") just as Jupiter’s, decodes under jupSwap
with Jupiter’s codec and account layout.
Right — one decoder per program:
program: { ...jupiter, programId: JUPITER_SECOND_DEPLOYMENT }.