1use elements::{hex::ToHex, pset::serialize::Deserialize};
4
5use crate::{types::Hex, LwkError};
6use std::{fmt::Display, sync::Arc};
7
8#[derive(uniffi::Object)]
10#[uniffi::export(Display)]
11pub struct Script {
12 inner: elements::Script,
13}
14
15impl From<elements::Script> for Script {
16 fn from(inner: elements::Script) -> Self {
17 Self { inner }
18 }
19}
20
21impl From<Script> for elements::Script {
22 fn from(script: Script) -> elements::Script {
23 script.inner
24 }
25}
26
27impl From<&Script> for elements::Script {
28 fn from(script: &Script) -> elements::Script {
29 script.inner.clone()
30 }
31}
32
33impl Display for Script {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 write!(f, "{}", self.inner.to_hex())
36 }
37}
38
39#[uniffi::export]
40impl Script {
41 #[uniffi::constructor]
44 pub fn new(hex: &Hex) -> Result<Arc<Self>, LwkError> {
45 let inner = elements::Script::deserialize(hex.as_ref())?;
46 Ok(Arc::new(Self { inner }))
47 }
48
49 pub fn bytes(&self) -> Vec<u8> {
51 self.inner.as_bytes().to_vec()
52 }
53
54 pub fn to_asm(&self) -> String {
58 self.inner.asm()
59 }
60
61 pub fn is_provably_unspendable(&self) -> bool {
63 self.inner.is_provably_unspendable()
64 }
65}
66
67#[uniffi::export]
69pub fn is_provably_segwit(script_pubkey: &Script, redeem_script: &Option<Arc<Script>>) -> bool {
70 lwk_common::is_provably_segwit(
71 &script_pubkey.into(),
72 &redeem_script.as_ref().map(|s| s.as_ref().into()),
73 )
74}
75
76#[cfg(test)]
77mod tests {
78 use elements::hashes::hex::FromHex;
79
80 use super::{is_provably_segwit, Script};
81
82 #[test]
83 fn script() {
84 let script_str = "0020d2e99f0c38089c08e5e1080ff6658c6075afaa7699d384333d956c470881afde";
85
86 let script = Script::new(&script_str.parse().unwrap()).unwrap();
87 assert_eq!(script.to_string(), script_str);
88
89 let script_bytes = Vec::<u8>::from_hex(script_str).unwrap();
90 assert_eq!(script.bytes(), script_bytes);
91
92 assert_eq!(
93 script.to_asm(),
94 "OP_0 OP_PUSHBYTES_32 d2e99f0c38089c08e5e1080ff6658c6075afaa7699d384333d956c470881afde"
95 );
96
97 assert!(is_provably_segwit(&script, &None));
98
99 let burn = Script::new(&"6a".parse().unwrap()).unwrap();
100 assert!(burn.is_provably_unspendable());
101 }
102}