renegade_sdk/renegade_wallet_client/
client.rs1use std::sync::Arc;
4use std::time::Duration;
5
6use crate::auth::HmacKey;
7use alloy::primitives::Address;
8use alloy::signers::local::PrivateKeySigner;
9use futures_util::Stream;
10use renegade_circuit_types::schnorr::{SchnorrPrivateKey, SchnorrPublicKey, SchnorrSignature};
11use renegade_circuit_types::traits::BaseType;
12use renegade_constants::Scalar;
13use uuid::Uuid;
14
15use renegade_external_api::types::websocket::{
16 AdminBalanceUpdateMessage, AdminOrderUpdateMessage, BalanceUpdateMessage, FillMessage,
17 OrderUpdateMessage, TaskUpdateMessage,
18};
19
20use crate::util::get_env_agnostic_chain;
21use crate::websocket::TaskWaiter;
22use crate::{
23 BASE_MAINNET_CHAIN_ID, BASE_SEPOLIA_CHAIN_ID, RenegadeClientError,
24 http::RelayerHttpClient,
25 renegade_wallet_client::{
26 config::RenegadeClientConfig,
27 utils::{
28 derive_account_id, derive_auth_hmac_key, derive_master_view_seed, derive_schnorr_key,
29 },
30 },
31 websocket::RenegadeWebsocketClient,
32};
33
34#[derive(Copy, Clone)]
40pub struct AccountSecrets {
41 pub account_id: Uuid,
43 pub master_view_seed: Scalar,
46 pub schnorr_key: SchnorrPrivateKey,
48 pub auth_hmac_key: HmacKey,
50}
51
52impl AccountSecrets {
53 pub fn new(key: &PrivateKeySigner, chain_id: u64) -> Result<Self, RenegadeClientError> {
55 let account_id = derive_account_id(key, chain_id).map_err(RenegadeClientError::setup)?;
56
57 let master_view_seed =
58 derive_master_view_seed(key, chain_id).map_err(RenegadeClientError::setup)?;
59
60 let schnorr_key = derive_schnorr_key(key, chain_id).map_err(RenegadeClientError::setup)?;
61
62 let auth_hmac_key =
63 derive_auth_hmac_key(key, chain_id).map_err(RenegadeClientError::setup)?;
64
65 Ok(Self { account_id, master_view_seed, schnorr_key, auth_hmac_key })
66 }
67}
68
69#[derive(Clone)]
75pub struct RenegadeClient {
76 pub config: RenegadeClientConfig,
78 pub secrets: AccountSecrets,
80 pub relayer_client: RelayerHttpClient,
82 pub admin_relayer_client: Option<RelayerHttpClient>,
84 pub historical_state_client: Arc<RelayerHttpClient>,
89 pub websocket_client: RenegadeWebsocketClient,
91}
92
93impl RenegadeClient {
94 pub fn new(config: RenegadeClientConfig) -> Result<Self, RenegadeClientError> {
96 let secrets = AccountSecrets::new(&config.key, config.chain_id)?;
97
98 let relayer_client =
99 RelayerHttpClient::new(config.relayer_base_url.clone(), secrets.auth_hmac_key);
100
101 let admin_relayer_client = config
102 .admin_hmac_key
103 .map(|key| RelayerHttpClient::new(config.relayer_base_url.clone(), key));
104
105 let chain = get_env_agnostic_chain(config.chain_id);
106 let historical_state_client = Arc::new(RelayerHttpClient::new(
107 format!("{}/{chain}", config.historical_state_base_url),
108 secrets.auth_hmac_key,
109 ));
110
111 let websocket_client = RenegadeWebsocketClient::new(
112 &config,
113 secrets.account_id,
114 secrets.auth_hmac_key,
115 config.admin_hmac_key,
116 );
117
118 Ok(Self {
119 config,
120 secrets,
121 relayer_client,
122 admin_relayer_client,
123 historical_state_client,
124 websocket_client,
125 })
126 }
127
128 pub fn new_arbitrum_sepolia(key: &PrivateKeySigner) -> Result<Self, RenegadeClientError> {
130 Self::new(RenegadeClientConfig::new_arbitrum_sepolia(key))
131 }
132
133 pub fn new_arbitrum_sepolia_admin(
135 key: &PrivateKeySigner,
136 admin_hmac_key: HmacKey,
137 ) -> Result<Self, RenegadeClientError> {
138 Self::new(RenegadeClientConfig::new_arbitrum_sepolia_admin(key, admin_hmac_key))
139 }
140
141 pub fn new_arbitrum_one(key: &PrivateKeySigner) -> Result<Self, RenegadeClientError> {
143 Self::new(RenegadeClientConfig::new_arbitrum_one(key))
144 }
145
146 pub fn new_arbitrum_one_admin(
148 key: &PrivateKeySigner,
149 admin_hmac_key: HmacKey,
150 ) -> Result<Self, RenegadeClientError> {
151 Self::new(RenegadeClientConfig::new_arbitrum_one_admin(key, admin_hmac_key))
152 }
153
154 pub fn new_base_sepolia(key: &PrivateKeySigner) -> Result<Self, RenegadeClientError> {
156 Self::new(RenegadeClientConfig::new_base_sepolia(key))
157 }
158
159 pub fn new_base_sepolia_admin(
161 key: &PrivateKeySigner,
162 admin_hmac_key: HmacKey,
163 ) -> Result<Self, RenegadeClientError> {
164 Self::new(RenegadeClientConfig::new_base_sepolia_admin(key, admin_hmac_key))
165 }
166
167 pub fn new_base_mainnet(key: &PrivateKeySigner) -> Result<Self, RenegadeClientError> {
169 Self::new(RenegadeClientConfig::new_base_mainnet(key))
170 }
171
172 pub fn new_ethereum_sepolia_admin(
174 key: &PrivateKeySigner,
175 admin_hmac_key: HmacKey,
176 ) -> Result<Self, RenegadeClientError> {
177 Self::new(RenegadeClientConfig::new_ethereum_sepolia_admin(key, admin_hmac_key))
178 }
179
180 pub fn new_ethereum_sepolia(key: &PrivateKeySigner) -> Result<Self, RenegadeClientError> {
182 Self::new(RenegadeClientConfig::new_ethereum_sepolia(key))
183 }
184
185 pub fn new_base_mainnet_admin(
187 key: &PrivateKeySigner,
188 admin_hmac_key: HmacKey,
189 ) -> Result<Self, RenegadeClientError> {
190 Self::new(RenegadeClientConfig::new_base_mainnet_admin(key, admin_hmac_key))
191 }
192
193 pub fn is_solidity_chain(&self) -> bool {
196 self.config.chain_id == BASE_MAINNET_CHAIN_ID
197 || self.config.chain_id == BASE_SEPOLIA_CHAIN_ID
198 }
199
200 pub async fn watch_task(
207 &self,
208 task_id: Uuid,
209 timeout: Duration,
210 ) -> Result<TaskWaiter, RenegadeClientError> {
211 self.websocket_client.watch_task(task_id, timeout).await
212 }
213
214 pub async fn subscribe_task_updates(
216 &self,
217 ) -> Result<impl Stream<Item = TaskUpdateMessage>, RenegadeClientError> {
218 self.websocket_client.subscribe_task_updates().await
219 }
220
221 pub async fn subscribe_balance_updates(
223 &self,
224 ) -> Result<impl Stream<Item = BalanceUpdateMessage>, RenegadeClientError> {
225 self.websocket_client.subscribe_balance_updates().await
226 }
227
228 pub async fn subscribe_order_updates(
230 &self,
231 ) -> Result<impl Stream<Item = OrderUpdateMessage>, RenegadeClientError> {
232 self.websocket_client.subscribe_order_updates().await
233 }
234
235 pub async fn subscribe_fills(
237 &self,
238 ) -> Result<impl Stream<Item = FillMessage>, RenegadeClientError> {
239 self.websocket_client.subscribe_fills().await
240 }
241
242 pub async fn subscribe_admin_balance_updates(
244 &self,
245 ) -> Result<impl Stream<Item = AdminBalanceUpdateMessage>, RenegadeClientError> {
246 self.websocket_client.subscribe_admin_balance_updates().await
247 }
248
249 pub async fn subscribe_admin_order_updates(
251 &self,
252 ) -> Result<impl Stream<Item = AdminOrderUpdateMessage>, RenegadeClientError> {
253 self.websocket_client.subscribe_admin_order_updates().await
254 }
255
256 pub fn get_admin_client(&self) -> Result<&RelayerHttpClient, RenegadeClientError> {
263 match self.admin_relayer_client.as_ref() {
264 Some(admin_client) => Ok(admin_client),
265 None => Err(RenegadeClientError::NotAdmin),
266 }
267 }
268
269 pub fn get_account_id(&self) -> Uuid {
271 self.secrets.account_id
272 }
273
274 pub fn get_master_view_seed(&self) -> Scalar {
276 self.secrets.master_view_seed
277 }
278
279 pub fn get_auth_hmac_key(&self) -> HmacKey {
281 self.secrets.auth_hmac_key
282 }
283
284 pub fn get_account_signer(&self) -> &PrivateKeySigner {
286 &self.config.key
287 }
288
289 pub fn get_account_address(&self) -> Address {
292 self.config.key.address()
293 }
294
295 pub fn schnorr_sign<T: BaseType>(
297 &self,
298 message: &T,
299 ) -> Result<SchnorrSignature, RenegadeClientError> {
300 self.secrets.schnorr_key.sign(message).map_err(RenegadeClientError::signing)
301 }
302
303 pub fn get_schnorr_public_key(&self) -> SchnorrPublicKey {
306 self.secrets.schnorr_key.public_key()
307 }
308
309 pub fn get_executor_address(&self) -> Address {
312 self.config.executor_address
313 }
314
315 pub fn get_relayer_fee_recipient(&self) -> Address {
317 self.config.relayer_fee_recipient
318 }
319
320 pub fn get_chain_id(&self) -> u64 {
322 self.config.chain_id
323 }
324
325 pub fn get_permit2_address(&self) -> Address {
327 self.config.permit2_address
328 }
329
330 pub fn get_darkpool_address(&self) -> Address {
332 self.config.darkpool_address
333 }
334}