1

say i have a PDA

struct Foo {
  created_at: i64
}

with a created_at unix sec timestamp field (ex: 1690004000). I want to filter all PDAs that were created in 1690000000. as far as i know ints are store in bs58 encoded little endian, which the bs58 encoding kind of ruins things. I tried doing

const bytes = anchor.utils.bytes.bs58.encode(new anchor.BN(1690000000).toBuffer("le", 8)).slice(0, 4)

const accts = await program
    .account.foo.all(
      [
        {
          memcmp: {
            offset: 8,
            bytes,
          }
        }
      ]
    )

but got nothing. is there a way to go about doing this or will i need to store the time epoch (1690000000 ) as a separate field in the PDA and do an exact filter?

1 Answer 1

1

base58 is simply the encoding used when sending data, it doesn't affect things otherwise.

Your logic is correct and I managed to reproduce the client code and I can confirm this works:

 // number to bs58, but a little different than your version
const ntobs58 = x => anchor.utils.bytes.bs58.encode(new anchor.BN(x).toArrayLike(Buffer, 'le', 8));

const accts = await pg.program.account.newAccount.all([
        {
          memcmp: {
            offset: 8,
            bytes: ntobs58(n), // n is a timestamp
          }
        }
      ]);

This is how my accounts looks like:

#[account]
pub struct NewAccount {
    created_at: i64
}

Double check that:

  • you're encoding the bytes correctly, I see you have a .slice(0, 4), I think that's the problem. Trimming a base58 string makes it invalid.
  • your account has indeed a single field (created_at) or, in case you have multiple fields, that this field is the first one in the byte representation of the account.

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.