edit tokens, perp markets, mango accounts, allow delegate to perform certain operations (#94)
Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
parent
dc4aee885b
commit
d74cc78a84
|
@ -9,6 +9,7 @@ pub struct CloseAccount<'info> {
|
||||||
|
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
|
// note: should never be the delegate
|
||||||
has_one = owner,
|
has_one = owner,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
close = sol_destination
|
close = sol_destination
|
||||||
|
|
|
@ -17,7 +17,6 @@ pub struct CreateAccount<'info> {
|
||||||
space = 8 + std::mem::size_of::<MangoAccount>(),
|
space = 8 + std::mem::size_of::<MangoAccount>(),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
|
|
||||||
pub owner: Signer<'info>,
|
pub owner: Signer<'info>,
|
||||||
|
|
||||||
#[account(mut)]
|
#[account(mut)]
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
use crate::error::MangoError;
|
||||||
|
use anchor_lang::prelude::*;
|
||||||
|
|
||||||
|
use crate::state::*;
|
||||||
|
use crate::util::fill32_from_str;
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
pub struct EditAccount<'info> {
|
||||||
|
pub group: AccountLoader<'info, Group>,
|
||||||
|
|
||||||
|
#[account(
|
||||||
|
mut,
|
||||||
|
// Note: should never be the delegate
|
||||||
|
has_one = owner,
|
||||||
|
has_one = group,
|
||||||
|
)]
|
||||||
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
|
pub owner: Signer<'info>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn edit_account(
|
||||||
|
ctx: Context<EditAccount>,
|
||||||
|
name_opt: Option<String>,
|
||||||
|
// note: can also be used to unset by using the default pubkey here as a param
|
||||||
|
delegate_opt: Option<Pubkey>,
|
||||||
|
) -> Result<()> {
|
||||||
|
require!(
|
||||||
|
name_opt.is_some() || delegate_opt.is_some(),
|
||||||
|
MangoError::SomeError
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut account = ctx.accounts.account.load_mut()?;
|
||||||
|
|
||||||
|
// msg!("old account {:#?}", account);
|
||||||
|
|
||||||
|
// note: unchanged fields are inline, and match exact definition in create_account
|
||||||
|
// please maintain, and don't remove, makes it easy to reason about which support modification by owner
|
||||||
|
|
||||||
|
if let Some(name) = name_opt {
|
||||||
|
account.name = fill32_from_str(name)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unchanged -
|
||||||
|
// owner
|
||||||
|
// account_num
|
||||||
|
// bump
|
||||||
|
|
||||||
|
if let Some(delegate) = delegate_opt {
|
||||||
|
account.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unchanged -
|
||||||
|
// tokens
|
||||||
|
// serum3
|
||||||
|
// perps
|
||||||
|
// being_liquidated
|
||||||
|
// is_bankrupt
|
||||||
|
|
||||||
|
// msg!("new account {:#?}", account);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ pub struct FlashLoan<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,12 @@ pub struct FlashLoan2End<'info> {
|
||||||
pub group: AccountLoader<'info, Group>,
|
pub group: AccountLoader<'info, Group>,
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = owner,
|
|
||||||
has_one = group,
|
has_one = group,
|
||||||
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
pub owner: Signer<'info>,
|
pub owner: Signer<'info>,
|
||||||
|
|
||||||
pub token_program: Program<'info, Token>,
|
pub token_program: Program<'info, Token>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,10 +40,11 @@ pub struct FlashLoan3Begin<'info> {
|
||||||
pub struct FlashLoan3End<'info> {
|
pub struct FlashLoan3End<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
pub owner: Signer<'info>,
|
pub owner: Signer<'info>,
|
||||||
|
|
||||||
pub token_program: Program<'info, Token>,
|
pub token_program: Program<'info, Token>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@ pub struct LiqTokenWithToken<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
|
constraint = liqor.load()?.owner == liqor_owner.key() || liqor.load()?.delegate == liqor_owner.key(),
|
||||||
)]
|
)]
|
||||||
pub liqor: AccountLoader<'info, MangoAccount>,
|
pub liqor: AccountLoader<'info, MangoAccount>,
|
||||||
#[account(address = liqor.load()?.owner)]
|
|
||||||
pub liqor_owner: Signer<'info>,
|
pub liqor_owner: Signer<'info>,
|
||||||
|
|
||||||
#[account(
|
#[account(
|
||||||
|
|
|
@ -6,6 +6,7 @@ pub use compute_account_data::*;
|
||||||
pub use create_account::*;
|
pub use create_account::*;
|
||||||
pub use create_group::*;
|
pub use create_group::*;
|
||||||
pub use create_stub_oracle::*;
|
pub use create_stub_oracle::*;
|
||||||
|
pub use edit_account::*;
|
||||||
pub use flash_loan::*;
|
pub use flash_loan::*;
|
||||||
pub use flash_loan2::*;
|
pub use flash_loan2::*;
|
||||||
pub use flash_loan3::*;
|
pub use flash_loan3::*;
|
||||||
|
@ -17,6 +18,7 @@ pub use perp_cancel_order_by_client_order_id::*;
|
||||||
pub use perp_close_market::*;
|
pub use perp_close_market::*;
|
||||||
pub use perp_consume_events::*;
|
pub use perp_consume_events::*;
|
||||||
pub use perp_create_market::*;
|
pub use perp_create_market::*;
|
||||||
|
pub use perp_edit_market::*;
|
||||||
pub use perp_place_order::*;
|
pub use perp_place_order::*;
|
||||||
pub use perp_update_funding::*;
|
pub use perp_update_funding::*;
|
||||||
pub use serum3_cancel_all_orders::*;
|
pub use serum3_cancel_all_orders::*;
|
||||||
|
@ -32,6 +34,7 @@ pub use set_stub_oracle::*;
|
||||||
pub use token_add_bank::*;
|
pub use token_add_bank::*;
|
||||||
pub use token_deposit::*;
|
pub use token_deposit::*;
|
||||||
pub use token_deregister::*;
|
pub use token_deregister::*;
|
||||||
|
pub use token_edit::*;
|
||||||
pub use token_register::*;
|
pub use token_register::*;
|
||||||
pub use token_withdraw::*;
|
pub use token_withdraw::*;
|
||||||
pub use update_index::*;
|
pub use update_index::*;
|
||||||
|
@ -44,6 +47,7 @@ mod compute_account_data;
|
||||||
mod create_account;
|
mod create_account;
|
||||||
mod create_group;
|
mod create_group;
|
||||||
mod create_stub_oracle;
|
mod create_stub_oracle;
|
||||||
|
mod edit_account;
|
||||||
mod flash_loan;
|
mod flash_loan;
|
||||||
mod flash_loan2;
|
mod flash_loan2;
|
||||||
mod flash_loan3;
|
mod flash_loan3;
|
||||||
|
@ -55,6 +59,7 @@ mod perp_cancel_order_by_client_order_id;
|
||||||
mod perp_close_market;
|
mod perp_close_market;
|
||||||
mod perp_consume_events;
|
mod perp_consume_events;
|
||||||
mod perp_create_market;
|
mod perp_create_market;
|
||||||
|
mod perp_edit_market;
|
||||||
mod perp_place_order;
|
mod perp_place_order;
|
||||||
mod perp_update_funding;
|
mod perp_update_funding;
|
||||||
mod serum3_cancel_all_orders;
|
mod serum3_cancel_all_orders;
|
||||||
|
@ -70,6 +75,7 @@ mod set_stub_oracle;
|
||||||
mod token_add_bank;
|
mod token_add_bank;
|
||||||
mod token_deposit;
|
mod token_deposit;
|
||||||
mod token_deregister;
|
mod token_deregister;
|
||||||
|
mod token_edit;
|
||||||
mod token_register;
|
mod token_register;
|
||||||
mod token_withdraw;
|
mod token_withdraw;
|
||||||
mod update_index;
|
mod update_index;
|
||||||
|
|
|
@ -10,9 +10,10 @@ pub struct PerpCancelAllOrders<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
|
pub owner: Signer<'info>,
|
||||||
|
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
|
@ -25,8 +26,6 @@ pub struct PerpCancelAllOrders<'info> {
|
||||||
pub asks: AccountLoader<'info, BookSide>,
|
pub asks: AccountLoader<'info, BookSide>,
|
||||||
#[account(mut)]
|
#[account(mut)]
|
||||||
pub bids: AccountLoader<'info, BookSide>,
|
pub bids: AccountLoader<'info, BookSide>,
|
||||||
|
|
||||||
pub owner: Signer<'info>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn perp_cancel_all_orders(ctx: Context<PerpCancelAllOrders>, limit: u8) -> Result<()> {
|
pub fn perp_cancel_all_orders(ctx: Context<PerpCancelAllOrders>, limit: u8) -> Result<()> {
|
||||||
|
|
|
@ -10,9 +10,10 @@ pub struct PerpCancelAllOrdersBySide<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
|
pub owner: Signer<'info>,
|
||||||
|
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
|
@ -25,8 +26,6 @@ pub struct PerpCancelAllOrdersBySide<'info> {
|
||||||
pub asks: AccountLoader<'info, BookSide>,
|
pub asks: AccountLoader<'info, BookSide>,
|
||||||
#[account(mut)]
|
#[account(mut)]
|
||||||
pub bids: AccountLoader<'info, BookSide>,
|
pub bids: AccountLoader<'info, BookSide>,
|
||||||
|
|
||||||
pub owner: Signer<'info>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn perp_cancel_all_orders_by_side(
|
pub fn perp_cancel_all_orders_by_side(
|
||||||
|
|
|
@ -10,9 +10,10 @@ pub struct PerpCancelOrder<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
|
pub owner: Signer<'info>,
|
||||||
|
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
|
@ -25,8 +26,6 @@ pub struct PerpCancelOrder<'info> {
|
||||||
pub asks: AccountLoader<'info, BookSide>,
|
pub asks: AccountLoader<'info, BookSide>,
|
||||||
#[account(mut)]
|
#[account(mut)]
|
||||||
pub bids: AccountLoader<'info, BookSide>,
|
pub bids: AccountLoader<'info, BookSide>,
|
||||||
|
|
||||||
pub owner: Signer<'info>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn perp_cancel_order(ctx: Context<PerpCancelOrder>, order_id: i128) -> Result<()> {
|
pub fn perp_cancel_order(ctx: Context<PerpCancelOrder>, order_id: i128) -> Result<()> {
|
||||||
|
|
|
@ -10,9 +10,10 @@ pub struct PerpCancelOrderByClientOrderId<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
|
pub owner: Signer<'info>,
|
||||||
|
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
|
@ -25,8 +26,6 @@ pub struct PerpCancelOrderByClientOrderId<'info> {
|
||||||
pub asks: AccountLoader<'info, BookSide>,
|
pub asks: AccountLoader<'info, BookSide>,
|
||||||
#[account(mut)]
|
#[account(mut)]
|
||||||
pub bids: AccountLoader<'info, BookSide>,
|
pub bids: AccountLoader<'info, BookSide>,
|
||||||
|
|
||||||
pub owner: Signer<'info>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn perp_cancel_order_by_client_order_id(
|
pub fn perp_cancel_order_by_client_order_id(
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
use crate::state::*;
|
||||||
|
use anchor_lang::prelude::*;
|
||||||
|
use fixed::types::I80F48;
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
pub struct PerpEditMarket<'info> {
|
||||||
|
#[account(
|
||||||
|
has_one = admin,
|
||||||
|
)]
|
||||||
|
pub group: AccountLoader<'info, Group>,
|
||||||
|
pub admin: Signer<'info>,
|
||||||
|
|
||||||
|
#[account(
|
||||||
|
mut,
|
||||||
|
has_one = group
|
||||||
|
)]
|
||||||
|
pub perp_market: AccountLoader<'info, PerpMarket>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn perp_edit_market(
|
||||||
|
ctx: Context<PerpEditMarket>,
|
||||||
|
oracle_opt: Option<Pubkey>,
|
||||||
|
oracle_config_opt: Option<OracleConfig>,
|
||||||
|
base_token_index_opt: Option<TokenIndex>,
|
||||||
|
base_token_decimals_opt: Option<u8>,
|
||||||
|
maint_asset_weight_opt: Option<f32>,
|
||||||
|
init_asset_weight_opt: Option<f32>,
|
||||||
|
maint_liab_weight_opt: Option<f32>,
|
||||||
|
init_liab_weight_opt: Option<f32>,
|
||||||
|
liquidation_fee_opt: Option<f32>,
|
||||||
|
maker_fee_opt: Option<f32>,
|
||||||
|
taker_fee_opt: Option<f32>,
|
||||||
|
min_funding_opt: Option<f32>,
|
||||||
|
max_funding_opt: Option<f32>,
|
||||||
|
impact_quantity_opt: Option<i64>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
|
||||||
|
|
||||||
|
// note: unchanged fields are inline, and match exact definition in perp_register_market
|
||||||
|
// please maintain, and don't remove, makes it easy to reason about which support admin modification
|
||||||
|
|
||||||
|
// unchanged -
|
||||||
|
// name
|
||||||
|
// group
|
||||||
|
|
||||||
|
if let Some(oracle) = oracle_opt {
|
||||||
|
perp_market.oracle = oracle;
|
||||||
|
}
|
||||||
|
if let Some(oracle_config) = oracle_config_opt {
|
||||||
|
perp_market.oracle_config = oracle_config;
|
||||||
|
};
|
||||||
|
|
||||||
|
// unchanged -
|
||||||
|
// bids
|
||||||
|
// asks
|
||||||
|
// event_queue
|
||||||
|
// quote_lot_size
|
||||||
|
// base_lot_size
|
||||||
|
|
||||||
|
if let Some(maint_asset_weight) = maint_asset_weight_opt {
|
||||||
|
perp_market.maint_asset_weight = I80F48::from_num(maint_asset_weight);
|
||||||
|
}
|
||||||
|
if let Some(init_asset_weight) = init_asset_weight_opt {
|
||||||
|
perp_market.init_asset_weight = I80F48::from_num(init_asset_weight);
|
||||||
|
}
|
||||||
|
if let Some(maint_liab_weight) = maint_liab_weight_opt {
|
||||||
|
perp_market.maint_liab_weight = I80F48::from_num(maint_liab_weight);
|
||||||
|
}
|
||||||
|
if let Some(init_liab_weight) = init_liab_weight_opt {
|
||||||
|
perp_market.init_liab_weight = I80F48::from_num(init_liab_weight);
|
||||||
|
}
|
||||||
|
if let Some(liquidation_fee) = liquidation_fee_opt {
|
||||||
|
perp_market.liquidation_fee = I80F48::from_num(liquidation_fee);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(maker_fee) = maker_fee_opt {
|
||||||
|
perp_market.maker_fee = I80F48::from_num(maker_fee);
|
||||||
|
}
|
||||||
|
if let Some(taker_fee) = taker_fee_opt {
|
||||||
|
perp_market.taker_fee = I80F48::from_num(taker_fee);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(min_funding) = min_funding_opt {
|
||||||
|
perp_market.min_funding = I80F48::from_num(min_funding);
|
||||||
|
}
|
||||||
|
if let Some(max_funding) = max_funding_opt {
|
||||||
|
perp_market.max_funding = I80F48::from_num(max_funding);
|
||||||
|
}
|
||||||
|
if let Some(impact_quantity) = impact_quantity_opt {
|
||||||
|
perp_market.impact_quantity = impact_quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unchanged -
|
||||||
|
// long_funding
|
||||||
|
// short_funding
|
||||||
|
// funding_last_updated
|
||||||
|
// open_interest
|
||||||
|
// seq_num
|
||||||
|
// fees_accrued
|
||||||
|
// bump
|
||||||
|
|
||||||
|
if let Some(base_token_decimals) = base_token_decimals_opt {
|
||||||
|
perp_market.base_token_decimals = base_token_decimals;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unchanged -
|
||||||
|
// perp_market_index
|
||||||
|
|
||||||
|
if let Some(base_token_index) = base_token_index_opt {
|
||||||
|
perp_market.base_token_index = base_token_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unchanged -
|
||||||
|
// quote_token_index
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -14,9 +14,10 @@ pub struct PerpPlaceOrder<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
|
pub owner: Signer<'info>,
|
||||||
|
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
|
@ -36,8 +37,6 @@ pub struct PerpPlaceOrder<'info> {
|
||||||
|
|
||||||
/// CHECK: The oracle can be one of several different account types and the pubkey is checked above
|
/// CHECK: The oracle can be one of several different account types and the pubkey is checked above
|
||||||
pub oracle: UncheckedAccount<'info>,
|
pub oracle: UncheckedAccount<'info>,
|
||||||
|
|
||||||
pub owner: Signer<'info>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub struct Serum3CancelAllOrders<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
pub owner: Signer<'info>,
|
pub owner: Signer<'info>,
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub struct Serum3CancelOrder<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
pub owner: Signer<'info>,
|
pub owner: Signer<'info>,
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub struct Serum3CloseOpenOrders<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
pub owner: Signer<'info>,
|
pub owner: Signer<'info>,
|
||||||
|
|
|
@ -10,9 +10,10 @@ pub struct Serum3CreateOpenOrders<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
|
pub owner: Signer<'info>,
|
||||||
|
|
||||||
#[account(
|
#[account(
|
||||||
has_one = group,
|
has_one = group,
|
||||||
|
@ -38,8 +39,6 @@ pub struct Serum3CreateOpenOrders<'info> {
|
||||||
/// CHECK: Newly created by serum cpi call
|
/// CHECK: Newly created by serum cpi call
|
||||||
pub open_orders: UncheckedAccount<'info>,
|
pub open_orders: UncheckedAccount<'info>,
|
||||||
|
|
||||||
pub owner: Signer<'info>,
|
|
||||||
|
|
||||||
#[account(mut)]
|
#[account(mut)]
|
||||||
pub payer: Signer<'info>,
|
pub payer: Signer<'info>,
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ pub struct Serum3PlaceOrder<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
pub owner: Signer<'info>,
|
pub owner: Signer<'info>,
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub struct Serum3SettleFunds<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = owner,
|
constraint = account.load()?.is_owner_or_delegate(owner.key()),
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
pub owner: Signer<'info>,
|
pub owner: Signer<'info>,
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
use anchor_lang::prelude::*;
|
||||||
|
|
||||||
|
use fixed::types::I80F48;
|
||||||
|
|
||||||
|
use super::InterestRateParams;
|
||||||
|
use crate::accounts_zerocopy::LoadMutZeroCopyRef;
|
||||||
|
|
||||||
|
use crate::state::*;
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
#[instruction(token_index: TokenIndex, bank_num: u64)]
|
||||||
|
pub struct TokenEdit<'info> {
|
||||||
|
#[account(
|
||||||
|
has_one = admin,
|
||||||
|
)]
|
||||||
|
pub group: AccountLoader<'info, Group>,
|
||||||
|
pub admin: Signer<'info>,
|
||||||
|
|
||||||
|
#[account(
|
||||||
|
has_one = group
|
||||||
|
)]
|
||||||
|
pub mint_info: AccountLoader<'info, MintInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn token_edit(
|
||||||
|
ctx: Context<TokenEdit>,
|
||||||
|
bank_num: u64,
|
||||||
|
oracle_opt: Option<Pubkey>,
|
||||||
|
oracle_config_opt: Option<OracleConfig>,
|
||||||
|
interest_rate_params_opt: Option<InterestRateParams>,
|
||||||
|
loan_fee_rate_opt: Option<f32>,
|
||||||
|
loan_origination_fee_rate_opt: Option<f32>,
|
||||||
|
maint_asset_weight_opt: Option<f32>,
|
||||||
|
init_asset_weight_opt: Option<f32>,
|
||||||
|
maint_liab_weight_opt: Option<f32>,
|
||||||
|
init_liab_weight_opt: Option<f32>,
|
||||||
|
liquidation_fee_opt: Option<f32>,
|
||||||
|
) -> Result<()> {
|
||||||
|
ctx.accounts
|
||||||
|
.mint_info
|
||||||
|
.load()?
|
||||||
|
.verify_banks_ais(ctx.remaining_accounts)?;
|
||||||
|
|
||||||
|
for ai in ctx.remaining_accounts.iter() {
|
||||||
|
let mut bank = ai.load_mut::<Bank>()?;
|
||||||
|
|
||||||
|
// note: unchanged fields are inline, and match exact definition in register_token
|
||||||
|
// please maintain, and don't remove, makes it easy to reason about which support admin modification
|
||||||
|
|
||||||
|
// unchanged -
|
||||||
|
// name
|
||||||
|
// group
|
||||||
|
// mint
|
||||||
|
// vault
|
||||||
|
|
||||||
|
if let Some(oracle) = oracle_opt {
|
||||||
|
bank.oracle = oracle;
|
||||||
|
}
|
||||||
|
if let Some(oracle_config) = oracle_config_opt {
|
||||||
|
bank.oracle_config = oracle_config;
|
||||||
|
};
|
||||||
|
|
||||||
|
// unchanged -
|
||||||
|
// deposit_index
|
||||||
|
// borrow_index
|
||||||
|
// cached_indexed_total_deposits
|
||||||
|
// cached_indexed_total_borrows
|
||||||
|
// indexed_deposits
|
||||||
|
// indexed_borrows
|
||||||
|
// last_updated
|
||||||
|
|
||||||
|
if let Some(ref interest_rate_params) = interest_rate_params_opt {
|
||||||
|
// TODO: add a require! verifying relation between the parameters
|
||||||
|
bank.util0 = I80F48::from_num(interest_rate_params.util0);
|
||||||
|
bank.rate0 = I80F48::from_num(interest_rate_params.rate0);
|
||||||
|
bank.util1 = I80F48::from_num(interest_rate_params.util1);
|
||||||
|
bank.rate1 = I80F48::from_num(interest_rate_params.rate1);
|
||||||
|
bank.max_rate = I80F48::from_num(interest_rate_params.max_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// unchanged -
|
||||||
|
// collected_fees_native
|
||||||
|
|
||||||
|
if let Some(loan_origination_fee_rate) = loan_origination_fee_rate_opt {
|
||||||
|
bank.loan_origination_fee_rate = I80F48::from_num(loan_origination_fee_rate);
|
||||||
|
}
|
||||||
|
if let Some(loan_fee_rate) = loan_fee_rate_opt {
|
||||||
|
bank.loan_fee_rate = I80F48::from_num(loan_fee_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(maint_asset_weight) = maint_asset_weight_opt {
|
||||||
|
bank.maint_asset_weight = I80F48::from_num(maint_asset_weight);
|
||||||
|
}
|
||||||
|
if let Some(init_asset_weight) = init_asset_weight_opt {
|
||||||
|
bank.init_asset_weight = I80F48::from_num(init_asset_weight);
|
||||||
|
}
|
||||||
|
if let Some(maint_liab_weight) = maint_liab_weight_opt {
|
||||||
|
bank.maint_liab_weight = I80F48::from_num(maint_liab_weight);
|
||||||
|
}
|
||||||
|
if let Some(init_liab_weight) = init_liab_weight_opt {
|
||||||
|
bank.init_liab_weight = I80F48::from_num(init_liab_weight);
|
||||||
|
}
|
||||||
|
if let Some(liquidation_fee) = liquidation_fee_opt {
|
||||||
|
bank.liquidation_fee = I80F48::from_num(liquidation_fee);
|
||||||
|
}
|
||||||
|
|
||||||
|
// unchanged -
|
||||||
|
// dust
|
||||||
|
// flash_loan_vault_initial
|
||||||
|
// flash_loan_approved_amount
|
||||||
|
// token_index
|
||||||
|
// bump
|
||||||
|
// mint_decimals
|
||||||
|
// bank_num
|
||||||
|
// reserved
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ pub struct TokenWithdraw<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
|
// note: should never be the delegate
|
||||||
has_one = owner,
|
has_one = owner,
|
||||||
)]
|
)]
|
||||||
pub account: AccountLoader<'info, MangoAccount>,
|
pub account: AccountLoader<'info, MangoAccount>,
|
||||||
|
|
|
@ -3,7 +3,6 @@ use anchor_lang::prelude::*;
|
||||||
use crate::logs::UpdateIndexLog;
|
use crate::logs::UpdateIndexLog;
|
||||||
use crate::{
|
use crate::{
|
||||||
accounts_zerocopy::{LoadMutZeroCopyRef, LoadZeroCopyRef},
|
accounts_zerocopy::{LoadMutZeroCopyRef, LoadZeroCopyRef},
|
||||||
error::MangoError,
|
|
||||||
state::{Bank, MintInfo},
|
state::{Bank, MintInfo},
|
||||||
};
|
};
|
||||||
use checked_math as cm;
|
use checked_math as cm;
|
||||||
|
@ -14,21 +13,14 @@ pub struct UpdateIndex<'info> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_index(ctx: Context<UpdateIndex>) -> Result<()> {
|
pub fn update_index(ctx: Context<UpdateIndex>) -> Result<()> {
|
||||||
let mint_info = ctx.accounts.mint_info.load()?;
|
ctx.accounts
|
||||||
|
.mint_info
|
||||||
let total_banks = mint_info
|
.load()?
|
||||||
.banks
|
.verify_banks_ais(ctx.remaining_accounts)?;
|
||||||
.iter()
|
|
||||||
.filter(|bank| *bank != &Pubkey::default())
|
|
||||||
.count();
|
|
||||||
|
|
||||||
require_eq!(total_banks, ctx.remaining_accounts.len());
|
|
||||||
let all_banks = ctx.remaining_accounts;
|
|
||||||
check_banks(all_banks, &mint_info)?;
|
|
||||||
|
|
||||||
let mut indexed_total_deposits = I80F48::ZERO;
|
let mut indexed_total_deposits = I80F48::ZERO;
|
||||||
let mut indexed_total_borrows = I80F48::ZERO;
|
let mut indexed_total_borrows = I80F48::ZERO;
|
||||||
for ai in all_banks.iter() {
|
for ai in ctx.remaining_accounts.iter() {
|
||||||
let bank = ai.load::<Bank>()?;
|
let bank = ai.load::<Bank>()?;
|
||||||
indexed_total_deposits = cm!(indexed_total_deposits + bank.indexed_deposits);
|
indexed_total_deposits = cm!(indexed_total_deposits + bank.indexed_deposits);
|
||||||
indexed_total_borrows = cm!(indexed_total_borrows + bank.indexed_borrows);
|
indexed_total_borrows = cm!(indexed_total_borrows + bank.indexed_borrows);
|
||||||
|
@ -36,7 +28,7 @@ pub fn update_index(ctx: Context<UpdateIndex>) -> Result<()> {
|
||||||
|
|
||||||
let now_ts = Clock::get()?.unix_timestamp;
|
let now_ts = Clock::get()?.unix_timestamp;
|
||||||
let (diff_ts, deposit_index, borrow_index) = {
|
let (diff_ts, deposit_index, borrow_index) = {
|
||||||
let mut some_bank = all_banks[0].load_mut::<Bank>()?;
|
let mut some_bank = ctx.remaining_accounts[0].load_mut::<Bank>()?;
|
||||||
|
|
||||||
// TODO: should we enforce a minimum window between 2 update_index ix calls?
|
// TODO: should we enforce a minimum window between 2 update_index ix calls?
|
||||||
let diff_ts = I80F48::from_num(now_ts - some_bank.last_updated);
|
let diff_ts = I80F48::from_num(now_ts - some_bank.last_updated);
|
||||||
|
@ -53,7 +45,7 @@ pub fn update_index(ctx: Context<UpdateIndex>) -> Result<()> {
|
||||||
msg!("deposit_index {}", deposit_index);
|
msg!("deposit_index {}", deposit_index);
|
||||||
msg!("borrow_index {}", borrow_index);
|
msg!("borrow_index {}", borrow_index);
|
||||||
|
|
||||||
for ai in all_banks.iter() {
|
for ai in ctx.remaining_accounts.iter() {
|
||||||
let mut bank = ai.load_mut::<Bank>()?;
|
let mut bank = ai.load_mut::<Bank>()?;
|
||||||
|
|
||||||
bank.cached_indexed_total_deposits = indexed_total_deposits;
|
bank.cached_indexed_total_deposits = indexed_total_deposits;
|
||||||
|
@ -77,22 +69,3 @@ pub fn update_index(ctx: Context<UpdateIndex>) -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_banks(all_banks: &[AccountInfo], mint_info: &MintInfo) -> Result<()> {
|
|
||||||
for (idx, ai) in all_banks.iter().enumerate() {
|
|
||||||
match ai.load::<Bank>() {
|
|
||||||
Ok(bank) => {
|
|
||||||
if mint_info.token_index != bank.token_index
|
|
||||||
|| mint_info.group != bank.group
|
|
||||||
// todo: just below check should be enough, above 2 checks are superfluous and defensive
|
|
||||||
|| mint_info.banks[idx] != ai.key()
|
|
||||||
{
|
|
||||||
return Err(error!(MangoError::SomeError));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(error) => return Err(error),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
|
@ -71,6 +71,37 @@ pub mod mango_v4 {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn token_edit(
|
||||||
|
ctx: Context<TokenEdit>,
|
||||||
|
bank_num: u64,
|
||||||
|
oracle_opt: Option<Pubkey>,
|
||||||
|
oracle_config_opt: Option<OracleConfig>,
|
||||||
|
interest_rate_params_opt: Option<InterestRateParams>,
|
||||||
|
loan_fee_rate_opt: Option<f32>,
|
||||||
|
loan_origination_fee_rate_opt: Option<f32>,
|
||||||
|
maint_asset_weight_opt: Option<f32>,
|
||||||
|
init_asset_weight_opt: Option<f32>,
|
||||||
|
maint_liab_weight_opt: Option<f32>,
|
||||||
|
init_liab_weight_opt: Option<f32>,
|
||||||
|
liquidation_fee_opt: Option<f32>,
|
||||||
|
) -> Result<()> {
|
||||||
|
instructions::token_edit(
|
||||||
|
ctx,
|
||||||
|
bank_num,
|
||||||
|
oracle_opt,
|
||||||
|
oracle_config_opt,
|
||||||
|
interest_rate_params_opt,
|
||||||
|
loan_fee_rate_opt,
|
||||||
|
loan_origination_fee_rate_opt,
|
||||||
|
maint_asset_weight_opt,
|
||||||
|
init_asset_weight_opt,
|
||||||
|
maint_liab_weight_opt,
|
||||||
|
init_liab_weight_opt,
|
||||||
|
liquidation_fee_opt,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn token_add_bank(
|
pub fn token_add_bank(
|
||||||
ctx: Context<TokenAddBank>,
|
ctx: Context<TokenAddBank>,
|
||||||
|
@ -99,7 +130,13 @@ pub mod mango_v4 {
|
||||||
instructions::create_account(ctx, account_num, name)
|
instructions::create_account(ctx, account_num, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO set delegate
|
pub fn edit_account(
|
||||||
|
ctx: Context<EditAccount>,
|
||||||
|
name_opt: Option<String>,
|
||||||
|
delegate_opt: Option<Pubkey>,
|
||||||
|
) -> Result<()> {
|
||||||
|
instructions::edit_account(ctx, name_opt, delegate_opt)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn close_account(ctx: Context<CloseAccount>) -> Result<()> {
|
pub fn close_account(ctx: Context<CloseAccount>) -> Result<()> {
|
||||||
instructions::close_account(ctx)
|
instructions::close_account(ctx)
|
||||||
|
@ -182,6 +219,11 @@ pub mod mango_v4 {
|
||||||
instructions::serum3_register_market(ctx, market_index, name)
|
instructions::serum3_register_market(ctx, market_index, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// note:
|
||||||
|
// pub fn serum3_edit_market - doesn't exist since a mango serum3 market only contains the properties
|
||||||
|
// registered base and quote token pairs, and serum3 external market its pointing to, and none of them
|
||||||
|
// should be edited once set on creation
|
||||||
|
|
||||||
pub fn serum3_deregister_market(ctx: Context<Serum3DeregisterMarket>) -> Result<()> {
|
pub fn serum3_deregister_market(ctx: Context<Serum3DeregisterMarket>) -> Result<()> {
|
||||||
instructions::serum3_deregister_market(ctx)
|
instructions::serum3_deregister_market(ctx)
|
||||||
}
|
}
|
||||||
|
@ -309,6 +351,43 @@ pub mod mango_v4 {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn perp_edit_market(
|
||||||
|
ctx: Context<PerpEditMarket>,
|
||||||
|
oracle_opt: Option<Pubkey>,
|
||||||
|
oracle_config_opt: Option<OracleConfig>,
|
||||||
|
base_token_index_opt: Option<TokenIndex>,
|
||||||
|
base_token_decimals_opt: Option<u8>,
|
||||||
|
maint_asset_weight_opt: Option<f32>,
|
||||||
|
init_asset_weight_opt: Option<f32>,
|
||||||
|
maint_liab_weight_opt: Option<f32>,
|
||||||
|
init_liab_weight_opt: Option<f32>,
|
||||||
|
liquidation_fee_opt: Option<f32>,
|
||||||
|
maker_fee_opt: Option<f32>,
|
||||||
|
taker_fee_opt: Option<f32>,
|
||||||
|
min_funding_opt: Option<f32>,
|
||||||
|
max_funding_opt: Option<f32>,
|
||||||
|
impact_quantity_opt: Option<i64>,
|
||||||
|
) -> Result<()> {
|
||||||
|
instructions::perp_edit_market(
|
||||||
|
ctx,
|
||||||
|
oracle_opt,
|
||||||
|
oracle_config_opt,
|
||||||
|
base_token_index_opt,
|
||||||
|
base_token_decimals_opt,
|
||||||
|
maint_asset_weight_opt,
|
||||||
|
init_asset_weight_opt,
|
||||||
|
maint_liab_weight_opt,
|
||||||
|
init_liab_weight_opt,
|
||||||
|
liquidation_fee_opt,
|
||||||
|
maker_fee_opt,
|
||||||
|
taker_fee_opt,
|
||||||
|
min_funding_opt,
|
||||||
|
max_funding_opt,
|
||||||
|
impact_quantity_opt,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn perp_close_market(ctx: Context<PerpCloseMarket>) -> Result<()> {
|
pub fn perp_close_market(ctx: Context<PerpCloseMarket>) -> Result<()> {
|
||||||
instructions::perp_close_market(ctx)
|
instructions::perp_close_market(ctx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use std::mem::size_of;
|
||||||
pub type TokenIndex = u16;
|
pub type TokenIndex = u16;
|
||||||
|
|
||||||
#[account(zero_copy)]
|
#[account(zero_copy)]
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Group {
|
pub struct Group {
|
||||||
// Relying on Anchor's discriminator be sufficient for our versioning needs?
|
// Relying on Anchor's discriminator be sufficient for our versioning needs?
|
||||||
// pub meta_data: MetaData,
|
// pub meta_data: MetaData,
|
||||||
|
|
|
@ -770,6 +770,10 @@ impl MangoAccount {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.trim_matches(char::from(0))
|
.trim_matches(char::from(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_owner_or_delegate(&self, ix_signer: Pubkey) -> bool {
|
||||||
|
self.owner == ix_signer || self.delegate == ix_signer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MangoAccount {
|
impl Default for MangoAccount {
|
||||||
|
|
|
@ -2,7 +2,9 @@ use anchor_lang::prelude::*;
|
||||||
use static_assertions::const_assert_eq;
|
use static_assertions::const_assert_eq;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
|
|
||||||
use super::TokenIndex;
|
use crate::{accounts_zerocopy::LoadZeroCopyRef, error::MangoError};
|
||||||
|
|
||||||
|
use super::{Bank, TokenIndex};
|
||||||
|
|
||||||
pub const MAX_BANKS: usize = 6;
|
pub const MAX_BANKS: usize = 6;
|
||||||
|
|
||||||
|
@ -44,4 +46,30 @@ impl MintInfo {
|
||||||
pub fn first_vault(&self) -> Pubkey {
|
pub fn first_vault(&self) -> Pubkey {
|
||||||
self.vaults[0]
|
self.vaults[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn verify_banks_ais(&self, all_bank_ais: &[AccountInfo]) -> Result<()> {
|
||||||
|
let total_banks = self
|
||||||
|
.banks
|
||||||
|
.iter()
|
||||||
|
.filter(|bank| *bank != &Pubkey::default())
|
||||||
|
.count();
|
||||||
|
require_eq!(total_banks, all_bank_ais.len());
|
||||||
|
|
||||||
|
for (idx, ai) in all_bank_ais.iter().enumerate() {
|
||||||
|
match ai.load::<Bank>() {
|
||||||
|
Ok(bank) => {
|
||||||
|
if self.token_index != bank.token_index
|
||||||
|
|| self.group != bank.group
|
||||||
|
// todo: just below check should be enough, above 2 checks are superfluous and defensive
|
||||||
|
|| self.banks[idx] != ai.key()
|
||||||
|
{
|
||||||
|
return Err(error!(MangoError::SomeError));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ use super::{Book, OracleConfig};
|
||||||
pub type PerpMarketIndex = u16;
|
pub type PerpMarketIndex = u16;
|
||||||
|
|
||||||
#[account(zero_copy)]
|
#[account(zero_copy)]
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct PerpMarket {
|
pub struct PerpMarket {
|
||||||
pub name: [u8; 16],
|
pub name: [u8; 16],
|
||||||
|
|
||||||
|
|
|
@ -1296,6 +1296,53 @@ impl<'keypair> ClientInstruction for CreateAccountInstruction<'keypair> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct EditAccountInstruction<'keypair> {
|
||||||
|
pub account_num: u8,
|
||||||
|
pub group: Pubkey,
|
||||||
|
pub owner: &'keypair Keypair,
|
||||||
|
pub name: String,
|
||||||
|
pub delegate: Pubkey,
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl<'keypair> ClientInstruction for EditAccountInstruction<'keypair> {
|
||||||
|
type Accounts = mango_v4::accounts::EditAccount;
|
||||||
|
type Instruction = mango_v4::instruction::EditAccount;
|
||||||
|
async fn to_instruction(
|
||||||
|
&self,
|
||||||
|
_account_loader: impl ClientAccountLoader + 'async_trait,
|
||||||
|
) -> (Self::Accounts, instruction::Instruction) {
|
||||||
|
let program_id = mango_v4::id();
|
||||||
|
let instruction = mango_v4::instruction::EditAccount {
|
||||||
|
name_opt: Option::from(self.name.to_string()),
|
||||||
|
delegate_opt: Option::from(self.delegate),
|
||||||
|
};
|
||||||
|
|
||||||
|
let account = Pubkey::find_program_address(
|
||||||
|
&[
|
||||||
|
self.group.as_ref(),
|
||||||
|
b"MangoAccount".as_ref(),
|
||||||
|
self.owner.pubkey().as_ref(),
|
||||||
|
&self.account_num.to_le_bytes(),
|
||||||
|
],
|
||||||
|
&program_id,
|
||||||
|
)
|
||||||
|
.0;
|
||||||
|
|
||||||
|
let accounts = mango_v4::accounts::EditAccount {
|
||||||
|
group: self.group,
|
||||||
|
account,
|
||||||
|
owner: self.owner.pubkey(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
||||||
|
(accounts, instruction)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signers(&self) -> Vec<&Keypair> {
|
||||||
|
vec![self.owner]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct CloseAccountInstruction<'keypair> {
|
pub struct CloseAccountInstruction<'keypair> {
|
||||||
pub group: Pubkey,
|
pub group: Pubkey,
|
||||||
pub account: Pubkey,
|
pub account: Pubkey,
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
#![cfg(feature = "test-bpf")]
|
||||||
|
|
||||||
|
use fixed::types::I80F48;
|
||||||
|
use solana_program_test::*;
|
||||||
|
use solana_sdk::{signature::Keypair, signature::Signer, transport::TransportError};
|
||||||
|
|
||||||
|
use mango_v4::state::*;
|
||||||
|
use program_test::*;
|
||||||
|
|
||||||
|
mod program_test;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_delegate() -> Result<(), TransportError> {
|
||||||
|
let context = TestContext::new().await;
|
||||||
|
let solana = &context.solana.clone();
|
||||||
|
|
||||||
|
let admin = &Keypair::new();
|
||||||
|
let owner = &context.users[0].key;
|
||||||
|
let payer = &context.users[1].key;
|
||||||
|
let delegate = &context.users[1].key;
|
||||||
|
let mints = &context.mints[0..1];
|
||||||
|
let payer_mint0_account = context.users[1].token_accounts[0];
|
||||||
|
|
||||||
|
//
|
||||||
|
// SETUP: Create a group, register a token (mint0), create an account
|
||||||
|
//
|
||||||
|
|
||||||
|
let mango_setup::GroupWithTokens { group, tokens } = mango_setup::GroupWithTokensConfig {
|
||||||
|
admin,
|
||||||
|
payer,
|
||||||
|
mints,
|
||||||
|
}
|
||||||
|
.create(solana)
|
||||||
|
.await;
|
||||||
|
let bank = tokens[0].bank;
|
||||||
|
|
||||||
|
let account = send_tx(
|
||||||
|
solana,
|
||||||
|
CreateAccountInstruction {
|
||||||
|
account_num: 0,
|
||||||
|
group,
|
||||||
|
owner,
|
||||||
|
payer,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.account;
|
||||||
|
|
||||||
|
// deposit
|
||||||
|
send_tx(
|
||||||
|
solana,
|
||||||
|
TokenDepositInstruction {
|
||||||
|
amount: 100,
|
||||||
|
account,
|
||||||
|
token_account: payer_mint0_account,
|
||||||
|
token_authority: payer,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
//
|
||||||
|
// TEST: Edit account - Set delegate
|
||||||
|
//
|
||||||
|
{
|
||||||
|
send_tx(
|
||||||
|
solana,
|
||||||
|
EditAccountInstruction {
|
||||||
|
delegate: delegate.pubkey(),
|
||||||
|
account_num: 0,
|
||||||
|
group,
|
||||||
|
owner,
|
||||||
|
name: "new_name".to_owned(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// TEST: Edit account as delegate - should fail
|
||||||
|
//
|
||||||
|
{
|
||||||
|
let res = send_tx(
|
||||||
|
solana,
|
||||||
|
EditAccountInstruction {
|
||||||
|
delegate: delegate.pubkey(),
|
||||||
|
account_num: 0,
|
||||||
|
group,
|
||||||
|
owner: delegate,
|
||||||
|
name: "new_name".to_owned(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert!(res.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// TEST: Withdraw funds as delegate should fail
|
||||||
|
//
|
||||||
|
{
|
||||||
|
let withdraw_amount = 50;
|
||||||
|
let res = send_tx(
|
||||||
|
solana,
|
||||||
|
TokenWithdrawInstruction {
|
||||||
|
amount: withdraw_amount,
|
||||||
|
allow_borrow: true,
|
||||||
|
account,
|
||||||
|
owner: delegate,
|
||||||
|
token_account: payer_mint0_account,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert!(res.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// TEST: Close account as delegate should fail
|
||||||
|
//
|
||||||
|
{
|
||||||
|
let bank_data: Bank = solana.get_account(bank).await;
|
||||||
|
send_tx(
|
||||||
|
solana,
|
||||||
|
TokenWithdrawInstruction {
|
||||||
|
amount: bank_data.native_deposits().to_num(),
|
||||||
|
allow_borrow: false,
|
||||||
|
account,
|
||||||
|
owner,
|
||||||
|
token_account: payer_mint0_account,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let res = send_tx(
|
||||||
|
solana,
|
||||||
|
CloseAccountInstruction {
|
||||||
|
group,
|
||||||
|
account,
|
||||||
|
owner: delegate,
|
||||||
|
sol_destination: payer.pubkey(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert!(res.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ cp -v ./target/types/mango_v4.ts ./ts/client/src/mango_v4.ts
|
||||||
if [[ -z "${NO_DEPLOY}" ]]; then
|
if [[ -z "${NO_DEPLOY}" ]]; then
|
||||||
# publish program
|
# publish program
|
||||||
solana --url https://mango.devnet.rpcpool.com program deploy --program-id $PROGRAM_ID \
|
solana --url https://mango.devnet.rpcpool.com program deploy --program-id $PROGRAM_ID \
|
||||||
-k $WALLET_WITH_FUNDS target/deploy/mango_v4.so
|
-k $WALLET_WITH_FUNDS target/deploy/mango_v4.so --skip-fee-check
|
||||||
|
|
||||||
# # publish idl
|
# # publish idl
|
||||||
# anchor idl upgrade --provider.cluster https://mango.devnet.rpcpool.com --provider.wallet $WALLET_WITH_FUNDS \
|
# anchor idl upgrade --provider.cluster https://mango.devnet.rpcpool.com --provider.wallet $WALLET_WITH_FUNDS \
|
||||||
|
|
|
@ -141,9 +141,39 @@ export class Bank {
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
return `Bank ${
|
return (
|
||||||
this.tokenIndex
|
'Bank ' +
|
||||||
} deposit index - ${this.depositIndex.toNumber()}, borrow index - ${this.borrowIndex.toNumber()}`;
|
'\n token index -' +
|
||||||
|
this.tokenIndex +
|
||||||
|
'\n deposit index -' +
|
||||||
|
this.depositIndex.toNumber() +
|
||||||
|
'\n borrow index -' +
|
||||||
|
this.borrowIndex.toNumber() +
|
||||||
|
'\n cachedIndexedTotalDeposits -' +
|
||||||
|
this.cachedIndexedTotalDeposits.toNumber() +
|
||||||
|
'\n cachedIndexedTotalBorrows -' +
|
||||||
|
this.cachedIndexedTotalBorrows.toNumber() +
|
||||||
|
'\n maxRate -' +
|
||||||
|
this.maxRate.toNumber() +
|
||||||
|
'\n util0 -' +
|
||||||
|
this.util0.toNumber() +
|
||||||
|
'\n rate0 -' +
|
||||||
|
this.rate0.toNumber() +
|
||||||
|
'\n util1 -' +
|
||||||
|
this.util1.toNumber() +
|
||||||
|
'\n rate1 -' +
|
||||||
|
this.rate1.toNumber() +
|
||||||
|
'\n maintAssetWeight -' +
|
||||||
|
this.maintAssetWeight.toNumber() +
|
||||||
|
'\n initAssetWeight -' +
|
||||||
|
this.initAssetWeight.toNumber() +
|
||||||
|
'\n maintLiabWeight -' +
|
||||||
|
this.maintLiabWeight.toNumber() +
|
||||||
|
'\n initLiabWeight -' +
|
||||||
|
this.initLiabWeight.toNumber() +
|
||||||
|
'\n liquidationFee -' +
|
||||||
|
this.liquidationFee.toNumber()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
nativeDeposits(): I80F48 {
|
nativeDeposits(): I80F48 {
|
||||||
|
|
|
@ -234,6 +234,7 @@ export class MangoAccount {
|
||||||
let res = 'MangoAccount';
|
let res = 'MangoAccount';
|
||||||
res = res + '\n pk: ' + this.publicKey.toString();
|
res = res + '\n pk: ' + this.publicKey.toString();
|
||||||
res = res + '\n name: ' + this.name;
|
res = res + '\n name: ' + this.name;
|
||||||
|
res = res + '\n delegate: ' + this.delegate;
|
||||||
|
|
||||||
res =
|
res =
|
||||||
this.tokensActive().length > 0
|
this.tokensActive().length > 0
|
||||||
|
|
|
@ -126,6 +126,28 @@ export class PerpMarket {
|
||||||
const quoteUnit = Math.pow(10, QUOTE_DECIMALS);
|
const quoteUnit = Math.pow(10, QUOTE_DECIMALS);
|
||||||
return new BN(uiQuote * quoteUnit).div(this.quoteLotSize);
|
return new BN(uiQuote * quoteUnit).div(this.quoteLotSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString(): string {
|
||||||
|
return (
|
||||||
|
'PerpMarket ' +
|
||||||
|
'\n perpMarketIndex -' +
|
||||||
|
this.perpMarketIndex +
|
||||||
|
'\n maintAssetWeight -' +
|
||||||
|
this.maintAssetWeight.toNumber() +
|
||||||
|
'\n initAssetWeight -' +
|
||||||
|
this.initAssetWeight.toNumber() +
|
||||||
|
'\n maintLiabWeight -' +
|
||||||
|
this.maintLiabWeight.toNumber() +
|
||||||
|
'\n initLiabWeight -' +
|
||||||
|
this.initLiabWeight.toNumber() +
|
||||||
|
'\n liquidationFee -' +
|
||||||
|
this.liquidationFee.toNumber() +
|
||||||
|
'\n makerFee -' +
|
||||||
|
this.makerFee.toNumber() +
|
||||||
|
'\n takerFee -' +
|
||||||
|
this.takerFee.toNumber()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Side {
|
export class Side {
|
||||||
|
|
|
@ -151,7 +151,6 @@ export class MangoClient {
|
||||||
initLiabWeight: number,
|
initLiabWeight: number,
|
||||||
liquidationFee: number,
|
liquidationFee: number,
|
||||||
): Promise<TransactionSignature> {
|
): Promise<TransactionSignature> {
|
||||||
const bn = I80F48.fromNumber(oracleConfFilter).getData();
|
|
||||||
return await this.program.methods
|
return await this.program.methods
|
||||||
.tokenRegister(
|
.tokenRegister(
|
||||||
tokenIndex,
|
tokenIndex,
|
||||||
|
@ -182,6 +181,60 @@ export class MangoClient {
|
||||||
.rpc();
|
.rpc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async tokenEdit(
|
||||||
|
group: Group,
|
||||||
|
tokenName: string,
|
||||||
|
oracle: PublicKey,
|
||||||
|
oracleConfFilter: number,
|
||||||
|
util0: number,
|
||||||
|
rate0: number,
|
||||||
|
util1: number,
|
||||||
|
rate1: number,
|
||||||
|
maxRate: number,
|
||||||
|
loanFeeRate: number,
|
||||||
|
loanOriginationFeeRate: number,
|
||||||
|
maintAssetWeight: number,
|
||||||
|
initAssetWeight: number,
|
||||||
|
maintLiabWeight: number,
|
||||||
|
initLiabWeight: number,
|
||||||
|
liquidationFee: number,
|
||||||
|
): Promise<TransactionSignature> {
|
||||||
|
const bank = group.banksMap.get(tokenName)!;
|
||||||
|
const mintInfo = group.mintInfosMap.get(bank.tokenIndex)!;
|
||||||
|
|
||||||
|
return await this.program.methods
|
||||||
|
.tokenEdit(
|
||||||
|
new BN(0),
|
||||||
|
oracle,
|
||||||
|
{
|
||||||
|
confFilter: {
|
||||||
|
val: I80F48.fromNumber(oracleConfFilter).getData(),
|
||||||
|
},
|
||||||
|
} as any, // future: nested custom types dont typecheck, fix if possible?
|
||||||
|
{ util0, rate0, util1, rate1, maxRate },
|
||||||
|
loanFeeRate,
|
||||||
|
loanOriginationFeeRate,
|
||||||
|
maintAssetWeight,
|
||||||
|
initAssetWeight,
|
||||||
|
maintLiabWeight,
|
||||||
|
initLiabWeight,
|
||||||
|
liquidationFee,
|
||||||
|
)
|
||||||
|
.accounts({
|
||||||
|
group: group.publicKey,
|
||||||
|
admin: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||||
|
mintInfo: mintInfo.publicKey,
|
||||||
|
})
|
||||||
|
.remainingAccounts([
|
||||||
|
{
|
||||||
|
pubkey: bank.publicKey,
|
||||||
|
isWritable: true,
|
||||||
|
isSigner: false,
|
||||||
|
} as AccountMeta,
|
||||||
|
])
|
||||||
|
.rpc({ skipPreflight: true });
|
||||||
|
}
|
||||||
|
|
||||||
public async tokenDeregister(
|
public async tokenDeregister(
|
||||||
group: Group,
|
group: Group,
|
||||||
tokenName: string,
|
tokenName: string,
|
||||||
|
@ -388,6 +441,20 @@ export class MangoClient {
|
||||||
.rpc();
|
.rpc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async editMangoAccount(
|
||||||
|
group: Group,
|
||||||
|
name?: string,
|
||||||
|
delegate?: PublicKey,
|
||||||
|
): Promise<TransactionSignature> {
|
||||||
|
return await this.program.methods
|
||||||
|
.editAccount(name, delegate)
|
||||||
|
.accounts({
|
||||||
|
group: group.publicKey,
|
||||||
|
owner: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||||
|
})
|
||||||
|
.rpc();
|
||||||
|
}
|
||||||
|
|
||||||
public async getMangoAccount(mangoAccount: MangoAccount) {
|
public async getMangoAccount(mangoAccount: MangoAccount) {
|
||||||
return MangoAccount.from(
|
return MangoAccount.from(
|
||||||
mangoAccount.publicKey,
|
mangoAccount.publicKey,
|
||||||
|
@ -1048,6 +1115,55 @@ export class MangoClient {
|
||||||
.rpc();
|
.rpc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async perpEditMarket(
|
||||||
|
group: Group,
|
||||||
|
perpMarketName: string,
|
||||||
|
oracle: PublicKey,
|
||||||
|
oracleConfFilter: number,
|
||||||
|
baseTokenIndex: number,
|
||||||
|
baseTokenDecimals: number,
|
||||||
|
maintAssetWeight: number,
|
||||||
|
initAssetWeight: number,
|
||||||
|
maintLiabWeight: number,
|
||||||
|
initLiabWeight: number,
|
||||||
|
liquidationFee: number,
|
||||||
|
makerFee: number,
|
||||||
|
takerFee: number,
|
||||||
|
minFunding: number,
|
||||||
|
maxFunding: number,
|
||||||
|
impactQuantity: number,
|
||||||
|
): Promise<TransactionSignature> {
|
||||||
|
const perpMarket = group.perpMarketsMap.get(perpMarketName)!;
|
||||||
|
|
||||||
|
return await this.program.methods
|
||||||
|
.perpEditMarket(
|
||||||
|
oracle,
|
||||||
|
{
|
||||||
|
confFilter: {
|
||||||
|
val: I80F48.fromNumber(oracleConfFilter).getData(),
|
||||||
|
},
|
||||||
|
} as any, // future: nested custom types dont typecheck, fix if possible?
|
||||||
|
baseTokenIndex,
|
||||||
|
baseTokenDecimals,
|
||||||
|
maintAssetWeight,
|
||||||
|
initAssetWeight,
|
||||||
|
maintLiabWeight,
|
||||||
|
initLiabWeight,
|
||||||
|
liquidationFee,
|
||||||
|
makerFee,
|
||||||
|
takerFee,
|
||||||
|
minFunding,
|
||||||
|
maxFunding,
|
||||||
|
new BN(impactQuantity),
|
||||||
|
)
|
||||||
|
.accounts({
|
||||||
|
group: group.publicKey,
|
||||||
|
admin: (this.program.provider as AnchorProvider).wallet.publicKey,
|
||||||
|
perpMarket: perpMarket.publicKey,
|
||||||
|
})
|
||||||
|
.rpc();
|
||||||
|
}
|
||||||
|
|
||||||
async perpCloseMarket(
|
async perpCloseMarket(
|
||||||
group: Group,
|
group: Group,
|
||||||
perpMarketName: string,
|
perpMarketName: string,
|
||||||
|
|
|
@ -264,6 +264,96 @@ export type MangoV4 = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "tokenEdit",
|
||||||
|
"accounts": [
|
||||||
|
{
|
||||||
|
"name": "group",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mintInfo",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "bankNum",
|
||||||
|
"type": "u64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "oracleOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "publicKey"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "oracleConfigOpt",
|
||||||
|
"type": {
|
||||||
|
"option": {
|
||||||
|
"defined": "OracleConfig"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "interestRateParamsOpt",
|
||||||
|
"type": {
|
||||||
|
"option": {
|
||||||
|
"defined": "InterestRateParams"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "loanFeeRateOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "loanOriginationFeeRateOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maintAssetWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "initAssetWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maintLiabWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "initLiabWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "liquidationFeeOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "tokenAddBank",
|
"name": "tokenAddBank",
|
||||||
"accounts": [
|
"accounts": [
|
||||||
|
@ -518,6 +608,40 @@ export type MangoV4 = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "editAccount",
|
||||||
|
"accounts": [
|
||||||
|
{
|
||||||
|
"name": "group",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "account",
|
||||||
|
"isMut": true,
|
||||||
|
"isSigner": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "nameOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "delegateOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "publicKey"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "closeAccount",
|
"name": "closeAccount",
|
||||||
"accounts": [
|
"accounts": [
|
||||||
|
@ -1046,6 +1170,11 @@ export type MangoV4 = {
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "serumMarket",
|
"name": "serumMarket",
|
||||||
"isMut": false,
|
"isMut": false,
|
||||||
|
@ -1085,11 +1214,6 @@ export type MangoV4 = {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"isMut": false,
|
|
||||||
"isSigner": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "payer",
|
"name": "payer",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
|
@ -1787,6 +1911,114 @@ export type MangoV4 = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "perpEditMarket",
|
||||||
|
"accounts": [
|
||||||
|
{
|
||||||
|
"name": "group",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "perpMarket",
|
||||||
|
"isMut": true,
|
||||||
|
"isSigner": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "oracleOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "publicKey"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "oracleConfigOpt",
|
||||||
|
"type": {
|
||||||
|
"option": {
|
||||||
|
"defined": "OracleConfig"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "baseTokenIndexOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "u16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "baseTokenDecimalsOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "u8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maintAssetWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "initAssetWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maintLiabWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "initLiabWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "liquidationFeeOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "makerFeeOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "takerFeeOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "minFundingOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maxFundingOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "impactQuantityOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "i64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "perpCloseMarket",
|
"name": "perpCloseMarket",
|
||||||
"accounts": [
|
"accounts": [
|
||||||
|
@ -1846,6 +2078,11 @@ export type MangoV4 = {
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "perpMarket",
|
"name": "perpMarket",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
|
@ -1870,11 +2107,6 @@ export type MangoV4 = {
|
||||||
"name": "oracle",
|
"name": "oracle",
|
||||||
"isMut": false,
|
"isMut": false,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"isMut": false,
|
|
||||||
"isSigner": true
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -1929,6 +2161,11 @@ export type MangoV4 = {
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "perpMarket",
|
"name": "perpMarket",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
|
@ -1943,11 +2180,6 @@ export type MangoV4 = {
|
||||||
"name": "bids",
|
"name": "bids",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"isMut": false,
|
|
||||||
"isSigner": true
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -1970,6 +2202,11 @@ export type MangoV4 = {
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "perpMarket",
|
"name": "perpMarket",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
|
@ -1984,11 +2221,6 @@ export type MangoV4 = {
|
||||||
"name": "bids",
|
"name": "bids",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"isMut": false,
|
|
||||||
"isSigner": true
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -2011,6 +2243,11 @@ export type MangoV4 = {
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "perpMarket",
|
"name": "perpMarket",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
|
@ -2025,11 +2262,6 @@ export type MangoV4 = {
|
||||||
"name": "bids",
|
"name": "bids",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"isMut": false,
|
|
||||||
"isSigner": true
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -2052,6 +2284,11 @@ export type MangoV4 = {
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "perpMarket",
|
"name": "perpMarket",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
|
@ -2066,11 +2303,6 @@ export type MangoV4 = {
|
||||||
"name": "bids",
|
"name": "bids",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"isMut": false,
|
|
||||||
"isSigner": true
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -4414,6 +4646,96 @@ export const IDL: MangoV4 = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "tokenEdit",
|
||||||
|
"accounts": [
|
||||||
|
{
|
||||||
|
"name": "group",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mintInfo",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "bankNum",
|
||||||
|
"type": "u64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "oracleOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "publicKey"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "oracleConfigOpt",
|
||||||
|
"type": {
|
||||||
|
"option": {
|
||||||
|
"defined": "OracleConfig"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "interestRateParamsOpt",
|
||||||
|
"type": {
|
||||||
|
"option": {
|
||||||
|
"defined": "InterestRateParams"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "loanFeeRateOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "loanOriginationFeeRateOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maintAssetWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "initAssetWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maintLiabWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "initLiabWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "liquidationFeeOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "tokenAddBank",
|
"name": "tokenAddBank",
|
||||||
"accounts": [
|
"accounts": [
|
||||||
|
@ -4668,6 +4990,40 @@ export const IDL: MangoV4 = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "editAccount",
|
||||||
|
"accounts": [
|
||||||
|
{
|
||||||
|
"name": "group",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "account",
|
||||||
|
"isMut": true,
|
||||||
|
"isSigner": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "nameOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "delegateOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "publicKey"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "closeAccount",
|
"name": "closeAccount",
|
||||||
"accounts": [
|
"accounts": [
|
||||||
|
@ -5196,6 +5552,11 @@ export const IDL: MangoV4 = {
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "serumMarket",
|
"name": "serumMarket",
|
||||||
"isMut": false,
|
"isMut": false,
|
||||||
|
@ -5235,11 +5596,6 @@ export const IDL: MangoV4 = {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"isMut": false,
|
|
||||||
"isSigner": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "payer",
|
"name": "payer",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
|
@ -5937,6 +6293,114 @@ export const IDL: MangoV4 = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "perpEditMarket",
|
||||||
|
"accounts": [
|
||||||
|
{
|
||||||
|
"name": "group",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "perpMarket",
|
||||||
|
"isMut": true,
|
||||||
|
"isSigner": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"name": "oracleOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "publicKey"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "oracleConfigOpt",
|
||||||
|
"type": {
|
||||||
|
"option": {
|
||||||
|
"defined": "OracleConfig"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "baseTokenIndexOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "u16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "baseTokenDecimalsOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "u8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maintAssetWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "initAssetWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maintLiabWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "initLiabWeightOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "liquidationFeeOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "makerFeeOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "takerFeeOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "minFundingOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maxFundingOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "f32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "impactQuantityOpt",
|
||||||
|
"type": {
|
||||||
|
"option": "i64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "perpCloseMarket",
|
"name": "perpCloseMarket",
|
||||||
"accounts": [
|
"accounts": [
|
||||||
|
@ -5996,6 +6460,11 @@ export const IDL: MangoV4 = {
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "perpMarket",
|
"name": "perpMarket",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
|
@ -6020,11 +6489,6 @@ export const IDL: MangoV4 = {
|
||||||
"name": "oracle",
|
"name": "oracle",
|
||||||
"isMut": false,
|
"isMut": false,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"isMut": false,
|
|
||||||
"isSigner": true
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -6079,6 +6543,11 @@ export const IDL: MangoV4 = {
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "perpMarket",
|
"name": "perpMarket",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
|
@ -6093,11 +6562,6 @@ export const IDL: MangoV4 = {
|
||||||
"name": "bids",
|
"name": "bids",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"isMut": false,
|
|
||||||
"isSigner": true
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -6120,6 +6584,11 @@ export const IDL: MangoV4 = {
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "perpMarket",
|
"name": "perpMarket",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
|
@ -6134,11 +6603,6 @@ export const IDL: MangoV4 = {
|
||||||
"name": "bids",
|
"name": "bids",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"isMut": false,
|
|
||||||
"isSigner": true
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -6161,6 +6625,11 @@ export const IDL: MangoV4 = {
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "perpMarket",
|
"name": "perpMarket",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
|
@ -6175,11 +6644,6 @@ export const IDL: MangoV4 = {
|
||||||
"name": "bids",
|
"name": "bids",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"isMut": false,
|
|
||||||
"isSigner": true
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -6202,6 +6666,11 @@ export const IDL: MangoV4 = {
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"isMut": false,
|
||||||
|
"isSigner": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "perpMarket",
|
"name": "perpMarket",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
|
@ -6216,11 +6685,6 @@ export const IDL: MangoV4 = {
|
||||||
"name": "bids",
|
"name": "bids",
|
||||||
"isMut": true,
|
"isMut": true,
|
||||||
"isSigner": false
|
"isSigner": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"isMut": false,
|
|
||||||
"isSigner": true
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"args": [
|
"args": [
|
||||||
|
|
|
@ -255,6 +255,116 @@ async function main() {
|
||||||
);
|
);
|
||||||
console.log(`...created perp market ${perpMarkets[0].publicKey}`);
|
console.log(`...created perp market ${perpMarkets[0].publicKey}`);
|
||||||
|
|
||||||
|
//
|
||||||
|
// edit
|
||||||
|
//
|
||||||
|
|
||||||
|
console.log(`Editing USDC...`);
|
||||||
|
try {
|
||||||
|
let sig = await client.tokenEdit(
|
||||||
|
group,
|
||||||
|
'USDC',
|
||||||
|
btcDevnetOracle,
|
||||||
|
0.1,
|
||||||
|
0.3,
|
||||||
|
0.08,
|
||||||
|
0.81,
|
||||||
|
0.91,
|
||||||
|
0.75,
|
||||||
|
0.0007,
|
||||||
|
1.7,
|
||||||
|
0.9,
|
||||||
|
0.7,
|
||||||
|
1.3,
|
||||||
|
1.5,
|
||||||
|
0.04,
|
||||||
|
);
|
||||||
|
console.log(`https://explorer.solana.com/tx/${sig}?cluster=devnet`);
|
||||||
|
await group.reloadAll(client);
|
||||||
|
console.log(group.banksMap.get('USDC').toString());
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
console.log(`Resetting USDC...`);
|
||||||
|
try {
|
||||||
|
let sig = await client.tokenEdit(
|
||||||
|
group,
|
||||||
|
'USDC',
|
||||||
|
usdcDevnetOracle.publicKey,
|
||||||
|
0.1,
|
||||||
|
0.4,
|
||||||
|
0.07,
|
||||||
|
0.8,
|
||||||
|
0.9,
|
||||||
|
1.5,
|
||||||
|
0.0005,
|
||||||
|
1.5,
|
||||||
|
0.8,
|
||||||
|
0.6,
|
||||||
|
1.2,
|
||||||
|
1.4,
|
||||||
|
0.02,
|
||||||
|
);
|
||||||
|
console.log(`https://explorer.solana.com/tx/${sig}?cluster=devnet`);
|
||||||
|
await group.reloadAll(client);
|
||||||
|
console.log(group.banksMap.get('USDC').toString());
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Editing perp market...`);
|
||||||
|
try {
|
||||||
|
let sig = await client.perpEditMarket(
|
||||||
|
group,
|
||||||
|
'BTC-PERP',
|
||||||
|
btcDevnetOracle,
|
||||||
|
0.2,
|
||||||
|
1,
|
||||||
|
6,
|
||||||
|
0.9,
|
||||||
|
0.9,
|
||||||
|
1.035,
|
||||||
|
1.06,
|
||||||
|
0.013,
|
||||||
|
0.0003,
|
||||||
|
0.1,
|
||||||
|
0.07,
|
||||||
|
0.07,
|
||||||
|
1001,
|
||||||
|
);
|
||||||
|
console.log(`https://explorer.solana.com/tx/${sig}?cluster=devnet`);
|
||||||
|
await group.reloadAll(client);
|
||||||
|
console.log(group.perpMarketsMap.get('BTC-PERP').toString());
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
console.log(`Resetting perp market...`);
|
||||||
|
try {
|
||||||
|
let sig = await client.perpEditMarket(
|
||||||
|
group,
|
||||||
|
'BTC-PERP',
|
||||||
|
btcDevnetOracle,
|
||||||
|
0.1,
|
||||||
|
0,
|
||||||
|
6,
|
||||||
|
1,
|
||||||
|
0.95,
|
||||||
|
1.025,
|
||||||
|
1.05,
|
||||||
|
0.012,
|
||||||
|
0.0002,
|
||||||
|
0.0,
|
||||||
|
0.05,
|
||||||
|
0.05,
|
||||||
|
100,
|
||||||
|
);
|
||||||
|
console.log(`https://explorer.solana.com/tx/${sig}?cluster=devnet`);
|
||||||
|
await group.reloadAll(client);
|
||||||
|
console.log(group.perpMarketsMap.get('BTC-PERP').toString());
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||||
|
import { Connection, Keypair } from '@solana/web3.js';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { OrderType, Side } from '../accounts/perp';
|
||||||
|
import {
|
||||||
|
Serum3OrderType,
|
||||||
|
Serum3SelfTradeBehavior,
|
||||||
|
Serum3Side,
|
||||||
|
} from '../accounts/serum3';
|
||||||
|
import { MangoClient } from '../client';
|
||||||
|
import { MANGO_V4_ID } from '../constants';
|
||||||
|
|
||||||
|
//
|
||||||
|
// An example for users based on high level api i.e. the client
|
||||||
|
// Create
|
||||||
|
// process.env.USER_KEYPAIR - mango account owner keypair path
|
||||||
|
// process.env.ADMIN_KEYPAIR - group admin keypair path (useful for automatically finding the group)
|
||||||
|
//
|
||||||
|
// This script deposits some tokens, places some serum orders, cancels them, places some perp orders
|
||||||
|
//
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const options = AnchorProvider.defaultOptions();
|
||||||
|
const connection = new Connection(
|
||||||
|
'https://mango.devnet.rpcpool.com',
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
// mango account owner
|
||||||
|
const user = Keypair.fromSecretKey(
|
||||||
|
Buffer.from(
|
||||||
|
JSON.parse(fs.readFileSync(process.env.USER_KEYPAIR!, 'utf-8')),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const userWallet = new Wallet(user);
|
||||||
|
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||||
|
const client = await MangoClient.connect(
|
||||||
|
userProvider,
|
||||||
|
'devnet',
|
||||||
|
MANGO_V4_ID['devnet'],
|
||||||
|
);
|
||||||
|
console.log(`User ${userWallet.publicKey.toBase58()}`);
|
||||||
|
|
||||||
|
// delegate
|
||||||
|
const delegate = Keypair.fromSecretKey(
|
||||||
|
Buffer.from(JSON.parse(fs.readFileSync(process.env.DELEGATE!, 'utf-8'))),
|
||||||
|
);
|
||||||
|
const delegateWallet = new Wallet(delegate);
|
||||||
|
const delegateProvider = new AnchorProvider(
|
||||||
|
connection,
|
||||||
|
delegateWallet,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
// Note: simply create a client with delegate and use this client to execute ixs
|
||||||
|
const delegateClient = await MangoClient.connect(
|
||||||
|
delegateProvider,
|
||||||
|
'devnet',
|
||||||
|
MANGO_V4_ID['devnet'],
|
||||||
|
);
|
||||||
|
console.log(`Delegate ${delegateWallet.publicKey.toBase58()}`);
|
||||||
|
|
||||||
|
// fetch group
|
||||||
|
const admin = Keypair.fromSecretKey(
|
||||||
|
Buffer.from(
|
||||||
|
JSON.parse(fs.readFileSync(process.env.ADMIN_KEYPAIR!, 'utf-8')),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const group = await delegateClient.getGroupForAdmin(admin.publicKey, 0);
|
||||||
|
console.log(group.toString());
|
||||||
|
|
||||||
|
// fetch mango account using owners pubkey
|
||||||
|
console.log(`Fetching mangoaccount...`);
|
||||||
|
const mangoAccount = (
|
||||||
|
await delegateClient.getMangoAccountForOwner(group, user.publicKey)
|
||||||
|
)[0];
|
||||||
|
console.log(`...created/found mangoAccount ${mangoAccount.publicKey}`);
|
||||||
|
console.log(mangoAccount.toString());
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
// set delegate, and change name
|
||||||
|
console.log(`...changing mango account name, and setting a delegate`);
|
||||||
|
await client.editMangoAccount(
|
||||||
|
group,
|
||||||
|
'my_changed_name',
|
||||||
|
delegate.publicKey,
|
||||||
|
);
|
||||||
|
await mangoAccount.reload(client, group);
|
||||||
|
console.log(mangoAccount.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
// deposit
|
||||||
|
console.log(`...depositing 50 USDC`);
|
||||||
|
await client.tokenDeposit(group, mangoAccount, 'USDC', 50);
|
||||||
|
await mangoAccount.reload(client, group);
|
||||||
|
|
||||||
|
console.log(`...depositing 0.0005 BTC`);
|
||||||
|
await client.tokenDeposit(group, mangoAccount, 'BTC', 0.0005);
|
||||||
|
await mangoAccount.reload(client, group);
|
||||||
|
|
||||||
|
// serum3
|
||||||
|
console.log(`...placing serum3 bid`);
|
||||||
|
await delegateClient.serum3PlaceOrder(
|
||||||
|
group,
|
||||||
|
mangoAccount,
|
||||||
|
'BTC/USDC',
|
||||||
|
Serum3Side.bid,
|
||||||
|
20,
|
||||||
|
0.0001,
|
||||||
|
Serum3SelfTradeBehavior.decrementTake,
|
||||||
|
Serum3OrderType.limit,
|
||||||
|
Date.now(),
|
||||||
|
10,
|
||||||
|
);
|
||||||
|
await mangoAccount.reload(delegateClient, group);
|
||||||
|
|
||||||
|
console.log(`...current own orders on OB`);
|
||||||
|
let orders = await delegateClient.getSerum3Orders(
|
||||||
|
group,
|
||||||
|
|
||||||
|
'BTC/USDC',
|
||||||
|
);
|
||||||
|
for (const order of orders) {
|
||||||
|
console.log(
|
||||||
|
` - order orderId ${order.orderId}, ${order.side}, ${order.price}, ${order.size}`,
|
||||||
|
);
|
||||||
|
console.log(` - cancelling order with ${order.orderId}`);
|
||||||
|
await delegateClient.serum3CancelOrder(
|
||||||
|
group,
|
||||||
|
mangoAccount,
|
||||||
|
'BTC/USDC',
|
||||||
|
order.side === 'buy' ? Serum3Side.bid : Serum3Side.ask,
|
||||||
|
order.orderId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`...settling funds`);
|
||||||
|
await delegateClient.serum3SettleFunds(
|
||||||
|
group,
|
||||||
|
mangoAccount,
|
||||||
|
|
||||||
|
'BTC/USDC',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
// perps
|
||||||
|
console.log(`...placing perp bid`);
|
||||||
|
try {
|
||||||
|
await delegateClient.perpPlaceOrder(
|
||||||
|
group,
|
||||||
|
mangoAccount,
|
||||||
|
'BTC-PERP',
|
||||||
|
Side.bid,
|
||||||
|
30000,
|
||||||
|
0.000001,
|
||||||
|
30000 * 0.000001,
|
||||||
|
Math.floor(Math.random() * 99999),
|
||||||
|
OrderType.limit,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
|
@ -1,5 +1,5 @@
|
||||||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||||
import { Connection, Keypair } from '@solana/web3.js';
|
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { OrderType, Side } from '../accounts/perp';
|
import { OrderType, Side } from '../accounts/perp';
|
||||||
import {
|
import {
|
||||||
|
@ -61,32 +61,47 @@ async function main() {
|
||||||
console.log(`...created/found mangoAccount ${mangoAccount.publicKey}`);
|
console.log(`...created/found mangoAccount ${mangoAccount.publicKey}`);
|
||||||
console.log(mangoAccount.toString());
|
console.log(mangoAccount.toString());
|
||||||
|
|
||||||
await mangoAccount.reloadAccountData(client, group);
|
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
// deposit and withdraw
|
// set delegate, and change name
|
||||||
console.log(`Depositing...50 USDC`);
|
console.log(`...changing mango account name, and setting a delegate`);
|
||||||
await client.tokenDeposit(group, mangoAccount, 'USDC', 50);
|
const randomKey = new PublicKey(
|
||||||
await mangoAccount.reload(client, group);
|
'4ZkS7ZZkxfsC3GtvvsHP3DFcUeByU9zzZELS4r8HCELo',
|
||||||
|
|
||||||
console.log(`Depositing...0.0005 BTC`);
|
|
||||||
await client.tokenDeposit(group, mangoAccount, 'BTC', 0.0005);
|
|
||||||
await mangoAccount.reload(client, group);
|
|
||||||
|
|
||||||
console.log(`Withdrawing...0.1 ORCA`);
|
|
||||||
await client.tokenWithdraw2(
|
|
||||||
group,
|
|
||||||
mangoAccount,
|
|
||||||
'ORCA',
|
|
||||||
0.1 * Math.pow(10, group.banksMap.get('ORCA').mintDecimals),
|
|
||||||
true,
|
|
||||||
);
|
);
|
||||||
|
await client.editMangoAccount(group, 'my_changed_name', randomKey);
|
||||||
await mangoAccount.reload(client, group);
|
await mangoAccount.reload(client, group);
|
||||||
console.log(mangoAccount.toString());
|
console.log(mangoAccount.toString());
|
||||||
|
|
||||||
|
console.log(`...resetting mango account name, and re-setting a delegate`);
|
||||||
|
await client.editMangoAccount(group, 'my_mango_account', PublicKey.default);
|
||||||
|
await mangoAccount.reload(client, group);
|
||||||
|
console.log(mangoAccount.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
// deposit and withdraw
|
||||||
|
console.log(`...depositing 50 USDC`);
|
||||||
|
await client.tokenDeposit(group, mangoAccount, 'USDC', 50);
|
||||||
|
await mangoAccount.reload(client, group);
|
||||||
|
|
||||||
|
console.log(`...depositing 0.0005 BTC`);
|
||||||
|
await client.tokenDeposit(group, mangoAccount, 'BTC', 0.0005);
|
||||||
|
await mangoAccount.reload(client, group);
|
||||||
|
|
||||||
|
// witdrawing fails if no (other) user has deposited ORCA in the group
|
||||||
|
// console.log(`Withdrawing...0.1 ORCA`);
|
||||||
|
// await client.tokenWithdraw2(
|
||||||
|
// group,
|
||||||
|
// mangoAccount,
|
||||||
|
// 'ORCA',
|
||||||
|
// 0.1 * Math.pow(10, group.banksMap.get('ORCA').mintDecimals),
|
||||||
|
// true,
|
||||||
|
// );
|
||||||
|
// await mangoAccount.reload(client, group);
|
||||||
|
// console.log(mangoAccount.toString());
|
||||||
|
|
||||||
// serum3
|
// serum3
|
||||||
console.log(
|
console.log(
|
||||||
`Placing serum3 bid which would not be settled since its relatively low then midprice...`,
|
`...placing serum3 bid which would not be settled since its relatively low then midprice`,
|
||||||
);
|
);
|
||||||
await client.serum3PlaceOrder(
|
await client.serum3PlaceOrder(
|
||||||
group,
|
group,
|
||||||
|
@ -103,7 +118,7 @@ async function main() {
|
||||||
);
|
);
|
||||||
await mangoAccount.reload(client, group);
|
await mangoAccount.reload(client, group);
|
||||||
|
|
||||||
console.log(`Placing serum3 bid way above midprice...`);
|
console.log(`...placing serum3 bid way above midprice`);
|
||||||
await client.serum3PlaceOrder(
|
await client.serum3PlaceOrder(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -119,7 +134,7 @@ async function main() {
|
||||||
);
|
);
|
||||||
await mangoAccount.reload(client, group);
|
await mangoAccount.reload(client, group);
|
||||||
|
|
||||||
console.log(`Placing serum3 ask way below midprice...`);
|
console.log(`...placing serum3 ask way below midprice`);
|
||||||
await client.serum3PlaceOrder(
|
await client.serum3PlaceOrder(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -134,7 +149,7 @@ async function main() {
|
||||||
10,
|
10,
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`Current own orders on OB...`);
|
console.log(`...current own orders on OB`);
|
||||||
let orders = await client.getSerum3Orders(
|
let orders = await client.getSerum3Orders(
|
||||||
group,
|
group,
|
||||||
|
|
||||||
|
@ -142,9 +157,9 @@ async function main() {
|
||||||
);
|
);
|
||||||
for (const order of orders) {
|
for (const order of orders) {
|
||||||
console.log(
|
console.log(
|
||||||
` - Order orderId ${order.orderId}, ${order.side}, ${order.price}, ${order.size}`,
|
` - order orderId ${order.orderId}, ${order.side}, ${order.price}, ${order.size}`,
|
||||||
);
|
);
|
||||||
console.log(` - Cancelling order with ${order.orderId}`);
|
console.log(` - cancelling order with ${order.orderId}`);
|
||||||
await client.serum3CancelOrder(
|
await client.serum3CancelOrder(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -155,7 +170,7 @@ async function main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Current own orders on OB...`);
|
console.log(`...current own orders on OB`);
|
||||||
orders = await client.getSerum3Orders(
|
orders = await client.getSerum3Orders(
|
||||||
group,
|
group,
|
||||||
|
|
||||||
|
@ -165,7 +180,7 @@ async function main() {
|
||||||
console.log(order);
|
console.log(order);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Settling funds...`);
|
console.log(`...settling funds`);
|
||||||
await client.serum3SettleFunds(
|
await client.serum3SettleFunds(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -177,23 +192,23 @@ async function main() {
|
||||||
if (true) {
|
if (true) {
|
||||||
await mangoAccount.reload(client, group);
|
await mangoAccount.reload(client, group);
|
||||||
console.log(
|
console.log(
|
||||||
'mangoAccount.getEquity() ' +
|
'...mangoAccount.getEquity() ' +
|
||||||
toUiDecimals(mangoAccount.getEquity().toNumber()),
|
toUiDecimals(mangoAccount.getEquity().toNumber()),
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
'mangoAccount.getCollateralValue() ' +
|
'...mangoAccount.getCollateralValue() ' +
|
||||||
toUiDecimals(mangoAccount.getCollateralValue().toNumber()),
|
toUiDecimals(mangoAccount.getCollateralValue().toNumber()),
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
'mangoAccount.getAssetsVal() ' +
|
'...mangoAccount.getAssetsVal() ' +
|
||||||
toUiDecimals(mangoAccount.getAssetsVal().toNumber()),
|
toUiDecimals(mangoAccount.getAssetsVal().toNumber()),
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
'mangoAccount.getLiabsVal() ' +
|
'...mangoAccount.getLiabsVal() ' +
|
||||||
toUiDecimals(mangoAccount.getLiabsVal().toNumber()),
|
toUiDecimals(mangoAccount.getLiabsVal().toNumber()),
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
"mangoAccount.getMaxWithdrawWithBorrowForToken(group, 'SOL') " +
|
'...mangoAccount.getMaxWithdrawWithBorrowForToken(group, "SOL") ' +
|
||||||
toUiDecimals(
|
toUiDecimals(
|
||||||
(
|
(
|
||||||
await mangoAccount.getMaxWithdrawWithBorrowForToken(group, 'SOL')
|
await mangoAccount.getMaxWithdrawWithBorrowForToken(group, 'SOL')
|
||||||
|
@ -201,7 +216,7 @@ async function main() {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
"mangoAccount.getSerum3MarketMarginAvailable(group, 'BTC/USDC') " +
|
"...mangoAccount.getSerum3MarketMarginAvailable(group, 'BTC/USDC') " +
|
||||||
toUiDecimals(
|
toUiDecimals(
|
||||||
mangoAccount
|
mangoAccount
|
||||||
.getSerum3MarketMarginAvailable(group, 'BTC/USDC')
|
.getSerum3MarketMarginAvailable(group, 'BTC/USDC')
|
||||||
|
@ -209,7 +224,7 @@ async function main() {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
"mangoAccount.getPerpMarketMarginAvailable(group, 'BTC-PERP') " +
|
"...mangoAccount.getPerpMarketMarginAvailable(group, 'BTC-PERP') " +
|
||||||
toUiDecimals(
|
toUiDecimals(
|
||||||
mangoAccount
|
mangoAccount
|
||||||
.getPerpMarketMarginAvailable(group, 'BTC-PERP')
|
.getPerpMarketMarginAvailable(group, 'BTC-PERP')
|
||||||
|
@ -220,7 +235,7 @@ async function main() {
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
// perps
|
// perps
|
||||||
console.log(`Placing perp bid...`);
|
console.log(`...placing perp bid`);
|
||||||
try {
|
try {
|
||||||
await client.perpPlaceOrder(
|
await client.perpPlaceOrder(
|
||||||
group,
|
group,
|
||||||
|
@ -239,7 +254,7 @@ async function main() {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Placing perp ask...`);
|
console.log(`...placing perp ask`);
|
||||||
await client.perpPlaceOrder(
|
await client.perpPlaceOrder(
|
||||||
group,
|
group,
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
|
@ -257,7 +272,7 @@ async function main() {
|
||||||
while (true) {
|
while (true) {
|
||||||
// TODO: quotePositionNative might be buggy on program side, investigate...
|
// TODO: quotePositionNative might be buggy on program side, investigate...
|
||||||
console.log(
|
console.log(
|
||||||
`Waiting for self trade to consume (note: make sure keeper crank is running)...`,
|
`...waiting for self trade to consume (note: make sure keeper crank is running)`,
|
||||||
);
|
);
|
||||||
await mangoAccount.reload(client, group);
|
await mangoAccount.reload(client, group);
|
||||||
console.log(mangoAccount.toString());
|
console.log(mangoAccount.toString());
|
||||||
|
|
Loading…
Reference in New Issue