Open lorisleiva opened 2 years ago
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: https://github.com/coral-xyz/anchor/pull/2125
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.
@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?
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 https://github.com/metaplex-foundation/metaplex-program-library/pull/420).
I'm not sure if something like this is feasible with Rust macro, but this is what I have in mind.
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.