Skip to content

Commit

Permalink
Update rust client
Browse files Browse the repository at this point in the history
  • Loading branch information
armaniferrante committed Feb 6, 2021
1 parent 16636e6 commit 95375f6
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 29 deletions.
39 changes: 18 additions & 21 deletions client/example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ use anchor_client::solana_sdk::sysvar;
use anchor_client::Client;
use anyhow::Result;
// The `accounts` and `instructions` modules are generated by the framework.
use basic_2::accounts::CreateAuthor;
use basic_2::instruction::Basic2Instruction;
use basic_2::Author;
use basic_2::accounts as basic_2_accounts;
use basic_2::instruction as basic_2_instruction;
use basic_2::Counter;
// The `accounts` and `instructions` modules are generated by the framework.
use composite::accounts::{Bar, CompositeUpdate, Foo, Initialize};
use composite::instruction::CompositeInstruction;
use composite::instruction as composite_instruction;
use composite::{DummyA, DummyB};
use rand::rngs::OsRng;

Expand All @@ -38,7 +38,7 @@ fn main() -> Result<()> {
// Make sure to run a localnet with the program deploy to run this example.
fn composite(client: &Client) -> Result<()> {
// Deployed program to execute.
let pid = "75TykCe6b1oBa8JWVvfkXsFbZydgqi3QfRjgBEJJwy2g"
let pid = "CD4y4hpiqB9N3vo2bAmZofsZuFmCnScqDPXejZSTeCV9"
.parse()
.unwrap();

Expand Down Expand Up @@ -73,7 +73,7 @@ fn composite(client: &Client) -> Result<()> {
dummy_b: dummy_b.pubkey(),
rent: sysvar::rent::ID,
})
.args(CompositeInstruction::Initialize)
.args(composite_instruction::Initialize)
.send()?;

// Assert the transaction worked.
Expand All @@ -93,7 +93,7 @@ fn composite(client: &Client) -> Result<()> {
dummy_b: dummy_b.pubkey(),
},
})
.args(CompositeInstruction::CompositeUpdate {
.args(composite_instruction::CompositeUpdate {
dummy_a: 1234,
dummy_b: 4321,
})
Expand All @@ -115,41 +115,38 @@ fn composite(client: &Client) -> Result<()> {
// Make sure to run a localnet with the program deploy to run this example.
fn basic_2(client: &Client) -> Result<()> {
// Deployed program to execute.
let program_id = "FU3yvTEGTFUdMa6qAjVyKfNcDU6hb4yXbPhz8f5iFyvE"
let program_id = "DXfgYBD7A3DvFDJoCTcS81EnyxfwXyeYadH5VdKMhVEx"
.parse()
.unwrap();

let program = client.program(program_id);

// `CreateAuthor` parameters.
let author = Keypair::generate(&mut OsRng);
// `Create` parameters.
let counter = Keypair::generate(&mut OsRng);
let authority = program.payer();

// Build and send a transaction.
program
.request()
.instruction(system_instruction::create_account(
&authority,
&author.pubkey(),
&counter.pubkey(),
program.rpc().get_minimum_balance_for_rent_exemption(500)?,
500,
&program_id,
))
.signer(&author)
.accounts(CreateAuthor {
author: author.pubkey(),
.signer(&counter)
.accounts(basic_2_accounts::Create {
counter: counter.pubkey(),
rent: sysvar::rent::ID,
})
.args(Basic2Instruction::CreateAuthor {
authority,
name: "My Book Name".to_string(),
})
.args(basic_2_instruction::Create { authority })
.send()?;

let author_account: Author = program.account(author.pubkey())?;
let counter_account: Counter = program.account(counter.pubkey())?;

assert_eq!(author_account.authority, authority);
assert_eq!(author_account.name, "My Book Name".to_string());
assert_eq!(counter_account.authority, authority);
assert_eq!(counter_account.count, 0);

println!("Success!");

Expand Down
7 changes: 3 additions & 4 deletions client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use anchor_lang::solana_program::instruction::{AccountMeta, Instruction};
use anchor_lang::solana_program::program_error::ProgramError;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::{AccountDeserialize, AnchorSerialize, ToAccountMetas};
use anchor_lang::{AccountDeserialize, InstructionData, ToAccountMetas};
use solana_client::client_error::ClientError as SolanaClientError;
use solana_client::rpc_client::RpcClient;
use solana_sdk::commitment_config::CommitmentConfig;
Expand Down Expand Up @@ -185,9 +185,8 @@ impl<'a> RequestBuilder<'a> {
self
}

pub fn args(mut self, args: impl AnchorSerialize) -> Self {
let data = args.try_to_vec().expect("Should always serialize");
self.instruction_data = Some(data);
pub fn args(mut self, args: impl InstructionData) -> Self {
self.instruction_data = Some(args.data());
self
}

Expand Down
8 changes: 8 additions & 0 deletions lang/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@ pub trait AccountDeserialize: Sized {
fn try_deserialize_unchecked(buf: &mut &[u8]) -> Result<Self, ProgramError>;
}

/// Calculates the data for an instruction invocation, where the data is
/// `Sha256(<namespace>::<method_name>)[..8] || BorshSerialize(args)`.
/// `args` is a borsh serialized struct of named fields for each argument given
/// to an instruction.
pub trait InstructionData: AnchorSerialize {
fn data(&self) -> Vec<u8>;
}

/// The prelude contains all commonly used components of the crate.
/// All programs should include it via `anchor_lang::prelude::*;`.
pub mod prelude {
Expand Down
46 changes: 42 additions & 4 deletions lang/syn/src/codegen/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,18 +605,39 @@ pub fn generate_instructions(program: &Program) -> proc_macro2::TokenStream {
.unwrap()
})
.collect();

let ix_data_trait = {
let name = method.raw_method.sig.ident.to_string();
let sighash_arr = sighash(SIGHASH_GLOBAL_NAMESPACE, &name);
let sighash_tts: proc_macro2::TokenStream =
format!("{:?}", sighash_arr).parse().unwrap();
quote! {
impl anchor_lang::InstructionData for #rpc_name_camel {
fn data(&self) -> Vec<u8> {
let mut d = #sighash_tts.to_vec();
d.append(&mut self.try_to_vec().expect("Should always serialize"));
d
}
}
}
};

// If no args, output a "unit" variant instead of a struct variant.
if method.args.len() == 0 {
quote! {
#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct #rpc_name_camel;

#ix_data_trait
}
} else {
quote! {
#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct #rpc_name_camel {
#(#raw_args),*
}

#ix_data_trait
}
}
})
Expand All @@ -626,10 +647,9 @@ pub fn generate_instructions(program: &Program) -> proc_macro2::TokenStream {
.rpcs
.iter()
.map(|rpc| {
let rpc_name_camel = proc_macro2::Ident::new(
&rpc.raw_method.sig.ident.to_string().to_camel_case(),
rpc.raw_method.sig.ident.span(),
);
let name = &rpc.raw_method.sig.ident.to_string();
let rpc_name_camel =
proc_macro2::Ident::new(&name.to_camel_case(), rpc.raw_method.sig.ident.span());
let raw_args: Vec<proc_macro2::TokenStream> = rpc
.args
.iter()
Expand All @@ -639,18 +659,36 @@ pub fn generate_instructions(program: &Program) -> proc_macro2::TokenStream {
.unwrap()
})
.collect();
let ix_data_trait = {
let sighash_arr = sighash(SIGHASH_GLOBAL_NAMESPACE, &name);
let sighash_tts: proc_macro2::TokenStream =
format!("{:?}", sighash_arr).parse().unwrap();
quote! {
impl anchor_lang::InstructionData for #rpc_name_camel {
fn data(&self) -> Vec<u8> {
let mut d = #sighash_tts.to_vec();
d.append(&mut self.try_to_vec().expect("Should always serialize"));
d
}
}
}
};
// If no args, output a "unit" variant instead of a struct variant.
if rpc.args.len() == 0 {
quote! {
#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct #rpc_name_camel;

#ix_data_trait
}
} else {
quote! {
#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct #rpc_name_camel {
#(#raw_args),*
}

#ix_data_trait
}
}
})
Expand Down

0 comments on commit 95375f6

Please sign in to comment.