hypercall/client/wallet_client/
mod.rs1mod directives;
2mod margin;
3mod onchain;
4mod orders;
5mod queries;
6mod signing;
7mod websocket;
8mod withdrawals;
9
10use hypercall_auth::SignatureRecovery;
11use hypercall_types::ws_protocol::WsMessage;
12use hypercall_types::WalletAddress;
13use std::sync::{
14 atomic::{AtomicU64, Ordering},
15 Arc,
16};
17use tokio::sync::{mpsc, Mutex};
18use tokio::time::Duration;
19use tokio_tungstenite::tungstenite;
20
21use alloy::sol_types::Eip712Domain;
22
23const DEFAULT_HTTP_TIMEOUT: Duration = Duration::from_secs(30);
25
26#[derive(Debug, Clone)]
27pub struct WalletClient {
28 pub wallet_address: WalletAddress,
29 pub private_key: String, pub signing_chain_id: u64,
31 ws_messages: Arc<Mutex<Vec<WsMessage>>>,
32 ws_tx: Arc<Mutex<Option<mpsc::UnboundedSender<tungstenite::Message>>>>,
33 nonce_counter: Arc<AtomicU64>,
34 http_client: reqwest::Client,
35}
36
37impl WalletClient {
38 pub async fn new(wallet_address: WalletAddress, private_key: String) -> Self {
39 let http_client = reqwest::Client::builder()
40 .timeout(DEFAULT_HTTP_TIMEOUT)
41 .connect_timeout(Duration::from_secs(10))
42 .build()
43 .expect("Failed to build HTTP client");
44
45 Self {
46 wallet_address,
47 private_key,
48 signing_chain_id: 998,
49 ws_messages: Arc::new(Mutex::new(Vec::new())),
50 ws_tx: Arc::new(Mutex::new(None)),
51 nonce_counter: Arc::new(AtomicU64::new(
52 std::time::SystemTime::now()
53 .duration_since(std::time::UNIX_EPOCH)
54 .unwrap()
55 .as_millis() as u64,
56 )),
57 http_client,
58 }
59 }
60
61 pub(super) fn next_nonce(&self) -> u64 {
63 self.nonce_counter.fetch_add(1, Ordering::SeqCst)
64 }
65
66 pub(super) fn hypercall_domain(&self) -> Eip712Domain {
68 SignatureRecovery::hypercall_domain(self.signing_chain_id)
69 }
70
71 pub(super) fn input_error(
72 message: impl Into<String>,
73 ) -> Box<dyn std::error::Error + Send + Sync> {
74 Box::new(std::io::Error::new(
75 std::io::ErrorKind::InvalidInput,
76 message.into(),
77 ))
78 }
79}