create_bitcoin_transaction/
lib.rs

1mod legacy_transaction;
2mod segwit_transaction;
3mod types;
4
5use legacy_transaction::get_legacy_unsigned_transaction_hex;
6use segwit_transaction::{
7    get_unsigned_segwit_transaction, sign_segwit_transaction, SegwitTransaction,
8};
9
10use crate::legacy_transaction::{sign_p2pkh_transaction_with_one_input, P2PKHTransaction};
11
12mod utils;
13pub use crate::types::PayFrom;
14pub use crate::types::PayTo;
15pub use crate::types::Wifs;
16
17pub fn get_unsigned_transaction_hex(
18    inputs: &Vec<PayFrom>,
19    outputs: &Vec<PayTo>,
20    version: u8,
21) -> String {
22    let is_legacy_transaction = inputs
23        .iter()
24        .any(|input| bitcoin_address::is_legacy(&input.address));
25    if is_legacy_transaction {
26        let transaction = P2PKHTransaction::new(inputs.clone(), outputs.clone(), version);
27        get_legacy_unsigned_transaction_hex(&transaction)
28    } else {
29        let transaction = SegwitTransaction::new(inputs.clone(), outputs.clone(), version);
30        get_unsigned_segwit_transaction(&transaction)
31    }
32}
33
34pub fn get_signed_transaction_hex(
35    inputs: &Vec<PayFrom>,
36    outputs: &Vec<PayTo>,
37    wifs: &Wifs,
38    version: u8,
39) -> String {
40    let is_legacy_transaction = inputs
41        .iter()
42        .any(|input| bitcoin_address::is_legacy(&input.address));
43    if is_legacy_transaction {
44        let transaction = P2PKHTransaction::new(inputs.clone(), outputs.clone(), version);
45        sign_p2pkh_transaction_with_one_input(&transaction, wifs)
46    } else {
47        let transaction = SegwitTransaction::new(inputs.clone(), outputs.clone(), version);
48        sign_segwit_transaction(&transaction, wifs)
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use crate::*;
55    #[test]
56    fn single_input_p2wpkh_to_p2tr() {
57        let version = 2;
58        let pay_froms = vec![PayFrom {
59            transaction: "2d0821b1a1ee6d04c5f91b0b400ec38cf7613bdb06a5d43ce658e672ea66d081"
60                .to_string(),
61            vout_index: 1,
62            script_pub_key_hex_of_vout: "001443400caddfaffbb17b130304349384c8ef7e6fa4".to_string(), // without length
63            address: "tb1qgdqqetwl4lamz7cnqvzrfyuyerhhumayhhprt2".to_string(), // Placeholder for now
64            vout_amount_in_sats: 30000, // Placeholde as it's not needed for legacy
65        }];
66        let pay_tos = vec![PayTo {
67            address: "tb1psmsr8rc6jwl47xsv4zahnt39m2peexxhxrfvprqpw86yf55rkzgq70ycww".to_string(),
68            amount_in_sats: 29878,
69        }];
70        let mut wifs: Wifs = Wifs::new();
71        wifs.insert(
72            0,
73            "cSPybNQG6n1LpmxGNiWUHSSseaVfNszVjoPwo7qi4dvRE2Se825q".to_string(),
74        );
75
76        let unsigned_transaction_hex = get_unsigned_transaction_hex(&pay_froms, &pay_tos, version);
77        assert_eq!(unsigned_transaction_hex, "020000000181d066ea72e658e63cd4a506db3b61f78cc30e400b1bf9c5046deea1b121082d0100000000fdffffff01b67400000000000022512086e0338f1a93bf5f1a0ca8bb79ae25da839c98d730d2c08c0171f444d283b09000000000");
78        let signed_transaction_hex =
79            get_signed_transaction_hex(&pay_froms, &pay_tos, &wifs, version);
80        assert_eq!(signed_transaction_hex, "0200000000010181d066ea72e658e63cd4a506db3b61f78cc30e400b1bf9c5046deea1b121082d0100000000fdffffff01b67400000000000022512086e0338f1a93bf5f1a0ca8bb79ae25da839c98d730d2c08c0171f444d283b09002483045022100854b7174c8864486538eacc53f3b77598bc9a5f1e0db69ac6a07fcdf73e2cd250220761703fd3b724a0b7431754c498bafa1046cdf41c0b5ecfd985a5a534c4cea93012102e3cbeaf1c32b9838fe5de49ffffd15b57fa12e99a3c08486e9eb5a35e8ac387700000000");
81    }
82    #[test]
83    fn single_input_p2wpkh_to_p2wpkh() {
84        let version = 2;
85        let pay_froms = vec![PayFrom {
86            transaction: "13b10f1fcb38a55c065d2605c87aa44fce9e81dd9d2b745d506c3dac3c3f35ec"
87                .to_string(),
88            vout_index: 1,
89            script_pub_key_hex_of_vout: "00140dda001b81ce9a2b0a22a1d6e253f583d8aaeff9".to_string(), // without length
90            address: "tb1qphdqqxupe6dzkz3z58twy5l4s0v24mle5gkp99".to_string(), // Placeholder for now
91            vout_amount_in_sats: 30000, // Placeholde as it's not needed for legacy
92        }];
93        let pay_tos = vec![PayTo {
94            address: "tb1qtzexd3yncgyacpz0775h5u48lvjdz98g29fq05".to_string(),
95            amount_in_sats: 29890,
96        }];
97        let mut wifs: Wifs = Wifs::new();
98        wifs.insert(
99            0,
100            "cRFjsTSi8azdDPVTzdkjNe2HWRy9oVFtbPEPEGJZenhHeQj8ibNy".to_string(),
101        );
102
103        let unsigned_transaction_hex = get_unsigned_transaction_hex(&pay_froms, &pay_tos, version);
104        assert_eq!(unsigned_transaction_hex, "0200000001ec353f3cac3d6c505d742b9ddd819ece4fa47ac805265d065ca538cb1f0fb1130100000000fdffffff01c27400000000000016001458b266c493c209dc044ff7a97a72a7fb24d114e800000000");
105        let signed_transaction_hex =
106            get_signed_transaction_hex(&pay_froms, &pay_tos, &wifs, version);
107        assert_eq!(signed_transaction_hex, "02000000000101ec353f3cac3d6c505d742b9ddd819ece4fa47ac805265d065ca538cb1f0fb1130100000000fdffffff01c27400000000000016001458b266c493c209dc044ff7a97a72a7fb24d114e802463043021f2fe907abb689b76301cb1ec673148e9bdf6ea358b09d84241d134be7c84b76022050c193826beeffced46d5ad0477c7e054b3cce132bef64482775917605eb40f901210230b8887b22c02acc2aa15d5d12859eb673f7c94f4f08b7daa205e13a6391ffc500000000");
108    }
109    #[test]
110    fn single_input_p2wpkh_to_p2sh() {
111        let version = 2;
112        let pay_froms = vec![PayFrom {
113            transaction: "13b10f1fcb38a55c065d2605c87aa44fce9e81dd9d2b745d506c3dac3c3f35ec"
114                .to_string(),
115            vout_index: 1,
116            script_pub_key_hex_of_vout: "00140dda001b81ce9a2b0a22a1d6e253f583d8aaeff9".to_string(), // without length
117            address: "tb1qphdqqxupe6dzkz3z58twy5l4s0v24mle5gkp99".to_string(), // Placeholder for now
118            vout_amount_in_sats: 30000, // Placeholde as it's not needed for legacy
119        }];
120        let pay_tos = vec![PayTo {
121            address: "2Mvn45VLAhg1TVjFrKjuyMRkoapoPNQS5Mf".to_string(),
122            amount_in_sats: 29889,
123        }];
124        let mut wifs: Wifs = Wifs::new();
125        wifs.insert(
126            0,
127            "cRFjsTSi8azdDPVTzdkjNe2HWRy9oVFtbPEPEGJZenhHeQj8ibNy".to_string(),
128        );
129
130        let unsigned_transaction_hex = get_unsigned_transaction_hex(&pay_froms, &pay_tos, version);
131        assert_eq!(unsigned_transaction_hex, "0200000001ec353f3cac3d6c505d742b9ddd819ece4fa47ac805265d065ca538cb1f0fb1130100000000fdffffff01c17400000000000017a91426bcffdf80a7e00c8a829f8eca55fcc1d4d65c468700000000");
132        let signed_transaction_hex =
133            get_signed_transaction_hex(&pay_froms, &pay_tos, &wifs, version);
134        assert_eq!(signed_transaction_hex, "02000000000101ec353f3cac3d6c505d742b9ddd819ece4fa47ac805265d065ca538cb1f0fb1130100000000fdffffff01c17400000000000017a91426bcffdf80a7e00c8a829f8eca55fcc1d4d65c46870247304402207ae40decea8ef2414f799b18f299ffcac8a39da0fa6445df1c96aaf71d82e045022035152d798bd0186b2f807ea29737baea04c351974208a45ec1b68cc5731a6b8001210230b8887b22c02acc2aa15d5d12859eb673f7c94f4f08b7daa205e13a6391ffc500000000");
135    }
136    #[test]
137    fn single_input_p2wpkh_to_p2pkh() {
138        let version = 2;
139        let pay_froms = vec![PayFrom {
140            transaction: "13b10f1fcb38a55c065d2605c87aa44fce9e81dd9d2b745d506c3dac3c3f35ec"
141                .to_string(),
142            vout_index: 1,
143            script_pub_key_hex_of_vout: "00140dda001b81ce9a2b0a22a1d6e253f583d8aaeff9".to_string(), // without length
144            address: "tb1qphdqqxupe6dzkz3z58twy5l4s0v24mle5gkp99".to_string(), // Placeholder for now
145            vout_amount_in_sats: 30000, // Placeholde as it's not needed for legacy
146        }];
147        let pay_tos = vec![PayTo {
148            address: "mtveoXKcb1EjpspMmhPAJ6RkGeewbzWYDd".to_string(),
149            amount_in_sats: 29887,
150        }];
151        let mut wifs: Wifs = Wifs::new();
152        wifs.insert(
153            0,
154            "cRFjsTSi8azdDPVTzdkjNe2HWRy9oVFtbPEPEGJZenhHeQj8ibNy".to_string(),
155        );
156
157        let unsigned_transaction_hex = get_unsigned_transaction_hex(&pay_froms, &pay_tos, version);
158        assert_eq!(unsigned_transaction_hex, "0200000001ec353f3cac3d6c505d742b9ddd819ece4fa47ac805265d065ca538cb1f0fb1130100000000fdffffff01bf740000000000001976a9149315044ac5f815df5fc9bd3fbecff8ad1dfc01ab88ac00000000");
159        let signed_transaction_hex =
160            get_signed_transaction_hex(&pay_froms, &pay_tos, &wifs, version);
161        assert_eq!(signed_transaction_hex, "02000000000101ec353f3cac3d6c505d742b9ddd819ece4fa47ac805265d065ca538cb1f0fb1130100000000fdffffff01bf740000000000001976a9149315044ac5f815df5fc9bd3fbecff8ad1dfc01ab88ac02483045022100c7249d685fcbc2d7e30b684a76a09eb24eb6579daa0ad9e7bece9464bbc4e73e02207d6b7c7cdb2054797a3ba43e5ba124c9576c29b04103e25ae72f61528423b2d101210230b8887b22c02acc2aa15d5d12859eb673f7c94f4f08b7daa205e13a6391ffc500000000");
162    }
163    #[test]
164    fn single_input_p2sh_to_p2wpkh() {
165        let version = 2;
166        let pay_froms = vec![PayFrom {
167            transaction: "f97db528e307a5928097692d1b9c2c4ee1ca4e1f57b1453c5e4699447b825fec"
168                .to_string(),
169            vout_index: 0,
170            script_pub_key_hex_of_vout: "a9144c0e2d95060d095c9600a983a8a4fd8639e77adb87"
171                .to_string(), // without length
172            address: "2MzBNKyJjx44BDJfwEevVzS3Q9Z5kSEYUZB".to_string(), // Placeholder for now
173            vout_amount_in_sats: 30000, // Placeholde as it's not needed for legacy
174        }];
175        let pay_tos = vec![PayTo {
176            address: "tb1qtzexd3yncgyacpz0775h5u48lvjdz98g29fq05".to_string(),
177            amount_in_sats: 29867,
178        }];
179        let mut wifs: Wifs = Wifs::new();
180        wifs.insert(
181            0,
182            "cUB9G7V8KBsoj7qQpqBooYUkpr1EoD1jmoXiCg1Bb61dbG7hN6js".to_string(),
183        );
184
185        let unsigned_transaction_hex = get_unsigned_transaction_hex(&pay_froms, &pay_tos, version);
186        assert_eq!(unsigned_transaction_hex, "0200000001ec5f827b4499465e3c45b1571f4ecae14e2c9c1b2d69978092a507e328b57df90000000000fdffffff01ab7400000000000016001458b266c493c209dc044ff7a97a72a7fb24d114e800000000");
187        let signed_transaction_hex =
188            get_signed_transaction_hex(&pay_froms, &pay_tos, &wifs, version);
189        assert_eq!(signed_transaction_hex, "02000000000101ec5f827b4499465e3c45b1571f4ecae14e2c9c1b2d69978092a507e328b57df9000000001716001428ee3db8eefa6096355504b6d7b4151604d79856fdffffff01ab7400000000000016001458b266c493c209dc044ff7a97a72a7fb24d114e802483045022100b6cd893987850748bbcf60b239bbe882f0815aa43f3238058cffa8701761b750022021a81c333e9815000030e55bab8cb25ef457940600d69bad4e64dd431fc6b9b6012102968b0c598585659784517e1532c055f4f4e784a8f8ffde0b32063d715936833f00000000");
190    }
191    #[test]
192    fn single_input_p2sh_to_p2sh() {
193        let version = 2;
194        let pay_froms = vec![PayFrom {
195            transaction: "f97db528e307a5928097692d1b9c2c4ee1ca4e1f57b1453c5e4699447b825fec"
196                .to_string(),
197            vout_index: 0,
198            script_pub_key_hex_of_vout: "a9144c0e2d95060d095c9600a983a8a4fd8639e77adb87"
199                .to_string(), // without length
200            address: "2MzBNKyJjx44BDJfwEevVzS3Q9Z5kSEYUZB".to_string(), // Placeholder for now
201            vout_amount_in_sats: 30000, // Placeholde as it's not needed for legacy
202        }];
203        let pay_tos = vec![PayTo {
204            address: "2Mvn45VLAhg1TVjFrKjuyMRkoapoPNQS5Mf".to_string(),
205            amount_in_sats: 29866,
206        }];
207        let mut wifs: Wifs = Wifs::new();
208        wifs.insert(
209            0,
210            "cUB9G7V8KBsoj7qQpqBooYUkpr1EoD1jmoXiCg1Bb61dbG7hN6js".to_string(),
211        );
212
213        let unsigned_transaction_hex = get_unsigned_transaction_hex(&pay_froms, &pay_tos, version);
214        assert_eq!(unsigned_transaction_hex, "0200000001ec5f827b4499465e3c45b1571f4ecae14e2c9c1b2d69978092a507e328b57df90000000000fdffffff01aa7400000000000017a91426bcffdf80a7e00c8a829f8eca55fcc1d4d65c468700000000");
215        let signed_transaction_hex =
216            get_signed_transaction_hex(&pay_froms, &pay_tos, &wifs, version);
217        assert_eq!(signed_transaction_hex, "02000000000101ec5f827b4499465e3c45b1571f4ecae14e2c9c1b2d69978092a507e328b57df9000000001716001428ee3db8eefa6096355504b6d7b4151604d79856fdffffff01aa7400000000000017a91426bcffdf80a7e00c8a829f8eca55fcc1d4d65c468702483045022100b3edf02595e8af7aa5bca019fb44e896f38e9723bb01a81012ef796b0e3208ff022011a9f8332a86e37b11f414fd3fe1c8a6a480343525726fc9ab7bb65991bc760c012102968b0c598585659784517e1532c055f4f4e784a8f8ffde0b32063d715936833f00000000");
218    }
219    #[test]
220    fn single_input_p2sh_to_p2pkh() {
221        let version = 2;
222        let pay_froms = vec![PayFrom {
223            transaction: "f97db528e307a5928097692d1b9c2c4ee1ca4e1f57b1453c5e4699447b825fec"
224                .to_string(),
225            vout_index: 0,
226            script_pub_key_hex_of_vout: "a9144c0e2d95060d095c9600a983a8a4fd8639e77adb87"
227                .to_string(), // without length
228            address: "2MzBNKyJjx44BDJfwEevVzS3Q9Z5kSEYUZB".to_string(), // Placeholder for now
229            vout_amount_in_sats: 30000, // Placeholde as it's not needed for legacy
230        }];
231        let pay_tos = vec![PayTo {
232            address: "mtveoXKcb1EjpspMmhPAJ6RkGeewbzWYDd".to_string(),
233            amount_in_sats: 29863,
234        }];
235        let mut wifs: Wifs = Wifs::new();
236        wifs.insert(
237            0,
238            "cUB9G7V8KBsoj7qQpqBooYUkpr1EoD1jmoXiCg1Bb61dbG7hN6js".to_string(),
239        );
240
241        let unsigned_transaction_hex = get_unsigned_transaction_hex(&pay_froms, &pay_tos, version);
242        assert_eq!(unsigned_transaction_hex, "0200000001ec5f827b4499465e3c45b1571f4ecae14e2c9c1b2d69978092a507e328b57df90000000000fdffffff01a7740000000000001976a9149315044ac5f815df5fc9bd3fbecff8ad1dfc01ab88ac00000000");
243        let signed_transaction_hex =
244            get_signed_transaction_hex(&pay_froms, &pay_tos, &wifs, version);
245        assert_eq!(signed_transaction_hex, "02000000000101ec5f827b4499465e3c45b1571f4ecae14e2c9c1b2d69978092a507e328b57df9000000001716001428ee3db8eefa6096355504b6d7b4151604d79856fdffffff01a7740000000000001976a9149315044ac5f815df5fc9bd3fbecff8ad1dfc01ab88ac0247304402203de8eac0d844ff9a6c2f97648d6ea882547821b12aeca44e7ddcb6904b53132e02202d00856ef69719c23690390513150d987a74265db6d5b682c5defeea28ca856a012102968b0c598585659784517e1532c055f4f4e784a8f8ffde0b32063d715936833f00000000");
246    }
247    #[test]
248    fn single_input_p2sh_to_p2tr() {
249        let version = 2;
250        let pay_froms = vec![PayFrom {
251            transaction: "f97db528e307a5928097692d1b9c2c4ee1ca4e1f57b1453c5e4699447b825fec"
252                .to_string(),
253            vout_index: 0,
254            script_pub_key_hex_of_vout: "a9144c0e2d95060d095c9600a983a8a4fd8639e77adb87"
255                .to_string(), // without length
256            address: "2MzBNKyJjx44BDJfwEevVzS3Q9Z5kSEYUZB".to_string(), // Placeholder for now
257            vout_amount_in_sats: 30000, // Placeholde as it's not needed for legacy
258        }];
259        let pay_tos = vec![PayTo {
260            address: "tb1ptwdm6l3p8eeffl3h2zm5xksxpzaem95cgvqxjhus8r7l7xtmvc3qen55vc".to_string(),
261            amount_in_sats: 29854,
262        }];
263        let mut wifs: Wifs = Wifs::new();
264        wifs.insert(
265            0,
266            "cUB9G7V8KBsoj7qQpqBooYUkpr1EoD1jmoXiCg1Bb61dbG7hN6js".to_string(),
267        );
268
269        let unsigned_transaction_hex = get_unsigned_transaction_hex(&pay_froms, &pay_tos, version);
270        assert_eq!(unsigned_transaction_hex, "0200000001ec5f827b4499465e3c45b1571f4ecae14e2c9c1b2d69978092a507e328b57df90000000000fdffffff019e740000000000002251205b9bbd7e213e7294fe3750b7435a0608bb9d96984300695f9038fdff197b662200000000");
271        let signed_transaction_hex =
272            get_signed_transaction_hex(&pay_froms, &pay_tos, &wifs, version);
273        assert_eq!(signed_transaction_hex, "02000000000101ec5f827b4499465e3c45b1571f4ecae14e2c9c1b2d69978092a507e328b57df9000000001716001428ee3db8eefa6096355504b6d7b4151604d79856fdffffff019e740000000000002251205b9bbd7e213e7294fe3750b7435a0608bb9d96984300695f9038fdff197b662202473044022049ec43b2659e4501437b21ad2c031ebd6856199bf889c55fb3cf1c928c78eb9a02201e246bf98d42dee12391c2f01178845d3407eeea0d8497c26d75c7b8247b95cd012102968b0c598585659784517e1532c055f4f4e784a8f8ffde0b32063d715936833f00000000");
274    }
275    #[test]
276    fn single_input_p2pkh_to_p2pkh() {
277        let version = 2;
278        let pay_froms = vec![PayFrom {
279            transaction: "57bded0a2734620ddd416f59d98260dc8646a990c5a901acc00a3d17a911e174"
280                .to_string(),
281            vout_index: 0,
282            script_pub_key_hex_of_vout: "76a914ad757fd3afbdae593efdf799912f969d16337ef788ac"
283                .to_string(), // without length
284            address: "mwL7xEgwbiF9yRVJEgLsCjgzGofG1MtsTH".to_string(), // Placeholder for now
285            vout_amount_in_sats: 28000, // Placeholde as it's not needed for legacy
286        }];
287        let pay_tos = vec![PayTo {
288            address: "mtveoXKcb1EjpspMmhPAJ6RkGeewbzWYDd".to_string(),
289            amount_in_sats: 27600,
290        }];
291        let mut wifs: Wifs = Wifs::new();
292        wifs.insert(
293            0,
294            "cVGvNsrgfgENrjLRrGy4dUPTTpmRsZnUdhoiMzwvbLRXTu6zq5y7".to_string(),
295        );
296
297        let unsigned_transaction_hex = get_unsigned_transaction_hex(&pay_froms, &pay_tos, version);
298        assert_eq!(unsigned_transaction_hex, "020000000174e111a9173d0ac0ac01a9c590a94686dc6082d9596f41dd0d6234270aedbd570000000000fdffffff01d06b0000000000001976a9149315044ac5f815df5fc9bd3fbecff8ad1dfc01ab88ac00000000");
299        let signed_transaction_hex =
300            get_signed_transaction_hex(&pay_froms, &pay_tos, &wifs, version);
301        assert_eq!(signed_transaction_hex, "020000000174e111a9173d0ac0ac01a9c590a94686dc6082d9596f41dd0d6234270aedbd57000000006b483045022100c353a28d44bddf6cdd019fec458180a119053ec6a326573c071cd3aca0ac6cdd022001bdcfbd8a883f9996d38975ee1ba54cf5b8dddfd64ecfc1b474bd405eb81635012102693cfb0a49a9e4006255ccefef7bee362c0f3fb2c41d7066d9d11e10053fb9abfdffffff01d06b0000000000001976a9149315044ac5f815df5fc9bd3fbecff8ad1dfc01ab88ac00000000");
302    }
303    #[test]
304    fn single_input_p2pkh_to_p2sh() {
305        let version = 2;
306        let pay_froms = vec![PayFrom {
307            transaction: "57bded0a2734620ddd416f59d98260dc8646a990c5a901acc00a3d17a911e174"
308                .to_string(),
309            vout_index: 0,
310            script_pub_key_hex_of_vout: "76a914ad757fd3afbdae593efdf799912f969d16337ef788ac"
311                .to_string(), // without length
312            address: "mwL7xEgwbiF9yRVJEgLsCjgzGofG1MtsTH".to_string(), // Placeholder for now
313            vout_amount_in_sats: 28000, // Placeholde as it's not needed for legacy
314        }];
315        let pay_tos = vec![PayTo {
316            address: "2Mvn45VLAhg1TVjFrKjuyMRkoapoPNQS5Mf".to_string(),
317            amount_in_sats: 27600,
318        }];
319        let mut wifs: Wifs = Wifs::new();
320        wifs.insert(
321            0,
322            "cVGvNsrgfgENrjLRrGy4dUPTTpmRsZnUdhoiMzwvbLRXTu6zq5y7".to_string(),
323        );
324
325        let unsigned_transaction_hex = get_unsigned_transaction_hex(&pay_froms, &pay_tos, version);
326        assert_eq!(unsigned_transaction_hex, "020000000174e111a9173d0ac0ac01a9c590a94686dc6082d9596f41dd0d6234270aedbd570000000000fdffffff01d06b00000000000017a91426bcffdf80a7e00c8a829f8eca55fcc1d4d65c468700000000");
327        let signed_transaction_hex =
328            get_signed_transaction_hex(&pay_froms, &pay_tos, &wifs, version);
329        assert_eq!(signed_transaction_hex, "020000000174e111a9173d0ac0ac01a9c590a94686dc6082d9596f41dd0d6234270aedbd57000000006a473044022042c0cae7224669274f0acddd297dbe685125b5a6b6976b83ca72d8fbe571604402200624c3c302a4eee0feed3f728a34edf1516204f8a436c33dc0eabe63eb7c60c6012102693cfb0a49a9e4006255ccefef7bee362c0f3fb2c41d7066d9d11e10053fb9abfdffffff01d06b00000000000017a91426bcffdf80a7e00c8a829f8eca55fcc1d4d65c468700000000");
330    }
331    #[test]
332    fn single_input_p2pkh_to_p2wpkh() {
333        let version = 2;
334        let pay_froms = vec![PayFrom {
335            transaction: "57bded0a2734620ddd416f59d98260dc8646a990c5a901acc00a3d17a911e174"
336                .to_string(),
337            vout_index: 0,
338            script_pub_key_hex_of_vout: "76a914ad757fd3afbdae593efdf799912f969d16337ef788ac"
339                .to_string(), // without length
340            address: "mwL7xEgwbiF9yRVJEgLsCjgzGofG1MtsTH".to_string(), // Placeholder for now
341            vout_amount_in_sats: 28000, // Placeholde as it's not needed for legacy
342        }];
343        let pay_tos = vec![PayTo {
344            address: "tb1qtzexd3yncgyacpz0775h5u48lvjdz98g29fq05".to_string(),
345            amount_in_sats: 27600,
346        }];
347        let mut wifs: Wifs = Wifs::new();
348        wifs.insert(
349            0,
350            "cVGvNsrgfgENrjLRrGy4dUPTTpmRsZnUdhoiMzwvbLRXTu6zq5y7".to_string(),
351        );
352
353        let unsigned_transaction_hex = get_unsigned_transaction_hex(&pay_froms, &pay_tos, version);
354        assert_eq!(unsigned_transaction_hex, "020000000174e111a9173d0ac0ac01a9c590a94686dc6082d9596f41dd0d6234270aedbd570000000000fdffffff01d06b00000000000016001458b266c493c209dc044ff7a97a72a7fb24d114e800000000");
355        let signed_transaction_hex =
356            get_signed_transaction_hex(&pay_froms, &pay_tos, &wifs, version);
357        assert_eq!(signed_transaction_hex, "020000000174e111a9173d0ac0ac01a9c590a94686dc6082d9596f41dd0d6234270aedbd57000000006b483045022100bf47e43542ed1d50d90ccbcf2b900ce441af351e9d7fec996862930fbbd9a3c4022008203489d37249c87820cdb33a71bb2385fc759c6f7740b51c4dde2655029060012102693cfb0a49a9e4006255ccefef7bee362c0f3fb2c41d7066d9d11e10053fb9abfdffffff01d06b00000000000016001458b266c493c209dc044ff7a97a72a7fb24d114e800000000");
358    }
359    #[test]
360    fn single_input_p2pkh_to_p2tr() {
361        let version = 2;
362        let pay_froms = vec![PayFrom {
363            transaction: "57bded0a2734620ddd416f59d98260dc8646a990c5a901acc00a3d17a911e174"
364                .to_string(),
365            vout_index: 0,
366            script_pub_key_hex_of_vout: "76a914ad757fd3afbdae593efdf799912f969d16337ef788ac"
367                .to_string(), // without length
368            address: "mwL7xEgwbiF9yRVJEgLsCjgzGofG1MtsTH".to_string(), // Placeholder for now
369            vout_amount_in_sats: 28000, // Placeholde as it's not needed for legacy
370        }];
371        let pay_tos = vec![PayTo {
372            address: "tb1ptwdm6l3p8eeffl3h2zm5xksxpzaem95cgvqxjhus8r7l7xtmvc3qen55vc".to_string(),
373            amount_in_sats: 27600,
374        }];
375        let mut wifs: Wifs = Wifs::new();
376        wifs.insert(
377            0,
378            "cVGvNsrgfgENrjLRrGy4dUPTTpmRsZnUdhoiMzwvbLRXTu6zq5y7".to_string(),
379        );
380
381        let unsigned_transaction_hex = get_unsigned_transaction_hex(&pay_froms, &pay_tos, version);
382        assert_eq!(unsigned_transaction_hex, "020000000174e111a9173d0ac0ac01a9c590a94686dc6082d9596f41dd0d6234270aedbd570000000000fdffffff01d06b0000000000002251205b9bbd7e213e7294fe3750b7435a0608bb9d96984300695f9038fdff197b662200000000");
383        let signed_transaction_hex =
384            get_signed_transaction_hex(&pay_froms, &pay_tos, &wifs, version);
385        assert_eq!(signed_transaction_hex, "020000000174e111a9173d0ac0ac01a9c590a94686dc6082d9596f41dd0d6234270aedbd57000000006a47304402200d51086e7fe52d63d57bc258d4c8846a549f9c02e141c3e26e546a04396497420220509e50be312d1ee884ed7bd19e4a70b4def3161f4301b164e878687c7d0f3c15012102693cfb0a49a9e4006255ccefef7bee362c0f3fb2c41d7066d9d11e10053fb9abfdffffff01d06b0000000000002251205b9bbd7e213e7294fe3750b7435a0608bb9d96984300695f9038fdff197b662200000000");
386    }
387}