bitcoincore_rpc_json/
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#![crate_name = "bitcoincore_rpc_json"]
17#![crate_type = "rlib"]
18
19pub extern crate bitcoin;
20#[allow(unused)]
21#[macro_use] // `macro_use` is needed for v1.24.0 compilation.
22extern crate serde;
23extern crate serde_json;
24
25use std::collections::HashMap;
26
27use bitcoin::address::NetworkUnchecked;
28use bitcoin::block::Version;
29use bitcoin::consensus::encode;
30use bitcoin::hashes::hex::FromHex;
31use bitcoin::hashes::sha256;
32use bitcoin::{
33    bip158, bip32, Address, Amount, PrivateKey, PublicKey, Script, ScriptBuf, SignedAmount,
34    Transaction,
35};
36use serde::de::Error as SerdeError;
37use serde::{Deserialize, Serialize};
38use std::fmt;
39
40//TODO(stevenroose) consider using a Time type
41
42/// A module used for serde serialization of bytes in hexadecimal format.
43///
44/// The module is compatible with the serde attribute.
45pub mod serde_hex {
46    use bitcoin::hashes::hex::FromHex;
47    use bitcoin_private::hex::exts::DisplayHex;
48    use serde::de::Error;
49    use serde::{Deserializer, Serializer};
50
51    pub fn serialize<S: Serializer>(b: &Vec<u8>, s: S) -> Result<S::Ok, S::Error> {
52        s.serialize_str(&b.to_lower_hex_string())
53    }
54
55    pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
56        let hex_str: String = ::serde::Deserialize::deserialize(d)?;
57        Ok(FromHex::from_hex(&hex_str).map_err(D::Error::custom)?)
58    }
59
60    pub mod opt {
61        use bitcoin::hashes::hex::FromHex;
62        use bitcoin_private::hex::exts::DisplayHex;
63        use serde::de::Error;
64        use serde::{Deserializer, Serializer};
65
66        pub fn serialize<S: Serializer>(b: &Option<Vec<u8>>, s: S) -> Result<S::Ok, S::Error> {
67            match *b {
68                None => s.serialize_none(),
69                Some(ref b) => s.serialize_str(&b.to_lower_hex_string()),
70            }
71        }
72
73        pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Option<Vec<u8>>, D::Error> {
74            let hex_str: String = ::serde::Deserialize::deserialize(d)?;
75            Ok(Some(FromHex::from_hex(&hex_str).map_err(D::Error::custom)?))
76        }
77    }
78}
79
80#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
81pub struct GetNetworkInfoResultNetwork {
82    pub name: String,
83    pub limited: bool,
84    pub reachable: bool,
85    pub proxy: String,
86    pub proxy_randomize_credentials: bool,
87}
88
89#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
90pub struct GetNetworkInfoResultAddress {
91    pub address: String,
92    pub port: usize,
93    pub score: usize,
94}
95
96#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
97pub struct GetNetworkInfoResult {
98    pub version: usize,
99    pub subversion: String,
100    #[serde(rename = "protocolversion")]
101    pub protocol_version: usize,
102    #[serde(rename = "localservices")]
103    pub local_services: String,
104    #[serde(rename = "localrelay")]
105    pub local_relay: bool,
106    #[serde(rename = "timeoffset")]
107    pub time_offset: isize,
108    pub connections: usize,
109    /// The number of inbound connections
110    /// Added in Bitcoin Core v0.21
111    pub connections_in: Option<usize>,
112    /// The number of outbound connections
113    /// Added in Bitcoin Core v0.21
114    pub connections_out: Option<usize>,
115    #[serde(rename = "networkactive")]
116    pub network_active: bool,
117    pub networks: Vec<GetNetworkInfoResultNetwork>,
118    #[serde(rename = "relayfee", with = "bitcoin::amount::serde::as_btc")]
119    pub relay_fee: Amount,
120    #[serde(rename = "incrementalfee", with = "bitcoin::amount::serde::as_btc")]
121    pub incremental_fee: Amount,
122    #[serde(rename = "localaddresses")]
123    pub local_addresses: Vec<GetNetworkInfoResultAddress>,
124    pub warnings: String,
125}
126
127#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
128#[serde(rename_all = "camelCase")]
129pub struct AddMultiSigAddressResult {
130    pub address: Address<NetworkUnchecked>,
131    pub redeem_script: ScriptBuf,
132}
133
134#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
135pub struct LoadWalletResult {
136    pub name: String,
137    pub warning: Option<String>,
138}
139
140#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
141pub struct UnloadWalletResult {
142    pub warning: Option<String>,
143}
144
145#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
146pub struct Descriptor {
147    pub desc: String,
148    pub timestamp: Timestamp,
149    pub active: bool,
150    pub internal: Option<bool>,
151    pub range: Option<(u64, u64)>,
152    pub next: Option<u64>,
153}
154
155#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
156pub struct ListDescriptorsResult {
157    pub wallet_name: String,
158    pub descriptors: Vec<Descriptor>,
159}
160
161#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
162pub struct ListWalletDirResult {
163    pub wallets: Vec<ListWalletDirItem>,
164}
165
166#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
167pub struct ListWalletDirItem {
168    pub name: String,
169}
170
171#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
172pub struct GetWalletInfoResult {
173    #[serde(rename = "walletname")]
174    pub wallet_name: String,
175    #[serde(rename = "walletversion")]
176    pub wallet_version: u32,
177    #[serde(with = "bitcoin::amount::serde::as_btc")]
178    pub balance: Amount,
179    #[serde(with = "bitcoin::amount::serde::as_btc")]
180    pub unconfirmed_balance: Amount,
181    #[serde(with = "bitcoin::amount::serde::as_btc")]
182    pub immature_balance: Amount,
183    #[serde(rename = "txcount")]
184    pub tx_count: usize,
185    #[serde(rename = "keypoololdest")]
186    pub keypool_oldest: Option<usize>,
187    #[serde(rename = "keypoolsize")]
188    pub keypool_size: usize,
189    #[serde(rename = "keypoolsize_hd_internal")]
190    pub keypool_size_hd_internal: usize,
191    pub unlocked_until: Option<u64>,
192    #[serde(rename = "paytxfee", with = "bitcoin::amount::serde::as_btc")]
193    pub pay_tx_fee: Amount,
194    #[serde(rename = "hdseedid")]
195    pub hd_seed_id: Option<bitcoin::hash_types::XpubIdentifier>,
196    pub private_keys_enabled: bool,
197    pub avoid_reuse: Option<bool>,
198    pub scanning: Option<ScanningDetails>,
199}
200
201#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
202#[serde(untagged)]
203pub enum ScanningDetails {
204    Scanning {
205        duration: usize,
206        progress: f32,
207    },
208    /// The bool in this field will always be false.
209    NotScanning(bool),
210}
211
212impl Eq for ScanningDetails {}
213
214#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
215#[serde(rename_all = "camelCase")]
216pub struct GetBlockResult {
217    pub hash: bitcoin::BlockHash,
218    pub confirmations: i32,
219    pub size: usize,
220    pub strippedsize: Option<usize>,
221    pub weight: usize,
222    pub height: usize,
223    pub version: i32,
224    #[serde(default, with = "crate::serde_hex::opt")]
225    pub version_hex: Option<Vec<u8>>,
226    pub merkleroot: bitcoin::hash_types::TxMerkleNode,
227    pub tx: Vec<bitcoin::Txid>,
228    pub time: usize,
229    pub mediantime: Option<usize>,
230    pub nonce: u32,
231    pub bits: String,
232    pub difficulty: f64,
233    #[serde(with = "crate::serde_hex")]
234    pub chainwork: Vec<u8>,
235    pub n_tx: usize,
236    pub previousblockhash: Option<bitcoin::BlockHash>,
237    pub nextblockhash: Option<bitcoin::BlockHash>,
238}
239
240#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
241#[serde(rename_all = "camelCase")]
242pub struct GetBlockHeaderResult {
243    pub hash: bitcoin::BlockHash,
244    pub confirmations: i32,
245    pub height: usize,
246    pub version: Version,
247    #[serde(default, with = "crate::serde_hex::opt")]
248    pub version_hex: Option<Vec<u8>>,
249    #[serde(rename = "merkleroot")]
250    pub merkle_root: bitcoin::hash_types::TxMerkleNode,
251    pub time: usize,
252    #[serde(rename = "mediantime")]
253    pub median_time: Option<usize>,
254    pub nonce: u32,
255    pub bits: String,
256    pub difficulty: f64,
257    #[serde(with = "crate::serde_hex")]
258    pub chainwork: Vec<u8>,
259    pub n_tx: usize,
260    #[serde(rename = "previousblockhash")]
261    pub previous_block_hash: Option<bitcoin::BlockHash>,
262    #[serde(rename = "nextblockhash")]
263    pub next_block_hash: Option<bitcoin::BlockHash>,
264}
265
266#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
267pub struct GetBlockStatsResult {
268    #[serde(rename = "avgfee", with = "bitcoin::amount::serde::as_sat")]
269    pub avg_fee: Amount,
270    #[serde(rename = "avgfeerate", with = "bitcoin::amount::serde::as_sat")]
271    pub avg_fee_rate: Amount,
272    #[serde(rename = "avgtxsize")]
273    pub avg_tx_size: u32,
274    #[serde(rename = "blockhash")]
275    pub block_hash: bitcoin::BlockHash,
276    #[serde(rename = "feerate_percentiles")]
277    pub fee_rate_percentiles: FeeRatePercentiles,
278    pub height: u64,
279    pub ins: usize,
280    #[serde(rename = "maxfee", with = "bitcoin::amount::serde::as_sat")]
281    pub max_fee: Amount,
282    #[serde(rename = "maxfeerate", with = "bitcoin::amount::serde::as_sat")]
283    pub max_fee_rate: Amount,
284    #[serde(rename = "maxtxsize")]
285    pub max_tx_size: u32,
286    #[serde(rename = "medianfee", with = "bitcoin::amount::serde::as_sat")]
287    pub median_fee: Amount,
288    #[serde(rename = "mediantime")]
289    pub median_time: u64,
290    #[serde(rename = "mediantxsize")]
291    pub median_tx_size: u32,
292    #[serde(rename = "minfee", with = "bitcoin::amount::serde::as_sat")]
293    pub min_fee: Amount,
294    #[serde(rename = "minfeerate", with = "bitcoin::amount::serde::as_sat")]
295    pub min_fee_rate: Amount,
296    #[serde(rename = "mintxsize")]
297    pub min_tx_size: u32,
298    pub outs: usize,
299    #[serde(with = "bitcoin::amount::serde::as_sat")]
300    pub subsidy: Amount,
301    #[serde(rename = "swtotal_size")]
302    pub sw_total_size: usize,
303    #[serde(rename = "swtotal_weight")]
304    pub sw_total_weight: usize,
305    #[serde(rename = "swtxs")]
306    pub sw_txs: usize,
307    pub time: u64,
308    #[serde(with = "bitcoin::amount::serde::as_sat")]
309    pub total_out: Amount,
310    pub total_size: usize,
311    pub total_weight: usize,
312    #[serde(rename = "totalfee", with = "bitcoin::amount::serde::as_sat")]
313    pub total_fee: Amount,
314    pub txs: usize,
315    pub utxo_increase: i32,
316    pub utxo_size_inc: i32,
317}
318
319#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
320pub struct GetBlockStatsResultPartial {
321    #[serde(
322        default,
323        rename = "avgfee",
324        with = "bitcoin::amount::serde::as_sat::opt",
325        skip_serializing_if = "Option::is_none"
326    )]
327    pub avg_fee: Option<Amount>,
328    #[serde(
329        default,
330        rename = "avgfeerate",
331        with = "bitcoin::amount::serde::as_sat::opt",
332        skip_serializing_if = "Option::is_none"
333    )]
334    pub avg_fee_rate: Option<Amount>,
335    #[serde(default, rename = "avgtxsize", skip_serializing_if = "Option::is_none")]
336    pub avg_tx_size: Option<u32>,
337    #[serde(default, rename = "blockhash", skip_serializing_if = "Option::is_none")]
338    pub block_hash: Option<bitcoin::BlockHash>,
339    #[serde(default, rename = "feerate_percentiles", skip_serializing_if = "Option::is_none")]
340    pub fee_rate_percentiles: Option<FeeRatePercentiles>,
341    #[serde(default, skip_serializing_if = "Option::is_none")]
342    pub height: Option<u64>,
343    #[serde(default, skip_serializing_if = "Option::is_none")]
344    pub ins: Option<usize>,
345    #[serde(
346        default,
347        rename = "maxfee",
348        with = "bitcoin::amount::serde::as_sat::opt",
349        skip_serializing_if = "Option::is_none"
350    )]
351    pub max_fee: Option<Amount>,
352    #[serde(
353        default,
354        rename = "maxfeerate",
355        with = "bitcoin::amount::serde::as_sat::opt",
356        skip_serializing_if = "Option::is_none"
357    )]
358    pub max_fee_rate: Option<Amount>,
359    #[serde(default, rename = "maxtxsize", skip_serializing_if = "Option::is_none")]
360    pub max_tx_size: Option<u32>,
361    #[serde(
362        default,
363        rename = "medianfee",
364        with = "bitcoin::amount::serde::as_sat::opt",
365        skip_serializing_if = "Option::is_none"
366    )]
367    pub median_fee: Option<Amount>,
368    #[serde(default, rename = "mediantime", skip_serializing_if = "Option::is_none")]
369    pub median_time: Option<u64>,
370    #[serde(default, rename = "mediantxsize", skip_serializing_if = "Option::is_none")]
371    pub median_tx_size: Option<u32>,
372    #[serde(
373        default,
374        rename = "minfee",
375        with = "bitcoin::amount::serde::as_sat::opt",
376        skip_serializing_if = "Option::is_none"
377    )]
378    pub min_fee: Option<Amount>,
379    #[serde(
380        default,
381        rename = "minfeerate",
382        with = "bitcoin::amount::serde::as_sat::opt",
383        skip_serializing_if = "Option::is_none"
384    )]
385    pub min_fee_rate: Option<Amount>,
386    #[serde(default, rename = "mintxsize", skip_serializing_if = "Option::is_none")]
387    pub min_tx_size: Option<u32>,
388    #[serde(default, skip_serializing_if = "Option::is_none")]
389    pub outs: Option<usize>,
390    #[serde(
391        default,
392        with = "bitcoin::amount::serde::as_sat::opt",
393        skip_serializing_if = "Option::is_none"
394    )]
395    pub subsidy: Option<Amount>,
396    #[serde(default, rename = "swtotal_size", skip_serializing_if = "Option::is_none")]
397    pub sw_total_size: Option<usize>,
398    #[serde(default, rename = "swtotal_weight", skip_serializing_if = "Option::is_none")]
399    pub sw_total_weight: Option<usize>,
400    #[serde(default, rename = "swtxs", skip_serializing_if = "Option::is_none")]
401    pub sw_txs: Option<usize>,
402    #[serde(default, skip_serializing_if = "Option::is_none")]
403    pub time: Option<u64>,
404    #[serde(
405        default,
406        with = "bitcoin::amount::serde::as_sat::opt",
407        skip_serializing_if = "Option::is_none"
408    )]
409    pub total_out: Option<Amount>,
410    #[serde(default, skip_serializing_if = "Option::is_none")]
411    pub total_size: Option<usize>,
412    #[serde(default, skip_serializing_if = "Option::is_none")]
413    pub total_weight: Option<usize>,
414    #[serde(
415        default,
416        rename = "totalfee",
417        with = "bitcoin::amount::serde::as_sat::opt",
418        skip_serializing_if = "Option::is_none"
419    )]
420    pub total_fee: Option<Amount>,
421    #[serde(default, skip_serializing_if = "Option::is_none")]
422    pub txs: Option<usize>,
423    #[serde(default, skip_serializing_if = "Option::is_none")]
424    pub utxo_increase: Option<i32>,
425    #[serde(default, skip_serializing_if = "Option::is_none")]
426    pub utxo_size_inc: Option<i32>,
427}
428
429#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
430pub struct FeeRatePercentiles {
431    #[serde(with = "bitcoin::amount::serde::as_sat")]
432    pub fr_10th: Amount,
433    #[serde(with = "bitcoin::amount::serde::as_sat")]
434    pub fr_25th: Amount,
435    #[serde(with = "bitcoin::amount::serde::as_sat")]
436    pub fr_50th: Amount,
437    #[serde(with = "bitcoin::amount::serde::as_sat")]
438    pub fr_75th: Amount,
439    #[serde(with = "bitcoin::amount::serde::as_sat")]
440    pub fr_90th: Amount,
441}
442
443#[derive(Clone)]
444pub enum BlockStatsFields {
445    AverageFee,
446    AverageFeeRate,
447    AverageTxSize,
448    BlockHash,
449    FeeRatePercentiles,
450    Height,
451    Ins,
452    MaxFee,
453    MaxFeeRate,
454    MaxTxSize,
455    MedianFee,
456    MedianTime,
457    MedianTxSize,
458    MinFee,
459    MinFeeRate,
460    MinTxSize,
461    Outs,
462    Subsidy,
463    SegWitTotalSize,
464    SegWitTotalWeight,
465    SegWitTxs,
466    Time,
467    TotalOut,
468    TotalSize,
469    TotalWeight,
470    TotalFee,
471    Txs,
472    UtxoIncrease,
473    UtxoSizeIncrease,
474}
475
476impl BlockStatsFields {
477    fn get_rpc_keyword(&self) -> &str {
478        match *self {
479            BlockStatsFields::AverageFee => "avgfee",
480            BlockStatsFields::AverageFeeRate => "avgfeerate",
481            BlockStatsFields::AverageTxSize => "avgtxsize",
482            BlockStatsFields::BlockHash => "blockhash",
483            BlockStatsFields::FeeRatePercentiles => "feerate_percentiles",
484            BlockStatsFields::Height => "height",
485            BlockStatsFields::Ins => "ins",
486            BlockStatsFields::MaxFee => "maxfee",
487            BlockStatsFields::MaxFeeRate => "maxfeerate",
488            BlockStatsFields::MaxTxSize => "maxtxsize",
489            BlockStatsFields::MedianFee => "medianfee",
490            BlockStatsFields::MedianTime => "mediantime",
491            BlockStatsFields::MedianTxSize => "mediantxsize",
492            BlockStatsFields::MinFee => "minfee",
493            BlockStatsFields::MinFeeRate => "minfeerate",
494            BlockStatsFields::MinTxSize => "minfeerate",
495            BlockStatsFields::Outs => "outs",
496            BlockStatsFields::Subsidy => "subsidy",
497            BlockStatsFields::SegWitTotalSize => "swtotal_size",
498            BlockStatsFields::SegWitTotalWeight => "swtotal_weight",
499            BlockStatsFields::SegWitTxs => "swtxs",
500            BlockStatsFields::Time => "time",
501            BlockStatsFields::TotalOut => "total_out",
502            BlockStatsFields::TotalSize => "total_size",
503            BlockStatsFields::TotalWeight => "total_weight",
504            BlockStatsFields::TotalFee => "totalfee",
505            BlockStatsFields::Txs => "txs",
506            BlockStatsFields::UtxoIncrease => "utxo_increase",
507            BlockStatsFields::UtxoSizeIncrease => "utxo_size_inc",
508        }
509    }
510}
511
512impl fmt::Display for BlockStatsFields {
513    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
514        write!(f, "{}", self.get_rpc_keyword())
515    }
516}
517
518impl From<BlockStatsFields> for serde_json::Value {
519    fn from(bsf: BlockStatsFields) -> Self {
520        Self::from(bsf.to_string())
521    }
522}
523
524#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
525#[serde(rename_all = "camelCase")]
526pub struct GetMiningInfoResult {
527    pub blocks: u32,
528    #[serde(rename = "currentblockweight")]
529    pub current_block_weight: Option<u64>,
530    #[serde(rename = "currentblocktx")]
531    pub current_block_tx: Option<usize>,
532    pub difficulty: f64,
533    #[serde(rename = "networkhashps")]
534    pub network_hash_ps: f64,
535    #[serde(rename = "pooledtx")]
536    pub pooled_tx: usize,
537    pub chain: String,
538    pub warnings: String,
539}
540
541#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
542#[serde(rename_all = "camelCase")]
543pub struct GetRawTransactionResultVinScriptSig {
544    pub asm: String,
545    #[serde(with = "crate::serde_hex")]
546    pub hex: Vec<u8>,
547}
548
549impl GetRawTransactionResultVinScriptSig {
550    pub fn script(&self) -> Result<ScriptBuf, encode::Error> {
551        Ok(ScriptBuf::from(self.hex.clone()))
552    }
553}
554
555#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
556#[serde(rename_all = "camelCase")]
557pub struct GetRawTransactionResultVin {
558    pub sequence: u32,
559    /// The raw scriptSig in case of a coinbase tx.
560    #[serde(default, with = "crate::serde_hex::opt")]
561    pub coinbase: Option<Vec<u8>>,
562    /// Not provided for coinbase txs.
563    pub txid: Option<bitcoin::Txid>,
564    /// Not provided for coinbase txs.
565    pub vout: Option<u32>,
566    /// The scriptSig in case of a non-coinbase tx.
567    pub script_sig: Option<GetRawTransactionResultVinScriptSig>,
568    /// Not provided for coinbase txs.
569    #[serde(default, deserialize_with = "deserialize_hex_array_opt")]
570    pub txinwitness: Option<Vec<Vec<u8>>>,
571}
572
573impl GetRawTransactionResultVin {
574    /// Whether this input is from a coinbase tx.
575    /// The [txid], [vout] and [script_sig] fields are not provided
576    /// for coinbase transactions.
577    pub fn is_coinbase(&self) -> bool {
578        self.coinbase.is_some()
579    }
580}
581
582#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
583#[serde(rename_all = "camelCase")]
584pub struct GetRawTransactionResultVoutScriptPubKey {
585    pub asm: String,
586    #[serde(with = "crate::serde_hex")]
587    pub hex: Vec<u8>,
588    pub req_sigs: Option<usize>,
589    #[serde(rename = "type")]
590    pub type_: Option<ScriptPubkeyType>,
591    // Deprecated in Bitcoin Core 22
592    #[serde(default)]
593    pub addresses: Vec<Address<NetworkUnchecked>>,
594    // Added in Bitcoin Core 22
595    #[serde(default)]
596    pub address: Option<Address<NetworkUnchecked>>,
597}
598
599impl GetRawTransactionResultVoutScriptPubKey {
600    pub fn script(&self) -> Result<ScriptBuf, encode::Error> {
601        Ok(ScriptBuf::from(self.hex.clone()))
602    }
603}
604
605#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
606#[serde(rename_all = "camelCase")]
607pub struct GetRawTransactionResultVout {
608    #[serde(with = "bitcoin::amount::serde::as_btc")]
609    pub value: Amount,
610    pub n: u32,
611    pub script_pub_key: GetRawTransactionResultVoutScriptPubKey,
612}
613
614#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
615#[serde(rename_all = "camelCase")]
616pub struct GetRawTransactionResult {
617    #[serde(rename = "in_active_chain")]
618    pub in_active_chain: Option<bool>,
619    #[serde(with = "crate::serde_hex")]
620    pub hex: Vec<u8>,
621    pub txid: bitcoin::Txid,
622    pub hash: bitcoin::Wtxid,
623    pub size: usize,
624    pub vsize: usize,
625    pub version: u32,
626    pub locktime: u32,
627    pub vin: Vec<GetRawTransactionResultVin>,
628    pub vout: Vec<GetRawTransactionResultVout>,
629    pub blockhash: Option<bitcoin::BlockHash>,
630    pub confirmations: Option<u32>,
631    pub time: Option<usize>,
632    pub blocktime: Option<usize>,
633}
634
635#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
636pub struct GetBlockFilterResult {
637    pub header: bitcoin::hash_types::FilterHash,
638    #[serde(with = "crate::serde_hex")]
639    pub filter: Vec<u8>,
640}
641
642impl GetBlockFilterResult {
643    /// Get the filter.
644    /// Note that this copies the underlying filter data. To prevent this,
645    /// use [into_filter] instead.
646    pub fn to_filter(&self) -> bip158::BlockFilter {
647        bip158::BlockFilter::new(&self.filter)
648    }
649
650    /// Convert the result in the filter type.
651    pub fn into_filter(self) -> bip158::BlockFilter {
652        bip158::BlockFilter {
653            content: self.filter,
654        }
655    }
656}
657
658impl GetRawTransactionResult {
659    /// Whether this tx is a coinbase tx.
660    pub fn is_coinbase(&self) -> bool {
661        self.vin.len() == 1 && self.vin[0].is_coinbase()
662    }
663
664    pub fn transaction(&self) -> Result<Transaction, encode::Error> {
665        Ok(encode::deserialize(&self.hex)?)
666    }
667}
668
669/// Enum to represent the BIP125 replaceable status for a transaction.
670#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
671#[serde(rename_all = "lowercase")]
672pub enum Bip125Replaceable {
673    Yes,
674    No,
675    Unknown,
676}
677
678/// Enum to represent the category of a transaction.
679#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
680#[serde(rename_all = "lowercase")]
681pub enum GetTransactionResultDetailCategory {
682    Send,
683    Receive,
684    Generate,
685    Immature,
686    Orphan,
687}
688
689#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
690pub struct GetTransactionResultDetail {
691    pub address: Option<Address<NetworkUnchecked>>,
692    pub category: GetTransactionResultDetailCategory,
693    #[serde(with = "bitcoin::amount::serde::as_btc")]
694    pub amount: SignedAmount,
695    pub label: Option<String>,
696    pub vout: u32,
697    #[serde(default, with = "bitcoin::amount::serde::as_btc::opt")]
698    pub fee: Option<SignedAmount>,
699    pub abandoned: Option<bool>,
700}
701
702#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
703pub struct WalletTxInfo {
704    pub confirmations: i32,
705    pub blockhash: Option<bitcoin::BlockHash>,
706    pub blockindex: Option<usize>,
707    pub blocktime: Option<u64>,
708    pub blockheight: Option<u32>,
709    pub txid: bitcoin::Txid,
710    pub time: u64,
711    pub timereceived: u64,
712    #[serde(rename = "bip125-replaceable")]
713    pub bip125_replaceable: Bip125Replaceable,
714    /// Conflicting transaction ids
715    #[serde(rename = "walletconflicts")]
716    pub wallet_conflicts: Vec<bitcoin::Txid>,
717}
718
719#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
720pub struct GetTransactionResult {
721    #[serde(flatten)]
722    pub info: WalletTxInfo,
723    #[serde(with = "bitcoin::amount::serde::as_btc")]
724    pub amount: SignedAmount,
725    #[serde(default, with = "bitcoin::amount::serde::as_btc::opt")]
726    pub fee: Option<SignedAmount>,
727    pub details: Vec<GetTransactionResultDetail>,
728    #[serde(with = "crate::serde_hex")]
729    pub hex: Vec<u8>,
730}
731
732impl GetTransactionResult {
733    pub fn transaction(&self) -> Result<Transaction, encode::Error> {
734        Ok(encode::deserialize(&self.hex)?)
735    }
736}
737
738#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
739pub struct ListTransactionResult {
740    #[serde(flatten)]
741    pub info: WalletTxInfo,
742    #[serde(flatten)]
743    pub detail: GetTransactionResultDetail,
744
745    pub trusted: Option<bool>,
746    pub comment: Option<String>,
747}
748
749#[derive(Clone, PartialEq, Eq, Debug, Deserialize)]
750pub struct ListSinceBlockResult {
751    pub transactions: Vec<ListTransactionResult>,
752    #[serde(default)]
753    pub removed: Vec<ListTransactionResult>,
754    pub lastblock: bitcoin::BlockHash,
755}
756
757#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
758#[serde(rename_all = "camelCase")]
759pub struct GetTxOutResult {
760    pub bestblock: bitcoin::BlockHash,
761    pub confirmations: u32,
762    #[serde(with = "bitcoin::amount::serde::as_btc")]
763    pub value: Amount,
764    pub script_pub_key: GetRawTransactionResultVoutScriptPubKey,
765    pub coinbase: bool,
766}
767
768#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Default)]
769#[serde(rename_all = "camelCase")]
770pub struct ListUnspentQueryOptions {
771    #[serde(
772        rename = "minimumAmount",
773        with = "bitcoin::amount::serde::as_btc::opt",
774        skip_serializing_if = "Option::is_none"
775    )]
776    pub minimum_amount: Option<Amount>,
777    #[serde(
778        rename = "maximumAmount",
779        with = "bitcoin::amount::serde::as_btc::opt",
780        skip_serializing_if = "Option::is_none"
781    )]
782    pub maximum_amount: Option<Amount>,
783    #[serde(rename = "maximumCount", skip_serializing_if = "Option::is_none")]
784    pub maximum_count: Option<usize>,
785    #[serde(
786        rename = "minimumSumAmount",
787        with = "bitcoin::amount::serde::as_btc::opt",
788        skip_serializing_if = "Option::is_none"
789    )]
790    pub minimum_sum_amount: Option<Amount>,
791}
792
793#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
794#[serde(rename_all = "camelCase")]
795pub struct ListUnspentResultEntry {
796    pub txid: bitcoin::Txid,
797    pub vout: u32,
798    pub address: Option<Address<NetworkUnchecked>>,
799    pub label: Option<String>,
800    pub redeem_script: Option<ScriptBuf>,
801    pub witness_script: Option<ScriptBuf>,
802    pub script_pub_key: ScriptBuf,
803    #[serde(with = "bitcoin::amount::serde::as_btc")]
804    pub amount: Amount,
805    pub confirmations: u32,
806    pub spendable: bool,
807    pub solvable: bool,
808    #[serde(rename = "desc")]
809    pub descriptor: Option<String>,
810    pub safe: bool,
811}
812
813#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
814#[serde(rename_all = "camelCase")]
815pub struct ListReceivedByAddressResult {
816    #[serde(default, rename = "involvesWatchonly")]
817    pub involved_watch_only: bool,
818    pub address: Address<NetworkUnchecked>,
819    #[serde(with = "bitcoin::amount::serde::as_btc")]
820    pub amount: Amount,
821    pub confirmations: u32,
822    pub label: String,
823    pub txids: Vec<bitcoin::Txid>,
824}
825
826#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
827#[serde(rename_all = "camelCase")]
828pub struct SignRawTransactionResultError {
829    pub txid: bitcoin::Txid,
830    pub vout: u32,
831    pub script_sig: ScriptBuf,
832    pub sequence: u32,
833    pub error: String,
834}
835
836#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
837#[serde(rename_all = "camelCase")]
838pub struct SignRawTransactionResult {
839    #[serde(with = "crate::serde_hex")]
840    pub hex: Vec<u8>,
841    pub complete: bool,
842    pub errors: Option<Vec<SignRawTransactionResultError>>,
843}
844
845impl SignRawTransactionResult {
846    pub fn transaction(&self) -> Result<Transaction, encode::Error> {
847        Ok(encode::deserialize(&self.hex)?)
848    }
849}
850
851#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
852pub struct TestMempoolAcceptResult {
853    pub txid: bitcoin::Txid,
854    pub allowed: bool,
855    #[serde(rename = "reject-reason")]
856    pub reject_reason: Option<String>,
857    /// Virtual transaction size as defined in BIP 141 (only present when 'allowed' is true)
858    /// Added in Bitcoin Core v0.21
859    pub vsize: Option<u64>,
860    /// Transaction fees (only present if 'allowed' is true)
861    /// Added in Bitcoin Core v0.21
862    pub fees: Option<TestMempoolAcceptResultFees>,
863}
864
865#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
866pub struct TestMempoolAcceptResultFees {
867    /// Transaction fee in BTC
868    #[serde(with = "bitcoin::amount::serde::as_btc")]
869    pub base: Amount,
870    // unlike GetMempoolEntryResultFees, this only has the `base` fee
871}
872
873#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
874#[serde(rename_all = "snake_case")]
875pub enum Bip9SoftforkStatus {
876    Defined,
877    Started,
878    LockedIn,
879    Active,
880    Failed,
881}
882
883#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
884pub struct Bip9SoftforkStatistics {
885    pub period: u32,
886    pub threshold: Option<u32>,
887    pub elapsed: u32,
888    pub count: u32,
889    pub possible: Option<bool>,
890}
891
892#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
893pub struct Bip9SoftforkInfo {
894    pub status: Bip9SoftforkStatus,
895    pub bit: Option<u8>,
896    // Can be -1 for 0.18.x inactive ones.
897    pub start_time: i64,
898    pub timeout: u64,
899    pub since: u32,
900    pub statistics: Option<Bip9SoftforkStatistics>,
901}
902
903#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
904#[serde(rename_all = "lowercase")]
905pub enum SoftforkType {
906    Buried,
907    Bip9,
908    #[serde(other)]
909    Other,
910}
911
912/// Status of a softfork
913#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
914pub struct Softfork {
915    #[serde(rename = "type")]
916    pub type_: SoftforkType,
917    pub bip9: Option<Bip9SoftforkInfo>,
918    pub height: Option<u32>,
919    pub active: bool,
920}
921
922#[allow(non_camel_case_types)]
923#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
924#[serde(rename_all = "lowercase")]
925pub enum ScriptPubkeyType {
926    Nonstandard,
927    Pubkey,
928    PubkeyHash,
929    ScriptHash,
930    MultiSig,
931    NullData,
932    Witness_v0_KeyHash,
933    Witness_v0_ScriptHash,
934    Witness_v1_Taproot,
935    Witness_Unknown,
936}
937
938#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
939pub struct GetAddressInfoResultEmbedded {
940    pub address: Address<NetworkUnchecked>,
941    #[serde(rename = "scriptPubKey")]
942    pub script_pub_key: ScriptBuf,
943    #[serde(rename = "is_script")]
944    pub is_script: Option<bool>,
945    #[serde(rename = "is_witness")]
946    pub is_witness: Option<bool>,
947    pub witness_version: Option<u32>,
948    #[serde(with = "crate::serde_hex")]
949    pub witness_program: Vec<u8>,
950    pub script: Option<ScriptPubkeyType>,
951    /// The redeemscript for the p2sh address.
952    #[serde(default, with = "crate::serde_hex::opt")]
953    pub hex: Option<Vec<u8>>,
954    pub pubkeys: Option<Vec<PublicKey>>,
955    #[serde(rename = "sigsrequired")]
956    pub n_signatures_required: Option<usize>,
957    pub pubkey: Option<PublicKey>,
958    #[serde(rename = "is_compressed")]
959    pub is_compressed: Option<bool>,
960    pub label: Option<String>,
961    #[serde(rename = "hdkeypath")]
962    pub hd_key_path: Option<bip32::DerivationPath>,
963    #[serde(rename = "hdseedid")]
964    pub hd_seed_id: Option<bitcoin::hash_types::XpubIdentifier>,
965    #[serde(default)]
966    pub labels: Vec<GetAddressInfoResultLabel>,
967}
968
969#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
970#[serde(rename_all = "lowercase")]
971pub enum GetAddressInfoResultLabelPurpose {
972    Send,
973    Receive,
974}
975
976#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
977#[serde(untagged)]
978pub enum GetAddressInfoResultLabel {
979    Simple(String),
980    WithPurpose {
981        name: String,
982        purpose: GetAddressInfoResultLabelPurpose,
983    },
984}
985
986#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
987pub struct GetAddressInfoResult {
988    pub address: Address<NetworkUnchecked>,
989    #[serde(rename = "scriptPubKey")]
990    pub script_pub_key: ScriptBuf,
991    #[serde(rename = "ismine")]
992    pub is_mine: Option<bool>,
993    #[serde(rename = "iswatchonly")]
994    pub is_watchonly: Option<bool>,
995    #[serde(rename = "isscript")]
996    pub is_script: Option<bool>,
997    #[serde(rename = "iswitness")]
998    pub is_witness: Option<bool>,
999    pub witness_version: Option<u32>,
1000    #[serde(default, with = "crate::serde_hex::opt")]
1001    pub witness_program: Option<Vec<u8>>,
1002    pub script: Option<ScriptPubkeyType>,
1003    /// The redeemscript for the p2sh address.
1004    #[serde(default, with = "crate::serde_hex::opt")]
1005    pub hex: Option<Vec<u8>>,
1006    pub pubkeys: Option<Vec<PublicKey>>,
1007    #[serde(rename = "sigsrequired")]
1008    pub n_signatures_required: Option<usize>,
1009    pub pubkey: Option<PublicKey>,
1010    /// Information about the address embedded in P2SH or P2WSH, if relevant and known.
1011    pub embedded: Option<GetAddressInfoResultEmbedded>,
1012    #[serde(rename = "is_compressed")]
1013    pub is_compressed: Option<bool>,
1014    pub timestamp: Option<u64>,
1015    #[serde(rename = "hdkeypath")]
1016    pub hd_key_path: Option<bip32::DerivationPath>,
1017    #[serde(rename = "hdseedid")]
1018    pub hd_seed_id: Option<bitcoin::hash_types::XpubIdentifier>,
1019    pub labels: Vec<GetAddressInfoResultLabel>,
1020    /// Deprecated in v0.20.0. See `labels` field instead.
1021    #[deprecated(note = "since Core v0.20.0")]
1022    pub label: Option<String>,
1023}
1024
1025/// Models the result of "getblockchaininfo"
1026#[derive(Clone, Debug, Deserialize, Serialize)]
1027pub struct GetBlockchainInfoResult {
1028    /// Current network name as defined in BIP70 (main, test, regtest)
1029    pub chain: String,
1030    /// The current number of blocks processed in the server
1031    pub blocks: u64,
1032    /// The current number of headers we have validated
1033    pub headers: u64,
1034    /// The hash of the currently best block
1035    #[serde(rename = "bestblockhash")]
1036    pub best_block_hash: bitcoin::BlockHash,
1037    /// The current difficulty
1038    pub difficulty: f64,
1039    /// Median time for the current best block
1040    #[serde(rename = "mediantime")]
1041    pub median_time: u64,
1042    /// Estimate of verification progress [0..1]
1043    #[serde(rename = "verificationprogress")]
1044    pub verification_progress: f64,
1045    /// Estimate of whether this node is in Initial Block Download mode
1046    #[serde(rename = "initialblockdownload")]
1047    pub initial_block_download: bool,
1048    /// Total amount of work in active chain, in hexadecimal
1049    #[serde(rename = "chainwork", with = "crate::serde_hex")]
1050    pub chain_work: Vec<u8>,
1051    /// The estimated size of the block and undo files on disk
1052    pub size_on_disk: u64,
1053    /// If the blocks are subject to pruning
1054    pub pruned: bool,
1055    /// Lowest-height complete block stored (only present if pruning is enabled)
1056    #[serde(rename = "pruneheight")]
1057    pub prune_height: Option<u64>,
1058    /// Whether automatic pruning is enabled (only present if pruning is enabled)
1059    pub automatic_pruning: Option<bool>,
1060    /// The target size used by pruning (only present if automatic pruning is enabled)
1061    pub prune_target_size: Option<u64>,
1062    /// Status of softforks in progress
1063    #[serde(default)]
1064    pub softforks: HashMap<String, Softfork>,
1065    /// Any network and blockchain warnings.
1066    pub warnings: String,
1067}
1068
1069#[derive(Clone, PartialEq, Eq, Debug)]
1070pub enum ImportMultiRequestScriptPubkey<'a> {
1071    Address(&'a Address),
1072    Script(&'a Script),
1073}
1074
1075#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1076pub struct GetMempoolInfoResult {
1077    /// True if the mempool is fully loaded
1078    pub loaded: bool,
1079    /// Current tx count
1080    pub size: usize,
1081    /// Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted
1082    pub bytes: usize,
1083    /// Total memory usage for the mempool
1084    pub usage: usize,
1085    /// Total fees for the mempool in BTC, ignoring modified fees through prioritisetransaction
1086    #[serde(with = "bitcoin::amount::serde::as_btc")]
1087    pub total_fee: Amount,
1088    /// Maximum memory usage for the mempool
1089    #[serde(rename = "maxmempool")]
1090    pub max_mempool: usize,
1091    /// Minimum fee rate in BTC/kvB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee
1092    #[serde(rename = "mempoolminfee", with = "bitcoin::amount::serde::as_btc")]
1093    pub mempool_min_fee: Amount,
1094    /// Current minimum relay fee for transactions
1095    #[serde(rename = "minrelaytxfee", with = "bitcoin::amount::serde::as_btc")]
1096    pub min_relay_tx_fee: Amount,
1097    /// Minimum fee rate increment for mempool limiting or replacement in BTC/kvB
1098    #[serde(rename = "incrementalrelayfee", with = "bitcoin::amount::serde::as_btc")]
1099    pub incremental_relay_fee: Amount,
1100    /// Current number of transactions that haven't passed initial broadcast yet
1101    #[serde(rename = "unbroadcastcount")]
1102    pub unbroadcast_count: usize,
1103    /// True if the mempool accepts RBF without replaceability signaling inspection
1104    #[serde(rename = "fullrbf")]
1105    pub full_rbf: bool,
1106}
1107
1108#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1109pub struct GetMempoolEntryResult {
1110    /// Virtual transaction size as defined in BIP 141. This is different from actual serialized
1111    /// size for witness transactions as witness data is discounted.
1112    #[serde(alias = "size")]
1113    pub vsize: u64,
1114    /// Transaction weight as defined in BIP 141. Added in Core v0.19.0.
1115    pub weight: Option<u64>,
1116    /// Local time transaction entered pool in seconds since 1 Jan 1970 GMT
1117    pub time: u64,
1118    /// Block height when transaction entered pool
1119    pub height: u64,
1120    /// Number of in-mempool descendant transactions (including this one)
1121    #[serde(rename = "descendantcount")]
1122    pub descendant_count: u64,
1123    /// Virtual transaction size of in-mempool descendants (including this one)
1124    #[serde(rename = "descendantsize")]
1125    pub descendant_size: u64,
1126    /// Number of in-mempool ancestor transactions (including this one)
1127    #[serde(rename = "ancestorcount")]
1128    pub ancestor_count: u64,
1129    /// Virtual transaction size of in-mempool ancestors (including this one)
1130    #[serde(rename = "ancestorsize")]
1131    pub ancestor_size: u64,
1132    /// Hash of serialized transaction, including witness data
1133    pub wtxid: bitcoin::Txid,
1134    /// Fee information
1135    pub fees: GetMempoolEntryResultFees,
1136    /// Unconfirmed transactions used as inputs for this transaction
1137    pub depends: Vec<bitcoin::Txid>,
1138    /// Unconfirmed transactions spending outputs from this transaction
1139    #[serde(rename = "spentby")]
1140    pub spent_by: Vec<bitcoin::Txid>,
1141    /// Whether this transaction could be replaced due to BIP125 (replace-by-fee)
1142    #[serde(rename = "bip125-replaceable")]
1143    pub bip125_replaceable: bool,
1144    /// Whether this transaction is currently unbroadcast (initial broadcast not yet acknowledged by any peers)
1145    /// Added in Bitcoin Core v0.21
1146    pub unbroadcast: Option<bool>,
1147}
1148
1149#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1150pub struct GetMempoolEntryResultFees {
1151    /// Transaction fee in BTC
1152    #[serde(with = "bitcoin::amount::serde::as_btc")]
1153    pub base: Amount,
1154    /// Transaction fee with fee deltas used for mining priority in BTC
1155    #[serde(with = "bitcoin::amount::serde::as_btc")]
1156    pub modified: Amount,
1157    /// Modified fees (see above) of in-mempool ancestors (including this one) in BTC
1158    #[serde(with = "bitcoin::amount::serde::as_btc")]
1159    pub ancestor: Amount,
1160    /// Modified fees (see above) of in-mempool descendants (including this one) in BTC
1161    #[serde(with = "bitcoin::amount::serde::as_btc")]
1162    pub descendant: Amount,
1163}
1164
1165impl<'a> serde::Serialize for ImportMultiRequestScriptPubkey<'a> {
1166    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1167    where
1168        S: serde::Serializer,
1169    {
1170        match *self {
1171            ImportMultiRequestScriptPubkey::Address(ref addr) => {
1172                #[derive(Serialize)]
1173                struct Tmp<'a> {
1174                    pub address: &'a Address,
1175                }
1176                serde::Serialize::serialize(
1177                    &Tmp {
1178                        address: addr,
1179                    },
1180                    serializer,
1181                )
1182            }
1183            ImportMultiRequestScriptPubkey::Script(script) => {
1184                serializer.serialize_str(&script.to_hex_string())
1185            }
1186        }
1187    }
1188}
1189
1190/// A import request for importmulti.
1191///
1192/// Note: unlike in bitcoind, `timestamp` defaults to 0.
1193#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize)]
1194pub struct ImportMultiRequest<'a> {
1195    pub timestamp: Timestamp,
1196    /// If using descriptor, do not also provide address/scriptPubKey, scripts, or pubkeys.
1197    #[serde(rename = "desc", skip_serializing_if = "Option::is_none")]
1198    pub descriptor: Option<&'a str>,
1199    #[serde(rename = "scriptPubKey", skip_serializing_if = "Option::is_none")]
1200    pub script_pubkey: Option<ImportMultiRequestScriptPubkey<'a>>,
1201    #[serde(rename = "redeemscript", skip_serializing_if = "Option::is_none")]
1202    pub redeem_script: Option<&'a Script>,
1203    #[serde(rename = "witnessscript", skip_serializing_if = "Option::is_none")]
1204    pub witness_script: Option<&'a Script>,
1205    #[serde(skip_serializing_if = "<[_]>::is_empty")]
1206    pub pubkeys: &'a [PublicKey],
1207    #[serde(skip_serializing_if = "<[_]>::is_empty")]
1208    pub keys: &'a [PrivateKey],
1209    #[serde(skip_serializing_if = "Option::is_none")]
1210    pub range: Option<(usize, usize)>,
1211    #[serde(skip_serializing_if = "Option::is_none")]
1212    pub internal: Option<bool>,
1213    #[serde(skip_serializing_if = "Option::is_none")]
1214    pub watchonly: Option<bool>,
1215    #[serde(skip_serializing_if = "Option::is_none")]
1216    pub label: Option<&'a str>,
1217    #[serde(skip_serializing_if = "Option::is_none")]
1218    pub keypool: Option<bool>,
1219}
1220
1221#[derive(Clone, PartialEq, Eq, Debug, Default, Deserialize, Serialize)]
1222pub struct ImportMultiOptions {
1223    #[serde(skip_serializing_if = "Option::is_none")]
1224    pub rescan: Option<bool>,
1225}
1226
1227#[derive(Clone, PartialEq, Eq, Copy, Debug)]
1228pub enum Timestamp {
1229    Now,
1230    Time(u64),
1231}
1232
1233impl serde::Serialize for Timestamp {
1234    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1235    where
1236        S: serde::Serializer,
1237    {
1238        match *self {
1239            Timestamp::Now => serializer.serialize_str("now"),
1240            Timestamp::Time(timestamp) => serializer.serialize_u64(timestamp),
1241        }
1242    }
1243}
1244
1245impl<'de> serde::Deserialize<'de> for Timestamp {
1246    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1247    where
1248        D: serde::Deserializer<'de>,
1249    {
1250        use serde::de;
1251        struct Visitor;
1252        impl<'de> de::Visitor<'de> for Visitor {
1253            type Value = Timestamp;
1254
1255            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1256                write!(formatter, "unix timestamp or 'now'")
1257            }
1258
1259            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
1260            where
1261                E: de::Error,
1262            {
1263                Ok(Timestamp::Time(value))
1264            }
1265
1266            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
1267            where
1268                E: de::Error,
1269            {
1270                if value == "now" {
1271                    Ok(Timestamp::Now)
1272                } else {
1273                    Err(de::Error::custom(format!(
1274                        "invalid str '{}', expecting 'now' or unix timestamp",
1275                        value
1276                    )))
1277                }
1278            }
1279        }
1280        deserializer.deserialize_any(Visitor)
1281    }
1282}
1283
1284impl Default for Timestamp {
1285    fn default() -> Self {
1286        Timestamp::Time(0)
1287    }
1288}
1289
1290impl From<u64> for Timestamp {
1291    fn from(t: u64) -> Self {
1292        Timestamp::Time(t)
1293    }
1294}
1295
1296impl From<Option<u64>> for Timestamp {
1297    fn from(timestamp: Option<u64>) -> Self {
1298        timestamp.map_or(Timestamp::Now, Timestamp::Time)
1299    }
1300}
1301
1302#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1303pub struct ImportMultiResultError {
1304    pub code: i64,
1305    pub message: String,
1306}
1307
1308#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1309pub struct ImportMultiResult {
1310    pub success: bool,
1311    #[serde(default)]
1312    pub warnings: Vec<String>,
1313    pub error: Option<ImportMultiResultError>,
1314}
1315
1316/// A import request for importdescriptors.
1317#[derive(Clone, PartialEq, Eq, Debug, Default, Deserialize, Serialize)]
1318pub struct ImportDescriptors {
1319    #[serde(rename = "desc")]
1320    pub descriptor: String,
1321    pub timestamp: Timestamp,
1322    #[serde(skip_serializing_if = "Option::is_none")]
1323    pub active: Option<bool>,
1324    #[serde(skip_serializing_if = "Option::is_none")]
1325    pub range: Option<(usize, usize)>,
1326    #[serde(skip_serializing_if = "Option::is_none")]
1327    pub next_index: Option<usize>,
1328    #[serde(skip_serializing_if = "Option::is_none")]
1329    pub internal: Option<bool>,
1330    #[serde(skip_serializing_if = "Option::is_none")]
1331    pub label: Option<String>,
1332}
1333
1334/// Progress toward rejecting pre-softfork blocks
1335#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1336pub struct RejectStatus {
1337    /// `true` if threshold reached
1338    pub status: bool,
1339}
1340
1341/// Models the result of "getpeerinfo"
1342#[derive(Clone, Debug, Deserialize, Serialize)]
1343pub struct GetPeerInfoResult {
1344    /// Peer index
1345    pub id: u64,
1346    /// The IP address and port of the peer
1347    // TODO: use a type for addr
1348    pub addr: String,
1349    /// Bind address of the connection to the peer
1350    // TODO: use a type for addrbind
1351    pub addrbind: String,
1352    /// Local address as reported by the peer
1353    // TODO: use a type for addrlocal
1354    pub addrlocal: Option<String>,
1355    /// Network (ipv4, ipv6, or onion) the peer connected through
1356    /// Added in Bitcoin Core v0.21
1357    pub network: Option<GetPeerInfoResultNetwork>,
1358    /// The services offered
1359    // TODO: use a type for services
1360    pub services: String,
1361    /// Whether peer has asked us to relay transactions to it
1362    pub relaytxes: bool,
1363    /// The time in seconds since epoch (Jan 1 1970 GMT) of the last send
1364    pub lastsend: u64,
1365    /// The time in seconds since epoch (Jan 1 1970 GMT) of the last receive
1366    pub lastrecv: u64,
1367    /// The time in seconds since epoch (Jan 1 1970 GMT) of the last valid transaction received from this peer
1368    /// Added in Bitcoin Core v0.21
1369    pub last_transaction: Option<u64>,
1370    /// The time in seconds since epoch (Jan 1 1970 GMT) of the last block received from this peer
1371    /// Added in Bitcoin Core v0.21
1372    pub last_block: Option<u64>,
1373    /// The total bytes sent
1374    pub bytessent: u64,
1375    /// The total bytes received
1376    pub bytesrecv: u64,
1377    /// The connection time in seconds since epoch (Jan 1 1970 GMT)
1378    pub conntime: u64,
1379    /// The time offset in seconds
1380    pub timeoffset: i64,
1381    /// ping time (if available)
1382    pub pingtime: Option<f64>,
1383    /// minimum observed ping time (if any at all)
1384    pub minping: Option<f64>,
1385    /// ping wait (if non-zero)
1386    pub pingwait: Option<f64>,
1387    /// The peer version, such as 70001
1388    pub version: u64,
1389    /// The string version
1390    pub subver: String,
1391    /// Inbound (true) or Outbound (false)
1392    pub inbound: bool,
1393    /// Whether connection was due to `addnode`/`-connect` or if it was an
1394    /// automatic/inbound connection
1395    /// Deprecated in Bitcoin Core v0.21
1396    pub addnode: Option<bool>,
1397    /// The starting height (block) of the peer
1398    pub startingheight: i64,
1399    /// The ban score
1400    /// Deprecated in Bitcoin Core v0.21
1401    pub banscore: Option<i64>,
1402    /// The last header we have in common with this peer
1403    pub synced_headers: i64,
1404    /// The last block we have in common with this peer
1405    pub synced_blocks: i64,
1406    /// The heights of blocks we're currently asking from this peer
1407    pub inflight: Vec<u64>,
1408    /// Whether the peer is whitelisted
1409    /// Deprecated in Bitcoin Core v0.21
1410    pub whitelisted: Option<bool>,
1411    #[serde(rename = "minfeefilter", default, with = "bitcoin::amount::serde::as_btc::opt")]
1412    pub min_fee_filter: Option<Amount>,
1413    /// The total bytes sent aggregated by message type
1414    pub bytessent_per_msg: HashMap<String, u64>,
1415    /// The total bytes received aggregated by message type
1416    pub bytesrecv_per_msg: HashMap<String, u64>,
1417    /// The type of the connection
1418    /// Added in Bitcoin Core v0.21
1419    pub connection_type: Option<GetPeerInfoResultConnectionType>,
1420}
1421
1422#[derive(Copy, Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
1423#[serde(rename_all = "snake_case")]
1424pub enum GetPeerInfoResultNetwork {
1425    Ipv4,
1426    Ipv6,
1427    Onion,
1428    #[deprecated]
1429    Unroutable,
1430    NotPubliclyRoutable,
1431    I2p,
1432    Cjdns,
1433    Internal,
1434}
1435
1436#[derive(Copy, Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
1437#[serde(rename_all = "kebab-case")]
1438pub enum GetPeerInfoResultConnectionType {
1439    OutboundFullRelay,
1440    BlockRelayOnly,
1441    Inbound,
1442    Manual,
1443    AddrFetch,
1444    Feeler,
1445}
1446
1447#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1448pub struct GetAddedNodeInfoResult {
1449    /// The node IP address or name (as provided to addnode)
1450    #[serde(rename = "addednode")]
1451    pub added_node: String,
1452    ///  If connected
1453    pub connected: bool,
1454    /// Only when connected = true
1455    pub addresses: Vec<GetAddedNodeInfoResultAddress>,
1456}
1457
1458#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1459pub struct GetAddedNodeInfoResultAddress {
1460    /// The bitcoin server IP and port we're connected to
1461    pub address: String,
1462    /// connection, inbound or outbound
1463    pub connected: GetAddedNodeInfoResultAddressType,
1464}
1465
1466#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1467#[serde(rename_all = "lowercase")]
1468pub enum GetAddedNodeInfoResultAddressType {
1469    Inbound,
1470    Outbound,
1471}
1472
1473#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1474pub struct GetNodeAddressesResult {
1475    /// Timestamp in seconds since epoch (Jan 1 1970 GMT) keeping track of when the node was last seen
1476    pub time: u64,
1477    /// The services offered
1478    pub services: usize,
1479    /// The address of the node
1480    pub address: String,
1481    /// The port of the node
1482    pub port: u16,
1483}
1484
1485#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1486pub struct ListBannedResult {
1487    pub address: String,
1488    pub banned_until: u64,
1489    pub ban_created: u64,
1490}
1491
1492/// Models the result of "estimatesmartfee"
1493#[derive(Clone, Debug, Deserialize, Serialize)]
1494pub struct EstimateSmartFeeResult {
1495    /// Estimate fee rate in BTC/kB.
1496    #[serde(
1497        default,
1498        rename = "feerate",
1499        skip_serializing_if = "Option::is_none",
1500        with = "bitcoin::amount::serde::as_btc::opt"
1501    )]
1502    pub fee_rate: Option<Amount>,
1503    /// Errors encountered during processing.
1504    pub errors: Option<Vec<String>>,
1505    /// Block number where estimate was found.
1506    pub blocks: i64,
1507}
1508
1509/// Models the result of "waitfornewblock", and "waitforblock"
1510#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1511pub struct BlockRef {
1512    pub hash: bitcoin::BlockHash,
1513    pub height: u64,
1514}
1515
1516/// Models the result of "getdescriptorinfo"
1517#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1518pub struct GetDescriptorInfoResult {
1519    pub descriptor: String,
1520    pub checksum: String,
1521    #[serde(rename = "isrange")]
1522    pub is_range: bool,
1523    #[serde(rename = "issolvable")]
1524    pub is_solvable: bool,
1525    #[serde(rename = "hasprivatekeys")]
1526    pub has_private_keys: bool,
1527}
1528
1529/// Models the request options of "getblocktemplate"
1530#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1531pub struct GetBlockTemplateOptions {
1532    pub mode: GetBlockTemplateModes,
1533    //// List of client side supported softfork deployment
1534    pub rules: Vec<GetBlockTemplateRules>,
1535    /// List of client side supported features
1536    pub capabilities: Vec<GetBlockTemplateCapabilities>,
1537}
1538
1539/// Enum to represent client-side supported features
1540#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1541#[serde(rename_all = "lowercase")]
1542pub enum GetBlockTemplateCapabilities {
1543    // No features supported yet. In the future this could be, for example, Proposal and Longpolling
1544}
1545
1546/// Enum to representing specific block rules that the requested template
1547/// should support.
1548#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1549#[serde(rename_all = "lowercase")]
1550pub enum GetBlockTemplateRules {
1551    SegWit,
1552    Signet,
1553    Csv,
1554    Taproot,
1555}
1556
1557/// Enum to represent client-side supported features.
1558#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1559#[serde(rename_all = "lowercase")]
1560pub enum GetBlockTemplateModes {
1561    /// Using this mode, the server build a block template and return it as
1562    /// response to the request. This is the default mode.
1563    Template,
1564    // TODO: Support for "proposal" mode is not yet implemented on the client
1565    // side.
1566}
1567
1568/// Models the result of "getblocktemplate"
1569#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1570pub struct GetBlockTemplateResult {
1571    /// The compressed difficulty in hexadecimal
1572    #[serde(with = "crate::serde_hex")]
1573    pub bits: Vec<u8>,
1574    /// The previous block hash the current template is mining on
1575    #[serde(rename = "previousblockhash")]
1576    pub previous_block_hash: bitcoin::BlockHash,
1577    /// The current time as seen by the server (recommended for block time)
1578    /// Note: this is not necessarily the system clock, and must fall within
1579    /// the mintime/maxtime rules. Expressed as UNIX timestamp.
1580    #[serde(rename = "curtime")]
1581    pub current_time: u64,
1582    /// The height of the block we will be mining: `current height + 1`
1583    pub height: u64,
1584    /// Block sigops limit
1585    #[serde(rename = "sigoplimit")]
1586    pub sigop_limit: u32,
1587    /// Block size limit
1588    #[serde(rename = "sizelimit")]
1589    pub size_limit: u32,
1590    /// Block weight limit
1591    #[serde(rename = "weightlimit")]
1592    pub weight_limit: u32,
1593    /// Block header version
1594    pub version: u32,
1595    /// Block rules that are to be enforced
1596    pub rules: Vec<GetBlockTemplateResultRules>,
1597    /// List of features the Bitcoin Core getblocktemplate implementation supports
1598    pub capabilities: Vec<GetBlockTemplateResultCapabilities>,
1599    /// Set of pending, supported versionbit (BIP 9) softfork deployments
1600    #[serde(rename = "vbavailable")]
1601    pub version_bits_available: HashMap<String, u32>,
1602    /// Bit mask of versionbits the server requires set in submissions
1603    #[serde(rename = "vbrequired")]
1604    pub version_bits_required: u32,
1605    /// Id used in longpoll requests for this template.
1606    pub longpollid: String,
1607    /// List of transactions included in the template block
1608    pub transactions: Vec<GetBlockTemplateResultTransaction>,
1609    /// The signet challenge. Only set if mining on a signet, otherwise empty
1610    #[serde(default, with = "bitcoin::script::ScriptBuf")]
1611    pub signet_challenge: bitcoin::script::ScriptBuf,
1612    /// The default witness commitment included in an OP_RETURN output of the
1613    /// coinbase transactions. Only set when mining on a network where SegWit
1614    /// is activated.
1615    #[serde(with = "bitcoin::script::ScriptBuf", default)]
1616    pub default_witness_commitment: bitcoin::script::ScriptBuf,
1617    /// Data that should be included in the coinbase's scriptSig content. Only
1618    /// the values (hexadecimal byte-for-byte) in this map should be included,
1619    /// not the keys. This does not include the block height, which is required
1620    /// to be included in the scriptSig by BIP 0034. It is advisable to encode
1621    /// values inside "PUSH" opcodes, so as to not inadvertently expend SIGOPs
1622    /// (which are counted toward limits, despite not being executed).
1623    pub coinbaseaux: HashMap<String, String>,
1624    /// Total funds available for the coinbase
1625    #[serde(rename = "coinbasevalue", with = "bitcoin::amount::serde::as_sat", default)]
1626    pub coinbase_value: Amount,
1627    /// The number which valid hashes must be less than, in big-endian
1628    #[serde(with = "crate::serde_hex")]
1629    pub target: Vec<u8>,
1630    /// The minimum timestamp appropriate for the next block time. Expressed as
1631    /// UNIX timestamp.
1632    #[serde(rename = "mintime")]
1633    pub min_time: u64,
1634    /// List of things that may be changed by the client before submitting a
1635    /// block
1636    pub mutable: Vec<GetBlockTemplateResulMutations>,
1637    /// A range of valid nonces
1638    #[serde(with = "crate::serde_hex", rename = "noncerange")]
1639    pub nonce_range: Vec<u8>,
1640}
1641
1642/// Models a single transaction entry in the result of "getblocktemplate"
1643#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1644pub struct GetBlockTemplateResultTransaction {
1645    /// The transaction id
1646    pub txid: bitcoin::Txid,
1647    /// The wtxid of the transaction
1648    #[serde(rename = "hash")]
1649    pub wtxid: bitcoin::Wtxid,
1650    /// The serilaized transaction bytes
1651    #[serde(with = "crate::serde_hex", rename = "data")]
1652    pub raw_tx: Vec<u8>,
1653    // The transaction fee
1654    #[serde(with = "bitcoin::amount::serde::as_sat")]
1655    pub fee: Amount,
1656    /// Transaction sigops
1657    pub sigops: u32,
1658    /// Transaction weight in weight units
1659    pub weight: usize,
1660    /// Transactions that must be in present in the final block if this one is.
1661    /// Indexed by a 1-based index in the `GetBlockTemplateResult.transactions`
1662    /// list
1663    pub depends: Vec<u32>,
1664}
1665
1666impl GetBlockTemplateResultTransaction {
1667    pub fn transaction(&self) -> Result<Transaction, encode::Error> {
1668        encode::deserialize(&self.raw_tx)
1669    }
1670}
1671
1672/// Enum to represent Bitcoin Core's supported features for getblocktemplate
1673#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1674#[serde(rename_all = "lowercase")]
1675pub enum GetBlockTemplateResultCapabilities {
1676    Proposal,
1677}
1678
1679/// Enum to representing specific block rules that client must support to work
1680/// with the template returned by Bitcoin Core
1681#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1682#[serde(rename_all = "lowercase")]
1683pub enum GetBlockTemplateResultRules {
1684    /// Inidcates that the client must support the SegWit rules when using this
1685    /// template.
1686    #[serde(alias = "!segwit")]
1687    SegWit,
1688    /// Indicates that the client must support the Signet rules when using this
1689    /// template.
1690    #[serde(alias = "!signet")]
1691    Signet,
1692    /// Indicates that the client must support the CSV rules when using this
1693    /// template.
1694    Csv,
1695    /// Indicates that the client must support the taproot rules when using this
1696    /// template.
1697    Taproot,
1698    /// Indicates that the client must support the Regtest rules when using this
1699    /// template. TestDummy is a test soft-fork only used on the regtest network.
1700    Testdummy,
1701}
1702
1703/// Enum to representing mutable parts of the block template. This does only
1704/// cover the muations implemented in Bitcoin Core. More mutations are defined
1705/// in [BIP-23](https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki#Mutations),
1706/// but not implemented in the getblocktemplate implementation of Bitcoin Core.
1707#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1708#[serde(rename_all = "lowercase")]
1709pub enum GetBlockTemplateResulMutations {
1710    /// The client is allowed to modify the time in the header of the block
1711    Time,
1712    /// The client is allowed to add transactions to the block
1713    Transactions,
1714    /// The client is allowed to use the work with other previous blocks.
1715    /// This implicitly allows removing transactions that are no longer valid.
1716    /// It also implies adjusting the "height" as necessary.
1717    #[serde(rename = "prevblock")]
1718    PreviousBlock,
1719}
1720
1721/// Models the result of "walletcreatefundedpsbt"
1722#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1723pub struct WalletCreateFundedPsbtResult {
1724    pub psbt: String,
1725    #[serde(with = "bitcoin::amount::serde::as_btc")]
1726    pub fee: Amount,
1727    #[serde(rename = "changepos")]
1728    pub change_position: i32,
1729}
1730
1731/// Models the result of "walletprocesspsbt"
1732#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1733pub struct WalletProcessPsbtResult {
1734    pub psbt: String,
1735    pub complete: bool,
1736}
1737
1738/// Models the request for "walletcreatefundedpsbt"
1739#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Default)]
1740pub struct WalletCreateFundedPsbtOptions {
1741    /// For a transaction with existing inputs, automatically include more if they are not enough (default true).
1742    /// Added in Bitcoin Core v0.21
1743    #[serde(skip_serializing_if = "Option::is_none")]
1744    pub add_inputs: Option<bool>,
1745    #[serde(rename = "changeAddress", skip_serializing_if = "Option::is_none")]
1746    pub change_address: Option<Address<NetworkUnchecked>>,
1747    #[serde(rename = "changePosition", skip_serializing_if = "Option::is_none")]
1748    pub change_position: Option<u16>,
1749    #[serde(skip_serializing_if = "Option::is_none")]
1750    pub change_type: Option<AddressType>,
1751    #[serde(rename = "includeWatching", skip_serializing_if = "Option::is_none")]
1752    pub include_watching: Option<bool>,
1753    #[serde(rename = "lockUnspents", skip_serializing_if = "Option::is_none")]
1754    pub lock_unspent: Option<bool>,
1755    #[serde(
1756        rename = "feeRate",
1757        skip_serializing_if = "Option::is_none",
1758        with = "bitcoin::amount::serde::as_btc::opt"
1759    )]
1760    pub fee_rate: Option<Amount>,
1761    #[serde(rename = "subtractFeeFromOutputs", skip_serializing_if = "Vec::is_empty")]
1762    pub subtract_fee_from_outputs: Vec<u16>,
1763    #[serde(skip_serializing_if = "Option::is_none")]
1764    pub replaceable: Option<bool>,
1765    #[serde(skip_serializing_if = "Option::is_none")]
1766    pub conf_target: Option<u16>,
1767    #[serde(skip_serializing_if = "Option::is_none")]
1768    pub estimate_mode: Option<EstimateMode>,
1769}
1770
1771/// Models the result of "finalizepsbt"
1772#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1773pub struct FinalizePsbtResult {
1774    pub psbt: Option<String>,
1775    #[serde(default, with = "crate::serde_hex::opt")]
1776    pub hex: Option<Vec<u8>>,
1777    pub complete: bool,
1778}
1779
1780/// Model for decode transaction
1781#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1782pub struct DecodeRawTransactionResult {
1783    pub txid: bitcoin::Txid,
1784    pub hash: bitcoin::Wtxid,
1785    pub size: u32,
1786    pub vsize: u32,
1787    pub weight: u32,
1788    pub version: u32,
1789    pub locktime: u32,
1790    pub vin: Vec<GetRawTransactionResultVin>,
1791    pub vout: Vec<GetRawTransactionResultVout>,
1792}
1793
1794/// Models the result of "getchaintips"
1795pub type GetChainTipsResult = Vec<GetChainTipsResultTip>;
1796
1797/// Models a single chain tip for the result of "getchaintips"
1798#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1799pub struct GetChainTipsResultTip {
1800    /// Block height of the chain tip
1801    pub height: u64,
1802    /// Header hash of the chain tip
1803    pub hash: bitcoin::BlockHash,
1804    /// Length of the branch (number of blocks since the last common block)
1805    #[serde(rename = "branchlen")]
1806    pub branch_length: usize,
1807    /// Status of the tip as seen by Bitcoin Core
1808    pub status: GetChainTipsResultStatus,
1809}
1810
1811#[derive(Copy, Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
1812#[serde(rename_all = "lowercase")]
1813pub enum GetChainTipsResultStatus {
1814    /// The branch contains at least one invalid block
1815    Invalid,
1816    /// Not all blocks for this branch are available, but the headers are valid
1817    #[serde(rename = "headers-only")]
1818    HeadersOnly,
1819    /// All blocks are available for this branch, but they were never fully validated
1820    #[serde(rename = "valid-headers")]
1821    ValidHeaders,
1822    /// This branch is not part of the active chain, but is fully validated
1823    #[serde(rename = "valid-fork")]
1824    ValidFork,
1825    /// This is the tip of the active main chain, which is certainly valid
1826    Active,
1827}
1828
1829impl FinalizePsbtResult {
1830    pub fn transaction(&self) -> Option<Result<Transaction, encode::Error>> {
1831        self.hex.as_ref().map(|h| encode::deserialize(h))
1832    }
1833}
1834
1835// Custom types for input arguments.
1836
1837#[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, PartialEq, Hash)]
1838#[serde(rename_all = "UPPERCASE")]
1839pub enum EstimateMode {
1840    Unset,
1841    Economical,
1842    Conservative,
1843}
1844
1845/// A wrapper around bitcoin::EcdsaSighashType that will be serialized
1846/// according to what the RPC expects.
1847pub struct SigHashType(bitcoin::sighash::EcdsaSighashType);
1848
1849impl From<bitcoin::sighash::EcdsaSighashType> for SigHashType {
1850    fn from(sht: bitcoin::sighash::EcdsaSighashType) -> SigHashType {
1851        SigHashType(sht)
1852    }
1853}
1854
1855impl serde::Serialize for SigHashType {
1856    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1857    where
1858        S: serde::Serializer,
1859    {
1860        serializer.serialize_str(match self.0 {
1861            bitcoin::sighash::EcdsaSighashType::All => "ALL",
1862            bitcoin::sighash::EcdsaSighashType::None => "NONE",
1863            bitcoin::sighash::EcdsaSighashType::Single => "SINGLE",
1864            bitcoin::sighash::EcdsaSighashType::AllPlusAnyoneCanPay => "ALL|ANYONECANPAY",
1865            bitcoin::sighash::EcdsaSighashType::NonePlusAnyoneCanPay => "NONE|ANYONECANPAY",
1866            bitcoin::sighash::EcdsaSighashType::SinglePlusAnyoneCanPay => "SINGLE|ANYONECANPAY",
1867        })
1868    }
1869}
1870
1871// Used for createrawtransaction argument.
1872#[derive(Serialize, Clone, PartialEq, Eq, Debug, Deserialize)]
1873#[serde(rename_all = "camelCase")]
1874pub struct CreateRawTransactionInput {
1875    pub txid: bitcoin::Txid,
1876    pub vout: u32,
1877    #[serde(skip_serializing_if = "Option::is_none")]
1878    pub sequence: Option<u32>,
1879}
1880
1881#[derive(Serialize, Clone, PartialEq, Eq, Debug, Default)]
1882#[serde(rename_all = "camelCase")]
1883pub struct FundRawTransactionOptions {
1884    /// For a transaction with existing inputs, automatically include more if they are not enough (default true).
1885    /// Added in Bitcoin Core v0.21
1886    #[serde(rename = "add_inputs", skip_serializing_if = "Option::is_none")]
1887    pub add_inputs: Option<bool>,
1888    #[serde(skip_serializing_if = "Option::is_none")]
1889    pub change_address: Option<Address>,
1890    #[serde(skip_serializing_if = "Option::is_none")]
1891    pub change_position: Option<u32>,
1892    #[serde(rename = "change_type", skip_serializing_if = "Option::is_none")]
1893    pub change_type: Option<AddressType>,
1894    #[serde(skip_serializing_if = "Option::is_none")]
1895    pub include_watching: Option<bool>,
1896    #[serde(skip_serializing_if = "Option::is_none")]
1897    pub lock_unspents: Option<bool>,
1898    #[serde(with = "bitcoin::amount::serde::as_btc::opt", skip_serializing_if = "Option::is_none")]
1899    pub fee_rate: Option<Amount>,
1900    #[serde(skip_serializing_if = "Option::is_none")]
1901    pub subtract_fee_from_outputs: Option<Vec<u32>>,
1902    #[serde(skip_serializing_if = "Option::is_none")]
1903    pub replaceable: Option<bool>,
1904    #[serde(rename = "conf_target", skip_serializing_if = "Option::is_none")]
1905    pub conf_target: Option<u32>,
1906    #[serde(rename = "estimate_mode", skip_serializing_if = "Option::is_none")]
1907    pub estimate_mode: Option<EstimateMode>,
1908}
1909
1910#[derive(Deserialize, Clone, PartialEq, Eq, Debug)]
1911#[serde(rename_all = "camelCase")]
1912pub struct FundRawTransactionResult {
1913    #[serde(with = "crate::serde_hex")]
1914    pub hex: Vec<u8>,
1915    #[serde(with = "bitcoin::amount::serde::as_btc")]
1916    pub fee: Amount,
1917    #[serde(rename = "changepos")]
1918    pub change_position: i32,
1919}
1920
1921#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, Debug)]
1922pub struct GetBalancesResultEntry {
1923    #[serde(with = "bitcoin::amount::serde::as_btc")]
1924    pub trusted: Amount,
1925    #[serde(with = "bitcoin::amount::serde::as_btc")]
1926    pub untrusted_pending: Amount,
1927    #[serde(with = "bitcoin::amount::serde::as_btc")]
1928    pub immature: Amount,
1929}
1930
1931#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, Debug)]
1932#[serde(rename_all = "camelCase")]
1933pub struct GetBalancesResult {
1934    pub mine: GetBalancesResultEntry,
1935    pub watchonly: Option<GetBalancesResultEntry>,
1936}
1937
1938impl FundRawTransactionResult {
1939    pub fn transaction(&self) -> Result<Transaction, encode::Error> {
1940        encode::deserialize(&self.hex)
1941    }
1942}
1943
1944// Used for signrawtransaction argument.
1945#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
1946#[serde(rename_all = "camelCase")]
1947pub struct SignRawTransactionInput {
1948    pub txid: bitcoin::Txid,
1949    pub vout: u32,
1950    pub script_pub_key: ScriptBuf,
1951    #[serde(skip_serializing_if = "Option::is_none")]
1952    pub redeem_script: Option<ScriptBuf>,
1953    #[serde(
1954        default,
1955        skip_serializing_if = "Option::is_none",
1956        with = "bitcoin::amount::serde::as_btc::opt"
1957    )]
1958    pub amount: Option<Amount>,
1959}
1960
1961/// Used to represent UTXO set hash type
1962#[derive(Clone, Serialize, PartialEq, Eq, Debug)]
1963#[serde(rename_all = "snake_case")]
1964pub enum TxOutSetHashType {
1965    HashSerialized2,
1966    Muhash,
1967    None,
1968}
1969
1970/// Used to specify a block hash or a height
1971#[derive(Clone, Serialize, PartialEq, Eq, Debug)]
1972#[serde(untagged)]
1973pub enum HashOrHeight {
1974    BlockHash(bitcoin::BlockHash),
1975    Height(u64),
1976}
1977
1978#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1979pub struct GetTxOutSetInfoResult {
1980    /// The block height (index) of the returned statistics
1981    pub height: u64,
1982    /// The hash of the block at which these statistics are calculated
1983    #[serde(rename = "bestblock")]
1984    pub best_block: bitcoin::BlockHash,
1985    /// The number of transactions with unspent outputs (not available when coinstatsindex is used)
1986    #[serde(default, skip_serializing_if = "Option::is_none")]
1987    pub transactions: Option<u64>,
1988    /// The number of unspent transaction outputs
1989    #[serde(rename = "txouts")]
1990    pub tx_outs: u64,
1991    /// A meaningless metric for UTXO set size
1992    pub bogosize: u64,
1993    /// The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)
1994    #[serde(default, skip_serializing_if = "Option::is_none")]
1995    pub hash_serialized_2: Option<sha256::Hash>,
1996    /// The serialized hash (only present if 'muhash' hash_type is chosen)
1997    #[serde(default, skip_serializing_if = "Option::is_none")]
1998    pub muhash: Option<sha256::Hash>,
1999    /// The estimated size of the chainstate on disk (not available when coinstatsindex is used)
2000    #[serde(default, skip_serializing_if = "Option::is_none")]
2001    pub disk_size: Option<u64>,
2002    /// The total amount
2003    #[serde(with = "bitcoin::amount::serde::as_btc")]
2004    pub total_amount: Amount,
2005    /// The total amount of coins permanently excluded from the UTXO set (only available if coinstatsindex is used)
2006    #[serde(
2007        default,
2008        skip_serializing_if = "Option::is_none",
2009        with = "bitcoin::amount::serde::as_btc::opt"
2010    )]
2011    pub total_unspendable_amount: Option<Amount>,
2012    /// Info on amounts in the block at this block height (only available if coinstatsindex is used)
2013    #[serde(default, skip_serializing_if = "Option::is_none")]
2014    pub block_info: Option<BlockInfo>,
2015}
2016
2017/// Info on amounts in the block at the block height of the `gettxoutsetinfo` call (only available if coinstatsindex is used)
2018#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
2019pub struct BlockInfo {
2020    /// Amount of previous outputs spent
2021    #[serde(with = "bitcoin::amount::serde::as_btc")]
2022    pub prevout_spent: Amount,
2023    /// Output size of the coinbase transaction
2024    #[serde(with = "bitcoin::amount::serde::as_btc")]
2025    pub coinbase: Amount,
2026    /// Newly-created outputs
2027    #[serde(with = "bitcoin::amount::serde::as_btc")]
2028    pub new_outputs_ex_coinbase: Amount,
2029    /// Amount of unspendable outputs
2030    #[serde(with = "bitcoin::amount::serde::as_btc")]
2031    pub unspendable: Amount,
2032    /// Detailed view of the unspendable categories
2033    pub unspendables: Unspendables,
2034}
2035
2036/// Detailed view of the unspendable categories
2037#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
2038pub struct Unspendables {
2039    /// Unspendable coins from the Genesis block
2040    #[serde(with = "bitcoin::amount::serde::as_btc")]
2041    pub genesis_block: Amount,
2042    /// Transactions overridden by duplicates (no longer possible with BIP30)
2043    #[serde(with = "bitcoin::amount::serde::as_btc")]
2044    pub bip30: Amount,
2045    /// Amounts sent to scripts that are unspendable (for example OP_RETURN outputs)
2046    #[serde(with = "bitcoin::amount::serde::as_btc")]
2047    pub scripts: Amount,
2048    /// Fee rewards that miners did not claim in their coinbase transaction
2049    #[serde(with = "bitcoin::amount::serde::as_btc")]
2050    pub unclaimed_rewards: Amount,
2051}
2052
2053#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
2054pub struct GetNetTotalsResult {
2055    /// Total bytes received
2056    #[serde(rename = "totalbytesrecv")]
2057    pub total_bytes_recv: u64,
2058    /// Total bytes sent
2059    #[serde(rename = "totalbytessent")]
2060    pub total_bytes_sent: u64,
2061    /// Current UNIX time in milliseconds
2062    #[serde(rename = "timemillis")]
2063    pub time_millis: u64,
2064    /// Upload target statistics
2065    #[serde(rename = "uploadtarget")]
2066    pub upload_target: GetNetTotalsResultUploadTarget,
2067}
2068
2069#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
2070pub struct GetNetTotalsResultUploadTarget {
2071    /// Length of the measuring timeframe in seconds
2072    #[serde(rename = "timeframe")]
2073    pub time_frame: u64,
2074    /// Target in bytes
2075    pub target: u64,
2076    /// True if target is reached
2077    pub target_reached: bool,
2078    /// True if serving historical blocks
2079    pub serve_historical_blocks: bool,
2080    /// Bytes left in current time cycle
2081    pub bytes_left_in_cycle: u64,
2082    /// Seconds left in current time cycle
2083    pub time_left_in_cycle: u64,
2084}
2085
2086/// Used to represent an address type.
2087#[derive(Copy, Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
2088#[serde(rename_all = "kebab-case")]
2089pub enum AddressType {
2090    Legacy,
2091    P2shSegwit,
2092    Bech32,
2093    Bech32m,
2094}
2095
2096/// Used to represent arguments that can either be an address or a public key.
2097#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
2098pub enum PubKeyOrAddress<'a> {
2099    Address(&'a Address),
2100    PubKey(&'a PublicKey),
2101}
2102
2103#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
2104#[serde(untagged)]
2105/// Start a scan of the UTXO set for an [output descriptor](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md).
2106pub enum ScanTxOutRequest {
2107    /// Scan for a single descriptor
2108    Single(String),
2109    /// Scan for a descriptor with xpubs
2110    Extended {
2111        /// Descriptor
2112        desc: String,
2113        /// Range of the xpub derivations to scan
2114        range: (u64, u64),
2115    },
2116}
2117
2118#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
2119pub struct ScanTxOutResult {
2120    pub success: Option<bool>,
2121    #[serde(rename = "txouts")]
2122    pub tx_outs: Option<u64>,
2123    pub height: Option<u64>,
2124    #[serde(rename = "bestblock")]
2125    pub best_block_hash: Option<bitcoin::BlockHash>,
2126    pub unspents: Vec<Utxo>,
2127    #[serde(with = "bitcoin::amount::serde::as_btc")]
2128    pub total_amount: bitcoin::Amount,
2129}
2130
2131#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
2132#[serde(rename_all = "camelCase")]
2133pub struct Utxo {
2134    pub txid: bitcoin::Txid,
2135    pub vout: u32,
2136    pub script_pub_key: bitcoin::ScriptBuf,
2137    #[serde(rename = "desc")]
2138    pub descriptor: String,
2139    #[serde(with = "bitcoin::amount::serde::as_btc")]
2140    pub amount: bitcoin::Amount,
2141    pub height: u64,
2142}
2143
2144#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
2145pub struct IndexStatus {
2146    pub synced: bool,
2147    pub best_block_height: u32,
2148}
2149
2150#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
2151pub struct GetIndexInfoResult {
2152    pub txindex: Option<IndexStatus>,
2153    pub coinstatsindex: Option<IndexStatus>,
2154    #[serde(rename = "basic block filter index")]
2155    pub basic_block_filter_index: Option<IndexStatus>,
2156}
2157
2158impl<'a> serde::Serialize for PubKeyOrAddress<'a> {
2159    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2160    where
2161        S: serde::Serializer,
2162    {
2163        match *self {
2164            PubKeyOrAddress::Address(a) => serde::Serialize::serialize(a, serializer),
2165            PubKeyOrAddress::PubKey(k) => serde::Serialize::serialize(k, serializer),
2166        }
2167    }
2168}
2169
2170// Custom deserializer functions.
2171
2172/// deserialize_hex_array_opt deserializes a vector of hex-encoded byte arrays.
2173fn deserialize_hex_array_opt<'de, D>(deserializer: D) -> Result<Option<Vec<Vec<u8>>>, D::Error>
2174where
2175    D: serde::Deserializer<'de>,
2176{
2177    //TODO(stevenroose) Revisit when issue is fixed:
2178    // https://github.com/serde-rs/serde/issues/723
2179
2180    let v: Vec<String> = Vec::deserialize(deserializer)?;
2181    let mut res = Vec::new();
2182    for h in v.into_iter() {
2183        res.push(FromHex::from_hex(&h).map_err(D::Error::custom)?);
2184    }
2185    Ok(Some(res))
2186}
2187
2188#[cfg(test)]
2189mod tests {
2190    use super::*;
2191
2192    #[test]
2193    fn test_softfork_type() {
2194        let buried: SoftforkType = serde_json::from_str("\"buried\"").unwrap();
2195        assert_eq!(buried, SoftforkType::Buried);
2196        let bip9: SoftforkType = serde_json::from_str("\"bip9\"").unwrap();
2197        assert_eq!(bip9, SoftforkType::Bip9);
2198        let other: SoftforkType = serde_json::from_str("\"bip8\"").unwrap();
2199        assert_eq!(other, SoftforkType::Other);
2200    }
2201}