use std::collections::HashMap; use std::fmt::Debug; use log::{error, info}; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use serde_json::json; pub mod error; pub mod jsonrpc; use liana::{ config::Config, miniscript::bitcoin::{consensus, util::psbt::Psbt, Address, OutPoint, Txid}, }; use super::{model::*, Daemon, DaemonError}; pub trait Client { type Error: Into + Debug; fn request( &self, method: &str, params: Option, ) -> Result; } #[derive(Debug, Clone)] pub struct Lianad { config: Config, client: C, } impl Lianad { pub fn new(client: C, config: Config) -> Lianad { Lianad { client, config } } /// Generic call function for RPC calls. fn call( &self, method: &str, input: Option, ) -> Result { info!("{}", method); self.client.request(method, input).map_err(|e| { error!("method {} failed: {:?}", method, e); e.into() }) } } impl Daemon for Lianad { fn is_external(&self) -> bool { true } fn config(&self) -> &Config { &self.config } fn stop(&mut self) -> Result<(), DaemonError> { let _res: serde_json::value::Value = self.call("stop", Option::::None)?; Ok(()) } fn get_info(&self) -> Result { self.call("getinfo", Option::::None) } fn get_new_address(&self) -> Result { self.call("getnewaddress", Option::::None) } fn list_coins(&self) -> Result { self.call("listcoins", Option::::None) } fn list_spend_txs(&self) -> Result { self.call("listspend", Option::::None) } fn create_spend_tx( &self, coins_outpoints: &[OutPoint], destinations: &HashMap, feerate_vb: u64, ) -> Result { self.call( "createspend", Some(vec![ json!(coins_outpoints), json!(destinations), json!(feerate_vb), ]), ) } fn update_spend_tx(&self, psbt: &Psbt) -> Result<(), DaemonError> { let spend_tx = base64::encode(&consensus::serialize(psbt)); let _res: serde_json::value::Value = self.call("updatespend", Some(vec![spend_tx]))?; Ok(()) } fn delete_spend_tx(&self, txid: &Txid) -> Result<(), DaemonError> { let _res: serde_json::value::Value = self.call("deletespend", Some(vec![txid.to_string()]))?; Ok(()) } fn broadcast_spend_tx(&self, txid: &Txid) -> Result<(), DaemonError> { let _res: serde_json::value::Value = self.call("broadcastspend", Some(vec![txid.to_string()]))?; Ok(()) } fn start_rescan(&self, t: u32) -> Result<(), DaemonError> { let _res: serde_json::value::Value = self.call("startrescan", Some(vec![t]))?; Ok(()) } } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Request {}