1use bytemuck::{Pod, Zeroable};
2use num_enum::TryFromPrimitive;
3use ore_api::consts::*;
4use ore_utils::{impl_instruction_from_bytes, impl_to_bytes};
5use solana_program::{
6 instruction::{AccountMeta, Instruction},
7 pubkey::Pubkey,
8 system_program, sysvar,
9};
10
11use crate::consts::*;
12
13#[repr(u8)]
14#[derive(Clone, Copy, Debug, Eq, PartialEq, TryFromPrimitive)]
15#[rustfmt::skip]
16pub enum RelayInstruction {
17 Claim = 0,
18 CloseEscrow = 1,
19 OpenEscrow = 2,
20 Stake = 3,
21 Migrate = 4,
22
23 Collect = 101,
24 UpdateMiner = 102,
25}
26
27#[repr(C)]
28#[derive(Clone, Copy, Debug, Pod, Zeroable)]
29pub struct ClaimArgs {
30 pub amount: [u8; 8],
31}
32
33#[repr(C)]
34#[derive(Clone, Copy, Debug, Pod, Zeroable)]
35pub struct CollectArgs {
36 pub fee: [u8; 8],
37}
38
39#[repr(C)]
40#[derive(Clone, Copy, Debug, Pod, Zeroable)]
41pub struct OpenEscrowArgs {
42 pub escrow_bump: u8,
43 pub proof_bump: u8,
44}
45
46#[repr(C)]
47#[derive(Clone, Copy, Debug, Pod, Zeroable)]
48pub struct MigrateArgs {
49 pub proof_bump: u8,
50}
51
52#[repr(C)]
53#[derive(Clone, Copy, Debug, Pod, Zeroable)]
54pub struct StakeArgs {
55 pub amount: [u8; 8],
56}
57
58impl RelayInstruction {
59 pub fn to_vec(&self) -> Vec<u8> {
60 vec![*self as u8]
61 }
62}
63
64impl_to_bytes!(ClaimArgs);
65impl_to_bytes!(CollectArgs);
66impl_to_bytes!(OpenEscrowArgs);
67impl_to_bytes!(MigrateArgs);
68impl_to_bytes!(StakeArgs);
69
70impl_instruction_from_bytes!(ClaimArgs);
71impl_instruction_from_bytes!(CollectArgs);
72impl_instruction_from_bytes!(OpenEscrowArgs);
73impl_instruction_from_bytes!(MigrateArgs);
74impl_instruction_from_bytes!(StakeArgs);
75
76pub fn collect(
78 signer: Pubkey,
79 escrow_authority: Pubkey,
80 beneficiary: Pubkey,
81 sol_fee: u64,
82) -> Instruction {
83 let (escrow_pda, _) =
84 Pubkey::find_program_address(&[ESCROW, escrow_authority.as_ref()], &crate::id());
85 let (proof_pda, _) =
86 Pubkey::find_program_address(&[PROOF, escrow_pda.as_ref()], &ore_api::id());
87 Instruction {
88 program_id: crate::id(),
89 accounts: vec![
90 AccountMeta::new(signer, true),
91 AccountMeta::new(beneficiary, false),
92 AccountMeta::new(escrow_pda, false),
93 AccountMeta::new(proof_pda, false),
94 AccountMeta::new_readonly(ore_api::consts::TREASURY_ADDRESS, false),
95 AccountMeta::new(ore_api::consts::TREASURY_TOKENS_ADDRESS, false),
96 AccountMeta::new_readonly(ore_api::id(), false),
97 AccountMeta::new_readonly(spl_token::id(), false),
98 ],
99 data: vec![
100 RelayInstruction::Collect.to_vec(),
101 CollectArgs {
102 fee: sol_fee.to_le_bytes(),
103 }
104 .to_bytes()
105 .to_vec(),
106 ]
107 .concat(),
108 }
109}
110
111pub fn claim(signer: Pubkey, beneficiary: Pubkey, amount: u64) -> Instruction {
113 let (escrow_pda, _) = Pubkey::find_program_address(&[ESCROW, signer.as_ref()], &crate::id());
114 let (proof_pda, _) =
115 Pubkey::find_program_address(&[PROOF, escrow_pda.as_ref()], &ore_api::id());
116 Instruction {
117 program_id: crate::id(),
118 accounts: vec![
119 AccountMeta::new(signer, true),
120 AccountMeta::new(beneficiary, false),
121 AccountMeta::new(escrow_pda, false),
122 AccountMeta::new(proof_pda, false),
123 AccountMeta::new_readonly(ore_api::consts::TREASURY_ADDRESS, false),
124 AccountMeta::new(ore_api::consts::TREASURY_TOKENS_ADDRESS, false),
125 AccountMeta::new_readonly(ore_api::id(), false),
126 AccountMeta::new_readonly(spl_token::id(), false),
127 ],
128 data: [
129 RelayInstruction::Claim.to_vec(),
130 ClaimArgs {
131 amount: amount.to_le_bytes(),
132 }
133 .to_bytes()
134 .to_vec(),
135 ]
136 .concat(),
137 }
138}
139
140pub fn stake(signer: Pubkey, sender: Pubkey, amount: u64) -> Instruction {
142 let (escrow_pda, _) = Pubkey::find_program_address(&[ESCROW, signer.as_ref()], &crate::id());
143 let escrow_tokens =
144 spl_associated_token_account::get_associated_token_address(&escrow_pda, &MINT_ADDRESS);
145 let (proof_pda, _) =
146 Pubkey::find_program_address(&[PROOF, escrow_pda.as_ref()], &ore_api::id());
147 Instruction {
148 program_id: crate::id(),
149 accounts: vec![
150 AccountMeta::new(signer, true),
151 AccountMeta::new(escrow_pda, false),
152 AccountMeta::new(escrow_tokens, false),
153 AccountMeta::new(proof_pda, false),
154 AccountMeta::new(sender, false),
155 AccountMeta::new(ore_api::consts::TREASURY_TOKENS_ADDRESS, false),
156 AccountMeta::new_readonly(ore_api::id(), false),
157 AccountMeta::new_readonly(spl_token::id(), false),
158 ],
159 data: [
160 RelayInstruction::Stake.to_vec(),
161 StakeArgs {
162 amount: amount.to_le_bytes(),
163 }
164 .to_bytes()
165 .to_vec(),
166 ]
167 .concat(),
168 }
169}
170
171pub fn open_escrow(signer: Pubkey, payer: Pubkey) -> Instruction {
173 let escrow_pda = Pubkey::find_program_address(&[ESCROW, signer.as_ref()], &crate::id());
174 let proof_pda = Pubkey::find_program_address(&[PROOF, escrow_pda.0.as_ref()], &ore_api::id());
175 let escrow_tokens_address =
176 spl_associated_token_account::get_associated_token_address(&escrow_pda.0, &MINT_ADDRESS);
177 Instruction {
178 program_id: crate::id(),
179 accounts: vec![
180 AccountMeta::new(signer, true),
181 AccountMeta::new_readonly(signer, false),
182 AccountMeta::new(payer, true),
183 AccountMeta::new(escrow_pda.0, false),
184 AccountMeta::new(escrow_tokens_address, false),
185 AccountMeta::new_readonly(MINT_ADDRESS, false),
186 AccountMeta::new(proof_pda.0, false),
187 AccountMeta::new_readonly(ore_api::id(), false),
188 AccountMeta::new_readonly(system_program::id(), false),
189 AccountMeta::new_readonly(spl_token::id(), false),
190 AccountMeta::new_readonly(spl_associated_token_account::id(), false),
191 AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
192 ],
193 data: [
194 RelayInstruction::OpenEscrow.to_vec(),
195 OpenEscrowArgs {
196 escrow_bump: escrow_pda.1,
197 proof_bump: proof_pda.1,
198 }
199 .to_bytes()
200 .to_vec(),
201 ]
202 .concat(),
203 }
204}
205
206pub fn update_miner(signer: Pubkey, miner: Pubkey) -> Instruction {
208 let escrow_pda = Pubkey::find_program_address(&[ESCROW, signer.as_ref()], &crate::id());
209 let proof_pda = Pubkey::find_program_address(&[PROOF, escrow_pda.0.as_ref()], &ore_api::id());
210 Instruction {
211 program_id: crate::id(),
212 accounts: vec![
213 AccountMeta::new(signer, true),
214 AccountMeta::new(escrow_pda.0, false),
215 AccountMeta::new_readonly(miner, false),
216 AccountMeta::new(proof_pda.0, false),
217 AccountMeta::new_readonly(ore_api::id(), false),
218 ],
219 data: RelayInstruction::UpdateMiner.to_vec(),
220 }
221}
222
223pub fn migrate(signer: Pubkey, payer: Pubkey, miner: Pubkey) -> Instruction {
226 let escrow_pda = Pubkey::find_program_address(&[ESCROW, signer.as_ref()], &crate::id());
227 let escrow_proof_pda =
228 Pubkey::find_program_address(&[PROOF, escrow_pda.0.as_ref()], &ore_api::id());
229 let escrow_tokens_address =
230 spl_associated_token_account::get_associated_token_address(&escrow_pda.0, &MINT_ADDRESS);
231 let proof_pda = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &ore_api::id());
232 let signer_tokens_address =
233 spl_associated_token_account::get_associated_token_address(&signer, &MINT_ADDRESS);
234 Instruction {
235 program_id: crate::id(),
236 accounts: vec![
237 AccountMeta::new(signer, true),
238 AccountMeta::new(signer_tokens_address, false),
239 AccountMeta::new_readonly(miner, false),
240 AccountMeta::new(payer, true),
241 AccountMeta::new(escrow_pda.0, false),
242 AccountMeta::new(escrow_proof_pda.0, false),
243 AccountMeta::new(escrow_tokens_address, false),
244 AccountMeta::new_readonly(MINT_ADDRESS, false),
245 AccountMeta::new(proof_pda.0, false),
246 AccountMeta::new_readonly(ore_api::consts::TREASURY_ADDRESS, false),
247 AccountMeta::new(ore_api::consts::TREASURY_TOKENS_ADDRESS, false),
248 AccountMeta::new_readonly(ore_api::id(), false),
249 AccountMeta::new_readonly(system_program::id(), false),
250 AccountMeta::new_readonly(spl_token::id(), false),
251 AccountMeta::new_readonly(spl_associated_token_account::id(), false),
252 AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
253 ],
254 data: [
255 RelayInstruction::Migrate.to_vec(),
256 MigrateArgs {
257 proof_bump: proof_pda.1,
258 }
259 .to_bytes()
260 .to_vec(),
261 ]
262 .concat(),
263 }
264}