csv_adapter_sui/
config.rs1use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
10pub enum SuiNetwork {
11 Mainnet,
13 Testnet,
15 Devnet,
17 Local,
19 Custom { chain_id: String },
21}
22
23impl SuiNetwork {
24 pub fn default_rpc_url(&self) -> &str {
26 match self {
27 SuiNetwork::Mainnet => "https://fullnode.mainnet.sui.io:443",
28 SuiNetwork::Testnet => "https://fullnode.testnet.sui.io:443",
29 SuiNetwork::Devnet => "https://fullnode.devnet.sui.io:443",
30 SuiNetwork::Local => "http://127.0.0.1:9000",
31 SuiNetwork::Custom { .. } => "",
32 }
33 }
34
35 pub fn chain_id(&self) -> &str {
37 match self {
38 SuiNetwork::Mainnet => "mainnet",
39 SuiNetwork::Testnet => "testnet",
40 SuiNetwork::Devnet => "devnet",
41 SuiNetwork::Local => "local",
42 SuiNetwork::Custom { chain_id } => chain_id.as_str(),
43 }
44 }
45}
46
47#[derive(Clone, Debug, Serialize, Deserialize)]
49pub struct CheckpointConfig {
50 pub require_certified: bool,
52 pub max_epoch_lookback: u64,
54 pub timeout_ms: u64,
56}
57
58impl Default for CheckpointConfig {
59 fn default() -> Self {
60 Self {
61 require_certified: true,
62 max_epoch_lookback: 5,
63 timeout_ms: 30_000,
64 }
65 }
66}
67
68#[derive(Clone, Debug, Serialize, Deserialize)]
70pub struct TransactionConfig {
71 pub max_gas_budget: u64,
73 pub max_gas_price: u64,
75 pub confirmation_timeout_ms: u64,
77 pub max_retries: u32,
79}
80
81impl Default for TransactionConfig {
82 fn default() -> Self {
83 Self {
84 max_gas_budget: 1_000_000_000, max_gas_price: 1_000,
86 confirmation_timeout_ms: 60_000,
87 max_retries: 3,
88 }
89 }
90}
91
92#[derive(Clone, Debug, Serialize, Deserialize)]
94pub struct SealContractConfig {
95 pub package_id: Option<String>,
98 pub module_name: String,
100 pub seal_type: String,
102}
103
104impl Default for SealContractConfig {
105 fn default() -> Self {
106 Self {
107 package_id: None, module_name: "csv_seal".to_string(),
109 seal_type: "Seal".to_string(),
110 }
111 }
112}
113
114#[derive(Clone, Debug, Serialize, Deserialize)]
116pub struct SuiConfig {
117 pub network: SuiNetwork,
119 pub rpc_url: String,
121 pub checkpoint: CheckpointConfig,
123 pub transaction: TransactionConfig,
125 pub seal_contract: SealContractConfig,
127}
128
129impl SuiConfig {
130 pub fn new(network: SuiNetwork) -> Self {
132 let rpc_url = network.default_rpc_url().to_string();
133 Self {
134 network,
135 rpc_url,
136 checkpoint: CheckpointConfig::default(),
137 transaction: TransactionConfig::default(),
138 seal_contract: SealContractConfig::default(),
139 }
140 }
141
142 pub fn chain_id(&self) -> &str {
144 self.network.chain_id()
145 }
146
147 pub fn validate(&self) -> Result<(), String> {
149 if self.rpc_url.is_empty() {
150 return Err("RPC URL cannot be empty".to_string());
151 }
152 match &self.seal_contract.package_id {
153 Some(id) if id.is_empty() => {
154 return Err("Seal contract package ID cannot be empty".to_string())
155 }
156 None => {
157 return Err(
158 "Seal contract package ID must be set — deploy the contract first".to_string(),
159 )
160 }
161 _ => {}
162 }
163 if self.transaction.max_gas_budget == 0 {
164 return Err("Max gas budget must be greater than 0".to_string());
165 }
166 if self.checkpoint.timeout_ms == 0 {
167 return Err("Checkpoint timeout must be greater than 0".to_string());
168 }
169 Ok(())
170 }
171}
172
173impl Default for SuiConfig {
174 fn default() -> Self {
175 Self::new(SuiNetwork::Testnet)
176 }
177}
178
179#[cfg(test)]
180mod tests {
181 use super::*;
182
183 #[test]
184 fn test_default_config() {
185 let config = SuiConfig::default();
186 assert_eq!(config.network, SuiNetwork::Testnet);
187 assert_eq!(config.rpc_url, "https://fullnode.testnet.sui.io:443");
188 }
189
190 #[test]
191 fn test_config_custom_rpc() {
192 let config = SuiConfig::new(SuiNetwork::Mainnet);
193 assert_eq!(config.network, SuiNetwork::Mainnet);
194 assert_eq!(config.rpc_url, "https://fullnode.mainnet.sui.io:443");
195 }
196
197 #[test]
198 fn test_config_validation() {
199 let mut config = SuiConfig::default();
200 config.seal_contract.package_id = Some("0x1234".to_string());
201 assert!(config.validate().is_ok());
202
203 config.rpc_url = "".to_string();
204 assert!(config.validate().is_err());
205 }
206
207 #[test]
208 fn test_network_chain_ids() {
209 assert_eq!(SuiNetwork::Mainnet.chain_id(), "mainnet");
210 assert_eq!(SuiNetwork::Testnet.chain_id(), "testnet");
211 assert_eq!(SuiNetwork::Devnet.chain_id(), "devnet");
212 }
213
214 #[test]
215 fn test_invalid_config() {
216 let mut config = SuiConfig::default();
217 config.seal_contract.package_id = Some("".to_string());
218 assert!(config.validate().is_err());
219 }
220}