bitcoincore_rpc/
client.rs

1// To the extent possible under law, the author(s) have dedicated all
2// copyright and related and neighboring rights to this software to
3// the public domain worldwide. This software is distributed without
4// any warranty.
5//
6// You should have received a copy of the CC0 Public Domain Dedication
7// along with this software.
8// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
9//
10
11use std::collections::HashMap;
12use std::fs::File;
13use std::io::{BufRead, BufReader};
14use std::iter::FromIterator;
15use std::path::PathBuf;
16use std::{fmt, result};
17
18use crate::bitcoin;
19use crate::bitcoin::consensus::encode;
20use bitcoin::hex::DisplayHex;
21use jsonrpc;
22use serde;
23use serde_json;
24
25use crate::bitcoin::address::{NetworkUnchecked, NetworkChecked};
26use crate::bitcoin::hashes::hex::FromHex;
27use crate::bitcoin::secp256k1::ecdsa::Signature;
28use crate::bitcoin::{
29    Address, Amount, Block, OutPoint, PrivateKey, PublicKey, Script, Transaction,
30};
31use log::Level::{Debug, Trace, Warn};
32
33use crate::error::*;
34use crate::json;
35use crate::queryable;
36
37/// Crate-specific Result type, shorthand for `std::result::Result` with our
38/// crate-specific Error type;
39pub type Result<T> = result::Result<T, Error>;
40
41/// Outpoint that serializes and deserializes as a map, instead of a string,
42/// for use as RPC arguments
43#[derive(Clone, Debug, Serialize, Deserialize)]
44pub struct JsonOutPoint {
45    pub txid: bitcoin::Txid,
46    pub vout: u32,
47}
48
49impl From<OutPoint> for JsonOutPoint {
50    fn from(o: OutPoint) -> JsonOutPoint {
51        JsonOutPoint {
52            txid: o.txid,
53            vout: o.vout,
54        }
55    }
56}
57
58impl Into<OutPoint> for JsonOutPoint {
59    fn into(self) -> OutPoint {
60        OutPoint {
61            txid: self.txid,
62            vout: self.vout,
63        }
64    }
65}
66
67/// Shorthand for converting a variable into a serde_json::Value.
68fn into_json<T>(val: T) -> Result<serde_json::Value>
69where
70    T: serde::ser::Serialize,
71{
72    Ok(serde_json::to_value(val)?)
73}
74
75/// Shorthand for converting an Option into an Option<serde_json::Value>.
76fn opt_into_json<T>(opt: Option<T>) -> Result<serde_json::Value>
77where
78    T: serde::ser::Serialize,
79{
80    match opt {
81        Some(val) => Ok(into_json(val)?),
82        None => Ok(serde_json::Value::Null),
83    }
84}
85
86/// Shorthand for `serde_json::Value::Null`.
87fn null() -> serde_json::Value {
88    serde_json::Value::Null
89}
90
91/// Shorthand for an empty serde_json::Value array.
92fn empty_arr() -> serde_json::Value {
93    serde_json::Value::Array(vec![])
94}
95
96/// Shorthand for an empty serde_json object.
97fn empty_obj() -> serde_json::Value {
98    serde_json::Value::Object(Default::default())
99}
100
101/// Handle default values in the argument list
102///
103/// Substitute `Value::Null`s with corresponding values from `defaults` table,
104/// except when they are trailing, in which case just skip them altogether
105/// in returned list.
106///
107/// Note, that `defaults` corresponds to the last elements of `args`.
108///
109/// ```norust
110/// arg1 arg2 arg3 arg4
111///           def1 def2
112/// ```
113///
114/// Elements of `args` without corresponding `defaults` value, won't
115/// be substituted, because they are required.
116fn handle_defaults<'a, 'b>(
117    args: &'a mut [serde_json::Value],
118    defaults: &'b [serde_json::Value],
119) -> &'a [serde_json::Value] {
120    assert!(args.len() >= defaults.len());
121
122    // Pass over the optional arguments in backwards order, filling in defaults after the first
123    // non-null optional argument has been observed.
124    let mut first_non_null_optional_idx = None;
125    for i in 0..defaults.len() {
126        let args_i = args.len() - 1 - i;
127        let defaults_i = defaults.len() - 1 - i;
128        if args[args_i] == serde_json::Value::Null {
129            if first_non_null_optional_idx.is_some() {
130                if defaults[defaults_i] == serde_json::Value::Null {
131                    panic!("Missing `default` for argument idx {}", args_i);
132                }
133                args[args_i] = defaults[defaults_i].clone();
134            }
135        } else if first_non_null_optional_idx.is_none() {
136            first_non_null_optional_idx = Some(args_i);
137        }
138    }
139
140    let required_num = args.len() - defaults.len();
141
142    if let Some(i) = first_non_null_optional_idx {
143        &args[..i + 1]
144    } else {
145        &args[..required_num]
146    }
147}
148
149/// Convert a possible-null result into an Option.
150fn opt_result<T: for<'a> serde::de::Deserialize<'a>>(
151    result: serde_json::Value,
152) -> Result<Option<T>> {
153    if result == serde_json::Value::Null {
154        Ok(None)
155    } else {
156        Ok(serde_json::from_value(result)?)
157    }
158}
159
160/// Used to pass raw txs into the API.
161pub trait RawTx: Sized + Clone {
162    fn raw_hex(self) -> String;
163}
164
165impl<'a> RawTx for &'a Transaction {
166    fn raw_hex(self) -> String {
167        encode::serialize_hex(self)
168    }
169}
170
171impl<'a> RawTx for &'a [u8] {
172    fn raw_hex(self) -> String {
173        self.to_lower_hex_string()
174    }
175}
176
177impl<'a> RawTx for &'a Vec<u8> {
178    fn raw_hex(self) -> String {
179        self.to_lower_hex_string()
180    }
181}
182
183impl<'a> RawTx for &'a str {
184    fn raw_hex(self) -> String {
185        self.to_owned()
186    }
187}
188
189impl RawTx for String {
190    fn raw_hex(self) -> String {
191        self
192    }
193}
194
195/// The different authentication methods for the client.
196#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
197pub enum Auth {
198    None,
199    UserPass(String, String),
200    CookieFile(PathBuf),
201}
202
203impl Auth {
204    /// Convert into the arguments that jsonrpc::Client needs.
205    pub fn get_user_pass(self) -> Result<(Option<String>, Option<String>)> {
206        match self {
207            Auth::None => Ok((None, None)),
208            Auth::UserPass(u, p) => Ok((Some(u), Some(p))),
209            Auth::CookieFile(path) => {
210                let line = BufReader::new(File::open(path)?)
211                    .lines()
212                    .next()
213                    .ok_or(Error::InvalidCookieFile)??;
214                let colon = line.find(':').ok_or(Error::InvalidCookieFile)?;
215                Ok((Some(line[..colon].into()), Some(line[colon + 1..].into())))
216            }
217        }
218    }
219}
220
221pub trait RpcApi: Sized {
222    /// Call a `cmd` rpc with given `args` list
223    fn call<T: for<'a> serde::de::Deserialize<'a>>(
224        &self,
225        cmd: &str,
226        args: &[serde_json::Value],
227    ) -> Result<T>;
228
229    /// Query an object implementing `Querable` type
230    fn get_by_id<T: queryable::Queryable<Self>>(
231        &self,
232        id: &<T as queryable::Queryable<Self>>::Id,
233    ) -> Result<T> {
234        T::query(&self, &id)
235    }
236
237    fn get_network_info(&self) -> Result<json::GetNetworkInfoResult> {
238        #[cfg(feature = "bitcoin_with_satsnet")]
239        return self.call("getinfo", &[]);
240        #[cfg(not(feature = "bitcoin_with_satsnet"))]
241        return self.call("getnetworkinfo", &[]);
242    }
243
244    fn get_index_info(&self) -> Result<json::GetIndexInfoResult> {
245        self.call("getindexinfo", &[])
246    }
247
248    fn version(&self) -> Result<usize> {
249        #[derive(Deserialize)]
250        struct Response {
251            pub version: usize,
252        }
253
254        #[cfg(feature = "bitcoin_with_satsnet")]
255        let res: Response = self.call("getinfo", &[])?;
256        #[cfg(not(feature = "bitcoin_with_satsnet"))]
257        let res: Response = self.call("getnetworkinfo", &[])?;
258        Ok(res.version)
259    }
260
261    fn add_multisig_address(
262        &self,
263        nrequired: usize,
264        keys: &[json::PubKeyOrAddress],
265        label: Option<&str>,
266        address_type: Option<json::AddressType>,
267    ) -> Result<json::AddMultiSigAddressResult> {
268        let mut args = [
269            into_json(nrequired)?,
270            into_json(keys)?,
271            opt_into_json(label)?,
272            opt_into_json(address_type)?,
273        ];
274        self.call("addmultisigaddress", handle_defaults(&mut args, &[into_json("")?, null()]))
275    }
276
277    fn load_wallet(&self, wallet: &str) -> Result<json::LoadWalletResult> {
278        self.call("loadwallet", &[wallet.into()])
279    }
280
281    fn unload_wallet(&self, wallet: Option<&str>) -> Result<Option<json::UnloadWalletResult>> {
282        let mut args = [opt_into_json(wallet)?];
283        self.call("unloadwallet", handle_defaults(&mut args, &[null()]))
284    }
285
286    fn create_wallet(
287        &self,
288        wallet: &str,
289        disable_private_keys: Option<bool>,
290        blank: Option<bool>,
291        passphrase: Option<&str>,
292        avoid_reuse: Option<bool>,
293    ) -> Result<json::LoadWalletResult> {
294        let mut args = [
295            wallet.into(),
296            opt_into_json(disable_private_keys)?,
297            opt_into_json(blank)?,
298            opt_into_json(passphrase)?,
299            opt_into_json(avoid_reuse)?,
300        ];
301        self.call(
302            "createwallet",
303            handle_defaults(&mut args, &[false.into(), false.into(), into_json("")?, false.into()]),
304        )
305    }
306
307    fn list_wallets(&self) -> Result<Vec<String>> {
308        self.call("listwallets", &[])
309    }
310
311    fn list_wallet_dir(&self) -> Result<Vec<String>> {
312        let result: json::ListWalletDirResult = self.call("listwalletdir", &[])?;
313        let names = result.wallets.into_iter().map(|x| x.name).collect();
314        Ok(names)
315    }
316
317    fn get_wallet_info(&self) -> Result<json::GetWalletInfoResult> {
318        self.call("getwalletinfo", &[])
319    }
320
321    fn backup_wallet(&self, destination: Option<&str>) -> Result<()> {
322        let mut args = [opt_into_json(destination)?];
323        self.call("backupwallet", handle_defaults(&mut args, &[null()]))
324    }
325
326    fn dump_private_key(&self, address: &Address) -> Result<PrivateKey> {
327        self.call("dumpprivkey", &[address.to_string().into()])
328    }
329
330    fn encrypt_wallet(&self, passphrase: &str) -> Result<()> {
331        self.call("encryptwallet", &[into_json(passphrase)?])
332    }
333
334    fn get_difficulty(&self) -> Result<f64> {
335        self.call("getdifficulty", &[])
336    }
337
338    fn get_connection_count(&self) -> Result<usize> {
339        self.call("getconnectioncount", &[])
340    }
341
342    fn get_block(&self, hash: &bitcoin::BlockHash) -> Result<Block> {
343        let hex: String = self.call("getblock", &[into_json(hash)?, 0.into()])?;
344        Ok(encode::deserialize_hex(&hex)?)
345    }
346
347    fn get_block_hex(&self, hash: &bitcoin::BlockHash) -> Result<String> {
348        self.call("getblock", &[into_json(hash)?, 0.into()])
349    }
350
351    fn get_block_info(&self, hash: &bitcoin::BlockHash) -> Result<json::GetBlockResult> {
352        self.call("getblock", &[into_json(hash)?, 1.into()])
353    }
354    //TODO(stevenroose) add getblock_txs
355
356    fn get_block_header(&self, hash: &bitcoin::BlockHash) -> Result<bitcoin::block::Header> {
357        let hex: String = self.call("getblockheader", &[into_json(hash)?, false.into()])?;
358        Ok(encode::deserialize_hex(&hex)?)
359    }
360
361    fn get_block_header_info(
362        &self,
363        hash: &bitcoin::BlockHash,
364    ) -> Result<json::GetBlockHeaderResult> {
365        self.call("getblockheader", &[into_json(hash)?, true.into()])
366    }
367
368    fn get_mining_info(&self) -> Result<json::GetMiningInfoResult> {
369        self.call("getmininginfo", &[])
370    }
371
372    fn get_block_template(
373        &self,
374        mode: json::GetBlockTemplateModes,
375        rules: &[json::GetBlockTemplateRules],
376        capabilities: &[json::GetBlockTemplateCapabilities],
377    ) -> Result<json::GetBlockTemplateResult> {
378        #[derive(Serialize)]
379        struct Argument<'a> {
380            mode: json::GetBlockTemplateModes,
381            rules: &'a [json::GetBlockTemplateRules],
382            capabilities: &'a [json::GetBlockTemplateCapabilities],
383        }
384
385        self.call(
386            "getblocktemplate",
387            &[into_json(Argument {
388                mode: mode,
389                rules: rules,
390                capabilities: capabilities,
391            })?],
392        )
393    }
394
395    /// Returns a data structure containing various state info regarding
396    /// blockchain processing.
397    #[cfg(feature = "bitcoin_with_satsnet")]
398    fn get_blockchain_info(&self) -> Result<json::GetBlockchainInfoResult> {
399        let raw: serde_json::Value = self.call("getblockchaininfo", &[])?;
400        Ok(if self.version()? < 24_02_00 {
401            let msg = format!(
402                "{} is not supported - please use satsnet? /btcd 240200+",
403                self.version()?
404            );
405            return Err(Error::ReturnedError(msg));
406        } else {
407            serde_json::from_value(raw)?
408        })
409    }
410
411    #[cfg(not(feature = "bitcoin_with_satsnet"))]
412    fn get_blockchain_info(&self) -> Result<json::GetBlockchainInfoResult> {
413        let mut raw: serde_json::Value = self.call("getblockchaininfo", &[])?;
414        // The softfork fields are not backwards compatible:
415        // - 0.18.x returns a "softforks" array and a "bip9_softforks" map.
416        // - 0.19.x returns a "softforks" map.
417        Ok(if self.version()? < 190000 {
418            use crate::Error::UnexpectedStructure as err;
419
420            // First, remove both incompatible softfork fields.
421            // We need to scope the mutable ref here for v1.29 borrowck.
422            let (bip9_softforks, old_softforks) = {
423                let map = raw.as_object_mut().ok_or(err)?;
424                let bip9_softforks = map.remove("bip9_softforks").ok_or(err)?;
425                let old_softforks = map.remove("softforks").ok_or(err)?;
426                // Put back an empty "softforks" field.
427                map.insert("softforks".into(), serde_json::Map::new().into());
428                (bip9_softforks, old_softforks)
429            };
430            let mut ret: json::GetBlockchainInfoResult = serde_json::from_value(raw)?;
431
432            // Then convert both softfork types and add them.
433            for sf in old_softforks.as_array().ok_or(err)?.iter() {
434                let json = sf.as_object().ok_or(err)?;
435                let id = json.get("id").ok_or(err)?.as_str().ok_or(err)?;
436                let reject = json.get("reject").ok_or(err)?.as_object().ok_or(err)?;
437                let active = reject.get("status").ok_or(err)?.as_bool().ok_or(err)?;
438                ret.softforks.insert(
439                    id.into(),
440                    json::Softfork {
441                        type_: json::SoftforkType::Buried,
442                        bip9: None,
443                        height: None,
444                        active: active,
445                    },
446                );
447            }
448            for (id, sf) in bip9_softforks.as_object().ok_or(err)?.iter() {
449                #[derive(Deserialize)]
450                struct OldBip9SoftFork {
451                    pub status: json::Bip9SoftforkStatus,
452                    pub bit: Option<u8>,
453                    #[serde(rename = "startTime")]
454                    pub start_time: i64,
455                    pub timeout: u64,
456                    pub since: u32,
457                    pub statistics: Option<json::Bip9SoftforkStatistics>,
458                }
459                let sf: OldBip9SoftFork = serde_json::from_value(sf.clone())?;
460                ret.softforks.insert(
461                    id.clone(),
462                    json::Softfork {
463                        type_: json::SoftforkType::Bip9,
464                        bip9: Some(json::Bip9SoftforkInfo {
465                            status: sf.status,
466                            bit: sf.bit,
467                            start_time: sf.start_time,
468                            timeout: sf.timeout,
469                            since: sf.since,
470                            statistics: sf.statistics,
471                        }),
472                        height: None,
473                        active: sf.status == json::Bip9SoftforkStatus::Active,
474                    },
475                );
476            }
477            ret
478        } else {
479            serde_json::from_value(raw)?
480        })
481    }
482
483    /// Returns the numbers of block in the longest chain.
484    fn get_block_count(&self) -> Result<u64> {
485        self.call("getblockcount", &[])
486    }
487
488    /// Returns the hash of the best (tip) block in the longest blockchain.
489    fn get_best_block_hash(&self) -> Result<bitcoin::BlockHash> {
490        self.call("getbestblockhash", &[])
491    }
492
493    /// Get block hash at a given height
494    fn get_block_hash(&self, height: u64) -> Result<bitcoin::BlockHash> {
495        self.call("getblockhash", &[height.into()])
496    }
497
498    fn get_block_stats(&self, height: u64) -> Result<json::GetBlockStatsResult> {
499        self.call("getblockstats", &[height.into()])
500    }
501
502    fn get_block_stats_fields(
503        &self,
504        height: u64,
505        fields: &[json::BlockStatsFields],
506    ) -> Result<json::GetBlockStatsResultPartial> {
507        self.call("getblockstats", &[height.into(), fields.into()])
508    }
509
510    fn get_raw_transaction(
511        &self,
512        txid: &bitcoin::Txid,
513        block_hash: Option<&bitcoin::BlockHash>,
514    ) -> Result<Transaction> {
515        let mut args = [into_json(txid)?, into_json(false)?, opt_into_json(block_hash)?];
516        let hex: String = self.call("getrawtransaction", handle_defaults(&mut args, &[null()]))?;
517        Ok(encode::deserialize_hex(&hex)?)
518    }
519
520    fn get_raw_transaction_hex(
521        &self,
522        txid: &bitcoin::Txid,
523        block_hash: Option<&bitcoin::BlockHash>,
524    ) -> Result<String> {
525        let mut args = [into_json(txid)?, into_json(false)?, opt_into_json(block_hash)?];
526        self.call("getrawtransaction", handle_defaults(&mut args, &[null()]))
527    }
528
529    fn get_raw_transaction_info(
530        &self,
531        txid: &bitcoin::Txid,
532        block_hash: Option<&bitcoin::BlockHash>,
533    ) -> Result<json::GetRawTransactionResult> {
534        let mut args = [into_json(txid)?, into_json(true)?, opt_into_json(block_hash)?];
535        self.call("getrawtransaction", handle_defaults(&mut args, &[null()]))
536    }
537
538    fn get_block_filter(
539        &self,
540        block_hash: &bitcoin::BlockHash,
541    ) -> Result<json::GetBlockFilterResult> {
542        self.call("getblockfilter", &[into_json(block_hash)?])
543    }
544
545    fn get_balance(
546        &self,
547        minconf: Option<usize>,
548        include_watchonly: Option<bool>,
549    ) -> Result<Amount> {
550        let mut args = ["*".into(), opt_into_json(minconf)?, opt_into_json(include_watchonly)?];
551        Ok(Amount::from_btc(
552            self.call("getbalance", handle_defaults(&mut args, &[0.into(), null()]))?,
553        )?)
554    }
555
556    fn get_balances(&self) -> Result<json::GetBalancesResult> {
557        Ok(self.call("getbalances", &[])?)
558    }
559
560    fn get_received_by_address(&self, address: &Address, minconf: Option<u32>) -> Result<Amount> {
561        let mut args = [address.to_string().into(), opt_into_json(minconf)?];
562        Ok(Amount::from_btc(
563            self.call("getreceivedbyaddress", handle_defaults(&mut args, &[null()]))?,
564        )?)
565    }
566
567    fn get_transaction(
568        &self,
569        txid: &bitcoin::Txid,
570        include_watchonly: Option<bool>,
571    ) -> Result<json::GetTransactionResult> {
572        let mut args = [into_json(txid)?, opt_into_json(include_watchonly)?];
573        self.call("gettransaction", handle_defaults(&mut args, &[null()]))
574    }
575
576    fn list_transactions(
577        &self,
578        label: Option<&str>,
579        count: Option<usize>,
580        skip: Option<usize>,
581        include_watchonly: Option<bool>,
582    ) -> Result<Vec<json::ListTransactionResult>> {
583        let mut args = [
584            label.unwrap_or("*").into(),
585            opt_into_json(count)?,
586            opt_into_json(skip)?,
587            opt_into_json(include_watchonly)?,
588        ];
589        self.call("listtransactions", handle_defaults(&mut args, &[10.into(), 0.into(), null()]))
590    }
591
592    fn list_since_block(
593        &self,
594        blockhash: Option<&bitcoin::BlockHash>,
595        target_confirmations: Option<usize>,
596        include_watchonly: Option<bool>,
597        include_removed: Option<bool>,
598    ) -> Result<json::ListSinceBlockResult> {
599        let mut args = [
600            opt_into_json(blockhash)?,
601            opt_into_json(target_confirmations)?,
602            opt_into_json(include_watchonly)?,
603            opt_into_json(include_removed)?,
604        ];
605        self.call("listsinceblock", handle_defaults(&mut args, &[null()]))
606    }
607
608    fn get_tx_out(
609        &self,
610        txid: &bitcoin::Txid,
611        vout: u32,
612        include_mempool: Option<bool>,
613    ) -> Result<Option<json::GetTxOutResult>> {
614        let mut args = [into_json(txid)?, into_json(vout)?, opt_into_json(include_mempool)?];
615        opt_result(self.call("gettxout", handle_defaults(&mut args, &[null()]))?)
616    }
617
618    fn get_tx_out_proof(
619        &self,
620        txids: &[bitcoin::Txid],
621        block_hash: Option<&bitcoin::BlockHash>,
622    ) -> Result<Vec<u8>> {
623        let mut args = [into_json(txids)?, opt_into_json(block_hash)?];
624        let hex: String = self.call("gettxoutproof", handle_defaults(&mut args, &[null()]))?;
625        Ok(FromHex::from_hex(&hex)?)
626    }
627
628    fn import_public_key(
629        &self,
630        pubkey: &PublicKey,
631        label: Option<&str>,
632        rescan: Option<bool>,
633    ) -> Result<()> {
634        let mut args = [pubkey.to_string().into(), opt_into_json(label)?, opt_into_json(rescan)?];
635        self.call("importpubkey", handle_defaults(&mut args, &[into_json("")?, null()]))
636    }
637
638    fn import_private_key(
639        &self,
640        privkey: &PrivateKey,
641        label: Option<&str>,
642        rescan: Option<bool>,
643    ) -> Result<()> {
644        let mut args = [privkey.to_string().into(), opt_into_json(label)?, opt_into_json(rescan)?];
645        self.call("importprivkey", handle_defaults(&mut args, &[into_json("")?, null()]))
646    }
647
648    fn import_address(
649        &self,
650        address: &Address,
651        label: Option<&str>,
652        rescan: Option<bool>,
653    ) -> Result<()> {
654        let mut args = [address.to_string().into(), opt_into_json(label)?, opt_into_json(rescan)?];
655        self.call("importaddress", handle_defaults(&mut args, &[into_json("")?, null()]))
656    }
657
658    fn import_address_script(
659        &self,
660        script: &Script,
661        label: Option<&str>,
662        rescan: Option<bool>,
663        p2sh: Option<bool>,
664    ) -> Result<()> {
665        let mut args = [
666            script.to_hex_string().into(),
667            opt_into_json(label)?,
668            opt_into_json(rescan)?,
669            opt_into_json(p2sh)?,
670        ];
671        self.call(
672            "importaddress",
673            handle_defaults(&mut args, &[into_json("")?, true.into(), null()]),
674        )
675    }
676
677    fn import_multi(
678        &self,
679        requests: &[json::ImportMultiRequest],
680        options: Option<&json::ImportMultiOptions>,
681    ) -> Result<Vec<json::ImportMultiResult>> {
682        let mut json_requests = Vec::with_capacity(requests.len());
683        for req in requests {
684            json_requests.push(serde_json::to_value(req)?);
685        }
686        let mut args = [json_requests.into(), opt_into_json(options)?];
687        self.call("importmulti", handle_defaults(&mut args, &[null()]))
688    }
689
690    fn import_descriptors(
691        &self,
692        req: json::ImportDescriptors,
693    ) -> Result<Vec<json::ImportMultiResult>> {
694        let json_request = vec![serde_json::to_value(req)?];
695        self.call("importdescriptors", handle_defaults(&mut [json_request.into()], &[null()]))
696    }
697
698    fn set_label(&self, address: &Address, label: &str) -> Result<()> {
699        self.call("setlabel", &[address.to_string().into(), label.into()])
700    }
701
702    fn key_pool_refill(&self, new_size: Option<usize>) -> Result<()> {
703        let mut args = [opt_into_json(new_size)?];
704        self.call("keypoolrefill", handle_defaults(&mut args, &[null()]))
705    }
706
707    fn list_unspent(
708        &self,
709        minconf: Option<usize>,
710        maxconf: Option<usize>,
711        addresses: Option<&[&Address<NetworkChecked>]>,
712        include_unsafe: Option<bool>,
713        query_options: Option<json::ListUnspentQueryOptions>,
714    ) -> Result<Vec<json::ListUnspentResultEntry>> {
715        let mut args = [
716            opt_into_json(minconf)?,
717            opt_into_json(maxconf)?,
718            opt_into_json(addresses)?,
719            opt_into_json(include_unsafe)?,
720            opt_into_json(query_options)?,
721        ];
722        let defaults = [into_json(0)?, into_json(9999999)?, empty_arr(), into_json(true)?, null()];
723        self.call("listunspent", handle_defaults(&mut args, &defaults))
724    }
725
726    /// To unlock, use [unlock_unspent].
727    fn lock_unspent(&self, outputs: &[OutPoint]) -> Result<bool> {
728        let outputs: Vec<_> = outputs
729            .into_iter()
730            .map(|o| serde_json::to_value(JsonOutPoint::from(*o)).unwrap())
731            .collect();
732        self.call("lockunspent", &[false.into(), outputs.into()])
733    }
734
735    fn unlock_unspent(&self, outputs: &[OutPoint]) -> Result<bool> {
736        let outputs: Vec<_> = outputs
737            .into_iter()
738            .map(|o| serde_json::to_value(JsonOutPoint::from(*o)).unwrap())
739            .collect();
740        self.call("lockunspent", &[true.into(), outputs.into()])
741    }
742
743    /// Unlock all unspent UTXOs.
744    fn unlock_unspent_all(&self) -> Result<bool> {
745        self.call("lockunspent", &[true.into()])
746    }
747
748    fn list_received_by_address(
749        &self,
750        address_filter: Option<&Address>,
751        minconf: Option<u32>,
752        include_empty: Option<bool>,
753        include_watchonly: Option<bool>,
754    ) -> Result<Vec<json::ListReceivedByAddressResult>> {
755        let mut args = [
756            opt_into_json(minconf)?,
757            opt_into_json(include_empty)?,
758            opt_into_json(include_watchonly)?,
759            opt_into_json(address_filter)?,
760        ];
761        let defaults = [1.into(), false.into(), false.into(), null()];
762        self.call("listreceivedbyaddress", handle_defaults(&mut args, &defaults))
763    }
764
765    fn create_psbt(
766        &self,
767        inputs: &[json::CreateRawTransactionInput],
768        outputs: &HashMap<String, Amount>,
769        locktime: Option<i64>,
770        replaceable: Option<bool>,
771    ) -> Result<String> {
772        let outs_converted = serde_json::Map::from_iter(
773            outputs.iter().map(|(k, v)| (k.clone(), serde_json::Value::from(v.to_btc()))),
774        );
775        self.call(
776            "createpsbt",
777            &[
778                into_json(inputs)?,
779                into_json(outs_converted)?,
780                into_json(locktime)?,
781                into_json(replaceable)?,
782            ],
783        )
784    }
785
786    fn create_raw_transaction_hex(
787        &self,
788        utxos: &[json::CreateRawTransactionInput],
789        outs: &HashMap<String, Amount>,
790        locktime: Option<i64>,
791        replaceable: Option<bool>,
792    ) -> Result<String> {
793        let outs_converted = serde_json::Map::from_iter(
794            outs.iter().map(|(k, v)| (k.clone(), serde_json::Value::from(v.to_btc()))),
795        );
796        let mut args = [
797            into_json(utxos)?,
798            into_json(outs_converted)?,
799            opt_into_json(locktime)?,
800            opt_into_json(replaceable)?,
801        ];
802        let defaults = [into_json(0i64)?, null()];
803        self.call("createrawtransaction", handle_defaults(&mut args, &defaults))
804    }
805
806    fn create_raw_transaction(
807        &self,
808        utxos: &[json::CreateRawTransactionInput],
809        outs: &HashMap<String, Amount>,
810        locktime: Option<i64>,
811        replaceable: Option<bool>,
812    ) -> Result<Transaction> {
813        let hex: String = self.create_raw_transaction_hex(utxos, outs, locktime, replaceable)?;
814        Ok(encode::deserialize_hex(&hex)?)
815    }
816
817    fn decode_raw_transaction<R: RawTx>(
818        &self,
819        tx: R,
820        is_witness: Option<bool>,
821    ) -> Result<json::DecodeRawTransactionResult> {
822        let mut args = [tx.raw_hex().into(), opt_into_json(is_witness)?];
823        let defaults = [null()];
824        self.call("decoderawtransaction", handle_defaults(&mut args, &defaults))
825    }
826
827    fn fund_raw_transaction<R: RawTx>(
828        &self,
829        tx: R,
830        options: Option<&json::FundRawTransactionOptions>,
831        is_witness: Option<bool>,
832    ) -> Result<json::FundRawTransactionResult> {
833        let mut args = [tx.raw_hex().into(), opt_into_json(options)?, opt_into_json(is_witness)?];
834        let defaults = [empty_obj(), null()];
835        self.call("fundrawtransaction", handle_defaults(&mut args, &defaults))
836    }
837
838    #[deprecated]
839    fn sign_raw_transaction<R: RawTx>(
840        &self,
841        tx: R,
842        utxos: Option<&[json::SignRawTransactionInput]>,
843        private_keys: Option<&[PrivateKey]>,
844        sighash_type: Option<json::SigHashType>,
845    ) -> Result<json::SignRawTransactionResult> {
846        let mut args = [
847            tx.raw_hex().into(),
848            opt_into_json(utxos)?,
849            opt_into_json(private_keys)?,
850            opt_into_json(sighash_type)?,
851        ];
852        let defaults = [empty_arr(), empty_arr(), null()];
853        self.call("signrawtransaction", handle_defaults(&mut args, &defaults))
854    }
855
856    fn sign_raw_transaction_with_wallet<R: RawTx>(
857        &self,
858        tx: R,
859        utxos: Option<&[json::SignRawTransactionInput]>,
860        sighash_type: Option<json::SigHashType>,
861    ) -> Result<json::SignRawTransactionResult> {
862        let mut args = [tx.raw_hex().into(), opt_into_json(utxos)?, opt_into_json(sighash_type)?];
863        let defaults = [empty_arr(), null()];
864        self.call("signrawtransactionwithwallet", handle_defaults(&mut args, &defaults))
865    }
866
867    fn sign_raw_transaction_with_key<R: RawTx>(
868        &self,
869        tx: R,
870        privkeys: &[PrivateKey],
871        prevtxs: Option<&[json::SignRawTransactionInput]>,
872        sighash_type: Option<json::SigHashType>,
873    ) -> Result<json::SignRawTransactionResult> {
874        let mut args = [
875            tx.raw_hex().into(),
876            into_json(privkeys)?,
877            opt_into_json(prevtxs)?,
878            opt_into_json(sighash_type)?,
879        ];
880        let defaults = [empty_arr(), null()];
881        self.call("signrawtransactionwithkey", handle_defaults(&mut args, &defaults))
882    }
883
884    fn test_mempool_accept<R: RawTx>(
885        &self,
886        rawtxs: &[R],
887    ) -> Result<Vec<json::TestMempoolAcceptResult>> {
888        let hexes: Vec<serde_json::Value> =
889            rawtxs.to_vec().into_iter().map(|r| r.raw_hex().into()).collect();
890        self.call("testmempoolaccept", &[hexes.into()])
891    }
892
893    fn stop(&self) -> Result<String> {
894        self.call("stop", &[])
895    }
896
897    fn verify_message(
898        &self,
899        address: &Address,
900        signature: &Signature,
901        message: &str,
902    ) -> Result<bool> {
903        let args = [address.to_string().into(), signature.to_string().into(), into_json(message)?];
904        self.call("verifymessage", &args)
905    }
906
907    /// Generate new address under own control
908    fn get_new_address(
909        &self,
910        label: Option<&str>,
911        address_type: Option<json::AddressType>,
912    ) -> Result<Address<NetworkUnchecked>> {
913        self.call("getnewaddress", &[opt_into_json(label)?, opt_into_json(address_type)?])
914    }
915
916    /// Generate new address for receiving change
917    fn get_raw_change_address(&self, address_type: Option<json::AddressType>) -> Result<Address<NetworkUnchecked>> {
918        self.call("getrawchangeaddress", &[opt_into_json(address_type)?])
919    }
920
921    fn get_address_info(&self, address: &Address) -> Result<json::GetAddressInfoResult> {
922        self.call("getaddressinfo", &[address.to_string().into()])
923    }
924
925    /// Mine `block_num` blocks and pay coinbase to `address`
926    ///
927    /// Returns hashes of the generated blocks
928    fn generate_to_address(
929        &self,
930        block_num: u64,
931        address: &Address<NetworkChecked>,
932    ) -> Result<Vec<bitcoin::BlockHash>> {
933        self.call("generatetoaddress", &[block_num.into(), address.to_string().into()])
934    }
935
936    /// Mine up to block_num blocks immediately (before the RPC call returns)
937    /// to an address in the wallet.
938    fn generate(&self, block_num: u64, maxtries: Option<u64>) -> Result<Vec<bitcoin::BlockHash>> {
939        self.call("generate", &[block_num.into(), opt_into_json(maxtries)?])
940    }
941
942    /// Mark a block as invalid by `block_hash`
943    fn invalidate_block(&self, block_hash: &bitcoin::BlockHash) -> Result<()> {
944        self.call("invalidateblock", &[into_json(block_hash)?])
945    }
946
947    /// Mark a block as valid by `block_hash`
948    fn reconsider_block(&self, block_hash: &bitcoin::BlockHash) -> Result<()> {
949        self.call("reconsiderblock", &[into_json(block_hash)?])
950    }
951
952    /// Returns details on the active state of the TX memory pool
953    fn get_mempool_info(&self) -> Result<json::GetMempoolInfoResult> {
954        self.call("getmempoolinfo", &[])
955    }
956
957    /// Get txids of all transactions in a memory pool
958    fn get_raw_mempool(&self) -> Result<Vec<bitcoin::Txid>> {
959        self.call("getrawmempool", &[])
960    }
961
962    /// Get details for the transactions in a memory pool
963    fn get_raw_mempool_verbose(
964        &self,
965    ) -> Result<HashMap<bitcoin::Txid, json::GetMempoolEntryResult>> {
966        self.call("getrawmempool", &[into_json(true)?])
967    }
968
969    /// Get mempool data for given transaction
970    fn get_mempool_entry(&self, txid: &bitcoin::Txid) -> Result<json::GetMempoolEntryResult> {
971        self.call("getmempoolentry", &[into_json(txid)?])
972    }
973
974    /// Get information about all known tips in the block tree, including the
975    /// main chain as well as stale branches.
976    fn get_chain_tips(&self) -> Result<json::GetChainTipsResult> {
977        self.call("getchaintips", &[])
978    }
979
980    fn send_to_address(
981        &self,
982        address: &Address<NetworkChecked>,
983        amount: Amount,
984        comment: Option<&str>,
985        comment_to: Option<&str>,
986        subtract_fee: Option<bool>,
987        replaceable: Option<bool>,
988        confirmation_target: Option<u32>,
989        estimate_mode: Option<json::EstimateMode>,
990    ) -> Result<bitcoin::Txid> {
991        let mut args = [
992            address.to_string().into(),
993            into_json(amount.to_btc())?,
994            opt_into_json(comment)?,
995            opt_into_json(comment_to)?,
996            opt_into_json(subtract_fee)?,
997            opt_into_json(replaceable)?,
998            opt_into_json(confirmation_target)?,
999            opt_into_json(estimate_mode)?,
1000        ];
1001        self.call(
1002            "sendtoaddress",
1003            handle_defaults(
1004                &mut args,
1005                &["".into(), "".into(), false.into(), false.into(), 6.into(), null()],
1006            ),
1007        )
1008    }
1009
1010    /// Attempts to add a node to the addnode list.
1011    /// Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).
1012    fn add_node(&self, addr: &str) -> Result<()> {
1013        self.call("addnode", &[into_json(&addr)?, into_json("add")?])
1014    }
1015
1016    /// Attempts to remove a node from the addnode list.
1017    fn remove_node(&self, addr: &str) -> Result<()> {
1018        self.call("addnode", &[into_json(&addr)?, into_json("remove")?])
1019    }
1020
1021    /// Attempts to connect to a node without permanently adding it to the addnode list.
1022    fn onetry_node(&self, addr: &str) -> Result<()> {
1023        self.call("addnode", &[into_json(&addr)?, into_json("onetry")?])
1024    }
1025
1026    /// Immediately disconnects from the specified peer node.
1027    fn disconnect_node(&self, addr: &str) -> Result<()> {
1028        self.call("disconnectnode", &[into_json(&addr)?])
1029    }
1030
1031    fn disconnect_node_by_id(&self, node_id: u32) -> Result<()> {
1032        self.call("disconnectnode", &[into_json("")?, into_json(node_id)?])
1033    }
1034
1035    /// Returns information about the given added node, or all added nodes (note that onetry addnodes are not listed here)
1036    fn get_added_node_info(&self, node: Option<&str>) -> Result<Vec<json::GetAddedNodeInfoResult>> {
1037        if let Some(addr) = node {
1038            self.call("getaddednodeinfo", &[into_json(&addr)?])
1039        } else {
1040            self.call("getaddednodeinfo", &[])
1041        }
1042    }
1043
1044    /// Return known addresses which can potentially be used to find new nodes in the network
1045    fn get_node_addresses(
1046        &self,
1047        count: Option<usize>,
1048    ) -> Result<Vec<json::GetNodeAddressesResult>> {
1049        let cnt = count.unwrap_or(1);
1050        self.call("getnodeaddresses", &[into_json(&cnt)?])
1051    }
1052
1053    /// List all banned IPs/Subnets.
1054    fn list_banned(&self) -> Result<Vec<json::ListBannedResult>> {
1055        self.call("listbanned", &[])
1056    }
1057
1058    /// Clear all banned IPs.
1059    fn clear_banned(&self) -> Result<()> {
1060        self.call("clearbanned", &[])
1061    }
1062
1063    /// Attempts to add an IP/Subnet to the banned list.
1064    fn add_ban(&self, subnet: &str, bantime: u64, absolute: bool) -> Result<()> {
1065        self.call(
1066            "setban",
1067            &[into_json(&subnet)?, into_json("add")?, into_json(&bantime)?, into_json(&absolute)?],
1068        )
1069    }
1070
1071    /// Attempts to remove an IP/Subnet from the banned list.
1072    fn remove_ban(&self, subnet: &str) -> Result<()> {
1073        self.call("setban", &[into_json(&subnet)?, into_json("remove")?])
1074    }
1075
1076    /// Disable/enable all p2p network activity.
1077    fn set_network_active(&self, state: bool) -> Result<bool> {
1078        self.call("setnetworkactive", &[into_json(&state)?])
1079    }
1080
1081    /// Returns data about each connected network node as an array of
1082    /// [`PeerInfo`][]
1083    ///
1084    /// [`PeerInfo`]: net/struct.PeerInfo.html
1085    fn get_peer_info(&self) -> Result<Vec<json::GetPeerInfoResult>> {
1086        self.call("getpeerinfo", &[])
1087    }
1088
1089    /// Requests that a ping be sent to all other nodes, to measure ping
1090    /// time.
1091    ///
1092    /// Results provided in `getpeerinfo`, `pingtime` and `pingwait` fields
1093    /// are decimal seconds.
1094    ///
1095    /// Ping command is handled in queue with all other commands, so it
1096    /// measures processing backlog, not just network ping.
1097    fn ping(&self) -> Result<()> {
1098        self.call("ping", &[])
1099    }
1100
1101    fn send_raw_transaction<R: RawTx>(&self, tx: R) -> Result<bitcoin::Txid> {
1102        self.call("sendrawtransaction", &[tx.raw_hex().into()])
1103    }
1104
1105    fn estimate_smart_fee(
1106        &self,
1107        conf_target: u16,
1108        estimate_mode: Option<json::EstimateMode>,
1109    ) -> Result<json::EstimateSmartFeeResult> {
1110        let mut args = [into_json(conf_target)?, opt_into_json(estimate_mode)?];
1111        self.call("estimatesmartfee", handle_defaults(&mut args, &[null()]))
1112    }
1113
1114    /// Waits for a specific new block and returns useful info about it.
1115    /// Returns the current block on timeout or exit.
1116    ///
1117    /// # Arguments
1118    ///
1119    /// 1. `timeout`: Time in milliseconds to wait for a response. 0
1120    /// indicates no timeout.
1121    fn wait_for_new_block(&self, timeout: u64) -> Result<json::BlockRef> {
1122        self.call("waitfornewblock", &[into_json(timeout)?])
1123    }
1124
1125    /// Waits for a specific new block and returns useful info about it.
1126    /// Returns the current block on timeout or exit.
1127    ///
1128    /// # Arguments
1129    ///
1130    /// 1. `blockhash`: Block hash to wait for.
1131    /// 2. `timeout`: Time in milliseconds to wait for a response. 0
1132    /// indicates no timeout.
1133    fn wait_for_block(
1134        &self,
1135        blockhash: &bitcoin::BlockHash,
1136        timeout: u64,
1137    ) -> Result<json::BlockRef> {
1138        let args = [into_json(blockhash)?, into_json(timeout)?];
1139        self.call("waitforblock", &args)
1140    }
1141
1142    fn wallet_create_funded_psbt(
1143        &self,
1144        inputs: &[json::CreateRawTransactionInput],
1145        outputs: &HashMap<String, Amount>,
1146        locktime: Option<i64>,
1147        options: Option<json::WalletCreateFundedPsbtOptions>,
1148        bip32derivs: Option<bool>,
1149    ) -> Result<json::WalletCreateFundedPsbtResult> {
1150        let outputs_converted = serde_json::Map::from_iter(
1151            outputs.iter().map(|(k, v)| (k.clone(), serde_json::Value::from(v.to_btc()))),
1152        );
1153        let mut args = [
1154            into_json(inputs)?,
1155            into_json(outputs_converted)?,
1156            opt_into_json(locktime)?,
1157            opt_into_json(options)?,
1158            opt_into_json(bip32derivs)?,
1159        ];
1160        self.call(
1161            "walletcreatefundedpsbt",
1162            handle_defaults(&mut args, &[0.into(), serde_json::Map::new().into(), false.into()]),
1163        )
1164    }
1165
1166    fn wallet_process_psbt(
1167        &self,
1168        psbt: &str,
1169        sign: Option<bool>,
1170        sighash_type: Option<json::SigHashType>,
1171        bip32derivs: Option<bool>,
1172    ) -> Result<json::WalletProcessPsbtResult> {
1173        let mut args = [
1174            into_json(psbt)?,
1175            opt_into_json(sign)?,
1176            opt_into_json(sighash_type)?,
1177            opt_into_json(bip32derivs)?,
1178        ];
1179        let defaults = [
1180            true.into(),
1181            into_json(json::SigHashType::from(bitcoin::sighash::EcdsaSighashType::All))?,
1182            true.into(),
1183        ];
1184        self.call("walletprocesspsbt", handle_defaults(&mut args, &defaults))
1185    }
1186
1187    fn get_descriptor_info(&self, desc: &str) -> Result<json::GetDescriptorInfoResult> {
1188        self.call("getdescriptorinfo", &[desc.to_string().into()])
1189    }
1190
1191    fn join_psbt(&self, psbts: &[String]) -> Result<String> {
1192        self.call("joinpsbts", &[into_json(psbts)?])
1193    }
1194
1195    fn combine_psbt(&self, psbts: &[String]) -> Result<String> {
1196        self.call("combinepsbt", &[into_json(psbts)?])
1197    }
1198
1199    fn combine_raw_transaction(&self, hex_strings: &[String]) -> Result<String> {
1200        self.call("combinerawtransaction", &[into_json(hex_strings)?])
1201    }
1202
1203    fn finalize_psbt(&self, psbt: &str, extract: Option<bool>) -> Result<json::FinalizePsbtResult> {
1204        let mut args = [into_json(psbt)?, opt_into_json(extract)?];
1205        self.call("finalizepsbt", handle_defaults(&mut args, &[true.into()]))
1206    }
1207
1208    fn derive_addresses(&self, descriptor: &str, range: Option<[u32; 2]>) -> Result<Vec<Address<NetworkUnchecked>>> {
1209        let mut args = [into_json(descriptor)?, opt_into_json(range)?];
1210        self.call("deriveaddresses", handle_defaults(&mut args, &[null()]))
1211    }
1212
1213    fn rescan_blockchain(
1214        &self,
1215        start_from: Option<usize>,
1216        stop_height: Option<usize>,
1217    ) -> Result<(usize, Option<usize>)> {
1218        let mut args = [opt_into_json(start_from)?, opt_into_json(stop_height)?];
1219
1220        #[derive(Deserialize)]
1221        struct Response {
1222            pub start_height: usize,
1223            pub stop_height: Option<usize>,
1224        }
1225        let res: Response =
1226            self.call("rescanblockchain", handle_defaults(&mut args, &[0.into(), null()]))?;
1227        Ok((res.start_height, res.stop_height))
1228    }
1229
1230    /// Returns statistics about the unspent transaction output set.
1231    /// Note this call may take some time if you are not using coinstatsindex.
1232    fn get_tx_out_set_info(
1233        &self,
1234        hash_type: Option<json::TxOutSetHashType>,
1235        hash_or_height: Option<json::HashOrHeight>,
1236        use_index: Option<bool>,
1237    ) -> Result<json::GetTxOutSetInfoResult> {
1238        let mut args =
1239            [opt_into_json(hash_type)?, opt_into_json(hash_or_height)?, opt_into_json(use_index)?];
1240        self.call("gettxoutsetinfo", handle_defaults(&mut args, &[null(), null(), null()]))
1241    }
1242
1243    /// Returns information about network traffic, including bytes in, bytes out,
1244    /// and current time.
1245    fn get_net_totals(&self) -> Result<json::GetNetTotalsResult> {
1246        self.call("getnettotals", &[])
1247    }
1248
1249    /// Returns the estimated network hashes per second based on the last n blocks.
1250    fn get_network_hash_ps(&self, nblocks: Option<u64>, height: Option<u64>) -> Result<f64> {
1251        let mut args = [opt_into_json(nblocks)?, opt_into_json(height)?];
1252        self.call("getnetworkhashps", handle_defaults(&mut args, &[null(), null()]))
1253    }
1254
1255    /// Returns the total uptime of the server in seconds
1256    fn uptime(&self) -> Result<u64> {
1257        self.call("uptime", &[])
1258    }
1259
1260    /// Submit a block
1261    fn submit_block(&self, block: &bitcoin::Block) -> Result<()> {
1262        let block_hex: String = bitcoin::consensus::encode::serialize_hex(block);
1263        self.submit_block_hex(&block_hex)
1264    }
1265
1266    /// Submit a raw block
1267    fn submit_block_bytes(&self, block_bytes: &[u8]) -> Result<()> {
1268        let block_hex: String = block_bytes.to_lower_hex_string();
1269        self.submit_block_hex(&block_hex)
1270    }
1271
1272    /// Submit a block as a hex string
1273    fn submit_block_hex(&self, block_hex: &str) -> Result<()> {
1274        match self.call("submitblock", &[into_json(&block_hex)?]) {
1275            Ok(serde_json::Value::Null) => Ok(()),
1276            Ok(res) => Err(Error::ReturnedError(res.to_string())),
1277            Err(err) => Err(err.into()),
1278        }
1279    }
1280
1281    fn scan_tx_out_set_blocking(
1282        &self,
1283        descriptors: &[json::ScanTxOutRequest],
1284    ) -> Result<json::ScanTxOutResult> {
1285        self.call("scantxoutset", &["start".into(), into_json(descriptors)?])
1286    }
1287
1288    /// Returns information about the active ZeroMQ notifications
1289    fn get_zmq_notifications(&self) -> Result<Vec<json::GetZmqNotificationsResult>> {
1290        self.call("getzmqnotifications", &[])
1291    }
1292}
1293
1294/// Client implements a JSON-RPC client for the Bitcoin Core daemon or compatible APIs.
1295pub struct Client {
1296    client: jsonrpc::client::Client,
1297}
1298
1299impl fmt::Debug for Client {
1300    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1301        write!(f, "bitcoincore_rpc::Client({:?})", self.client)
1302    }
1303}
1304
1305impl Client {
1306    /// Creates a client to a bitcoind JSON-RPC server.
1307    ///
1308    /// Can only return [Err] when using cookie authentication.
1309    pub fn new(url: &str, auth: Auth) -> Result<Self> {
1310        let (user, pass) = auth.get_user_pass()?;
1311        jsonrpc::client::Client::simple_http(url, user, pass)
1312            .map(|client| Client {
1313                client,
1314            })
1315            .map_err(|e| super::error::Error::JsonRpc(e.into()))
1316    }
1317
1318    /// Create a new Client using the given [jsonrpc::Client].
1319    pub fn from_jsonrpc(client: jsonrpc::client::Client) -> Client {
1320        Client {
1321            client,
1322        }
1323    }
1324
1325    /// Get the underlying JSONRPC client.
1326    pub fn get_jsonrpc_client(&self) -> &jsonrpc::client::Client {
1327        &self.client
1328    }
1329}
1330
1331impl RpcApi for Client {
1332    /// Call an `cmd` rpc with given `args` list
1333    fn call<T: for<'a> serde::de::Deserialize<'a>>(
1334        &self,
1335        cmd: &str,
1336        args: &[serde_json::Value],
1337    ) -> Result<T> {
1338        let raw = serde_json::value::to_raw_value(args)?;
1339        let req = self.client.build_request(&cmd, Some(&*raw));
1340        if log_enabled!(Debug) {
1341            debug!(target: "bitcoincore_rpc", "JSON-RPC request: {} {}", cmd, serde_json::Value::from(args));
1342        }
1343
1344        let resp = self.client.send_request(req).map_err(Error::from);
1345        log_response(cmd, &resp);
1346        Ok(resp?.result()?)
1347    }
1348}
1349
1350fn log_response(cmd: &str, resp: &Result<jsonrpc::Response>) {
1351    if log_enabled!(Warn) || log_enabled!(Debug) || log_enabled!(Trace) {
1352        match resp {
1353            Err(ref e) => {
1354                if log_enabled!(Debug) {
1355                    debug!(target: "bitcoincore_rpc", "JSON-RPC failed parsing reply of {}: {:?}", cmd, e);
1356                }
1357            }
1358            Ok(ref resp) => {
1359                if let Some(ref e) = resp.error {
1360                    if log_enabled!(Debug) {
1361                        debug!(target: "bitcoincore_rpc", "JSON-RPC error for {}: {:?}", cmd, e);
1362                    }
1363                } else if log_enabled!(Trace) {
1364                    let def = serde_json::value::to_raw_value(&serde_json::value::Value::Null).unwrap();
1365                    let result = resp.result.as_ref().unwrap_or(&def);
1366                    trace!(target: "bitcoincore_rpc", "JSON-RPC response for {}: {}", cmd, result);
1367                }
1368            }
1369        }
1370    }
1371}
1372
1373#[cfg(test)]
1374mod tests {
1375    use super::*;
1376    use crate::bitcoin;
1377    use serde_json;
1378
1379    #[test]
1380    fn test_raw_tx() {
1381        use crate::bitcoin::consensus::encode;
1382        let client = Client::new("http://localhost/".into(), Auth::None).unwrap();
1383        let tx: bitcoin::Transaction = encode::deserialize(&Vec::<u8>::from_hex("0200000001586bd02815cf5faabfec986a4e50d25dbee089bd2758621e61c5fab06c334af0000000006b483045022100e85425f6d7c589972ee061413bcf08dc8c8e589ce37b217535a42af924f0e4d602205c9ba9cb14ef15513c9d946fa1c4b797883e748e8c32171bdf6166583946e35c012103dae30a4d7870cd87b45dd53e6012f71318fdd059c1c2623b8cc73f8af287bb2dfeffffff021dc4260c010000001976a914f602e88b2b5901d8aab15ebe4a97cf92ec6e03b388ac00e1f505000000001976a914687ffeffe8cf4e4c038da46a9b1d37db385a472d88acfd211500").unwrap()).unwrap();
1384
1385        assert!(client.send_raw_transaction(&tx).is_err());
1386        assert!(client.send_raw_transaction(&encode::serialize(&tx)).is_err());
1387        assert!(client.send_raw_transaction("deadbeef").is_err());
1388        assert!(client.send_raw_transaction("deadbeef".to_owned()).is_err());
1389    }
1390
1391    fn test_handle_defaults_inner() -> Result<()> {
1392        {
1393            let mut args = [into_json(0)?, null(), null()];
1394            let defaults = [into_json(1)?, into_json(2)?];
1395            let res = [into_json(0)?];
1396            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1397        }
1398        {
1399            let mut args = [into_json(0)?, into_json(1)?, null()];
1400            let defaults = [into_json(2)?];
1401            let res = [into_json(0)?, into_json(1)?];
1402            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1403        }
1404        {
1405            let mut args = [into_json(0)?, null(), into_json(5)?];
1406            let defaults = [into_json(2)?, into_json(3)?];
1407            let res = [into_json(0)?, into_json(2)?, into_json(5)?];
1408            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1409        }
1410        {
1411            let mut args = [into_json(0)?, null(), into_json(5)?, null()];
1412            let defaults = [into_json(2)?, into_json(3)?, into_json(4)?];
1413            let res = [into_json(0)?, into_json(2)?, into_json(5)?];
1414            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1415        }
1416        {
1417            let mut args = [null(), null()];
1418            let defaults = [into_json(2)?, into_json(3)?];
1419            let res: [serde_json::Value; 0] = [];
1420            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1421        }
1422        {
1423            let mut args = [null(), into_json(1)?];
1424            let defaults = [];
1425            let res = [null(), into_json(1)?];
1426            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1427        }
1428        {
1429            let mut args = [];
1430            let defaults = [];
1431            let res: [serde_json::Value; 0] = [];
1432            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1433        }
1434        {
1435            let mut args = [into_json(0)?];
1436            let defaults = [into_json(2)?];
1437            let res = [into_json(0)?];
1438            assert_eq!(handle_defaults(&mut args, &defaults), &res);
1439        }
1440        Ok(())
1441    }
1442
1443    #[test]
1444    fn test_handle_defaults() {
1445        test_handle_defaults_inner().unwrap();
1446    }
1447
1448    #[test]
1449    fn auth_cookie_file_ignores_newline() {
1450        let tempdir = tempfile::tempdir().unwrap();
1451        let path = tempdir.path().join("cookie");
1452        std::fs::write(&path, "foo:bar\n").unwrap();
1453        assert_eq!(
1454            Auth::CookieFile(path).get_user_pass().unwrap(),
1455            (Some("foo".into()), Some("bar".into())),
1456        );
1457    }
1458
1459    #[test]
1460    fn auth_cookie_file_ignores_additional_lines() {
1461        let tempdir = tempfile::tempdir().unwrap();
1462        let path = tempdir.path().join("cookie");
1463        std::fs::write(&path, "foo:bar\nbaz").unwrap();
1464        assert_eq!(
1465            Auth::CookieFile(path).get_user_pass().unwrap(),
1466            (Some("foo".into()), Some("bar".into())),
1467        );
1468    }
1469
1470    #[test]
1471    fn auth_cookie_file_fails_if_colon_isnt_present() {
1472        let tempdir = tempfile::tempdir().unwrap();
1473        let path = tempdir.path().join("cookie");
1474        std::fs::write(&path, "foobar").unwrap();
1475        assert!(matches!(Auth::CookieFile(path).get_user_pass(), Err(Error::InvalidCookieFile)));
1476    }
1477}