clementine_core/
tx_sender_ext.rs1use crate::rpc;
2use crate::rpc::clementine::TxDebugInfo;
3use bitcoin::hashes::Hash;
4use clementine_errors::{BridgeError, ResultExt as _, RoundIndex};
5use clementine_tx_sender::client::TxSenderClient;
6use clementine_tx_sender::TxSender;
7use clementine_utils::FeePayingType;
8use tonic::async_trait;
9
10#[async_trait]
11pub trait TxSenderClientExt {
12 async fn debug_tx(&self, id: u32) -> Result<TxDebugInfo, BridgeError>;
23}
24
25#[async_trait]
26impl TxSenderClientExt for TxSenderClient {
27 async fn debug_tx(&self, id: u32) -> Result<TxDebugInfo, BridgeError> {
28 use crate::rpc::clementine::{TxDebugFeePayerUtxo, TxDebugInfo, TxDebugSubmissionError};
29
30 let (tx_metadata, tx, fee_paying_type, seen_at_height, _) =
31 self.db.get_try_to_send_tx(None, id).await.map_to_eyre()?;
32
33 let submission_errors = self
34 .db
35 .get_tx_debug_submission_errors(None, id)
36 .await
37 .map_to_eyre()?;
38
39 let submission_errors = submission_errors
40 .into_iter()
41 .map(|(error_message, timestamp)| TxDebugSubmissionError {
42 error_message,
43 timestamp,
44 })
45 .collect();
46
47 let current_state = self.db.get_tx_debug_info(None, id).await.map_to_eyre()?;
48
49 let fee_payer_utxos = self
50 .db
51 .get_tx_debug_fee_payer_utxos(None, id)
52 .await
53 .map_to_eyre()?;
54
55 let fee_payer_utxos = fee_payer_utxos
56 .into_iter()
57 .map(|(txid, vout, amount, confirmed)| TxDebugFeePayerUtxo {
58 txid: Some(txid.into()),
59 vout,
60 amount: amount.to_sat(),
61 confirmed,
62 })
63 .collect::<Vec<_>>();
64
65 let txid = match fee_paying_type {
66 FeePayingType::CPFP | FeePayingType::NoFunding => tx.compute_txid(),
67 FeePayingType::RBF | FeePayingType::RbfWtxidGrind => self
68 .db
69 .get_last_rbf_txid(None, id)
70 .await
71 .map_to_eyre()?
72 .unwrap_or(bitcoin::Txid::all_zeros()),
73 };
74 let debug_info = TxDebugInfo {
75 id,
76 is_active: seen_at_height.is_none(),
77 current_state: current_state.unwrap_or_else(|| "unknown".to_string()),
78 submission_errors,
79 created_at: "".to_string(),
80 txid: Some(txid.into()),
81 fee_paying_type: format!("{fee_paying_type:?}"),
82 fee_payer_utxos_count: fee_payer_utxos.len() as u32,
83 fee_payer_utxos_confirmed_count: fee_payer_utxos
84 .iter()
85 .filter(|utxo| utxo.confirmed)
86 .count() as u32,
87 fee_payer_utxos,
88 raw_tx: bitcoin::consensus::serialize(&tx),
89 metadata: tx_metadata.map(|metadata| rpc::clementine::TxMetadata {
90 deposit_outpoint: metadata.deposit_outpoint.map(Into::into),
91 operator_xonly_pk: metadata.operator_xonly_pk.map(Into::into),
92
93 round_idx: metadata
94 .round_idx
95 .unwrap_or(RoundIndex::Round(0))
96 .to_index() as u32,
97 kickoff_idx: metadata.kickoff_idx.unwrap_or(0),
98 tx_type: Some(metadata.tx_type.into()),
99 }),
100 };
101
102 Ok(debug_info)
103 }
104}
105
106#[async_trait]
107pub trait TxSenderExt {
108 async fn debug_tx(&self, id: u32) -> Result<TxDebugInfo, BridgeError>;
109}
110
111#[async_trait]
112impl TxSenderExt for TxSender {
113 async fn debug_tx(&self, id: u32) -> Result<TxDebugInfo, BridgeError> {
114 let client = self.client();
115 client.debug_tx(id).await
116 }
117}