1use std::collections::BTreeSet;
4use std::str::FromStr;
5
6use crate::error::FfiError;
7use crate::{Amount, CurrencyUnit, KeySetInfo, MintUrl, Proofs};
8
9#[derive(Debug, uniffi::Object)]
11pub struct Token {
12 pub(crate) inner: cdk::nuts::Token,
13}
14
15impl std::fmt::Display for Token {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 write!(f, "{}", self.inner)
18 }
19}
20
21impl FromStr for Token {
22 type Err = FfiError;
23
24 fn from_str(s: &str) -> Result<Self, Self::Err> {
25 let token = cdk::nuts::Token::from_str(s)
26 .map_err(|e| FfiError::internal(format!("Invalid token: {}", e)))?;
27 Ok(Token { inner: token })
28 }
29}
30
31impl From<cdk::nuts::Token> for Token {
32 fn from(token: cdk::nuts::Token) -> Self {
33 Self { inner: token }
34 }
35}
36
37impl From<Token> for cdk::nuts::Token {
38 fn from(token: Token) -> Self {
39 token.inner
40 }
41}
42
43#[uniffi::export]
44impl Token {
45 #[uniffi::constructor]
47 pub fn from_string(encoded_token: String) -> Result<Token, FfiError> {
48 let token = cdk::nuts::Token::from_str(&encoded_token)
49 .map_err(|e| FfiError::internal(format!("Invalid token: {}", e)))?;
50 Ok(Token { inner: token })
51 }
52
53 pub fn value(&self) -> Result<Amount, FfiError> {
55 Ok(self.inner.value()?.into())
56 }
57
58 pub fn memo(&self) -> Option<String> {
60 self.inner.memo().clone()
61 }
62
63 pub fn unit(&self) -> Option<CurrencyUnit> {
65 self.inner.unit().map(Into::into)
66 }
67
68 pub fn mint_url(&self) -> Result<MintUrl, FfiError> {
70 Ok(self.inner.mint_url()?.into())
71 }
72
73 pub fn proofs_simple(&self) -> Result<Proofs, FfiError> {
75 let empty_keysets = vec![];
77 let proofs = self.inner.proofs(&empty_keysets)?;
78 Ok(proofs.into_iter().map(|p| p.into()).collect())
79 }
80
81 pub fn proofs(&self, mint_keysets: Vec<KeySetInfo>) -> Result<Proofs, FfiError> {
83 let mint_keysets: Vec<_> = mint_keysets
84 .into_iter()
85 .map(TryInto::try_into)
86 .collect::<Result<_, _>>()?;
87 let proofs = self.inner.proofs(&mint_keysets)?;
88 Ok(proofs.into_iter().map(|p| p.into()).collect())
89 }
90
91 pub fn to_raw_bytes(&self) -> Result<Vec<u8>, FfiError> {
93 Ok(self.inner.to_raw_bytes()?)
94 }
95
96 pub fn encode(&self) -> String {
98 self.to_string()
99 }
100
101 #[uniffi::constructor]
103 pub fn from_raw_bytes(bytes: Vec<u8>) -> Result<Token, FfiError> {
104 let token = cdk::nuts::Token::try_from(&bytes)?;
105 Ok(Token { inner: token })
106 }
107
108 #[uniffi::constructor]
110 pub fn decode(encoded_token: String) -> Result<Token, FfiError> {
111 encoded_token.parse()
112 }
113
114 pub fn spending_conditions(&self) -> Vec<crate::types::SpendingConditions> {
116 self.inner
117 .spending_conditions()
118 .map(|set| set.into_iter().map(Into::into).collect())
119 .unwrap_or_default()
120 }
121
122 pub fn p2pk_pubkeys(&self) -> Vec<String> {
124 let set = self
125 .inner
126 .p2pk_pubkeys()
127 .map(|keys| {
128 keys.into_iter()
129 .map(|k| k.to_string())
130 .collect::<BTreeSet<_>>()
131 })
132 .unwrap_or_default();
133 set.into_iter().collect()
134 }
135
136 pub fn p2pk_refund_pubkeys(&self) -> Vec<String> {
138 let set = self
139 .inner
140 .p2pk_refund_pubkeys()
141 .map(|keys| {
142 keys.into_iter()
143 .map(|k| k.to_string())
144 .collect::<BTreeSet<_>>()
145 })
146 .unwrap_or_default();
147 set.into_iter().collect()
148 }
149
150 pub fn htlc_hashes(&self) -> Vec<String> {
152 let set = self
153 .inner
154 .htlc_hashes()
155 .map(|hashes| {
156 hashes
157 .into_iter()
158 .map(|h| h.to_string())
159 .collect::<BTreeSet<_>>()
160 })
161 .unwrap_or_default();
162 set.into_iter().collect()
163 }
164
165 pub fn locktimes(&self) -> Vec<u64> {
167 self.inner
168 .locktimes()
169 .map(|s| s.into_iter().collect())
170 .unwrap_or_default()
171 }
172}