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();
136 legacy
137 .setTakerFee(U256::from(self.id), fee_converter.to_unsigned(taker_fee))
138 .gas(500000)
139 .send()
140 .await
141 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
142 .unwrap()
143 .get_receipt()
144 .await
145 .unwrap();
146 legacy
147 .setMakerFee(U256::from(self.id), fee_converter.to_unsigned(maker_fee))
148 .gas(500000)
149 .send()
150 .await
151 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
152 .unwrap()
153 .get_receipt()
154 .await
155 .unwrap();
156 self
157 }
158
159 pub async fn set_fee_schedule(
167 &self,
168 taker_fees: [UD64; state::FEE_TIERS],
169 maker_fees: [UD64; state::FEE_TIERS],
170 ) -> PendingTransactionBuilder<Ethereum> {
171 self.set_own_fee_schedule_values(taker_fees, maker_fees)
172 .await;
173 self.use_own_fee_schedule().await
174 }
175
176 pub async fn set_own_fee_schedule_values(
180 &self,
181 taker_fees: [UD64; state::FEE_TIERS],
182 maker_fees: [UD64; state::FEE_TIERS],
183 ) {
184 let fee_converter = num::fee_converter();
185 self.exchange
186 .exchange
187 .setFeeSchedValues(
188 U256::from(self.id),
189 taker_fees.map(|fee| fee_converter.to_unsigned(fee)),
190 maker_fees.map(|fee| fee_converter.to_unsigned(fee)),
191 )
192 .gas(500000)
193 .send()
194 .await
195 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
196 .unwrap()
197 .get_receipt()
198 .await
199 .unwrap();
200 }
201
202 pub async fn use_own_fee_schedule(&self) -> PendingTransactionBuilder<Ethereum> {
205 self.exchange
206 .exchange
207 .setPerpToFeeSchedule(U256::from(self.id), U256::from(self.id))
208 .gas(500000)
209 .send()
210 .await
211 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
212 .unwrap()
213 }
214
215 pub async fn set_rwa_default_fee(&self) -> PendingTransactionBuilder<Ethereum> {
218 self.exchange
219 .exchange
220 .setPerpToDefaultRwaFeeSched(U256::from(self.id))
221 .gas(500000)
222 .send()
223 .await
224 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
225 .unwrap()
226 }
227
228 pub async fn order(
231 &self,
232 account_id: types::AccountId,
233 request: types::OrderRequest,
234 ) -> PendingTransactionBuilder<Ethereum> {
235 self.exchange
236 .exchange
237 .execOrder(request.to_order_desc(
238 self.price_converter,
239 self.size_converter,
240 self.leverage_converter,
241 Some(self.exchange.collateral_converter),
242 ))
243 .from(self.account_address(account_id))
244 .gas(5000000)
245 .send()
246 .await
247 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
248 .unwrap()
249 }
250
251 pub async fn order_v2(
254 &self,
255 account_id: types::AccountId,
256 request: types::OrderRequest,
257 ) -> PendingTransactionBuilder<Ethereum> {
258 self.exchange
259 .exchange
260 .execOrderV2(
261 request.to_order_desc(
262 self.price_converter,
263 self.size_converter,
264 self.leverage_converter,
265 Some(self.exchange.collateral_converter),
266 ),
267 request.to_order_extension().unwrap(),
268 )
269 .from(self.account_address(account_id))
270 .gas(5000000)
271 .send()
272 .await
273 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
274 .unwrap()
275 }
276
277 pub async fn orders_v2(
280 &self,
281 account_id: types::AccountId,
282 requests: Vec<types::OrderRequest>,
283 revert_on_fail: bool,
284 ) -> PendingTransactionBuilder<Ethereum> {
285 self.exchange
286 .exchange
287 .execOrdersV2(
288 requests
289 .iter()
290 .map(|req| {
291 req.to_order_desc(
292 self.price_converter,
293 self.size_converter,
294 self.leverage_converter,
295 Some(self.exchange.collateral_converter),
296 )
297 })
298 .collect(),
299 revert_on_fail,
300 requests
301 .iter()
302 .map(|req| req.to_order_extension().unwrap())
303 .collect(),
304 )
305 .from(self.account_address(account_id))
306 .gas(150000000)
307 .send()
308 .await
309 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
310 .unwrap()
311 }
312
313 fn account_address(&self, account_id: types::AccountId) -> Address {
314 *self
315 .exchange
316 .account_address
317 .get(&account_id)
318 .unwrap()
319 .value()
320 }
321
322 pub async fn orders(
323 &self,
324 account_id: types::AccountId,
325 requests: Vec<types::OrderRequest>,
326 ) -> PendingTransactionBuilder<Ethereum> {
327 self.exchange
328 .exchange
329 .execOrders(
330 requests
331 .iter()
332 .map(|req| {
333 req.to_order_desc(
334 self.price_converter,
335 self.size_converter,
336 self.leverage_converter,
337 Some(self.exchange.collateral_converter),
338 )
339 })
340 .collect(),
341 true,
342 )
343 .from(self.account_address(account_id))
344 .gas(150000000)
345 .send()
346 .await
347 .map_err::<DexError, _>(|err| DexError::Provider(err.into()))
348 .unwrap()
349 }
350}