main.rs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. use anchor_client::solana_sdk::commitment_config::CommitmentConfig;
  2. use anchor_client::solana_sdk::pubkey::Pubkey;
  3. use anchor_client::solana_sdk::signature::read_keypair_file;
  4. use anchor_client::solana_sdk::signature::{Keypair, Signer};
  5. use anchor_client::solana_sdk::system_instruction;
  6. use anchor_client::{Client, Cluster, EventContext};
  7. use anyhow::Result;
  8. use solana_sdk::system_program;
  9. // The `accounts` and `instructions` modules are generated by the framework.
  10. use basic_2::accounts as basic_2_accounts;
  11. use basic_2::instruction as basic_2_instruction;
  12. use basic_2::Counter;
  13. use events::instruction as events_instruction;
  14. use events::MyEvent;
  15. // The `accounts` and `instructions` modules are generated by the framework.
  16. use basic_4::accounts as basic_4_accounts;
  17. use basic_4::basic_4::Counter as CounterState;
  18. use basic_4::instruction as basic_4_instruction;
  19. use clap::Parser;
  20. // The `accounts` and `instructions` modules are generated by the framework.
  21. use composite::accounts::{Bar, CompositeUpdate, Foo, Initialize};
  22. use composite::instruction as composite_instruction;
  23. use composite::{DummyA, DummyB};
  24. use rand::rngs::OsRng;
  25. use std::time::Duration;
  26. #[derive(Parser, Debug)]
  27. pub struct Opts {
  28. #[clap(long)]
  29. composite_pid: Pubkey,
  30. #[clap(long)]
  31. basic_2_pid: Pubkey,
  32. #[clap(long)]
  33. basic_4_pid: Pubkey,
  34. #[clap(long)]
  35. events_pid: Pubkey,
  36. }
  37. // This example assumes a local validator is running with the programs
  38. // deployed at the addresses given by the CLI args.
  39. fn main() -> Result<()> {
  40. println!("Starting test...");
  41. let opts = Opts::parse();
  42. // Wallet and cluster params.
  43. let payer = read_keypair_file(&*shellexpand::tilde("~/.config/solana/id.json"))
  44. .expect("Example requires a keypair file");
  45. let url = Cluster::Custom(
  46. "http://localhost:8899".to_string(),
  47. "ws://127.0.0.1:8900".to_string(),
  48. );
  49. // Client.
  50. let client = Client::new_with_options(url, payer, CommitmentConfig::processed());
  51. // Run tests.
  52. composite(&client, opts.composite_pid)?;
  53. basic_2(&client, opts.basic_2_pid)?;
  54. basic_4(&client, opts.basic_4_pid)?;
  55. events(&client, opts.events_pid)?;
  56. // Success.
  57. Ok(())
  58. }
  59. // Runs a client for examples/tutorial/composite.
  60. //
  61. // Make sure to run a localnet with the program deploy to run this example.
  62. fn composite(client: &Client, pid: Pubkey) -> Result<()> {
  63. // Program client.
  64. let program = client.program(pid);
  65. // `Initialize` parameters.
  66. let dummy_a = Keypair::generate(&mut OsRng);
  67. let dummy_b = Keypair::generate(&mut OsRng);
  68. // Build and send a transaction.
  69. program
  70. .request()
  71. .instruction(system_instruction::create_account(
  72. &program.payer(),
  73. &dummy_a.pubkey(),
  74. program.rpc().get_minimum_balance_for_rent_exemption(500)?,
  75. 500,
  76. &program.id(),
  77. ))
  78. .instruction(system_instruction::create_account(
  79. &program.payer(),
  80. &dummy_b.pubkey(),
  81. program.rpc().get_minimum_balance_for_rent_exemption(500)?,
  82. 500,
  83. &program.id(),
  84. ))
  85. .signer(&dummy_a)
  86. .signer(&dummy_b)
  87. .accounts(Initialize {
  88. dummy_a: dummy_a.pubkey(),
  89. dummy_b: dummy_b.pubkey(),
  90. })
  91. .args(composite_instruction::Initialize)
  92. .send()?;
  93. // Assert the transaction worked.
  94. let dummy_a_account: DummyA = program.account(dummy_a.pubkey())?;
  95. let dummy_b_account: DummyB = program.account(dummy_b.pubkey())?;
  96. assert_eq!(dummy_a_account.data, 0);
  97. assert_eq!(dummy_b_account.data, 0);
  98. // Build and send another transaction, using composite account parameters.
  99. program
  100. .request()
  101. .accounts(CompositeUpdate {
  102. foo: Foo {
  103. dummy_a: dummy_a.pubkey(),
  104. },
  105. bar: Bar {
  106. dummy_b: dummy_b.pubkey(),
  107. },
  108. })
  109. .args(composite_instruction::CompositeUpdate {
  110. dummy_a: 1234,
  111. dummy_b: 4321,
  112. })
  113. .send()?;
  114. // Assert the transaction worked.
  115. let dummy_a_account: DummyA = program.account(dummy_a.pubkey())?;
  116. let dummy_b_account: DummyB = program.account(dummy_b.pubkey())?;
  117. assert_eq!(dummy_a_account.data, 1234);
  118. assert_eq!(dummy_b_account.data, 4321);
  119. println!("Composite success!");
  120. Ok(())
  121. }
  122. // Runs a client for examples/tutorial/basic-2.
  123. //
  124. // Make sure to run a localnet with the program deploy to run this example.
  125. fn basic_2(client: &Client, pid: Pubkey) -> Result<()> {
  126. let program = client.program(pid);
  127. // `Create` parameters.
  128. let counter = Keypair::generate(&mut OsRng);
  129. let authority = program.payer();
  130. // Build and send a transaction.
  131. program
  132. .request()
  133. .signer(&counter)
  134. .accounts(basic_2_accounts::Create {
  135. counter: counter.pubkey(),
  136. user: authority,
  137. system_program: system_program::ID,
  138. })
  139. .args(basic_2_instruction::Create { authority })
  140. .send()?;
  141. let counter_account: Counter = program.account(counter.pubkey())?;
  142. assert_eq!(counter_account.authority, authority);
  143. assert_eq!(counter_account.count, 0);
  144. println!("Basic 2 success!");
  145. Ok(())
  146. }
  147. fn events(client: &Client, pid: Pubkey) -> Result<()> {
  148. let program = client.program(pid);
  149. let (sender, receiver) = std::sync::mpsc::channel();
  150. let handle = program.on(move |_ctx: &EventContext, event: MyEvent| {
  151. sender.send(event).unwrap();
  152. })?;
  153. std::thread::sleep(Duration::from_millis(1000));
  154. program
  155. .request()
  156. .args(events_instruction::Initialize {})
  157. .send()?;
  158. let event = receiver.recv().unwrap();
  159. assert_eq!(event.data, 5);
  160. assert_eq!(event.label, "hello".to_string());
  161. // TODO: remove once https://github.com/solana-labs/solana/issues/16102
  162. // is addressed. Until then, drop the subscription handle in another
  163. // thread so that we deadlock in the other thread as to not block
  164. // this thread.
  165. std::thread::spawn(move || {
  166. drop(handle);
  167. });
  168. println!("Events success!");
  169. Ok(())
  170. }
  171. pub fn basic_4(client: &Client, pid: Pubkey) -> Result<()> {
  172. let program = client.program(pid);
  173. let authority = program.payer();
  174. // Invoke the state's `new` constructor.
  175. program
  176. .state_request()
  177. .accounts(basic_4_accounts::Auth { authority })
  178. .new(basic_4_instruction::state::New)
  179. .send()?;
  180. let counter_account: CounterState = program.state()?;
  181. assert_eq!(counter_account.authority, authority);
  182. assert_eq!(counter_account.count, 0);
  183. // Call a state method.
  184. program
  185. .state_request()
  186. .accounts(basic_4_accounts::Auth { authority })
  187. .args(basic_4_instruction::state::Increment)
  188. .send()?;
  189. let counter_account: CounterState = program.state()?;
  190. assert_eq!(counter_account.authority, authority);
  191. assert_eq!(counter_account.count, 1);
  192. println!("Basic 4 success!");
  193. Ok(())
  194. }