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