spl_binary_oracle_pair/
instruction.rs

1//! Instruction types
2
3use borsh::{BorshDeserialize, BorshSerialize};
4use solana_program::{
5    clock::Slot,
6    instruction::{AccountMeta, Instruction},
7    program_error::ProgramError,
8    pubkey::Pubkey,
9    sysvar,
10};
11
12/// Initialize arguments for pool
13#[repr(C)]
14#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
15pub struct InitArgs {
16    /// mint end slot
17    pub mint_end_slot: Slot,
18    /// decide end slot
19    pub decide_end_slot: Slot,
20    /// authority nonce
21    pub bump_seed: u8,
22}
23
24/// Instruction definition
25#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
26pub enum PoolInstruction {
27    /// Initializes a new binary oracle pair pool.
28    ///
29    ///   0. `[w]` Pool account.
30    ///   1. `[]` Authority
31    ///   2. `[]` Decider authority
32    ///   3. `[]` Deposit currency SPL Token mint. Must be initialized.
33    ///   4. `[w]` Deposit token account. Should not be initialized
34    ///   5. `[w]` Token Pass mint. Should not be initialized
35    ///   6. `[w]` Token Fail mint. Should not be initialized
36    ///   7. `[]` Rent sysvar
37    ///   8. `[]` Token program id
38    InitPool(InitArgs),
39
40    ///   Deposit into the pool.
41    ///
42    ///   0. `[]` Pool
43    ///   1. `[]` Authority
44    ///   2. `[s]` User transfer authority
45    ///   3. `[w]` Token SOURCE Account, amount is transferable by pool authority with allowances.
46    ///   4. `[w]` Deposit token account
47    ///   5. `[w]` token_P PASS mint
48    ///   6. `[w]` token_F FAIL mint
49    ///   7. `[w]` token_P DESTINATION Account
50    ///   8. `[w]` token_F DESTINATION Account
51    ///   9. `[]` Sysvar Clock
52    ///   10. `[]` Token program id
53    Deposit(u64),
54
55    ///   Withdraw from the pool.
56    ///   If current slot is < mint_end slot, 1 Pass AND 1 Fail token convert to 1 deposit
57    ///   If current slot is > decide_end_slot slot && decide == Some(true), 1 Pass convert to 1 deposit
58    ///   otherwise 1 Fail converts to 1 deposit
59    ///
60    ///   Pass tokens convert 1:1 to the deposit token iff decision is set to Some(true)
61    ///   AND current slot is > decide_end_slot.
62    ///
63    ///   0. `[]` Pool
64    ///   1. `[]` Authority
65    ///   2. `[s]` User transfer authority
66    ///   3. `[w]` Pool deposit token account
67    ///   4. `[w]` token_P PASS SOURCE Account
68    ///   5. `[w]` token_F FAIL SOURCE Account
69    ///   6. `[w]` token_P PASS mint
70    ///   7. `[w]` token_F FAIL mint
71    ///   8. `[w]` Deposit DESTINATION Account
72    ///   9. `[]` Sysvar Clock
73    ///   10. `[]` Token program id
74    Withdraw(u64),
75
76    ///  Trigger the decision.
77    ///  Call only succeeds once and if current slot > mint_end slot AND < decide_end slot
78    ///   0. `[]` Pool
79    ///   1. `[s]` Decider pubkey
80    ///   2. `[]` Sysvar Clock
81    Decide(bool),
82}
83
84/// Create `InitPool` instruction
85#[allow(clippy::too_many_arguments)]
86pub fn init_pool(
87    program_id: &Pubkey,
88    pool: &Pubkey,
89    authority: &Pubkey,
90    decider: &Pubkey,
91    deposit_token_mint: &Pubkey,
92    deposit_account: &Pubkey,
93    token_pass_mint: &Pubkey,
94    token_fail_mint: &Pubkey,
95    token_program_id: &Pubkey,
96    init_args: InitArgs,
97) -> Result<Instruction, ProgramError> {
98    let init_data = PoolInstruction::InitPool(init_args);
99    let data = init_data.try_to_vec()?;
100    let accounts = vec![
101        AccountMeta::new(*pool, false),
102        AccountMeta::new_readonly(*authority, false),
103        AccountMeta::new_readonly(*decider, false),
104        AccountMeta::new_readonly(*deposit_token_mint, false),
105        AccountMeta::new(*deposit_account, false),
106        AccountMeta::new(*token_pass_mint, false),
107        AccountMeta::new(*token_fail_mint, false),
108        AccountMeta::new_readonly(sysvar::rent::id(), false),
109        AccountMeta::new_readonly(*token_program_id, false),
110    ];
111    Ok(Instruction {
112        program_id: *program_id,
113        accounts,
114        data,
115    })
116}
117
118/// Create `Deposit` instruction
119#[allow(clippy::too_many_arguments)]
120pub fn deposit(
121    program_id: &Pubkey,
122    pool: &Pubkey,
123    authority: &Pubkey,
124    user_transfer_authority: &Pubkey,
125    user_token_account: &Pubkey,
126    pool_deposit_token_account: &Pubkey,
127    token_pass_mint: &Pubkey,
128    token_fail_mint: &Pubkey,
129    token_pass_destination_account: &Pubkey,
130    token_fail_destination_account: &Pubkey,
131    token_program_id: &Pubkey,
132    amount: u64,
133) -> Result<Instruction, ProgramError> {
134    let init_data = PoolInstruction::Deposit(amount);
135    let data = init_data.try_to_vec()?;
136
137    let accounts = vec![
138        AccountMeta::new_readonly(*pool, false),
139        AccountMeta::new_readonly(*authority, false),
140        AccountMeta::new_readonly(
141            *user_transfer_authority,
142            authority != user_transfer_authority,
143        ),
144        AccountMeta::new(*user_token_account, false),
145        AccountMeta::new(*pool_deposit_token_account, false),
146        AccountMeta::new(*token_pass_mint, false),
147        AccountMeta::new(*token_fail_mint, false),
148        AccountMeta::new(*token_pass_destination_account, false),
149        AccountMeta::new(*token_fail_destination_account, false),
150        AccountMeta::new_readonly(sysvar::clock::id(), false),
151        AccountMeta::new_readonly(*token_program_id, false),
152    ];
153    Ok(Instruction {
154        program_id: *program_id,
155        accounts,
156        data,
157    })
158}
159
160/// Create `Withdraw` instruction
161#[allow(clippy::too_many_arguments)]
162pub fn withdraw(
163    program_id: &Pubkey,
164    pool: &Pubkey,
165    authority: &Pubkey,
166    user_transfer_authority: &Pubkey,
167    pool_deposit_token_account: &Pubkey,
168    token_pass_user_account: &Pubkey,
169    token_fail_user_account: &Pubkey,
170    token_pass_mint: &Pubkey,
171    token_fail_mint: &Pubkey,
172    user_token_destination_account: &Pubkey,
173    token_program_id: &Pubkey,
174    amount: u64,
175) -> Result<Instruction, ProgramError> {
176    let init_data = PoolInstruction::Withdraw(amount);
177    let data = init_data.try_to_vec()?;
178    let accounts = vec![
179        AccountMeta::new_readonly(*pool, false),
180        AccountMeta::new_readonly(*authority, false),
181        AccountMeta::new_readonly(
182            *user_transfer_authority,
183            authority != user_transfer_authority,
184        ),
185        AccountMeta::new(*pool_deposit_token_account, false),
186        AccountMeta::new(*token_pass_user_account, false),
187        AccountMeta::new(*token_fail_user_account, false),
188        AccountMeta::new(*token_pass_mint, false),
189        AccountMeta::new(*token_fail_mint, false),
190        AccountMeta::new(*user_token_destination_account, false),
191        AccountMeta::new_readonly(sysvar::clock::id(), false),
192        AccountMeta::new_readonly(*token_program_id, false),
193    ];
194    Ok(Instruction {
195        program_id: *program_id,
196        accounts,
197        data,
198    })
199}
200
201/// Create `Decide` instruction
202pub fn decide(
203    program_id: &Pubkey,
204    pool: &Pubkey,
205    decider: &Pubkey,
206    decision: bool,
207) -> Result<Instruction, ProgramError> {
208    let init_data = PoolInstruction::Decide(decision);
209    let data = init_data.try_to_vec()?;
210    let accounts = vec![
211        AccountMeta::new(*pool, false),
212        AccountMeta::new_readonly(*decider, true),
213        AccountMeta::new_readonly(sysvar::clock::id(), false),
214    ];
215    Ok(Instruction {
216        program_id: *program_id,
217        accounts,
218        data,
219    })
220}