Skip to main content

oil_api/
sdk.rs

1use solana_program::pubkey::Pubkey;
2use spl_associated_token_account::get_associated_token_address;
3use steel::*;
4
5use crate::{
6    consts::{AUCTION, BOARD, MINT_ADDRESS, SOL_MINT, TREASURY_ADDRESS},
7    instruction::{self, *},
8    state::*,
9};
10
11pub fn log(signer: Pubkey, msg: &[u8]) -> Instruction {
12    let mut data = Log {}.to_bytes();
13    data.extend_from_slice(msg);
14    Instruction {
15        program_id: crate::ID,
16        accounts: vec![AccountMeta::new(signer, true)],
17        data: data,
18    }
19}
20
21pub fn program_log(accounts: &[AccountInfo], msg: &[u8]) -> Result<(), ProgramError> {
22    // Derive Board PDA to use as signer for log instruction
23    let (board_address, _) = board_pda();
24    invoke_signed(&log(board_address, msg), accounts, &crate::ID, &[BOARD])
25}
26
27/// Log event for auction-based instructions (uses Auction PDA instead of Board)
28pub fn auction_program_log(accounts: &[AccountInfo], msg: &[u8]) -> Result<(), ProgramError> {
29    // Derive Auction PDA to use as signer for log instruction
30    let (auction_address, _) = auction_pda();
31    invoke_signed(&log(auction_address, msg), accounts, &crate::ID, &[AUCTION])
32}
33
34// let [signer_info, board_info, config_info, mint_info, treasury_info, treasury_tokens_info, system_program, token_program, associated_token_program] = accounts else {
35// pub fn initialize(
36//     signer: Pubkey,
37//     barrel_authority: Pubkey,
38//     fee_collector: Pubkey,
39//     swap_program: Pubkey,
40//     var_address: Pubkey,
41//     admin_fee: u64,
42// ) -> Instruction {
43//     let board_address = board_pda().0;
44//     let config_address = config_pda().0;
45//     let mint_address = MINT_ADDRESS;
46//     let treasury_address = TREASURY_ADDRESS;
47//     let treasury_tokens_address = treasury_tokens_address();
48//     Instruction {
49//         program_id: crate::ID,
50//         accounts: vec![
51//             AccountMeta::new(signer, true),
52//             AccountMeta::new(board_address, false),
53//             AccountMeta::new(config_address, false),
54//             AccountMeta::new(mint_address, false),
55//             AccountMeta::new(treasury_address, false),
56//             AccountMeta::new(treasury_tokens_address, false),
57//             AccountMeta::new_readonly(system_program::ID, false),
58//             AccountMeta::new_readonly(spl_token::ID, false),
59//             AccountMeta::new_readonly(spl_associated_token_account::ID, false),
60//         ],
61//         data: Initialize {
62//             barrel_authority: barrel_authority.to_bytes(),
63//             fee_collector: fee_collector.to_bytes(),
64//             swap_program: swap_program.to_bytes(),
65//             var_address: var_address.to_bytes(),
66//             admin_fee: admin_fee.to_le_bytes(),
67//         }
68//         .to_bytes(),
69//     }
70// }
71
72// let [signer_info, automation_info, executor_info, miner_info, system_program] = accounts else {
73
74/// Set up automation for a miner. If the miner doesn't exist yet, pass a referrer to set it.
75/// If a referrer is provided and the miner is new, the referral account must be included.
76pub fn automate(
77    signer: Pubkey,
78    authority: Pubkey,
79    amount: u64,
80    deposit: u64,
81    executor: Pubkey,
82    fee: u64,
83    mask: u64,
84    strategy: u8,
85    reload: bool,
86    referrer: Option<Pubkey>,
87    pooled: bool,
88    is_new_miner: bool,
89) -> Instruction {
90    let automation_address = automation_pda(authority).0;
91    let miner_address = miner_pda(authority).0;
92    let config_address = config_pda().0;
93    let referrer_pk = referrer.unwrap_or(Pubkey::default());
94    
95    let mut accounts = vec![
96            AccountMeta::new(signer, true), // 0: signer (payer)
97            AccountMeta::new(authority, false), // 1: authority (user's wallet)
98            AccountMeta::new(automation_address, false), // 2: automation
99            AccountMeta::new(executor, false), // 3: executor
100            AccountMeta::new(miner_address, false), // 4: miner
101            AccountMeta::new_readonly(system_program::ID, false), // 5: system_program
102            AccountMeta::new_readonly(crate::ID, false), // 6: oil_program
103            AccountMeta::new_readonly(config_address, false), // 7: config
104    ];
105    
106    // Token accounts (user_wrapped_sol, automation_wrapped_sol, token_program, program_signer (optional), payer (optional), mint, ata_program)
107    // These are added by the client, not here in the SDK
108    
109    // Add referral account if referrer is provided and miner is new (for incrementing total_referred)
110    if is_new_miner && referrer.is_some() && referrer_pk != Pubkey::default() {
111        let referral_address = referral_pda(referrer_pk).0;
112        accounts.push(AccountMeta::new(referral_address, false));
113    }
114    
115    Instruction {
116        program_id: crate::ID,
117        accounts,
118        data: Automate {
119            amount: amount.to_le_bytes(),
120            deposit: deposit.to_le_bytes(),
121            fee: fee.to_le_bytes(),
122            mask: mask.to_le_bytes(),
123            strategy: strategy as u8,
124            reload: (reload as u64).to_le_bytes(),
125            referrer: referrer_pk.to_bytes(),
126            pooled: pooled as u8,
127        }
128        .to_bytes(),
129    }
130}
131
132/// Claim SOL rewards with single-tier referral system.
133/// 
134/// If the miner has a referrer, 1.0% of the claim goes to the referrer.
135/// 
136/// Account structure:
137/// - Base: signer, miner, system_program
138/// - If miner has referrer (required): [miner_referrer, referral_referrer]
139pub fn claim_sol(
140    signer: Pubkey,
141    referrer_miner: Option<Pubkey>, // Referrer's miner PDA (if miner has referrer)
142    referrer_referral: Option<Pubkey>, // Referrer's referral PDA (if miner has referrer)
143) -> Instruction {
144    let miner_address = miner_pda(signer).0;
145    
146    let mut accounts = vec![
147        AccountMeta::new(signer, true),
148        AccountMeta::new(miner_address, false),
149        AccountMeta::new_readonly(system_program::ID, false),
150    ];
151    
152    // Add referrer accounts if provided (required if miner has referrer)
153    if let (Some(miner_pubkey), Some(referral_pubkey)) = (referrer_miner, referrer_referral) {
154        accounts.push(AccountMeta::new(miner_pubkey, false));
155        accounts.push(AccountMeta::new(referral_pubkey, false));
156    }
157    
158    Instruction {
159        program_id: crate::ID,
160        accounts,
161        data: ClaimSOL {}.to_bytes(),
162    }
163}
164
165// let [signer_info, miner_info, mint_info, recipient_info, treasury_info, treasury_tokens_info, system_program, token_program, associated_token_program] =
166
167/// Claim OIL rewards with single-tier referral system.
168/// 
169/// If the miner has a referrer, 1.0% of the claim goes to the referrer.
170/// 
171/// Account structure:
172/// - Base: signer, miner, mint, recipient, treasury, treasury_tokens, system_program, token_program, associated_token_program
173/// - If miner has referrer (required): [miner_referrer, referral_referrer, referral_referrer_oil_ata]
174pub fn claim_oil(
175    signer: Pubkey,
176    referrer_miner: Option<Pubkey>, // Referrer's miner PDA (if miner has referrer)
177    referrer_referral: Option<Pubkey>, // Referrer's referral PDA (if miner has referrer)
178    referrer_referral_oil_ata: Option<Pubkey>, // Referrer's referral OIL ATA (if miner has referrer)
179) -> Instruction {
180    let miner_address = miner_pda(signer).0;
181    let treasury_address = treasury_pda().0;
182    let treasury_tokens_address = get_associated_token_address(&treasury_address, &MINT_ADDRESS);
183    let recipient_address = get_associated_token_address(&signer, &MINT_ADDRESS);
184    
185    let mut accounts = vec![
186        AccountMeta::new(signer, true),
187        AccountMeta::new(miner_address, false),
188        AccountMeta::new(MINT_ADDRESS, false),
189        AccountMeta::new(recipient_address, false),
190        AccountMeta::new(treasury_address, false),
191        AccountMeta::new(treasury_tokens_address, false),
192        AccountMeta::new_readonly(system_program::ID, false),
193        AccountMeta::new_readonly(spl_token::ID, false),
194        AccountMeta::new_readonly(spl_associated_token_account::ID, false),
195    ];
196    
197    // Add referrer accounts if provided (required if miner has referrer)
198    if let (Some(miner_pubkey), Some(referral_pubkey), Some(oil_ata_pubkey)) = 
199        (referrer_miner, referrer_referral, referrer_referral_oil_ata) {
200        accounts.push(AccountMeta::new(miner_pubkey, false));
201        accounts.push(AccountMeta::new(referral_pubkey, false));
202        accounts.push(AccountMeta::new(oil_ata_pubkey, false));
203    }
204    
205    Instruction {
206        program_id: crate::ID,
207        accounts,
208        data: ClaimOIL {}.to_bytes(),
209    }
210}
211
212
213pub fn close(signer: Pubkey, round_id: u64, rent_payer: Pubkey) -> Instruction {
214    let board_address = board_pda().0;
215    let round_address = round_pda(round_id).0;
216    let treasury_address = TREASURY_ADDRESS;
217    Instruction {
218        program_id: crate::ID,
219        accounts: vec![
220            AccountMeta::new(signer, true),
221            AccountMeta::new(board_address, false),
222            AccountMeta::new(rent_payer, false),
223            AccountMeta::new(round_address, false),
224            AccountMeta::new(treasury_address, false),
225            AccountMeta::new_readonly(system_program::ID, false),
226        ],
227        data: Close {}.to_bytes(),
228    }
229}
230
231/// Deploy SOL to prospect on squares.
232/// 
233/// This function uses native SOL transfers and is used for:
234/// - Regular wallets (signer == authority)
235/// - Automations (bot-executed deploys, signer != authority, using native SOL from automation account balance)
236/// 
237/// Pass a referrer pubkey for new miners to set up referral.
238/// Set `pooled` to true to join the mining pool (rewards shared proportionally).
239pub fn deploy(
240    signer: Pubkey,
241    authority: Pubkey,
242    amount: u64,
243    round_id: u64,
244    squares: [bool; 25],
245    referrer: Option<Pubkey>,
246    pooled: bool,
247) -> Instruction {
248    let automation_address = automation_pda(authority).0;
249    let board_address = board_pda().0;
250    let miner_address = miner_pda(authority).0;
251    let round_address = round_pda(round_id).0;
252    let entropy_var_address = entropy_rng_api::state::var_pda(board_address, 0).0;
253
254    let mut mask: u32 = 0;
255    for (i, &square) in squares.iter().enumerate() {
256        if square {
257            mask |= 1 << i;
258        }
259    }
260    
261    let referrer_pubkey = referrer.unwrap_or(Pubkey::default());
262    let referrer_bytes = referrer_pubkey.to_bytes();
263
264    // Build accounts list - must match program structure:
265    // Oil accounts: base (11) + optional referral (1) = 11-12
266    // Entropy accounts: var + program = 2 (always exactly 2)
267    let mut accounts = vec![
268        AccountMeta::new(signer, true), // 0: signer
269        AccountMeta::new(authority, false), // 1: authority
270        AccountMeta::new(automation_address, false), // 2: automation
271        AccountMeta::new(board_address, false), // 3: board
272        AccountMeta::new(miner_address, false), // 4: miner
273        AccountMeta::new(round_address, false), // 5: round
274        AccountMeta::new_readonly(system_program::ID, false), // 6: system_program
275        AccountMeta::new_readonly(crate::ID, false), // 7: oil_program
276        AccountMeta::new_readonly(spl_token::ID, false), // 8: token_program
277        AccountMeta::new_readonly(SOL_MINT, false), // 9: mint (SOL_MINT)
278        AccountMeta::new_readonly(spl_associated_token_account::ID, false), // 10: associated_token_program
279    ];
280    
281    // Add referral account if referrer is provided (in oil_accounts)
282    if referrer_pubkey != Pubkey::default() {
283        let referral_address = referral_pda(referrer_pubkey).0;
284        accounts.push(AccountMeta::new(referral_address, false)); // referral (optional, in oil_accounts)
285    }
286    
287    // Entropy accounts (always exactly 2, come after all oil_accounts)
288    accounts.push(AccountMeta::new(entropy_var_address, false)); // entropy_var
289    accounts.push(AccountMeta::new_readonly(entropy_rng_api::ID, false)); // entropy_program
290
291    Instruction {
292        program_id: crate::ID,
293        accounts,
294        data: Deploy {
295            amount: amount.to_le_bytes(),
296            squares: mask.to_le_bytes(),
297            referrer: referrer_bytes,
298            pooled: if pooled { 1 } else { 0 },
299        }
300        .to_bytes(),
301    }
302}
303
304
305// let [pool, user_source_token, user_destination_token, a_vault, b_vault, a_token_vault, b_token_vault, a_vault_lp_mint, b_vault_lp_mint, a_vault_lp, b_vault_lp, protocol_token_fee, user_key, vault_program, token_program] =
306
307pub fn wrap(signer: Pubkey, use_liquidity: bool, amount: u64) -> Instruction {
308    let config_address = config_pda().0;
309    let treasury_address = TREASURY_ADDRESS;
310    let treasury_sol_address = get_associated_token_address(&treasury_address, &SOL_MINT);
311    let data = Wrap {
312        use_liquidity: if use_liquidity { 1 } else { 0 },
313        amount: amount.to_le_bytes(),
314    }
315    .to_bytes();
316    Instruction {
317        program_id: crate::ID,
318        accounts: vec![
319            AccountMeta::new(signer, true),
320            AccountMeta::new_readonly(config_address, false),
321            AccountMeta::new(treasury_address, false),
322            AccountMeta::new(treasury_sol_address, false),
323            AccountMeta::new_readonly(solana_program::system_program::ID, false),
324        ],
325        data,
326    }
327}
328
329pub fn buyback(signer: Pubkey, swap_accounts: &[AccountMeta], swap_data: &[u8]) -> Instruction {
330    let board_address = board_pda().0;
331    let mint_address = MINT_ADDRESS;
332    let treasury_address = TREASURY_ADDRESS;
333    let treasury_oil_address = get_associated_token_address(&treasury_address, &MINT_ADDRESS);
334    let treasury_sol_address = get_associated_token_address(&treasury_address, &SOL_MINT);
335    let mut accounts = vec![
336        AccountMeta::new(signer, true),
337        AccountMeta::new(board_address, false),
338        AccountMeta::new(mint_address, false),
339        AccountMeta::new(treasury_address, false),
340        AccountMeta::new(treasury_oil_address, false),
341        AccountMeta::new(treasury_sol_address, false),
342        AccountMeta::new_readonly(spl_token::ID, false),
343        AccountMeta::new_readonly(crate::ID, false),
344    ];
345    for account in swap_accounts.iter() {
346        let mut acc_clone = account.clone();
347        acc_clone.is_signer = false;
348        accounts.push(acc_clone);
349    }
350    let mut data = Buyback {}.to_bytes();
351    data.extend_from_slice(swap_data);
352    Instruction {
353        program_id: crate::ID,
354        accounts,
355        data,
356    }
357}
358
359pub fn barrel(signer: Pubkey, amount: u64) -> Instruction {
360    let board_address = board_pda().0;
361    let mint_address = MINT_ADDRESS;
362    let treasury_address = TREASURY_ADDRESS;
363    let sender_oil_address = get_associated_token_address(&signer, &MINT_ADDRESS);
364    let treasury_oil_address = get_associated_token_address(&treasury_address, &MINT_ADDRESS);
365    let data = Barrel {
366        amount: amount.to_le_bytes(),
367    }
368    .to_bytes();
369    Instruction {
370        program_id: crate::ID,
371        accounts: vec![
372            AccountMeta::new(signer, true),
373            AccountMeta::new(sender_oil_address, false),
374            AccountMeta::new(board_address, false),
375            AccountMeta::new(mint_address, false),
376            AccountMeta::new(treasury_address, false),
377            AccountMeta::new(treasury_oil_address, false),
378            AccountMeta::new_readonly(spl_token::ID, false),
379            AccountMeta::new_readonly(crate::ID, false),
380        ],
381        data,
382    }
383}
384
385
386// let [signer_info, board_info, config_info, fee_collector_info, mint_info, round_info, round_next_info, top_miner_info, treasury_info, treasury_tokens_info, system_program, token_program, oil_program, slot_hashes_sysvar] =
387
388pub fn reset(
389    signer: Pubkey,
390    fee_collector: Pubkey,
391    round_id: u64,
392    top_miner: Pubkey,
393    var_address: Pubkey,
394) -> Instruction {
395    reset_with_miners(signer, fee_collector, round_id, top_miner, var_address, &[])
396}
397
398pub fn reset_with_miners(
399    signer: Pubkey,
400    fee_collector: Pubkey,
401    round_id: u64,
402    top_miner: Pubkey,
403    var_address: Pubkey,
404    miner_accounts: &[Pubkey],
405) -> Instruction {
406    let board_address = board_pda().0;
407    let config_address = config_pda().0;
408    let mint_address = MINT_ADDRESS;
409    let round_address = round_pda(round_id).0;
410    let round_next_address = round_pda(round_id + 1).0;
411    let top_miner_address = miner_pda(top_miner).0;
412    let treasury_address = TREASURY_ADDRESS;
413    let treasury_tokens_address = treasury_tokens_address();
414    let pool_address = pool_pda().0;
415    let mint_authority_address = oil_mint_api::state::authority_pda().0;
416    let mut reset_instruction = Instruction {
417        program_id: crate::ID,
418        accounts: vec![
419            AccountMeta::new(signer, true),
420            AccountMeta::new(board_address, false),
421            AccountMeta::new(config_address, false),
422            AccountMeta::new(fee_collector, false),
423            AccountMeta::new(mint_address, false),
424            AccountMeta::new(round_address, false),
425            AccountMeta::new(round_next_address, false),
426            AccountMeta::new(top_miner_address, false),
427            AccountMeta::new(treasury_address, false),
428            AccountMeta::new(pool_address, false),
429            AccountMeta::new(treasury_tokens_address, false),
430            AccountMeta::new_readonly(system_program::ID, false),
431            AccountMeta::new_readonly(spl_token::ID, false),
432            AccountMeta::new_readonly(crate::ID, false),
433            AccountMeta::new_readonly(sysvar::slot_hashes::ID, false),
434            AccountMeta::new_readonly(SOL_MINT, false),
435            // Entropy accounts (these are in "other_accounts" after the split)
436            AccountMeta::new(var_address, false),
437            AccountMeta::new_readonly(entropy_rng_api::ID, false),
438            // Mint accounts.
439            AccountMeta::new(mint_authority_address, false),
440            AccountMeta::new_readonly(oil_mint_api::ID, false),
441        ],
442        data: Reset {}.to_bytes(),
443    };
444    
445    // Add miner accounts for seeker rewards (optional)
446    for miner_pubkey in miner_accounts {
447        reset_instruction.accounts.push(AccountMeta::new(
448            miner_pda(*miner_pubkey).0,
449            false,
450        ));
451    }
452    
453    reset_instruction
454}
455    
456// let [signer_info, automation_info, board_info, miner_info, round_info, treasury_info, system_program] =
457
458pub fn checkpoint(signer: Pubkey, authority: Pubkey, round_id: u64) -> Instruction {
459    let miner_address = miner_pda(authority).0;
460    let board_address = board_pda().0;
461    let config_address = config_pda().0;
462    let round_address = round_pda(round_id).0;
463    let treasury_address = TREASURY_ADDRESS;
464    Instruction {
465        program_id: crate::ID,
466        accounts: vec![
467            AccountMeta::new(signer, true), // payer (session payer or regular wallet, receives bot fee)
468            AccountMeta::new(authority, false), // authority (user's wallet, for PDA derivation - must be writable when combined with deploy)
469            AccountMeta::new(board_address, false),
470            AccountMeta::new(config_address, false), // config (needed for premine check)
471            AccountMeta::new(miner_address, false),
472            AccountMeta::new(round_address, false),
473            AccountMeta::new(treasury_address, false),
474            AccountMeta::new_readonly(system_program::ID, false),
475        ],
476        data: Checkpoint {}.to_bytes(),
477    }
478}
479
480pub fn set_admin(signer: Pubkey, admin: Pubkey) -> Instruction {
481    let config_address = config_pda().0;
482    Instruction {
483        program_id: crate::ID,
484        accounts: vec![
485            AccountMeta::new(signer, true),
486            AccountMeta::new(config_address, false),
487            AccountMeta::new_readonly(system_program::ID, false),
488        ],
489        data: SetAdmin {
490            admin: admin.to_bytes(),
491        }
492        .to_bytes(),
493    }
494}
495
496pub fn set_admin_fee(signer: Pubkey, admin_fee: u64) -> Instruction {
497    let config_address = config_pda().0;
498    Instruction {
499        program_id: crate::ID,
500        accounts: vec![
501            AccountMeta::new(signer, true),
502            AccountMeta::new(config_address, false),
503            AccountMeta::new_readonly(system_program::ID, false),
504        ],
505        data: SetAdminFee {
506            admin_fee: admin_fee.to_le_bytes(),
507        }
508        .to_bytes(),
509    }
510}
511
512pub fn set_fee_collector(signer: Pubkey, fee_collector: Pubkey) -> Instruction {
513    let config_address = config_pda().0;
514    Instruction {
515        program_id: crate::ID,
516        accounts: vec![
517            AccountMeta::new(signer, true),
518            AccountMeta::new(config_address, false),
519            AccountMeta::new_readonly(system_program::ID, false),
520        ],
521        data: SetFeeCollector {
522            fee_collector: fee_collector.to_bytes(),
523        }
524        .to_bytes(),
525    }
526}
527
528/// Sets the TGE (Token Generation Event) timestamp.
529/// If current time < tge_timestamp, pre-mine is active.
530/// Set to 0 to disable pre-mine.
531/// Admin-only instruction.
532pub fn set_tge_timestamp(signer: Pubkey, tge_timestamp: i64) -> Instruction {
533    let config_address = config_pda().0;
534    Instruction {
535        program_id: crate::ID,
536        accounts: vec![
537            AccountMeta::new(signer, true),
538            AccountMeta::new(config_address, false),
539            AccountMeta::new_readonly(system_program::ID, false),
540        ],
541        data: SetTgeTimestamp {
542            tge_timestamp: tge_timestamp.to_le_bytes(),
543        }
544        .to_bytes(),
545    }
546}
547
548pub fn set_auction(
549    signer: Pubkey,
550    halving_period_seconds: u64,
551    last_halving_time: u64,
552    base_mining_rates: [u64; 4],
553    auction_duration_seconds: u64,
554    starting_prices: [u64; 4],
555    _well_id: u64, // Kept for backwards compatibility, but not used (always updates auction only)
556) -> Instruction {
557    let config_address = config_pda().0;
558    let auction_address = auction_pda().0;
559    
560    Instruction {
561        program_id: crate::ID,
562        accounts: vec![
563            AccountMeta::new(signer, true),
564            AccountMeta::new_readonly(config_address, false),
565            AccountMeta::new(auction_address, false),
566        ],
567        data: SetAuction {
568            halving_period_seconds: halving_period_seconds.to_le_bytes(),
569            last_halving_time: last_halving_time.to_le_bytes(),
570            base_mining_rates: [
571                base_mining_rates[0].to_le_bytes(),
572                base_mining_rates[1].to_le_bytes(),
573                base_mining_rates[2].to_le_bytes(),
574                base_mining_rates[3].to_le_bytes(),
575            ],
576            auction_duration_seconds: auction_duration_seconds.to_le_bytes(),
577            starting_prices: [
578                starting_prices[0].to_le_bytes(),
579                starting_prices[1].to_le_bytes(),
580                starting_prices[2].to_le_bytes(),
581                starting_prices[3].to_le_bytes(),
582            ],
583            well_id: 4u64.to_le_bytes(), // Always use 4 to indicate auction-only update
584        }
585        .to_bytes(),
586    }
587}
588
589// let [signer_info, mint_info, sender_info, stake_info, stake_tokens_info, treasury_info, system_program, token_program, associated_token_program] =
590
591pub fn deposit(signer: Pubkey, authority: Pubkey, amount: u64, lock_duration_days: u64, stake_id: u64) -> Instruction {
592    let mint_address = MINT_ADDRESS;
593    let stake_address = stake_pda_with_id(authority, stake_id).0; // Derive from authority, not signer
594    let stake_tokens_address = get_associated_token_address(&stake_address, &MINT_ADDRESS);
595    let sender_address = get_associated_token_address(&authority, &MINT_ADDRESS); // Authority's ATA
596    let pool_address = pool_pda().0;
597    let pool_tokens_address = pool_tokens_address();
598    let miner_address = miner_pda(authority).0; // Derive from authority
599    Instruction {
600        program_id: crate::ID,
601        accounts: vec![
602            AccountMeta::new(signer, true), // payer (session payer or regular wallet, pays fees)
603            AccountMeta::new(authority, true), // authority (user's wallet, signs token transfer and used for PDA derivation)
604            AccountMeta::new(mint_address, false),
605            AccountMeta::new(sender_address, false),
606            AccountMeta::new(stake_address, false),
607            AccountMeta::new(stake_tokens_address, false),
608            AccountMeta::new(pool_address, false),
609            AccountMeta::new(pool_tokens_address, false),
610            AccountMeta::new(miner_address, false),
611            AccountMeta::new_readonly(system_program::ID, false),
612            AccountMeta::new_readonly(spl_token::ID, false),
613            AccountMeta::new_readonly(spl_associated_token_account::ID, false),
614        ],
615        data: Deposit {
616            amount: amount.to_le_bytes(),
617            lock_duration_days: lock_duration_days.to_le_bytes(),
618            stake_id: stake_id.to_le_bytes(),
619        }
620        .to_bytes(),
621    }
622}
623
624// let [signer_info, mint_info, recipient_info, stake_info, stake_tokens_info, treasury_info, system_program, token_program, associated_token_program] =
625
626pub fn withdraw(signer: Pubkey, authority: Pubkey, amount: u64, stake_id: u64) -> Instruction {
627    let stake_address = stake_pda_with_id(authority, stake_id).0; // Derive from authority, not signer
628    let stake_tokens_address = get_associated_token_address(&stake_address, &MINT_ADDRESS);
629    let mint_address = MINT_ADDRESS;
630    let recipient_address = get_associated_token_address(&authority, &MINT_ADDRESS); // Authority's ATA
631    let pool_address = pool_pda().0;
632    let pool_tokens_address = pool_tokens_address();
633    let miner_address = miner_pda(authority).0; // Derive from authority
634    let treasury_address = treasury_pda().0;
635    let treasury_tokens_address = treasury_tokens_address();
636    Instruction {
637        program_id: crate::ID,
638        accounts: vec![
639            AccountMeta::new(signer, true), // payer (session payer or regular wallet)
640            AccountMeta::new(authority, false), // authority (user's wallet, for PDA derivation)
641            AccountMeta::new(mint_address, false),
642            AccountMeta::new(recipient_address, false),
643            AccountMeta::new(stake_address, false),
644            AccountMeta::new(stake_tokens_address, false),
645            AccountMeta::new(pool_address, false),
646            AccountMeta::new(pool_tokens_address, false),
647            AccountMeta::new(miner_address, false),
648            AccountMeta::new(treasury_address, false), // Treasury account (writable, signed by PDA)
649            AccountMeta::new(treasury_tokens_address, false), // Treasury OIL token account (writable, signed by PDA)
650            AccountMeta::new_readonly(system_program::ID, false),
651            AccountMeta::new_readonly(spl_token::ID, false),
652            AccountMeta::new_readonly(spl_associated_token_account::ID, false),
653        ],
654        data: Withdraw {
655            amount: amount.to_le_bytes(),
656            stake_id: stake_id.to_le_bytes(),
657        }
658        .to_bytes(),
659    }
660}
661
662// let [signer_info, automation_info, miner_info, system_program] = accounts else {
663
664/// Reload SOL from miner account to automation balance with single-tier referral system.
665/// 
666/// If the miner has a referrer, 1.0% of the claim goes to the referrer.
667/// 
668/// Account structure:
669/// - Base: signer, automation, miner, system_program
670/// - If miner has referrer (required): [miner_referrer, referral_referrer]
671pub fn reload_sol(
672    signer: Pubkey,
673    authority: Pubkey,
674    referrer_miner: Option<Pubkey>,
675    referrer_referral: Option<Pubkey>,
676) -> Instruction {
677    let automation_address = automation_pda(authority).0;
678    let miner_address = miner_pda(authority).0;
679    
680    let mut accounts = vec![
681        AccountMeta::new(signer, true),
682        AccountMeta::new(automation_address, false),
683        AccountMeta::new(miner_address, false),
684        AccountMeta::new_readonly(system_program::ID, false),
685    ];
686    
687    // Add referral accounts if provided (required when miner has referrer)
688    if let (Some(miner_ref), Some(referral_ref)) = (referrer_miner, referrer_referral) {
689        accounts.push(AccountMeta::new(miner_ref, false));
690        accounts.push(AccountMeta::new(referral_ref, false));
691    }
692    
693    Instruction {
694        program_id: crate::ID,
695        accounts,
696        data: ReloadSOL {}.to_bytes(),
697    }
698}
699
700// let [signer_info, mint_info, recipient_info, stake_info, treasury_info, treasury_tokens_info, system_program, token_program, associated_token_program] =
701
702/// Claim SOL yield from staking. Stakers earn SOL rewards (2% of round winnings), not OIL.
703pub fn claim_yield(signer: Pubkey, amount: u64, stake_id: u64) -> Instruction {
704    let stake_address = stake_pda_with_id(signer, stake_id).0;
705    let pool_address = pool_pda().0;
706    Instruction {
707        program_id: crate::ID,
708        accounts: vec![
709            AccountMeta::new(signer, true), // signer and writable for receiving SOL
710            AccountMeta::new(stake_address, false),
711            AccountMeta::new(pool_address, false),
712            AccountMeta::new_readonly(system_program::ID, false),
713        ],
714        data: ClaimYield {
715            amount: amount.to_le_bytes(),
716        }
717        .to_bytes(),
718    }
719}
720
721pub fn new_var(
722    signer: Pubkey,
723    provider: Pubkey,
724    id: u64,
725    commit: [u8; 32],
726    samples: u64,
727) -> Instruction {
728    let board_address = board_pda().0;
729    let config_address = config_pda().0;
730    let var_address = entropy_rng_api::state::var_pda(board_address, id).0;
731    Instruction {
732        program_id: crate::ID,
733        accounts: vec![
734            AccountMeta::new(signer, true),
735            AccountMeta::new(board_address, false),
736            AccountMeta::new(config_address, false),
737            AccountMeta::new(provider, false),
738            AccountMeta::new(var_address, false),
739            AccountMeta::new_readonly(system_program::ID, false),
740            AccountMeta::new_readonly(entropy_rng_api::ID, false),
741        ],
742        data: NewVar {
743            id: id.to_le_bytes(),
744            commit: commit,
745            samples: samples.to_le_bytes(),
746        }
747        .to_bytes(),
748    }
749}
750
751pub fn set_swap_program(signer: Pubkey, new_program: Pubkey) -> Instruction {
752    let config_address = config_pda().0;
753    Instruction {
754        program_id: crate::ID,
755        accounts: vec![
756            AccountMeta::new(signer, true),
757            AccountMeta::new(config_address, false),
758            AccountMeta::new_readonly(new_program, false),
759        ],
760        data: SetSwapProgram {}.to_bytes(),
761    }
762}
763
764pub fn set_var_address(signer: Pubkey, new_var_address: Pubkey) -> Instruction {
765    let board_address = board_pda().0;
766    let config_address = config_pda().0;
767    Instruction {
768        program_id: crate::ID,
769        accounts: vec![
770            AccountMeta::new(signer, true),
771            AccountMeta::new(board_address, false),
772            AccountMeta::new(config_address, false),
773            AccountMeta::new(new_var_address, false),
774        ],
775        data: SetVarAddress {}.to_bytes(),
776    }
777}
778
779/// Migrate: Extend Treasury struct with liquidity field.
780/// This migration ensures the Treasury account has the new liquidity field available.
781/// Must be called by the admin.
782/// Accounts: signer, config, treasury, system_program
783pub fn migrate(signer: Pubkey) -> Instruction {
784    let config_address = config_pda().0;
785    let treasury_address = treasury_pda().0;
786    Instruction {
787        program_id: crate::ID,
788        accounts: vec![
789            AccountMeta::new(signer, true),
790            AccountMeta::new(config_address, false),
791            AccountMeta::new(treasury_address, false),
792            AccountMeta::new_readonly(system_program::ID, false),
793        ],
794        data: Migrate {}.to_bytes(),
795    }
796}
797
798/// Create a referral account to become a referrer.
799pub fn create_referral(signer: Pubkey) -> Instruction {
800    let referral_address = referral_pda(signer).0;
801    Instruction {
802        program_id: crate::ID,
803        accounts: vec![
804            AccountMeta::new(signer, true),
805            AccountMeta::new(referral_address, false),
806            AccountMeta::new_readonly(system_program::ID, false),
807        ],
808        data: CreateReferral {}.to_bytes(),
809    }
810}
811
812/// Creates a Whitelist account for a shared access code.
813/// Admin-only instruction.
814/// Accounts: signer (admin), config, whitelist, system_program
815pub fn create_whitelist(
816    signer: Pubkey,
817    code_hash: [u8; 32],
818) -> Instruction {
819    let config_address = config_pda().0;
820    let (whitelist_address, _) = Whitelist::pda(code_hash);
821    Instruction {
822        program_id: crate::ID,
823        accounts: vec![
824            AccountMeta::new(signer, true), // signer (admin)
825            AccountMeta::new_readonly(config_address, false), // config
826            AccountMeta::new(whitelist_address, false), // whitelist
827            AccountMeta::new_readonly(system_program::ID, false), // system_program
828        ],
829        data: CreateWhitelist {
830            code_hash,
831        }
832        .to_bytes(),
833    }
834}
835
836/// Claim pending referral rewards (both SOL and OIL).
837/// 
838/// Account structure (for Fogo sessions):
839/// - Base: signer (payer), authority (user's wallet), referral, referral_tokens, mint, recipient, system_program, token_program, associated_token_program
840pub fn claim_referral(signer: Pubkey, authority: Pubkey) -> Instruction {
841    let referral_address = referral_pda(authority).0;
842    let referral_oil_address = get_associated_token_address(&referral_address, &MINT_ADDRESS);
843    let recipient_oil_address = get_associated_token_address(&authority, &MINT_ADDRESS);
844    Instruction {
845        program_id: crate::ID,
846        accounts: vec![
847            AccountMeta::new(signer, true), // 0: signer (payer)
848            AccountMeta::new(authority, false), // 1: authority (user's wallet, receives SOL)
849            AccountMeta::new(referral_address, false), // 2: referral
850            AccountMeta::new(referral_oil_address, false), // 3: referral_tokens (Referral account's OIL ATA)
851            AccountMeta::new(MINT_ADDRESS, false), // 4: mint
852            AccountMeta::new(recipient_oil_address, false), // 5: recipient (Recipient's OIL ATA - authority's wallet)
853            AccountMeta::new_readonly(system_program::ID, false), // 6: system_program
854            AccountMeta::new_readonly(spl_token::ID, false), // 7: token_program
855            AccountMeta::new_readonly(spl_associated_token_account::ID, false), // 8: associated_token_program
856        ],
857        data: ClaimReferral {}.to_bytes(),
858    }
859}
860
861/// Direct solo bid on an auction well (seize ownership).
862/// The bid amount is calculated on-chain as current_price + 1 lamport.
863/// User must have enough SOL in their wallet to cover the bid.
864/// 
865/// Account structure:
866/// - Base: signer, authority, program_signer (optional), payer (optional), well, auction, treasury, treasury_tokens, mint, mint_authority, mint_program, staking_pool, fee_collector, config, token_program, system_program, oil_program
867/// - If previous owner exists (optional): [previous_owner_miner, previous_owner]
868/// - If referrer is provided (optional): [referral]
869pub fn place_bid(
870    signer: Pubkey,
871    authority: Pubkey,
872    square_id: u64,
873    fee_collector: Pubkey,
874    previous_owner_miner: Option<Pubkey>, // Previous owner's miner PDA (if previous owner exists)
875    previous_owner: Option<Pubkey>, // Previous owner pubkey (if previous owner exists)
876    referrer: Option<Pubkey>, // Optional referrer pubkey for new miners
877) -> Instruction {
878    let well_address = well_pda(square_id).0;
879    let auction_address = auction_pda().0;
880    let treasury_address = treasury_pda().0;
881    let treasury_tokens_address = get_associated_token_address(&treasury_address, &MINT_ADDRESS);
882    let staking_pool_address = pool_pda().0;
883    let config_address = config_pda().0;
884    let mint_authority_address = oil_mint_api::state::authority_pda().0;
885    let bidder_miner_address = miner_pda(authority).0;
886    
887    let mut accounts = vec![
888        AccountMeta::new(signer, true), // 0: signer
889        AccountMeta::new(authority, false), // 1: authority
890    ];
891    
892    // Add program_signer and payer for Fogo sessions (these are added by the client, not here)
893    // For now, we'll add placeholders or the client will add them
894    
895    accounts.extend_from_slice(&[
896        AccountMeta::new(well_address, false), // well
897        AccountMeta::new(auction_address, false), // Must be writable for auction_program_log CPI
898        AccountMeta::new(treasury_address, false),
899        AccountMeta::new(treasury_tokens_address, false),
900        AccountMeta::new(MINT_ADDRESS, false),
901        AccountMeta::new(mint_authority_address, false),
902        AccountMeta::new_readonly(oil_mint_api::ID, false),
903        AccountMeta::new(staking_pool_address, false),
904        AccountMeta::new(fee_collector, false),
905        AccountMeta::new_readonly(config_address, false),
906        AccountMeta::new_readonly(spl_token::ID, false),
907        AccountMeta::new_readonly(system_program::ID, false),
908        AccountMeta::new_readonly(crate::ID, false), // oil_program
909        AccountMeta::new(bidder_miner_address, false), // bidder_miner
910    ]);
911    
912    // Add previous owner accounts if provided
913    if let (Some(miner_pubkey), Some(owner_pubkey)) = (previous_owner_miner, previous_owner) {
914        accounts.push(AccountMeta::new(miner_pubkey, false)); // previous_owner_miner
915        accounts.push(AccountMeta::new(owner_pubkey, false)); // previous_owner
916    }
917    
918    // Add referral account if referrer is provided
919    if let Some(referrer_pubkey) = referrer {
920        let referral_address = referral_pda(referrer_pubkey).0;
921        accounts.push(AccountMeta::new(referral_address, false)); // referral
922    }
923    
924    // Note: Wrapped token accounts are added by the client:
925    // - user_wrapped_sol (source)
926    // - treasury_wrapped_sol (temp ATA for all wrapped SOL - will be closed to get native SOL)
927    // - token_program, native_mint, ata_program
928    // The program distributes native SOL from treasury to pool and fee_collector after closing the temp ATA.
929    
930    Instruction {
931        program_id: crate::ID,
932        accounts,
933        data: instruction::PlaceBid {
934            square_id: square_id.to_le_bytes(),
935            referrer: referrer.unwrap_or(Pubkey::default()).to_bytes(),
936        }
937        .to_bytes(),
938    }
939}
940
941/// Claim auction-based OIL rewards
942/// - OIL rewards: from current ownership and previous ownership (pre-minted)
943/// 
944/// Account structure:
945/// - Base: signer, miner, well accounts (one per well in mask), auction pool accounts (optional, one per well), auction, treasury, treasury_tokens, mint, mint_authority, mint_program, recipient, token_program, associated_token_program, system_program, oil_program
946/// - Bid accounts (one per well in mask, required for pool contributors): [bid_0, bid_1, bid_2, bid_3] (must include epoch_id in PDA)
947/// Claim auction-based OIL rewards
948/// 
949/// Account structure:
950/// - Base: signer, miner, well_0, well_1, well_2, well_3, auction, treasury, treasury_tokens, mint, mint_authority, mint_program, recipient, token_program, associated_token_program, system_program, oil_program
951/// - If miner has referrer (required): [miner_referrer, referral_referrer, referral_referrer_oil_ata]
952pub fn claim_auction_oil(
953    signer: Pubkey,
954    well_mask: u8, // Bitmask: bit 0 = well 0, bit 1 = well 1, etc.
955    referrer_miner: Option<Pubkey>, // Referrer's miner PDA (if miner has referrer)
956    referrer_referral: Option<Pubkey>, // Referrer's referral PDA (if miner has referrer)
957    referrer_referral_oil_ata: Option<Pubkey>, // Referrer's referral OIL ATA (if miner has referrer)
958) -> Instruction {
959    let miner_address = miner_pda(signer).0;
960    let well_0_address = well_pda(0).0;
961    let well_1_address = well_pda(1).0;
962    let well_2_address = well_pda(2).0;
963    let well_3_address = well_pda(3).0;
964    let auction_address = auction_pda().0;
965    let treasury_address = treasury_pda().0;
966    let treasury_tokens_address = get_associated_token_address(&treasury_address, &MINT_ADDRESS);
967    let recipient_address = get_associated_token_address(&signer, &MINT_ADDRESS);
968    let mint_authority_address = oil_mint_api::state::authority_pda().0;
969    
970    let mut accounts = vec![
971        AccountMeta::new(signer, true),
972        AccountMeta::new(miner_address, false),
973        AccountMeta::new(well_0_address, false),
974        AccountMeta::new(well_1_address, false),
975        AccountMeta::new(well_2_address, false),
976        AccountMeta::new(well_3_address, false),
977        AccountMeta::new(auction_address, false),
978        AccountMeta::new(treasury_address, false),
979        AccountMeta::new(treasury_tokens_address, false),
980        AccountMeta::new(MINT_ADDRESS, false),
981        AccountMeta::new(mint_authority_address, false),
982        AccountMeta::new_readonly(oil_mint_api::ID, false),
983        AccountMeta::new(recipient_address, false),
984        AccountMeta::new_readonly(spl_token::ID, false),
985        AccountMeta::new_readonly(spl_associated_token_account::ID, false),
986        AccountMeta::new_readonly(system_program::ID, false),
987        AccountMeta::new_readonly(crate::ID, false),
988    ];
989    
990    // Add referrer accounts if provided (required if miner has referrer)
991    if let (Some(miner_pubkey), Some(referral_pubkey), Some(oil_ata_pubkey)) = 
992        (referrer_miner, referrer_referral, referrer_referral_oil_ata) {
993        accounts.push(AccountMeta::new(miner_pubkey, false));
994        accounts.push(AccountMeta::new(referral_pubkey, false));
995        accounts.push(AccountMeta::new(oil_ata_pubkey, false));
996    }
997    
998    Instruction {
999        program_id: crate::ID,
1000        accounts,
1001        data: ClaimAuctionOIL {
1002            well_mask,
1003        }
1004        .to_bytes(),
1005    }
1006}
1007
1008/// Claim auction-based SOL rewards
1009/// 
1010/// Account structure:
1011/// - Base: signer (writable), miner, treasury, auction, system_program, oil_program
1012/// - If miner has referrer (required): [miner_referrer, referral_referrer]
1013pub fn claim_auction_sol(
1014    signer: Pubkey,
1015    referrer_miner: Option<Pubkey>, // Referrer's miner PDA (if miner has referrer)
1016    referrer_referral: Option<Pubkey>, // Referrer's referral PDA (if miner has referrer)
1017) -> Instruction {
1018    let miner_address = miner_pda(signer).0;
1019    let (auction_address, _) = auction_pda();
1020    let treasury_address = treasury_pda().0;
1021    
1022    let mut accounts = vec![
1023        AccountMeta::new(signer, true), // signer and writable for receiving SOL
1024        AccountMeta::new(miner_address, false),
1025        AccountMeta::new(treasury_address, false),
1026        AccountMeta::new(auction_address, false),
1027        AccountMeta::new_readonly(system_program::ID, false),
1028        AccountMeta::new_readonly(crate::ID, false),
1029    ];
1030    
1031    // Add referrer accounts if provided (required if miner has referrer)
1032    if let (Some(miner_pubkey), Some(referral_pubkey)) = (referrer_miner, referrer_referral) {
1033        accounts.push(AccountMeta::new(miner_pubkey, false));
1034        accounts.push(AccountMeta::new(referral_pubkey, false));
1035    }
1036    
1037    Instruction {
1038        program_id: crate::ID,
1039        accounts,
1040        data: ClaimAuctionSOL {
1041            _reserved: 0,
1042        }
1043        .to_bytes(),
1044    }
1045}
1046
1047// ============================================================================
1048// FOGO Session SDK Functions
1049// ============================================================================
1050
1051pub fn deploy_with_session(
1052    signer: Pubkey,
1053    authority: Pubkey,
1054    program_signer: Pubkey,
1055    payer: Pubkey,
1056    amount: u64,
1057    round_id: u64,
1058    squares: [bool; 25],
1059    referrer: Option<Pubkey>,
1060    pooled: bool,
1061) -> Instruction {
1062    let automation_address = automation_pda(authority).0;
1063    let board_address = board_pda().0;
1064    let miner_address = miner_pda(authority).0;
1065    let round_address = round_pda(round_id).0;
1066    let entropy_var_address = entropy_rng_api::state::var_pda(board_address, 0).0;
1067
1068    let mut mask: u32 = 0;
1069    for (i, &square) in squares.iter().enumerate() {
1070        if square {
1071            mask |= 1 << i;
1072        }
1073    }
1074    
1075    let referrer_pubkey = referrer.unwrap_or(Pubkey::default());
1076    let user_wrapped_sol_ata = get_associated_token_address(&authority, &SOL_MINT);
1077    let round_wrapped_sol_ata = get_associated_token_address(&round_address, &SOL_MINT);
1078
1079    let mut accounts = vec![
1080        AccountMeta::new(signer, true),
1081        AccountMeta::new(authority, false),
1082        AccountMeta::new_readonly(program_signer, false),
1083        AccountMeta::new(payer, false),
1084        AccountMeta::new(automation_address, false),
1085        AccountMeta::new(board_address, false),
1086        AccountMeta::new(miner_address, false),
1087        AccountMeta::new(round_address, false),
1088        AccountMeta::new_readonly(system_program::ID, false),
1089        AccountMeta::new_readonly(crate::ID, false),
1090        AccountMeta::new(user_wrapped_sol_ata, false),
1091        AccountMeta::new(round_wrapped_sol_ata, false),
1092        AccountMeta::new_readonly(spl_token::ID, false),
1093        AccountMeta::new_readonly(SOL_MINT, false),
1094        AccountMeta::new_readonly(spl_associated_token_account::ID, false),
1095    ];
1096    
1097    if referrer_pubkey != Pubkey::default() {
1098        let referral_address = referral_pda(referrer_pubkey).0;
1099        accounts.push(AccountMeta::new(referral_address, false));
1100    }
1101    
1102    accounts.push(AccountMeta::new(entropy_var_address, false));
1103    accounts.push(AccountMeta::new_readonly(entropy_rng_api::ID, false));
1104
1105    Instruction {
1106        program_id: crate::ID,
1107        accounts,
1108        data: Deploy {
1109            amount: amount.to_le_bytes(),
1110            squares: mask.to_le_bytes(),
1111            referrer: referrer_pubkey.to_bytes(),
1112            pooled: if pooled { 1 } else { 0 },
1113        }
1114        .to_bytes(),
1115    }
1116}
1117
1118pub fn automate_with_session(
1119    signer: Pubkey,
1120    authority: Pubkey,
1121    program_signer: Pubkey,
1122    payer: Pubkey,
1123    amount: u64,
1124    deposit: u64,
1125    executor: Pubkey,
1126    fee: u64,
1127    mask: u64,
1128    strategy: u8,
1129    reload: bool,
1130    referrer: Option<Pubkey>,
1131    pooled: bool,
1132    is_new_miner: bool,
1133) -> Instruction {
1134    let automation_address = automation_pda(authority).0;
1135    let miner_address = miner_pda(authority).0;
1136    let referrer_pk = referrer.unwrap_or(Pubkey::default());
1137    let user_wrapped_sol_ata = get_associated_token_address(&authority, &SOL_MINT);
1138    let automation_wrapped_sol_ata = get_associated_token_address(&automation_address, &SOL_MINT);
1139    
1140    let mut accounts = vec![
1141        AccountMeta::new(signer, true),
1142        AccountMeta::new(authority, false),
1143        AccountMeta::new_readonly(program_signer, false),
1144        AccountMeta::new(payer, false),
1145        AccountMeta::new(automation_address, false),
1146        AccountMeta::new(executor, false),
1147        AccountMeta::new(miner_address, false),
1148        AccountMeta::new_readonly(system_program::ID, false),
1149        AccountMeta::new_readonly(crate::ID, false),
1150        AccountMeta::new(user_wrapped_sol_ata, false),
1151        AccountMeta::new(automation_wrapped_sol_ata, false),
1152        AccountMeta::new_readonly(spl_token::ID, false),
1153        AccountMeta::new_readonly(SOL_MINT, false),
1154        AccountMeta::new_readonly(spl_associated_token_account::ID, false),
1155    ];
1156    
1157    if is_new_miner && referrer.is_some() && referrer_pk != Pubkey::default() {
1158        let referral_address = referral_pda(referrer_pk).0;
1159        accounts.push(AccountMeta::new(referral_address, false));
1160    }
1161    
1162    Instruction {
1163        program_id: crate::ID,
1164        accounts,
1165        data: Automate {
1166            amount: amount.to_le_bytes(),
1167            deposit: deposit.to_le_bytes(),
1168            fee: fee.to_le_bytes(),
1169            mask: mask.to_le_bytes(),
1170            strategy: strategy as u8,
1171            reload: (reload as u64).to_le_bytes(),
1172            referrer: referrer_pk.to_bytes(),
1173            pooled: pooled as u8,
1174        }
1175        .to_bytes(),
1176    }
1177}
1178
1179pub fn place_bid_with_session(
1180    signer: Pubkey,
1181    authority: Pubkey,
1182    program_signer: Pubkey,
1183    payer: Pubkey,
1184    square_id: u64,
1185    fee_collector: Pubkey,
1186    previous_owner_miner: Option<Pubkey>,
1187    previous_owner: Option<Pubkey>,
1188    referrer: Option<Pubkey>,
1189) -> Instruction {
1190    let well_address = well_pda(square_id).0;
1191    let auction_address = auction_pda().0;
1192    let treasury_address = treasury_pda().0;
1193    let treasury_tokens_address = get_associated_token_address(&treasury_address, &MINT_ADDRESS);
1194    let staking_pool_address = pool_pda().0;
1195    let config_address = config_pda().0;
1196    let mint_authority_address = oil_mint_api::state::authority_pda().0;
1197    let bidder_miner_address = miner_pda(authority).0;
1198    let user_wrapped_sol_ata = get_associated_token_address(&authority, &SOL_MINT);
1199    let treasury_wrapped_sol_ata = get_associated_token_address(&treasury_address, &SOL_MINT);
1200    
1201    let mut accounts = vec![
1202        AccountMeta::new(signer, true),
1203        AccountMeta::new(authority, false),
1204        AccountMeta::new_readonly(program_signer, false),
1205        AccountMeta::new(payer, false),
1206        AccountMeta::new(well_address, false),
1207        AccountMeta::new(auction_address, false),
1208        AccountMeta::new(treasury_address, false),
1209        AccountMeta::new(treasury_tokens_address, false),
1210        AccountMeta::new(MINT_ADDRESS, false),
1211        AccountMeta::new(mint_authority_address, false),
1212        AccountMeta::new_readonly(oil_mint_api::ID, false),
1213        AccountMeta::new(staking_pool_address, false),
1214        AccountMeta::new(fee_collector, false),
1215        AccountMeta::new_readonly(config_address, false),
1216        AccountMeta::new_readonly(spl_token::ID, false),
1217        AccountMeta::new_readonly(system_program::ID, false),
1218        AccountMeta::new_readonly(crate::ID, false),
1219        AccountMeta::new(bidder_miner_address, false),
1220    ];
1221    
1222    if let (Some(miner_pubkey), Some(owner_pubkey)) = (previous_owner_miner, previous_owner) {
1223        accounts.push(AccountMeta::new(miner_pubkey, false));
1224        accounts.push(AccountMeta::new(owner_pubkey, false));
1225    }
1226    
1227    if let Some(referrer_pubkey) = referrer {
1228        let referral_address = referral_pda(referrer_pubkey).0;
1229        accounts.push(AccountMeta::new(referral_address, false));
1230    }
1231    
1232    accounts.extend_from_slice(&[
1233        AccountMeta::new(user_wrapped_sol_ata, false),
1234        AccountMeta::new(treasury_wrapped_sol_ata, false),
1235        AccountMeta::new_readonly(spl_token::ID, false),
1236        AccountMeta::new_readonly(SOL_MINT, false),
1237        AccountMeta::new_readonly(spl_associated_token_account::ID, false),
1238    ]);
1239    
1240    Instruction {
1241        program_id: crate::ID,
1242        accounts,
1243        data: instruction::PlaceBid {
1244            square_id: square_id.to_le_bytes(),
1245            referrer: referrer.unwrap_or(Pubkey::default()).to_bytes(),
1246        }
1247        .to_bytes(),
1248    }
1249}
1250
1251pub fn claim_auction_oil_with_session(
1252    signer: Pubkey,
1253    authority: Pubkey,
1254    program_signer: Pubkey,
1255    payer: Pubkey,
1256    well_mask: u8,
1257    referrer_miner: Option<Pubkey>,
1258    referrer_referral: Option<Pubkey>,
1259    referrer_referral_oil_ata: Option<Pubkey>,
1260) -> Instruction {
1261    let miner_address = miner_pda(authority).0;
1262    let well_0_address = well_pda(0).0;
1263    let well_1_address = well_pda(1).0;
1264    let well_2_address = well_pda(2).0;
1265    let well_3_address = well_pda(3).0;
1266    let auction_address = auction_pda().0;
1267    let treasury_address = treasury_pda().0;
1268    let treasury_tokens_address = get_associated_token_address(&treasury_address, &MINT_ADDRESS);
1269    let recipient_address = get_associated_token_address(&authority, &MINT_ADDRESS);
1270    let mint_authority_address = oil_mint_api::state::authority_pda().0;
1271    
1272    let mut accounts = vec![
1273        AccountMeta::new(signer, true),
1274        AccountMeta::new(authority, false),
1275        AccountMeta::new_readonly(program_signer, false),
1276        AccountMeta::new(payer, false),
1277        AccountMeta::new(miner_address, false),
1278        AccountMeta::new(well_0_address, false),
1279        AccountMeta::new(well_1_address, false),
1280        AccountMeta::new(well_2_address, false),
1281        AccountMeta::new(well_3_address, false),
1282        AccountMeta::new(auction_address, false),
1283        AccountMeta::new(treasury_address, false),
1284        AccountMeta::new(treasury_tokens_address, false),
1285        AccountMeta::new(MINT_ADDRESS, false),
1286        AccountMeta::new(mint_authority_address, false),
1287        AccountMeta::new_readonly(oil_mint_api::ID, false),
1288        AccountMeta::new(recipient_address, false),
1289        AccountMeta::new_readonly(spl_token::ID, false),
1290        AccountMeta::new_readonly(spl_associated_token_account::ID, false),
1291        AccountMeta::new_readonly(system_program::ID, false),
1292        AccountMeta::new_readonly(crate::ID, false),
1293    ];
1294    
1295    if let (Some(miner_pubkey), Some(referral_pubkey), Some(oil_ata_pubkey)) = 
1296        (referrer_miner, referrer_referral, referrer_referral_oil_ata) {
1297        accounts.push(AccountMeta::new(miner_pubkey, false));
1298        accounts.push(AccountMeta::new(referral_pubkey, false));
1299        accounts.push(AccountMeta::new(oil_ata_pubkey, false));
1300    }
1301    
1302    Instruction {
1303        program_id: crate::ID,
1304        accounts,
1305        data: ClaimAuctionOIL {
1306            well_mask,
1307        }
1308        .to_bytes(),
1309    }
1310}
1311
1312pub fn claim_auction_sol_with_session(
1313    signer: Pubkey,
1314    authority: Pubkey,
1315    program_signer: Pubkey,
1316    payer: Pubkey,
1317    referrer_miner: Option<Pubkey>,
1318    referrer_referral: Option<Pubkey>,
1319) -> Instruction {
1320    let miner_address = miner_pda(authority).0;
1321    let (auction_address, _) = auction_pda();
1322    let treasury_address = treasury_pda().0;
1323    
1324    let mut accounts = vec![
1325        AccountMeta::new(signer, true),
1326        AccountMeta::new(authority, false),
1327        AccountMeta::new_readonly(program_signer, false),
1328        AccountMeta::new(payer, false),
1329        AccountMeta::new(miner_address, false),
1330        AccountMeta::new(treasury_address, false),
1331        AccountMeta::new(auction_address, false),
1332        AccountMeta::new_readonly(system_program::ID, false),
1333        AccountMeta::new_readonly(crate::ID, false),
1334    ];
1335    
1336    if let (Some(miner_pubkey), Some(referral_pubkey)) = (referrer_miner, referrer_referral) {
1337        accounts.push(AccountMeta::new(miner_pubkey, false));
1338        accounts.push(AccountMeta::new(referral_pubkey, false));
1339    }
1340    
1341    Instruction {
1342        program_id: crate::ID,
1343        accounts,
1344        data: ClaimAuctionSOL {
1345            _reserved: 0,
1346        }
1347        .to_bytes(),
1348    }
1349}
1350
1351pub fn claim_sol_with_session(
1352    signer: Pubkey,
1353    authority: Pubkey,
1354    program_signer: Pubkey,
1355    payer: Pubkey,
1356    referrer_miner: Option<Pubkey>,
1357    referrer_referral: Option<Pubkey>,
1358) -> Instruction {
1359    let miner_address = miner_pda(authority).0;
1360    
1361    let mut accounts = vec![
1362        AccountMeta::new(signer, true),
1363        AccountMeta::new(authority, false),
1364        AccountMeta::new_readonly(program_signer, false),
1365        AccountMeta::new(payer, false),
1366        AccountMeta::new(miner_address, false),
1367        AccountMeta::new_readonly(system_program::ID, false),
1368    ];
1369    
1370    if let (Some(miner_pubkey), Some(referral_pubkey)) = (referrer_miner, referrer_referral) {
1371        accounts.push(AccountMeta::new(miner_pubkey, false));
1372        accounts.push(AccountMeta::new(referral_pubkey, false));
1373    }
1374    
1375    Instruction {
1376        program_id: crate::ID,
1377        accounts,
1378        data: ClaimSOL {}.to_bytes(),
1379    }
1380}
1381
1382pub fn claim_oil_with_session(
1383    signer: Pubkey,
1384    authority: Pubkey,
1385    program_signer: Pubkey,
1386    payer: Pubkey,
1387    referrer_miner: Option<Pubkey>,
1388    referrer_referral: Option<Pubkey>,
1389    referrer_referral_oil_ata: Option<Pubkey>,
1390) -> Instruction {
1391    let miner_address = miner_pda(authority).0;
1392    let treasury_address = treasury_pda().0;
1393    let treasury_tokens_address = get_associated_token_address(&treasury_address, &MINT_ADDRESS);
1394    let recipient_address = get_associated_token_address(&authority, &MINT_ADDRESS);
1395    
1396    let mut accounts = vec![
1397        AccountMeta::new(signer, true),
1398        AccountMeta::new(authority, false),
1399        AccountMeta::new_readonly(program_signer, false),
1400        AccountMeta::new(payer, false),
1401        AccountMeta::new(miner_address, false),
1402        AccountMeta::new(MINT_ADDRESS, false),
1403        AccountMeta::new(recipient_address, false),
1404        AccountMeta::new(treasury_address, false),
1405        AccountMeta::new(treasury_tokens_address, false),
1406        AccountMeta::new_readonly(system_program::ID, false),
1407        AccountMeta::new_readonly(spl_token::ID, false),
1408        AccountMeta::new_readonly(spl_associated_token_account::ID, false),
1409    ];
1410    
1411    if let (Some(miner_pubkey), Some(referral_pubkey), Some(oil_ata_pubkey)) = 
1412        (referrer_miner, referrer_referral, referrer_referral_oil_ata) {
1413        accounts.push(AccountMeta::new(miner_pubkey, false));
1414        accounts.push(AccountMeta::new(referral_pubkey, false));
1415        accounts.push(AccountMeta::new(oil_ata_pubkey, false));
1416    }
1417    
1418    Instruction {
1419        program_id: crate::ID,
1420        accounts,
1421        data: ClaimOIL {}.to_bytes(),
1422    }
1423}
1424
1425pub fn withdraw_with_session(
1426    signer: Pubkey,
1427    authority: Pubkey,
1428    program_signer: Pubkey,
1429    payer: Pubkey,
1430    amount: u64,
1431    stake_id: u64,
1432) -> Instruction {
1433    let stake_address = stake_pda_with_id(authority, stake_id).0;
1434    let stake_tokens_address = get_associated_token_address(&stake_address, &MINT_ADDRESS);
1435    let mint_address = MINT_ADDRESS;
1436    let recipient_address = get_associated_token_address(&authority, &MINT_ADDRESS);
1437    let pool_address = pool_pda().0;
1438    let pool_tokens_address = pool_tokens_address();
1439    let miner_address = miner_pda(authority).0;
1440    let treasury_address = treasury_pda().0;
1441    let treasury_tokens_address = treasury_tokens_address();
1442    
1443    Instruction {
1444        program_id: crate::ID,
1445        accounts: vec![
1446            AccountMeta::new(signer, true),
1447            AccountMeta::new(authority, false),
1448            AccountMeta::new_readonly(program_signer, false),
1449            AccountMeta::new(payer, false),
1450            AccountMeta::new(mint_address, false),
1451            AccountMeta::new(recipient_address, false),
1452            AccountMeta::new(stake_address, false),
1453            AccountMeta::new(stake_tokens_address, false),
1454            AccountMeta::new(pool_address, false),
1455            AccountMeta::new(pool_tokens_address, false),
1456            AccountMeta::new(miner_address, false),
1457            AccountMeta::new(treasury_address, false),
1458            AccountMeta::new(treasury_tokens_address, false),
1459            AccountMeta::new_readonly(system_program::ID, false),
1460            AccountMeta::new_readonly(spl_token::ID, false),
1461            AccountMeta::new_readonly(spl_associated_token_account::ID, false),
1462        ],
1463        data: Withdraw {
1464            amount: amount.to_le_bytes(),
1465            stake_id: stake_id.to_le_bytes(),
1466        }
1467        .to_bytes(),
1468    }
1469}