metaplex-foundation / umi-hotline

2 stars 0 forks source link

Kinobi gpaBuilder problems #12

Closed KultureElectric closed 1 year ago

KultureElectric commented 1 year ago

Umi version

No response

Code

I'm trying to use the gpaBuilder to fetch a list of program accounts from my program.

Trying to use the gpaBuilder.get() function results in an empty array being returned in all cases below.

And even without setting any filters. 

 // Fetch Pools
    const pool = await fetchStakePool(umi, stakePool);
    console.log(pool);

    const poolGpaBuilder = getStakePoolGpaBuilder(umi);
    const stakePools = await poolGpaBuilder.get();
    console.log(stakePools);

    // Fetch Entry
    const stakeEntry = await fetchStakeEntry(umi, stakeEntryPda);

    // Fetch stake entries

    let gpaBuilder = getStakeEntryGpaBuilder(umi);

    const stakeEntries = await gpaBuilder.get();
    console.log(stakeEntries);

    const lastStakerOffset = await gpaBuilder.whereField(
      "lastStaker",
      umi.identity.publicKey
    );
    console.log(await lastStakerOffset.get());
  });

I think that means that either the discriminator that was generated by kinobi is wrong or there is a bug in the get() function.

It cold also be a case that I forgot to add some required settings in the kinobi.js file.

Here my kinobi generated getGpaBuilder function:

  return gpaBuilder(context, programId)
    .registerFields<{
      discriminator: Array<number>;
      bump: number;
      pool: PublicKey;
      amount: number | bigint;
      originalMint: PublicKey;
      originalMintClaimed: boolean;
      lastStaker: PublicKey;
      lastStakedAt: number | bigint;
      pointsSpent: number | bigint;
      previousStakeSeconds: Option<number | bigint>;
    }>({
      discriminator: [0, s.array(s.u8(), { size: 8 })],
      bump: [8, s.u8()],
      pool: [9, s.publicKey()],
      amount: [41, s.u64()],
      originalMint: [49, s.publicKey()],
      originalMintClaimed: [81, s.bool()],
      lastStaker: [82, s.publicKey()],
      lastStakedAt: [114, s.i64()],
      pointsSpent: [122, s.u64()],
      previousStakeSeconds: [130, s.option(s.u128())],
    })
    .deserializeUsing<StakeEntry>((account) =>
      deserializeStakeEntry(context, account)
    )
    .whereField("discriminator", [161, 81, 238, 68, 121, 171, 215, 218]);
}

And my Kinobi file:

const path = require("path");
const k = require("@metaplex-foundation/kinobi");

// Paths.
const clientDir = path.join(__dirname, "./", "clients");
const idlDir = path.join(__dirname, "./idl/");

// Instanciate Kinobi.
const kinobi = k.createFromIdls([
  path.join(idlDir, "cardinal_staking_starter.json"),
]);

// Update accounts.
kinobi.update(
  new k.UpdateAccountsVisitor({
    identifier: {
      seeds: [k.stringConstantSeed("identifier")],
    },
    stakeEntry: {
      seeds: [
        k.stringConstantSeed("stake-entry"),
        k.publicKeySeed("pool", "The address of the stake pool"),
        k.publicKeySeed("mint", "The address of the NFT Mint"),
        k.publicKeySeed("user", "The address of the user"),
      ],
    },
    stakePool: {
      seeds: [
        k.stringConstantSeed("stake-pool"),
        k.variableSeed(
          "identifier",
          k.numberTypeNode("u64", "le"),
          "The identifier number of the pool"
        ),
      ],
    },
  })
);

// Render JavaScript.
const jsDir = path.join(clientDir, "js", "src", "generated");
// const prettier = require(path.join(clientDir, "js", ".prettierrc.json"));
kinobi.accept(new k.RenderJavaScriptVisitor(jsDir));

Appreciate the help!



### Error

_No response_
KultureElectric commented 1 year ago

Checked the discriminator in the generated client with the discriminator of an actual account and it doesn't match.

lorisleiva commented 1 year ago

Hi there, are you using Anchor? If so what should the discriminator be?

KultureElectric commented 1 year ago

Hey GM, that was quick!

Yes I'm using Anchor but nor sure what you mean with your second question.

I checked the discriminator of one of the accounts and it's this:

[187, 127, 9, 35, 155, 68, 86, 40]

The generated GPA Builder Function in the kinobi client has a different discriminator at the .where() at the bottom:

export function getStakeEntryGpaBuilder(
  context: Pick<Context, "rpc" | "serializer" | "programs">
) {
  const s = context.serializer;
  const programId = context.programs.getPublicKey(
    "cardinalStakingStarter",
    "2QAt6wzQh2vJRCynbto7JBea4Q2uG8BpVZK3aDpQ3YLd"
  );
  return gpaBuilder(context, programId)
    .registerFields<{
      discriminator: Array<number>;
      bump: number;
      pool: PublicKey;
      amount: number | bigint;
      originalMint: PublicKey;
      originalMintClaimed: boolean;
      lastStaker: PublicKey;
      lastStakedAt: number | bigint;
      pointsSpent: number | bigint;
      previousStakeSeconds: Option<number | bigint>;
    }>({
      discriminator: [0, s.array(s.u8(), { size: 8 })],
      bump: [8, s.u8()],
      pool: [9, s.publicKey()],
      amount: [41, s.u64()],
      originalMint: [49, s.publicKey()],
      originalMintClaimed: [81, s.bool()],
      lastStaker: [82, s.publicKey()],
      lastStakedAt: [114, s.i64()],
      pointsSpent: [122, s.u64()],
      previousStakeSeconds: [130, s.option(s.u128())],
    })
    .deserializeUsing<StakeEntry>((account) =>
      deserializeStakeEntry(context, account)
    )
    .whereField("discriminator", [187, 127, 9, 35, 155, 68, 86, 40]); // Changed it manually now but if I run node kinobi it's wrong again
lorisleiva commented 1 year ago

Weird, I wonder if Anchor changed their discriminator logic recently?

Usually, it's calculated as the first 8-bytes of the hash of the account name as it appears on the IDL. What's the IDL name of the StakeEntry account in your case?

KultureElectric commented 1 year ago

"accounts": [
    {
      "name": "StakeEntry",
      "type": {
KultureElectric commented 1 year ago

Any updates?

Also had 2 other questions:

  1. How can I pass "additionalAccounts" into Umi created instructions
  2. There's no getBlockTime method in umi.rpc - do you plan to integrate this?
lorisleiva commented 1 year ago

Hey, I'll take a look at the discriminator computation right now.

Regarding your questions:

  1. You can always update the instructions inside the transaction builder but there's no helper to help you do that right now. I'm thinking of adding a method called addAccountMeta(instructionIndex, accountMeta) on the transaction builder to help you do that. What do you think?
  2. I can do that today too. πŸ™‚
KultureElectric commented 1 year ago

Amazing!

  1. That helper function would be greaet!
  2. Sounds great.

Appreciate your help here! Umi is awesome!

lorisleiva commented 1 year ago

Can you try Kinobi version 0.8.5? That should fix the Anchor discriminator for accounts. πŸ™‚

lorisleiva commented 1 year ago

Also Umi version 0.7.10 now has a addRemainingAccounts helper on the transaction builder and a getBlockTime method on the RPC interface.

KultureElectric commented 1 year ago

Amazing! Something still seems to be wrong with the getBlockTime function. I type does exist but not the function:

umi.rpc.getBlockTime is not a function

lorisleiva commented 1 year ago

Could you try to rm -rf node_modules? I've double-checked the published package and it's there. πŸ€”

KultureElectric commented 1 year ago

Just did that in reinstalled in my anchor repository.

Also setup a single separated script to test it and it still doesn't work. Type is included but maybe you forgot to export it in the package?

Maybe a new file that wasn't yet exported properly?

lorisleiva commented 1 year ago

It's exported as part of the RpcInterface and its implementation relying on Web3.js (this is the commit).

Can you share your package.json (or a subset of it) to double check the imports?

KultureElectric commented 1 year ago
"@metaplex-foundation/mpl-candy-machine": "^6.0.0-alpha.10",
"@metaplex-foundation/mpl-essentials": "^0.5.7",
"@metaplex-foundation/mpl-token-metadata": "^3.0.0-alpha.18",
"@metaplex-foundation/umi": "^0.7.10",
"@metaplex-foundation/umi-bundle-defaults": "^0.7.2",

import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
const runn = async () => {
  const umi = createUmi("url");

  const slot = await umi.rpc.getSlot();
  console.log(await umi.rpc.getBlockTime(slot));
};

runn();

Oh it's probably because I'm using createUmi from the umi-bundle-defaults package, right?

What is the new way with createUmi from the umi package? How do I set the rpc url on there?

lorisleiva commented 1 year ago

Yeah they are versioned together so:

"@metaplex-foundation/umi-bundle-defaults": "^0.7.2",

should be

"@metaplex-foundation/umi-bundle-defaults": "^0.7.10",
KultureElectric commented 1 year ago

Got it that worked