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 _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 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 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 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 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 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}