4

I use getProgramAccounts to get a big number of accounts.

I would like to only get the first 5 accounts with the highest field score. I know that pagination and ordering is not supported officially, but are there tricks to do it ?

2 Answers 2

4

You can deserialize the data of each account and then sort the deserialized accounts using the score field.

const accounts = await provider.connection.getProgramAccounts(program.programId);

deserialized_accounts = []
accounts.forEach((account) => {
  // deserialize the data
})

// sort deserialized accounts
deserialized_accounts.sort((a, b) => (a.score > b.score) ? 1 : -1)

There are multiple ways to deserialize an account.

1
  • 1
    Thanks, it is not that effective but I think it's the only solution atm. Commented Feb 16, 2023 at 20:01
2

Assuming you have a list of all the accounts that exist, e.g. let keys: PublicKey[] = [....], if you are using Anchor, you can fetch multiple accounts with:

program.account.whatever.fetchMultiple(keys)

If you really want ALL of the accounts of that type, use this.program.account.whatever.all()

In either case, now you have an array of the serialized accounts and you can sort easily.

If you REALLY want to fetch only the matching accounts on chain, you can use memcmp, but you will have to find the offset of score to figure out which bytes to compare, and you'll have to specify some value to use as a cutoff, so "5 highest" isn't really possible:

import { sha256 } from "js-sha256"
import bs58 from "bs58"
async function fetchAccounts(connection: Connection, programId: PublicKey) {
// If using Anchor, filter accounts that match the discriminator (first 8 bytes)
    const discriminator = Buffer.from(sha256.digest("account:MyAccount")).subarray(0, 8)
    const filter = { memcmp: { offset: 0,
                               bytes: bs58.encode(discriminator)
                             }
// Figure out the offset of "score", and the values you want to filter
                   }
    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.