renegade_sdk/renegade_wallet_client/actions/
cancel_order.rs1use alloy::primitives::U256;
4use renegade_darkpool_types::intent::DarkpoolStateIntent;
5use renegade_external_api::{
6 http::order::{CANCEL_ORDER_ROUTE, CancelOrderRequest, CancelOrderResponse},
7 types::{ApiOrder, ApiPublicIntentPermit, OrderAuth, SignatureWithNonce},
8};
9use renegade_solidity_abi::v2::IDarkpoolV2::{
10 PublicIntentPermit, SignatureWithNonce as SolSignatureWithNonce,
11};
12use uuid::Uuid;
13
14use crate::{
15 RenegadeClientError,
16 actions::{NON_BLOCKING_PARAM, construct_http_path},
17 client::RenegadeClient,
18 websocket::{DEFAULT_TASK_TIMEOUT, TaskWaiter},
19};
20
21const CANCEL_DOMAIN: &[u8] = b"cancel";
23
24impl RenegadeClient {
26 pub async fn cancel_order(&self, order_id: Uuid) -> Result<(), RenegadeClientError> {
29 let request = self.build_cancel_order_request(order_id).await?;
30
31 let path = self.build_cancel_order_request_path(order_id, false)?;
32
33 self.relayer_client.post::<_, CancelOrderResponse>(&path, request).await?;
34
35 Ok(())
36 }
37
38 pub async fn enqueue_order_cancellation(
41 &self,
42 order_id: Uuid,
43 ) -> Result<TaskWaiter, RenegadeClientError> {
44 let request = self.build_cancel_order_request(order_id).await?;
45
46 let path = self.build_cancel_order_request_path(order_id, true)?;
47
48 let CancelOrderResponse { task_id, .. } = self.relayer_client.post(&path, request).await?;
49
50 let task_waiter = self.watch_task(task_id, DEFAULT_TASK_TIMEOUT).await?;
52
53 Ok(task_waiter)
54 }
55}
56
57impl RenegadeClient {
59 async fn build_cancel_order_request(
61 &self,
62 order_id: Uuid,
63 ) -> Result<CancelOrderRequest, RenegadeClientError> {
64 let (order, auth) = self.get_order_with_auth(order_id).await?;
65
66 let cancel_signature = if let OrderAuth::PublicOrder { permit, intent_signature } = auth {
67 self.build_ring0_cancel_signature(permit, intent_signature)?
68 } else {
69 self.build_private_cancel_signature(order)?
70 };
71
72 Ok(CancelOrderRequest { cancel_signature })
73 }
74
75 fn build_cancel_order_request_path(
77 &self,
78 order_id: Uuid,
79 non_blocking: bool,
80 ) -> Result<String, RenegadeClientError> {
81 let path = construct_http_path!(CANCEL_ORDER_ROUTE, "account_id" => self.get_account_id(), "order_id" => order_id);
82 let query_string =
83 serde_urlencoded::to_string(&[(NON_BLOCKING_PARAM, non_blocking.to_string())])
84 .map_err(RenegadeClientError::serde)?;
85
86 Ok(format!("{path}?{query_string}"))
87 }
88
89 fn build_ring0_cancel_signature(
97 &self,
98 permit: ApiPublicIntentPermit,
99 intent_signature: SignatureWithNonce,
100 ) -> Result<SignatureWithNonce, RenegadeClientError> {
101 let chain_id = self.get_chain_id();
102 let signer = self.get_account_signer();
103
104 let permit: PublicIntentPermit = permit.into();
106 let sol_intent_sig: SolSignatureWithNonce = intent_signature.into();
107
108 let intent_nullifier = permit.compute_nullifier(sol_intent_sig.nonce);
110
111 let nullifier_bytes = intent_nullifier.to_be_bytes::<{ U256::BYTES }>();
113 let cancel_payload = [CANCEL_DOMAIN, nullifier_bytes.as_slice()].concat();
114
115 let sol_sig = SolSignatureWithNonce::sign(&cancel_payload, chain_id, signer)
117 .map_err(RenegadeClientError::signing)?;
118
119 Ok(sol_sig.into())
120 }
121
122 fn build_private_cancel_signature(
127 &self,
128 order: ApiOrder,
129 ) -> Result<SignatureWithNonce, RenegadeClientError> {
130 let chain_id = self.get_chain_id();
131 let signer = self.get_account_signer();
132
133 let intent: DarkpoolStateIntent = order.into();
134 let nullifier = intent.compute_nullifier();
135 let nullifier_bytes = nullifier.to_bytes_be();
136
137 let sol_sig = SolSignatureWithNonce::sign(&nullifier_bytes, chain_id, signer)
138 .map_err(RenegadeClientError::signing)?;
139
140 Ok(sol_sig.into())
141 }
142}