Skip to main content

cdk_ffi/types/
keys.rs

1//! Key-related FFI types
2
3use std::collections::HashMap;
4
5use serde::{Deserialize, Serialize};
6
7use super::amount::CurrencyUnit;
8use crate::error::FfiError;
9
10/// FFI-compatible KeySetInfo
11#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Record)]
12pub struct KeySetInfo {
13    pub id: String,
14    pub unit: CurrencyUnit,
15    pub active: bool,
16    /// Input fee per thousand (ppk)
17    pub input_fee_ppk: u64,
18}
19
20impl From<cdk::nuts::KeySetInfo> for KeySetInfo {
21    fn from(keyset: cdk::nuts::KeySetInfo) -> Self {
22        Self {
23            id: keyset.id.to_string(),
24            unit: keyset.unit.into(),
25            active: keyset.active,
26            input_fee_ppk: keyset.input_fee_ppk,
27        }
28    }
29}
30
31impl From<KeySetInfo> for cdk::nuts::KeySetInfo {
32    fn from(keyset: KeySetInfo) -> Self {
33        use std::str::FromStr;
34        Self {
35            id: cdk::nuts::Id::from_str(&keyset.id).expect("Invalid keyset ID"),
36            unit: keyset.unit.into(),
37            active: keyset.active,
38            final_expiry: None,
39            input_fee_ppk: keyset.input_fee_ppk,
40        }
41    }
42}
43
44impl KeySetInfo {
45    /// Convert KeySetInfo to JSON string
46    pub fn to_json(&self) -> Result<String, FfiError> {
47        Ok(serde_json::to_string(self)?)
48    }
49}
50
51/// Decode KeySetInfo from JSON string
52#[uniffi::export]
53pub fn decode_key_set_info(json: String) -> Result<KeySetInfo, FfiError> {
54    Ok(serde_json::from_str(&json)?)
55}
56
57/// Encode KeySetInfo to JSON string
58#[uniffi::export]
59pub fn encode_key_set_info(info: KeySetInfo) -> Result<String, FfiError> {
60    Ok(serde_json::to_string(&info)?)
61}
62
63/// FFI-compatible PublicKey
64#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Record)]
65#[serde(transparent)]
66pub struct PublicKey {
67    /// Hex-encoded public key
68    pub hex: String,
69}
70
71impl From<cdk::nuts::PublicKey> for PublicKey {
72    fn from(key: cdk::nuts::PublicKey) -> Self {
73        Self {
74            hex: key.to_string(),
75        }
76    }
77}
78
79impl TryFrom<PublicKey> for cdk::nuts::PublicKey {
80    type Error = FfiError;
81
82    fn try_from(key: PublicKey) -> Result<Self, Self::Error> {
83        key.hex
84            .parse()
85            .map_err(|e| FfiError::internal(format!("Invalid public key: {}", e)))
86    }
87}
88
89/// FFI-compatible Keys (simplified - contains only essential info)
90#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Record)]
91pub struct Keys {
92    /// Keyset ID
93    pub id: String,
94    /// Currency unit
95    pub unit: CurrencyUnit,
96    /// Map of amount to public key hex (simplified from BTreeMap)
97    pub keys: HashMap<u64, String>,
98}
99
100impl From<cdk::nuts::Keys> for Keys {
101    fn from(keys: cdk::nuts::Keys) -> Self {
102        // Keys doesn't have id and unit - we'll need to get these from context
103        // For now, use placeholder values
104        Self {
105            id: "unknown".to_string(), // This should come from KeySet
106            unit: CurrencyUnit::Sat,   // This should come from KeySet
107            keys: keys
108                .keys()
109                .iter()
110                .map(|(amount, pubkey)| (u64::from(*amount), pubkey.to_string()))
111                .collect(),
112        }
113    }
114}
115
116impl TryFrom<Keys> for cdk::nuts::Keys {
117    type Error = FfiError;
118
119    fn try_from(keys: Keys) -> Result<Self, Self::Error> {
120        use std::collections::BTreeMap;
121        use std::str::FromStr;
122
123        // Convert the HashMap to BTreeMap with proper types
124        let mut keys_map = BTreeMap::new();
125        for (amount_u64, pubkey_hex) in keys.keys {
126            let amount = cdk::Amount::from(amount_u64);
127            let pubkey = cdk::nuts::PublicKey::from_str(&pubkey_hex)
128                .map_err(|e| FfiError::internal(format!("Invalid public key: {}", e)))?;
129            keys_map.insert(amount, pubkey);
130        }
131
132        Ok(cdk::nuts::Keys::new(keys_map))
133    }
134}
135
136impl Keys {
137    /// Convert Keys to JSON string
138    pub fn to_json(&self) -> Result<String, FfiError> {
139        Ok(serde_json::to_string(self)?)
140    }
141}
142
143/// Decode Keys from JSON string
144#[uniffi::export]
145pub fn decode_keys(json: String) -> Result<Keys, FfiError> {
146    Ok(serde_json::from_str(&json)?)
147}
148
149/// Encode Keys to JSON string
150#[uniffi::export]
151pub fn encode_keys(keys: Keys) -> Result<String, FfiError> {
152    Ok(serde_json::to_string(&keys)?)
153}
154
155/// FFI-compatible KeySet
156#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Record)]
157pub struct KeySet {
158    /// Keyset ID
159    pub id: String,
160    /// Currency unit
161    pub unit: CurrencyUnit,
162    /// Keyset state - indicates whether the mint will sign new outputs with this keyset
163    pub active: Option<bool>,
164    /// Input fee in parts per thousand (ppk) per input spent from this keyset
165    pub input_fee_ppk: u64,
166    /// The keys (map of amount to public key hex)
167    pub keys: HashMap<u64, String>,
168    /// Optional expiry timestamp
169    pub final_expiry: Option<u64>,
170}
171
172impl From<cdk::nuts::KeySet> for KeySet {
173    fn from(keyset: cdk::nuts::KeySet) -> Self {
174        Self {
175            id: keyset.id.to_string(),
176            unit: keyset.unit.into(),
177            active: keyset.active,
178            input_fee_ppk: keyset.input_fee_ppk,
179            keys: keyset
180                .keys
181                .keys()
182                .iter()
183                .map(|(amount, pubkey)| (u64::from(*amount), pubkey.to_string()))
184                .collect(),
185            final_expiry: keyset.final_expiry,
186        }
187    }
188}
189
190impl TryFrom<KeySet> for cdk::nuts::KeySet {
191    type Error = FfiError;
192
193    fn try_from(keyset: KeySet) -> Result<Self, Self::Error> {
194        use std::collections::BTreeMap;
195        use std::str::FromStr;
196
197        // Convert id
198        let id = cdk::nuts::Id::from_str(&keyset.id)
199            .map_err(|e| FfiError::internal(format!("Invalid keyset ID: {}", e)))?;
200
201        // Convert unit
202        let unit: cdk::nuts::CurrencyUnit = keyset.unit.into();
203
204        // Convert keys
205        let mut keys_map = BTreeMap::new();
206        for (amount_u64, pubkey_hex) in keyset.keys {
207            let amount = cdk::Amount::from(amount_u64);
208            let pubkey = cdk::nuts::PublicKey::from_str(&pubkey_hex)
209                .map_err(|e| FfiError::internal(format!("Invalid public key: {}", e)))?;
210            keys_map.insert(amount, pubkey);
211        }
212        let keys = cdk::nuts::Keys::new(keys_map);
213
214        Ok(cdk::nuts::KeySet {
215            id,
216            unit,
217            active: keyset.active,
218            input_fee_ppk: keyset.input_fee_ppk,
219            keys,
220            final_expiry: keyset.final_expiry,
221        })
222    }
223}
224
225impl KeySet {
226    /// Convert KeySet to JSON string
227    pub fn to_json(&self) -> Result<String, FfiError> {
228        Ok(serde_json::to_string(self)?)
229    }
230}
231
232/// Decode KeySet from JSON string
233#[uniffi::export]
234pub fn decode_key_set(json: String) -> Result<KeySet, FfiError> {
235    Ok(serde_json::from_str(&json)?)
236}
237
238/// Encode KeySet to JSON string
239#[uniffi::export]
240pub fn encode_key_set(keyset: KeySet) -> Result<String, FfiError> {
241    Ok(serde_json::to_string(&keyset)?)
242}
243
244/// FFI-compatible Id (for keyset IDs)
245#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Record)]
246#[serde(transparent)]
247pub struct Id {
248    pub hex: String,
249}
250
251impl From<cdk::nuts::Id> for Id {
252    fn from(id: cdk::nuts::Id) -> Self {
253        Self {
254            hex: id.to_string(),
255        }
256    }
257}
258
259impl From<Id> for cdk::nuts::Id {
260    fn from(id: Id) -> Self {
261        use std::str::FromStr;
262        Self::from_str(&id.hex).expect("Invalid ID hex")
263    }
264}