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