1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! Exchange program

use crate::exchange_state::*;
use crate::id;
use serde_derive::{Deserialize, Serialize};
use solana_sdk::instruction::{AccountMeta, Instruction};
use solana_sdk::pubkey::Pubkey;

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct OrderRequestInfo {
    /// Side of market of the order (bid/ask)
    pub side: OrderSide,

    /// Token pair to trade
    pub pair: AssetPair,

    /// Number of tokens to exchange; refers to the primary or the secondary depending on the order side
    pub tokens: u64,

    /// The price ratio the primary price over the secondary price.  The primary price is fixed
    /// and equal to the variable `SCALER`.
    pub price: u64,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum ExchangeInstruction {
    /// New token account
    /// key 0 - Signer
    /// key 1 - New token account
    AccountRequest,

    /// Transfer tokens between two accounts
    /// key 0 - Account to transfer tokens to
    /// key 1 - Account to transfer tokens from.  This can be the exchange program itself,
    ///         the exchange has a limitless number of tokens it can transfer.
    TransferRequest(Token, u64),

    /// Order request
    /// key 0 - Signer
    /// key 1 - Account in which to record the trade order
    /// key 2 - Token account to source tokens from
    OrderRequest(OrderRequestInfo),

    /// Order cancellation
    /// key 0 - Signer
    /// key 1 - Order to cancel
    OrderCancellation,

    /// Trade swap request
    /// key 0 - Signer
    /// key 2 - 'To' trade order
    /// key 3 - `From` trade order
    /// key 6 - Token account in which to deposit the brokers profit from the swap.
    SwapRequest,
}

pub fn account_request(owner: &Pubkey, new: &Pubkey) -> Instruction {
    let account_metas = vec![
        AccountMeta::new(*owner, true),
        AccountMeta::new(*new, false),
    ];
    Instruction::new(id(), &ExchangeInstruction::AccountRequest, account_metas)
}

pub fn transfer_request(
    owner: &Pubkey,
    to: &Pubkey,
    from: &Pubkey,
    token: Token,
    tokens: u64,
) -> Instruction {
    let account_metas = vec![
        AccountMeta::new(*owner, true),
        AccountMeta::new(*to, false),
        AccountMeta::new(*from, false),
    ];
    Instruction::new(
        id(),
        &ExchangeInstruction::TransferRequest(token, tokens),
        account_metas,
    )
}

pub fn trade_request(
    owner: &Pubkey,
    trade: &Pubkey,
    side: OrderSide,
    pair: AssetPair,
    tokens: u64,
    price: u64,
    src_account: &Pubkey,
) -> Instruction {
    let account_metas = vec![
        AccountMeta::new(*owner, true),
        AccountMeta::new(*trade, false),
        AccountMeta::new(*src_account, false),
    ];
    Instruction::new(
        id(),
        &ExchangeInstruction::OrderRequest(OrderRequestInfo {
            side,
            pair,
            tokens,
            price,
        }),
        account_metas,
    )
}

pub fn order_cancellation(owner: &Pubkey, order: &Pubkey) -> Instruction {
    let account_metas = vec![
        AccountMeta::new(*owner, true),
        AccountMeta::new(*order, false),
    ];
    Instruction::new(id(), &ExchangeInstruction::OrderCancellation, account_metas)
}

pub fn swap_request(
    owner: &Pubkey,
    to_trade: &Pubkey,
    from_trade: &Pubkey,
    profit_account: &Pubkey,
) -> Instruction {
    let account_metas = vec![
        AccountMeta::new(*owner, true),
        AccountMeta::new(*to_trade, false),
        AccountMeta::new(*from_trade, false),
        AccountMeta::new(*profit_account, false),
    ];
    Instruction::new(id(), &ExchangeInstruction::SwapRequest, account_metas)
}