Skip to content

Commit

Permalink
add test
Browse files Browse the repository at this point in the history
  • Loading branch information
riordanp committed Feb 14, 2024
1 parent 3f9b6ad commit 2d7afab
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 5 deletions.
12 changes: 9 additions & 3 deletions programs/openbook-v2/src/instructions/settle_funds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@ use crate::token_utils::*;

pub fn settle_funds<'info>(ctx: Context<'_, '_, '_, 'info, SettleFunds<'info>>) -> Result<()> {
let mut open_orders_account = ctx.accounts.open_orders_account.load_mut()?;

// ensure delegate can only withdraw to owner's token accounts
let delegate_option: Option<Pubkey> = Option::from(open_orders_account.delegate);
let signer = ctx.accounts.owner.key();
if Some(signer) == delegate_option {
assert_eq!(ctx.accounts.user_base_account.owner, open_orders_account.owner);
assert_eq!(ctx.accounts.user_quote_account.owner, open_orders_account.owner);
assert_eq!(
ctx.accounts.user_base_account.owner,
open_orders_account.owner
);
assert_eq!(
ctx.accounts.user_quote_account.owner,
open_orders_account.owner
);
}

let mut market = ctx.accounts.market.load_mut()?;
Expand Down
218 changes: 218 additions & 0 deletions programs/openbook-v2/tests/cases/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,224 @@ async fn test_simple_settle() -> Result<(), TransportError> {
Ok(())
}

#[tokio::test]
async fn test_delegate_settle() -> Result<(), TransportError> {
let TestInitialize {
context,
collect_fee_admin,
owner,
payer,
mints,
owner_token_0,
owner_token_1,
market,
market_base_vault,
market_quote_vault,
price_lots,
tokens,
account_1,
account_2,
..
} = TestContext::new_with_market(TestNewMarketInitialize {
close_market_admin_bool: true,
payer_as_delegate: true,
..TestNewMarketInitialize::default()
})
.await?;
let solana = &context.solana.clone();
let payer_token_0 = context.users[1].token_accounts[0];
let payer_token_1 = context.users[1].token_accounts[1];

//
// TEST: Create another market
//

let market_2 = TestKeypair::new();

send_tx(
solana,
CreateMarketInstruction {
collect_fee_admin: collect_fee_admin.pubkey(),
open_orders_admin: None,
close_market_admin: None,
payer,
market: market_2,
quote_lot_size: 10,
base_lot_size: 100,
maker_fee: -200,
taker_fee: 400,
base_mint: mints[0].pubkey,
quote_mint: mints[1].pubkey,
..CreateMarketInstruction::with_new_book_and_heap(solana, None, None).await
},
)
.await
.unwrap();

// Set the initial oracle price
set_stub_oracle_price(solana, &tokens[1], collect_fee_admin, 1000.0).await;

send_tx(
solana,
PlaceOrderInstruction {
open_orders_account: account_1,
open_orders_admin: None,
market,
signer: owner,
user_token_account: owner_token_1,
market_vault: market_quote_vault,
side: Side::Bid,
price_lots,
max_base_lots: 1,
max_quote_lots_including_fees: 10000,

client_order_id: 0,
expiry_timestamp: 0,
order_type: PlaceOrderType::Limit,
self_trade_behavior: SelfTradeBehavior::default(),
remainings: vec![],
},
)
.await
.unwrap();

send_tx(
solana,
PlaceOrderInstruction {
open_orders_account: account_2,
open_orders_admin: None,
market,
signer: owner,
user_token_account: owner_token_0,
market_vault: market_base_vault,
side: Side::Ask,
price_lots,
max_base_lots: 1,
max_quote_lots_including_fees: 10000,

client_order_id: 0,
expiry_timestamp: 0,
order_type: PlaceOrderType::Limit,
self_trade_behavior: SelfTradeBehavior::default(),
remainings: vec![],
},
)
.await
.unwrap();

{
let open_orders_account_1 = solana.get_account::<OpenOrdersAccount>(account_1).await;
let open_orders_account_2 = solana.get_account::<OpenOrdersAccount>(account_2).await;

assert_eq!(open_orders_account_1.position.bids_base_lots, 1);
assert_eq!(open_orders_account_2.position.bids_base_lots, 0);
assert_eq!(open_orders_account_1.position.asks_base_lots, 0);
assert_eq!(open_orders_account_2.position.asks_base_lots, 0);
assert_eq!(open_orders_account_1.position.base_free_native, 0);
assert_eq!(open_orders_account_2.position.base_free_native, 0);
assert_eq!(open_orders_account_1.position.quote_free_native, 0);
assert_eq!(open_orders_account_2.position.quote_free_native, 99960);
}

send_tx(
solana,
ConsumeEventsInstruction {
consume_events_admin: None,
market,
open_orders_accounts: vec![account_1, account_2],
},
)
.await
.unwrap();

{
let open_orders_account_1 = solana.get_account::<OpenOrdersAccount>(account_1).await;
let open_orders_account_2 = solana.get_account::<OpenOrdersAccount>(account_2).await;

assert_eq!(open_orders_account_1.position.bids_base_lots, 0);
assert_eq!(open_orders_account_2.position.bids_base_lots, 0);
assert_eq!(open_orders_account_1.position.asks_base_lots, 0);
assert_eq!(open_orders_account_2.position.asks_base_lots, 0);
assert_eq!(open_orders_account_1.position.base_free_native, 100);
assert_eq!(open_orders_account_2.position.base_free_native, 0);
assert_eq!(open_orders_account_1.position.quote_free_native, 20);
assert_eq!(open_orders_account_2.position.quote_free_native, 99960);
}

// delegate settle to own account fails
assert!(send_tx(
solana,
SettleFundsInstruction {
owner: payer,
market,
open_orders_account: account_1,
market_base_vault,
market_quote_vault,
user_base_account: payer_token_0,
user_quote_account: payer_token_1,
referrer_account: None,
},
)
.await
.is_err());

// delegate settle to owner succeeds
send_tx(
solana,
SettleFundsInstruction {
owner: payer,
market,
open_orders_account: account_1,
market_base_vault,
market_quote_vault,
user_base_account: owner_token_0,
user_quote_account: owner_token_1,
referrer_account: None,
},
)
.await
.unwrap();

{
let open_orders_account_1 = solana.get_account::<OpenOrdersAccount>(account_1).await;
let open_orders_account_2 = solana.get_account::<OpenOrdersAccount>(account_2).await;

assert_eq!(open_orders_account_1.position.base_free_native, 0);
assert_eq!(open_orders_account_2.position.base_free_native, 0);
assert_eq!(open_orders_account_1.position.quote_free_native, 0);
assert_eq!(open_orders_account_2.position.quote_free_native, 99960);
}

// owner settle to payer account succeeds
send_tx(
solana,
SettleFundsInstruction {
owner,
market,
open_orders_account: account_2,
market_base_vault,
market_quote_vault,
user_base_account: payer_token_0,
user_quote_account: payer_token_1,
referrer_account: None,
},
)
.await
.unwrap();

{
let open_orders_account_1 = solana.get_account::<OpenOrdersAccount>(account_1).await;
let open_orders_account_2 = solana.get_account::<OpenOrdersAccount>(account_2).await;

assert_eq!(open_orders_account_1.position.base_free_native, 0);
assert_eq!(open_orders_account_2.position.base_free_native, 0);
assert_eq!(open_orders_account_1.position.quote_free_native, 0);
assert_eq!(open_orders_account_2.position.quote_free_native, 0);
}

Ok(())
}

#[tokio::test]
async fn test_cancel_orders() -> Result<(), TransportError> {
let TestInitialize {
Expand Down
14 changes: 12 additions & 2 deletions programs/openbook-v2/tests/program_test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ pub struct TestNewMarketInitialize {
pub consume_events_admin_bool: bool,
pub time_expiry: i64,
pub with_oracle: bool,
pub payer_as_delegate: bool,
}

impl Default for TestNewMarketInitialize {
Expand All @@ -296,6 +297,7 @@ impl Default for TestNewMarketInitialize {
consume_events_admin_bool: false,
time_expiry: 0,
with_oracle: true,
payer_as_delegate: false,
}
}
}
Expand Down Expand Up @@ -380,10 +382,18 @@ impl TestContext {

let _indexer = create_open_orders_indexer(solana, &context.users[1], owner, market).await;

let delegate_opt = if args.payer_as_delegate {
Some(payer.pubkey())
} else {
None
};

let account_1 =
create_open_orders_account(solana, owner, market, 1, &context.users[1], None).await;
create_open_orders_account(solana, owner, market, 1, &context.users[1], delegate_opt)
.await;
let account_2 =
create_open_orders_account(solana, owner, market, 2, &context.users[1], None).await;
create_open_orders_account(solana, owner, market, 2, &context.users[1], delegate_opt)
.await;

let price_lots = {
let market = solana.get_account::<Market>(market).await;
Expand Down

0 comments on commit 2d7afab

Please sign in to comment.