use alloy::{
network::Ethereum,
primitives::{Address, I256, U256},
providers::PendingTransactionBuilder,
};
use fastnum::UD64;
use super::TestExchange;
use crate::{abi::dex_legacy::LegacyExchange, error::DexError, num, state, types};
#[derive(Debug)]
pub struct TestPerp<'e> {
pub id: types::PerpetualId,
pub name: String,
pub price_converter: num::Converter,
pub size_converter: num::Converter,
pub leverage_converter: num::Converter,
pub exchange: &'e TestExchange,
}
impl<'e> TestPerp<'e> {
pub async fn with_mark_price(self, price: UD64) -> Self {
self.exchange
.exchange
.updateMarkPricePNS(U256::from(self.id), self.price_converter.to_unsigned(price).to())
.from(self.exchange.price_admin)
.gas(500000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
.get_receipt()
.await
.unwrap();
self
}
pub async fn with_min_post(self, min: U256) -> Self {
self.exchange
.exchange
.setMinPost(min)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
.get_receipt()
.await
.unwrap();
self
}
pub async fn with_min_settle(self, min: U256) -> Self {
self.exchange
.exchange
.setMinSettle(min)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
.get_receipt()
.await
.unwrap();
self
}
pub async fn unpause(self) -> Self {
self.exchange
.exchange
.setContractPaused(U256::from(self.id), false)
.gas(500000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
.get_receipt()
.await
.unwrap();
self
}
pub async fn set_maintenance_margin(
&self,
maintenance_margin: UD64,
) -> PendingTransactionBuilder<Ethereum> {
self.exchange
.exchange
.setMaintenanceMarginFraction(
U256::from(self.id),
self.leverage_converter.to_unsigned(maintenance_margin),
)
.gas(500000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
}
pub async fn set_mark_price(&self, price: UD64) -> PendingTransactionBuilder<Ethereum> {
self.exchange
.exchange
.updateMarkPricePNS(U256::from(self.id), self.price_converter.to_unsigned(price).to())
.from(self.exchange.price_admin)
.gas(500000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
}
pub async fn set_funding_rate(
&self,
price: u32,
rate: i32,
) -> PendingTransactionBuilder<Ethereum> {
self.exchange
.exchange
.setFundingSum(U256::from(self.id), I256::try_from(rate).unwrap(), price, true, true)
.from(self.exchange.anvil.addresses()[2]) .gas(500000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
}
pub async fn with_legacy_fees(self, taker_fee: UD64, maker_fee: UD64) -> Self {
let legacy =
LegacyExchange::new(*self.exchange.exchange.address(), self.exchange.provider.clone());
let fee_converter = num::fee_converter();
legacy
.setTakerFee(U256::from(self.id), fee_converter.to_unsigned(taker_fee))
.gas(500000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
.get_receipt()
.await
.unwrap();
legacy
.setMakerFee(U256::from(self.id), fee_converter.to_unsigned(maker_fee))
.gas(500000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
.get_receipt()
.await
.unwrap();
self
}
pub async fn set_fee_schedule(
&self,
taker_fees: [UD64; state::FEE_TIERS],
maker_fees: [UD64; state::FEE_TIERS],
) -> PendingTransactionBuilder<Ethereum> {
self.set_own_fee_schedule_values(taker_fees, maker_fees)
.await;
self.use_own_fee_schedule().await
}
pub async fn set_own_fee_schedule_values(
&self,
taker_fees: [UD64; state::FEE_TIERS],
maker_fees: [UD64; state::FEE_TIERS],
) {
let fee_converter = num::fee_converter();
self.exchange
.exchange
.setFeeSchedValues(
U256::from(self.id),
taker_fees.map(|fee| fee_converter.to_unsigned(fee)),
maker_fees.map(|fee| fee_converter.to_unsigned(fee)),
)
.gas(500000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
.get_receipt()
.await
.unwrap();
}
pub async fn use_own_fee_schedule(&self) -> PendingTransactionBuilder<Ethereum> {
self.exchange
.exchange
.setPerpToFeeSchedule(U256::from(self.id), U256::from(self.id))
.gas(500000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
}
pub async fn set_rwa_default_fee(&self) -> PendingTransactionBuilder<Ethereum> {
self.exchange
.exchange
.setPerpToDefaultRwaFeeSched(U256::from(self.id))
.gas(500000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
}
pub async fn order(
&self,
account_id: types::AccountId,
request: types::OrderRequest,
) -> PendingTransactionBuilder<Ethereum> {
self.exchange
.exchange
.execOrder(request.to_order_desc(
self.price_converter,
self.size_converter,
self.leverage_converter,
Some(self.exchange.collateral_converter),
))
.from(self.account_address(account_id))
.gas(5000000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
}
pub async fn order_v2(
&self,
account_id: types::AccountId,
request: types::OrderRequest,
) -> PendingTransactionBuilder<Ethereum> {
self.exchange
.exchange
.execOrderV2(
request.to_order_desc(
self.price_converter,
self.size_converter,
self.leverage_converter,
Some(self.exchange.collateral_converter),
),
request.to_order_extension().unwrap(),
)
.from(self.account_address(account_id))
.gas(5000000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
}
pub async fn orders_v2(
&self,
account_id: types::AccountId,
requests: Vec<types::OrderRequest>,
revert_on_fail: bool,
) -> PendingTransactionBuilder<Ethereum> {
self.exchange
.exchange
.execOrdersV2(
requests
.iter()
.map(|req| {
req.to_order_desc(
self.price_converter,
self.size_converter,
self.leverage_converter,
Some(self.exchange.collateral_converter),
)
})
.collect(),
revert_on_fail,
requests
.iter()
.map(|req| req.to_order_extension().unwrap())
.collect(),
)
.from(self.account_address(account_id))
.gas(150000000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
}
fn account_address(&self, account_id: types::AccountId) -> Address {
*self
.exchange
.account_address
.get(&account_id)
.unwrap()
.value()
}
pub async fn orders(
&self,
account_id: types::AccountId,
requests: Vec<types::OrderRequest>,
) -> PendingTransactionBuilder<Ethereum> {
self.exchange
.exchange
.execOrders(
requests
.iter()
.map(|req| {
req.to_order_desc(
self.price_converter,
self.size_converter,
self.leverage_converter,
Some(self.exchange.collateral_converter),
)
})
.collect(),
true,
)
.from(self.account_address(account_id))
.gas(150000000)
.send()
.await
.map_err::<DexError, _>(|err| DexError::Provider(err.into()))
.unwrap()
}
}