Skip to main content

smplx_test/
context.rs

1use std::path::PathBuf;
2
3use electrsd::bitcoind::bitcoincore_rpc::Auth;
4
5use smplx_regtest::Regtest;
6use smplx_regtest::client::RegtestClient;
7
8use smplx_sdk::provider::{EsploraProvider, ProviderInfo, ProviderTrait, SimplexProvider, SimplicityNetwork};
9use smplx_sdk::signer::Signer;
10use smplx_sdk::utils::random_mnemonic;
11
12use crate::config::TestConfig;
13use crate::error::TestError;
14
15#[allow(dead_code)]
16pub struct TestContext {
17    _client: Option<RegtestClient>,
18    // since providers can't be cloned, we need this variable to create new signers
19    _provider_info: ProviderInfo,
20    config: TestConfig,
21    signer: Signer,
22}
23
24impl TestContext {
25    pub fn new(config_path: PathBuf) -> Result<Self, TestError> {
26        let config = TestConfig::from_file(&config_path)?;
27
28        let (signer, provider_info, client) = Self::setup(&config)?;
29
30        Ok(Self {
31            _client: client,
32            _provider_info: provider_info,
33            config,
34            signer,
35        })
36    }
37
38    pub fn create_signer(&self, mnemonic: &str) -> Signer {
39        let provider: Box<dyn ProviderTrait> = if self._provider_info.elements_url.is_some() {
40            // local regtest or external regtest
41            Box::new(SimplexProvider::new(
42                self._provider_info.esplora_url.clone(),
43                self._provider_info.elements_url.clone().unwrap(),
44                self._provider_info.auth.clone().unwrap(),
45                *self.get_network(),
46            ))
47        } else {
48            // external esplora
49            Box::new(EsploraProvider::new(
50                self._provider_info.esplora_url.clone(),
51                *self.get_network(),
52            ))
53        };
54
55        Signer::new(mnemonic, provider)
56    }
57
58    pub fn random_signer(&self) -> Signer {
59        self.create_signer(random_mnemonic().as_str())
60    }
61
62    pub fn get_default_signer(&self) -> &Signer {
63        &self.signer
64    }
65
66    pub fn get_default_provider(&self) -> &dyn ProviderTrait {
67        self.signer.get_provider()
68    }
69
70    pub fn get_config(&self) -> &TestConfig {
71        &self.config
72    }
73
74    pub fn get_network(&self) -> &SimplicityNetwork {
75        self.signer.get_provider().get_network()
76    }
77
78    fn setup(config: &TestConfig) -> Result<(Signer, ProviderInfo, Option<RegtestClient>), TestError> {
79        let client: Option<RegtestClient>;
80        let provider_info: ProviderInfo;
81        let signer: Signer;
82
83        match config.esplora.clone() {
84            Some(esplora) => match config.rpc.clone() {
85                Some(rpc) => {
86                    // custom regtest case
87                    let auth = Auth::UserPass(rpc.username, rpc.password);
88                    let provider = Box::new(SimplexProvider::new(
89                        esplora.url.clone(),
90                        rpc.url.clone(),
91                        auth.clone(),
92                        SimplicityNetwork::default_regtest(),
93                    ));
94
95                    provider_info = ProviderInfo {
96                        esplora_url: esplora.url,
97                        elements_url: Some(rpc.url),
98                        auth: Some(auth),
99                    };
100                    signer = Signer::new(config.mnemonic.as_str(), provider);
101                    client = None;
102                }
103                None => {
104                    // external esplora network
105                    let network = match esplora.network.as_str() {
106                        "Liquid" => SimplicityNetwork::Liquid,
107                        "LiquidTestnet" => SimplicityNetwork::LiquidTestnet,
108                        "ElementsRegtest" => SimplicityNetwork::default_regtest(),
109                        other => return Err(TestError::BadNetworkName(other.to_string())),
110                    };
111                    let provider = Box::new(EsploraProvider::new(esplora.url.clone(), network));
112
113                    provider_info = ProviderInfo {
114                        esplora_url: esplora.url,
115                        elements_url: None,
116                        auth: None,
117                    };
118                    signer = Signer::new(config.mnemonic.as_str(), provider);
119                    client = None;
120                }
121            },
122            None => {
123                // simplex inner network
124                let (regtest_client, regtest_signer) = Regtest::from_config(config.to_regtest_config())?;
125
126                provider_info = ProviderInfo {
127                    esplora_url: regtest_client.esplora_url(),
128                    elements_url: Some(regtest_client.rpc_url()),
129                    auth: Some(regtest_client.auth()),
130                };
131                signer = regtest_signer;
132                client = Some(regtest_client);
133            }
134        }
135
136        Ok((signer, provider_info, client))
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use std::fs;
143
144    use super::*;
145
146    #[test]
147    fn invalid_network_returns_error() {
148        let config = r#"
149            mnemonic = "exist carry drive collect lend cereal occur much tiger just involve mean"
150            bitcoins = 10000
151
152            [esplora]
153            url = "http://localhost:3000"
154            network = "InvalidNetwork"
155        "#;
156
157        let path = std::env::temp_dir().join("smplx_test_invalid_network.toml");
158        fs::write(&path, config).unwrap();
159
160        let result = TestContext::new(path);
161        let Err(e) = result else {
162            panic!("expected BadNetworkName error")
163        };
164        assert!(
165            matches!(e, TestError::BadNetworkName(ref s) if s == "InvalidNetwork"),
166            "expected BadNetworkName, got: {e}"
167        );
168    }
169}