spark_sdk/wallet/utils/
transaction.rs

1use crate::wallet::utils::bitcoin::p2tr_script_from_pubkey;
2use crate::wallet::utils::sequence::initial_sequence;
3use bitcoin::{absolute, transaction::Version, Amount, OutPoint, Sequence, Transaction, TxOut};
4
5// todo: check if used everywhere needed
6pub(crate) fn ephemeral_anchor_output() -> bitcoin::TxOut {
7    bitcoin::TxOut {
8        value: bitcoin::Amount::from_sat(0),
9        script_pubkey: bitcoin::ScriptBuf::from_bytes(vec![bitcoin::opcodes::OP_TRUE.to_u8()]),
10    }
11}
12
13pub(crate) fn create_root_tx(deposit_outpoint: OutPoint, deposit_txout: TxOut) -> Transaction {
14    let mut root_tx = Transaction {
15        version: Version::TWO,
16        lock_time: absolute::LockTime::ZERO,
17        input: vec![],
18        output: vec![],
19    };
20
21    root_tx.input.push(bitcoin::TxIn {
22        previous_output: deposit_outpoint,
23        script_sig: bitcoin::Script::new().into(),
24        sequence: bitcoin::Sequence::default(),
25        witness: bitcoin::Witness::new(),
26    });
27
28    root_tx.output.push(deposit_txout);
29    root_tx.output.push(ephemeral_anchor_output());
30
31    root_tx
32}
33
34pub(crate) fn create_split_tx(parent_outpoint: OutPoint, child_txouts: Vec<TxOut>) -> Transaction {
35    let mut split_tx = Transaction {
36        version: Version::TWO,
37        lock_time: absolute::LockTime::ZERO,
38        input: vec![],
39        output: vec![],
40    };
41
42    split_tx.input.push(bitcoin::TxIn {
43        previous_output: parent_outpoint,
44        script_sig: bitcoin::Script::new().into(),
45        sequence: bitcoin::Sequence::default(),
46        witness: bitcoin::Witness::new(),
47    });
48    for txout in child_txouts {
49        split_tx.output.push(txout);
50    }
51    split_tx.output.push(ephemeral_anchor_output());
52
53    split_tx
54}
55
56pub(crate) fn create_node_tx(parent_outpoint: OutPoint, txout: TxOut) -> Transaction {
57    let mut node_tx = Transaction {
58        version: Version::TWO,
59        lock_time: absolute::LockTime::ZERO,
60        input: vec![],
61        output: vec![],
62    };
63
64    node_tx.input.push(bitcoin::TxIn {
65        previous_output: parent_outpoint,
66        script_sig: bitcoin::Script::new().into(),
67        sequence: bitcoin::Sequence::default(),
68        witness: bitcoin::Witness::new(),
69    });
70
71    node_tx.output.push(txout);
72    node_tx.output.push(ephemeral_anchor_output());
73
74    node_tx
75}
76
77pub(crate) fn create_leaf_node_tx(parent_outpoint: OutPoint, txout: TxOut) -> Transaction {
78    let mut new_leaf_tx = Transaction {
79        version: Version::TWO,
80        lock_time: absolute::LockTime::ZERO,
81        input: vec![],
82        output: vec![],
83    };
84
85    new_leaf_tx.input.push(bitcoin::TxIn {
86        previous_output: parent_outpoint,
87        script_sig: bitcoin::Script::new().into(),
88        sequence: initial_sequence(),
89        witness: bitcoin::Witness::new(),
90    });
91
92    new_leaf_tx.output.push(txout);
93    new_leaf_tx.output.push(ephemeral_anchor_output());
94
95    new_leaf_tx
96}
97
98pub(crate) fn create_refund_tx(
99    sequence: u32,
100    node_outpoint: OutPoint,
101    amount_sats: bitcoin::Amount,
102    receiving_pubkey: &bitcoin::secp256k1::PublicKey,
103    network: bitcoin::Network,
104) -> Transaction {
105    let mut new_refund_tx = Transaction {
106        version: Version::TWO,
107        lock_time: absolute::LockTime::ZERO,
108        input: vec![],
109        output: vec![],
110    };
111
112    new_refund_tx.input.push(bitcoin::TxIn {
113        previous_output: node_outpoint,
114        script_sig: bitcoin::Script::new().into(),
115        sequence: Sequence(sequence),
116        witness: bitcoin::Witness::new(),
117    });
118
119    let script_pubkey = p2tr_script_from_pubkey(receiving_pubkey, network);
120    new_refund_tx.output.push(bitcoin::TxOut {
121        value: amount_sats,
122        script_pubkey,
123    });
124    new_refund_tx.output.push(ephemeral_anchor_output());
125
126    new_refund_tx
127}
128
129pub(crate) fn create_connector_refund_tx(
130    sequence: u32,
131    node_outpoint: OutPoint,
132    connector_output: OutPoint,
133    amount_sats: u64,
134    receiver_pubkey: &bitcoin::secp256k1::PublicKey,
135    network: bitcoin::Network,
136) -> Transaction {
137    let mut refund_tx = Transaction {
138        version: Version::TWO,
139        lock_time: absolute::LockTime::ZERO,
140        input: vec![],
141        output: vec![],
142    };
143
144    refund_tx.input.push(bitcoin::TxIn {
145        previous_output: node_outpoint,
146        script_sig: bitcoin::Script::new().into(),
147        sequence: Sequence(sequence),
148        witness: bitcoin::Witness::new(),
149    });
150    refund_tx.input.push(bitcoin::TxIn {
151        previous_output: connector_output,
152        script_sig: bitcoin::Script::new().into(),
153        sequence: bitcoin::Sequence::default(),
154        witness: bitcoin::Witness::new(),
155    });
156
157    let script_pubkey = p2tr_script_from_pubkey(receiver_pubkey, network);
158    refund_tx.output.push(TxOut {
159        value: Amount::from_sat(amount_sats),
160        script_pubkey,
161    });
162    refund_tx.output.push(ephemeral_anchor_output());
163
164    refund_tx
165}