titan_types/
transaction.rs1use {
2 crate::rune::RuneAmount,
3 crate::tx_out::SpentStatus,
4 bitcoin::{BlockHash, ScriptBuf, TxIn, Txid},
5 borsh::{BorshDeserialize, BorshSerialize},
6 serde::{Deserialize, Serialize},
7 std::io::{Read, Result, Write},
8};
9
10#[derive(Debug, Serialize, Deserialize)]
11pub struct TransactionStatus {
12 pub confirmed: bool,
13 #[serde(skip_serializing_if = "Option::is_none")]
14 pub block_height: Option<u64>,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 pub block_hash: Option<BlockHash>,
17}
18
19impl TransactionStatus {
20 pub fn unconfirmed() -> Self {
21 Self {
22 confirmed: false,
23 block_height: None,
24 block_hash: None,
25 }
26 }
27
28 pub fn confirmed(block_height: u64, block_hash: BlockHash) -> Self {
29 Self {
30 confirmed: true,
31 block_height: Some(block_height),
32 block_hash: Some(block_hash),
33 }
34 }
35}
36
37#[derive(Debug, Serialize, Deserialize)]
38pub struct Transaction {
39 pub txid: Txid,
40 pub version: i32,
41 pub lock_time: u32,
42 pub input: Vec<TxIn>,
43 pub output: Vec<TxOut>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub status: Option<TransactionStatus>,
46}
47
48impl From<bitcoin::Transaction> for Transaction {
49 fn from(transaction: bitcoin::Transaction) -> Self {
50 Transaction {
51 txid: transaction.compute_txid(),
52 version: transaction.version.0,
53 lock_time: transaction.lock_time.to_consensus_u32(),
54 input: transaction.input,
55 output: transaction
56 .output
57 .iter()
58 .map(|tx_out| TxOut {
59 value: tx_out.value.to_sat(),
60 script_pubkey: tx_out.script_pubkey.clone(),
61 runes: vec![],
62 risky_runes: vec![],
63 spent: SpentStatus::Unspent,
64 })
65 .collect(),
66 status: None,
67 }
68 }
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct TxOut {
73 pub value: u64,
74 pub script_pubkey: ScriptBuf,
75 pub runes: Vec<RuneAmount>,
76 pub risky_runes: Vec<RuneAmount>,
77 pub spent: SpentStatus,
78}
79
80impl BorshSerialize for TxOut {
81 fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
82 BorshSerialize::serialize(&self.value, writer)?;
83 let script_bytes = self.script_pubkey.as_bytes();
84 BorshSerialize::serialize(&(script_bytes.len() as u32), writer)?;
85 writer.write_all(script_bytes)?;
86 BorshSerialize::serialize(&self.runes, writer)?;
87 BorshSerialize::serialize(&self.risky_runes, writer)?;
88 BorshSerialize::serialize(&self.spent, writer)?;
89 Ok(())
90 }
91}
92
93impl BorshDeserialize for TxOut {
94 fn deserialize_reader<R: Read>(reader: &mut R) -> Result<Self> {
95 let value = u64::deserialize_reader(reader)?;
96 let script_len = u32::deserialize_reader(reader)? as usize;
97 let mut script_bytes = vec![0u8; script_len];
98 reader.read_exact(&mut script_bytes)?;
99 let script_pubkey = ScriptBuf::from_bytes(script_bytes);
100 let runes = Vec::<RuneAmount>::deserialize_reader(reader)?;
101 let risky_runes = Vec::<RuneAmount>::deserialize_reader(reader)?;
102 let spent = SpentStatus::deserialize_reader(reader)?;
103
104 Ok(Self {
105 value,
106 script_pubkey,
107 runes,
108 risky_runes,
109 spent,
110 })
111 }
112}