1use std::collections::HashMap;
7use std::sync::Arc;
8
9use async_trait::async_trait;
10#[cfg(all(feature = "bip353", not(target_arch = "wasm32")))]
11use cdk_common::bitcoin;
12use cdk_common::wallet::Wallet as WalletTraitDef;
13
14use crate::error::FfiError;
15use crate::types::*;
16use crate::wallet::Wallet;
17
18#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
19#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
20impl WalletTraitDef for Wallet {
21 type Error = FfiError;
22 type Amount = Amount;
23 type MintUrl = MintUrl;
24 type CurrencyUnit = CurrencyUnit;
25 type MintInfo = MintInfo;
26 type KeySetInfo = KeySetInfo;
27 type MintQuote = MintQuote;
28 type MeltQuote = MeltQuote;
29 type PaymentMethod = PaymentMethod;
30 type MeltOptions = MeltOptions;
31 type OperationId = String;
32 type PreparedSend<'a> = Arc<PreparedSend>;
33 type PreparedMelt<'a> = PreparedMelt;
34 type Subscription = Arc<crate::types::ActiveSubscription>;
35 type SubscribeParams = crate::types::SubscribeParams;
36 type RecoveryReport = RecoveryReport;
37
38 fn mint_url(&self) -> Self::MintUrl {
39 self.inner().mint_url.clone().into()
40 }
41
42 fn unit(&self) -> Self::CurrencyUnit {
43 self.inner().unit.clone().into()
44 }
45
46 async fn total_balance(&self) -> Result<Self::Amount, Self::Error> {
47 let balance = WalletTraitDef::total_balance(self.inner().as_ref()).await?;
48 Ok(balance.into())
49 }
50
51 async fn total_pending_balance(&self) -> Result<Self::Amount, Self::Error> {
52 let balance = WalletTraitDef::total_pending_balance(self.inner().as_ref()).await?;
53 Ok(balance.into())
54 }
55
56 async fn total_reserved_balance(&self) -> Result<Self::Amount, Self::Error> {
57 let balance = WalletTraitDef::total_reserved_balance(self.inner().as_ref()).await?;
58 Ok(balance.into())
59 }
60
61 async fn fetch_mint_info(&self) -> Result<Option<Self::MintInfo>, Self::Error> {
62 let info = WalletTraitDef::fetch_mint_info(self.inner().as_ref()).await?;
63 Ok(info.map(Into::into))
64 }
65
66 async fn load_mint_info(&self) -> Result<Self::MintInfo, Self::Error> {
67 let info = WalletTraitDef::load_mint_info(self.inner().as_ref()).await?;
68 Ok(info.into())
69 }
70
71 async fn refresh_keysets(&self) -> Result<Vec<Self::KeySetInfo>, Self::Error> {
72 let keysets = WalletTraitDef::refresh_keysets(self.inner().as_ref()).await?;
73 Ok(keysets.into_iter().map(Into::into).collect())
74 }
75
76 async fn get_active_keyset(&self) -> Result<Self::KeySetInfo, Self::Error> {
77 let keyset = WalletTraitDef::get_active_keyset(self.inner().as_ref()).await?;
78 Ok(keyset.into())
79 }
80
81 async fn load_keyset_keys(
82 &self,
83 keyset_id: cdk_common::nuts::Id,
84 ) -> Result<cdk_common::nuts::Keys, Self::Error> {
85 let keys = WalletTraitDef::load_keyset_keys(self.inner().as_ref(), keyset_id).await?;
86 Ok(keys)
87 }
88
89 async fn get_mint_keysets(
90 &self,
91 filter: cdk_common::wallet::KeysetFilter,
92 ) -> Result<Vec<Self::KeySetInfo>, Self::Error> {
93 let keysets = WalletTraitDef::get_mint_keysets(self.inner().as_ref(), filter).await?;
94 Ok(keysets.into_iter().map(Into::into).collect())
95 }
96
97 async fn fetch_active_keyset(&self) -> Result<Self::KeySetInfo, Self::Error> {
98 let keyset = WalletTraitDef::fetch_active_keyset(self.inner().as_ref()).await?;
99 Ok(keyset.into())
100 }
101
102 async fn get_keyset_fees_and_amounts(
103 &self,
104 ) -> Result<cdk_common::amount::KeysetFeeAndAmounts, Self::Error> {
105 let fees = WalletTraitDef::get_keyset_fees_and_amounts(self.inner().as_ref()).await?;
106 Ok(fees)
107 }
108
109 async fn get_keyset_count_fee(
110 &self,
111 keyset_id: &cdk_common::nuts::Id,
112 count: u64,
113 ) -> Result<Self::Amount, Self::Error> {
114 let fee =
115 WalletTraitDef::get_keyset_count_fee(self.inner().as_ref(), keyset_id, count).await?;
116 Ok(fee.into())
117 }
118
119 async fn get_keyset_fees_and_amounts_by_id(
120 &self,
121 keyset_id: cdk_common::nuts::Id,
122 ) -> Result<cdk_common::amount::FeeAndAmounts, Self::Error> {
123 let fee =
124 WalletTraitDef::get_keyset_fees_and_amounts_by_id(self.inner().as_ref(), keyset_id)
125 .await?;
126 Ok(fee)
127 }
128
129 async fn mint_quote(
130 &self,
131 method: Self::PaymentMethod,
132 amount: Option<Self::Amount>,
133 description: Option<String>,
134 extra: Option<String>,
135 ) -> Result<Self::MintQuote, Self::Error> {
136 let quote = WalletTraitDef::mint_quote(
137 self.inner().as_ref(),
138 method.into(),
139 amount.map(Into::into),
140 description,
141 extra,
142 )
143 .await?;
144 Ok(quote.into())
145 }
146
147 async fn melt_quote(
148 &self,
149 method: Self::PaymentMethod,
150 request: String,
151 options: Option<Self::MeltOptions>,
152 extra: Option<String>,
153 ) -> Result<Self::MeltQuote, Self::Error> {
154 let quote = WalletTraitDef::melt_quote(
155 self.inner().as_ref(),
156 method.into(),
157 request,
158 options.map(Into::into),
159 extra,
160 )
161 .await?;
162 Ok(quote.into())
163 }
164
165 async fn list_transactions(
166 &self,
167 direction: Option<cdk_common::wallet::TransactionDirection>,
168 ) -> Result<Vec<cdk_common::wallet::Transaction>, Self::Error> {
169 let txs = WalletTraitDef::list_transactions(self.inner().as_ref(), direction).await?;
170 Ok(txs)
171 }
172
173 async fn get_transaction(
174 &self,
175 id: cdk_common::wallet::TransactionId,
176 ) -> Result<Option<cdk_common::wallet::Transaction>, Self::Error> {
177 let tx = WalletTraitDef::get_transaction(self.inner().as_ref(), id).await?;
178 Ok(tx)
179 }
180
181 async fn get_proofs_for_transaction(
182 &self,
183 id: cdk_common::wallet::TransactionId,
184 ) -> Result<cdk_common::Proofs, Self::Error> {
185 let proofs = WalletTraitDef::get_proofs_for_transaction(self.inner().as_ref(), id).await?;
186 Ok(proofs)
187 }
188
189 async fn revert_transaction(
190 &self,
191 id: cdk_common::wallet::TransactionId,
192 ) -> Result<(), Self::Error> {
193 WalletTraitDef::revert_transaction(self.inner().as_ref(), id).await?;
194 Ok(())
195 }
196
197 async fn check_all_pending_proofs(&self) -> Result<Self::Amount, Self::Error> {
198 let amount = WalletTraitDef::check_all_pending_proofs(self.inner().as_ref()).await?;
199 Ok(amount.into())
200 }
201
202 async fn recover_incomplete_sagas(&self) -> Result<Self::RecoveryReport, Self::Error> {
203 let report = WalletTraitDef::recover_incomplete_sagas(self.inner().as_ref()).await?;
204 Ok(report.into())
205 }
206
207 async fn check_proofs_spent(
208 &self,
209 proofs: cdk_common::Proofs,
210 ) -> Result<Vec<cdk_common::nuts::nut07::ProofState>, Self::Error> {
211 let states = WalletTraitDef::check_proofs_spent(self.inner().as_ref(), proofs).await?;
212 Ok(states)
213 }
214
215 async fn get_keyset_fees_by_id(
216 &self,
217 keyset_id: cdk_common::nuts::Id,
218 ) -> Result<u64, Self::Error> {
219 let fee = WalletTraitDef::get_keyset_fees_by_id(self.inner().as_ref(), keyset_id).await?;
220 Ok(fee)
221 }
222
223 async fn calculate_fee(
224 &self,
225 proof_count: u64,
226 keyset_id: cdk_common::nuts::Id,
227 ) -> Result<Self::Amount, Self::Error> {
228 let fee =
229 WalletTraitDef::calculate_fee(self.inner().as_ref(), proof_count, keyset_id).await?;
230 Ok(fee.into())
231 }
232
233 async fn receive(
234 &self,
235 encoded_token: &str,
236 options: cdk_common::wallet::ReceiveOptions,
237 ) -> Result<Self::Amount, Self::Error> {
238 let amount = WalletTraitDef::receive(self.inner().as_ref(), encoded_token, options).await?;
239 Ok(amount.into())
240 }
241
242 async fn receive_proofs(
243 &self,
244 proofs: cdk_common::Proofs,
245 options: cdk_common::wallet::ReceiveOptions,
246 memo: Option<String>,
247 token: Option<String>,
248 ) -> Result<Self::Amount, Self::Error> {
249 let amount =
250 WalletTraitDef::receive_proofs(self.inner().as_ref(), proofs, options, memo, token)
251 .await?;
252 Ok(amount.into())
253 }
254
255 async fn prepare_send(
256 &self,
257 amount: Self::Amount,
258 options: cdk_common::wallet::SendOptions,
259 ) -> Result<Arc<PreparedSend>, Self::Error> {
260 let prepared = self.inner().prepare_send(amount.into(), options).await?;
261 Ok(Arc::new(PreparedSend::new(self.inner().clone(), &prepared)))
262 }
263
264 async fn get_pending_sends(&self) -> Result<Vec<String>, Self::Error> {
265 let ids = WalletTraitDef::get_pending_sends(self.inner().as_ref()).await?;
266 Ok(ids.into_iter().map(|id| id.to_string()).collect())
267 }
268
269 async fn revoke_send(&self, operation_id: String) -> Result<Self::Amount, Self::Error> {
270 let uuid = uuid::Uuid::parse_str(&operation_id)
271 .map_err(|e| FfiError::internal(format!("Invalid operation ID: {}", e)))?;
272 let amount = WalletTraitDef::revoke_send(self.inner().as_ref(), uuid).await?;
273 Ok(amount.into())
274 }
275
276 async fn check_send_status(&self, operation_id: String) -> Result<bool, Self::Error> {
277 let uuid = uuid::Uuid::parse_str(&operation_id)
278 .map_err(|e| FfiError::internal(format!("Invalid operation ID: {}", e)))?;
279 let claimed = WalletTraitDef::check_send_status(self.inner().as_ref(), uuid).await?;
280 Ok(claimed)
281 }
282
283 async fn mint(
284 &self,
285 quote_id: &str,
286 split_target: cdk_common::amount::SplitTarget,
287 spending_conditions: Option<cdk_common::nuts::SpendingConditions>,
288 ) -> Result<cdk_common::Proofs, Self::Error> {
289 let proofs = WalletTraitDef::mint(
290 self.inner().as_ref(),
291 quote_id,
292 split_target,
293 spending_conditions,
294 )
295 .await?;
296 Ok(proofs)
297 }
298
299 async fn check_mint_quote_status(
300 &self,
301 quote_id: &str,
302 ) -> Result<Self::MintQuote, Self::Error> {
303 let quote =
304 WalletTraitDef::check_mint_quote_status(self.inner().as_ref(), quote_id).await?;
305 Ok(quote.into())
306 }
307
308 async fn fetch_mint_quote(
309 &self,
310 quote_id: &str,
311 payment_method: Option<Self::PaymentMethod>,
312 ) -> Result<Self::MintQuote, Self::Error> {
313 let method = payment_method.map(Into::into);
314 let quote =
315 WalletTraitDef::fetch_mint_quote(self.inner().as_ref(), quote_id, method).await?;
316 Ok(quote.into())
317 }
318
319 async fn prepare_melt(
320 &self,
321 quote_id: &str,
322 metadata: HashMap<String, String>,
323 ) -> Result<PreparedMelt, Self::Error> {
324 let prepared = self.inner().prepare_melt(quote_id, metadata).await?;
325 Ok(PreparedMelt::new(self.inner().clone(), &prepared))
326 }
327
328 async fn prepare_melt_proofs(
329 &self,
330 quote_id: &str,
331 proofs: cdk_common::Proofs,
332 metadata: HashMap<String, String>,
333 ) -> Result<PreparedMelt, Self::Error> {
334 let prepared = self
335 .inner()
336 .prepare_melt_proofs(quote_id, proofs, metadata)
337 .await?;
338 Ok(PreparedMelt::new(self.inner().clone(), &prepared))
339 }
340
341 async fn prepare_melt_token(
342 &self,
343 quote_id: &str,
344 encoded_token: &str,
345 metadata: HashMap<String, String>,
346 ) -> Result<PreparedMelt, Self::Error> {
347 let prepared = self
348 .inner()
349 .prepare_melt_token(quote_id, encoded_token, metadata)
350 .await?;
351 Ok(PreparedMelt::new(self.inner().clone(), &prepared))
352 }
353
354 async fn swap(
355 &self,
356 amount: Option<Self::Amount>,
357 split_target: cdk_common::amount::SplitTarget,
358 input_proofs: cdk_common::Proofs,
359 spending_conditions: Option<cdk_common::nuts::SpendingConditions>,
360 include_fees: bool,
361 use_p2bk: bool,
362 ) -> Result<Option<cdk_common::Proofs>, Self::Error> {
363 let result = WalletTraitDef::swap(
364 self.inner().as_ref(),
365 amount.map(Into::into),
366 split_target,
367 input_proofs,
368 spending_conditions,
369 include_fees,
370 use_p2bk,
371 )
372 .await?;
373 Ok(result)
374 }
375
376 async fn set_cat(&self, cat: String) -> Result<(), Self::Error> {
377 WalletTraitDef::set_cat(self.inner().as_ref(), cat).await?;
378 Ok(())
379 }
380
381 async fn set_refresh_token(&self, refresh_token: String) -> Result<(), Self::Error> {
382 WalletTraitDef::set_refresh_token(self.inner().as_ref(), refresh_token).await?;
383 Ok(())
384 }
385
386 async fn refresh_access_token(&self) -> Result<(), Self::Error> {
387 WalletTraitDef::refresh_access_token(self.inner().as_ref()).await?;
388 Ok(())
389 }
390
391 async fn mint_blind_auth(
392 &self,
393 amount: Self::Amount,
394 ) -> Result<cdk_common::Proofs, Self::Error> {
395 let proofs = WalletTraitDef::mint_blind_auth(self.inner().as_ref(), amount.into()).await?;
396 Ok(proofs)
397 }
398
399 async fn get_unspent_auth_proofs(
400 &self,
401 ) -> Result<Vec<cdk_common::nuts::AuthProof>, Self::Error> {
402 let proofs = WalletTraitDef::get_unspent_auth_proofs(self.inner().as_ref()).await?;
403 Ok(proofs)
404 }
405
406 async fn restore(&self) -> Result<cdk_common::wallet::Restored, Self::Error> {
407 let restored = WalletTraitDef::restore(self.inner().as_ref()).await?;
408 Ok(restored)
409 }
410
411 async fn restore_with_opts(
412 &self,
413 opts: cdk_common::wallet::NUT13Options,
414 ) -> Result<cdk_common::wallet::Restored, Self::Error> {
415 let restored = WalletTraitDef::restore_with_opts(self.inner().as_ref(), opts).await?;
416 Ok(restored)
417 }
418
419 async fn verify_token_dleq(&self, token_str: &str) -> Result<(), Self::Error> {
420 WalletTraitDef::verify_token_dleq(self.inner().as_ref(), token_str).await?;
421 Ok(())
422 }
423
424 async fn pay_request(
425 &self,
426 request: cdk_common::nuts::nut18::PaymentRequest,
427 custom_amount: Option<Self::Amount>,
428 ) -> Result<(), Self::Error> {
429 WalletTraitDef::pay_request(
430 self.inner().as_ref(),
431 request,
432 custom_amount.map(Into::into),
433 )
434 .await?;
435 Ok(())
436 }
437
438 async fn subscribe_mint_quote_state(
439 &self,
440 quote_ids: Vec<String>,
441 method: Self::PaymentMethod,
442 ) -> Result<Arc<crate::types::ActiveSubscription>, Self::Error> {
443 let cdk_sub = WalletTraitDef::subscribe_mint_quote_state(
444 self.inner().as_ref(),
445 quote_ids,
446 method.into(),
447 )
448 .await?;
449 let sub_id = uuid::Uuid::new_v4().to_string();
450 Ok(Arc::new(crate::types::ActiveSubscription::new(
451 cdk_sub, sub_id,
452 )))
453 }
454
455 fn set_metadata_cache_ttl(&self, ttl_secs: Option<u64>) {
456 let ttl = ttl_secs.map(std::time::Duration::from_secs);
457 self.inner().set_metadata_cache_ttl(ttl);
458 }
459
460 async fn subscribe(
461 &self,
462 params: crate::types::SubscribeParams,
463 ) -> Result<Arc<crate::types::ActiveSubscription>, Self::Error> {
464 let cdk_params: cdk_common::subscription::WalletParams = params.into();
465 let sub_id = cdk_params.id.to_string();
466 let active_sub = WalletTraitDef::subscribe(self.inner().as_ref(), cdk_params).await?;
467 Ok(Arc::new(crate::types::ActiveSubscription::new(
468 active_sub, sub_id,
469 )))
470 }
471
472 #[cfg(all(feature = "bip353", not(target_arch = "wasm32")))]
473 async fn melt_bip353_quote(
474 &self,
475 bip353_address: &str,
476 amount_msat: Self::Amount,
477 network: bitcoin::Network,
478 ) -> Result<Self::MeltQuote, Self::Error> {
479 let cdk_amount: cdk_common::Amount = amount_msat.into();
480 let quote = self
481 .inner()
482 .melt_bip353_quote(bip353_address, cdk_amount, network)
483 .await?;
484 Ok(quote.into())
485 }
486
487 #[cfg(not(target_arch = "wasm32"))]
488 async fn melt_lightning_address_quote(
489 &self,
490 lightning_address: &str,
491 amount_msat: Self::Amount,
492 ) -> Result<Self::MeltQuote, Self::Error> {
493 let cdk_amount: cdk_common::Amount = amount_msat.into();
494 let quote = self
495 .inner()
496 .melt_lightning_address_quote(lightning_address, cdk_amount)
497 .await?;
498 Ok(quote.into())
499 }
500
501 #[cfg(all(feature = "bip353", not(target_arch = "wasm32")))]
502 async fn melt_human_readable_quote(
503 &self,
504 address: &str,
505 amount_msat: Self::Amount,
506 network: bitcoin::Network,
507 ) -> Result<Self::MeltQuote, Self::Error> {
508 let cdk_amount: cdk_common::Amount = amount_msat.into();
509 let quote = self
510 .inner()
511 .melt_human_readable_quote(address, cdk_amount, network)
512 .await?;
513 Ok(quote.into())
514 }
515
516 async fn get_proofs_by_states(
517 &self,
518 states: Vec<cdk_common::nuts::State>,
519 ) -> Result<cdk_common::Proofs, Self::Error> {
520 let proofs = WalletTraitDef::get_proofs_by_states(self.inner().as_ref(), states).await?;
521 Ok(proofs)
522 }
523
524 async fn generate_public_key(&self) -> Result<cdk::nuts::PublicKey, Self::Error> {
526 let quote = WalletTraitDef::generate_public_key(self.inner().as_ref()).await?;
527 Ok(quote)
528 }
529
530 async fn get_public_key(
532 &self,
533 pubkey: &cdk::nuts::PublicKey,
534 ) -> Result<Option<cdk_common::wallet::P2PKSigningKey>, Self::Error> {
535 let pubkey = WalletTraitDef::get_public_key(self.inner().as_ref(), pubkey).await?;
536 Ok(pubkey)
537 }
538
539 async fn get_public_keys(
541 &self,
542 ) -> Result<Vec<cdk_common::wallet::P2PKSigningKey>, Self::Error> {
543 let pubkeys = WalletTraitDef::get_public_keys(self.inner().as_ref()).await?;
544 Ok(pubkeys)
545 }
546
547 async fn get_latest_public_key(
549 &self,
550 ) -> Result<Option<cdk_common::wallet::P2PKSigningKey>, Self::Error> {
551 let pubkey = WalletTraitDef::get_latest_public_key(self.inner().as_ref()).await?;
552 Ok(pubkey)
553 }
554
555 async fn get_signing_key(
557 &self,
558 pubkey: &cdk::nuts::PublicKey,
559 ) -> Result<Option<cdk::nuts::SecretKey>, Self::Error> {
560 let signing_key = WalletTraitDef::get_signing_key(self.inner().as_ref(), pubkey).await?;
561 Ok(signing_key)
562 }
563}