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, Debug, PartialEq, Deserialize, Serialize)]
188pub struct GetMempoolInfo {
189 pub loaded: bool,
190 pub size: usize,
191 pub bytes: usize,
192 pub usage: usize,
193 pub maxmempool: usize,
194 pub mempoolminfee: f64,
195 pub minrelaytxfee: f64,
196 pub unbroadcastcount: usize,
197}
198
199#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
203pub struct GetRawTransactionVerbosityOne {
204 pub in_active_chain: Option<bool>,
205 #[serde(deserialize_with = "deserialize_tx")]
206 #[serde(rename = "hex")]
207 pub transaction: Transaction,
208 pub txid: Txid,
209 pub hash: Wtxid,
210 pub size: usize,
211 pub vsize: usize,
212 pub version: u32,
213 pub locktime: u32,
214 pub blockhash: Option<BlockHash>,
215 pub confirmations: Option<u32>,
216 pub time: Option<usize>,
217 pub blocktime: Option<usize>,
218}
219
220#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
230pub struct GetTxOut {
231 #[serde(rename = "bestblock")]
233 pub best_block: String,
234 pub confirmations: u32, pub value: f64,
238 #[serde(rename = "scriptPubkey")]
240 pub script_pubkey: Option<ScriptPubkey>,
241 pub coinbase: bool,
243}
244
245#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
247pub struct ScriptPubkey {
248 pub asm: String,
250 pub hex: String,
252 #[serde(rename = "reqSigs")]
253 pub req_sigs: i64,
254 #[serde(rename = "type")]
256 pub type_: String,
257 pub address: Option<String>,
259}
260
261#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
267pub struct CreateRawTransaction {
268 pub inputs: Vec<CreateRawTransactionInput>,
269 pub outputs: Vec<CreateRawTransactionOutput>,
270}
271
272#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
274pub struct CreateRawTransactionInput {
275 pub txid: String,
276 pub vout: u32,
277}
278
279#[derive(Clone, Debug, PartialEq, Deserialize)]
284#[serde(untagged)]
285pub enum CreateRawTransactionOutput {
286 AddressAmount {
288 address: String,
290 amount: f64,
292 },
293 Data {
295 data: String,
297 },
298}
299
300impl Serialize for CreateRawTransactionOutput {
301 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
302 where
303 S: serde::Serializer,
304 {
305 match self {
306 CreateRawTransactionOutput::AddressAmount { address, amount } => {
307 let mut map = serde_json::Map::new();
308 map.insert(
309 address.clone(),
310 serde_json::Value::Number(serde_json::Number::from_f64(*amount).unwrap()),
311 );
312 map.serialize(serializer)
313 }
314 CreateRawTransactionOutput::Data { data } => {
315 let mut map = serde_json::Map::new();
316 map.insert("data".to_string(), serde_json::Value::String(data.clone()));
317 map.serialize(serializer)
318 }
319 }
320 }
321}
322
323#[allow(clippy::doc_lazy_continuation)]
345#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
346pub struct SubmitPackage {
347 pub package_msg: String,
351 #[serde(rename = "tx-results")]
353 pub tx_results: BTreeMap<String, SubmitPackageTxResult>,
354 #[serde(rename = "replaced-transactions")]
356 pub replaced_transactions: Vec<String>,
357}
358
359#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
361pub struct SubmitPackageTxResult {
362 pub txid: String,
364 #[serde(rename = "other-wtxid")]
369 pub other_wtxid: Option<String>,
370 pub vsize: i64,
372 pub fees: Option<SubmitPackageTxResultFees>,
374 pub error: Option<String>,
376}
377
378#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
380pub struct SubmitPackageTxResultFees {
381 #[serde(rename = "base")]
383 pub base_fee: f64,
384 #[serde(rename = "effective-feerate")]
389 pub effective_fee_rate: Option<f64>,
390 #[serde(rename = "effective-includes")]
393 pub effective_includes: Option<Vec<String>>,
394}
395
396#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
403pub struct GetTransactionDetail {
404 pub address: String,
405 pub category: GetTransactionDetailCategory,
406 pub amount: f64,
407 pub label: Option<String>,
408 pub vout: u32,
409 pub fee: Option<f64>,
410 pub abandoned: Option<bool>,
411}
412
413#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
415#[serde(rename_all = "lowercase")]
416pub enum GetTransactionDetailCategory {
417 Send,
418 Receive,
419 Generate,
420 Immature,
421 Orphan,
422}
423
424#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
431pub struct GetNewAddress(pub String);
432
433impl GetNewAddress {
434 pub fn address(self) -> Result<Address<NetworkUnchecked>, address::ParseError> {
436 let address = self.0.parse::<Address<_>>()?;
437 Ok(address)
438 }
439}
440
441#[derive(Clone, Debug, PartialEq, Deserialize)]
452pub struct GetTransaction {
453 #[serde(deserialize_with = "deserialize_signed_bitcoin")]
455 pub amount: SignedAmount,
456 pub confirmations: u64,
458 pub generated: Option<bool>,
459 pub trusted: Option<bool>,
460 pub blockhash: Option<String>,
461 pub blockheight: Option<u64>,
462 pub blockindex: Option<u32>,
463 pub blocktime: Option<u64>,
464 #[serde(deserialize_with = "deserialize_txid")]
466 pub txid: Txid,
467 pub wtxid: String,
468 pub walletconflicts: Vec<String>,
469 pub replaced_by_txid: Option<String>,
470 pub replaces_txid: Option<String>,
471 pub comment: Option<String>,
472 pub to: Option<String>,
473 pub time: u64,
474 pub timereceived: u64,
475 #[serde(rename = "bip125-replaceable")]
476 pub bip125_replaceable: String,
477 pub details: Vec<GetTransactionDetail>,
478 #[serde(deserialize_with = "deserialize_tx")]
480 pub hex: Transaction,
481}
482
483impl GetTransaction {
484 pub fn block_height(&self) -> u64 {
485 if self.confirmations == 0 {
486 return 0;
487 }
488 self.blockheight.unwrap_or_else(|| {
489 warn!("Txn confirmed but did not obtain blockheight. Setting height to zero");
490 0
491 })
492 }
493}
494
495#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
502pub struct ListUnspent {
503 #[serde(deserialize_with = "deserialize_txid")]
505 pub txid: Txid,
506 pub vout: u32,
508 #[serde(deserialize_with = "deserialize_address")]
510 pub address: Address<NetworkUnchecked>,
511 pub label: Option<String>,
513 #[serde(rename = "scriptPubKey")]
515 pub script_pubkey: String,
516 #[serde(deserialize_with = "deserialize_bitcoin")]
518 pub amount: Amount,
519 pub confirmations: u32,
521 pub spendable: bool,
523 pub solvable: bool,
525 pub safe: bool,
530}
531
532#[derive(Clone, Debug, PartialEq, Deserialize)]
543pub struct ListTransactions {
544 #[serde(deserialize_with = "deserialize_address")]
546 pub address: Address<NetworkUnchecked>,
547 category: TransactionCategory,
549 #[serde(deserialize_with = "deserialize_signed_bitcoin")]
551 pub amount: SignedAmount,
552 pub label: Option<String>,
554 pub confirmations: u32,
556 pub trusted: Option<bool>,
557 pub generated: Option<bool>,
558 pub blockhash: Option<String>,
559 pub blockheight: Option<u64>,
560 pub blockindex: Option<u32>,
561 pub blocktime: Option<u64>,
562 #[serde(deserialize_with = "deserialize_txid")]
564 pub txid: Txid,
565}
566
567#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
569pub struct TestMempoolAccept {
570 #[serde(deserialize_with = "deserialize_txid")]
572 pub txid: Txid,
573 pub reject_reason: Option<String>,
575}
576
577#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
584pub struct SignRawTransactionWithWallet {
585 pub hex: String,
587 pub complete: bool,
589 pub errors: Option<Vec<SignRawTransactionWithWalletError>>,
591}
592
593#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
614pub struct PreviousTransactionOutput {
615 #[serde(deserialize_with = "deserialize_txid")]
617 pub txid: Txid,
618 pub vout: u32,
620 #[serde(rename = "scriptPubKey")]
622 pub script_pubkey: String,
623 #[serde(rename = "redeemScript")]
625 pub redeem_script: Option<String>,
626 #[serde(rename = "witnessScript")]
628 pub witness_script: Option<String>,
629 pub amount: Option<f64>,
631}
632
633#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
635pub struct ListDescriptors {
636 pub descriptors: Vec<ListDescriptor>,
638}
639
640#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
642pub struct ListDescriptor {
643 pub desc: String,
645}
646
647#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
649pub struct ImportDescriptors {
650 pub descriptors: Vec<ListDescriptor>,
652}
653
654#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
656pub struct ImportDescriptor {
657 pub desc: String,
659 pub active: Option<bool>,
662 pub timestamp: String,
665}
666#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
668pub struct ImportDescriptorResult {
669 pub success: bool,
671}
672
673#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
679pub struct CreateWallet {
680 pub wallet_name: String,
682 pub load_on_startup: Option<bool>,
684}
685
686fn deserialize_bitcoin<'d, D>(deserializer: D) -> Result<Amount, D::Error>
688where
689 D: Deserializer<'d>,
690{
691 struct SatVisitor;
692
693 impl Visitor<'_> for SatVisitor {
694 type Value = Amount;
695
696 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
697 write!(formatter, "a float representation of btc values expected")
698 }
699
700 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
701 where
702 E: de::Error,
703 {
704 let amount = Amount::from_btc(v).expect("Amount deserialization failed");
705 Ok(amount)
706 }
707 }
708 deserializer.deserialize_any(SatVisitor)
709}
710
711fn deserialize_signed_bitcoin<'d, D>(deserializer: D) -> Result<SignedAmount, D::Error>
713where
714 D: Deserializer<'d>,
715{
716 struct SatVisitor;
717
718 impl Visitor<'_> for SatVisitor {
719 type Value = SignedAmount;
720
721 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
722 write!(formatter, "a float representation of btc values expected")
723 }
724
725 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
726 where
727 E: de::Error,
728 {
729 let signed_amount = SignedAmount::from_btc(v).expect("Amount deserialization failed");
730 Ok(signed_amount)
731 }
732 }
733 deserializer.deserialize_any(SatVisitor)
734}
735
736#[expect(dead_code)]
738fn deserialize_signed_bitcoin_option<'d, D>(
739 deserializer: D,
740) -> Result<Option<SignedAmount>, D::Error>
741where
742 D: Deserializer<'d>,
743{
744 let f: Option<f64> = Option::deserialize(deserializer)?;
745 match f {
746 Some(v) => deserialize_signed_bitcoin(v.into_deserializer()).map(Some),
747 None => Ok(None),
748 }
749}
750
751fn deserialize_txid<'d, D>(deserializer: D) -> Result<Txid, D::Error>
753where
754 D: Deserializer<'d>,
755{
756 struct TxidVisitor;
757
758 impl Visitor<'_> for TxidVisitor {
759 type Value = Txid;
760
761 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
762 write!(formatter, "a transaction id string expected")
763 }
764
765 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
766 where
767 E: de::Error,
768 {
769 let txid = v.parse::<Txid>().expect("invalid txid");
770
771 Ok(txid)
772 }
773 }
774 deserializer.deserialize_any(TxidVisitor)
775}
776
777fn deserialize_tx<'d, D>(deserializer: D) -> Result<Transaction, D::Error>
779where
780 D: Deserializer<'d>,
781{
782 struct TxVisitor;
783
784 impl Visitor<'_> for TxVisitor {
785 type Value = Transaction;
786
787 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
788 write!(formatter, "a transaction hex string expected")
789 }
790
791 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
792 where
793 E: de::Error,
794 {
795 let tx = consensus::encode::deserialize_hex::<Transaction>(v)
796 .expect("failed to deserialize tx hex");
797 Ok(tx)
798 }
799 }
800 deserializer.deserialize_any(TxVisitor)
801}
802
803fn deserialize_address<'d, D>(deserializer: D) -> Result<Address<NetworkUnchecked>, D::Error>
810where
811 D: Deserializer<'d>,
812{
813 struct AddressVisitor;
814 impl Visitor<'_> for AddressVisitor {
815 type Value = Address<NetworkUnchecked>;
816
817 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
818 write!(formatter, "a Bitcoin address string expected")
819 }
820
821 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
822 where
823 E: de::Error,
824 {
825 let address = v
826 .parse::<Address<_>>()
827 .expect("Address deserialization failed");
828 Ok(address)
829 }
830 }
831 deserializer.deserialize_any(AddressVisitor)
832}
833
834#[expect(dead_code)]
836fn deserialize_blockhash<'d, D>(deserializer: D) -> Result<BlockHash, D::Error>
837where
838 D: Deserializer<'d>,
839{
840 struct BlockHashVisitor;
841
842 impl Visitor<'_> for BlockHashVisitor {
843 type Value = BlockHash;
844
845 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
846 write!(formatter, "a blockhash string expected")
847 }
848
849 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
850 where
851 E: de::Error,
852 {
853 let blockhash = consensus::encode::deserialize_hex::<BlockHash>(v)
854 .expect("BlockHash deserialization failed");
855 Ok(blockhash)
856 }
857 }
858 deserializer.deserialize_any(BlockHashVisitor)
859}
860
861#[expect(dead_code)]
863fn deserialize_height<'d, D>(deserializer: D) -> Result<Height, D::Error>
864where
865 D: Deserializer<'d>,
866{
867 struct HeightVisitor;
868
869 impl Visitor<'_> for HeightVisitor {
870 type Value = Height;
871
872 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
873 write!(formatter, "a height u32 string expected")
874 }
875
876 fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
877 where
878 E: de::Error,
879 {
880 let height = Height::from_consensus(v).expect("Height deserialization failed");
881 Ok(height)
882 }
883 }
884 deserializer.deserialize_any(HeightVisitor)
885}