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, Clone, 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, Clone, 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 pub status: TransactionStatus,
45}
46
47impl From<(bitcoin::Transaction, TransactionStatus)> for Transaction {
48 fn from((transaction, status): (bitcoin::Transaction, TransactionStatus)) -> Self {
49 Transaction {
50 txid: transaction.compute_txid(),
51 version: transaction.version.0,
52 lock_time: transaction.lock_time.to_consensus_u32(),
53 input: transaction.input,
54 output: transaction
55 .output
56 .iter()
57 .map(|tx_out| TxOut {
58 value: tx_out.value.to_sat(),
59 script_pubkey: tx_out.script_pubkey.clone(),
60 runes: vec![],
61 risky_runes: vec![],
62 spent: SpentStatus::Unspent,
63 })
64 .collect(),
65 status,
66 }
67 }
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct TxOut {
72 pub value: u64,
73 pub script_pubkey: ScriptBuf,
74 pub runes: Vec<RuneAmount>,
75 pub risky_runes: Vec<RuneAmount>,
76 pub spent: SpentStatus,
77}
78
79impl BorshSerialize for TxOut {
80 fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
81 BorshSerialize::serialize(&self.value, writer)?;
82 let script_bytes = self.script_pubkey.as_bytes();
83 BorshSerialize::serialize(&(script_bytes.len() as u32), writer)?;
84 writer.write_all(script_bytes)?;
85 BorshSerialize::serialize(&self.runes, writer)?;
86 BorshSerialize::serialize(&self.risky_runes, writer)?;
87 BorshSerialize::serialize(&self.spent, writer)?;
88 Ok(())
89 }
90}
91
92impl BorshDeserialize for TxOut {
93 fn deserialize_reader<R: Read>(reader: &mut R) -> Result<Self> {
94 let value = u64::deserialize_reader(reader)?;
95 let script_len = u32::deserialize_reader(reader)? as usize;
96 let mut script_bytes = vec![0u8; script_len];
97 reader.read_exact(&mut script_bytes)?;
98 let script_pubkey = ScriptBuf::from_bytes(script_bytes);
99 let runes = Vec::<RuneAmount>::deserialize_reader(reader)?;
100 let risky_runes = Vec::<RuneAmount>::deserialize_reader(reader)?;
101 let spent = SpentStatus::deserialize_reader(reader)?;
102
103 Ok(Self {
104 value,
105 script_pubkey,
106 runes,
107 risky_runes,
108 spent,
109 })
110 }
111}