Skip to main content

smplx_sdk/provider/rpc/
elements.rs

1use std::str::FromStr;
2
3use electrsd::bitcoind::bitcoincore_rpc::{Auth, Client, RpcApi};
4
5use serde_json::Value;
6
7use simplicityhl::elements::{Address, AssetId, Txid};
8use simplicityhl::simplicity::bitcoin;
9
10use super::error::RpcError;
11
12use crate::utils::sat2btc;
13
14pub struct ElementsRpc {
15    pub inner: Client,
16    pub auth: Auth,
17    pub url: String,
18}
19
20impl ElementsRpc {
21    pub fn new(url: String, auth: Auth) -> Result<Self, RpcError> {
22        let inner = Client::new(url.as_str(), auth.clone())?;
23        inner.ping()?;
24
25        Ok(Self { inner, auth, url })
26    }
27
28    pub fn get_new_address(&self, label: &str) -> Result<Address, RpcError> {
29        const METHOD: &str = "getnewaddress";
30
31        let addr: Value = self.inner.call(METHOD, &[label.into(), "bech32".to_string().into()])?;
32
33        Ok(Address::from_str(addr.as_str().unwrap()).unwrap())
34    }
35
36    pub fn send_to_address(&self, address: &Address, satoshi: u64, asset: Option<AssetId>) -> Result<Txid, RpcError> {
37        const METHOD: &str = "sendtoaddress";
38
39        let btc = sat2btc(satoshi);
40        let btc = bitcoin::amount::Amount::from_btc(btc)
41            .unwrap()
42            .to_string_in(bitcoin::amount::Denomination::Bitcoin);
43
44        let r = match asset {
45            Some(asset) => self.inner.call::<Value>(
46                METHOD,
47                &[
48                    address.to_string().into(),
49                    btc.into(),
50                    "".into(),
51                    "".into(),
52                    false.into(),
53                    false.into(),
54                    1.into(),
55                    "UNSET".into(),
56                    false.into(),
57                    asset.to_string().into(),
58                ],
59            )?,
60            None => self
61                .inner
62                .call::<Value>(METHOD, &[address.to_string().into(), btc.into()])?,
63        };
64
65        Ok(Txid::from_str(r.as_str().unwrap()).unwrap())
66    }
67
68    pub fn rescan_blockchain(&self, start: Option<u64>, stop: Option<u64>) -> Result<(), RpcError> {
69        const METHOD: &str = "rescanblockchain";
70
71        let mut args = Vec::with_capacity(2);
72
73        if start.is_some() {
74            args.push(start.into());
75        }
76
77        if stop.is_some() {
78            args.push(stop.into());
79        }
80
81        self.inner.call::<Value>(METHOD, &args)?;
82
83        Ok(())
84    }
85
86    pub fn generate_blocks(&self, block_num: u32) -> Result<(), RpcError> {
87        const METHOD: &str = "generatetoaddress";
88
89        let address = self.get_new_address("")?.to_string();
90        self.inner.call::<Value>(METHOD, &[block_num.into(), address.into()])?;
91
92        Ok(())
93    }
94
95    pub fn sweep_initialfreecoins(&self) -> Result<(), RpcError> {
96        const METHOD: &str = "sendtoaddress";
97
98        let address = self.get_new_address("")?;
99        self.inner.call::<Value>(
100            METHOD,
101            &[
102                address.to_string().into(),
103                "21".into(),
104                "".into(),
105                "".into(),
106                true.into(),
107            ],
108        )?;
109
110        Ok(())
111    }
112}