rustrade_execution/client/hyperliquid/
config.rs1use ethers::signers::{LocalWallet, Signer};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone)]
17pub struct HyperliquidConfig {
18 pub wallet: LocalWallet,
20 pub testnet: bool,
22}
23
24impl HyperliquidConfig {
25 pub fn new(wallet: LocalWallet, testnet: bool) -> Self {
27 Self { wallet, testnet }
28 }
29
30 pub fn from_env() -> Result<Self, ConfigError> {
40 let private_key =
41 std::env::var("HYPERLIQUID_PRIVATE_KEY").map_err(|_| ConfigError::MissingPrivateKey)?;
42
43 let testnet = std::env::var("HYPERLIQUID_TESTNET")
44 .map(|v| v.eq_ignore_ascii_case("true") || v == "1")
45 .unwrap_or(false);
46
47 Self::from_private_key(&private_key, testnet)
48 }
49
50 pub fn from_private_key(private_key: &str, testnet: bool) -> Result<Self, ConfigError> {
54 let key = private_key.strip_prefix("0x").unwrap_or(private_key);
55
56 let wallet: LocalWallet = key
57 .parse()
58 .map_err(|e| ConfigError::InvalidPrivateKey(format!("{e}")))?;
59
60 Ok(Self { wallet, testnet })
61 }
62
63 pub fn wallet_address_hex(&self) -> String {
65 format!("{:#x}", self.wallet.address())
66 }
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct HyperliquidConfigFile {
75 #[serde(default)]
77 pub testnet: bool,
78}
79
80#[derive(Debug, thiserror::Error)]
82pub enum ConfigError {
83 #[error("HYPERLIQUID_PRIVATE_KEY environment variable not set")]
84 MissingPrivateKey,
85
86 #[error("Invalid private key: {0}")]
87 InvalidPrivateKey(String),
88}
89
90#[cfg(test)]
91#[allow(clippy::unwrap_used)] mod tests {
93 use super::*;
94
95 #[test]
96 fn test_from_private_key_with_prefix() {
97 let key = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
98 let config = HyperliquidConfig::from_private_key(key, false).unwrap();
99 assert!(!config.testnet);
100 assert!(config.wallet_address_hex().starts_with("0x"));
101 }
102
103 #[test]
104 fn test_from_private_key_without_prefix() {
105 let key = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
106 let config = HyperliquidConfig::from_private_key(key, true).unwrap();
107 assert!(config.testnet);
108 }
109
110 #[test]
111 fn test_invalid_private_key() {
112 let result = HyperliquidConfig::from_private_key("invalid", false);
113 assert!(result.is_err());
114 }
115}