123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- use anchor_client::solana_sdk::pubkey::Pubkey;
- use anchor_client::solana_sdk::signature::{Keypair, Signer};
- use anchor_client::solana_sdk::system_instruction;
- use anchor_client::{Client, Cluster};
- use anyhow::Result;
- use clap::Parser;
- use solana_sdk::commitment_config::CommitmentConfig;
- use solana_sdk::signature::read_keypair_file;
- use solana_sdk::system_program;
- // The `accounts` and `instructions` modules are generated by the framework.
- use basic_2::accounts as basic_2_accounts;
- use basic_2::instruction as basic_2_instruction;
- use basic_2::Counter;
- use events::instruction as events_instruction;
- use events::MyEvent;
- use optional::accounts::Initialize as OptionalInitialize;
- use optional::instruction as optional_instruction;
- // The `accounts` and `instructions` modules are generated by the framework.
- use basic_4::accounts as basic_4_accounts;
- use basic_4::instruction as basic_4_instruction;
- use basic_4::Counter as CounterAccount;
- // The `accounts` and `instructions` modules are generated by the framework.
- use crate::Opts;
- use composite::accounts::{Bar, CompositeUpdate, Foo, Initialize};
- use composite::instruction as composite_instruction;
- use composite::{DummyA, DummyB};
- use optional::account::{DataAccount, DataPda};
- use std::ops::Deref;
- use std::sync::Arc;
- use std::time::Duration;
- use tokio::sync::mpsc;
- use tokio::time::sleep;
- pub async fn main() -> Result<()> {
- let opts = Opts::parse();
- // Wallet and cluster params.
- let payer = read_keypair_file(&*shellexpand::tilde("~/.config/solana/id.json"))
- .expect("Example requires a keypair file");
- let url = Cluster::Custom(
- "http://localhost:8899".to_string(),
- "ws://127.0.0.1:8900".to_string(),
- );
- // Client.
- let payer = Arc::new(payer);
- let client =
- Client::new_with_options(url.clone(), payer.clone(), CommitmentConfig::processed());
- println!("\nStarting async test...");
- composite(&client, opts.composite_pid).await?;
- basic_2(&client, opts.basic_2_pid).await?;
- basic_4(&client, opts.basic_4_pid).await?;
- test_tokio(client, opts.basic_2_pid).await?;
- // Can also use references, since they deref to a signer
- let payer: &Keypair = &payer;
- let client = Client::new_with_options(url, payer, CommitmentConfig::processed());
- events(&client, opts.events_pid).await?;
- optional(&client, opts.optional_pid).await?;
- // Success.
- Ok(())
- }
- pub async fn test_tokio(client: Client<Arc<Keypair>>, pid: Pubkey) -> Result<()> {
- tokio::spawn(async move {
- let program = client.program(pid).unwrap();
- // `Create` parameters.
- let counter = Arc::new(Keypair::new());
- let counter_pubkey = counter.pubkey();
- let authority = program.payer();
- // Build and send a transaction.
- program
- .request()
- .signer(counter)
- .accounts(basic_2_accounts::Create {
- counter: counter_pubkey,
- user: authority,
- system_program: system_program::ID,
- })
- .args(basic_2_instruction::Create { authority })
- .send()
- .await
- .unwrap();
- let counter_account: Counter = program.account(counter_pubkey).await.unwrap();
- assert_eq!(counter_account.authority, authority);
- assert_eq!(counter_account.count, 0);
- })
- .await
- .unwrap();
- println!("Tokio success!");
- Ok(())
- }
- pub async fn composite<C: Deref<Target = impl Signer> + Clone>(
- client: &Client<C>,
- pid: Pubkey,
- ) -> Result<()> {
- // Program client.
- let program = client.program(pid)?;
- // `Initialize` parameters.
- let dummy_a = Arc::new(Keypair::new());
- let dummy_b = Arc::new(Keypair::new());
- // Build and send a transaction.
- program
- .request()
- .instruction(system_instruction::create_account(
- &program.payer(),
- &dummy_a.pubkey(),
- program
- .rpc()
- .get_minimum_balance_for_rent_exemption(500)
- .await?,
- 500,
- &program.id(),
- ))
- .instruction(system_instruction::create_account(
- &program.payer(),
- &dummy_b.pubkey(),
- program
- .rpc()
- .get_minimum_balance_for_rent_exemption(500)
- .await?,
- 500,
- &program.id(),
- ))
- .signer(dummy_a.clone())
- .signer(dummy_b.clone())
- .accounts(Initialize {
- dummy_a: dummy_a.pubkey(),
- dummy_b: dummy_b.pubkey(),
- })
- .args(composite_instruction::Initialize)
- .send()
- .await?;
- // Assert the transaction worked.
- let dummy_a_account: DummyA = program.account(dummy_a.pubkey()).await?;
- let dummy_b_account: DummyB = program.account(dummy_b.pubkey()).await?;
- assert_eq!(dummy_a_account.data, 0);
- assert_eq!(dummy_b_account.data, 0);
- // Build and send another transaction, using composite account parameters.
- program
- .request()
- .accounts(CompositeUpdate {
- foo: Foo {
- dummy_a: dummy_a.pubkey(),
- },
- bar: Bar {
- dummy_b: dummy_b.pubkey(),
- },
- })
- .args(composite_instruction::CompositeUpdate {
- dummy_a: 1234,
- dummy_b: 4321,
- })
- .send()
- .await?;
- // Assert the transaction worked.
- let dummy_a_account: DummyA = program.account(dummy_a.pubkey()).await?;
- let dummy_b_account: DummyB = program.account(dummy_b.pubkey()).await?;
- assert_eq!(dummy_a_account.data, 1234);
- assert_eq!(dummy_b_account.data, 4321);
- println!("Composite success!");
- Ok(())
- }
- pub async fn basic_2<C: Deref<Target = impl Signer> + Clone>(
- client: &Client<C>,
- pid: Pubkey,
- ) -> Result<()> {
- let program = client.program(pid)?;
- // `Create` parameters.
- let counter = Arc::new(Keypair::new());
- let authority = program.payer();
- // Build and send a transaction.
- program
- .request()
- .signer(counter.clone())
- .accounts(basic_2_accounts::Create {
- counter: counter.pubkey(),
- user: authority,
- system_program: system_program::ID,
- })
- .args(basic_2_instruction::Create { authority })
- .send()
- .await?;
- let counter_account: Counter = program.account(counter.pubkey()).await?;
- assert_eq!(counter_account.authority, authority);
- assert_eq!(counter_account.count, 0);
- println!("Basic 2 success!");
- Ok(())
- }
- pub async fn events<C: Deref<Target = impl Signer> + Clone>(
- client: &Client<C>,
- pid: Pubkey,
- ) -> Result<()> {
- let program = client.program(pid)?;
- let (sender, mut receiver) = mpsc::unbounded_channel();
- let event_unsubscriber = program
- .on(move |_, event: MyEvent| {
- if sender.send(event).is_err() {
- println!("Error while transferring the event.")
- }
- })
- .await?;
- sleep(Duration::from_millis(1000)).await;
- program
- .request()
- .args(events_instruction::Initialize {})
- .send()
- .await?;
- let event = receiver.recv().await.unwrap();
- assert_eq!(event.data, 5);
- assert_eq!(event.label, "hello".to_string());
- event_unsubscriber.unsubscribe().await;
- println!("Events success!");
- Ok(())
- }
- pub async fn basic_4<C: Deref<Target = impl Signer> + Clone>(
- client: &Client<C>,
- pid: Pubkey,
- ) -> Result<()> {
- let program = client.program(pid)?;
- let authority = program.payer();
- let (counter, _) = Pubkey::find_program_address(&[b"counter"], &pid);
- program
- .request()
- .accounts(basic_4_accounts::Initialize {
- counter,
- authority,
- system_program: system_program::ID,
- })
- .args(basic_4_instruction::Initialize {})
- .send()
- .await?;
- let counter_account: CounterAccount = program.account(counter).await?;
- assert_eq!(counter_account.authority, authority);
- assert_eq!(counter_account.count, 0);
- program
- .request()
- .accounts(basic_4_accounts::Increment { counter, authority })
- .args(basic_4_instruction::Increment {})
- .send()
- .await?;
- let counter_account: CounterAccount = program.account(counter).await?;
- assert_eq!(counter_account.authority, authority);
- assert_eq!(counter_account.count, 1);
- println!("Basic 4 success!");
- Ok(())
- }
- pub async fn optional<C: Deref<Target = impl Signer> + Clone>(
- client: &Client<C>,
- pid: Pubkey,
- ) -> Result<()> {
- // Program client.
- let program = client.program(pid)?;
- // `Initialize` parameters.
- let data_account_keypair = Arc::new(Keypair::new());
- let data_account_key = data_account_keypair.pubkey();
- let data_pda_seeds = &[DataPda::PREFIX.as_ref(), data_account_key.as_ref()];
- let data_pda_key = Pubkey::find_program_address(data_pda_seeds, &pid).0;
- let required_keypair = Arc::new(Keypair::new());
- let value: u64 = 10;
- // Build and send a transaction.
- program
- .request()
- .instruction(system_instruction::create_account(
- &program.payer(),
- &required_keypair.pubkey(),
- program
- .rpc()
- .get_minimum_balance_for_rent_exemption(DataAccount::LEN)
- .await?,
- DataAccount::LEN as u64,
- &program.id(),
- ))
- .signer(data_account_keypair.clone())
- .signer(required_keypair.clone())
- .accounts(OptionalInitialize {
- payer: Some(program.payer()),
- required: required_keypair.pubkey(),
- system_program: Some(system_program::id()),
- optional_account: Some(data_account_keypair.pubkey()),
- optional_pda: None,
- })
- .args(optional_instruction::Initialize { value, key: pid })
- .send()
- .await
- .unwrap();
- // Assert the transaction worked.
- let required: DataAccount = program.account(required_keypair.pubkey()).await?;
- assert_eq!(required.data, 0);
- let optional_pda = program.account::<DataPda>(data_pda_key).await;
- assert!(optional_pda.is_err());
- let optional_account: DataAccount = program.account(data_account_keypair.pubkey()).await?;
- assert_eq!(optional_account.data, value * 2);
- println!("Optional success!");
- Ok(())
- }
|