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