main.rs 7.0 KB

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