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