1use std::collections::BTreeMap;
2
3use bitcoin::{
4 absolute::Height,
5 address::{self, NetworkUnchecked},
6 block::Header,
7 consensus::{self, encode},
8 Address, Amount, Block, BlockHash, SignedAmount, Transaction, Txid, Wtxid,
9};
10use serde::{
11 de::{self, IntoDeserializer, Visitor},
12 Deserialize, Deserializer, Serialize,
13};
14use tracing::*;
15
16use crate::error::SignRawTransactionWithWalletError;
17
18#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
28#[serde(rename_all = "lowercase")]
29pub enum TransactionCategory {
30 Send,
32 Receive,
34 Generate,
36 Immature,
38 Orphan,
40}
41
42#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
48pub struct GetBlockchainInfo {
49 pub chain: String,
51 pub blocks: u64,
53 pub headers: u64,
55 #[serde(rename = "bestblockhash")]
57 pub best_block_hash: String,
58 pub difficulty: f64,
60 #[serde(rename = "mediantime")]
62 pub median_time: u64,
63 #[serde(rename = "verificationprogress")]
65 pub verification_progress: f64,
66 #[serde(rename = "initialblockdownload")]
68 pub initial_block_download: bool,
69 #[serde(rename = "chainwork")]
71 pub chain_work: String,
72 pub size_on_disk: u64,
74 pub pruned: bool,
76 #[serde(rename = "pruneheight")]
78 pub prune_height: Option<u64>,
79 pub automatic_pruning: Option<bool>,
81 pub prune_target_size: Option<u64>,
83}
84
85#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
91pub struct GetBlockHeaderVerbosityZero(pub String);
92
93impl GetBlockHeaderVerbosityZero {
94 pub fn header(self) -> Result<Header, encode::FromHexError> {
96 let header: Header = encode::deserialize_hex(&self.0)?;
97 Ok(header)
98 }
99}
100
101#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
107pub struct GetBlockVerbosityZero(pub String);
108
109impl GetBlockVerbosityZero {
110 pub fn block(self) -> Result<Block, encode::FromHexError> {
112 let block: Block = encode::deserialize_hex(&self.0)?;
113 Ok(block)
114 }
115}
116
117#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
119pub struct GetBlockVerbosityOne {
120 pub hash: String,
122 pub confirmations: i32,
124 pub size: usize,
126 #[serde(rename = "strippedsize")]
128 pub stripped_size: Option<usize>,
129 pub weight: u64,
131 pub height: usize,
133 pub version: i32,
135 #[serde(rename = "versionHex")]
137 pub version_hex: String,
138 #[serde(rename = "merkleroot")]
140 pub merkle_root: String,
141 pub tx: Vec<String>,
143 pub time: usize,
145 #[serde(rename = "mediantime")]
147 pub median_time: Option<usize>,
148 pub nonce: u32,
150 pub bits: String,
152 pub difficulty: f64,
154 #[serde(rename = "chainwork")]
156 pub chain_work: String,
157 #[serde(rename = "nTx")]
159 pub n_tx: u32,
160 #[serde(rename = "previousblockhash")]
162 pub previous_block_hash: Option<String>,
163 #[serde(rename = "nextblockhash")]
165 pub next_block_hash: Option<String>,
166}
167
168#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
174pub struct GetRawTransactionVerbosityZero(pub String);
175
176impl GetRawTransactionVerbosityZero {
177 pub fn transaction(self) -> Result<Transaction, encode::FromHexError> {
179 let transaction: Transaction = encode::deserialize_hex(&self.0)?;
180 Ok(transaction)
181 }
182}
183
184#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
188pub struct GetRawTransactionVerbosityOne {
189 pub in_active_chain: Option<bool>,
190 #[serde(deserialize_with = "deserialize_tx")]
191 #[serde(rename = "hex")]
192 pub transaction: Transaction,
193 pub txid: Txid,
194 pub hash: Wtxid,
195 pub size: usize,
196 pub vsize: usize,
197 pub version: u32,
198 pub locktime: u32,
199 pub blockhash: Option<BlockHash>,
200 pub confirmations: Option<u32>,
201 pub time: Option<usize>,
202 pub blocktime: Option<usize>,
203}
204
205#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
215pub struct GetTxOut {
216 #[serde(rename = "bestblock")]
218 pub best_block: String,
219 pub confirmations: u32, pub value: f64,
223 #[serde(rename = "scriptPubkey")]
225 pub script_pubkey: Option<ScriptPubkey>,
226 pub coinbase: bool,
228}
229
230#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
232pub struct ScriptPubkey {
233 pub asm: String,
235 pub hex: String,
237 #[serde(rename = "reqSigs")]
238 pub req_sigs: i64,
239 #[serde(rename = "type")]
241 pub type_: String,
242 pub address: Option<String>,
244}
245
246#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
252pub struct CreateRawTransaction {
253 pub inputs: Vec<CreateRawTransactionInput>,
254 pub outputs: Vec<CreateRawTransactionOutput>,
255}
256
257#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
259pub struct CreateRawTransactionInput {
260 pub txid: String,
261 pub vout: u32,
262}
263
264#[derive(Clone, Debug, PartialEq, Deserialize)]
269#[serde(untagged)]
270pub enum CreateRawTransactionOutput {
271 AddressAmount {
273 address: String,
275 amount: f64,
277 },
278 Data {
280 data: String,
282 },
283}
284
285impl Serialize for CreateRawTransactionOutput {
286 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
287 where
288 S: serde::Serializer,
289 {
290 match self {
291 CreateRawTransactionOutput::AddressAmount { address, amount } => {
292 let mut map = serde_json::Map::new();
293 map.insert(
294 address.clone(),
295 serde_json::Value::Number(serde_json::Number::from_f64(*amount).unwrap()),
296 );
297 map.serialize(serializer)
298 }
299 CreateRawTransactionOutput::Data { data } => {
300 let mut map = serde_json::Map::new();
301 map.insert("data".to_string(), serde_json::Value::String(data.clone()));
302 map.serialize(serializer)
303 }
304 }
305 }
306}
307
308#[allow(clippy::doc_lazy_continuation)]
330#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
331pub struct SubmitPackage {
332 pub package_msg: String,
336 #[serde(rename = "tx-results")]
338 pub tx_results: BTreeMap<String, SubmitPackageTxResult>,
339 #[serde(rename = "replaced-transactions")]
341 pub replaced_transactions: Vec<String>,
342}
343
344#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
346pub struct SubmitPackageTxResult {
347 pub txid: String,
349 #[serde(rename = "other-wtxid")]
354 pub other_wtxid: Option<String>,
355 pub vsize: i64,
357 pub fees: Option<SubmitPackageTxResultFees>,
359 pub error: Option<String>,
361}
362
363#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
365pub struct SubmitPackageTxResultFees {
366 #[serde(rename = "base")]
368 pub base_fee: f64,
369 #[serde(rename = "effective-feerate")]
374 pub effective_fee_rate: Option<f64>,
375 #[serde(rename = "effective-includes")]
378 pub effective_includes: Option<Vec<String>>,
379}
380
381#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
388pub struct GetTransactionDetail {
389 pub address: String,
390 pub category: GetTransactionDetailCategory,
391 pub amount: f64,
392 pub label: Option<String>,
393 pub vout: u32,
394 pub fee: Option<f64>,
395 pub abandoned: Option<bool>,
396}
397
398#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
400#[serde(rename_all = "lowercase")]
401pub enum GetTransactionDetailCategory {
402 Send,
403 Receive,
404 Generate,
405 Immature,
406 Orphan,
407}
408
409#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
416pub struct GetNewAddress(pub String);
417
418impl GetNewAddress {
419 pub fn address(self) -> Result<Address<NetworkUnchecked>, address::ParseError> {
421 let address = self.0.parse::<Address<_>>()?;
422 Ok(address)
423 }
424}
425
426#[derive(Clone, Debug, PartialEq, Deserialize)]
437pub struct GetTransaction {
438 #[serde(deserialize_with = "deserialize_signed_bitcoin")]
440 pub amount: SignedAmount,
441 pub confirmations: u64,
443 pub generated: Option<bool>,
444 pub trusted: Option<bool>,
445 pub blockhash: Option<String>,
446 pub blockheight: Option<u64>,
447 pub blockindex: Option<u32>,
448 pub blocktime: Option<u64>,
449 #[serde(deserialize_with = "deserialize_txid")]
451 pub txid: Txid,
452 pub wtxid: String,
453 pub walletconflicts: Vec<String>,
454 pub replaced_by_txid: Option<String>,
455 pub replaces_txid: Option<String>,
456 pub comment: Option<String>,
457 pub to: Option<String>,
458 pub time: u64,
459 pub timereceived: u64,
460 #[serde(rename = "bip125-replaceable")]
461 pub bip125_replaceable: String,
462 pub details: Vec<GetTransactionDetail>,
463 #[serde(deserialize_with = "deserialize_tx")]
465 pub hex: Transaction,
466}
467
468impl GetTransaction {
469 pub fn block_height(&self) -> u64 {
470 if self.confirmations == 0 {
471 return 0;
472 }
473 self.blockheight.unwrap_or_else(|| {
474 warn!("Txn confirmed but did not obtain blockheight. Setting height to zero");
475 0
476 })
477 }
478}
479
480#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
487pub struct ListUnspent {
488 #[serde(deserialize_with = "deserialize_txid")]
490 pub txid: Txid,
491 pub vout: u32,
493 #[serde(deserialize_with = "deserialize_address")]
495 pub address: Address<NetworkUnchecked>,
496 pub label: Option<String>,
498 #[serde(rename = "scriptPubKey")]
500 pub script_pubkey: String,
501 #[serde(deserialize_with = "deserialize_bitcoin")]
503 pub amount: Amount,
504 pub confirmations: u32,
506 pub spendable: bool,
508 pub solvable: bool,
510 pub safe: bool,
515}
516
517#[derive(Clone, Debug, PartialEq, Deserialize)]
528pub struct ListTransactions {
529 #[serde(deserialize_with = "deserialize_address")]
531 pub address: Address<NetworkUnchecked>,
532 category: TransactionCategory,
534 #[serde(deserialize_with = "deserialize_signed_bitcoin")]
536 pub amount: SignedAmount,
537 pub label: Option<String>,
539 pub confirmations: u32,
541 pub trusted: Option<bool>,
542 pub generated: Option<bool>,
543 pub blockhash: Option<String>,
544 pub blockheight: Option<u64>,
545 pub blockindex: Option<u32>,
546 pub blocktime: Option<u64>,
547 #[serde(deserialize_with = "deserialize_txid")]
549 pub txid: Txid,
550}
551
552#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
554pub struct TestMempoolAccept {
555 #[serde(deserialize_with = "deserialize_txid")]
557 pub txid: Txid,
558 pub reject_reason: Option<String>,
560}
561
562#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
569pub struct SignRawTransactionWithWallet {
570 pub hex: String,
572 pub complete: bool,
574 pub errors: Option<Vec<SignRawTransactionWithWalletError>>,
576}
577
578#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
599pub struct PreviousTransactionOutput {
600 #[serde(deserialize_with = "deserialize_txid")]
602 pub txid: Txid,
603 pub vout: u32,
605 #[serde(rename = "scriptPubKey")]
607 pub script_pubkey: String,
608 #[serde(rename = "redeemScript")]
610 pub redeem_script: Option<String>,
611 #[serde(rename = "witnessScript")]
613 pub witness_script: Option<String>,
614 pub amount: Option<f64>,
616}
617
618#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
620pub struct ListDescriptors {
621 pub descriptors: Vec<ListDescriptor>,
623}
624
625#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
627pub struct ListDescriptor {
628 pub desc: String,
630}
631
632#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
634pub struct ImportDescriptors {
635 pub descriptors: Vec<ListDescriptor>,
637}
638
639#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
641pub struct ImportDescriptor {
642 pub desc: String,
644 pub active: Option<bool>,
647 pub timestamp: String,
650}
651#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
653pub struct ImportDescriptorResult {
654 pub success: bool,
656}
657
658#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
664pub struct CreateWallet {
665 pub wallet_name: String,
667 pub load_on_startup: Option<bool>,
669}
670
671fn deserialize_bitcoin<'d, D>(deserializer: D) -> Result<Amount, D::Error>
673where
674 D: Deserializer<'d>,
675{
676 struct SatVisitor;
677
678 impl Visitor<'_> for SatVisitor {
679 type Value = Amount;
680
681 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
682 write!(formatter, "a float representation of btc values expected")
683 }
684
685 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
686 where
687 E: de::Error,
688 {
689 let amount = Amount::from_btc(v).expect("Amount deserialization failed");
690 Ok(amount)
691 }
692 }
693 deserializer.deserialize_any(SatVisitor)
694}
695
696fn deserialize_signed_bitcoin<'d, D>(deserializer: D) -> Result<SignedAmount, D::Error>
698where
699 D: Deserializer<'d>,
700{
701 struct SatVisitor;
702
703 impl Visitor<'_> for SatVisitor {
704 type Value = SignedAmount;
705
706 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
707 write!(formatter, "a float representation of btc values expected")
708 }
709
710 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
711 where
712 E: de::Error,
713 {
714 let signed_amount = SignedAmount::from_btc(v).expect("Amount deserialization failed");
715 Ok(signed_amount)
716 }
717 }
718 deserializer.deserialize_any(SatVisitor)
719}
720
721#[expect(dead_code)]
723fn deserialize_signed_bitcoin_option<'d, D>(
724 deserializer: D,
725) -> Result<Option<SignedAmount>, D::Error>
726where
727 D: Deserializer<'d>,
728{
729 let f: Option<f64> = Option::deserialize(deserializer)?;
730 match f {
731 Some(v) => deserialize_signed_bitcoin(v.into_deserializer()).map(Some),
732 None => Ok(None),
733 }
734}
735
736fn deserialize_txid<'d, D>(deserializer: D) -> Result<Txid, D::Error>
738where
739 D: Deserializer<'d>,
740{
741 struct TxidVisitor;
742
743 impl Visitor<'_> for TxidVisitor {
744 type Value = Txid;
745
746 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
747 write!(formatter, "a transaction id string expected")
748 }
749
750 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
751 where
752 E: de::Error,
753 {
754 let txid = v.parse::<Txid>().expect("invalid txid");
755
756 Ok(txid)
757 }
758 }
759 deserializer.deserialize_any(TxidVisitor)
760}
761
762fn deserialize_tx<'d, D>(deserializer: D) -> Result<Transaction, D::Error>
764where
765 D: Deserializer<'d>,
766{
767 struct TxVisitor;
768
769 impl Visitor<'_> for TxVisitor {
770 type Value = Transaction;
771
772 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
773 write!(formatter, "a transaction hex string expected")
774 }
775
776 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
777 where
778 E: de::Error,
779 {
780 let tx = consensus::encode::deserialize_hex::<Transaction>(v)
781 .expect("failed to deserialize tx hex");
782 Ok(tx)
783 }
784 }
785 deserializer.deserialize_any(TxVisitor)
786}
787
788fn deserialize_address<'d, D>(deserializer: D) -> Result<Address<NetworkUnchecked>, D::Error>
795where
796 D: Deserializer<'d>,
797{
798 struct AddressVisitor;
799 impl Visitor<'_> for AddressVisitor {
800 type Value = Address<NetworkUnchecked>;
801
802 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
803 write!(formatter, "a Bitcoin address string expected")
804 }
805
806 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
807 where
808 E: de::Error,
809 {
810 let address = v
811 .parse::<Address<_>>()
812 .expect("Address deserialization failed");
813 Ok(address)
814 }
815 }
816 deserializer.deserialize_any(AddressVisitor)
817}
818
819#[expect(dead_code)]
821fn deserialize_blockhash<'d, D>(deserializer: D) -> Result<BlockHash, D::Error>
822where
823 D: Deserializer<'d>,
824{
825 struct BlockHashVisitor;
826
827 impl Visitor<'_> for BlockHashVisitor {
828 type Value = BlockHash;
829
830 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
831 write!(formatter, "a blockhash string expected")
832 }
833
834 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
835 where
836 E: de::Error,
837 {
838 let blockhash = consensus::encode::deserialize_hex::<BlockHash>(v)
839 .expect("BlockHash deserialization failed");
840 Ok(blockhash)
841 }
842 }
843 deserializer.deserialize_any(BlockHashVisitor)
844}
845
846#[expect(dead_code)]
848fn deserialize_height<'d, D>(deserializer: D) -> Result<Height, D::Error>
849where
850 D: Deserializer<'d>,
851{
852 struct HeightVisitor;
853
854 impl Visitor<'_> for HeightVisitor {
855 type Value = Height;
856
857 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
858 write!(formatter, "a height u32 string expected")
859 }
860
861 fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
862 where
863 E: de::Error,
864 {
865 let height = Height::from_consensus(v).expect("Height deserialization failed");
866 Ok(height)
867 }
868 }
869 deserializer.deserialize_any(HeightVisitor)
870}