bitcoin_async_client/
client.rs

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