use super::*;
use crate::test_support::{Recorded, block_on};
const PAGE: &str = include_str!("../../../../fixtures/lighter/trades_1.json");
fn page() -> TradePage {
serde_json::from_str(PAGE).unwrap()
}
fn index(account: u64) -> AccountIndex {
AccountIndex::new(account).unwrap()
}
#[test]
fn a_recorded_trade_is_the_maker_s_fill_on_one_side_and_the_taker_s_on_the_other() {
let trade = &page().trades[0];
let maker = Fill::of(trade, index(702_384)).unwrap();
assert_eq!((maker.side, maker.is_maker, maker.fee_rate), (Side::Bid, true, 28));
assert_eq!(maker.fee.to_string(), "0.010748", "383.840469 at 0.0028%");
assert_eq!(maker.realized_pnl, Some(Dec::ZERO), "a long buying adds");
assert_eq!(
(maker.order_index(), maker.client_order_index().map(ClientOrderIndex::get)),
(844_421_215_082_639, Some(105_497_301_242_118))
);
let taker = Fill::of(trade, index(750_486)).unwrap();
assert_eq!((taker.side, taker.is_maker, taker.fee_rate, taker.fee), (Side::Ask, false, 0, Dec::ZERO));
assert_eq!(taker.realized_pnl, Some(Dec::ZERO), "a short selling adds");
assert_eq!((taker.market().get(), taker.timestamp_ms(), taker.is_liquidation()), (1, 1_792_918_079_391, false));
assert_eq!((taker.price().to_string(), taker.size().to_string()), ("80469.7".to_owned(), "0.00477".to_owned()));
assert_eq!(Fill::of(trade, index(1)), None, "not the account's");
}
#[test]
fn a_fill_against_the_position_realizes_against_its_average_entry() {
let text = r#"{"trade_id":1,"tx_hash":"00","type":"trade","market_id":1,"size":"3","price":"110",
"usd_amount":"330","ask_id":562949953421313,"bid_id":562949953421314,"ask_account_id":7,"bid_account_id":8,
"is_maker_ask":false,"timestamp":1790000000000,"taker_fee":280,"taker_position_size_before":"2",
"taker_entry_quote_before":"200","maker_position_size_before":"-1","maker_entry_quote_before":"120",
"ask_account_pnl":"20.000000"}"#;
let trade: Trade = serde_json::from_str(text).unwrap();
let seller = Fill::of(&trade, index(7)).unwrap();
assert_eq!(seller.realized_pnl.map(|pnl| pnl.to_string()).as_deref(), Some("20"), "2 closed at 110 against 100");
assert_eq!(
(seller.fee.to_string(), seller.venue_pnl().map(|pnl| pnl.to_string())),
("0.0924".to_owned(), Some("20".to_owned()))
);
let buyer = Fill::of(&trade, index(8)).unwrap();
assert_eq!(
buyer.realized_pnl.map(|pnl| pnl.to_string()).as_deref(),
Some("10"),
"a short of 1 at 120 bought back at 110"
);
assert_eq!((buyer.is_maker, buyer.fee), (true, Dec::ZERO));
assert_eq!(realized(Side::Ask, Dec::ONE, Dec::ONE, None, Some(Dec::ONE)), None, "no position before, no figure");
let third = Dec::parse("0.000001").unwrap();
let odd = realized(Side::Ask, Dec::from_int(1), Dec::from_int(1), Some(Dec::from_int(3)), Some(third));
assert_eq!(odd.map(|pnl| pnl.to_string()).as_deref(), Some("1"), "rounded once, to six places");
assert_eq!(fee(Dec::parse("1000").unwrap(), 10_000).to_string(), "10", "the 1% liquidation fee");
}
#[test]
fn the_account_s_trades_are_asked_with_the_token_and_every_filter() {
let transport = Recorded::answering(PAGE);
let query = TradeQuery {
market: Some(MarketId::new(1).unwrap()),
kinds: vec![MarketKind::Perps],
role: Some(Role::Taker),
kind: Some(TradeKind::Liquidation),
side: Some(Side::Bid),
limit: 0,
..TradeQuery::new(index(702_384))
};
let first = block_on(account_trades(&transport, &query)).unwrap();
assert_eq!((first.trades.len(), first.next()), (5, Some("eyJpbmRleCI6MzYzODg2MjcxNDJ9")));
let call = transport.only();
assert_eq!((call.path, call.auth), ("trades", true));
assert_eq!(
call.fields,
[
("account_index", "702384".to_owned()),
("market_id", "1".to_owned()),
("market_type", "perp".to_owned()),
("sort_by", "timestamp".to_owned()),
("ask_filter", "0".to_owned()),
("role", "taker".to_owned()),
("type", "liquidation".to_owned()),
("limit", "1".to_owned()),
]
);
assert_eq!(
account_trades_call(&query.after(&first).unwrap()).value("cursor"),
Some("eyJpbmRleCI6MzYzODg2MjcxNDJ9")
);
}
#[test]
fn fills_since_reads_pages_until_one_reaches_back_past_the_start() {
let account = index(702_384);
let transport = Recorded::answering(PAGE);
let all = block_on(fills_since(&transport, account, &[], 0, 3)).unwrap();
assert_eq!(transport.sent().len(), 3, "never past the pages asked");
assert_eq!(all.len(), 3 * page().trades.iter().filter(|trade| trade.side_of(account).is_some()).count());
assert_eq!(all.len(), 6);
let transport = Recorded::answering(PAGE);
let later = block_on(fills_since(&transport, account, &[MarketKind::Perps], 1_792_918_079_392, 5)).unwrap();
assert_eq!((transport.sent().len(), later.len()), (1, 0), "the first page already reached back past it");
assert_eq!(transport.sent()[0].value("market_type"), Some("perp"));
}