solana-program-library/binary-oracle-pair/program/src/instruction.rs

221 lines
7.1 KiB
Rust

//! Instruction types
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::{
clock::Slot,
instruction::{AccountMeta, Instruction},
program_error::ProgramError,
pubkey::Pubkey,
sysvar,
};
/// Initialize arguments for pool
#[repr(C)]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
pub struct InitArgs {
/// mint end slot
pub mint_end_slot: Slot,
/// decide end slot
pub decide_end_slot: Slot,
/// authority nonce
pub bump_seed: u8,
}
/// Instruction definition
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
pub enum PoolInstruction {
/// Initializes a new binary oracle pair pool.
///
/// 0. `[w]` Pool account.
/// 1. `[]` Authority
/// 2. `[]` Decider authority
/// 3. `[]` Deposit currency SPL Token mint. Must be initialized.
/// 4. `[w]` Deposit token account. Should not be initialized
/// 5. `[w]` Token Pass mint. Should not be initialized
/// 6. `[w]` Token Fail mint. Should not be initialized
/// 7. `[]` Rent sysvar
/// 8. `[]` Token program id
InitPool(InitArgs),
/// Deposit into the pool.
///
/// 0. `[]` Pool
/// 1. `[]` Authority
/// 2. `[s]` User transfer authority
/// 3. `[w]` Token SOURCE Account, amount is transferable by pool authority with allowances.
/// 4. `[w]` Deposit token account
/// 5. `[w]` token_P PASS mint
/// 6. `[w]` token_F FAIL mint
/// 7. `[w]` token_P DESTINATION Account
/// 8. `[w]` token_F DESTINATION Account
/// 9. `[]` Sysvar Clock
/// 10. `[]` Token program id
Deposit(u64),
/// Withdraw from the pool.
/// If current slot is < mint_end slot, 1 Pass AND 1 Fail token convert to 1 deposit
/// If current slot is > decide_end_slot slot && decide == Some(true), 1 Pass convert to 1 deposit
/// otherwise 1 Fail converts to 1 deposit
///
/// Pass tokens convert 1:1 to the deposit token iff decision is set to Some(true)
/// AND current slot is > decide_end_slot.
///
/// 0. `[]` Pool
/// 1. `[]` Authority
/// 2. `[s]` User transfer authority
/// 3. `[w]` Pool deposit token account
/// 4. `[w]` token_P PASS SOURCE Account
/// 5. `[w]` token_F FAIL SOURCE Account
/// 6. `[w]` token_P PASS mint
/// 7. `[w]` token_F FAIL mint
/// 8. `[w]` Deposit DESTINATION Account
/// 9. `[]` Sysvar Clock
/// 10. `[]` Token program id
Withdraw(u64),
/// Trigger the decision.
/// Call only succeeds once and if current slot > mint_end slot AND < decide_end slot
/// 0. `[]` Pool
/// 1. `[s]` Decider pubkey
/// 2. `[]` Sysvar Clock
Decide(bool),
}
/// Create `InitPool` instruction
#[allow(clippy::too_many_arguments)]
pub fn init_pool(
program_id: &Pubkey,
pool: &Pubkey,
authority: &Pubkey,
decider: &Pubkey,
deposit_token_mint: &Pubkey,
deposit_account: &Pubkey,
token_pass_mint: &Pubkey,
token_fail_mint: &Pubkey,
token_program_id: &Pubkey,
init_args: InitArgs,
) -> Result<Instruction, ProgramError> {
let init_data = PoolInstruction::InitPool(init_args);
let data = init_data.try_to_vec()?;
let accounts = vec![
AccountMeta::new(*pool, false),
AccountMeta::new_readonly(*authority, false),
AccountMeta::new_readonly(*decider, false),
AccountMeta::new_readonly(*deposit_token_mint, false),
AccountMeta::new(*deposit_account, false),
AccountMeta::new(*token_pass_mint, false),
AccountMeta::new(*token_fail_mint, false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
AccountMeta::new_readonly(*token_program_id, false),
];
Ok(Instruction {
program_id: *program_id,
accounts,
data,
})
}
/// Create `Deposit` instruction
#[allow(clippy::too_many_arguments)]
pub fn deposit(
program_id: &Pubkey,
pool: &Pubkey,
authority: &Pubkey,
user_transfer_authority: &Pubkey,
user_token_account: &Pubkey,
pool_deposit_token_account: &Pubkey,
token_pass_mint: &Pubkey,
token_fail_mint: &Pubkey,
token_pass_destination_account: &Pubkey,
token_fail_destination_account: &Pubkey,
token_program_id: &Pubkey,
amount: u64,
) -> Result<Instruction, ProgramError> {
let init_data = PoolInstruction::Deposit(amount);
let data = init_data.try_to_vec()?;
let accounts = vec![
AccountMeta::new_readonly(*pool, false),
AccountMeta::new_readonly(*authority, false),
AccountMeta::new_readonly(
*user_transfer_authority,
authority != user_transfer_authority,
),
AccountMeta::new(*user_token_account, false),
AccountMeta::new(*pool_deposit_token_account, false),
AccountMeta::new(*token_pass_mint, false),
AccountMeta::new(*token_fail_mint, false),
AccountMeta::new(*token_pass_destination_account, false),
AccountMeta::new(*token_fail_destination_account, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(*token_program_id, false),
];
Ok(Instruction {
program_id: *program_id,
accounts,
data,
})
}
/// Create `Withdraw` instruction
#[allow(clippy::too_many_arguments)]
pub fn withdraw(
program_id: &Pubkey,
pool: &Pubkey,
authority: &Pubkey,
user_transfer_authority: &Pubkey,
pool_deposit_token_account: &Pubkey,
token_pass_user_account: &Pubkey,
token_fail_user_account: &Pubkey,
token_pass_mint: &Pubkey,
token_fail_mint: &Pubkey,
user_token_destination_account: &Pubkey,
token_program_id: &Pubkey,
amount: u64,
) -> Result<Instruction, ProgramError> {
let init_data = PoolInstruction::Withdraw(amount);
let data = init_data.try_to_vec()?;
let accounts = vec![
AccountMeta::new_readonly(*pool, false),
AccountMeta::new_readonly(*authority, false),
AccountMeta::new_readonly(
*user_transfer_authority,
authority != user_transfer_authority,
),
AccountMeta::new(*pool_deposit_token_account, false),
AccountMeta::new(*token_pass_user_account, false),
AccountMeta::new(*token_fail_user_account, false),
AccountMeta::new(*token_pass_mint, false),
AccountMeta::new(*token_fail_mint, false),
AccountMeta::new(*user_token_destination_account, false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
AccountMeta::new_readonly(*token_program_id, false),
];
Ok(Instruction {
program_id: *program_id,
accounts,
data,
})
}
/// Create `Decide` instruction
pub fn decide(
program_id: &Pubkey,
pool: &Pubkey,
decider: &Pubkey,
decision: bool,
) -> Result<Instruction, ProgramError> {
let init_data = PoolInstruction::Decide(decision);
let data = init_data.try_to_vec()?;
let accounts = vec![
AccountMeta::new(*pool, false),
AccountMeta::new_readonly(*decider, true),
AccountMeta::new_readonly(sysvar::clock::id(), false),
];
Ok(Instruction {
program_id: *program_id,
accounts,
data,
})
}