Try   HackMD
tags: solana

solana/web3: How to use filter

This is the example of connection.getProgramAddress.
The function the get all the PDA under a certain programId

In this case, we want to filter out a PDA which has following data struct

export const FARM_LEDGER_LAYOUT_V5_2 = struct([
  u64("state"),
  publicKey("id"),
  publicKey("owner"),
  u64("deposited"),
  seq(u128(), 2, "rewardDebts"),
  seq(u64(), 17),
]);

There are two way to filter:

MemcmpFilter

This is to let function know that from 40 bytes of the data structure will be the wallet address

const adminIdMemcmp: MemcmpFilter = {
    memcmp: {
      offset: 8 + 32,
      bytes: wallet.toString(),
    },
  };

DataSizeFilter

This is to let the function know that the size (in bytes) of the data structure.

  const sizeFilter: DataSizeFilter = {
    dataSize: 8 + 32 + 32 + 8 + 16 * 2 + 8 * 17,
  };

Call function with filters

const filters = [adminIdMemcmp, sizeFilter];
  const config: GetProgramAccountsConfig = { filters: filters };
  const allMinerAccount = await connection.getProgramAccounts(
    STAKE_PROGRAM_ID_V5,
    config
  );

Decode the data

We can double check if the result is what we want be decode the bytes data

let leger = FARM_LEDGER_LAYOUT_V5_2.decode(allMinerAccount[0].account.data);
console.log(leger.id.toBase58());
console.log(leger.owner.toBase58());

Reference example code

const FARM_LEDGER_LAYOUT_V5_2 = struct([
  u64("state"),
  publicKey("id"),
  publicKey("owner"),
  u64("deposited"),
  u128("rewardDebts1"),
  u128("rewardDebts2"),
  u64("TBC"),
]);


async function getAllMiner(connection: Connection, wallet: PublicKey) {
  const adminIdMemcmp: MemcmpFilter = {
    memcmp: {
      offset: 8 + 32,
      bytes: wallet.toString(),
    },
  };
  const sizeFilter: DataSizeFilter = {
    dataSize: 8 + 32 + 32 + 8 + 16 * 2 + 8 * 17,
  };
  // const filters = [sizeFilter];
  const filters = [adminIdMemcmp, sizeFilter];
  const config: GetProgramAccountsConfig = { filters: filters };
  const allMinerAccount = await connection.getProgramAccounts(
    STAKE_PROGRAM_ID_V5,
    config
  );
  console.log(allMinerAccount);
  // let leger = FARM_LEDGER_LAYOUT_V5_2.decode(allMinerAccount[2].account.data);
  let leger = FARM_LEDGER_LAYOUT_V5_2.decode(allMinerAccount[0].account.data);
  console.log(leger.id.toBase58());
  console.log(leger.owner.toBase58());
}
getAllMiner(
  connection,
  new PublicKey("6c2417zcPUXTUcKwq2VNwLTxKMRBoZzW7hFc8Pv1BE2e")
).then((r) => console);