1use alloy::{
2 network::Ethereum,
3 primitives::{Address, I256, U256},
4 providers::PendingTransactionBuilder,
5};
6use fastnum::UD64;
7
8use super::TestExchange;
9use crate::{abi::dex_legacy::LegacyExchange, error::DexError, num, state, types};
10
11#[derive(Debug)]
12pub struct TestPerp<'e> {
13 pub id: types::PerpetualId,
14 pub name: String,
15 pub price_converter: num::Converter,
16 pub size_converter: num::Converter,
17 pub leverage_converter: num::Converter,
18 pub exchange: &'e TestExchange,
19}
20
21impl<'e> TestPerp<'e> {
22 pub async fn with_mark_price(self, price: UD64) -> Self {
23 self.exchange
24 .exchange
25 .updateMarkPricePNS(U256::from(self.id), self.price_converter.to_unsigned(price).to())
26 .from(self.exchange.price_admin)
27 .gas(500000)
28 .send()
29 .await
30 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
31 .unwrap()
32 .get_receipt()
33 .await
34 .unwrap();
35 self
36 }
37
38 pub async fn with_min_post(self, min: U256) -> Self {
39 self.exchange
40 .exchange
41 .setMinPost(min)
42 .send()
43 .await
44 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
45 .unwrap()
46 .get_receipt()
47 .await
48 .unwrap();
49 self
50 }
51
52 pub async fn with_min_settle(self, min: U256) -> Self {
53 self.exchange
54 .exchange
55 .setMinSettle(min)
56 .send()
57 .await
58 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
59 .unwrap()
60 .get_receipt()
61 .await
62 .unwrap();
63 self
64 }
65
66 pub async fn unpause(self) -> Self {
67 self.exchange
68 .exchange
69 .setContractPaused(U256::from(self.id), false)
70 .gas(500000)
71 .send()
72 .await
73 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
74 .unwrap()
75 .get_receipt()
76 .await
77 .unwrap();
78 self
79 }
80
81 pub async fn set_maintenance_margin(
82 &self,
83 maintenance_margin: UD64,
84 ) -> PendingTransactionBuilder<Ethereum> {
85 self.exchange
86 .exchange
87 .setMaintenanceMarginFraction(
88 U256::from(self.id),
89 self.leverage_converter.to_unsigned(maintenance_margin),
90 )
91 .gas(500000)
92 .send()
93 .await
94 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
95 .unwrap()
96 }
97
98 pub async fn set_mark_price(&self, price: UD64) -> PendingTransactionBuilder<Ethereum> {
99 self.exchange
100 .exchange
101 .updateMarkPricePNS(U256::from(self.id), self.price_converter.to_unsigned(price).to())
102 .from(self.exchange.price_admin)
103 .gas(500000)
104 .send()
105 .await
106 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
107 .unwrap()
108 }
109
110 pub async fn set_funding_rate(
111 &self,
112 price: u32,
113 rate: i32,
114 ) -> PendingTransactionBuilder<Ethereum> {
115 self.exchange
116 .exchange
117 .setFundingSum(U256::from(self.id), I256::try_from(rate).unwrap(), price, true, true)
118 .from(self.exchange.anvil.addresses()[2]) .gas(500000)
120 .send()
121 .await
122 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
123 .unwrap()
124 }
125
126 pub async fn with_legacy_fees(self, taker_fee: UD64, maker_fee: UD64) -> Self {
133 let legacy =
134 LegacyExchange::new(*self.exchange.exchange.address(), self.exchange.provider.clone());
135 let fee_converter = num::fee_converter();
138 legacy
139 .setTakerFee(U256::from(self.id), fee_converter.to_unsigned(taker_fee))
140 .gas(500000)
141 .send()
142 .await
143 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
144 .unwrap()
145 .get_receipt()
146 .await
147 .unwrap();
148 legacy
149 .setMakerFee(U256::from(self.id), fee_converter.to_unsigned(maker_fee))
150 .gas(500000)
151 .send()
152 .await
153 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
154 .unwrap()
155 .get_receipt()
156 .await
157 .unwrap();
158 self
159 }
160
161 pub async fn set_fee_schedule(
169 &self,
170 taker_fees: [UD64; state::FEE_TIERS],
171 maker_fees: [UD64; state::FEE_TIERS],
172 ) -> PendingTransactionBuilder<Ethereum> {
173 self.set_own_fee_schedule_values(taker_fees, maker_fees)
174 .await;
175 self.use_own_fee_schedule().await
176 }
177
178 pub async fn set_own_fee_schedule_values(
182 &self,
183 taker_fees: [UD64; state::FEE_TIERS],
184 maker_fees: [UD64; state::FEE_TIERS],
185 ) {
186 let fee_converter = num::ppm_fee_converter();
189 self.exchange
190 .exchange
191 .setFeeSchedValues(
192 U256::from(self.id),
193 taker_fees.map(|fee| fee_converter.to_unsigned(fee)),
194 maker_fees.map(|fee| fee_converter.to_unsigned(fee)),
195 )
196 .gas(500000)
197 .send()
198 .await
199 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
200 .unwrap()
201 .get_receipt()
202 .await
203 .unwrap();
204 }
205
206 pub async fn use_own_fee_schedule(&self) -> PendingTransactionBuilder<Ethereum> {
209 self.exchange
210 .exchange
211 .setPerpToFeeSchedule(U256::from(self.id), U256::from(self.id))
212 .gas(500000)
213 .send()
214 .await
215 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
216 .unwrap()
217 }
218
219 pub async fn set_rwa_default_fee(&self) -> PendingTransactionBuilder<Ethereum> {
222 self.exchange
223 .exchange
224 .setPerpToDefaultRwaFeeSched(U256::from(self.id))
225 .gas(500000)
226 .send()
227 .await
228 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
229 .unwrap()
230 }
231
232 pub async fn order(
235 &self,
236 account_id: types::AccountId,
237 request: types::OrderRequest,
238 ) -> PendingTransactionBuilder<Ethereum> {
239 self.exchange
240 .exchange
241 .execOrder(request.to_order_desc(
242 self.price_converter,
243 self.size_converter,
244 self.leverage_converter,
245 Some(self.exchange.collateral_converter),
246 ))
247 .from(self.account_address(account_id))
248 .gas(5000000)
249 .send()
250 .await
251 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
252 .unwrap()
253 }
254
255 pub async fn order_v2(
258 &self,
259 account_id: types::AccountId,
260 request: types::OrderRequest,
261 ) -> PendingTransactionBuilder<Ethereum> {
262 self.exchange
263 .exchange
264 .execOrderV2(
265 request.to_order_desc(
266 self.price_converter,
267 self.size_converter,
268 self.leverage_converter,
269 Some(self.exchange.collateral_converter),
270 ),
271 request.to_order_extension().unwrap(),
272 )
273 .from(self.account_address(account_id))
274 .gas(5000000)
275 .send()
276 .await
277 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
278 .unwrap()
279 }
280
281 pub async fn orders_v2(
284 &self,
285 account_id: types::AccountId,
286 requests: Vec<types::OrderRequest>,
287 revert_on_fail: bool,
288 ) -> PendingTransactionBuilder<Ethereum> {
289 self.exchange
290 .exchange
291 .execOrdersV2(
292 requests
293 .iter()
294 .map(|req| {
295 req.to_order_desc(
296 self.price_converter,
297 self.size_converter,
298 self.leverage_converter,
299 Some(self.exchange.collateral_converter),
300 )
301 })
302 .collect(),
303 revert_on_fail,
304 requests
305 .iter()
306 .map(|req| req.to_order_extension().unwrap())
307 .collect(),
308 )
309 .from(self.account_address(account_id))
310 .gas(150000000)
311 .send()
312 .await
313 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
314 .unwrap()
315 }
316
317 fn account_address(&self, account_id: types::AccountId) -> Address {
318 *self
319 .exchange
320 .account_address
321 .get(&account_id)
322 .unwrap()
323 .value()
324 }
325
326 pub async fn orders(
327 &self,
328 account_id: types::AccountId,
329 requests: Vec<types::OrderRequest>,
330 ) -> PendingTransactionBuilder<Ethereum> {
331 self.exchange
332 .exchange
333 .execOrders(
334 requests
335 .iter()
336 .map(|req| {
337 req.to_order_desc(
338 self.price_converter,
339 self.size_converter,
340 self.leverage_converter,
341 Some(self.exchange.collateral_converter),
342 )
343 })
344 .collect(),
345 true,
346 )
347 .from(self.account_address(account_id))
348 .gas(150000000)
349 .send()
350 .await
351 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
352 .unwrap()
353 }
354}