Skip to main content
A 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:
With the deprecated 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:
Token and Token-2022 are two programs as well, each with its own typegen module and decoder. A second deployment of the same program replaces the address in a copy of the module: program: { ...jupiter, programId: JUPITER_SECOND_DEPLOYMENT }.