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