Skip to content

Add CodamaPdaHelpers derive#86

Open
grod220 wants to merge 1 commit intocodama-idl:mainfrom
grod220:pda-helpers
Open

Add CodamaPdaHelpers derive#86
grod220 wants to merge 1 commit intocodama-idl:mainfrom
grod220:pda-helpers

Conversation

@grod220
Copy link
Copy Markdown

@grod220 grod220 commented Mar 25, 2026

Adds #[derive(CodamaPdaHelpers)] which generates runtime PDA helper methods from existing #[codama(seed(...))] attributes. This reduces repeated manual PDA boilerplate program devs are writing.

API

use codama::{CodamaPda, CodamaPdaHelpers};

#[derive(CodamaPda, CodamaPdaHelpers)]
#[codama(seed(type = string(utf8), value = "mint"))]
#[codama(seed(name = "unwrappedMint", type = public_key))]
#[codama(seed(name = "wrappedTokenProgram", type = public_key))]
pub struct WrappedMintPda;

// ==== In program ==== 

let (address, bump) = WrappedMintPda::derive_program_address(
    &unwrapped_mint,
    &wrapped_token_program,
    &program_id,
)?;

let signer_seeds: [Seed; 4] = WrappedMintPda::signer_seeds(
    &unwrapped_mint,
    &wrapped_token_program,
    &bump_bytes,
);
  • Implemented macro expansion that parses struct-level #[codama(seed(...))] directives and generates:
    • seeds
    • seeds_with_bump
    • signer_seeds
    • (wrapping Address methods below)
    • derive_address
    • create_program_address
    • find_program_address
    • try_find_program_address
    • derive_program_address
  • Supports constant seeds (string(utf8), integer number(...)) and variable/linked seeds
  • Handles seed name deduplication, identifier collision detection, reserved bump, and Rust keyword escaping

Discussion points

  • Better name?
  • Should all of those Address methods be shipped? Aka, should we drop find_program_address?
  • The intention was for program usage, but might clients also need this?
  • An impl vs external crate helpers
  • How does this sit next to the CPI helpers PR (link?)

Comment on lines +62 to +63
#[proc_macro_derive(CodamaPdaHelpers, attributes(codama))]
pub fn codama_pda_helpers_derive(input: TokenStream) -> TokenStream {
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@febo better naming proposals?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whatever we land on with the derive name, just want to flag that IMO it should start with Codama since it purely relies on codama attributes.

Comment on lines +296 to +301
/// (wrapping `Address` methods)
/// - `derive_address`
/// - `create_program_address`
/// - `find_program_address`
/// - `try_find_program_address`
/// - `derive_program_address`
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@febo thoughts on which Address methods this should include? This sort of wraps everything, but maybe it should be a blessed subset.

Copy link
Copy Markdown
Member

@lorisleiva lorisleiva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll go through this thoroughly asap but I just wanted to share some early first impression feedback.

@@ -0,0 +1,97 @@
use heck::ToSnakeCase;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we already have an exported CamelCaseString struct in codama-nodes maybe it would be cleaner / more consistent to also add a SnakeCaseString struct there instead of introducing a new dependency.

Comment on lines +62 to +75
#[proc_macro_derive(CodamaPdaHelpers, attributes(codama))]
pub fn codama_pda_helpers_derive(input: TokenStream) -> TokenStream {
#[cfg(not(target_os = "solana"))]
{
pda_helpers::codama_pda_helpers_derive_impl(input.into())
.unwrap_or_else(codama_errors::CodamaError::into_compile_error)
.into()
}
#[cfg(target_os = "solana")]
{
input
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice if this macro was on its own crate. Maybe something like codama-pda-helpers or whatever the name ends up being here.

That way, if anyone wants to use a slightly different version of our generated code, it's easier for them to fork that crate on its own.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants