Documentation Index
Fetch the complete documentation index at: https://beta.docs.sqd.dev/llms.txt
Use this file to discover all available pages before exploring further.
solanaInstructionDecoder() bundles a Solana instruction query with a decoding transform into a single reusable module. Pass the result as an output to solanaPortalStream:
import * as orcaWhirlpool from './abi/orca_whirlpool'
import { solanaInstructionDecoder, solanaPortalStream } from '@subsquid/pipes/solana'
const stream = solanaPortalStream({
portal: 'https://portal.sqd.dev/datasets/solana-mainnet',
outputs: {
orcaWhirlpool: solanaInstructionDecoder({
range: { from: 340_000_000 },
programId: orcaWhirlpool.programId,
instructions: {
swap: orcaWhirlpool.instructions.swap,
swapV2: orcaWhirlpool.instructions.swapV2,
},
}),
},
})
for await (const { data } of stream) {
console.log(`parsed ${data.orcaWhirlpool.swap.length} swaps`)
}
solanaInstructionDecoder() can:
- Fetch from one or multiple programs — pass a single address or an array to
programId.
- Filter by instruction type — only instructions whose discriminator matches one of the entries in
instructions are fetched and decoded.
- Handle decode errors with a custom
onError callback instead of letting them propagate.
See the solanaInstructionDecoder() reference for all parameters.
Generating a typed ABI module
Typed ABI modules for Solana programs are generated from Anchor IDL files by @subsquid/solana-typegen. Each generated module exports typed decode functions, so decoded instruction field types are statically known at compile time — you get precise type checking and IDE autocompletion across the entire pipeline.
Install:
npm install -D @subsquid/solana-typegen
From a local IDL file
npx squid-solana-typegen src/abi whirlpool.json
The output module name is derived from the filename (whirlpool). Override it with a #name fragment:
npx squid-solana-typegen src/abi whirlpool.json#orca_whirlpool
From a program address
For Anchor programs that publish their IDL on-chain, pass the program address directly:
npx squid-solana-typegen src/abi whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc#orca_whirlpool
The tool tries two sources in parallel: the on-chain IDL account (defaulting to Solana mainnet) and the SolanaFM IDL database. It fails only if both sources fail. Use --solana-rpc-endpoint to point at a different RPC endpoint:
npx squid-solana-typegen \
--solana-rpc-endpoint https://my-rpc.example.com \
src/abi \
whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc#orca_whirlpool
Without the #name fragment the program address itself becomes the module name.
From a URL
npx squid-solana-typegen src/abi https://example.com/whirlpool.json#orca_whirlpool
Generated module structure
For an input named orca_whirlpool, the tool creates:
src/abi/
abi.support.ts # shared runtime, generated once per output dir
orca_whirlpool/
index.ts # re-exports + programId
instructions.ts # one typed constant per instruction
events.ts # one typed constant per event (if any)
types.ts # shared struct types
Each entry in instructions.ts is a TypeScript interface (the decoded shape) alongside a constant carrying the discriminator and decode logic:
export interface CloseBundledPosition {
bundleIndex: number
}
export const closeBundledPosition = instruction(
{ d8: '0x2924d8f51b556743' },
{
bundledPosition: 0,
positionBundle: 1,
positionBundleTokenAccount: 2,
positionBundleAuthority: 3,
receiver: 4,
whirlpoolProgram: 5,
},
struct({ bundleIndex: u16 })
)
The d8 discriminator and account index map are embedded in the constant — solanaInstructionDecoder() reads them automatically to build the source query filter.
Accessing decoded data
The keys of the instructions map become field names in the decoded output batch. Each field is an array of decoded instruction objects:
for await (const { data } of stream) {
for (const ins of data.orcaWhirlpool.swap) {
const { accounts, data: fields } = ins.instruction
console.log(accounts.tokenAuthority, fields.amount)
}
}
See the decoded instruction structure reference for the full field list.