Skip to content

Commit

Permalink
Add instruction for open orders initialization (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
armaniferrante authored May 31, 2021
1 parent 2d4a7a9 commit ec29034
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 3 deletions.
55 changes: 52 additions & 3 deletions dex/crank/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ use serum_common::client::Cluster;
use serum_context::Context;
use serum_dex::instruction::{
cancel_order_by_client_order_id as cancel_order_by_client_order_id_ix,
close_open_orders as close_open_orders_ix, MarketInstruction, NewOrderInstructionV3,
SelfTradeBehavior,
close_open_orders as close_open_orders_ix, init_open_orders as init_open_orders_ix,
MarketInstruction, NewOrderInstructionV3, SelfTradeBehavior,
};
use serum_dex::matching::{OrderType, Side};
use serum_dex::state::gen_vault_signer_key;
Expand Down Expand Up @@ -850,8 +850,12 @@ fn whole_shebang(client: &RpcClient, program_id: &Pubkey, payer: &Keypair) -> Re
)?;
debug_println!("Minted {}", pc_wallet.pubkey());

debug_println!("Placing bid...");
let mut orders = None;

debug_println!("Initializing open orders");
init_open_orders(client, program_id, payer, &market_keys, &mut orders)?;

debug_println!("Placing bid...");
place_order(
client,
program_id,
Expand Down Expand Up @@ -997,6 +1001,51 @@ pub fn close_open_orders(
Ok(())
}

pub fn init_open_orders(
client: &RpcClient,
program_id: &Pubkey,
owner: &Keypair,
state: &MarketPubkeys,
orders: &mut Option<Pubkey>,
) -> Result<()> {
let mut instructions = Vec::new();
let orders_keypair;
let mut signers = Vec::new();
let orders_pubkey = match *orders {
Some(pk) => pk,
None => {
let (orders_key, instruction) = create_dex_account(
client,
program_id,
&owner.pubkey(),
size_of::<serum_dex::state::OpenOrders>(),
)?;
orders_keypair = orders_key;
signers.push(&orders_keypair);
instructions.push(instruction);
orders_keypair.pubkey()
}
};
*orders = Some(orders_pubkey);
instructions.push(init_open_orders_ix(
program_id,
&orders_pubkey,
&owner.pubkey(),
&state.market,
)?);
signers.push(owner);

let (recent_hash, _fee_calc) = client.get_recent_blockhash()?;
let txn = Transaction::new_signed_with_payer(
&instructions,
Some(&owner.pubkey()),
&signers,
recent_hash,
);
send_txn(client, &txn, false)?;
Ok(())
}

pub fn place_order(
client: &RpcClient,
program_id: &Pubkey,
Expand Down
26 changes: 26 additions & 0 deletions dex/fuzz/fuzz_targets/multiple_orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ enum Action {
ConsumeEvents(u16),
SettleFunds(OwnerId, Option<ReferrerId>),
SweepFees,
InitOpenOrders {
owner_id: OwnerId,
},
CloseOpenOrders {
owner_id: OwnerId,
},
Expand Down Expand Up @@ -585,6 +588,29 @@ fn run_action<'bump>(
)
.unwrap();
}

Action::InitOpenOrders { owner_id } => {
let owner = owners
.entry(owner_id)
.or_insert_with(|| Owner::new(&market_accounts, &bump));
process_instruction(
market_accounts.market.owner,
&[
owner.orders_account.clone(),
owner.signer_account.clone(),
market_accounts.market.clone(),
market_accounts.rent_sysvar.clone(),
],
&MarketInstruction::InitOpenOrders.pack(),
)
.map_err(|e| match e {
DexError::ErrorCode(DexErrorCode::WrongOrdersAccount)
if owner.closed_open_orders => {}
e => Err(e).unwrap(),
})
.ok();
}

Action::CloseOpenOrders { owner_id } => {
let owner = owners
.entry(owner_id)
Expand Down
26 changes: 26 additions & 0 deletions dex/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,11 @@ pub enum MarketInstruction {
/// 2. `[writable]` the destination account to send rent exemption SOL to
/// 3. `[]` market
CloseOpenOrders,
/// 0. `[writable]` OpenOrders
/// 1. `[signer]` the OpenOrders owner
/// 2. `[]` market
/// 3. `[]` the rent sysvar
InitOpenOrders,
}

impl MarketInstruction {
Expand Down Expand Up @@ -530,6 +535,7 @@ impl MarketInstruction {
SendTakeInstruction::unpack(data_arr)?
}),
(14, 0) => MarketInstruction::CloseOpenOrders,
(15, 0) => MarketInstruction::InitOpenOrders,
_ => return None,
})
}
Expand Down Expand Up @@ -873,6 +879,26 @@ pub fn close_open_orders(
})
}

pub fn init_open_orders(
program_id: &Pubkey,
open_orders: &Pubkey,
owner: &Pubkey,
market: &Pubkey,
) -> Result<Instruction, DexError> {
let data = MarketInstruction::InitOpenOrders.pack();
let accounts: Vec<AccountMeta> = vec![
AccountMeta::new(*open_orders, false),
AccountMeta::new_readonly(*owner, true),
AccountMeta::new_readonly(*market, false),
AccountMeta::new_readonly(rent::ID, false),
];
Ok(Instruction {
program_id: *program_id,
data,
accounts,
})
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
50 changes: 50 additions & 0 deletions dex/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2048,6 +2048,45 @@ pub(crate) mod account_parser {
})
}
}

pub struct InitOpenOrdersArgs;

impl InitOpenOrdersArgs {
pub fn with_parsed_args<T>(
program_id: &Pubkey,
accounts: &[AccountInfo],
f: impl FnOnce(InitOpenOrdersArgs) -> DexResult<T>,
) -> DexResult<T> {
// Parse accounts.
check_assert_eq!(accounts.len(), 4)?;
#[rustfmt::skip]
let &[
ref open_orders_acc,
ref owner_acc,
ref market_acc,
ref rent_acc,
] = array_ref![accounts, 0, 4];

// Validate the accounts given are valid.
let rent = {
let rent_sysvar = RentSysvarAccount::new(rent_acc)?;
Rent::from_account_info(rent_sysvar.inner()).or(check_unreachable!())?
};
let owner = SignerAccount::new(owner_acc)?;
let market = MarketState::load(market_acc, program_id)?;

// Perform open orders initialization.
let _open_orders = market.load_orders_mut(
open_orders_acc,
Some(owner.inner()),
program_id,
Some(rent),
)?;

// Invoke processor.
f(InitOpenOrdersArgs)
}
}
}

#[inline]
Expand Down Expand Up @@ -2150,6 +2189,13 @@ impl State {
Self::process_close_open_orders,
)?
}
MarketInstruction::InitOpenOrders => {
account_parser::InitOpenOrdersArgs::with_parsed_args(
program_id,
accounts,
Self::process_init_open_orders,
)?
}
};
Ok(())
}
Expand All @@ -2159,6 +2205,10 @@ impl State {
unimplemented!()
}

fn process_init_open_orders(_args: account_parser::InitOpenOrdersArgs) -> DexResult {
Ok(())
}

fn process_close_open_orders(args: account_parser::CloseOpenOrdersArgs) -> DexResult {
let account_parser::CloseOpenOrdersArgs {
open_orders,
Expand Down

0 comments on commit ec29034

Please sign in to comment.