3

When the size of an Anchor account is known, we can get all the accounts in a certain program like so (noting that size is the real size + 8 bytes for the discriminator):

export const fetchCertainAccounts = async (
    connection: Connection,
  ) => {
    const sizeFilter: DataSizeFilter = {
        dataSize: ACC_SIZE
    };
    const getAccountsConfig: GetProgramAccountsConfig = {
        commitment: "confirmed",
        filters: [sizeFilter]
    };
    return await connection.getProgramAccounts(programKey, getAccountsConfig);
  };

But another account might be same size by chance, so this isn't reliable, and needs to be filtered after arrival. Can we use memcmp to filter only the Anchor accounts with the given 8 byte discriminator? Is there any reliability concern to doing it this way?

1 Answer 1

5

Yes, using dataSize filter will fetch you all the program accounts of the given size, so if your program happens to own two (or more) types of accounts with the same size that you specified, it will fetch all of those. As you have pointed out, we can use memcmp filter to filter accounts of a specific type using the discriminator (assuming your program is written using Anchor). For example let's say in your Anchor program, you have defined an account as below:

#[account]
pub struct MyAccount {
    //your fields here
}

In the data field of the account, the first 8 bytes will correspond to the first 8 bytes of SHA-256 hash of the string "account:MyAccount", and is called the account discriminator (calculated and set by Anchor by default).

memcmp compares the bytes stored in account's data field and the bytes we specify. We need to specify two things:

  1. offset: the byte location in account's data field where we want comparison to start
  2. bytes: the raw bytes encoded in base 58 format

In your typescript client you will fetch all the accounts of type MyAccount as follows:

import { sha256 } from "js-sha256"
import bs58 from "bs58"
async function fetchAccounts(connection: Connection, programId: PublicKey) {
    const discriminator = Buffer.from(sha256.digest("account:MyAccount")).subarray(0, 8)
    const filter = { memcmp: { offset: 0,
                               bytes: bs58.encode(discriminator)
                             }
                   }
    const accounts = await connection.getProgramAccounts(programId, { filters: [filter] })
    return accounts
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.