1use bytemuck::{Pod, Zeroable};
2use num_enum::TryFromPrimitive;
3use shank::ShankInstruction;
4use solana_program::{
5 instruction::{AccountMeta, Instruction},
6 pubkey::Pubkey,
7 system_program, sysvar,
8};
9
10use crate::{
11 impl_instruction_from_bytes, impl_to_bytes, state::Hash, BUS, METADATA, MINT, MINT_ADDRESS,
12 MINT_NOISE, PROOF, TREASURY, TREASURY_ADDRESS,
13};
14
15#[repr(u8)]
16#[derive(Clone, Copy, Debug, Eq, PartialEq, ShankInstruction, TryFromPrimitive)]
17#[rustfmt::skip]
18pub enum OreInstruction {
19 #[account(0, name = "ore_program", desc = "Ore program")]
20 #[account(1, name = "signer", desc = "Signer", signer)]
21 #[account(2, name = "bus_0", desc = "Ore bus account 0", writable)]
22 #[account(3, name = "bus_1", desc = "Ore bus account 1", writable)]
23 #[account(4, name = "bus_2", desc = "Ore bus account 2", writable)]
24 #[account(5, name = "bus_3", desc = "Ore bus account 3", writable)]
25 #[account(6, name = "bus_4", desc = "Ore bus account 4", writable)]
26 #[account(7, name = "bus_5", desc = "Ore bus account 5", writable)]
27 #[account(8, name = "bus_6", desc = "Ore bus account 6", writable)]
28 #[account(9, name = "bus_7", desc = "Ore bus account 7", writable)]
29 #[account(10, name = "mint", desc = "Ore token mint account", writable)]
30 #[account(11, name = "treasury", desc = "Ore treasury account", writable)]
31 #[account(12, name = "treasury_tokens", desc = "Ore treasury token account", writable)]
32 #[account(13, name = "token_program", desc = "SPL token program")]
33 Reset = 0,
34
35 #[account(0, name = "ore_program", desc = "Ore program")]
36 #[account(1, name = "signer", desc = "Signer", signer)]
37 #[account(2, name = "proof", desc = "Ore proof account", writable)]
38 #[account(3, name = "system_program", desc = "Solana system program")]
39 Register = 1,
40
41 #[account(0, name = "ore_program", desc = "Ore program")]
42 #[account(1, name = "signer", desc = "Signer", signer)]
43 #[account(2, name = "bus", desc = "Ore bus account", writable)]
44 #[account(3, name = "proof", desc = "Ore proof account", writable)]
45 #[account(4, name = "treasury", desc = "Ore treasury account")]
46 #[account(5, name = "slot_hashes", desc = "Solana slot hashes sysvar")]
47 Mine = 2,
48
49 #[account(0, name = "ore_program", desc = "Ore program")]
50 #[account(1, name = "signer", desc = "Signer", signer)]
51 #[account(2, name = "beneficiary", desc = "Beneficiary token account", writable)]
52 #[account(3, name = "proof", desc = "Ore proof account", writable)]
53 #[account(4, name = "treasury", desc = "Ore treasury account", writable)]
54 #[account(5, name = "treasury_tokens", desc = "Ore treasury token account", writable)]
55 #[account(6, name = "token_program", desc = "SPL token program")]
56 Claim = 3,
57
58 #[account(0, name = "ore_program", desc = "Ore program")]
59 #[account(1, name = "signer", desc = "Admin signer", signer)]
60 #[account(2, name = "bus_0", desc = "Ore bus account 0", writable)]
61 #[account(3, name = "bus_1", desc = "Ore bus account 1", writable)]
62 #[account(4, name = "bus_2", desc = "Ore bus account 2", writable)]
63 #[account(5, name = "bus_3", desc = "Ore bus account 3", writable)]
64 #[account(6, name = "bus_4", desc = "Ore bus account 4", writable)]
65 #[account(7, name = "bus_5", desc = "Ore bus account 5", writable)]
66 #[account(8, name = "bus_6", desc = "Ore bus account 6", writable)]
67 #[account(9, name = "bus_7", desc = "Ore bus account 7", writable)]
68 #[account(10, name = "metadata", desc = "Ore mint metadata account", writable)]
69 #[account(11, name = "mint", desc = "Ore mint account", writable)]
70 #[account(12, name = "treasury", desc = "Ore treasury account", writable)]
71 #[account(13, name = "treasury_tokens", desc = "Ore treasury token account", writable)]
72 #[account(14, name = "system_program", desc = "Solana system program")]
73 #[account(15, name = "token_program", desc = "SPL token program")]
74 #[account(16, name = "associated_token_program", desc = "SPL associated token program")]
75 #[account(17, name = "mpl_metadata_program", desc = "Metaplex metadata program")]
76 #[account(18, name = "rent", desc = "Solana rent sysvar")]
77 Initialize = 100,
78
79 #[account(0, name = "ore_program", desc = "Ore program")]
80 #[account(1, name = "signer", desc = "Admin signer", signer)]
81 #[account(2, name = "treasury", desc = "Ore treasury account")]
82 UpdateAdmin = 101,
83
84 #[account(0, name = "ore_program", desc = "Ore program")]
85 #[account(1, name = "signer", desc = "Admin signer", signer)]
86 #[account(2, name = "treasury", desc = "Ore treasury account")]
87 UpdateDifficulty = 102,
88}
89
90impl OreInstruction {
91 pub fn to_vec(&self) -> Vec<u8> {
92 vec![*self as u8]
93 }
94}
95
96#[repr(C)]
97#[derive(Clone, Copy, Debug, Pod, Zeroable)]
98pub struct InitializeArgs {
99 pub bus_0_bump: u8,
100 pub bus_1_bump: u8,
101 pub bus_2_bump: u8,
102 pub bus_3_bump: u8,
103 pub bus_4_bump: u8,
104 pub bus_5_bump: u8,
105 pub bus_6_bump: u8,
106 pub bus_7_bump: u8,
107 pub metadata_bump: u8,
108 pub mint_bump: u8,
109 pub treasury_bump: u8,
110}
111
112#[repr(C)]
113#[derive(Clone, Copy, Debug, Pod, Zeroable)]
114pub struct RegisterArgs {
115 pub bump: u8,
116}
117
118#[repr(C)]
119#[derive(Clone, Copy, Debug, Pod, Zeroable)]
120pub struct MineArgs {
121 pub hash: Hash,
122 pub nonce: [u8; 8],
123}
124
125#[repr(C)]
126#[derive(Clone, Copy, Debug, Pod, Zeroable)]
127pub struct ClaimArgs {
128 pub amount: [u8; 8],
129}
130
131#[repr(C)]
132#[derive(Clone, Copy, Debug, Pod, Zeroable)]
133pub struct UpdateAdminArgs {
134 pub new_admin: Pubkey,
135}
136
137#[repr(C)]
138#[derive(Clone, Copy, Debug, Pod, Zeroable)]
139pub struct UpdateDifficultyArgs {
140 pub new_difficulty: Hash,
141}
142
143impl_to_bytes!(InitializeArgs);
144impl_to_bytes!(RegisterArgs);
145impl_to_bytes!(MineArgs);
146impl_to_bytes!(ClaimArgs);
147impl_to_bytes!(UpdateAdminArgs);
148impl_to_bytes!(UpdateDifficultyArgs);
149
150impl_instruction_from_bytes!(InitializeArgs);
151impl_instruction_from_bytes!(RegisterArgs);
152impl_instruction_from_bytes!(MineArgs);
153impl_instruction_from_bytes!(ClaimArgs);
154impl_instruction_from_bytes!(UpdateAdminArgs);
155impl_instruction_from_bytes!(UpdateDifficultyArgs);
156
157pub fn reset(signer: Pubkey) -> Instruction {
159 let bus_0 = Pubkey::find_program_address(&[BUS, &[0]], &crate::id()).0;
160 let bus_1 = Pubkey::find_program_address(&[BUS, &[1]], &crate::id()).0;
161 let bus_2 = Pubkey::find_program_address(&[BUS, &[2]], &crate::id()).0;
162 let bus_3 = Pubkey::find_program_address(&[BUS, &[3]], &crate::id()).0;
163 let bus_4 = Pubkey::find_program_address(&[BUS, &[4]], &crate::id()).0;
164 let bus_5 = Pubkey::find_program_address(&[BUS, &[5]], &crate::id()).0;
165 let bus_6 = Pubkey::find_program_address(&[BUS, &[6]], &crate::id()).0;
166 let bus_7 = Pubkey::find_program_address(&[BUS, &[7]], &crate::id()).0;
167 let treasury_tokens = spl_associated_token_account::get_associated_token_address(
168 &TREASURY_ADDRESS,
169 &MINT_ADDRESS,
170 );
171 Instruction {
172 program_id: crate::id(),
173 accounts: vec![
174 AccountMeta::new(signer, true),
175 AccountMeta::new(bus_0, false),
176 AccountMeta::new(bus_1, false),
177 AccountMeta::new(bus_2, false),
178 AccountMeta::new(bus_3, false),
179 AccountMeta::new(bus_4, false),
180 AccountMeta::new(bus_5, false),
181 AccountMeta::new(bus_6, false),
182 AccountMeta::new(bus_7, false),
183 AccountMeta::new(MINT_ADDRESS, false),
184 AccountMeta::new(TREASURY_ADDRESS, false),
185 AccountMeta::new(treasury_tokens, false),
186 AccountMeta::new_readonly(spl_token::id(), false),
187 ],
188 data: OreInstruction::Reset.to_vec(),
189 }
190}
191
192pub fn register(signer: Pubkey) -> Instruction {
194 let proof_pda = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id());
195 Instruction {
196 program_id: crate::id(),
197 accounts: vec![
198 AccountMeta::new(signer, true),
199 AccountMeta::new(proof_pda.0, false),
200 AccountMeta::new_readonly(solana_program::system_program::id(), false),
201 ],
202 data: [
203 OreInstruction::Register.to_vec(),
204 RegisterArgs { bump: proof_pda.1 }.to_bytes().to_vec(),
205 ]
206 .concat(),
207 }
208}
209
210pub fn mine(signer: Pubkey, bus: Pubkey, hash: Hash, nonce: u64) -> Instruction {
212 let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0;
213 Instruction {
214 program_id: crate::id(),
215 accounts: vec![
216 AccountMeta::new(signer, true),
217 AccountMeta::new(bus, false),
218 AccountMeta::new(proof, false),
219 AccountMeta::new_readonly(TREASURY_ADDRESS, false),
220 AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
221 ],
222 data: [
223 OreInstruction::Mine.to_vec(),
224 MineArgs {
225 hash,
226 nonce: nonce.to_le_bytes(),
227 }
228 .to_bytes()
229 .to_vec(),
230 ]
231 .concat(),
232 }
233}
234
235pub fn claim(signer: Pubkey, beneficiary: Pubkey, amount: u64) -> Instruction {
237 let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0;
238 let treasury_tokens = spl_associated_token_account::get_associated_token_address(
239 &TREASURY_ADDRESS,
240 &MINT_ADDRESS,
241 );
242 Instruction {
243 program_id: crate::id(),
244 accounts: vec![
245 AccountMeta::new(signer, true),
246 AccountMeta::new(beneficiary, false),
247 AccountMeta::new(proof, false),
248 AccountMeta::new(TREASURY_ADDRESS, false),
249 AccountMeta::new(treasury_tokens, false),
250 AccountMeta::new_readonly(spl_token::id(), false),
251 ],
252 data: [
253 OreInstruction::Claim.to_vec(),
254 ClaimArgs {
255 amount: amount.to_le_bytes(),
256 }
257 .to_bytes()
258 .to_vec(),
259 ]
260 .concat(),
261 }
262}
263
264pub fn initialize(signer: Pubkey) -> Instruction {
266 let bus_pdas = [
267 Pubkey::find_program_address(&[BUS, &[0]], &crate::id()),
268 Pubkey::find_program_address(&[BUS, &[1]], &crate::id()),
269 Pubkey::find_program_address(&[BUS, &[2]], &crate::id()),
270 Pubkey::find_program_address(&[BUS, &[3]], &crate::id()),
271 Pubkey::find_program_address(&[BUS, &[4]], &crate::id()),
272 Pubkey::find_program_address(&[BUS, &[5]], &crate::id()),
273 Pubkey::find_program_address(&[BUS, &[6]], &crate::id()),
274 Pubkey::find_program_address(&[BUS, &[7]], &crate::id()),
275 ];
276 let mint_pda = Pubkey::find_program_address(&[MINT, MINT_NOISE.as_slice()], &crate::id());
277 let treasury_pda = Pubkey::find_program_address(&[TREASURY], &crate::id());
278 let treasury_tokens =
279 spl_associated_token_account::get_associated_token_address(&treasury_pda.0, &mint_pda.0);
280 let metadata_pda = Pubkey::find_program_address(
281 &[
282 METADATA,
283 mpl_token_metadata::ID.as_ref(),
284 mint_pda.0.as_ref(),
285 ],
286 &mpl_token_metadata::ID,
287 );
288 Instruction {
289 program_id: crate::id(),
290 accounts: vec![
291 AccountMeta::new(signer, true),
292 AccountMeta::new(bus_pdas[0].0, false),
293 AccountMeta::new(bus_pdas[1].0, false),
294 AccountMeta::new(bus_pdas[2].0, false),
295 AccountMeta::new(bus_pdas[3].0, false),
296 AccountMeta::new(bus_pdas[4].0, false),
297 AccountMeta::new(bus_pdas[5].0, false),
298 AccountMeta::new(bus_pdas[6].0, false),
299 AccountMeta::new(bus_pdas[7].0, false),
300 AccountMeta::new(metadata_pda.0, false),
301 AccountMeta::new(mint_pda.0, false),
302 AccountMeta::new(treasury_pda.0, false),
303 AccountMeta::new(treasury_tokens, false),
304 AccountMeta::new_readonly(system_program::id(), false),
305 AccountMeta::new_readonly(spl_token::id(), false),
306 AccountMeta::new_readonly(spl_associated_token_account::id(), false),
307 AccountMeta::new_readonly(mpl_token_metadata::ID, false),
308 AccountMeta::new_readonly(sysvar::rent::id(), false),
309 ],
310 data: [
311 OreInstruction::Initialize.to_vec(),
312 InitializeArgs {
313 bus_0_bump: bus_pdas[0].1,
314 bus_1_bump: bus_pdas[1].1,
315 bus_2_bump: bus_pdas[2].1,
316 bus_3_bump: bus_pdas[3].1,
317 bus_4_bump: bus_pdas[4].1,
318 bus_5_bump: bus_pdas[5].1,
319 bus_6_bump: bus_pdas[6].1,
320 bus_7_bump: bus_pdas[7].1,
321 metadata_bump: metadata_pda.1,
322 mint_bump: mint_pda.1,
323 treasury_bump: treasury_pda.1,
324 }
325 .to_bytes()
326 .to_vec(),
327 ]
328 .concat(),
329 }
330}
331
332pub fn update_admin(signer: Pubkey, new_admin: Pubkey) -> Instruction {
334 Instruction {
335 program_id: crate::id(),
336 accounts: vec![
337 AccountMeta::new(signer, true),
338 AccountMeta::new(TREASURY_ADDRESS, false),
339 ],
340 data: [
341 OreInstruction::UpdateAdmin.to_vec(),
342 UpdateAdminArgs { new_admin }.to_bytes().to_vec(),
343 ]
344 .concat(),
345 }
346}
347
348pub fn update_difficulty(signer: Pubkey, new_difficulty: Hash) -> Instruction {
350 Instruction {
351 program_id: crate::id(),
352 accounts: vec![
353 AccountMeta::new(signer, true),
354 AccountMeta::new(TREASURY_ADDRESS, false),
355 ],
356 data: [
357 OreInstruction::UpdateDifficulty.to_vec(),
358 UpdateDifficultyArgs { new_difficulty }.to_bytes().to_vec(),
359 ]
360 .concat(),
361 }
362}