mango-v4/programs/mango-v4/tests/test_serum.rs

238 lines
5.7 KiB
Rust

#![cfg(feature = "test-bpf")]
use solana_program_test::*;
use solana_sdk::{signature::Keypair, signer::Signer, transport::TransportError};
use mango_v4::{
instructions::{Serum3OrderType, Serum3SelfTradeBehavior, Serum3Side},
state::*,
};
use program_test::*;
mod program_test;
#[tokio::test]
async fn test_serum() -> 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 mints = &context.mints[0..2];
let payer_mint_accounts = &context.users[1].token_accounts[0..=2];
//
// SETUP: Create a group and an account
//
let mango_setup::GroupWithTokens { group, tokens, .. } = mango_setup::GroupWithTokensConfig {
admin,
payer,
mints,
}
.create(solana)
.await;
let base_token = &tokens[0];
let quote_token = &tokens[1];
let account = send_tx(
solana,
AccountCreateInstruction {
account_num: 0,
account_size: AccountSize::Large,
group,
owner,
payer,
},
)
.await
.unwrap()
.account;
//
// SETUP: Create serum market
//
let serum_market_cookie = context
.serum
.list_spot_market(&base_token.mint, &quote_token.mint)
.await;
//
// SETUP: Deposit user funds
//
{
let deposit_amount = 1000;
send_tx(
solana,
TokenDepositInstruction {
amount: deposit_amount,
account,
token_account: payer_mint_accounts[0],
token_authority: payer.clone(),
bank_index: 0,
},
)
.await
.unwrap();
send_tx(
solana,
TokenDepositInstruction {
amount: deposit_amount,
account,
token_account: payer_mint_accounts[1],
token_authority: payer.clone(),
bank_index: 0,
},
)
.await
.unwrap();
}
//
// TEST: Register a serum market
//
let serum_market = send_tx(
solana,
Serum3RegisterMarketInstruction {
group,
admin,
serum_program: context.serum.program_id,
serum_market_external: serum_market_cookie.market,
market_index: 0,
base_bank: base_token.bank,
quote_bank: quote_token.bank,
payer,
},
)
.await
.unwrap()
.serum_market;
//
// TEST: Create an open orders account
//
let open_orders = send_tx(
solana,
Serum3CreateOpenOrdersInstruction {
account,
serum_market,
owner,
payer,
},
)
.await
.unwrap()
.open_orders;
let account_data = get_mango_account(solana, account).await;
assert_eq!(
account_data
.serum3_iter_active()
.map(|v| (v.open_orders, v.market_index))
.collect::<Vec<_>>(),
[(open_orders, 0)]
);
//
// TEST: Place an order
//
send_tx(
solana,
Serum3PlaceOrderInstruction {
side: Serum3Side::Bid,
limit_price: 10, // in quote_lot (10) per base lot (100)
max_base_qty: 1, // in base lot (100)
max_native_quote_qty_including_fees: 100,
self_trade_behavior: Serum3SelfTradeBehavior::DecrementTake,
order_type: Serum3OrderType::Limit,
client_order_id: 0,
limit: 10,
account,
owner,
serum_market,
},
)
.await
.unwrap();
let native0 = account_position(solana, account, base_token.bank).await;
let native1 = account_position(solana, account, quote_token.bank).await;
assert_eq!(native0, 1000);
assert_eq!(native1, 900);
// get the order id
let open_orders_bytes = solana.get_account_data(open_orders).await.unwrap();
let open_orders_data: &serum_dex::state::OpenOrders = bytemuck::from_bytes(
&open_orders_bytes[5..5 + std::mem::size_of::<serum_dex::state::OpenOrders>()],
);
let order_id = open_orders_data.orders[0];
assert!(order_id != 0);
//
// TEST: Cancel the order
//
send_tx(
solana,
Serum3CancelOrderInstruction {
side: Serum3Side::Bid,
order_id,
account,
owner,
serum_market,
},
)
.await
.unwrap();
//
// TEST: Settle, moving the freed up funds back
//
send_tx(
solana,
Serum3SettleFundsInstruction {
account,
owner,
serum_market,
},
)
.await
.unwrap();
let native0 = account_position(solana, account, base_token.bank).await;
let native1 = account_position(solana, account, quote_token.bank).await;
assert_eq!(native0, 1000);
assert_eq!(native1, 1000);
// close oo account
// TODO: custom program error: 0x2a TooManyOpenOrders https://github.com/project-serum/serum-dex/blob/master/dex/src/error.rs#L88
// send_tx(
// solana,
// Serum3CloseOpenOrdersInstruction {
// account,
// serum_market,
// owner,
// sol_destination: payer.pubkey(),
// },
// )
// .await
// .unwrap();
// deregister serum3 market
send_tx(
solana,
Serum3DeregisterMarketInstruction {
group,
admin,
serum_market_external: serum_market_cookie.market,
sol_destination: payer.pubkey(),
},
)
.await
.unwrap();
Ok(())
}