The filters are a conjunction
getProgramAccounts lists accounts owned by one program and applies your filters. Every filter must pass. A correct owner plus a dataSize that describes another account variant is enough to produce an empty result. Program ownership is separate from a wallet authority stored inside account data.
Work from one fixture
{"jsonrpc":"2.0","id":1,"method":"getProgramAccounts","params":["PROGRAM_ID",{"encoding":"base64","filters":[{"dataSize":165}]}]}The 165-byte size is an illustrative fixed layout. Replace it with the actual size after inspecting a known matching account with getAccountInfo. Record its owner and raw data length. For variable-length or extension-bearing accounts, a single fixed size may exclude valid results.
Add byte comparisons carefully
- Verify the program ID and cluster against the known account.
- Begin with a bounded, approved query; broad scans can be expensive or restricted.
- Derive memcmp offsets from the actual schema, including any discriminator or version prefix. Offsets count bytes.
- Encode the compared bytes using the filter's expected encoding. Comparing a textual base58 string as raw account bytes is not equivalent.
Use the narrowest suitable method
For token holdings, getTokenAccountsByOwner can express the question directly. Token Program and Token-2022 have different owners and account layouts, so one token-program scan is not a complete inventory of both. Keep a fixture per program version and test it after parser changes. Read Supanode method weights and restrictions before scheduling repeated program-wide scans.