coral-xyz / anchor

⚓ Solana Sealevel Framework
https://anchor-lang.com
Apache License 2.0
3.6k stars 1.32k forks source link

Feature Request: Generate rust bindings for the contract #1006

Closed mangas closed 2 years ago

mangas commented 2 years ago

Hi,

As a rust developer a much prefer writing test code in rust rather than typescript. I also think this would reduce friction between anchor and non anchor "standards" since this is how the current native contracts work.

883 also shows the confusion this causes for newcomers.

Essentially the following snippet was shared on the anchor discord as a way of achieve calls from rust to anchor contracts and as you can see it's quite verbose and not very practical.

I think it would be great to have these types of bindings generated along with the contract, I couldn't find it in the expanded macro code but if it already exists then would be great to point it out in the docs.

https://gist.github.com/bonedaddy/0a51ad0191856c4330f2fd8adff10990 Here's a copy for convenience

pub fn stake_tokens_instruction(
    authority: Pubkey,
    miner: Pubkey,
    quarry: Pubkey,
    miner_vault: Pubkey,
    token_account: Pubkey,
    token_program: Pubkey,
    rewarder: Pubkey,
    clock: Pubkey,
    quarry_mine_program: Pubkey,
    amount: u64,
) -> Instruction {
    let ix = {
        let mut ix_data = AnchorSerialize::try_to_vec(&StakeTokensInstruction {
            amount,
        }).unwrap();
        let mut data = crate::quarry::STAKE_TOKENS_SIGHASH.to_vec();
        data.append(&mut ix_data);
        let accounts: Vec<AccountMeta> = vec![
            AccountMeta {
                pubkey: authority,
                is_writable: false,
                is_signer: true,
            },
            AccountMeta {
                pubkey: miner,
                is_writable: true,
                is_signer: false,
            },
            AccountMeta {
                pubkey: quarry,
                is_writable: true,
                is_signer: false,
            },
            AccountMeta {
                pubkey: miner_vault,
                is_writable: true,
                is_signer: false,
            },
            AccountMeta {
                pubkey: token_account,
                is_writable: true,
                is_signer: false,
            },
            AccountMeta {
                pubkey: token_program,
                is_writable: false,
                is_signer: false,
            },
            AccountMeta {
                pubkey: rewarder,
                is_writable: false,
                is_signer: false,
            },
            AccountMeta {
                pubkey: clock,
                is_writable: false,
                is_signer: false,
            },
        ];
        anchor_lang::solana_program::instruction::Instruction{
            program_id: quarry_mine_program,
            accounts,
            data
        }
    };
    ix
}
armaniferrante commented 2 years ago

The macro generates each component.

accounts - is exposed via crate::accounts::<ix-name>{..}.to_account_metas() data - is exposed via crate::instruction::<ix-name>{..}.data()

fanatid commented 2 years ago

It's already possible to use anchor projects from Rust code. You can use https://github.com/dtolnay/cargo-expand for exploration of what anchor macros generate and how it's can be used.