2022-03-15 06:44:47 -07:00
|
|
|
#![allow(dead_code)]
|
|
|
|
|
2022-02-25 04:10:51 -08:00
|
|
|
use anchor_lang::prelude::*;
|
|
|
|
use anchor_lang::solana_program::sysvar::{self, SysvarId};
|
|
|
|
use anchor_spl::token::{Token, TokenAccount};
|
2022-02-28 08:17:01 -08:00
|
|
|
use fixed::types::I80F48;
|
2022-03-29 02:49:26 -07:00
|
|
|
use itertools::Itertools;
|
2022-04-12 08:35:39 -07:00
|
|
|
use mango_v4::instructions::{
|
|
|
|
InterestRateParams, Serum3OrderType, Serum3SelfTradeBehavior, Serum3Side,
|
|
|
|
};
|
2022-02-28 08:17:01 -08:00
|
|
|
use solana_program::instruction::Instruction;
|
2022-02-25 04:10:51 -08:00
|
|
|
use solana_sdk::instruction;
|
|
|
|
use solana_sdk::signature::{Keypair, Signer};
|
2022-05-18 08:16:14 -07:00
|
|
|
use solana_sdk::transport::TransportError;
|
2022-04-09 12:18:07 -07:00
|
|
|
|
2022-02-28 21:28:12 -08:00
|
|
|
use std::str::FromStr;
|
2022-02-25 04:10:51 -08:00
|
|
|
|
2022-02-28 02:07:04 -08:00
|
|
|
use super::solana::SolanaCookie;
|
2022-02-28 06:42:14 -08:00
|
|
|
use mango_v4::state::*;
|
2022-02-28 02:07:04 -08:00
|
|
|
|
2022-02-25 04:10:51 -08:00
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
pub trait ClientAccountLoader {
|
|
|
|
async fn load_bytes(&self, pubkey: &Pubkey) -> Option<Vec<u8>>;
|
|
|
|
async fn load<T: AccountDeserialize>(&self, pubkey: &Pubkey) -> Option<T> {
|
|
|
|
let bytes = self.load_bytes(pubkey).await?;
|
|
|
|
AccountDeserialize::try_deserialize(&mut &bytes[..]).ok()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl ClientAccountLoader for &SolanaCookie {
|
|
|
|
async fn load_bytes(&self, pubkey: &Pubkey) -> Option<Vec<u8>> {
|
|
|
|
self.get_account_data(*pubkey).await
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: report error outwards etc
|
2022-02-28 00:12:24 -08:00
|
|
|
pub async fn send_tx<CI: ClientInstruction>(
|
|
|
|
solana: &SolanaCookie,
|
|
|
|
ix: CI,
|
2022-05-18 08:16:14 -07:00
|
|
|
) -> std::result::Result<CI::Accounts, TransportError> {
|
2022-02-26 08:47:16 -08:00
|
|
|
let (accounts, instruction) = ix.to_instruction(solana).await;
|
2022-02-25 04:10:51 -08:00
|
|
|
let signers = ix.signers();
|
2022-02-26 08:47:16 -08:00
|
|
|
let instructions = vec![instruction];
|
2022-02-25 04:10:51 -08:00
|
|
|
solana
|
|
|
|
.process_transaction(&instructions, Some(&signers[..]))
|
2022-02-28 00:12:24 -08:00
|
|
|
.await?;
|
|
|
|
Ok(accounts)
|
2022-02-25 04:10:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
pub trait ClientInstruction {
|
|
|
|
type Accounts: anchor_lang::ToAccountMetas;
|
|
|
|
type Instruction: anchor_lang::InstructionData;
|
|
|
|
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
loader: impl ClientAccountLoader + 'async_trait,
|
2022-02-26 08:47:16 -08:00
|
|
|
) -> (Self::Accounts, instruction::Instruction);
|
2022-02-25 04:10:51 -08:00
|
|
|
fn signers(&self) -> Vec<&Keypair>;
|
|
|
|
}
|
|
|
|
|
2022-02-26 08:47:16 -08:00
|
|
|
fn make_instruction(
|
|
|
|
program_id: Pubkey,
|
|
|
|
accounts: &impl anchor_lang::ToAccountMetas,
|
|
|
|
data: impl anchor_lang::InstructionData,
|
|
|
|
) -> instruction::Instruction {
|
|
|
|
instruction::Instruction {
|
|
|
|
program_id,
|
|
|
|
accounts: anchor_lang::ToAccountMetas::to_account_metas(accounts, None),
|
|
|
|
data: anchor_lang::InstructionData::data(&data),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-14 05:34:54 -07:00
|
|
|
async fn get_mint_info_by_mint(
|
2022-03-05 09:03:57 -08:00
|
|
|
account_loader: &impl ClientAccountLoader,
|
|
|
|
account: &MangoAccount,
|
|
|
|
mint: Pubkey,
|
|
|
|
) -> MintInfo {
|
|
|
|
let mint_info_pk = Pubkey::find_program_address(
|
2022-03-11 11:10:15 -08:00
|
|
|
&[account.group.as_ref(), b"MintInfo".as_ref(), mint.as_ref()],
|
2022-03-05 09:03:57 -08:00
|
|
|
&mango_v4::id(),
|
|
|
|
)
|
|
|
|
.0;
|
|
|
|
account_loader.load(&mint_info_pk).await.unwrap()
|
|
|
|
}
|
|
|
|
|
2022-03-14 05:34:54 -07:00
|
|
|
async fn get_mint_info_by_token_index(
|
|
|
|
account_loader: &impl ClientAccountLoader,
|
|
|
|
account: &MangoAccount,
|
|
|
|
token_index: TokenIndex,
|
|
|
|
) -> MintInfo {
|
|
|
|
let bank_pk = Pubkey::find_program_address(
|
|
|
|
&[
|
|
|
|
account.group.as_ref(),
|
2022-03-14 05:39:54 -07:00
|
|
|
b"Bank".as_ref(),
|
2022-03-14 05:34:54 -07:00
|
|
|
&token_index.to_le_bytes(),
|
|
|
|
],
|
|
|
|
&mango_v4::id(),
|
|
|
|
)
|
|
|
|
.0;
|
|
|
|
let bank: Bank = account_loader.load(&bank_pk).await.unwrap();
|
|
|
|
get_mint_info_by_mint(account_loader, account, bank.mint).await
|
|
|
|
}
|
|
|
|
|
2022-03-05 09:03:57 -08:00
|
|
|
// all the accounts that instructions like deposit/withdraw need to compute account health
|
|
|
|
async fn derive_health_check_remaining_account_metas(
|
|
|
|
account_loader: &impl ClientAccountLoader,
|
|
|
|
account: &MangoAccount,
|
2022-03-07 06:43:29 -08:00
|
|
|
affected_bank: Option<Pubkey>,
|
|
|
|
writable_banks: bool,
|
2022-03-05 09:03:57 -08:00
|
|
|
) -> Vec<AccountMeta> {
|
|
|
|
// figure out all the banks/oracles that need to be passed for the health check
|
|
|
|
let mut banks = vec![];
|
|
|
|
let mut oracles = vec![];
|
2022-04-02 02:21:41 -07:00
|
|
|
for position in account.tokens.iter_active() {
|
2022-03-14 05:34:54 -07:00
|
|
|
let mint_info =
|
|
|
|
get_mint_info_by_token_index(account_loader, account, position.token_index).await;
|
2022-03-31 00:25:47 -07:00
|
|
|
// TODO: ALTs are unavailable
|
|
|
|
// let lookup_table = account_loader
|
|
|
|
// .load_bytes(&mint_info.address_lookup_table)
|
|
|
|
// .await
|
|
|
|
// .unwrap();
|
|
|
|
// let addresses = mango_v4::address_lookup_table::addresses(&lookup_table);
|
|
|
|
// banks.push(addresses[mint_info.address_lookup_table_bank_index as usize]);
|
|
|
|
// oracles.push(addresses[mint_info.address_lookup_table_oracle_index as usize]);
|
|
|
|
banks.push(mint_info.bank);
|
|
|
|
oracles.push(mint_info.oracle);
|
2022-03-05 09:03:57 -08:00
|
|
|
}
|
2022-03-07 06:43:29 -08:00
|
|
|
if let Some(affected_bank) = affected_bank {
|
|
|
|
if banks.iter().find(|&&v| v == affected_bank).is_none() {
|
|
|
|
// If there is not yet an active position for the token, we need to pass
|
|
|
|
// the bank/oracle for health check anyway.
|
|
|
|
let new_position = account
|
2022-04-02 02:21:41 -07:00
|
|
|
.tokens
|
2022-03-07 06:43:29 -08:00
|
|
|
.values
|
|
|
|
.iter()
|
|
|
|
.position(|p| !p.is_active())
|
|
|
|
.unwrap();
|
|
|
|
banks.insert(new_position, affected_bank);
|
2022-03-07 07:16:34 -08:00
|
|
|
let affected_bank: Bank = account_loader.load(&affected_bank).await.unwrap();
|
2022-03-07 06:43:29 -08:00
|
|
|
oracles.insert(new_position, affected_bank.oracle);
|
|
|
|
}
|
2022-03-05 09:03:57 -08:00
|
|
|
}
|
|
|
|
|
2022-04-02 02:21:41 -07:00
|
|
|
let serum_oos = account.serum3.iter_active().map(|&s| s.open_orders);
|
2022-03-16 05:42:29 -07:00
|
|
|
|
2022-03-05 09:03:57 -08:00
|
|
|
banks
|
|
|
|
.iter()
|
|
|
|
.map(|&pubkey| AccountMeta {
|
|
|
|
pubkey,
|
2022-03-07 06:43:29 -08:00
|
|
|
is_writable: writable_banks,
|
2022-03-05 09:03:57 -08:00
|
|
|
is_signer: false,
|
|
|
|
})
|
2022-03-07 06:43:29 -08:00
|
|
|
.chain(oracles.iter().map(|&pubkey| AccountMeta {
|
|
|
|
pubkey,
|
|
|
|
is_writable: false,
|
|
|
|
is_signer: false,
|
|
|
|
}))
|
2022-03-16 05:42:29 -07:00
|
|
|
.chain(serum_oos.map(|pubkey| AccountMeta {
|
|
|
|
pubkey,
|
|
|
|
is_writable: false,
|
|
|
|
is_signer: false,
|
|
|
|
}))
|
2022-03-05 09:03:57 -08:00
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2022-03-29 02:49:26 -07:00
|
|
|
async fn derive_liquidation_remaining_account_metas(
|
|
|
|
account_loader: &impl ClientAccountLoader,
|
|
|
|
liqee: &MangoAccount,
|
|
|
|
liqor: &MangoAccount,
|
|
|
|
asset_token_index: TokenIndex,
|
|
|
|
liab_token_index: TokenIndex,
|
|
|
|
) -> Vec<AccountMeta> {
|
|
|
|
let mut banks = vec![];
|
|
|
|
let mut oracles = vec![];
|
|
|
|
let token_indexes = liqee
|
2022-04-02 02:21:41 -07:00
|
|
|
.tokens
|
2022-03-29 02:49:26 -07:00
|
|
|
.iter_active()
|
2022-04-02 02:21:41 -07:00
|
|
|
.chain(liqor.tokens.iter_active())
|
2022-03-29 02:49:26 -07:00
|
|
|
.map(|ta| ta.token_index)
|
|
|
|
.unique();
|
|
|
|
for token_index in token_indexes {
|
|
|
|
let mint_info = get_mint_info_by_token_index(account_loader, liqee, token_index).await;
|
|
|
|
let writable_bank = token_index == asset_token_index || token_index == liab_token_index;
|
2022-03-31 00:25:47 -07:00
|
|
|
// TODO: ALTs are unavailable
|
|
|
|
// let lookup_table = account_loader
|
|
|
|
// .load_bytes(&mint_info.address_lookup_table)
|
|
|
|
// .await
|
|
|
|
// .unwrap();
|
|
|
|
// let addresses = mango_v4::address_lookup_table::addresses(&lookup_table);
|
|
|
|
// banks.push((
|
|
|
|
// addresses[mint_info.address_lookup_table_bank_index as usize],
|
|
|
|
// writable_bank,
|
|
|
|
// ));
|
|
|
|
// oracles.push(addresses[mint_info.address_lookup_table_oracle_index as usize]);
|
|
|
|
banks.push((mint_info.bank, writable_bank));
|
|
|
|
oracles.push(mint_info.oracle);
|
2022-03-29 02:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
let serum_oos = liqee
|
2022-04-02 02:21:41 -07:00
|
|
|
.serum3
|
2022-03-29 02:49:26 -07:00
|
|
|
.iter_active()
|
2022-04-02 02:21:41 -07:00
|
|
|
.chain(liqor.serum3.iter_active())
|
2022-03-29 02:49:26 -07:00
|
|
|
.map(|&s| s.open_orders);
|
|
|
|
|
|
|
|
banks
|
|
|
|
.iter()
|
|
|
|
.map(|(pubkey, is_writable)| AccountMeta {
|
|
|
|
pubkey: *pubkey,
|
|
|
|
is_writable: *is_writable,
|
|
|
|
is_signer: false,
|
|
|
|
})
|
|
|
|
.chain(oracles.iter().map(|&pubkey| AccountMeta {
|
|
|
|
pubkey,
|
|
|
|
is_writable: false,
|
|
|
|
is_signer: false,
|
|
|
|
}))
|
|
|
|
.chain(serum_oos.map(|pubkey| AccountMeta {
|
|
|
|
pubkey,
|
|
|
|
is_writable: false,
|
|
|
|
is_signer: false,
|
|
|
|
}))
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2022-03-14 09:21:16 -07:00
|
|
|
fn from_serum_style_pubkey(d: &[u64; 4]) -> Pubkey {
|
|
|
|
Pubkey::new(bytemuck::cast_slice(d as &[_]))
|
|
|
|
}
|
|
|
|
|
2022-03-15 06:44:47 -07:00
|
|
|
pub async fn account_position(solana: &SolanaCookie, account: Pubkey, bank: Pubkey) -> i64 {
|
|
|
|
let account_data: MangoAccount = solana.get_account(account).await;
|
|
|
|
let bank_data: Bank = solana.get_account(bank).await;
|
|
|
|
let native = account_data
|
2022-04-02 02:21:41 -07:00
|
|
|
.tokens
|
2022-03-15 06:44:47 -07:00
|
|
|
.find(bank_data.token_index)
|
|
|
|
.unwrap()
|
|
|
|
.native(&bank_data);
|
|
|
|
native.round().to_num::<i64>()
|
|
|
|
}
|
|
|
|
|
2022-05-20 01:55:48 -07:00
|
|
|
pub async fn account_position_f64(solana: &SolanaCookie, account: Pubkey, bank: Pubkey) -> f64 {
|
|
|
|
let account_data: MangoAccount = solana.get_account(account).await;
|
|
|
|
let bank_data: Bank = solana.get_account(bank).await;
|
|
|
|
let native = account_data
|
|
|
|
.tokens
|
|
|
|
.find(bank_data.token_index)
|
|
|
|
.unwrap()
|
|
|
|
.native(&bank_data);
|
|
|
|
native.to_num::<f64>()
|
|
|
|
}
|
|
|
|
|
2022-02-25 04:10:51 -08:00
|
|
|
//
|
|
|
|
// a struct for each instruction along with its
|
|
|
|
// ClientInstruction impl
|
|
|
|
//
|
|
|
|
|
2022-03-04 05:30:53 -08:00
|
|
|
pub struct MarginTradeInstruction<'keypair> {
|
|
|
|
pub account: Pubkey,
|
|
|
|
pub owner: &'keypair Keypair,
|
2022-05-19 04:45:46 -07:00
|
|
|
pub mango_token_bank: Pubkey,
|
2022-03-04 05:30:53 -08:00
|
|
|
pub mango_token_vault: Pubkey,
|
2022-05-20 01:55:48 -07:00
|
|
|
pub withdraw_amount: u64,
|
2022-03-04 05:30:53 -08:00
|
|
|
pub margin_trade_program_id: Pubkey,
|
2022-03-08 01:23:58 -08:00
|
|
|
pub deposit_account: Pubkey,
|
|
|
|
pub deposit_account_owner: Pubkey,
|
2022-03-04 05:30:53 -08:00
|
|
|
pub margin_trade_program_ix_cpi_data: Vec<u8>,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for MarginTradeInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::MarginTrade;
|
|
|
|
type Instruction = mango_v4::instruction::MarginTrade;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
account_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
2022-03-08 01:23:58 -08:00
|
|
|
|
|
|
|
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
|
|
|
|
2022-03-04 05:30:53 -08:00
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: account.group,
|
|
|
|
account: self.account,
|
|
|
|
owner: self.owner.pubkey(),
|
2022-05-20 01:55:48 -07:00
|
|
|
token_program: Token::id(),
|
2022-03-04 05:30:53 -08:00
|
|
|
};
|
|
|
|
|
2022-05-19 04:45:46 -07:00
|
|
|
let health_check_metas = derive_health_check_remaining_account_metas(
|
|
|
|
&account_loader,
|
|
|
|
&account,
|
|
|
|
Some(self.mango_token_bank),
|
|
|
|
true,
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
let instruction = Self::Instruction {
|
|
|
|
num_health_accounts: health_check_metas.len(),
|
2022-05-20 01:55:48 -07:00
|
|
|
withdraws: vec![(1, self.withdraw_amount)],
|
2022-05-19 04:45:46 -07:00
|
|
|
cpi_data: self.margin_trade_program_ix_cpi_data.clone(),
|
|
|
|
};
|
2022-03-04 05:30:53 -08:00
|
|
|
|
|
|
|
let mut instruction = make_instruction(program_id, &accounts, instruction);
|
2022-03-07 06:43:29 -08:00
|
|
|
instruction.accounts.extend(health_check_metas.into_iter());
|
2022-03-04 05:30:53 -08:00
|
|
|
instruction.accounts.push(AccountMeta {
|
|
|
|
pubkey: self.margin_trade_program_id,
|
|
|
|
is_writable: false,
|
|
|
|
is_signer: false,
|
|
|
|
});
|
2022-05-19 04:45:46 -07:00
|
|
|
instruction.accounts.push(AccountMeta {
|
|
|
|
pubkey: self.mango_token_bank,
|
|
|
|
is_writable: false,
|
|
|
|
is_signer: false,
|
|
|
|
});
|
2022-03-04 05:30:53 -08:00
|
|
|
instruction.accounts.push(AccountMeta {
|
|
|
|
pubkey: self.mango_token_vault,
|
|
|
|
is_writable: true,
|
|
|
|
is_signer: false,
|
|
|
|
});
|
|
|
|
instruction.accounts.push(AccountMeta {
|
2022-03-08 01:23:58 -08:00
|
|
|
pubkey: self.deposit_account,
|
2022-03-04 05:30:53 -08:00
|
|
|
is_writable: true,
|
|
|
|
is_signer: false,
|
|
|
|
});
|
|
|
|
instruction.accounts.push(AccountMeta {
|
2022-03-08 01:23:58 -08:00
|
|
|
pubkey: self.deposit_account_owner,
|
2022-03-04 05:30:53 -08:00
|
|
|
is_writable: false,
|
|
|
|
is_signer: false,
|
|
|
|
});
|
|
|
|
instruction.accounts.push(AccountMeta {
|
|
|
|
pubkey: spl_token::ID,
|
|
|
|
is_writable: false,
|
|
|
|
is_signer: false,
|
|
|
|
});
|
|
|
|
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.owner]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-25 06:14:15 -08:00
|
|
|
pub struct WithdrawInstruction<'keypair> {
|
|
|
|
pub amount: u64,
|
|
|
|
pub allow_borrow: bool,
|
|
|
|
|
|
|
|
pub account: Pubkey,
|
|
|
|
pub owner: &'keypair Keypair,
|
|
|
|
pub token_account: Pubkey,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for WithdrawInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::Withdraw;
|
|
|
|
type Instruction = mango_v4::instruction::Withdraw;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
account_loader: impl ClientAccountLoader + 'async_trait,
|
2022-02-26 08:47:16 -08:00
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
2022-02-25 06:14:15 -08:00
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {
|
|
|
|
amount: self.amount,
|
|
|
|
allow_borrow: self.allow_borrow,
|
|
|
|
};
|
|
|
|
|
2022-03-03 05:30:44 -08:00
|
|
|
// load accounts, find PDAs, find remainingAccounts
|
2022-02-25 06:14:15 -08:00
|
|
|
let token_account: TokenAccount = account_loader.load(&self.token_account).await.unwrap();
|
2022-02-28 06:42:14 -08:00
|
|
|
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
2022-03-14 05:19:50 -07:00
|
|
|
let mint_info = Pubkey::find_program_address(
|
2022-02-25 06:14:15 -08:00
|
|
|
&[
|
2022-02-28 06:42:14 -08:00
|
|
|
account.group.as_ref(),
|
2022-03-14 05:19:50 -07:00
|
|
|
b"MintInfo".as_ref(),
|
2022-02-25 06:14:15 -08:00
|
|
|
token_account.mint.as_ref(),
|
|
|
|
],
|
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
2022-03-14 05:19:50 -07:00
|
|
|
let mint_info: MintInfo = account_loader.load(&mint_info).await.unwrap();
|
2022-02-25 06:14:15 -08:00
|
|
|
|
2022-03-07 06:43:29 -08:00
|
|
|
let health_check_metas = derive_health_check_remaining_account_metas(
|
|
|
|
&account_loader,
|
|
|
|
&account,
|
2022-03-14 05:19:50 -07:00
|
|
|
Some(mint_info.bank),
|
2022-03-07 06:43:29 -08:00
|
|
|
false,
|
|
|
|
)
|
|
|
|
.await;
|
2022-03-03 05:30:44 -08:00
|
|
|
|
2022-02-25 06:14:15 -08:00
|
|
|
let accounts = Self::Accounts {
|
2022-02-28 06:42:14 -08:00
|
|
|
group: account.group,
|
2022-02-25 06:14:15 -08:00
|
|
|
account: self.account,
|
|
|
|
owner: self.owner.pubkey(),
|
2022-03-14 05:19:50 -07:00
|
|
|
bank: mint_info.bank,
|
|
|
|
vault: mint_info.vault,
|
2022-02-25 06:14:15 -08:00
|
|
|
token_account: self.token_account,
|
|
|
|
token_program: Token::id(),
|
|
|
|
};
|
|
|
|
|
2022-02-26 08:47:16 -08:00
|
|
|
let mut instruction = make_instruction(program_id, &accounts, instruction);
|
2022-03-05 09:03:57 -08:00
|
|
|
instruction.accounts.extend(health_check_metas.into_iter());
|
2022-02-26 08:47:16 -08:00
|
|
|
|
|
|
|
(accounts, instruction)
|
2022-02-25 06:14:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.owner]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-25 04:10:51 -08:00
|
|
|
pub struct DepositInstruction<'keypair> {
|
|
|
|
pub amount: u64,
|
|
|
|
|
|
|
|
pub account: Pubkey,
|
2022-02-25 06:14:15 -08:00
|
|
|
pub token_account: Pubkey,
|
|
|
|
pub token_authority: &'keypair Keypair,
|
2022-02-25 04:10:51 -08:00
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for DepositInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::Deposit;
|
|
|
|
type Instruction = mango_v4::instruction::Deposit;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
account_loader: impl ClientAccountLoader + 'async_trait,
|
2022-02-26 08:47:16 -08:00
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
2022-02-25 04:10:51 -08:00
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {
|
|
|
|
amount: self.amount,
|
|
|
|
};
|
|
|
|
|
2022-02-25 06:14:15 -08:00
|
|
|
// load account so we know its mint
|
|
|
|
let token_account: TokenAccount = account_loader.load(&self.token_account).await.unwrap();
|
2022-02-28 06:42:14 -08:00
|
|
|
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
2022-03-14 05:19:50 -07:00
|
|
|
let mint_info = Pubkey::find_program_address(
|
2022-02-25 04:10:51 -08:00
|
|
|
&[
|
2022-02-28 06:42:14 -08:00
|
|
|
account.group.as_ref(),
|
2022-03-14 05:19:50 -07:00
|
|
|
b"MintInfo".as_ref(),
|
2022-02-25 06:14:15 -08:00
|
|
|
token_account.mint.as_ref(),
|
2022-02-25 04:10:51 -08:00
|
|
|
],
|
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
2022-03-14 05:19:50 -07:00
|
|
|
let mint_info: MintInfo = account_loader.load(&mint_info).await.unwrap();
|
2022-02-25 04:10:51 -08:00
|
|
|
|
2022-03-07 06:43:29 -08:00
|
|
|
let health_check_metas = derive_health_check_remaining_account_metas(
|
|
|
|
&account_loader,
|
|
|
|
&account,
|
2022-03-14 05:19:50 -07:00
|
|
|
Some(mint_info.bank),
|
2022-03-07 06:43:29 -08:00
|
|
|
false,
|
|
|
|
)
|
|
|
|
.await;
|
2022-03-05 09:03:57 -08:00
|
|
|
|
2022-02-25 04:10:51 -08:00
|
|
|
let accounts = Self::Accounts {
|
2022-02-28 06:42:14 -08:00
|
|
|
group: account.group,
|
2022-02-25 04:10:51 -08:00
|
|
|
account: self.account,
|
2022-03-14 05:19:50 -07:00
|
|
|
bank: mint_info.bank,
|
|
|
|
vault: mint_info.vault,
|
2022-02-25 06:14:15 -08:00
|
|
|
token_account: self.token_account,
|
|
|
|
token_authority: self.token_authority.pubkey(),
|
2022-02-25 04:10:51 -08:00
|
|
|
token_program: Token::id(),
|
|
|
|
};
|
|
|
|
|
2022-03-05 09:03:57 -08:00
|
|
|
let mut instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
instruction.accounts.extend(health_check_metas.into_iter());
|
|
|
|
|
2022-02-26 08:47:16 -08:00
|
|
|
(accounts, instruction)
|
2022-02-25 04:10:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
2022-02-25 06:14:15 -08:00
|
|
|
vec![self.token_authority]
|
2022-02-25 04:10:51 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct RegisterTokenInstruction<'keypair> {
|
2022-03-14 05:19:50 -07:00
|
|
|
pub token_index: TokenIndex,
|
2022-02-25 04:10:51 -08:00
|
|
|
pub decimals: u8,
|
2022-04-09 07:53:30 -07:00
|
|
|
pub util0: f32,
|
|
|
|
pub rate0: f32,
|
|
|
|
pub util1: f32,
|
|
|
|
pub rate1: f32,
|
|
|
|
pub max_rate: f32,
|
2022-05-09 02:14:50 -07:00
|
|
|
pub loan_origination_fee_rate: f32,
|
|
|
|
pub loan_fee_rate: f32,
|
2022-02-25 09:29:54 -08:00
|
|
|
pub maint_asset_weight: f32,
|
|
|
|
pub init_asset_weight: f32,
|
|
|
|
pub maint_liab_weight: f32,
|
|
|
|
pub init_liab_weight: f32,
|
2022-03-26 11:34:44 -07:00
|
|
|
pub liquidation_fee: f32,
|
2022-02-25 04:10:51 -08:00
|
|
|
|
|
|
|
pub group: Pubkey,
|
|
|
|
pub admin: &'keypair Keypair,
|
|
|
|
pub mint: Pubkey,
|
2022-03-03 05:30:44 -08:00
|
|
|
pub address_lookup_table: Pubkey,
|
2022-02-25 04:10:51 -08:00
|
|
|
pub payer: &'keypair Keypair,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for RegisterTokenInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::RegisterToken;
|
|
|
|
type Instruction = mango_v4::instruction::RegisterToken;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_account_loader: impl ClientAccountLoader + 'async_trait,
|
2022-02-26 08:47:16 -08:00
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
2022-02-25 04:10:51 -08:00
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {
|
2022-04-12 07:19:58 -07:00
|
|
|
name: "some_ticker".to_string(),
|
2022-03-14 05:19:50 -07:00
|
|
|
token_index: self.token_index,
|
2022-04-12 08:28:47 -07:00
|
|
|
interest_rate_params: InterestRateParams {
|
|
|
|
util0: self.util0,
|
|
|
|
rate0: self.rate0,
|
|
|
|
util1: self.util1,
|
|
|
|
rate1: self.rate1,
|
|
|
|
max_rate: self.max_rate,
|
|
|
|
},
|
2022-05-09 02:14:50 -07:00
|
|
|
loan_fee_rate: self.loan_fee_rate,
|
|
|
|
loan_origination_fee_rate: self.loan_origination_fee_rate,
|
2022-02-25 09:29:54 -08:00
|
|
|
maint_asset_weight: self.maint_asset_weight,
|
|
|
|
init_asset_weight: self.init_asset_weight,
|
|
|
|
maint_liab_weight: self.maint_liab_weight,
|
|
|
|
init_liab_weight: self.init_liab_weight,
|
2022-03-26 11:34:44 -07:00
|
|
|
liquidation_fee: self.liquidation_fee,
|
2022-02-25 04:10:51 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
let bank = Pubkey::find_program_address(
|
|
|
|
&[
|
|
|
|
self.group.as_ref(),
|
2022-03-14 05:39:54 -07:00
|
|
|
b"Bank".as_ref(),
|
2022-03-14 05:19:50 -07:00
|
|
|
&self.token_index.to_le_bytes(),
|
2022-02-25 04:10:51 -08:00
|
|
|
],
|
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
|
|
|
let vault = Pubkey::find_program_address(
|
|
|
|
&[
|
|
|
|
self.group.as_ref(),
|
2022-03-14 05:39:54 -07:00
|
|
|
b"Vault".as_ref(),
|
2022-03-14 05:19:50 -07:00
|
|
|
&self.token_index.to_le_bytes(),
|
2022-02-25 04:10:51 -08:00
|
|
|
],
|
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
2022-03-03 05:30:44 -08:00
|
|
|
let mint_info = Pubkey::find_program_address(
|
|
|
|
&[
|
|
|
|
self.group.as_ref(),
|
2022-03-11 11:10:15 -08:00
|
|
|
b"MintInfo".as_ref(),
|
2022-03-03 05:30:44 -08:00
|
|
|
self.mint.as_ref(),
|
|
|
|
],
|
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
2022-04-02 12:04:00 -07:00
|
|
|
// TODO: remove copy pasta of pda derivation, use reference
|
2022-02-28 05:48:59 -08:00
|
|
|
let oracle = Pubkey::find_program_address(
|
2022-04-02 12:02:48 -07:00
|
|
|
&[
|
|
|
|
self.group.as_ref(),
|
|
|
|
b"StubOracle".as_ref(),
|
|
|
|
self.mint.as_ref(),
|
|
|
|
],
|
2022-02-28 05:48:59 -08:00
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
2022-02-25 04:10:51 -08:00
|
|
|
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: self.group,
|
|
|
|
admin: self.admin.pubkey(),
|
|
|
|
mint: self.mint,
|
|
|
|
bank,
|
|
|
|
vault,
|
2022-03-03 05:30:44 -08:00
|
|
|
mint_info,
|
2022-02-28 05:48:59 -08:00
|
|
|
oracle,
|
2022-03-31 00:25:47 -07:00
|
|
|
// TODO: ALTs are unavailable
|
|
|
|
//address_lookup_table: self.address_lookup_table,
|
2022-02-25 04:10:51 -08:00
|
|
|
payer: self.payer.pubkey(),
|
|
|
|
token_program: Token::id(),
|
|
|
|
system_program: System::id(),
|
2022-03-31 00:25:47 -07:00
|
|
|
// TODO: ALTs are unavailable
|
|
|
|
//address_lookup_table_program: mango_v4::address_lookup_table::id(),
|
2022-02-25 04:10:51 -08:00
|
|
|
rent: sysvar::rent::Rent::id(),
|
|
|
|
};
|
|
|
|
|
2022-02-26 08:47:16 -08:00
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
2022-02-25 04:10:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.admin, self.payer]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-28 08:17:01 -08:00
|
|
|
pub struct SetStubOracle<'keypair> {
|
|
|
|
pub mint: Pubkey,
|
2022-04-02 11:42:17 -07:00
|
|
|
pub group: Pubkey,
|
|
|
|
pub admin: &'keypair Keypair,
|
2022-02-28 08:17:01 -08:00
|
|
|
pub payer: &'keypair Keypair,
|
2022-02-28 21:28:12 -08:00
|
|
|
pub price: &'static str,
|
2022-02-28 08:17:01 -08:00
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for SetStubOracle<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::SetStubOracle;
|
|
|
|
type Instruction = mango_v4::instruction::SetStubOracle;
|
|
|
|
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
2022-03-01 04:49:59 -08:00
|
|
|
_loader: impl ClientAccountLoader + 'async_trait,
|
2022-02-28 08:17:01 -08:00
|
|
|
) -> (Self::Accounts, Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {
|
2022-02-28 21:28:12 -08:00
|
|
|
price: I80F48::from_str(self.price).unwrap(),
|
2022-02-28 08:17:01 -08:00
|
|
|
};
|
2022-04-02 12:04:00 -07:00
|
|
|
// TODO: remove copy pasta of pda derivation, use reference
|
2022-02-28 08:17:01 -08:00
|
|
|
let oracle = Pubkey::find_program_address(
|
2022-04-02 11:42:17 -07:00
|
|
|
&[
|
|
|
|
self.group.as_ref(),
|
|
|
|
b"StubOracle".as_ref(),
|
|
|
|
self.mint.as_ref(),
|
|
|
|
],
|
2022-02-28 08:17:01 -08:00
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
|
|
|
|
2022-04-02 11:42:17 -07:00
|
|
|
let accounts = Self::Accounts {
|
|
|
|
oracle,
|
|
|
|
group: self.group,
|
|
|
|
admin: self.admin.pubkey(),
|
|
|
|
payer: self.payer.pubkey(),
|
|
|
|
};
|
2022-02-28 08:17:01 -08:00
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
2022-04-02 11:42:17 -07:00
|
|
|
vec![self.payer, self.admin]
|
2022-02-28 08:17:01 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct CreateStubOracle<'keypair> {
|
2022-04-02 11:42:17 -07:00
|
|
|
pub group: Pubkey,
|
2022-02-28 08:17:01 -08:00
|
|
|
pub mint: Pubkey,
|
2022-04-02 11:42:17 -07:00
|
|
|
pub admin: &'keypair Keypair,
|
2022-02-28 08:17:01 -08:00
|
|
|
pub payer: &'keypair Keypair,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for CreateStubOracle<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::CreateStubOracle;
|
|
|
|
type Instruction = mango_v4::instruction::CreateStubOracle;
|
|
|
|
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
2022-03-01 04:49:59 -08:00
|
|
|
_loader: impl ClientAccountLoader + 'async_trait,
|
2022-02-28 08:17:01 -08:00
|
|
|
) -> (Self::Accounts, Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {
|
|
|
|
price: I80F48::from_num(1.0),
|
|
|
|
};
|
|
|
|
|
|
|
|
let oracle = Pubkey::find_program_address(
|
2022-04-02 11:42:17 -07:00
|
|
|
&[
|
|
|
|
self.group.as_ref(),
|
|
|
|
b"StubOracle".as_ref(),
|
|
|
|
self.mint.as_ref(),
|
|
|
|
],
|
2022-02-28 08:17:01 -08:00
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
|
|
|
|
|
|
|
let accounts = Self::Accounts {
|
2022-04-02 11:42:17 -07:00
|
|
|
group: self.group,
|
2022-02-28 08:17:01 -08:00
|
|
|
oracle,
|
|
|
|
token_mint: self.mint,
|
2022-04-02 11:42:17 -07:00
|
|
|
admin: self.admin.pubkey(),
|
2022-02-28 08:17:01 -08:00
|
|
|
payer: self.payer.pubkey(),
|
|
|
|
system_program: System::id(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
2022-04-02 11:42:17 -07:00
|
|
|
vec![self.payer, self.admin]
|
2022-02-28 08:17:01 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-25 04:10:51 -08:00
|
|
|
pub struct CreateGroupInstruction<'keypair> {
|
|
|
|
pub admin: &'keypair Keypair,
|
|
|
|
pub payer: &'keypair Keypair,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for CreateGroupInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::CreateGroup;
|
|
|
|
type Instruction = mango_v4::instruction::CreateGroup;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_account_loader: impl ClientAccountLoader + 'async_trait,
|
2022-02-26 08:47:16 -08:00
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
2022-02-25 04:10:51 -08:00
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {};
|
|
|
|
|
|
|
|
let group = Pubkey::find_program_address(
|
2022-03-14 05:39:54 -07:00
|
|
|
&[b"Group".as_ref(), self.admin.pubkey().as_ref()],
|
2022-02-25 04:10:51 -08:00
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
|
|
|
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group,
|
|
|
|
admin: self.admin.pubkey(),
|
|
|
|
payer: self.payer.pubkey(),
|
|
|
|
system_program: System::id(),
|
|
|
|
};
|
|
|
|
|
2022-02-26 08:47:16 -08:00
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
2022-02-25 04:10:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.admin, self.payer]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct CreateAccountInstruction<'keypair> {
|
|
|
|
pub account_num: u8,
|
|
|
|
|
|
|
|
pub group: Pubkey,
|
|
|
|
pub owner: &'keypair Keypair,
|
|
|
|
pub payer: &'keypair Keypair,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for CreateAccountInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::CreateAccount;
|
|
|
|
type Instruction = mango_v4::instruction::CreateAccount;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_account_loader: impl ClientAccountLoader + 'async_trait,
|
2022-02-26 08:47:16 -08:00
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
2022-02-25 04:10:51 -08:00
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = mango_v4::instruction::CreateAccount {
|
|
|
|
account_num: self.account_num,
|
2022-04-12 07:19:58 -07:00
|
|
|
name: "my_mango_account".to_string(),
|
2022-02-25 04:10:51 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
let account = Pubkey::find_program_address(
|
|
|
|
&[
|
|
|
|
self.group.as_ref(),
|
2022-03-14 05:39:54 -07:00
|
|
|
b"MangoAccount".as_ref(),
|
2022-02-25 04:10:51 -08:00
|
|
|
self.owner.pubkey().as_ref(),
|
|
|
|
&self.account_num.to_le_bytes(),
|
|
|
|
],
|
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
|
|
|
|
|
|
|
let accounts = mango_v4::accounts::CreateAccount {
|
|
|
|
group: self.group,
|
|
|
|
owner: self.owner.pubkey(),
|
|
|
|
account,
|
|
|
|
payer: self.payer.pubkey(),
|
|
|
|
system_program: System::id(),
|
|
|
|
};
|
|
|
|
|
2022-02-26 08:47:16 -08:00
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
2022-02-25 04:10:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.owner, self.payer]
|
|
|
|
}
|
|
|
|
}
|
2022-03-11 03:59:42 -08:00
|
|
|
|
2022-03-31 08:22:56 -07:00
|
|
|
pub struct CloseAccountInstruction<'keypair> {
|
|
|
|
pub account: Pubkey,
|
|
|
|
pub owner: &'keypair Keypair,
|
|
|
|
pub sol_destination: Pubkey,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for CloseAccountInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::CloseAccount;
|
|
|
|
type Instruction = mango_v4::instruction::CloseAccount;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_account_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {};
|
|
|
|
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
owner: self.owner.pubkey(),
|
|
|
|
account: self.account,
|
|
|
|
sol_destination: self.sol_destination,
|
|
|
|
token_program: Token::id(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.owner]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-18 05:42:20 -07:00
|
|
|
pub struct Serum3RegisterMarketInstruction<'keypair> {
|
2022-03-11 03:59:42 -08:00
|
|
|
pub group: Pubkey,
|
|
|
|
pub admin: &'keypair Keypair,
|
|
|
|
pub payer: &'keypair Keypair,
|
|
|
|
|
|
|
|
pub serum_program: Pubkey,
|
|
|
|
pub serum_market_external: Pubkey,
|
|
|
|
|
2022-03-30 03:24:07 -07:00
|
|
|
pub base_bank: Pubkey,
|
|
|
|
pub quote_bank: Pubkey,
|
|
|
|
|
2022-03-18 05:42:20 -07:00
|
|
|
pub market_index: Serum3MarketIndex,
|
2022-03-11 03:59:42 -08:00
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
2022-03-18 05:42:20 -07:00
|
|
|
impl<'keypair> ClientInstruction for Serum3RegisterMarketInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::Serum3RegisterMarket;
|
|
|
|
type Instruction = mango_v4::instruction::Serum3RegisterMarket;
|
2022-03-11 03:59:42 -08:00
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_account_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {
|
2022-03-14 05:47:34 -07:00
|
|
|
market_index: self.market_index,
|
2022-04-12 11:38:35 -07:00
|
|
|
name: "UUU/usdc".to_string(),
|
2022-03-11 03:59:42 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
let serum_market = Pubkey::find_program_address(
|
|
|
|
&[
|
|
|
|
self.group.as_ref(),
|
2022-03-18 05:42:20 -07:00
|
|
|
b"Serum3Market".as_ref(),
|
2022-03-11 03:59:42 -08:00
|
|
|
self.serum_market_external.as_ref(),
|
|
|
|
],
|
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
|
|
|
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: self.group,
|
|
|
|
admin: self.admin.pubkey(),
|
|
|
|
serum_program: self.serum_program,
|
|
|
|
serum_market_external: self.serum_market_external,
|
|
|
|
serum_market,
|
2022-03-30 03:24:07 -07:00
|
|
|
base_bank: self.base_bank,
|
|
|
|
quote_bank: self.quote_bank,
|
2022-03-11 03:59:42 -08:00
|
|
|
payer: self.payer.pubkey(),
|
|
|
|
system_program: System::id(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.admin, self.payer]
|
|
|
|
}
|
|
|
|
}
|
2022-03-11 05:26:42 -08:00
|
|
|
|
2022-03-18 05:42:20 -07:00
|
|
|
pub struct Serum3CreateOpenOrdersInstruction<'keypair> {
|
2022-03-11 05:26:42 -08:00
|
|
|
pub account: Pubkey,
|
|
|
|
pub serum_market: Pubkey,
|
|
|
|
pub owner: &'keypair Keypair,
|
|
|
|
pub payer: &'keypair Keypair,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
2022-03-18 05:42:20 -07:00
|
|
|
impl<'keypair> ClientInstruction for Serum3CreateOpenOrdersInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::Serum3CreateOpenOrders;
|
|
|
|
type Instruction = mango_v4::instruction::Serum3CreateOpenOrders;
|
2022-03-11 05:26:42 -08:00
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
account_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {};
|
|
|
|
|
|
|
|
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
2022-03-18 05:42:20 -07:00
|
|
|
let serum_market: Serum3Market = account_loader.load(&self.serum_market).await.unwrap();
|
2022-03-11 05:26:42 -08:00
|
|
|
let open_orders = Pubkey::find_program_address(
|
|
|
|
&[
|
|
|
|
self.account.as_ref(),
|
2022-03-18 05:42:20 -07:00
|
|
|
b"Serum3OO".as_ref(),
|
2022-03-11 05:26:42 -08:00
|
|
|
self.serum_market.as_ref(),
|
|
|
|
],
|
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
|
|
|
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: account.group,
|
|
|
|
account: self.account,
|
|
|
|
serum_market: self.serum_market,
|
|
|
|
serum_program: serum_market.serum_program,
|
|
|
|
serum_market_external: serum_market.serum_market_external,
|
|
|
|
open_orders,
|
|
|
|
owner: self.owner.pubkey(),
|
|
|
|
payer: self.payer.pubkey(),
|
|
|
|
system_program: System::id(),
|
2022-03-11 06:28:27 -08:00
|
|
|
rent: sysvar::rent::Rent::id(),
|
2022-03-11 05:26:42 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.owner, self.payer]
|
|
|
|
}
|
|
|
|
}
|
2022-03-14 05:19:50 -07:00
|
|
|
|
2022-03-18 05:42:20 -07:00
|
|
|
pub struct Serum3PlaceOrderInstruction<'keypair> {
|
2022-04-01 23:59:07 -07:00
|
|
|
pub side: Serum3Side,
|
2022-03-14 09:21:16 -07:00
|
|
|
pub limit_price: u64,
|
|
|
|
pub max_base_qty: u64,
|
|
|
|
pub max_native_quote_qty_including_fees: u64,
|
2022-04-01 23:59:07 -07:00
|
|
|
pub self_trade_behavior: Serum3SelfTradeBehavior,
|
|
|
|
pub order_type: Serum3OrderType,
|
2022-03-14 09:21:16 -07:00
|
|
|
pub client_order_id: u64,
|
|
|
|
pub limit: u16,
|
|
|
|
|
2022-03-14 05:19:50 -07:00
|
|
|
pub account: Pubkey,
|
|
|
|
pub owner: &'keypair Keypair,
|
2022-03-14 09:21:16 -07:00
|
|
|
|
|
|
|
pub serum_market: Pubkey,
|
2022-03-14 05:19:50 -07:00
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
2022-03-18 05:42:20 -07:00
|
|
|
impl<'keypair> ClientInstruction for Serum3PlaceOrderInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::Serum3PlaceOrder;
|
|
|
|
type Instruction = mango_v4::instruction::Serum3PlaceOrder;
|
2022-03-14 05:19:50 -07:00
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
account_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
2022-03-14 09:21:16 -07:00
|
|
|
let instruction = Self::Instruction {
|
2022-04-01 23:59:07 -07:00
|
|
|
side: self.side,
|
|
|
|
limit_price: self.limit_price,
|
|
|
|
max_base_qty: self.max_base_qty,
|
|
|
|
max_native_quote_qty_including_fees: self.max_native_quote_qty_including_fees,
|
|
|
|
self_trade_behavior: self.self_trade_behavior,
|
|
|
|
order_type: self.order_type,
|
|
|
|
client_order_id: self.client_order_id,
|
|
|
|
limit: self.limit,
|
2022-03-14 09:21:16 -07:00
|
|
|
};
|
2022-03-14 05:19:50 -07:00
|
|
|
|
|
|
|
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
2022-03-18 05:42:20 -07:00
|
|
|
let serum_market: Serum3Market = account_loader.load(&self.serum_market).await.unwrap();
|
2022-03-14 09:21:16 -07:00
|
|
|
let open_orders = account
|
2022-04-02 02:21:41 -07:00
|
|
|
.serum3
|
2022-03-14 09:21:16 -07:00
|
|
|
.find(serum_market.market_index)
|
|
|
|
.unwrap()
|
|
|
|
.open_orders;
|
|
|
|
let quote_info =
|
|
|
|
get_mint_info_by_token_index(&account_loader, &account, serum_market.quote_token_index)
|
|
|
|
.await;
|
|
|
|
let base_info =
|
|
|
|
get_mint_info_by_token_index(&account_loader, &account, serum_market.base_token_index)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
let market_external_bytes = account_loader
|
|
|
|
.load_bytes(&serum_market.serum_market_external)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
let market_external: &serum_dex::state::MarketState = bytemuck::from_bytes(
|
|
|
|
&market_external_bytes[5..5 + std::mem::size_of::<serum_dex::state::MarketState>()],
|
|
|
|
);
|
|
|
|
// unpack the data, to avoid unaligned references
|
|
|
|
let bids = market_external.bids;
|
|
|
|
let asks = market_external.asks;
|
|
|
|
let event_q = market_external.event_q;
|
|
|
|
let req_q = market_external.req_q;
|
|
|
|
let coin_vault = market_external.coin_vault;
|
|
|
|
let pc_vault = market_external.pc_vault;
|
2022-03-18 02:38:38 -07:00
|
|
|
let vault_signer = serum_dex::state::gen_vault_signer_key(
|
|
|
|
market_external.vault_signer_nonce,
|
|
|
|
&serum_market.serum_market_external,
|
|
|
|
&serum_market.serum_program,
|
|
|
|
)
|
|
|
|
.unwrap();
|
2022-03-14 09:21:16 -07:00
|
|
|
|
|
|
|
let health_check_metas =
|
|
|
|
derive_health_check_remaining_account_metas(&account_loader, &account, None, false)
|
|
|
|
.await;
|
2022-03-14 05:19:50 -07:00
|
|
|
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: account.group,
|
|
|
|
account: self.account,
|
|
|
|
open_orders,
|
2022-03-14 09:21:16 -07:00
|
|
|
quote_bank: quote_info.bank,
|
|
|
|
quote_vault: quote_info.vault,
|
|
|
|
base_bank: base_info.bank,
|
|
|
|
base_vault: base_info.vault,
|
2022-03-14 05:19:50 -07:00
|
|
|
serum_market: self.serum_market,
|
|
|
|
serum_program: serum_market.serum_program,
|
|
|
|
serum_market_external: serum_market.serum_market_external,
|
2022-03-14 09:21:16 -07:00
|
|
|
market_bids: from_serum_style_pubkey(&bids),
|
|
|
|
market_asks: from_serum_style_pubkey(&asks),
|
|
|
|
market_event_queue: from_serum_style_pubkey(&event_q),
|
|
|
|
market_request_queue: from_serum_style_pubkey(&req_q),
|
|
|
|
market_base_vault: from_serum_style_pubkey(&coin_vault),
|
|
|
|
market_quote_vault: from_serum_style_pubkey(&pc_vault),
|
2022-03-18 02:38:38 -07:00
|
|
|
market_vault_signer: vault_signer,
|
2022-03-14 05:19:50 -07:00
|
|
|
owner: self.owner.pubkey(),
|
2022-03-14 09:21:16 -07:00
|
|
|
token_program: Token::id(),
|
2022-03-18 07:58:39 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
let mut instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
instruction.accounts.extend(health_check_metas.into_iter());
|
|
|
|
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.owner]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-19 04:11:56 -07:00
|
|
|
pub struct Serum3CancelOrderInstruction<'keypair> {
|
2022-04-01 23:59:07 -07:00
|
|
|
pub side: Serum3Side,
|
2022-03-19 04:11:56 -07:00
|
|
|
pub order_id: u128,
|
|
|
|
|
|
|
|
pub account: Pubkey,
|
|
|
|
pub owner: &'keypair Keypair,
|
|
|
|
|
|
|
|
pub serum_market: Pubkey,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for Serum3CancelOrderInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::Serum3CancelOrder;
|
|
|
|
type Instruction = mango_v4::instruction::Serum3CancelOrder;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
account_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {
|
2022-04-01 23:59:07 -07:00
|
|
|
side: self.side,
|
|
|
|
order_id: self.order_id,
|
2022-03-19 04:11:56 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
|
|
|
let serum_market: Serum3Market = account_loader.load(&self.serum_market).await.unwrap();
|
|
|
|
let open_orders = account
|
2022-04-02 02:21:41 -07:00
|
|
|
.serum3
|
2022-03-19 04:11:56 -07:00
|
|
|
.find(serum_market.market_index)
|
|
|
|
.unwrap()
|
|
|
|
.open_orders;
|
|
|
|
|
|
|
|
let market_external_bytes = account_loader
|
|
|
|
.load_bytes(&serum_market.serum_market_external)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
let market_external: &serum_dex::state::MarketState = bytemuck::from_bytes(
|
|
|
|
&market_external_bytes[5..5 + std::mem::size_of::<serum_dex::state::MarketState>()],
|
|
|
|
);
|
|
|
|
// unpack the data, to avoid unaligned references
|
|
|
|
let bids = market_external.bids;
|
|
|
|
let asks = market_external.asks;
|
|
|
|
let event_q = market_external.event_q;
|
|
|
|
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: account.group,
|
|
|
|
account: self.account,
|
|
|
|
open_orders,
|
|
|
|
serum_market: self.serum_market,
|
|
|
|
serum_program: serum_market.serum_program,
|
|
|
|
serum_market_external: serum_market.serum_market_external,
|
|
|
|
market_bids: from_serum_style_pubkey(&bids),
|
|
|
|
market_asks: from_serum_style_pubkey(&asks),
|
|
|
|
market_event_queue: from_serum_style_pubkey(&event_q),
|
|
|
|
owner: self.owner.pubkey(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.owner]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-18 07:58:39 -07:00
|
|
|
pub struct Serum3SettleFundsInstruction<'keypair> {
|
|
|
|
pub account: Pubkey,
|
|
|
|
pub owner: &'keypair Keypair,
|
|
|
|
|
|
|
|
pub serum_market: Pubkey,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for Serum3SettleFundsInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::Serum3SettleFunds;
|
|
|
|
type Instruction = mango_v4::instruction::Serum3SettleFunds;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
account_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {};
|
|
|
|
|
|
|
|
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
|
|
|
let serum_market: Serum3Market = account_loader.load(&self.serum_market).await.unwrap();
|
|
|
|
let open_orders = account
|
2022-04-02 02:21:41 -07:00
|
|
|
.serum3
|
2022-03-18 07:58:39 -07:00
|
|
|
.find(serum_market.market_index)
|
|
|
|
.unwrap()
|
|
|
|
.open_orders;
|
|
|
|
let quote_info =
|
|
|
|
get_mint_info_by_token_index(&account_loader, &account, serum_market.quote_token_index)
|
|
|
|
.await;
|
|
|
|
let base_info =
|
|
|
|
get_mint_info_by_token_index(&account_loader, &account, serum_market.base_token_index)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
let market_external_bytes = account_loader
|
|
|
|
.load_bytes(&serum_market.serum_market_external)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
let market_external: &serum_dex::state::MarketState = bytemuck::from_bytes(
|
|
|
|
&market_external_bytes[5..5 + std::mem::size_of::<serum_dex::state::MarketState>()],
|
|
|
|
);
|
|
|
|
// unpack the data, to avoid unaligned references
|
|
|
|
let coin_vault = market_external.coin_vault;
|
|
|
|
let pc_vault = market_external.pc_vault;
|
|
|
|
let vault_signer = serum_dex::state::gen_vault_signer_key(
|
|
|
|
market_external.vault_signer_nonce,
|
|
|
|
&serum_market.serum_market_external,
|
|
|
|
&serum_market.serum_program,
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: account.group,
|
|
|
|
account: self.account,
|
|
|
|
open_orders,
|
|
|
|
quote_bank: quote_info.bank,
|
|
|
|
quote_vault: quote_info.vault,
|
|
|
|
base_bank: base_info.bank,
|
|
|
|
base_vault: base_info.vault,
|
|
|
|
serum_market: self.serum_market,
|
|
|
|
serum_program: serum_market.serum_program,
|
|
|
|
serum_market_external: serum_market.serum_market_external,
|
|
|
|
market_base_vault: from_serum_style_pubkey(&coin_vault),
|
|
|
|
market_quote_vault: from_serum_style_pubkey(&pc_vault),
|
|
|
|
market_vault_signer: vault_signer,
|
|
|
|
owner: self.owner.pubkey(),
|
|
|
|
token_program: Token::id(),
|
2022-03-14 05:19:50 -07:00
|
|
|
};
|
|
|
|
|
2022-03-19 01:05:42 -07:00
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
2022-03-14 05:19:50 -07:00
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.owner]
|
|
|
|
}
|
2022-03-14 09:21:16 -07:00
|
|
|
}
|
2022-03-19 01:05:42 -07:00
|
|
|
|
2022-03-21 04:55:05 -07:00
|
|
|
pub struct Serum3LiqForceCancelOrdersInstruction {
|
|
|
|
pub account: Pubkey,
|
|
|
|
pub serum_market: Pubkey,
|
|
|
|
pub limit: u8,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl ClientInstruction for Serum3LiqForceCancelOrdersInstruction {
|
|
|
|
type Accounts = mango_v4::accounts::Serum3LiqForceCancelOrders;
|
|
|
|
type Instruction = mango_v4::instruction::Serum3LiqForceCancelOrders;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
account_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction { limit: self.limit };
|
|
|
|
|
|
|
|
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
|
|
|
let serum_market: Serum3Market = account_loader.load(&self.serum_market).await.unwrap();
|
|
|
|
let open_orders = account
|
2022-04-02 02:21:41 -07:00
|
|
|
.serum3
|
2022-03-21 04:55:05 -07:00
|
|
|
.find(serum_market.market_index)
|
|
|
|
.unwrap()
|
|
|
|
.open_orders;
|
|
|
|
let quote_info =
|
|
|
|
get_mint_info_by_token_index(&account_loader, &account, serum_market.quote_token_index)
|
|
|
|
.await;
|
|
|
|
let base_info =
|
|
|
|
get_mint_info_by_token_index(&account_loader, &account, serum_market.base_token_index)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
let market_external_bytes = account_loader
|
|
|
|
.load_bytes(&serum_market.serum_market_external)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
let market_external: &serum_dex::state::MarketState = bytemuck::from_bytes(
|
|
|
|
&market_external_bytes[5..5 + std::mem::size_of::<serum_dex::state::MarketState>()],
|
|
|
|
);
|
|
|
|
// unpack the data, to avoid unaligned references
|
|
|
|
let bids = market_external.bids;
|
|
|
|
let asks = market_external.asks;
|
|
|
|
let event_q = market_external.event_q;
|
|
|
|
let coin_vault = market_external.coin_vault;
|
|
|
|
let pc_vault = market_external.pc_vault;
|
|
|
|
let vault_signer = serum_dex::state::gen_vault_signer_key(
|
|
|
|
market_external.vault_signer_nonce,
|
|
|
|
&serum_market.serum_market_external,
|
|
|
|
&serum_market.serum_program,
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
2022-03-22 01:24:37 -07:00
|
|
|
let health_check_metas =
|
|
|
|
derive_health_check_remaining_account_metas(&account_loader, &account, None, false)
|
|
|
|
.await;
|
|
|
|
|
2022-03-21 04:55:05 -07:00
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: account.group,
|
|
|
|
account: self.account,
|
|
|
|
open_orders,
|
|
|
|
quote_bank: quote_info.bank,
|
|
|
|
quote_vault: quote_info.vault,
|
|
|
|
base_bank: base_info.bank,
|
|
|
|
base_vault: base_info.vault,
|
|
|
|
serum_market: self.serum_market,
|
|
|
|
serum_program: serum_market.serum_program,
|
|
|
|
serum_market_external: serum_market.serum_market_external,
|
|
|
|
market_bids: from_serum_style_pubkey(&bids),
|
|
|
|
market_asks: from_serum_style_pubkey(&asks),
|
|
|
|
market_event_queue: from_serum_style_pubkey(&event_q),
|
|
|
|
market_base_vault: from_serum_style_pubkey(&coin_vault),
|
|
|
|
market_quote_vault: from_serum_style_pubkey(&pc_vault),
|
|
|
|
market_vault_signer: vault_signer,
|
|
|
|
token_program: Token::id(),
|
|
|
|
};
|
|
|
|
|
2022-03-22 01:24:37 -07:00
|
|
|
let mut instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
instruction.accounts.extend(health_check_metas.into_iter());
|
|
|
|
|
2022-03-21 04:55:05 -07:00
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-29 02:49:26 -07:00
|
|
|
pub struct LiqTokenWithTokenInstruction<'keypair> {
|
|
|
|
pub liqee: Pubkey,
|
|
|
|
pub liqor: Pubkey,
|
|
|
|
pub liqor_owner: &'keypair Keypair,
|
|
|
|
|
|
|
|
pub asset_token_index: TokenIndex,
|
|
|
|
pub liab_token_index: TokenIndex,
|
|
|
|
pub max_liab_transfer: I80F48,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for LiqTokenWithTokenInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::LiqTokenWithToken;
|
|
|
|
type Instruction = mango_v4::instruction::LiqTokenWithToken;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
account_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {
|
|
|
|
asset_token_index: self.asset_token_index,
|
|
|
|
liab_token_index: self.liab_token_index,
|
|
|
|
max_liab_transfer: self.max_liab_transfer,
|
|
|
|
};
|
|
|
|
|
|
|
|
let liqee: MangoAccount = account_loader.load(&self.liqee).await.unwrap();
|
|
|
|
let liqor: MangoAccount = account_loader.load(&self.liqor).await.unwrap();
|
|
|
|
let health_check_metas = derive_liquidation_remaining_account_metas(
|
|
|
|
&account_loader,
|
|
|
|
&liqee,
|
|
|
|
&liqor,
|
|
|
|
self.asset_token_index,
|
|
|
|
self.liab_token_index,
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: liqee.group,
|
|
|
|
liqee: self.liqee,
|
|
|
|
liqor: self.liqor,
|
|
|
|
liqor_owner: self.liqor_owner.pubkey(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
instruction.accounts.extend(health_check_metas.into_iter());
|
|
|
|
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.liqor_owner]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-31 23:01:56 -07:00
|
|
|
pub struct PerpCreateMarketInstruction<'keypair> {
|
2022-03-18 02:08:53 -07:00
|
|
|
pub group: Pubkey,
|
|
|
|
pub admin: &'keypair Keypair,
|
2022-03-21 12:29:28 -07:00
|
|
|
pub oracle: Pubkey,
|
|
|
|
pub asks: Pubkey,
|
|
|
|
pub bids: Pubkey,
|
2022-03-22 23:53:45 -07:00
|
|
|
pub event_queue: Pubkey,
|
2022-03-18 02:08:53 -07:00
|
|
|
pub payer: &'keypair Keypair,
|
2022-03-18 23:28:37 -07:00
|
|
|
pub perp_market_index: PerpMarketIndex,
|
|
|
|
pub base_token_index: TokenIndex,
|
|
|
|
pub quote_token_index: TokenIndex,
|
2022-03-18 02:08:53 -07:00
|
|
|
pub quote_lot_size: i64,
|
|
|
|
pub base_lot_size: i64,
|
2022-03-24 11:15:46 -07:00
|
|
|
pub maint_asset_weight: f32,
|
|
|
|
pub init_asset_weight: f32,
|
|
|
|
pub maint_liab_weight: f32,
|
|
|
|
pub init_liab_weight: f32,
|
2022-03-24 09:29:30 -07:00
|
|
|
pub liquidation_fee: f32,
|
|
|
|
pub maker_fee: f32,
|
|
|
|
pub taker_fee: f32,
|
2022-03-18 02:08:53 -07:00
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
2022-03-31 23:01:56 -07:00
|
|
|
impl<'keypair> ClientInstruction for PerpCreateMarketInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::PerpCreateMarket;
|
|
|
|
type Instruction = mango_v4::instruction::PerpCreateMarket;
|
2022-03-18 02:08:53 -07:00
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {
|
2022-05-06 05:19:49 -07:00
|
|
|
name: "UUU-PERP".to_string(),
|
2022-03-18 23:28:37 -07:00
|
|
|
perp_market_index: self.perp_market_index,
|
|
|
|
base_token_index_opt: Option::from(self.base_token_index),
|
|
|
|
quote_token_index: self.quote_token_index,
|
2022-03-18 02:08:53 -07:00
|
|
|
quote_lot_size: self.quote_lot_size,
|
|
|
|
base_lot_size: self.base_lot_size,
|
2022-03-24 11:15:46 -07:00
|
|
|
maint_asset_weight: self.maint_asset_weight,
|
|
|
|
init_asset_weight: self.init_asset_weight,
|
|
|
|
maint_liab_weight: self.maint_liab_weight,
|
|
|
|
init_liab_weight: self.init_liab_weight,
|
2022-03-24 09:29:30 -07:00
|
|
|
liquidation_fee: self.liquidation_fee,
|
|
|
|
maker_fee: self.maker_fee,
|
|
|
|
taker_fee: self.taker_fee,
|
2022-05-17 01:07:24 -07:00
|
|
|
max_funding: 0.05,
|
|
|
|
min_funding: 0.05,
|
|
|
|
impact_quantity: 100,
|
2022-03-18 02:08:53 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
let perp_market = Pubkey::find_program_address(
|
2022-03-18 23:28:37 -07:00
|
|
|
&[
|
|
|
|
self.group.as_ref(),
|
|
|
|
b"PerpMarket".as_ref(),
|
|
|
|
self.perp_market_index.to_le_bytes().as_ref(),
|
|
|
|
],
|
2022-03-18 02:08:53 -07:00
|
|
|
&program_id,
|
|
|
|
)
|
|
|
|
.0;
|
|
|
|
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: self.group,
|
|
|
|
admin: self.admin.pubkey(),
|
2022-03-21 12:29:28 -07:00
|
|
|
oracle: self.oracle,
|
2022-03-18 02:08:53 -07:00
|
|
|
perp_market,
|
2022-03-21 12:29:28 -07:00
|
|
|
asks: self.asks,
|
|
|
|
bids: self.bids,
|
2022-03-22 23:53:45 -07:00
|
|
|
event_queue: self.event_queue,
|
2022-03-18 02:08:53 -07:00
|
|
|
payer: self.payer.pubkey(),
|
|
|
|
system_program: System::id(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.admin, self.payer]
|
|
|
|
}
|
|
|
|
}
|
2022-03-21 12:29:28 -07:00
|
|
|
|
2022-03-31 23:01:56 -07:00
|
|
|
pub struct PerpPlaceOrderInstruction<'keypair> {
|
2022-03-21 12:29:28 -07:00
|
|
|
pub group: Pubkey,
|
|
|
|
pub account: Pubkey,
|
|
|
|
pub perp_market: Pubkey,
|
|
|
|
pub asks: Pubkey,
|
|
|
|
pub bids: Pubkey,
|
2022-03-22 23:53:45 -07:00
|
|
|
pub event_queue: Pubkey,
|
2022-03-21 12:29:28 -07:00
|
|
|
pub oracle: Pubkey,
|
|
|
|
pub owner: &'keypair Keypair,
|
2022-03-26 09:27:50 -07:00
|
|
|
pub side: Side,
|
2022-04-01 06:47:12 -07:00
|
|
|
pub price_lots: i64,
|
|
|
|
pub max_base_lots: i64,
|
|
|
|
pub max_quote_lots: i64,
|
2022-05-16 01:34:22 -07:00
|
|
|
pub client_order_id: u64,
|
2022-03-21 12:29:28 -07:00
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
2022-03-31 23:01:56 -07:00
|
|
|
impl<'keypair> ClientInstruction for PerpPlaceOrderInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::PerpPlaceOrder;
|
|
|
|
type Instruction = mango_v4::instruction::PerpPlaceOrder;
|
2022-03-21 12:29:28 -07:00
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {
|
2022-03-26 09:27:50 -07:00
|
|
|
side: self.side,
|
2022-04-01 06:47:12 -07:00
|
|
|
price_lots: self.price_lots,
|
|
|
|
max_base_lots: self.max_base_lots,
|
|
|
|
max_quote_lots: self.max_quote_lots,
|
2022-05-16 01:34:22 -07:00
|
|
|
client_order_id: self.client_order_id,
|
2022-03-21 12:29:28 -07:00
|
|
|
order_type: OrderType::Limit,
|
|
|
|
expiry_timestamp: 0,
|
|
|
|
limit: 1,
|
|
|
|
};
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: self.group,
|
|
|
|
account: self.account,
|
|
|
|
perp_market: self.perp_market,
|
|
|
|
asks: self.asks,
|
|
|
|
bids: self.bids,
|
2022-03-22 23:53:45 -07:00
|
|
|
event_queue: self.event_queue,
|
2022-03-21 12:29:28 -07:00
|
|
|
oracle: self.oracle,
|
|
|
|
owner: self.owner.pubkey(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.owner]
|
|
|
|
}
|
|
|
|
}
|
2022-05-16 01:34:22 -07:00
|
|
|
|
|
|
|
pub struct PerpCancelOrderInstruction<'keypair> {
|
|
|
|
pub group: Pubkey,
|
|
|
|
pub account: Pubkey,
|
|
|
|
pub perp_market: Pubkey,
|
|
|
|
pub asks: Pubkey,
|
|
|
|
pub bids: Pubkey,
|
|
|
|
pub owner: &'keypair Keypair,
|
|
|
|
pub order_id: i128,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for PerpCancelOrderInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::PerpCancelOrder;
|
|
|
|
type Instruction = mango_v4::instruction::PerpCancelOrder;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {
|
|
|
|
order_id: self.order_id,
|
|
|
|
};
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: self.group,
|
|
|
|
account: self.account,
|
|
|
|
perp_market: self.perp_market,
|
|
|
|
asks: self.asks,
|
|
|
|
bids: self.bids,
|
|
|
|
owner: self.owner.pubkey(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.owner]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct PerpCancelOrderByClientOrderIdInstruction<'keypair> {
|
|
|
|
pub group: Pubkey,
|
|
|
|
pub account: Pubkey,
|
|
|
|
pub perp_market: Pubkey,
|
|
|
|
pub asks: Pubkey,
|
|
|
|
pub bids: Pubkey,
|
|
|
|
pub owner: &'keypair Keypair,
|
|
|
|
pub client_order_id: u64,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for PerpCancelOrderByClientOrderIdInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::PerpCancelOrderByClientOrderId;
|
|
|
|
type Instruction = mango_v4::instruction::PerpCancelOrderByClientOrderId;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {
|
|
|
|
client_order_id: self.client_order_id,
|
|
|
|
};
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: self.group,
|
|
|
|
account: self.account,
|
|
|
|
perp_market: self.perp_market,
|
|
|
|
asks: self.asks,
|
|
|
|
bids: self.bids,
|
|
|
|
owner: self.owner.pubkey(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.owner]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct PerpCancelAllOrdersInstruction<'keypair> {
|
|
|
|
pub group: Pubkey,
|
|
|
|
pub account: Pubkey,
|
|
|
|
pub perp_market: Pubkey,
|
|
|
|
pub asks: Pubkey,
|
|
|
|
pub bids: Pubkey,
|
|
|
|
pub owner: &'keypair Keypair,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl<'keypair> ClientInstruction for PerpCancelAllOrdersInstruction<'keypair> {
|
|
|
|
type Accounts = mango_v4::accounts::PerpCancelAllOrders;
|
|
|
|
type Instruction = mango_v4::instruction::PerpCancelAllOrders;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction { limit: 5 };
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: self.group,
|
|
|
|
account: self.account,
|
|
|
|
perp_market: self.perp_market,
|
|
|
|
asks: self.asks,
|
|
|
|
bids: self.bids,
|
|
|
|
owner: self.owner.pubkey(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![self.owner]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-05 01:25:32 -07:00
|
|
|
pub struct PerpConsumeEventsInstruction {
|
|
|
|
pub group: Pubkey,
|
|
|
|
pub perp_market: Pubkey,
|
|
|
|
pub event_queue: Pubkey,
|
|
|
|
pub mango_accounts: Vec<Pubkey>,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl ClientInstruction for PerpConsumeEventsInstruction {
|
|
|
|
type Accounts = mango_v4::accounts::PerpConsumeEvents;
|
|
|
|
type Instruction = mango_v4::instruction::PerpConsumeEvents;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction { limit: 10 };
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
group: self.group,
|
|
|
|
perp_market: self.perp_market,
|
|
|
|
event_queue: self.event_queue,
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
instruction
|
|
|
|
.accounts
|
|
|
|
.extend(self.mango_accounts.iter().map(|ma| AccountMeta {
|
|
|
|
pubkey: *ma,
|
|
|
|
is_signer: false,
|
|
|
|
is_writable: true,
|
|
|
|
}));
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-17 06:59:47 -07:00
|
|
|
pub struct PerpUpdateFundingInstruction {
|
|
|
|
pub perp_market: Pubkey,
|
|
|
|
pub bids: Pubkey,
|
|
|
|
pub asks: Pubkey,
|
|
|
|
pub oracle: Pubkey,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl ClientInstruction for PerpUpdateFundingInstruction {
|
|
|
|
type Accounts = mango_v4::accounts::PerpUpdateFunding;
|
|
|
|
type Instruction = mango_v4::instruction::PerpUpdateFunding;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {};
|
|
|
|
let accounts = Self::Accounts {
|
|
|
|
perp_market: self.perp_market,
|
|
|
|
bids: self.bids,
|
|
|
|
asks: self.asks,
|
|
|
|
oracle: self.oracle,
|
|
|
|
};
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-25 22:16:52 -07:00
|
|
|
pub struct BenchmarkInstruction {}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl ClientInstruction for BenchmarkInstruction {
|
|
|
|
type Accounts = mango_v4::accounts::Benchmark;
|
|
|
|
type Instruction = mango_v4::instruction::Benchmark;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {};
|
|
|
|
let accounts = Self::Accounts {};
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![]
|
|
|
|
}
|
|
|
|
}
|
2022-04-09 07:53:30 -07:00
|
|
|
pub struct UpdateIndexInstruction {
|
|
|
|
pub bank: Pubkey,
|
|
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl ClientInstruction for UpdateIndexInstruction {
|
|
|
|
type Accounts = mango_v4::accounts::UpdateIndex;
|
|
|
|
type Instruction = mango_v4::instruction::UpdateIndex;
|
|
|
|
async fn to_instruction(
|
|
|
|
&self,
|
|
|
|
_loader: impl ClientAccountLoader + 'async_trait,
|
|
|
|
) -> (Self::Accounts, instruction::Instruction) {
|
|
|
|
let program_id = mango_v4::id();
|
|
|
|
let instruction = Self::Instruction {};
|
|
|
|
let accounts = Self::Accounts { bank: self.bank };
|
|
|
|
|
|
|
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
|
|
|
(accounts, instruction)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn signers(&self) -> Vec<&Keypair> {
|
|
|
|
vec![]
|
|
|
|
}
|
|
|
|
}
|