Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat]: Capture PDA knowledge #23

Open
lorisleiva opened this issue May 5, 2022 · 3 comments
Open

[feat]: Capture PDA knowledge #23

lorisleiva opened this issue May 5, 2022 · 3 comments
Assignees

Comments

@lorisleiva
Copy link

It would be great if Shank could capture all the PDAs of a program in the IRL so they can be auto-generated by Solita (See metaplex-foundation/metaplex-program-library#420).

I'm not sure if something like this is feasible with Rust macro, but this is what I have in mind.

  #[repr(C)]
- #[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize, ShankAccount)]
+ #[derive(Clone, Debug, PartialEq, BorshSerialize, BorshDeserialize, ShankPda)]
+ #[seed(0, literal="metadata")]
+ #[seed(1, programId)]
+ #[seed(2, name="mint", desc="The public key of the mint account")]
+ #[seed(3, literal="edition")]
  pub struct MasterEditionV2 {
      pub key: Key,
  
      pub supply: u64,
  
      pub max_supply: Option<u64>,
  }

Where a seed can be one of three types:

  • literal="something": The seed is literally the string "something".
  • programId: The seed is the ID of the program.
  • name="something", desc="some description": The seed is a custom parameter that needs to be provided.
@stegaBOB
Copy link
Contributor

stegaBOB commented Aug 14, 2022

Following up on this after just fixing the seed parsing for anchor IDL generation (it currently generates seeds as well). We can do something similar to what loris is saying but for instructions too! From there it can be parsed into the same format that anchor generates:

(For the accounts part of the instruction definition)

{
  "name": "accountName",
  "isMut": true,
  "isSigner": false,
  "pda": {
    "seeds": [
      {
        "kind": "const",
        "type": "string", // any valid type
        "value": "the string value"
      },
      {
        "kind": "arg", // meaning one of the ix args
        "type": "u64", // again, can be any valid type here
        "path": "amount" // the name of the argument
      },
      {
        "kind": "account", // referring to one of the accounts in the ix
        "type": "publicKey",
        "path": "authority" // the account name
      }
    ]
  }
},

The anchor TS client uses this to autopopulate PDAs (i.e. they arent required to be passed in in the accounts struct). We should be able to replicate this behavior in Solita.

Anchor PR for reference: coral-xyz/anchor#2125

@thlorenz
Copy link
Contributor

thlorenz commented Sep 26, 2022

After experimenting a bit with solutions to efficiently providing seeds I came up with an easily parseable (by humans and proc_macros) way to provide seeds.

Using the example above it'd be as follows:

#[derive(ShankAccount)]
#[seeds("prefix", program_id, something("description of something"), "postfix")]
struct MyAccount { .. }

Which would result in seeds + pda helper impl methods similar to the below:

impl MyAccount {
    /// @param program_id the id of the program to generate the PDA for
    /// @param something description of something
    pub fn get_seeds<'a>(program_id: &'a Pubkey, something: &'a Pubkey) -> [&'a [u8]; 4] {
        [
            "prefix".as_bytes(),
            program_id.as_ref(),
            something.as_ref(),
            "postfix".as_bytes(),
        ]
    }

    pub fn get_pda<'a>(program_id: &'a Pubkey, something: &'a Pubkey) -> (Pubkey, u8) {
        let seeds = get_seeds(program_id, something);
        let (key, bump) = Pubkey::find_program_address(&seeds, program_id);
        (key, bump)
    }
}

Additionally the relevant info to generate similar methods in TypeScript will be added to the IDL.
My assumption here is that we only use either literal strings or public keys in order to derive seeds. If we need other types of data we could express this as something_else("desc of else", u8) (defaulting to Pubkey if the second param is not provided).

Waiting for approval/suggestions while I'm working on something along those lines.

@thlorenz
Copy link
Contributor

@stegaBOB reading your comment from above, the above should cover this.
However, given that those consts can just be hard-coded in the get_seeds method I'm not sure the below is needed.

{
      "kind": "const",
      "type": "string", // any valid type
      "value": "the string value"
    },

Could you clarify why this still would be useful to include in the IDL and/or why I'm incorrect?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants