bitcoincore_rpc_json_async/
lib.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
11//! # Rust Client for Bitcoin Core API
12//!
13//! This is a client library for the Bitcoin Core JSON-RPC API.
14//!
15
16
17use std::collections::HashMap;
18pub use bitcoin;
19
20use bitcoin::consensus::encode;
21use bitcoin::hashes::hex::{FromHex, ToHex};
22use bitcoin::hashes::sha256;
23use bitcoin::util::{bip158, bip32};
24use bitcoin::{Address, Amount, PrivateKey, PublicKey, Script, SignedAmount, Transaction};
25use serde::de::Error as SerdeError;
26use serde::{Deserialize, Serialize};
27
28//TODO(stevenroose) consider using a Time type
29
30/// A module used for serde serialization of bytes in hexadecimal format.
31///
32/// The module is compatible with the serde attribute.
33pub mod serde_hex {
34    use bitcoin::hashes::hex::{FromHex, ToHex};
35    use serde::de::Error;
36    use serde::{Deserializer, Serializer};
37
38    pub fn serialize<S: Serializer>(b: &Vec<u8>, s: S) -> Result<S::Ok, S::Error> {
39        s.serialize_str(&b.to_hex())
40    }
41
42    pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
43        let hex_str: String = ::serde::Deserialize::deserialize(d)?;
44        Ok(FromHex::from_hex(&hex_str).map_err(D::Error::custom)?)
45    }
46
47    pub mod opt {
48        use bitcoin::hashes::hex::{FromHex, ToHex};
49        use serde::de::Error;
50        use serde::{Deserializer, Serializer};
51
52        pub fn serialize<S: Serializer>(b: &Option<Vec<u8>>, s: S) -> Result<S::Ok, S::Error> {
53            match *b {
54                None => s.serialize_none(),
55                Some(ref b) => s.serialize_str(&b.to_hex()),
56            }
57        }
58
59        pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Option<Vec<u8>>, D::Error> {
60            let hex_str: String = ::serde::Deserialize::deserialize(d)?;
61            Ok(Some(FromHex::from_hex(&hex_str).map_err(D::Error::custom)?))
62        }
63    }
64}
65
66#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
67pub struct GetNetworkInfoResultNetwork {
68    pub name: String,
69    pub limited: bool,
70    pub reachable: bool,
71    pub proxy: String,
72    pub proxy_randomize_credentials: bool,
73}
74
75#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
76pub struct GetNetworkInfoResultAddress {
77    pub address: String,
78    pub port: usize,
79    pub score: usize,
80}
81
82#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
83pub struct GetNetworkInfoResult {
84    pub version: usize,
85    pub subversion: String,
86    #[serde(rename = "protocolversion")]
87    pub protocol_version: usize,
88    #[serde(rename = "localservices")]
89    pub local_services: String,
90    #[serde(rename = "localrelay")]
91    pub local_relay: bool,
92    #[serde(rename = "timeoffset")]
93    pub time_offset: isize,
94    pub connections: usize,
95    #[serde(rename = "networkactive")]
96    pub network_active: bool,
97    pub networks: Vec<GetNetworkInfoResultNetwork>,
98    #[serde(rename = "relayfee", with = "bitcoin::util::amount::serde::as_btc")]
99    pub relay_fee: Amount,
100    #[serde(rename = "incrementalfee", with = "bitcoin::util::amount::serde::as_btc")]
101    pub incremental_fee: Amount,
102    #[serde(rename = "localaddresses")]
103    pub local_addresses: Vec<GetNetworkInfoResultAddress>,
104    pub warnings: String,
105}
106
107#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
108#[serde(rename_all = "camelCase")]
109pub struct AddMultiSigAddressResult {
110    pub address: Address,
111    pub redeem_script: Script,
112}
113
114#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
115pub struct LoadWalletResult {
116    pub name: String,
117    pub warning: Option<String>,
118}
119
120#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
121pub struct GetWalletInfoResult {
122    #[serde(rename = "walletname")]
123    pub wallet_name: String,
124    #[serde(rename = "walletversion")]
125    pub wallet_version: u32,
126    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
127    pub balance: Amount,
128    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
129    pub unconfirmed_balance: Amount,
130    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
131    pub immature_balance: Amount,
132    #[serde(rename = "txcount")]
133    pub tx_count: usize,
134    #[serde(rename = "keypoololdest")]
135    pub keypool_oldest: usize,
136    #[serde(rename = "keypoolsize")]
137    pub keypool_size: usize,
138    #[serde(rename = "keypoolsize_hd_internal")]
139    pub keypool_size_hd_internal: usize,
140    pub unlocked_until: Option<u64>,
141    #[serde(rename = "paytxfee", with = "bitcoin::util::amount::serde::as_btc")]
142    pub pay_tx_fee: Amount,
143    #[serde(rename = "hdseedid")]
144    pub hd_seed_id: Option<bitcoin::XpubIdentifier>,
145    pub private_keys_enabled: bool,
146    pub avoid_reuse: Option<bool>,
147    pub scanning: Option<ScanningDetails>,
148}
149
150#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
151#[serde(untagged)]
152pub enum ScanningDetails {
153    Scanning {
154        duration: usize,
155        progress: f32,
156    },
157    /// The bool in this field will always be false.
158    NotScanning(bool),
159}
160
161impl Eq for ScanningDetails {}
162
163#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
164#[serde(rename_all = "camelCase")]
165pub struct GetBlockResult {
166    pub hash: bitcoin::BlockHash,
167    pub confirmations: u32,
168    pub size: usize,
169    pub strippedsize: Option<usize>,
170    pub weight: usize,
171    pub height: usize,
172    pub version: i32,
173    #[serde(default, with = "serde_hex::opt")]
174    pub version_hex: Option<Vec<u8>>,
175    pub merkleroot: bitcoin::TxMerkleNode,
176    pub tx: Vec<bitcoin::Txid>,
177    pub time: usize,
178    pub mediantime: Option<usize>,
179    pub nonce: u32,
180    pub bits: String,
181    pub difficulty: f64,
182    #[serde(with = "serde_hex")]
183    pub chainwork: Vec<u8>,
184    pub n_tx: usize,
185    pub previousblockhash: Option<bitcoin::BlockHash>,
186    pub nextblockhash: Option<bitcoin::BlockHash>,
187}
188
189#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
190#[serde(rename_all = "camelCase")]
191pub struct GetBlockHeaderResult {
192    pub hash: bitcoin::BlockHash,
193    pub confirmations: u32,
194    pub height: usize,
195    pub version: i32,
196    #[serde(default, with = "serde_hex::opt")]
197    pub version_hex: Option<Vec<u8>>,
198    #[serde(rename = "merkleroot")]
199    pub merkle_root: bitcoin::TxMerkleNode,
200    pub time: usize,
201    #[serde(rename = "mediantime")]
202    pub median_time: Option<usize>,
203    pub nonce: u32,
204    pub bits: String,
205    pub difficulty: f64,
206    #[serde(with = "serde_hex")]
207    pub chainwork: Vec<u8>,
208    pub n_tx: usize,
209    #[serde(rename = "previousblockhash")]
210    pub previous_block_hash: Option<bitcoin::BlockHash>,
211    #[serde(rename = "nextblockhash")]
212    pub next_block_hash: Option<bitcoin::BlockHash>,
213}
214
215#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
216#[serde(rename_all = "camelCase")]
217pub struct GetMiningInfoResult {
218    pub blocks: u32,
219    #[serde(rename = "currentblockweight")]
220    pub current_block_weight: Option<u64>,
221    #[serde(rename = "currentblocktx")]
222    pub current_block_tx: Option<usize>,
223    pub difficulty: f64,
224    #[serde(rename = "networkhashps")]
225    pub network_hash_ps: f64,
226    #[serde(rename = "pooledtx")]
227    pub pooled_tx: usize,
228    pub chain: String,
229    pub warnings: String,
230}
231
232#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
233#[serde(rename_all = "camelCase")]
234pub struct GetRawTransactionResultVinScriptSig {
235    pub asm: String,
236    #[serde(with = "serde_hex")]
237    pub hex: Vec<u8>,
238}
239
240impl GetRawTransactionResultVinScriptSig {
241    pub fn script(&self) -> Result<Script, encode::Error> {
242        Ok(Script::from(self.hex.clone()))
243    }
244}
245
246#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
247#[serde(rename_all = "camelCase")]
248pub struct GetRawTransactionResultVin {
249    pub sequence: u32,
250    /// The raw scriptSig in case of a coinbase tx.
251    #[serde(default, with = "serde_hex::opt")]
252    pub coinbase: Option<Vec<u8>>,
253    /// Not provided for coinbase txs.
254    pub txid: Option<bitcoin::Txid>,
255    /// Not provided for coinbase txs.
256    pub vout: Option<u32>,
257    /// The scriptSig in case of a non-coinbase tx.
258    pub script_sig: Option<GetRawTransactionResultVinScriptSig>,
259    /// Not provided for coinbase txs.
260    #[serde(default, deserialize_with = "deserialize_hex_array_opt")]
261    pub txinwitness: Option<Vec<Vec<u8>>>,
262}
263
264impl GetRawTransactionResultVin {
265    /// Whether this input is from a coinbase tx.
266    /// The [txid], [vout] and [script_sig] fields are not provided
267    /// for coinbase transactions.
268    pub fn is_coinbase(&self) -> bool {
269        self.coinbase.is_some()
270    }
271}
272
273#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
274#[serde(rename_all = "camelCase")]
275pub struct GetRawTransactionResultVoutScriptPubKey {
276    pub asm: String,
277    #[serde(with = "serde_hex")]
278    pub hex: Vec<u8>,
279    pub req_sigs: Option<usize>,
280    #[serde(rename = "type")]
281    pub type_: Option<ScriptPubkeyType>,
282    pub addresses: Option<Vec<Address>>,
283}
284
285impl GetRawTransactionResultVoutScriptPubKey {
286    pub fn script(&self) -> Result<Script, encode::Error> {
287        Ok(Script::from(self.hex.clone()))
288    }
289}
290
291#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
292#[serde(rename_all = "camelCase")]
293pub struct GetRawTransactionResultVout {
294    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
295    pub value: Amount,
296    pub n: u32,
297    pub script_pub_key: GetRawTransactionResultVoutScriptPubKey,
298}
299
300#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
301#[serde(rename_all = "camelCase")]
302pub struct GetRawTransactionResult {
303    #[serde(rename = "in_active_chain")]
304    pub in_active_chain: Option<bool>,
305    #[serde(with = "serde_hex")]
306    pub hex: Vec<u8>,
307    pub txid: bitcoin::Txid,
308    pub hash: bitcoin::Wtxid,
309    pub size: usize,
310    pub vsize: usize,
311    pub version: u32,
312    pub locktime: u32,
313    pub vin: Vec<GetRawTransactionResultVin>,
314    pub vout: Vec<GetRawTransactionResultVout>,
315    pub blockhash: Option<bitcoin::BlockHash>,
316    pub confirmations: Option<u32>,
317    pub time: Option<usize>,
318    pub blocktime: Option<usize>,
319}
320
321#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
322pub struct GetBlockFilterResult {
323    pub header: bitcoin::FilterHash,
324    #[serde(with = "serde_hex")]
325    pub filter: Vec<u8>,
326}
327
328impl GetBlockFilterResult {
329    /// Get the filter.
330    /// Note that this copies the underlying filter data. To prevent this,
331    /// use [into_filter] instead.
332    pub fn to_filter(&self) -> bip158::BlockFilter {
333        bip158::BlockFilter::new(&self.filter)
334    }
335
336    /// Convert the result in the filter type.
337    pub fn into_filter(self) -> bip158::BlockFilter {
338        bip158::BlockFilter {
339            content: self.filter,
340        }
341    }
342}
343
344impl GetRawTransactionResult {
345    /// Whether this tx is a coinbase tx.
346    pub fn is_coinbase(&self) -> bool {
347        self.vin.len() == 1 && self.vin[0].is_coinbase()
348    }
349
350    pub fn transaction(&self) -> Result<Transaction, encode::Error> {
351        Ok(encode::deserialize(&self.hex)?)
352    }
353}
354
355/// Enum to represent the BIP125 replaceable status for a transaction.
356#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
357#[serde(rename_all = "lowercase")]
358pub enum Bip125Replaceable {
359    Yes,
360    No,
361    Unknown,
362}
363
364/// Enum to represent the category of a transaction.
365#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
366#[serde(rename_all = "lowercase")]
367pub enum GetTransactionResultDetailCategory {
368    Send,
369    Receive,
370    Generate,
371    Immature,
372    Orphan,
373}
374
375#[derive(Clone, PartialEq, Eq, Debug, Deserialize)]
376pub struct GetTransactionResultDetail {
377    pub address: Option<Address>,
378    pub category: GetTransactionResultDetailCategory,
379    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
380    pub amount: SignedAmount,
381    pub label: Option<String>,
382    pub vout: u32,
383    #[serde(default, with = "bitcoin::util::amount::serde::as_btc::opt")]
384    pub fee: Option<SignedAmount>,
385    pub abandoned: Option<bool>,
386}
387
388#[derive(Clone, PartialEq, Eq, Debug, Deserialize)]
389pub struct WalletTxInfo {
390    pub confirmations: i32,
391    pub blockhash: Option<bitcoin::BlockHash>,
392    pub blockindex: Option<usize>,
393    pub blocktime: Option<u64>,
394    pub blockheight: Option<u32>,
395    pub txid: bitcoin::Txid,
396    pub time: u64,
397    pub timereceived: u64,
398    #[serde(rename = "bip125-replaceable")]
399    pub bip125_replaceable: Bip125Replaceable,
400}
401
402#[derive(Clone, PartialEq, Eq, Debug, Deserialize)]
403pub struct GetTransactionResult {
404    #[serde(flatten)]
405    pub info: WalletTxInfo,
406    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
407    pub amount: SignedAmount,
408    #[serde(default, with = "bitcoin::util::amount::serde::as_btc::opt")]
409    pub fee: Option<SignedAmount>,
410    pub details: Vec<GetTransactionResultDetail>,
411    #[serde(with = "serde_hex")]
412    pub hex: Vec<u8>,
413}
414
415impl GetTransactionResult {
416    pub fn transaction(&self) -> Result<Transaction, encode::Error> {
417        Ok(encode::deserialize(&self.hex)?)
418    }
419}
420
421#[derive(Clone, PartialEq, Eq, Debug, Deserialize)]
422pub struct ListTransactionResult {
423    #[serde(flatten)]
424    pub info: WalletTxInfo,
425    #[serde(flatten)]
426    pub detail: GetTransactionResultDetail,
427
428    pub trusted: Option<bool>,
429    pub comment: Option<String>,
430}
431
432#[derive(Clone, PartialEq, Eq, Debug, Deserialize)]
433pub struct ListSinceBlockResult {
434    pub transactions: Vec<ListTransactionResult>,
435    #[serde(default)]
436    pub removed: Vec<ListTransactionResult>,
437    pub lastblock: bitcoin::BlockHash,
438}
439
440#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
441#[serde(rename_all = "camelCase")]
442pub struct GetTxOutResult {
443    pub bestblock: bitcoin::BlockHash,
444    pub confirmations: u32,
445    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
446    pub value: Amount,
447    pub script_pub_key: GetRawTransactionResultVoutScriptPubKey,
448    pub coinbase: bool,
449}
450
451#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Default)]
452#[serde(rename_all = "camelCase")]
453pub struct ListUnspentQueryOptions {
454    #[serde(
455        rename = "minimumAmount",
456        with = "bitcoin::util::amount::serde::as_btc::opt",
457        skip_serializing_if = "Option::is_none"
458    )]
459    pub minimum_amount: Option<Amount>,
460    #[serde(
461        rename = "maximumAmount",
462        with = "bitcoin::util::amount::serde::as_btc::opt",
463        skip_serializing_if = "Option::is_none"
464    )]
465    pub maximum_amount: Option<Amount>,
466    #[serde(rename = "maximumCount", skip_serializing_if = "Option::is_none")]
467    pub maximum_count: Option<usize>,
468    #[serde(
469        rename = "minimumSumAmount",
470        with = "bitcoin::util::amount::serde::as_btc::opt",
471        skip_serializing_if = "Option::is_none"
472    )]
473    pub minimum_sum_amount: Option<Amount>,
474}
475
476#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
477#[serde(rename_all = "camelCase")]
478pub struct ListUnspentResultEntry {
479    pub txid: bitcoin::Txid,
480    pub vout: u32,
481    pub address: Option<Address>,
482    pub label: Option<String>,
483    pub redeem_script: Option<Script>,
484    pub witness_script: Option<Script>,
485    pub script_pub_key: Script,
486    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
487    pub amount: Amount,
488    pub confirmations: u32,
489    pub spendable: bool,
490    pub solvable: bool,
491    #[serde(rename = "desc")]
492    pub descriptor: Option<String>,
493    pub safe: bool,
494}
495
496#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
497#[serde(rename_all = "camelCase")]
498pub struct ListReceivedByAddressResult {
499    #[serde(default, rename = "involvesWatchonly")]
500    pub involved_watch_only: bool,
501    pub address: Address,
502    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
503    pub amount: Amount,
504    pub confirmations: u32,
505    pub label: String,
506    pub txids: Vec<bitcoin::Txid>,
507}
508
509#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
510#[serde(rename_all = "camelCase")]
511pub struct SignRawTransactionResultError {
512    pub txid: bitcoin::Txid,
513    pub vout: u32,
514    pub script_sig: Script,
515    pub sequence: u32,
516    pub error: String,
517}
518
519#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
520#[serde(rename_all = "camelCase")]
521pub struct SignRawTransactionResult {
522    #[serde(with = "serde_hex")]
523    pub hex: Vec<u8>,
524    pub complete: bool,
525    pub errors: Option<Vec<SignRawTransactionResultError>>,
526}
527
528impl SignRawTransactionResult {
529    pub fn transaction(&self) -> Result<Transaction, encode::Error> {
530        Ok(encode::deserialize(&self.hex)?)
531    }
532}
533
534#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
535pub struct TestMempoolAcceptResult {
536    pub txid: bitcoin::Txid,
537    pub allowed: bool,
538    #[serde(rename = "reject-reason")]
539    pub reject_reason: Option<String>,
540}
541
542#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
543#[serde(rename_all = "snake_case")]
544pub enum Bip9SoftforkStatus {
545    Defined,
546    Started,
547    LockedIn,
548    Active,
549    Failed,
550}
551
552#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
553pub struct Bip9SoftforkStatistics {
554    pub period: u32,
555    pub threshold: u32,
556    pub elapsed: u32,
557    pub count: u32,
558    pub possible: bool,
559}
560
561#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
562pub struct Bip9SoftforkInfo {
563    pub status: Bip9SoftforkStatus,
564    pub bit: Option<u8>,
565    // Can be -1 for 0.18.x inactive ones.
566    pub start_time: i64,
567    pub timeout: u64,
568    pub since: u32,
569    pub statistics: Option<Bip9SoftforkStatistics>,
570}
571
572#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
573#[serde(rename_all = "lowercase")]
574pub enum SoftforkType {
575    Buried,
576    Bip9,
577}
578
579/// Status of a softfork
580#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
581pub struct Softfork {
582    #[serde(rename = "type")]
583    pub type_: SoftforkType,
584    pub bip9: Option<Bip9SoftforkInfo>,
585    pub height: Option<u32>,
586    pub active: bool,
587}
588
589#[allow(non_camel_case_types)]
590#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
591#[serde(rename_all = "lowercase")]
592pub enum ScriptPubkeyType {
593    Nonstandard,
594    Pubkey,
595    PubkeyHash,
596    ScriptHash,
597    MultiSig,
598    NullData,
599    Witness_v0_KeyHash,
600    Witness_v0_ScriptHash,
601    Witness_Unknown,
602}
603
604#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
605pub struct GetAddressInfoResultEmbedded {
606    pub address: Address,
607    #[serde(rename = "scriptPubKey")]
608    pub script_pub_key: Script,
609    #[serde(rename = "is_script")]
610    pub is_script: Option<bool>,
611    #[serde(rename = "is_witness")]
612    pub is_witness: Option<bool>,
613    pub witness_version: Option<u32>,
614    #[serde(with = "serde_hex")]
615    pub witness_program: Vec<u8>,
616    pub script: Option<ScriptPubkeyType>,
617    /// The redeemscript for the p2sh address.
618    #[serde(default, with = "serde_hex::opt")]
619    pub hex: Option<Vec<u8>>,
620    pub pubkeys: Option<Vec<PublicKey>>,
621    #[serde(rename = "sigsrequired")]
622    pub n_signatures_required: Option<usize>,
623    pub pubkey: Option<PublicKey>,
624    #[serde(rename = "is_compressed")]
625    pub is_compressed: Option<bool>,
626    pub label: Option<String>,
627    #[serde(rename = "hdkeypath")]
628    pub hd_key_path: Option<bip32::DerivationPath>,
629    #[serde(rename = "hdseedid")]
630    pub hd_seed_id: Option<bitcoin::XpubIdentifier>,
631    #[serde(default)]
632    pub labels: Vec<GetAddressInfoResultLabel>,
633}
634
635#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
636#[serde(rename_all = "lowercase")]
637pub enum GetAddressInfoResultLabelPurpose {
638    Send,
639    Receive,
640}
641
642#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
643#[serde(untagged)]
644pub enum GetAddressInfoResultLabel {
645    Simple(String),
646    WithPurpose {
647        name: String,
648        purpose: GetAddressInfoResultLabelPurpose,
649    },
650}
651
652#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
653pub struct GetAddressInfoResult {
654    pub address: Address,
655    #[serde(rename = "scriptPubKey")]
656    pub script_pub_key: Script,
657    #[serde(rename = "ismine")]
658    pub is_mine: Option<bool>,
659    #[serde(rename = "iswatchonly")]
660    pub is_watchonly: Option<bool>,
661    #[serde(rename = "isscript")]
662    pub is_script: Option<bool>,
663    #[serde(rename = "iswitness")]
664    pub is_witness: Option<bool>,
665    pub witness_version: Option<u32>,
666    #[serde(default, with = "serde_hex::opt")]
667    pub witness_program: Option<Vec<u8>>,
668    pub script: Option<ScriptPubkeyType>,
669    /// The redeemscript for the p2sh address.
670    #[serde(default, with = "serde_hex::opt")]
671    pub hex: Option<Vec<u8>>,
672    pub pubkeys: Option<Vec<PublicKey>>,
673    #[serde(rename = "sigsrequired")]
674    pub n_signatures_required: Option<usize>,
675    pub pubkey: Option<PublicKey>,
676    /// Information about the address embedded in P2SH or P2WSH, if relevant and known.
677    pub embedded: Option<GetAddressInfoResultEmbedded>,
678    #[serde(rename = "is_compressed")]
679    pub is_compressed: Option<bool>,
680    pub timestamp: Option<u64>,
681    #[serde(rename = "hdkeypath")]
682    pub hd_key_path: Option<bip32::DerivationPath>,
683    #[serde(rename = "hdseedid")]
684    pub hd_seed_id: Option<bitcoin::XpubIdentifier>,
685    pub labels: Vec<GetAddressInfoResultLabel>,
686    /// Deprecated in v0.20.0. See `labels` field instead.
687    #[deprecated(note = "since Core v0.20.0")]
688    pub label: Option<String>,
689}
690
691/// Models the result of "getblockchaininfo"
692#[derive(Clone, Debug, Deserialize, Serialize)]
693pub struct GetBlockchainInfoResult {
694    /// Current network name as defined in BIP70 (main, test, regtest)
695    pub chain: String,
696    /// The current number of blocks processed in the server
697    pub blocks: u64,
698    /// The current number of headers we have validated
699    pub headers: u64,
700    /// The hash of the currently best block
701    #[serde(rename = "bestblockhash")]
702    pub best_block_hash: bitcoin::BlockHash,
703    /// The current difficulty
704    pub difficulty: f64,
705    /// Median time for the current best block
706    #[serde(rename = "mediantime")]
707    pub median_time: u64,
708    /// Estimate of verification progress [0..1]
709    #[serde(rename = "verificationprogress")]
710    pub verification_progress: f64,
711    /// Estimate of whether this node is in Initial Block Download mode
712    #[serde(rename = "initialblockdownload")]
713    pub initial_block_download: bool,
714    /// Total amount of work in active chain, in hexadecimal
715    #[serde(rename = "chainwork", with = "serde_hex")]
716    pub chain_work: Vec<u8>,
717    /// The estimated size of the block and undo files on disk
718    pub size_on_disk: u64,
719    /// If the blocks are subject to pruning
720    pub pruned: bool,
721    /// Lowest-height complete block stored (only present if pruning is enabled)
722    #[serde(rename = "pruneheight")]
723    pub prune_height: Option<u64>,
724    /// Whether automatic pruning is enabled (only present if pruning is enabled)
725    pub automatic_pruning: Option<bool>,
726    /// The target size used by pruning (only present if automatic pruning is enabled)
727    pub prune_target_size: Option<u64>,
728    /// Status of softforks in progress
729    #[serde(default)]
730    pub softforks: HashMap<String, Softfork>,
731    /// Any network and blockchain warnings.
732    pub warnings: String,
733}
734
735#[derive(Clone, PartialEq, Eq, Debug)]
736pub enum ImportMultiRequestScriptPubkey<'a> {
737    Address(&'a Address),
738    Script(&'a Script),
739}
740
741#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
742pub struct GetMempoolEntryResult {
743    /// Virtual transaction size as defined in BIP 141. This is different from actual serialized
744    /// size for witness transactions as witness data is discounted.
745    #[serde(alias = "size")]
746    pub vsize: u64,
747    /// Transaction weight as defined in BIP 141. Added in Core v0.19.0.
748    pub weight: Option<u64>,
749    /// Local time transaction entered pool in seconds since 1 Jan 1970 GMT
750    pub time: u64,
751    /// Block height when transaction entered pool
752    pub height: u64,
753    /// Number of in-mempool descendant transactions (including this one)
754    #[serde(rename = "descendantcount")]
755    pub descendant_count: u64,
756    /// Virtual transaction size of in-mempool descendants (including this one)
757    #[serde(rename = "descendantsize")]
758    pub descendant_size: u64,
759    /// Number of in-mempool ancestor transactions (including this one)
760    #[serde(rename = "ancestorcount")]
761    pub ancestor_count: u64,
762    /// Virtual transaction size of in-mempool ancestors (including this one)
763    #[serde(rename = "ancestorsize")]
764    pub ancestor_size: u64,
765    /// Hash of serialized transaction, including witness data
766    pub wtxid: bitcoin::Txid,
767    /// Fee information
768    pub fees: GetMempoolEntryResultFees,
769    /// Unconfirmed transactions used as inputs for this transaction
770    pub depends: Vec<bitcoin::Txid>,
771    /// Unconfirmed transactions spending outputs from this transaction
772    #[serde(rename = "spentby")]
773    pub spent_by: Vec<bitcoin::Txid>,
774    /// Whether this transaction could be replaced due to BIP125 (replace-by-fee)
775    #[serde(rename = "bip125-replaceable")]
776    pub bip125_replaceable: bool,
777}
778
779#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
780pub struct GetMempoolEntryResultFees {
781    /// Transaction fee in BTC
782    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
783    pub base: Amount,
784    /// Transaction fee with fee deltas used for mining priority in BTC
785    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
786    pub modified: Amount,
787    /// Modified fees (see above) of in-mempool ancestors (including this one) in BTC
788    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
789    pub ancestor: Amount,
790    /// Modified fees (see above) of in-mempool descendants (including this one) in BTC
791    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
792    pub descendant: Amount,
793}
794
795impl<'a> serde::Serialize for ImportMultiRequestScriptPubkey<'a> {
796    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
797    where
798        S: serde::Serializer,
799    {
800        match *self {
801            ImportMultiRequestScriptPubkey::Address(ref addr) => {
802                #[derive(Serialize)]
803                struct Tmp<'a> {
804                    pub address: &'a Address,
805                };
806                serde::Serialize::serialize(
807                    &Tmp {
808                        address: addr,
809                    },
810                    serializer,
811                )
812            }
813            ImportMultiRequestScriptPubkey::Script(script) => {
814                serializer.serialize_str(&script.as_bytes().to_hex())
815            }
816        }
817    }
818}
819
820/// A import request for importmulti.
821///
822/// Note: unlike in bitcoind, `timestamp` defaults to 0.
823#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize)]
824pub struct ImportMultiRequest<'a> {
825    pub timestamp: ImportMultiRescanSince,
826    /// If using descriptor, do not also provide address/scriptPubKey, scripts, or pubkeys.
827    #[serde(rename = "desc", skip_serializing_if = "Option::is_none")]
828    pub descriptor: Option<&'a str>,
829    #[serde(rename = "scriptPubKey", skip_serializing_if = "Option::is_none")]
830    pub script_pubkey: Option<ImportMultiRequestScriptPubkey<'a>>,
831    #[serde(rename = "redeemscript", skip_serializing_if = "Option::is_none")]
832    pub redeem_script: Option<&'a Script>,
833    #[serde(rename = "witnessscript", skip_serializing_if = "Option::is_none")]
834    pub witness_script: Option<&'a Script>,
835    #[serde(skip_serializing_if = "<[_]>::is_empty")]
836    pub pubkeys: &'a [PublicKey],
837    #[serde(skip_serializing_if = "<[_]>::is_empty")]
838    pub keys: &'a [PrivateKey],
839    #[serde(skip_serializing_if = "Option::is_none")]
840    pub range: Option<(usize, usize)>,
841    #[serde(skip_serializing_if = "Option::is_none")]
842    pub internal: Option<bool>,
843    #[serde(skip_serializing_if = "Option::is_none")]
844    pub watchonly: Option<bool>,
845    #[serde(skip_serializing_if = "Option::is_none")]
846    pub label: Option<&'a str>,
847    #[serde(skip_serializing_if = "Option::is_none")]
848    pub keypool: Option<bool>,
849}
850
851#[derive(Clone, PartialEq, Eq, Debug, Default, Deserialize, Serialize)]
852pub struct ImportMultiOptions {
853    #[serde(skip_serializing_if = "Option::is_none")]
854    pub rescan: Option<bool>,
855}
856
857#[derive(Clone, PartialEq, Eq, Copy, Debug)]
858pub enum ImportMultiRescanSince {
859    Now,
860    Timestamp(u64),
861}
862
863impl serde::Serialize for ImportMultiRescanSince {
864    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
865    where
866        S: serde::Serializer,
867    {
868        match *self {
869            ImportMultiRescanSince::Now => serializer.serialize_str("now"),
870            ImportMultiRescanSince::Timestamp(timestamp) => serializer.serialize_u64(timestamp),
871        }
872    }
873}
874
875impl Default for ImportMultiRescanSince {
876    fn default() -> Self {
877        ImportMultiRescanSince::Timestamp(0)
878    }
879}
880
881#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
882pub struct ImportMultiResultError {
883    pub code: i64,
884    pub message: String,
885}
886
887#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
888pub struct ImportMultiResult {
889    pub success: bool,
890    #[serde(default)]
891    pub warnings: Vec<String>,
892    pub error: Option<ImportMultiResultError>,
893}
894
895/// Progress toward rejecting pre-softfork blocks
896#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
897pub struct RejectStatus {
898    /// `true` if threshold reached
899    pub status: bool,
900}
901
902/// Models the result of "getpeerinfo"
903#[derive(Clone, Debug, Deserialize, Serialize)]
904pub struct GetPeerInfoResult {
905    /// Peer index
906    pub id: u64,
907    /// The IP address and port of the peer
908    // TODO: use a type for addr
909    pub addr: String,
910    /// Bind address of the connection to the peer
911    // TODO: use a type for addrbind
912    pub addrbind: String,
913    /// Local address as reported by the peer
914    // TODO: use a type for addrlocal
915    pub addrlocal: Option<String>,
916    /// The services offered
917    // TODO: use a type for services
918    pub services: String,
919    /// Whether peer has asked us to relay transactions to it
920    pub relaytxes: bool,
921    /// The time in seconds since epoch (Jan 1 1970 GMT) of the last send
922    pub lastsend: u64,
923    /// The time in seconds since epoch (Jan 1 1970 GMT) of the last receive
924    pub lastrecv: u64,
925    /// The total bytes sent
926    pub bytessent: u64,
927    /// The total bytes received
928    pub bytesrecv: u64,
929    /// The connection time in seconds since epoch (Jan 1 1970 GMT)
930    pub conntime: u64,
931    /// The time offset in seconds
932    pub timeoffset: i64,
933    /// ping time (if available)
934    pub pingtime: Option<f64>,
935    /// minimum observed ping time (if any at all)
936    pub minping: Option<f64>,
937    /// ping wait (if non-zero)
938    pub pingwait: Option<f64>,
939    /// The peer version, such as 70001
940    pub version: u64,
941    /// The string version
942    pub subver: String,
943    /// Inbound (true) or Outbound (false)
944    pub inbound: bool,
945    /// Whether connection was due to `addnode`/`-connect` or if it was an
946    /// automatic/inbound connection
947    pub addnode: bool,
948    /// The starting height (block) of the peer
949    pub startingheight: i64,
950    /// The ban score
951    pub banscore: i64,
952    /// The last header we have in common with this peer
953    pub synced_headers: i64,
954    /// The last block we have in common with this peer
955    pub synced_blocks: i64,
956    /// The heights of blocks we're currently asking from this peer
957    pub inflight: Vec<u64>,
958    /// Whether the peer is whitelisted
959    pub whitelisted: bool,
960    #[serde(rename = "minfeefilter", default, with = "bitcoin::util::amount::serde::as_btc::opt")]
961    pub min_fee_filter: Option<Amount>,
962    /// The total bytes sent aggregated by message type
963    pub bytessent_per_msg: HashMap<String, u64>,
964    /// The total bytes received aggregated by message type
965    pub bytesrecv_per_msg: HashMap<String, u64>,
966}
967
968/// Models the result of "estimatesmartfee"
969#[derive(Clone, Debug, Deserialize, Serialize)]
970pub struct EstimateSmartFeeResult {
971    /// Estimate fee rate in BTC/kB.
972    #[serde(
973        default,
974        rename = "feerate",
975        skip_serializing_if = "Option::is_none",
976        with = "bitcoin::util::amount::serde::as_btc::opt"
977    )]
978    pub fee_rate: Option<Amount>,
979    /// Errors encountered during processing.
980    pub errors: Option<Vec<String>>,
981    /// Block number where estimate was found.
982    pub blocks: i64,
983}
984
985/// Models the result of "waitfornewblock", and "waitforblock"
986#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
987pub struct BlockRef {
988    pub hash: bitcoin::BlockHash,
989    pub height: u64,
990}
991
992/// Models the result of "getdescriptorinfo"
993#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
994pub struct GetDescriptorInfoResult {
995    pub descriptor: String,
996    pub checksum: String,
997    #[serde(rename = "isrange")]
998    pub is_range: bool,
999    #[serde(rename = "issolvable")]
1000    pub is_solvable: bool,
1001    #[serde(rename = "hasprivatekeys")]
1002    pub has_private_keys: bool,
1003}
1004
1005/// Models the result of "walletcreatefundedpsbt"
1006#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1007pub struct WalletCreateFundedPsbtResult {
1008    pub psbt: String,
1009    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
1010    pub fee: Amount,
1011    #[serde(rename = "changepos")]
1012    pub change_position: i32,
1013}
1014
1015/// Models the request for "walletcreatefundedpsbt"
1016#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Default)]
1017pub struct WalletCreateFundedPsbtOptions {
1018    #[serde(rename = "changeAddress", skip_serializing_if = "Option::is_none")]
1019    pub change_address: Option<Address>,
1020    #[serde(rename = "changePosition", skip_serializing_if = "Option::is_none")]
1021    pub change_position: Option<u16>,
1022    #[serde(skip_serializing_if = "Option::is_none")]
1023    pub change_type: Option<AddressType>,
1024    #[serde(rename = "includeWatching", skip_serializing_if = "Option::is_none")]
1025    pub include_watching: Option<bool>,
1026    #[serde(rename = "lockUnspents", skip_serializing_if = "Option::is_none")]
1027    pub lock_unspent: Option<bool>,
1028    #[serde(
1029        rename = "feeRate",
1030        skip_serializing_if = "Option::is_none",
1031        with = "bitcoin::util::amount::serde::as_btc::opt"
1032    )]
1033    pub fee_rate: Option<Amount>,
1034    #[serde(rename = "subtractFeeFromOutputs", skip_serializing_if = "Vec::is_empty")]
1035    pub subtract_fee_from_outputs: Vec<u16>,
1036    #[serde(skip_serializing_if = "Option::is_none")]
1037    pub replaceable: Option<bool>,
1038    #[serde(skip_serializing_if = "Option::is_none")]
1039    pub conf_target: Option<u16>,
1040    #[serde(skip_serializing_if = "Option::is_none")]
1041    pub estimate_mode: Option<EstimateMode>,
1042}
1043
1044/// Models the result of "finalizepsbt"
1045#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1046pub struct FinalizePsbtResult {
1047    pub psbt: Option<String>,
1048    #[serde(default, with = "serde_hex::opt")]
1049    pub hex: Option<Vec<u8>>,
1050    pub complete: bool,
1051}
1052
1053impl FinalizePsbtResult {
1054    pub fn transaction(&self) -> Option<Result<Transaction, encode::Error>> {
1055        self.hex.as_ref().map(|h| encode::deserialize(h))
1056    }
1057}
1058
1059// Custom types for input arguments.
1060
1061#[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, PartialEq, Hash)]
1062#[serde(rename_all = "UPPERCASE")]
1063pub enum EstimateMode {
1064    Unset,
1065    Economical,
1066    Conservative,
1067}
1068
1069/// A wrapper around bitcoin::SigHashType that will be serialized
1070/// according to what the RPC expects.
1071pub struct SigHashType(bitcoin::SigHashType);
1072
1073impl From<bitcoin::SigHashType> for SigHashType {
1074    fn from(sht: bitcoin::SigHashType) -> SigHashType {
1075        SigHashType(sht)
1076    }
1077}
1078
1079impl serde::Serialize for SigHashType {
1080    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1081    where
1082        S: serde::Serializer,
1083    {
1084        serializer.serialize_str(match self.0 {
1085            bitcoin::SigHashType::All => "ALL",
1086            bitcoin::SigHashType::None => "NONE",
1087            bitcoin::SigHashType::Single => "SINGLE",
1088            bitcoin::SigHashType::AllPlusAnyoneCanPay => "ALL|ANYONECANPAY",
1089            bitcoin::SigHashType::NonePlusAnyoneCanPay => "NONE|ANYONECANPAY",
1090            bitcoin::SigHashType::SinglePlusAnyoneCanPay => "SINGLE|ANYONECANPAY",
1091        })
1092    }
1093}
1094
1095// Used for createrawtransaction argument.
1096#[derive(Serialize, Clone, PartialEq, Eq, Debug)]
1097#[serde(rename_all = "camelCase")]
1098pub struct CreateRawTransactionInput {
1099    pub txid: bitcoin::Txid,
1100    pub vout: u32,
1101    #[serde(skip_serializing_if = "Option::is_none")]
1102    pub sequence: Option<u32>,
1103}
1104
1105#[derive(Serialize, Clone, PartialEq, Eq, Debug, Default)]
1106#[serde(rename_all = "camelCase")]
1107pub struct FundRawTransactionOptions {
1108    #[serde(skip_serializing_if = "Option::is_none")]
1109    pub change_address: Option<Address>,
1110    #[serde(skip_serializing_if = "Option::is_none")]
1111    pub change_position: Option<u32>,
1112    #[serde(rename = "change_type", skip_serializing_if = "Option::is_none")]
1113    pub change_type: Option<AddressType>,
1114    #[serde(skip_serializing_if = "Option::is_none")]
1115    pub include_watching: Option<bool>,
1116    #[serde(skip_serializing_if = "Option::is_none")]
1117    pub lock_unspents: Option<bool>,
1118    #[serde(
1119        with = "bitcoin::util::amount::serde::as_btc::opt",
1120        skip_serializing_if = "Option::is_none"
1121    )]
1122    pub fee_rate: Option<Amount>,
1123    #[serde(skip_serializing_if = "Option::is_none")]
1124    pub subtract_fee_from_outputs: Option<Vec<u32>>,
1125    #[serde(skip_serializing_if = "Option::is_none")]
1126    pub replaceable: Option<bool>,
1127    #[serde(rename = "conf_target", skip_serializing_if = "Option::is_none")]
1128    pub conf_target: Option<u32>,
1129    #[serde(rename = "estimate_mode", skip_serializing_if = "Option::is_none")]
1130    pub estimate_mode: Option<EstimateMode>,
1131}
1132
1133#[derive(Deserialize, Clone, PartialEq, Eq, Debug)]
1134#[serde(rename_all = "camelCase")]
1135pub struct FundRawTransactionResult {
1136    #[serde(with = "serde_hex")]
1137    pub hex: Vec<u8>,
1138    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
1139    pub fee: Amount,
1140    #[serde(rename = "changepos")]
1141    pub change_position: i32,
1142}
1143
1144#[derive(Deserialize, Clone, PartialEq, Eq, Debug)]
1145pub struct GetBalancesResultEntry {
1146    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
1147    pub trusted: Amount,
1148    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
1149    pub untrusted_pending: Amount,
1150    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
1151    pub immature: Amount,
1152}
1153
1154#[derive(Deserialize, Clone, PartialEq, Eq, Debug)]
1155#[serde(rename_all = "camelCase")]
1156pub struct GetBalancesResult {
1157    pub mine: GetBalancesResultEntry,
1158    pub watchonly: Option<GetBalancesResultEntry>,
1159}
1160
1161impl FundRawTransactionResult {
1162    pub fn transaction(&self) -> Result<Transaction, encode::Error> {
1163        encode::deserialize(&self.hex)
1164    }
1165}
1166
1167// Used for signrawtransaction argument.
1168#[derive(Serialize, Clone, PartialEq, Debug)]
1169#[serde(rename_all = "camelCase")]
1170pub struct SignRawTransactionInput {
1171    pub txid: bitcoin::Txid,
1172    pub vout: u32,
1173    pub script_pub_key: Script,
1174    #[serde(skip_serializing_if = "Option::is_none")]
1175    pub redeem_script: Option<Script>,
1176    #[serde(
1177        default,
1178        skip_serializing_if = "Option::is_none",
1179        with = "bitcoin::util::amount::serde::as_btc::opt"
1180    )]
1181    pub amount: Option<Amount>,
1182}
1183
1184#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1185pub struct GetTxOutSetInfoResult {
1186    /// The current block height (index)
1187    pub height: u64,
1188    /// The hash of the block at the tip of the chain
1189    #[serde(rename = "bestblock")]
1190    pub best_block: bitcoin::BlockHash,
1191    /// The number of transactions with unspent outputs
1192    pub transactions: u64,
1193    /// The number of unspent transaction outputs
1194    #[serde(rename = "txouts")]
1195    pub tx_outs: u64,
1196    /// A meaningless metric for UTXO set size
1197    pub bogosize: u64,
1198    /// The serialized hash
1199    pub hash_serialized_2: sha256::Hash,
1200    /// The estimated size of the chainstate on disk
1201    pub disk_size: u64,
1202    /// The total amount
1203    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
1204    pub total_amount: Amount,
1205}
1206
1207#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1208pub struct GetNetTotalsResult {
1209    /// Total bytes received
1210    #[serde(rename = "totalbytesrecv")]
1211    pub total_bytes_recv: u64,
1212    /// Total bytes sent
1213    #[serde(rename = "totalbytessent")]
1214    pub total_bytes_sent: u64,
1215    /// Current UNIX time in milliseconds
1216    #[serde(rename = "timemillis")]
1217    pub time_millis: u64,
1218    /// Upload target statistics
1219    #[serde(rename = "uploadtarget")]
1220    pub upload_target: GetNetTotalsResultUploadTarget,
1221}
1222
1223#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1224pub struct GetNetTotalsResultUploadTarget {
1225    /// Length of the measuring timeframe in seconds
1226    #[serde(rename = "timeframe")]
1227    pub time_frame: u64,
1228    /// Target in bytes
1229    pub target: u64,
1230    /// True if target is reached
1231    pub target_reached: bool,
1232    /// True if serving historical blocks
1233    pub serve_historical_blocks: bool,
1234    /// Bytes left in current time cycle
1235    pub bytes_left_in_cycle: u64,
1236    /// Seconds left in current time cycle
1237    pub time_left_in_cycle: u64,
1238}
1239
1240/// Used to represent an address type.
1241#[derive(Copy, Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
1242#[serde(rename_all = "kebab-case")]
1243pub enum AddressType {
1244    Legacy,
1245    P2shSegwit,
1246    Bech32,
1247}
1248
1249/// Used to represent arguments that can either be an address or a public key.
1250#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
1251pub enum PubKeyOrAddress<'a> {
1252    Address(&'a Address),
1253    PubKey(&'a PublicKey),
1254}
1255
1256#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
1257#[serde(untagged)]
1258/// Start a scan of the UTXO set for an [output descriptor](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md).
1259pub enum ScanTxOutRequest {
1260    /// Scan for a single descriptor
1261    Single(String),
1262    /// Scan for a descriptor with xpubs
1263    Extended {
1264        /// Descriptor
1265        desc: String,
1266        /// Range of the xpub derivations to scan
1267        range: (u64, u64),
1268    },
1269}
1270
1271#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
1272pub struct ScanTxOutResult {
1273    pub success: Option<bool>,
1274    #[serde(rename = "txouts")]
1275    pub tx_outs: Option<u64>,
1276    pub height: Option<u64>,
1277    #[serde(rename = "bestblock")]
1278    pub best_block_hash: Option<bitcoin::BlockHash>,
1279    pub unspents: Vec<Utxo>,
1280    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
1281    pub total_amount: bitcoin::Amount,
1282}
1283
1284#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
1285#[serde(rename_all = "camelCase")]
1286pub struct Utxo {
1287    pub txid: bitcoin::Txid,
1288    pub vout: u32,
1289    pub script_pub_key: bitcoin::Script,
1290    #[serde(rename = "desc")]
1291    pub descriptor: String,
1292    #[serde(with = "bitcoin::util::amount::serde::as_btc")]
1293    pub amount: bitcoin::Amount,
1294    pub height: u64,
1295}
1296
1297impl<'a> serde::Serialize for PubKeyOrAddress<'a> {
1298    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1299    where
1300        S: serde::Serializer,
1301    {
1302        match *self {
1303            PubKeyOrAddress::Address(a) => serde::Serialize::serialize(a, serializer),
1304            PubKeyOrAddress::PubKey(k) => serde::Serialize::serialize(k, serializer),
1305        }
1306    }
1307}
1308
1309// Custom deserializer functions.
1310
1311/// deserialize_hex_array_opt deserializes a vector of hex-encoded byte arrays.
1312fn deserialize_hex_array_opt<'de, D>(deserializer: D) -> Result<Option<Vec<Vec<u8>>>, D::Error>
1313where
1314    D: serde::Deserializer<'de>,
1315{
1316    //TODO(stevenroose) Revisit when issue is fixed:
1317    // https://github.com/serde-rs/serde/issues/723
1318
1319    let v: Vec<String> = Vec::deserialize(deserializer)?;
1320    let mut res = Vec::new();
1321    for h in v.into_iter() {
1322        res.push(FromHex::from_hex(&h).map_err(D::Error::custom)?);
1323    }
1324    Ok(Some(res))
1325}