nonblocking.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. use anchor_client::solana_sdk::pubkey::Pubkey;
  2. use anchor_client::solana_sdk::signature::{Keypair, Signer};
  3. use anchor_client::solana_sdk::system_instruction;
  4. use anchor_client::{Client, Cluster};
  5. use anyhow::Result;
  6. use clap::Parser;
  7. use solana_sdk::commitment_config::CommitmentConfig;
  8. use solana_sdk::signature::read_keypair_file;
  9. use solana_sdk::system_program;
  10. // The `accounts` and `instructions` modules are generated by the framework.
  11. use basic_2::accounts as basic_2_accounts;
  12. use basic_2::instruction as basic_2_instruction;
  13. use basic_2::Counter;
  14. use events::instruction as events_instruction;
  15. use events::MyEvent;
  16. use optional::accounts::Initialize as OptionalInitialize;
  17. use optional::instruction as optional_instruction;
  18. // The `accounts` and `instructions` modules are generated by the framework.
  19. use basic_4::accounts as basic_4_accounts;
  20. use basic_4::instruction as basic_4_instruction;
  21. use basic_4::Counter as CounterAccount;
  22. // The `accounts` and `instructions` modules are generated by the framework.
  23. use crate::Opts;
  24. use composite::accounts::{Bar, CompositeUpdate, Foo, Initialize};
  25. use composite::instruction as composite_instruction;
  26. use composite::{DummyA, DummyB};
  27. use optional::account::{DataAccount, DataPda};
  28. use std::ops::Deref;
  29. use std::sync::Arc;
  30. use std::time::Duration;
  31. use tokio::sync::mpsc;
  32. use tokio::time::sleep;
  33. pub async fn main() -> Result<()> {
  34. let opts = Opts::parse();
  35. // Wallet and cluster params.
  36. let payer = read_keypair_file(&*shellexpand::tilde("~/.config/solana/id.json"))
  37. .expect("Example requires a keypair file");
  38. let url = Cluster::Custom(
  39. "http://localhost:8899".to_string(),
  40. "ws://127.0.0.1:8900".to_string(),
  41. );
  42. // Client.
  43. let payer = Arc::new(payer);
  44. let client =
  45. Client::new_with_options(url.clone(), payer.clone(), CommitmentConfig::processed());
  46. println!("\nStarting async test...");
  47. composite(&client, opts.composite_pid).await?;
  48. basic_2(&client, opts.basic_2_pid).await?;
  49. basic_4(&client, opts.basic_4_pid).await?;
  50. test_tokio(client, opts.basic_2_pid).await?;
  51. // Can also use references, since they deref to a signer
  52. let payer: &Keypair = &payer;
  53. let client = Client::new_with_options(url, payer, CommitmentConfig::processed());
  54. events(&client, opts.events_pid).await?;
  55. optional(&client, opts.optional_pid).await?;
  56. // Success.
  57. Ok(())
  58. }
  59. pub async fn test_tokio(client: Client<Arc<Keypair>>, pid: Pubkey) -> Result<()> {
  60. tokio::spawn(async move {
  61. let program = client.program(pid).unwrap();
  62. // `Create` parameters.
  63. let counter = Arc::new(Keypair::new());
  64. let counter_pubkey = counter.pubkey();
  65. let authority = program.payer();
  66. // Build and send a transaction.
  67. program
  68. .request()
  69. .signer(counter)
  70. .accounts(basic_2_accounts::Create {
  71. counter: counter_pubkey,
  72. user: authority,
  73. system_program: system_program::ID,
  74. })
  75. .args(basic_2_instruction::Create { authority })
  76. .send()
  77. .await
  78. .unwrap();
  79. let counter_account: Counter = program.account(counter_pubkey).await.unwrap();
  80. assert_eq!(counter_account.authority, authority);
  81. assert_eq!(counter_account.count, 0);
  82. })
  83. .await
  84. .unwrap();
  85. println!("Tokio success!");
  86. Ok(())
  87. }
  88. pub async fn composite<C: Deref<Target = impl Signer> + Clone>(
  89. client: &Client<C>,
  90. pid: Pubkey,
  91. ) -> Result<()> {
  92. // Program client.
  93. let program = client.program(pid)?;
  94. // `Initialize` parameters.
  95. let dummy_a = Arc::new(Keypair::new());
  96. let dummy_b = Arc::new(Keypair::new());
  97. // Build and send a transaction.
  98. program
  99. .request()
  100. .instruction(system_instruction::create_account(
  101. &program.payer(),
  102. &dummy_a.pubkey(),
  103. program
  104. .rpc()
  105. .get_minimum_balance_for_rent_exemption(500)
  106. .await?,
  107. 500,
  108. &program.id(),
  109. ))
  110. .instruction(system_instruction::create_account(
  111. &program.payer(),
  112. &dummy_b.pubkey(),
  113. program
  114. .rpc()
  115. .get_minimum_balance_for_rent_exemption(500)
  116. .await?,
  117. 500,
  118. &program.id(),
  119. ))
  120. .signer(dummy_a.clone())
  121. .signer(dummy_b.clone())
  122. .accounts(Initialize {
  123. dummy_a: dummy_a.pubkey(),
  124. dummy_b: dummy_b.pubkey(),
  125. })
  126. .args(composite_instruction::Initialize)
  127. .send()
  128. .await?;
  129. // Assert the transaction worked.
  130. let dummy_a_account: DummyA = program.account(dummy_a.pubkey()).await?;
  131. let dummy_b_account: DummyB = program.account(dummy_b.pubkey()).await?;
  132. assert_eq!(dummy_a_account.data, 0);
  133. assert_eq!(dummy_b_account.data, 0);
  134. // Build and send another transaction, using composite account parameters.
  135. program
  136. .request()
  137. .accounts(CompositeUpdate {
  138. foo: Foo {
  139. dummy_a: dummy_a.pubkey(),
  140. },
  141. bar: Bar {
  142. dummy_b: dummy_b.pubkey(),
  143. },
  144. })
  145. .args(composite_instruction::CompositeUpdate {
  146. dummy_a: 1234,
  147. dummy_b: 4321,
  148. })
  149. .send()
  150. .await?;
  151. // Assert the transaction worked.
  152. let dummy_a_account: DummyA = program.account(dummy_a.pubkey()).await?;
  153. let dummy_b_account: DummyB = program.account(dummy_b.pubkey()).await?;
  154. assert_eq!(dummy_a_account.data, 1234);
  155. assert_eq!(dummy_b_account.data, 4321);
  156. println!("Composite success!");
  157. Ok(())
  158. }
  159. pub async fn basic_2<C: Deref<Target = impl Signer> + Clone>(
  160. client: &Client<C>,
  161. pid: Pubkey,
  162. ) -> Result<()> {
  163. let program = client.program(pid)?;
  164. // `Create` parameters.
  165. let counter = Arc::new(Keypair::new());
  166. let authority = program.payer();
  167. // Build and send a transaction.
  168. program
  169. .request()
  170. .signer(counter.clone())
  171. .accounts(basic_2_accounts::Create {
  172. counter: counter.pubkey(),
  173. user: authority,
  174. system_program: system_program::ID,
  175. })
  176. .args(basic_2_instruction::Create { authority })
  177. .send()
  178. .await?;
  179. let counter_account: Counter = program.account(counter.pubkey()).await?;
  180. assert_eq!(counter_account.authority, authority);
  181. assert_eq!(counter_account.count, 0);
  182. println!("Basic 2 success!");
  183. Ok(())
  184. }
  185. pub async fn events<C: Deref<Target = impl Signer> + Clone>(
  186. client: &Client<C>,
  187. pid: Pubkey,
  188. ) -> Result<()> {
  189. let program = client.program(pid)?;
  190. let (sender, mut receiver) = mpsc::unbounded_channel();
  191. let event_unsubscriber = program
  192. .on(move |_, event: MyEvent| {
  193. if sender.send(event).is_err() {
  194. println!("Error while transferring the event.")
  195. }
  196. })
  197. .await?;
  198. sleep(Duration::from_millis(1000)).await;
  199. program
  200. .request()
  201. .args(events_instruction::Initialize {})
  202. .send()
  203. .await?;
  204. let event = receiver.recv().await.unwrap();
  205. assert_eq!(event.data, 5);
  206. assert_eq!(event.label, "hello".to_string());
  207. event_unsubscriber.unsubscribe().await;
  208. println!("Events success!");
  209. Ok(())
  210. }
  211. pub async fn basic_4<C: Deref<Target = impl Signer> + Clone>(
  212. client: &Client<C>,
  213. pid: Pubkey,
  214. ) -> Result<()> {
  215. let program = client.program(pid)?;
  216. let authority = program.payer();
  217. let (counter, _) = Pubkey::find_program_address(&[b"counter"], &pid);
  218. program
  219. .request()
  220. .accounts(basic_4_accounts::Initialize {
  221. counter,
  222. authority,
  223. system_program: system_program::ID,
  224. })
  225. .args(basic_4_instruction::Initialize {})
  226. .send()
  227. .await?;
  228. let counter_account: CounterAccount = program.account(counter).await?;
  229. assert_eq!(counter_account.authority, authority);
  230. assert_eq!(counter_account.count, 0);
  231. program
  232. .request()
  233. .accounts(basic_4_accounts::Increment { counter, authority })
  234. .args(basic_4_instruction::Increment {})
  235. .send()
  236. .await?;
  237. let counter_account: CounterAccount = program.account(counter).await?;
  238. assert_eq!(counter_account.authority, authority);
  239. assert_eq!(counter_account.count, 1);
  240. println!("Basic 4 success!");
  241. Ok(())
  242. }
  243. pub async fn optional<C: Deref<Target = impl Signer> + Clone>(
  244. client: &Client<C>,
  245. pid: Pubkey,
  246. ) -> Result<()> {
  247. // Program client.
  248. let program = client.program(pid)?;
  249. // `Initialize` parameters.
  250. let data_account_keypair = Arc::new(Keypair::new());
  251. let data_account_key = data_account_keypair.pubkey();
  252. let data_pda_seeds = &[DataPda::PREFIX.as_ref(), data_account_key.as_ref()];
  253. let data_pda_key = Pubkey::find_program_address(data_pda_seeds, &pid).0;
  254. let required_keypair = Arc::new(Keypair::new());
  255. let value: u64 = 10;
  256. // Build and send a transaction.
  257. program
  258. .request()
  259. .instruction(system_instruction::create_account(
  260. &program.payer(),
  261. &required_keypair.pubkey(),
  262. program
  263. .rpc()
  264. .get_minimum_balance_for_rent_exemption(DataAccount::LEN)
  265. .await?,
  266. DataAccount::LEN as u64,
  267. &program.id(),
  268. ))
  269. .signer(data_account_keypair.clone())
  270. .signer(required_keypair.clone())
  271. .accounts(OptionalInitialize {
  272. payer: Some(program.payer()),
  273. required: required_keypair.pubkey(),
  274. system_program: Some(system_program::id()),
  275. optional_account: Some(data_account_keypair.pubkey()),
  276. optional_pda: None,
  277. })
  278. .args(optional_instruction::Initialize { value, key: pid })
  279. .send()
  280. .await
  281. .unwrap();
  282. // Assert the transaction worked.
  283. let required: DataAccount = program.account(required_keypair.pubkey()).await?;
  284. assert_eq!(required.data, 0);
  285. let optional_pda = program.account::<DataPda>(data_pda_key).await;
  286. assert!(optional_pda.is_err());
  287. let optional_account: DataAccount = program.account(data_account_keypair.pubkey()).await?;
  288. assert_eq!(optional_account.data, value * 2);
  289. println!("Optional success!");
  290. Ok(())
  291. }