1use std::fs;
2use std::fs::OpenOptions;
3use std::io::Read;
4use std::io::Write;
5use std::path::Path;
6
7use serde::{Deserialize, Serialize};
8
9use smplx_regtest::RegtestConfig;
10use smplx_sdk::program::TrackerLogLevel;
11
12use super::error::TestError;
13
14pub const TEST_ENV_NAME: &str = "SIMPLEX_TEST_ENV";
15pub const DEFAULT_TEST_MNEMONIC: &str = "exist carry drive collect lend cereal occur much tiger just involve mean";
16pub const DEFAULT_BITCOINS: u64 = 10_000_000;
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19#[serde(default)]
20pub struct TestConfig {
21 pub mnemonic: String,
22 pub bitcoins: u64,
23 pub esplora: Option<EsploraConfig>,
24 pub rpc: Option<RpcConfig>,
25 pub verbosity: Option<Verbosity>,
26}
27
28#[derive(Debug, Default, Clone, Serialize, Deserialize)]
29pub struct EsploraConfig {
30 pub url: String,
31 pub network: String,
32}
33
34#[derive(Debug, Default, Clone, Serialize, Deserialize)]
35pub struct RpcConfig {
36 pub url: String,
37 pub username: String,
38 pub password: String,
39}
40
41#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
42pub struct Verbosity(pub u64);
43
44impl TryInto<TrackerLogLevel> for Verbosity {
45 type Error = Self;
46
47 fn try_into(self) -> Result<TrackerLogLevel, Self::Error> {
48 match self {
49 Verbosity(1) => Ok(TrackerLogLevel::None),
50 Verbosity(2) => Ok(TrackerLogLevel::Warning),
51 Verbosity(3) => Ok(TrackerLogLevel::Debug),
52 Verbosity(4) => Ok(TrackerLogLevel::Trace),
53 _ => Err(self),
54 }
55 }
56}
57
58impl TestConfig {
59 pub fn from_file(path: impl AsRef<Path>) -> Result<Self, TestError> {
60 let mut content = String::new();
61 let mut file = OpenOptions::new().read(true).open(path)?;
62
63 file.read_to_string(&mut content)?;
64
65 Ok(toml::from_str(&content)?)
66 }
67
68 pub fn to_regtest_config(&self) -> RegtestConfig {
69 RegtestConfig {
70 mnemonic: self.mnemonic.clone(),
71 bitcoins: self.bitcoins,
72 rpc_port: None,
73 esplora_port: None,
74 rpc_user: None,
75 rpc_password: None,
76 }
77 }
78
79 pub fn to_file(&self, path: &impl AsRef<Path>) -> Result<(), TestError> {
80 if let Some(parent_dir) = path.as_ref().parent() {
81 fs::create_dir_all(parent_dir)?;
82 }
83
84 let mut file = OpenOptions::new().create(true).write(true).truncate(true).open(path)?;
85
86 file.write_all(toml::to_string_pretty(&self).unwrap().as_bytes())?;
87 file.flush()?;
88
89 Ok(())
90 }
91}
92
93impl Default for TestConfig {
94 fn default() -> Self {
95 Self {
96 mnemonic: DEFAULT_TEST_MNEMONIC.to_string(),
97 bitcoins: DEFAULT_BITCOINS,
98 esplora: None,
99 rpc: None,
100 verbosity: Some(Verbosity(3)),
101 }
102 }
103}