1use std::collections::HashMap;
4use std::sync::Arc;
5
6use cdk_common::bitcoin::bip32::DerivationPath;
7use cdk_common::database::WalletDatabase as CdkWalletDatabase;
8use cdk_common::wallet::WalletSaga;
9
10use crate::error::FfiError;
11#[cfg(feature = "postgres")]
12use crate::postgres::WalletPostgresDatabase;
13use crate::sqlite::WalletSqliteDatabase;
14use crate::types::*;
15
16#[uniffi::export(with_foreign)]
19#[async_trait::async_trait]
20pub trait WalletDatabase: Send + Sync {
21 async fn get_mint(&self, mint_url: MintUrl) -> Result<Option<MintInfo>, FfiError>;
25
26 async fn get_mints(&self) -> Result<HashMap<MintUrl, Option<MintInfo>>, FfiError>;
28
29 async fn get_mint_keysets(
31 &self,
32 mint_url: MintUrl,
33 ) -> Result<Option<Vec<KeySetInfo>>, FfiError>;
34
35 async fn get_keyset_by_id(&self, keyset_id: Id) -> Result<Option<KeySetInfo>, FfiError>;
37
38 async fn get_mint_quote(&self, quote_id: String) -> Result<Option<MintQuote>, FfiError>;
40
41 async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, FfiError>;
43
44 async fn get_unissued_mint_quotes(&self) -> Result<Vec<MintQuote>, FfiError>;
47
48 async fn get_melt_quote(&self, quote_id: String) -> Result<Option<MeltQuote>, FfiError>;
50
51 async fn get_melt_quotes(&self) -> Result<Vec<MeltQuote>, FfiError>;
53
54 async fn get_keys(&self, id: Id) -> Result<Option<Keys>, FfiError>;
56
57 async fn get_proofs(
59 &self,
60 mint_url: Option<MintUrl>,
61 unit: Option<CurrencyUnit>,
62 state: Option<Vec<ProofState>>,
63 spending_conditions: Option<Vec<SpendingConditions>>,
64 ) -> Result<Vec<ProofInfo>, FfiError>;
65
66 async fn get_proofs_by_ys(&self, ys: Vec<PublicKey>) -> Result<Vec<ProofInfo>, FfiError>;
68
69 async fn get_balance(
71 &self,
72 mint_url: Option<MintUrl>,
73 unit: Option<CurrencyUnit>,
74 state: Option<Vec<ProofState>>,
75 ) -> Result<u64, FfiError>;
76
77 async fn get_transaction(
79 &self,
80 transaction_id: TransactionId,
81 ) -> Result<Option<Transaction>, FfiError>;
82
83 async fn list_transactions(
85 &self,
86 mint_url: Option<MintUrl>,
87 direction: Option<TransactionDirection>,
88 unit: Option<CurrencyUnit>,
89 ) -> Result<Vec<Transaction>, FfiError>;
90
91 async fn kv_read(
93 &self,
94 primary_namespace: String,
95 secondary_namespace: String,
96 key: String,
97 ) -> Result<Option<Vec<u8>>, FfiError>;
98
99 async fn kv_list(
101 &self,
102 primary_namespace: String,
103 secondary_namespace: String,
104 ) -> Result<Vec<String>, FfiError>;
105
106 async fn add_p2pk_key(
108 &self,
109 pubkey: PublicKey,
110 derivation_path: String,
111 derivation_index: u32,
112 ) -> Result<(), FfiError>;
113
114 async fn get_p2pk_key(&self, pubkey: PublicKey) -> Result<Option<P2PKSigningKey>, FfiError>;
116
117 async fn list_p2pk_keys(&self) -> Result<Vec<P2PKSigningKey>, FfiError>;
119
120 async fn latest_p2pk(&self) -> Result<Option<P2PKSigningKey>, FfiError>;
122
123 async fn kv_write(
125 &self,
126 primary_namespace: String,
127 secondary_namespace: String,
128 key: String,
129 value: Vec<u8>,
130 ) -> Result<(), FfiError>;
131
132 async fn kv_remove(
134 &self,
135 primary_namespace: String,
136 secondary_namespace: String,
137 key: String,
138 ) -> Result<(), FfiError>;
139
140 async fn update_proofs(
144 &self,
145 added: Vec<ProofInfo>,
146 removed_ys: Vec<PublicKey>,
147 ) -> Result<(), FfiError>;
148
149 async fn update_proofs_state(
151 &self,
152 ys: Vec<PublicKey>,
153 state: ProofState,
154 ) -> Result<(), FfiError>;
155
156 async fn add_transaction(&self, transaction: Transaction) -> Result<(), FfiError>;
158
159 async fn remove_transaction(&self, transaction_id: TransactionId) -> Result<(), FfiError>;
161
162 async fn update_mint_url(
164 &self,
165 old_mint_url: MintUrl,
166 new_mint_url: MintUrl,
167 ) -> Result<(), FfiError>;
168
169 async fn increment_keyset_counter(&self, keyset_id: Id, count: u32) -> Result<u32, FfiError>;
171
172 async fn add_mint(
174 &self,
175 mint_url: MintUrl,
176 mint_info: Option<MintInfo>,
177 ) -> Result<(), FfiError>;
178
179 async fn remove_mint(&self, mint_url: MintUrl) -> Result<(), FfiError>;
181
182 async fn add_mint_keysets(
184 &self,
185 mint_url: MintUrl,
186 keysets: Vec<KeySetInfo>,
187 ) -> Result<(), FfiError>;
188
189 async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), FfiError>;
191
192 async fn remove_mint_quote(&self, quote_id: String) -> Result<(), FfiError>;
194
195 async fn add_melt_quote(&self, quote: MeltQuote) -> Result<(), FfiError>;
197
198 async fn remove_melt_quote(&self, quote_id: String) -> Result<(), FfiError>;
200
201 async fn add_keys(&self, keyset: KeySet) -> Result<(), FfiError>;
203
204 async fn remove_keys(&self, id: Id) -> Result<(), FfiError>;
206
207 async fn add_saga(&self, saga_json: String) -> Result<(), FfiError>;
212
213 async fn get_saga(&self, id: String) -> Result<Option<String>, FfiError>;
215
216 async fn update_saga(&self, saga_json: String) -> Result<bool, FfiError>;
221
222 async fn delete_saga(&self, id: String) -> Result<(), FfiError>;
224
225 async fn get_incomplete_sagas(&self) -> Result<Vec<String>, FfiError>;
227
228 async fn reserve_proofs(
232 &self,
233 ys: Vec<PublicKey>,
234 operation_id: String,
235 ) -> Result<(), FfiError>;
236
237 async fn release_proofs(&self, operation_id: String) -> Result<(), FfiError>;
239
240 async fn get_reserved_proofs(&self, operation_id: String) -> Result<Vec<ProofInfo>, FfiError>;
242
243 async fn reserve_melt_quote(
247 &self,
248 quote_id: String,
249 operation_id: String,
250 ) -> Result<(), FfiError>;
251
252 async fn release_melt_quote(&self, operation_id: String) -> Result<(), FfiError>;
254
255 async fn reserve_mint_quote(
257 &self,
258 quote_id: String,
259 operation_id: String,
260 ) -> Result<(), FfiError>;
261
262 async fn release_mint_quote(&self, operation_id: String) -> Result<(), FfiError>;
264}
265
266struct WalletDatabaseBridge {
269 ffi_db: Arc<dyn WalletDatabase>,
270}
271
272impl WalletDatabaseBridge {
273 fn new(ffi_db: Arc<dyn WalletDatabase>) -> Self {
274 Self { ffi_db }
275 }
276}
277
278impl std::fmt::Debug for WalletDatabaseBridge {
279 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
280 write!(f, "WalletDatabaseBridge")
281 }
282}
283
284#[async_trait::async_trait]
285impl CdkWalletDatabase<cdk::cdk_database::Error> for WalletDatabaseBridge {
286 async fn kv_read(
287 &self,
288 primary_namespace: &str,
289 secondary_namespace: &str,
290 key: &str,
291 ) -> Result<Option<Vec<u8>>, cdk::cdk_database::Error> {
292 self.ffi_db
293 .kv_read(
294 primary_namespace.to_string(),
295 secondary_namespace.to_string(),
296 key.to_string(),
297 )
298 .await
299 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
300 }
301
302 async fn kv_list(
303 &self,
304 primary_namespace: &str,
305 secondary_namespace: &str,
306 ) -> Result<Vec<String>, cdk::cdk_database::Error> {
307 self.ffi_db
308 .kv_list(
309 primary_namespace.to_string(),
310 secondary_namespace.to_string(),
311 )
312 .await
313 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
314 }
315
316 async fn get_mint(
318 &self,
319 mint_url: cdk::mint_url::MintUrl,
320 ) -> Result<Option<cdk::nuts::MintInfo>, cdk::cdk_database::Error> {
321 let ffi_mint_url = mint_url.into();
322 let result = self
323 .ffi_db
324 .get_mint(ffi_mint_url)
325 .await
326 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
327 result
328 .map(TryInto::try_into)
329 .transpose()
330 .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))
331 }
332
333 async fn get_mints(
334 &self,
335 ) -> Result<
336 HashMap<cdk::mint_url::MintUrl, Option<cdk::nuts::MintInfo>>,
337 cdk::cdk_database::Error,
338 > {
339 let result = self
340 .ffi_db
341 .get_mints()
342 .await
343 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
344
345 let mut cdk_result = HashMap::new();
346 for (ffi_mint_url, mint_info_opt) in result {
347 let cdk_url = ffi_mint_url
348 .try_into()
349 .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))?;
350 let cdk_mint_info = mint_info_opt
351 .map(TryInto::try_into)
352 .transpose()
353 .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))?;
354 cdk_result.insert(cdk_url, cdk_mint_info);
355 }
356 Ok(cdk_result)
357 }
358
359 async fn get_mint_keysets(
361 &self,
362 mint_url: cdk::mint_url::MintUrl,
363 ) -> Result<Option<Vec<cdk::nuts::KeySetInfo>>, cdk::cdk_database::Error> {
364 let ffi_mint_url = mint_url.into();
365 let result = self
366 .ffi_db
367 .get_mint_keysets(ffi_mint_url)
368 .await
369 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
370 let cdk_keysets = result
371 .map(|keysets| {
372 keysets
373 .into_iter()
374 .map(TryInto::try_into)
375 .collect::<Result<Vec<_>, _>>()
376 })
377 .transpose()
378 .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))?;
379
380 Ok(cdk_keysets)
381 }
382
383 async fn get_keyset_by_id(
384 &self,
385 keyset_id: &cdk::nuts::Id,
386 ) -> Result<Option<cdk::nuts::KeySetInfo>, cdk::cdk_database::Error> {
387 let ffi_id = (*keyset_id).into();
388 let result = self
389 .ffi_db
390 .get_keyset_by_id(ffi_id)
391 .await
392 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
393 let cdk_keyset = result
394 .map(TryInto::try_into)
395 .transpose()
396 .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))?;
397
398 Ok(cdk_keyset)
399 }
400
401 async fn get_mint_quote(
403 &self,
404 quote_id: &str,
405 ) -> Result<Option<cdk::wallet::MintQuote>, cdk::cdk_database::Error> {
406 let result = self
407 .ffi_db
408 .get_mint_quote(quote_id.to_string())
409 .await
410 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
411 Ok(result
412 .map(|q| {
413 q.try_into()
414 .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))
415 })
416 .transpose()?)
417 }
418
419 async fn get_mint_quotes(
420 &self,
421 ) -> Result<Vec<cdk::wallet::MintQuote>, cdk::cdk_database::Error> {
422 let result = self
423 .ffi_db
424 .get_mint_quotes()
425 .await
426 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
427 Ok(result
428 .into_iter()
429 .map(|q| {
430 q.try_into()
431 .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))
432 })
433 .collect::<Result<Vec<_>, _>>()?)
434 }
435
436 async fn get_unissued_mint_quotes(
437 &self,
438 ) -> Result<Vec<cdk::wallet::MintQuote>, cdk::cdk_database::Error> {
439 let result = self
440 .ffi_db
441 .get_unissued_mint_quotes()
442 .await
443 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
444 Ok(result
445 .into_iter()
446 .map(|q| {
447 q.try_into()
448 .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))
449 })
450 .collect::<Result<Vec<_>, _>>()?)
451 }
452
453 async fn get_melt_quote(
455 &self,
456 quote_id: &str,
457 ) -> Result<Option<cdk::wallet::MeltQuote>, cdk::cdk_database::Error> {
458 let result = self
459 .ffi_db
460 .get_melt_quote(quote_id.to_string())
461 .await
462 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
463 Ok(result
464 .map(|q| {
465 q.try_into()
466 .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))
467 })
468 .transpose()?)
469 }
470
471 async fn get_melt_quotes(
472 &self,
473 ) -> Result<Vec<cdk::wallet::MeltQuote>, cdk::cdk_database::Error> {
474 let result = self
475 .ffi_db
476 .get_melt_quotes()
477 .await
478 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
479 Ok(result
480 .into_iter()
481 .map(|q| {
482 q.try_into()
483 .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))
484 })
485 .collect::<Result<Vec<_>, _>>()?)
486 }
487
488 async fn get_keys(
490 &self,
491 id: &cdk::nuts::Id,
492 ) -> Result<Option<cdk::nuts::Keys>, cdk::cdk_database::Error> {
493 let ffi_id: Id = (*id).into();
494 let result = self
495 .ffi_db
496 .get_keys(ffi_id)
497 .await
498 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
499
500 result
502 .map(|ffi_keys| {
503 ffi_keys
504 .try_into()
505 .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))
506 })
507 .transpose()
508 }
509
510 async fn get_proofs(
512 &self,
513 mint_url: Option<cdk::mint_url::MintUrl>,
514 unit: Option<cdk::nuts::CurrencyUnit>,
515 state: Option<Vec<cdk::nuts::State>>,
516 spending_conditions: Option<Vec<cdk::nuts::SpendingConditions>>,
517 ) -> Result<Vec<cdk::types::ProofInfo>, cdk::cdk_database::Error> {
518 let ffi_mint_url = mint_url.map(Into::into);
519 let ffi_unit = unit.map(Into::into);
520 let ffi_state = state.map(|s| s.into_iter().map(Into::into).collect());
521 let ffi_spending_conditions =
522 spending_conditions.map(|sc| sc.into_iter().map(Into::into).collect());
523
524 let result = self
525 .ffi_db
526 .get_proofs(ffi_mint_url, ffi_unit, ffi_state, ffi_spending_conditions)
527 .await
528 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
529
530 let cdk_result: Result<Vec<cdk::types::ProofInfo>, cdk::cdk_database::Error> = result
532 .into_iter()
533 .map(|info| {
534 Ok(cdk::types::ProofInfo {
535 proof: info.proof.try_into().map_err(|e: FfiError| {
536 cdk::cdk_database::Error::Database(e.to_string().into())
537 })?,
538 y: info.y.try_into().map_err(|e: FfiError| {
539 cdk::cdk_database::Error::Database(e.to_string().into())
540 })?,
541 mint_url: info.mint_url.try_into().map_err(|e: FfiError| {
542 cdk::cdk_database::Error::Database(e.to_string().into())
543 })?,
544 state: info.state.into(),
545 spending_condition: info
546 .spending_condition
547 .map(|sc| sc.try_into())
548 .transpose()
549 .map_err(|e: FfiError| {
550 cdk::cdk_database::Error::Database(e.to_string().into())
551 })?,
552 unit: info.unit.into(),
553 used_by_operation: info
554 .used_by_operation
555 .map(|id| uuid::Uuid::parse_str(&id))
556 .transpose()
557 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?,
558 created_by_operation: info
559 .created_by_operation
560 .map(|id| uuid::Uuid::parse_str(&id))
561 .transpose()
562 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?,
563 })
564 })
565 .collect();
566
567 cdk_result
568 }
569
570 async fn get_proofs_by_ys(
571 &self,
572 ys: Vec<cdk::nuts::PublicKey>,
573 ) -> Result<Vec<cdk::types::ProofInfo>, cdk::cdk_database::Error> {
574 let ffi_ys: Vec<PublicKey> = ys.into_iter().map(Into::into).collect();
575
576 let result = self
577 .ffi_db
578 .get_proofs_by_ys(ffi_ys)
579 .await
580 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
581
582 let cdk_result: Result<Vec<cdk::types::ProofInfo>, cdk::cdk_database::Error> = result
584 .into_iter()
585 .map(|info| {
586 Ok(cdk::types::ProofInfo {
587 proof: info.proof.try_into().map_err(|e: FfiError| {
588 cdk::cdk_database::Error::Database(e.to_string().into())
589 })?,
590 y: info.y.try_into().map_err(|e: FfiError| {
591 cdk::cdk_database::Error::Database(e.to_string().into())
592 })?,
593 mint_url: info.mint_url.try_into().map_err(|e: FfiError| {
594 cdk::cdk_database::Error::Database(e.to_string().into())
595 })?,
596 state: info.state.into(),
597 spending_condition: info
598 .spending_condition
599 .map(|sc| sc.try_into())
600 .transpose()
601 .map_err(|e: FfiError| {
602 cdk::cdk_database::Error::Database(e.to_string().into())
603 })?,
604 unit: info.unit.into(),
605 used_by_operation: info
606 .used_by_operation
607 .map(|id| uuid::Uuid::parse_str(&id))
608 .transpose()
609 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?,
610 created_by_operation: info
611 .created_by_operation
612 .map(|id| uuid::Uuid::parse_str(&id))
613 .transpose()
614 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?,
615 })
616 })
617 .collect();
618
619 cdk_result
620 }
621
622 async fn get_balance(
623 &self,
624 mint_url: Option<cdk::mint_url::MintUrl>,
625 unit: Option<cdk::nuts::CurrencyUnit>,
626 state: Option<Vec<cdk::nuts::State>>,
627 ) -> Result<u64, cdk::cdk_database::Error> {
628 let ffi_mint_url = mint_url.map(Into::into);
629 let ffi_unit = unit.map(Into::into);
630 let ffi_state = state.map(|s| s.into_iter().map(Into::into).collect());
631
632 self.ffi_db
633 .get_balance(ffi_mint_url, ffi_unit, ffi_state)
634 .await
635 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
636 }
637
638 async fn get_transaction(
640 &self,
641 transaction_id: cdk::wallet::types::TransactionId,
642 ) -> Result<Option<cdk::wallet::types::Transaction>, cdk::cdk_database::Error> {
643 let ffi_id = transaction_id.into();
644 let result = self
645 .ffi_db
646 .get_transaction(ffi_id)
647 .await
648 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
649
650 result
651 .map(|tx| tx.try_into())
652 .transpose()
653 .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))
654 }
655
656 async fn list_transactions(
657 &self,
658 mint_url: Option<cdk::mint_url::MintUrl>,
659 direction: Option<cdk::wallet::types::TransactionDirection>,
660 unit: Option<cdk::nuts::CurrencyUnit>,
661 ) -> Result<Vec<cdk::wallet::types::Transaction>, cdk::cdk_database::Error> {
662 let ffi_mint_url = mint_url.map(Into::into);
663 let ffi_direction = direction.map(Into::into);
664 let ffi_unit = unit.map(Into::into);
665
666 let result = self
667 .ffi_db
668 .list_transactions(ffi_mint_url, ffi_direction, ffi_unit)
669 .await
670 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
671
672 result
673 .into_iter()
674 .map(|tx| tx.try_into())
675 .collect::<Result<Vec<_>, FfiError>>()
676 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
677 }
678
679 async fn add_p2pk_key(
682 &self,
683 pubkey: &cdk::nuts::PublicKey,
684 derivation_path: DerivationPath,
685 derivation_index: u32,
686 ) -> Result<(), cdk::cdk_database::Error> {
687 let ffi_pubkey: PublicKey = (*pubkey).into();
688 let ffi_derivation_path = derivation_path.to_string();
689 self.ffi_db
690 .add_p2pk_key(ffi_pubkey, ffi_derivation_path, derivation_index)
691 .await
692 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
693 }
694
695 async fn list_p2pk_keys(
696 &self,
697 ) -> Result<Vec<cdk_common::wallet::P2PKSigningKey>, cdk::cdk_database::Error> {
698 let result = self
699 .ffi_db
700 .list_p2pk_keys()
701 .await
702 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
703 Ok(result
704 .into_iter()
705 .map(|k| {
706 k.try_into().map_err(|e: crate::error::FfiError| {
707 cdk::cdk_database::Error::Database(e.to_string().into())
708 })
709 })
710 .collect::<Result<Vec<_>, _>>()?)
711 }
712
713 async fn latest_p2pk(
714 &self,
715 ) -> Result<Option<cdk_common::wallet::P2PKSigningKey>, cdk::cdk_database::Error> {
716 let result = self
717 .ffi_db
718 .latest_p2pk()
719 .await
720 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
721 Ok(result
722 .map(|k| {
723 k.try_into().map_err(|e: crate::error::FfiError| {
724 cdk::cdk_database::Error::Database(e.to_string().into())
725 })
726 })
727 .transpose()?)
728 }
729
730 async fn get_p2pk_key(
731 &self,
732 pubkey: &cdk::nuts::PublicKey,
733 ) -> Result<Option<cdk_common::wallet::P2PKSigningKey>, cdk::cdk_database::Error> {
734 let ffi_pubkey: PublicKey = (*pubkey).into();
735 let result = self
736 .ffi_db
737 .get_p2pk_key(ffi_pubkey)
738 .await
739 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
740 Ok(result
741 .map(|k| {
742 k.try_into().map_err(|e: crate::error::FfiError| {
743 cdk::cdk_database::Error::Database(e.to_string().into())
744 })
745 })
746 .transpose()?)
747 }
748
749 async fn update_proofs(
752 &self,
753 added: Vec<cdk::types::ProofInfo>,
754 removed_ys: Vec<cdk::nuts::PublicKey>,
755 ) -> Result<(), cdk::cdk_database::Error> {
756 let ffi_added: Vec<ProofInfo> = added.into_iter().map(Into::into).collect();
757 let ffi_removed_ys: Vec<PublicKey> = removed_ys.into_iter().map(Into::into).collect();
758 self.ffi_db
759 .update_proofs(ffi_added, ffi_removed_ys)
760 .await
761 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
762 }
763
764 async fn update_proofs_state(
765 &self,
766 ys: Vec<cdk::nuts::PublicKey>,
767 state: cdk::nuts::State,
768 ) -> Result<(), cdk::cdk_database::Error> {
769 let ffi_ys: Vec<PublicKey> = ys.into_iter().map(Into::into).collect();
770 let ffi_state = state.into();
771 self.ffi_db
772 .update_proofs_state(ffi_ys, ffi_state)
773 .await
774 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
775 }
776
777 async fn add_transaction(
778 &self,
779 transaction: cdk::wallet::types::Transaction,
780 ) -> Result<(), cdk::cdk_database::Error> {
781 let ffi_transaction = transaction.into();
782 self.ffi_db
783 .add_transaction(ffi_transaction)
784 .await
785 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
786 }
787
788 async fn update_mint_url(
789 &self,
790 old_mint_url: cdk::mint_url::MintUrl,
791 new_mint_url: cdk::mint_url::MintUrl,
792 ) -> Result<(), cdk::cdk_database::Error> {
793 let ffi_old = old_mint_url.into();
794 let ffi_new = new_mint_url.into();
795 self.ffi_db
796 .update_mint_url(ffi_old, ffi_new)
797 .await
798 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
799 }
800
801 async fn increment_keyset_counter(
802 &self,
803 keyset_id: &cdk::nuts::Id,
804 count: u32,
805 ) -> Result<u32, cdk::cdk_database::Error> {
806 let ffi_id = (*keyset_id).into();
807 self.ffi_db
808 .increment_keyset_counter(ffi_id, count)
809 .await
810 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
811 }
812
813 async fn add_mint(
814 &self,
815 mint_url: cdk::mint_url::MintUrl,
816 mint_info: Option<cdk::nuts::MintInfo>,
817 ) -> Result<(), cdk::cdk_database::Error> {
818 let ffi_mint_url = mint_url.into();
819 let ffi_mint_info = mint_info.map(Into::into);
820 self.ffi_db
821 .add_mint(ffi_mint_url, ffi_mint_info)
822 .await
823 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
824 }
825
826 async fn remove_mint(
827 &self,
828 mint_url: cdk::mint_url::MintUrl,
829 ) -> Result<(), cdk::cdk_database::Error> {
830 let ffi_mint_url = mint_url.into();
831 self.ffi_db
832 .remove_mint(ffi_mint_url)
833 .await
834 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
835 }
836
837 async fn add_mint_keysets(
838 &self,
839 mint_url: cdk::mint_url::MintUrl,
840 keysets: Vec<cdk::nuts::KeySetInfo>,
841 ) -> Result<(), cdk::cdk_database::Error> {
842 let ffi_mint_url = mint_url.into();
843 let ffi_keysets: Vec<KeySetInfo> = keysets.into_iter().map(Into::into).collect();
844 self.ffi_db
845 .add_mint_keysets(ffi_mint_url, ffi_keysets)
846 .await
847 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
848 }
849
850 async fn add_mint_quote(
851 &self,
852 quote: cdk::wallet::MintQuote,
853 ) -> Result<(), cdk::cdk_database::Error> {
854 let ffi_quote = quote.into();
855 self.ffi_db
856 .add_mint_quote(ffi_quote)
857 .await
858 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
859 }
860
861 async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), cdk::cdk_database::Error> {
862 self.ffi_db
863 .remove_mint_quote(quote_id.to_string())
864 .await
865 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
866 }
867
868 async fn add_melt_quote(
869 &self,
870 quote: cdk::wallet::MeltQuote,
871 ) -> Result<(), cdk::cdk_database::Error> {
872 let ffi_quote = quote.into();
873 self.ffi_db
874 .add_melt_quote(ffi_quote)
875 .await
876 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
877 }
878
879 async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), cdk::cdk_database::Error> {
880 self.ffi_db
881 .remove_melt_quote(quote_id.to_string())
882 .await
883 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
884 }
885
886 async fn add_keys(&self, keyset: cdk::nuts::KeySet) -> Result<(), cdk::cdk_database::Error> {
887 let ffi_keyset: KeySet = keyset.into();
888 self.ffi_db
889 .add_keys(ffi_keyset)
890 .await
891 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
892 }
893
894 async fn remove_keys(&self, id: &cdk::nuts::Id) -> Result<(), cdk::cdk_database::Error> {
895 let ffi_id = (*id).into();
896 self.ffi_db
897 .remove_keys(ffi_id)
898 .await
899 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
900 }
901
902 async fn remove_transaction(
903 &self,
904 transaction_id: cdk::wallet::types::TransactionId,
905 ) -> Result<(), cdk::cdk_database::Error> {
906 let ffi_id = transaction_id.into();
907 self.ffi_db
908 .remove_transaction(ffi_id)
909 .await
910 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
911 }
912
913 async fn add_saga(&self, saga: WalletSaga) -> Result<(), cdk::cdk_database::Error> {
914 let json = serde_json::to_string(&saga)
915 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
916 self.ffi_db
917 .add_saga(json)
918 .await
919 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
920 }
921
922 async fn get_saga(
923 &self,
924 id: &uuid::Uuid,
925 ) -> Result<Option<WalletSaga>, cdk::cdk_database::Error> {
926 let json_opt = self
927 .ffi_db
928 .get_saga(id.to_string())
929 .await
930 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
931
932 match json_opt {
933 Some(json) => {
934 let saga: WalletSaga = serde_json::from_str(&json)
935 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
936 Ok(Some(saga))
937 }
938 None => Ok(None),
939 }
940 }
941
942 async fn update_saga(&self, saga: WalletSaga) -> Result<bool, cdk::cdk_database::Error> {
943 let json = serde_json::to_string(&saga)
944 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
945 self.ffi_db
946 .update_saga(json)
947 .await
948 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
949 }
950
951 async fn delete_saga(&self, id: &uuid::Uuid) -> Result<(), cdk::cdk_database::Error> {
952 self.ffi_db
953 .delete_saga(id.to_string())
954 .await
955 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
956 }
957
958 async fn get_incomplete_sagas(&self) -> Result<Vec<WalletSaga>, cdk::cdk_database::Error> {
959 let json_vec = self
960 .ffi_db
961 .get_incomplete_sagas()
962 .await
963 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
964
965 json_vec
966 .into_iter()
967 .map(|json| {
968 serde_json::from_str(&json)
969 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
970 })
971 .collect()
972 }
973
974 async fn reserve_proofs(
975 &self,
976 ys: Vec<cdk::nuts::PublicKey>,
977 operation_id: &uuid::Uuid,
978 ) -> Result<(), cdk::cdk_database::Error> {
979 let ffi_ys: Vec<PublicKey> = ys.into_iter().map(Into::into).collect();
980 self.ffi_db
981 .reserve_proofs(ffi_ys, operation_id.to_string())
982 .await
983 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
984 }
985
986 async fn release_proofs(
987 &self,
988 operation_id: &uuid::Uuid,
989 ) -> Result<(), cdk::cdk_database::Error> {
990 self.ffi_db
991 .release_proofs(operation_id.to_string())
992 .await
993 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
994 }
995
996 async fn get_reserved_proofs(
997 &self,
998 operation_id: &uuid::Uuid,
999 ) -> Result<Vec<cdk::types::ProofInfo>, cdk::cdk_database::Error> {
1000 let result = self
1001 .ffi_db
1002 .get_reserved_proofs(operation_id.to_string())
1003 .await
1004 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
1005
1006 result
1007 .into_iter()
1008 .map(|info| {
1009 Ok(cdk::types::ProofInfo {
1010 proof: info.proof.try_into().map_err(|e: FfiError| {
1011 cdk::cdk_database::Error::Database(e.to_string().into())
1012 })?,
1013 y: info.y.try_into().map_err(|e: FfiError| {
1014 cdk::cdk_database::Error::Database(e.to_string().into())
1015 })?,
1016 mint_url: info.mint_url.try_into().map_err(|e: FfiError| {
1017 cdk::cdk_database::Error::Database(e.to_string().into())
1018 })?,
1019 state: info.state.into(),
1020 spending_condition: info
1021 .spending_condition
1022 .map(|sc| sc.try_into())
1023 .transpose()
1024 .map_err(|e: FfiError| {
1025 cdk::cdk_database::Error::Database(e.to_string().into())
1026 })?,
1027 unit: info.unit.into(),
1028 used_by_operation: info
1029 .used_by_operation
1030 .map(|id| uuid::Uuid::parse_str(&id))
1031 .transpose()
1032 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?,
1033 created_by_operation: info
1034 .created_by_operation
1035 .map(|id| uuid::Uuid::parse_str(&id))
1036 .transpose()
1037 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?,
1038 })
1039 })
1040 .collect()
1041 }
1042
1043 async fn reserve_melt_quote(
1044 &self,
1045 quote_id: &str,
1046 operation_id: &uuid::Uuid,
1047 ) -> Result<(), cdk::cdk_database::Error> {
1048 self.ffi_db
1049 .reserve_melt_quote(quote_id.to_string(), operation_id.to_string())
1050 .await
1051 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
1052 }
1053
1054 async fn release_melt_quote(
1055 &self,
1056 operation_id: &uuid::Uuid,
1057 ) -> Result<(), cdk::cdk_database::Error> {
1058 self.ffi_db
1059 .release_melt_quote(operation_id.to_string())
1060 .await
1061 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
1062 }
1063
1064 async fn reserve_mint_quote(
1065 &self,
1066 quote_id: &str,
1067 operation_id: &uuid::Uuid,
1068 ) -> Result<(), cdk::cdk_database::Error> {
1069 self.ffi_db
1070 .reserve_mint_quote(quote_id.to_string(), operation_id.to_string())
1071 .await
1072 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
1073 }
1074
1075 async fn release_mint_quote(
1076 &self,
1077 operation_id: &uuid::Uuid,
1078 ) -> Result<(), cdk::cdk_database::Error> {
1079 self.ffi_db
1080 .release_mint_quote(operation_id.to_string())
1081 .await
1082 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
1083 }
1084
1085 async fn kv_write(
1086 &self,
1087 primary_namespace: &str,
1088 secondary_namespace: &str,
1089 key: &str,
1090 value: &[u8],
1091 ) -> Result<(), cdk::cdk_database::Error> {
1092 self.ffi_db
1093 .kv_write(
1094 primary_namespace.to_string(),
1095 secondary_namespace.to_string(),
1096 key.to_string(),
1097 value.to_vec(),
1098 )
1099 .await
1100 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
1101 }
1102
1103 async fn kv_remove(
1104 &self,
1105 primary_namespace: &str,
1106 secondary_namespace: &str,
1107 key: &str,
1108 ) -> Result<(), cdk::cdk_database::Error> {
1109 self.ffi_db
1110 .kv_remove(
1111 primary_namespace.to_string(),
1112 secondary_namespace.to_string(),
1113 key.to_string(),
1114 )
1115 .await
1116 .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
1117 }
1118}
1119
1120pub(crate) struct FfiWalletDatabaseWrapper<T, E>
1125where
1126 T: CdkWalletDatabase<E> + Send + Sync + 'static,
1127 E: std::error::Error
1128 + Send
1129 + Sync
1130 + Into<cdk_common::database::Error>
1131 + From<cdk_common::database::Error>
1132 + 'static,
1133{
1134 inner: T,
1135 _phantom: std::marker::PhantomData<E>,
1136}
1137
1138impl<T, E> std::fmt::Debug for FfiWalletDatabaseWrapper<T, E>
1139where
1140 T: CdkWalletDatabase<E> + std::fmt::Debug + Send + Sync + 'static,
1141 E: std::error::Error
1142 + Send
1143 + Sync
1144 + Into<cdk_common::database::Error>
1145 + From<cdk_common::database::Error>
1146 + 'static,
1147{
1148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1149 f.debug_struct("FfiWalletDatabaseWrapper")
1150 .field("inner", &self.inner)
1151 .finish()
1152 }
1153}
1154
1155impl<T, E> FfiWalletDatabaseWrapper<T, E>
1156where
1157 T: CdkWalletDatabase<E> + Send + Sync + 'static,
1158 E: std::error::Error
1159 + Send
1160 + Sync
1161 + Into<cdk_common::database::Error>
1162 + From<cdk_common::database::Error>
1163 + 'static,
1164{
1165 pub fn new(inner: T) -> Arc<Self> {
1167 Arc::new(Self {
1168 inner,
1169 _phantom: std::marker::PhantomData,
1170 })
1171 }
1172
1173 #[cfg(feature = "supabase")]
1178 pub fn inner(&self) -> &T {
1179 &self.inner
1180 }
1181}
1182
1183#[async_trait::async_trait]
1185impl<T, E> WalletDatabase for FfiWalletDatabaseWrapper<T, E>
1186where
1187 T: CdkWalletDatabase<E> + Send + Sync + 'static,
1188 E: std::error::Error
1189 + Send
1190 + Sync
1191 + Into<cdk_common::database::Error>
1192 + From<cdk_common::database::Error>
1193 + 'static,
1194{
1195 async fn get_proofs_by_ys(&self, ys: Vec<PublicKey>) -> Result<Vec<ProofInfo>, FfiError> {
1198 let cdk_ys: Vec<cdk::nuts::PublicKey> = ys
1199 .into_iter()
1200 .map(|y| y.try_into())
1201 .collect::<Result<Vec<_>, FfiError>>()?;
1202
1203 let result = self
1204 .inner
1205 .get_proofs_by_ys(cdk_ys)
1206 .await
1207 .map_err(FfiError::internal)?;
1208
1209 Ok(result.into_iter().map(Into::into).collect())
1210 }
1211
1212 async fn get_mint(&self, mint_url: MintUrl) -> Result<Option<MintInfo>, FfiError> {
1213 let cdk_mint_url = mint_url.try_into()?;
1214 let result = self
1215 .inner
1216 .get_mint(cdk_mint_url)
1217 .await
1218 .map_err(FfiError::internal)?;
1219 Ok(result.map(Into::into))
1220 }
1221
1222 async fn get_mints(&self) -> Result<HashMap<MintUrl, Option<MintInfo>>, FfiError> {
1223 let result = self.inner.get_mints().await.map_err(FfiError::internal)?;
1224 Ok(result
1225 .into_iter()
1226 .map(|(k, v)| (k.into(), v.map(Into::into)))
1227 .collect())
1228 }
1229
1230 async fn get_mint_keysets(
1231 &self,
1232 mint_url: MintUrl,
1233 ) -> Result<Option<Vec<KeySetInfo>>, FfiError> {
1234 let cdk_mint_url = mint_url.try_into()?;
1235 let result = self
1236 .inner
1237 .get_mint_keysets(cdk_mint_url)
1238 .await
1239 .map_err(FfiError::internal)?;
1240 Ok(result.map(|keysets| keysets.into_iter().map(Into::into).collect()))
1241 }
1242
1243 async fn get_keyset_by_id(&self, keyset_id: Id) -> Result<Option<KeySetInfo>, FfiError> {
1244 let cdk_id = keyset_id.try_into()?;
1245 let result = self
1246 .inner
1247 .get_keyset_by_id(&cdk_id)
1248 .await
1249 .map_err(FfiError::internal)?;
1250 Ok(result.map(Into::into))
1251 }
1252
1253 async fn get_mint_quote(&self, quote_id: String) -> Result<Option<MintQuote>, FfiError> {
1254 let result = self
1255 .inner
1256 .get_mint_quote("e_id)
1257 .await
1258 .map_err(FfiError::internal)?;
1259 Ok(result.map(|q| q.into()))
1260 }
1261
1262 async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, FfiError> {
1263 let result = self
1264 .inner
1265 .get_mint_quotes()
1266 .await
1267 .map_err(FfiError::internal)?;
1268 Ok(result.into_iter().map(|q| q.into()).collect())
1269 }
1270
1271 async fn get_unissued_mint_quotes(&self) -> Result<Vec<MintQuote>, FfiError> {
1272 let result = self
1273 .inner
1274 .get_unissued_mint_quotes()
1275 .await
1276 .map_err(FfiError::internal)?;
1277 Ok(result.into_iter().map(|q| q.into()).collect())
1278 }
1279
1280 async fn get_melt_quote(&self, quote_id: String) -> Result<Option<MeltQuote>, FfiError> {
1281 let result = self
1282 .inner
1283 .get_melt_quote("e_id)
1284 .await
1285 .map_err(FfiError::internal)?;
1286 Ok(result.map(|q| q.into()))
1287 }
1288
1289 async fn get_melt_quotes(&self) -> Result<Vec<MeltQuote>, FfiError> {
1290 let result = self
1291 .inner
1292 .get_melt_quotes()
1293 .await
1294 .map_err(FfiError::internal)?;
1295 Ok(result.into_iter().map(|q| q.into()).collect())
1296 }
1297
1298 async fn get_keys(&self, id: Id) -> Result<Option<Keys>, FfiError> {
1299 let cdk_id = id.try_into()?;
1300 let result = self
1301 .inner
1302 .get_keys(&cdk_id)
1303 .await
1304 .map_err(FfiError::internal)?;
1305 Ok(result.map(Into::into))
1306 }
1307
1308 async fn get_proofs(
1309 &self,
1310 mint_url: Option<MintUrl>,
1311 unit: Option<CurrencyUnit>,
1312 state: Option<Vec<ProofState>>,
1313 spending_conditions: Option<Vec<SpendingConditions>>,
1314 ) -> Result<Vec<ProofInfo>, FfiError> {
1315 let cdk_mint_url = mint_url.map(|u| u.try_into()).transpose()?;
1316 let cdk_unit = unit.map(Into::into);
1317 let cdk_state = state.map(|s| s.into_iter().map(Into::into).collect());
1318 let cdk_spending_conditions: Option<Vec<cdk::nuts::SpendingConditions>> =
1319 spending_conditions
1320 .map(|sc| {
1321 sc.into_iter()
1322 .map(|c| c.try_into())
1323 .collect::<Result<Vec<_>, FfiError>>()
1324 })
1325 .transpose()?;
1326
1327 let result = self
1328 .inner
1329 .get_proofs(cdk_mint_url, cdk_unit, cdk_state, cdk_spending_conditions)
1330 .await
1331 .map_err(FfiError::internal)?;
1332
1333 Ok(result.into_iter().map(Into::into).collect())
1334 }
1335
1336 async fn get_balance(
1337 &self,
1338 mint_url: Option<MintUrl>,
1339 unit: Option<CurrencyUnit>,
1340 state: Option<Vec<ProofState>>,
1341 ) -> Result<u64, FfiError> {
1342 let cdk_mint_url = mint_url.map(|u| u.try_into()).transpose()?;
1343 let cdk_unit = unit.map(Into::into);
1344 let cdk_state = state.map(|s| s.into_iter().map(Into::into).collect());
1345
1346 self.inner
1347 .get_balance(cdk_mint_url, cdk_unit, cdk_state)
1348 .await
1349 .map_err(FfiError::internal)
1350 }
1351
1352 async fn get_transaction(
1353 &self,
1354 transaction_id: TransactionId,
1355 ) -> Result<Option<Transaction>, FfiError> {
1356 let cdk_id = transaction_id.try_into()?;
1357 let result = self
1358 .inner
1359 .get_transaction(cdk_id)
1360 .await
1361 .map_err(FfiError::internal)?;
1362 Ok(result.map(Into::into))
1363 }
1364
1365 async fn list_transactions(
1366 &self,
1367 mint_url: Option<MintUrl>,
1368 direction: Option<TransactionDirection>,
1369 unit: Option<CurrencyUnit>,
1370 ) -> Result<Vec<Transaction>, FfiError> {
1371 let cdk_mint_url = mint_url.map(|u| u.try_into()).transpose()?;
1372 let cdk_direction = direction.map(Into::into);
1373 let cdk_unit = unit.map(Into::into);
1374
1375 let result = self
1376 .inner
1377 .list_transactions(cdk_mint_url, cdk_direction, cdk_unit)
1378 .await
1379 .map_err(FfiError::internal)?;
1380
1381 Ok(result.into_iter().map(Into::into).collect())
1382 }
1383
1384 async fn kv_read(
1385 &self,
1386 primary_namespace: String,
1387 secondary_namespace: String,
1388 key: String,
1389 ) -> Result<Option<Vec<u8>>, FfiError> {
1390 self.inner
1391 .kv_read(&primary_namespace, &secondary_namespace, &key)
1392 .await
1393 .map_err(FfiError::internal)
1394 }
1395
1396 async fn kv_list(
1397 &self,
1398 primary_namespace: String,
1399 secondary_namespace: String,
1400 ) -> Result<Vec<String>, FfiError> {
1401 self.inner
1402 .kv_list(&primary_namespace, &secondary_namespace)
1403 .await
1404 .map_err(FfiError::internal)
1405 }
1406
1407 async fn add_p2pk_key(
1408 &self,
1409 pubkey: PublicKey,
1410 derivation_path: String,
1411 derivation_index: u32,
1412 ) -> Result<(), FfiError> {
1413 use std::str::FromStr;
1414
1415 use cdk_common::bitcoin::bip32::DerivationPath;
1416
1417 let cdk_pubkey: cdk::nuts::PublicKey = pubkey.try_into()?;
1418 let cdk_derivation_path =
1419 DerivationPath::from_str(&derivation_path).map_err(FfiError::internal)?;
1420
1421 self.inner
1422 .add_p2pk_key(&cdk_pubkey, cdk_derivation_path, derivation_index)
1423 .await
1424 .map_err(FfiError::database)
1425 }
1426
1427 async fn get_p2pk_key(&self, pubkey: PublicKey) -> Result<Option<P2PKSigningKey>, FfiError> {
1428 let cdk_pubkey: cdk::nuts::PublicKey = pubkey.try_into()?;
1429 let result = self
1430 .inner
1431 .get_p2pk_key(&cdk_pubkey)
1432 .await
1433 .map_err(FfiError::database)?;
1434 Ok(result.map(Into::into))
1435 }
1436
1437 async fn list_p2pk_keys(&self) -> Result<Vec<P2PKSigningKey>, FfiError> {
1438 let result = self
1439 .inner
1440 .list_p2pk_keys()
1441 .await
1442 .map_err(FfiError::database)?;
1443 Ok(result.into_iter().map(Into::into).collect())
1444 }
1445
1446 async fn latest_p2pk(&self) -> Result<Option<P2PKSigningKey>, FfiError> {
1447 let result = self.inner.latest_p2pk().await.map_err(FfiError::database)?;
1448 Ok(result.map(Into::into))
1449 }
1450
1451 async fn kv_write(
1452 &self,
1453 primary_namespace: String,
1454 secondary_namespace: String,
1455 key: String,
1456 value: Vec<u8>,
1457 ) -> Result<(), FfiError> {
1458 self.inner
1459 .kv_write(&primary_namespace, &secondary_namespace, &key, &value)
1460 .await
1461 .map_err(FfiError::internal)
1462 }
1463
1464 async fn kv_remove(
1465 &self,
1466 primary_namespace: String,
1467 secondary_namespace: String,
1468 key: String,
1469 ) -> Result<(), FfiError> {
1470 self.inner
1471 .kv_remove(&primary_namespace, &secondary_namespace, &key)
1472 .await
1473 .map_err(FfiError::internal)
1474 }
1475
1476 async fn update_proofs(
1479 &self,
1480 added: Vec<ProofInfo>,
1481 removed_ys: Vec<PublicKey>,
1482 ) -> Result<(), FfiError> {
1483 let cdk_added: Result<Vec<cdk::types::ProofInfo>, FfiError> = added
1484 .into_iter()
1485 .map(|info| {
1486 Ok::<cdk::types::ProofInfo, FfiError>(cdk::types::ProofInfo {
1487 proof: info.proof.try_into()?,
1488 y: info.y.try_into()?,
1489 mint_url: info.mint_url.try_into()?,
1490 state: info.state.into(),
1491 spending_condition: info
1492 .spending_condition
1493 .map(|sc| sc.try_into())
1494 .transpose()?,
1495 unit: info.unit.into(),
1496 used_by_operation: info
1497 .used_by_operation
1498 .map(|id| uuid::Uuid::parse_str(&id))
1499 .transpose()
1500 .map_err(|e| FfiError::internal(e.to_string()))?,
1501 created_by_operation: info
1502 .created_by_operation
1503 .map(|id| uuid::Uuid::parse_str(&id))
1504 .transpose()
1505 .map_err(|e| FfiError::internal(e.to_string()))?,
1506 })
1507 })
1508 .collect();
1509 let cdk_added = cdk_added?;
1510
1511 let cdk_removed_ys: Result<Vec<cdk::nuts::PublicKey>, FfiError> =
1512 removed_ys.into_iter().map(|pk| pk.try_into()).collect();
1513 let cdk_removed_ys = cdk_removed_ys?;
1514
1515 self.inner
1516 .update_proofs(cdk_added, cdk_removed_ys)
1517 .await
1518 .map_err(FfiError::internal)
1519 }
1520
1521 async fn update_proofs_state(
1522 &self,
1523 ys: Vec<PublicKey>,
1524 state: ProofState,
1525 ) -> Result<(), FfiError> {
1526 let cdk_ys: Result<Vec<cdk::nuts::PublicKey>, FfiError> =
1527 ys.into_iter().map(|pk| pk.try_into()).collect();
1528 let cdk_ys = cdk_ys?;
1529 let cdk_state = state.into();
1530
1531 self.inner
1532 .update_proofs_state(cdk_ys, cdk_state)
1533 .await
1534 .map_err(FfiError::internal)
1535 }
1536
1537 async fn add_transaction(&self, transaction: Transaction) -> Result<(), FfiError> {
1538 let cdk_transaction: cdk::wallet::types::Transaction = transaction.try_into()?;
1539 self.inner
1540 .add_transaction(cdk_transaction)
1541 .await
1542 .map_err(FfiError::internal)
1543 }
1544
1545 async fn remove_transaction(&self, transaction_id: TransactionId) -> Result<(), FfiError> {
1546 let cdk_id = transaction_id.try_into()?;
1547 self.inner
1548 .remove_transaction(cdk_id)
1549 .await
1550 .map_err(FfiError::internal)
1551 }
1552
1553 async fn update_mint_url(
1554 &self,
1555 old_mint_url: MintUrl,
1556 new_mint_url: MintUrl,
1557 ) -> Result<(), FfiError> {
1558 let cdk_old = old_mint_url.try_into()?;
1559 let cdk_new = new_mint_url.try_into()?;
1560 self.inner
1561 .update_mint_url(cdk_old, cdk_new)
1562 .await
1563 .map_err(FfiError::internal)
1564 }
1565
1566 async fn increment_keyset_counter(&self, keyset_id: Id, count: u32) -> Result<u32, FfiError> {
1567 let cdk_id = keyset_id.try_into()?;
1568 self.inner
1569 .increment_keyset_counter(&cdk_id, count)
1570 .await
1571 .map_err(FfiError::internal)
1572 }
1573
1574 async fn add_mint(
1575 &self,
1576 mint_url: MintUrl,
1577 mint_info: Option<MintInfo>,
1578 ) -> Result<(), FfiError> {
1579 let cdk_mint_url = mint_url.try_into()?;
1580 let cdk_mint_info = mint_info.map(TryInto::try_into).transpose()?;
1581 self.inner
1582 .add_mint(cdk_mint_url, cdk_mint_info)
1583 .await
1584 .map_err(FfiError::internal)
1585 }
1586
1587 async fn remove_mint(&self, mint_url: MintUrl) -> Result<(), FfiError> {
1588 let cdk_mint_url = mint_url.try_into()?;
1589 self.inner
1590 .remove_mint(cdk_mint_url)
1591 .await
1592 .map_err(FfiError::internal)
1593 }
1594
1595 async fn add_mint_keysets(
1596 &self,
1597 mint_url: MintUrl,
1598 keysets: Vec<KeySetInfo>,
1599 ) -> Result<(), FfiError> {
1600 let cdk_mint_url = mint_url.try_into()?;
1601 let cdk_keysets: Vec<cdk::nuts::KeySetInfo> = keysets
1602 .into_iter()
1603 .map(TryInto::try_into)
1604 .collect::<Result<_, _>>()?;
1605 self.inner
1606 .add_mint_keysets(cdk_mint_url, cdk_keysets)
1607 .await
1608 .map_err(FfiError::internal)
1609 }
1610
1611 async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), FfiError> {
1612 let cdk_quote = quote.try_into()?;
1613 self.inner
1614 .add_mint_quote(cdk_quote)
1615 .await
1616 .map_err(FfiError::internal)
1617 }
1618
1619 async fn remove_mint_quote(&self, quote_id: String) -> Result<(), FfiError> {
1620 self.inner
1621 .remove_mint_quote("e_id)
1622 .await
1623 .map_err(FfiError::internal)
1624 }
1625
1626 async fn add_melt_quote(&self, quote: MeltQuote) -> Result<(), FfiError> {
1627 let cdk_quote = quote.try_into()?;
1628 self.inner
1629 .add_melt_quote(cdk_quote)
1630 .await
1631 .map_err(FfiError::internal)
1632 }
1633
1634 async fn remove_melt_quote(&self, quote_id: String) -> Result<(), FfiError> {
1635 self.inner
1636 .remove_melt_quote("e_id)
1637 .await
1638 .map_err(FfiError::internal)
1639 }
1640
1641 async fn add_keys(&self, keyset: KeySet) -> Result<(), FfiError> {
1642 let cdk_keyset: cdk::nuts::KeySet = keyset.try_into()?;
1643 self.inner
1644 .add_keys(cdk_keyset)
1645 .await
1646 .map_err(FfiError::internal)
1647 }
1648
1649 async fn remove_keys(&self, id: Id) -> Result<(), FfiError> {
1650 let cdk_id = id.try_into()?;
1651 self.inner
1652 .remove_keys(&cdk_id)
1653 .await
1654 .map_err(FfiError::internal)
1655 }
1656
1657 async fn add_saga(&self, saga_json: String) -> Result<(), FfiError> {
1660 let saga: WalletSaga = serde_json::from_str(&saga_json).map_err(FfiError::internal)?;
1661 self.inner.add_saga(saga).await.map_err(FfiError::internal)
1662 }
1663
1664 async fn get_saga(&self, id: String) -> Result<Option<String>, FfiError> {
1665 let id = uuid::Uuid::parse_str(&id).map_err(FfiError::internal)?;
1666 let result = self.inner.get_saga(&id).await.map_err(FfiError::internal)?;
1667
1668 match result {
1669 Some(saga) => {
1670 let json = serde_json::to_string(&saga).map_err(FfiError::internal)?;
1671 Ok(Some(json))
1672 }
1673 None => Ok(None),
1674 }
1675 }
1676
1677 async fn update_saga(&self, saga_json: String) -> Result<bool, FfiError> {
1678 let saga: WalletSaga = serde_json::from_str(&saga_json).map_err(FfiError::internal)?;
1679 self.inner
1680 .update_saga(saga)
1681 .await
1682 .map_err(FfiError::internal)
1683 }
1684
1685 async fn delete_saga(&self, id: String) -> Result<(), FfiError> {
1686 let id = uuid::Uuid::parse_str(&id).map_err(FfiError::internal)?;
1687 self.inner
1688 .delete_saga(&id)
1689 .await
1690 .map_err(FfiError::internal)
1691 }
1692
1693 async fn get_incomplete_sagas(&self) -> Result<Vec<String>, FfiError> {
1694 let result = self
1695 .inner
1696 .get_incomplete_sagas()
1697 .await
1698 .map_err(FfiError::internal)?;
1699
1700 result
1701 .into_iter()
1702 .map(|saga| serde_json::to_string(&saga).map_err(FfiError::internal))
1703 .collect()
1704 }
1705
1706 async fn reserve_proofs(
1709 &self,
1710 ys: Vec<PublicKey>,
1711 operation_id: String,
1712 ) -> Result<(), FfiError> {
1713 let operation_id = uuid::Uuid::parse_str(&operation_id).map_err(FfiError::internal)?;
1714 let cdk_ys: Result<Vec<cdk::nuts::PublicKey>, FfiError> =
1715 ys.into_iter().map(|pk| pk.try_into()).collect();
1716 let cdk_ys = cdk_ys?;
1717 self.inner
1718 .reserve_proofs(cdk_ys, &operation_id)
1719 .await
1720 .map_err(FfiError::internal)
1721 }
1722
1723 async fn release_proofs(&self, operation_id: String) -> Result<(), FfiError> {
1724 let operation_id = uuid::Uuid::parse_str(&operation_id).map_err(FfiError::internal)?;
1725 self.inner
1726 .release_proofs(&operation_id)
1727 .await
1728 .map_err(FfiError::internal)
1729 }
1730
1731 async fn get_reserved_proofs(&self, operation_id: String) -> Result<Vec<ProofInfo>, FfiError> {
1732 let operation_id = uuid::Uuid::parse_str(&operation_id).map_err(FfiError::internal)?;
1733 let result = self
1734 .inner
1735 .get_reserved_proofs(&operation_id)
1736 .await
1737 .map_err(FfiError::internal)?;
1738
1739 Ok(result.into_iter().map(Into::into).collect())
1740 }
1741
1742 async fn reserve_melt_quote(
1745 &self,
1746 quote_id: String,
1747 operation_id: String,
1748 ) -> Result<(), FfiError> {
1749 let operation_id = uuid::Uuid::parse_str(&operation_id).map_err(FfiError::internal)?;
1750 self.inner
1751 .reserve_melt_quote("e_id, &operation_id)
1752 .await
1753 .map_err(FfiError::internal)
1754 }
1755
1756 async fn release_melt_quote(&self, operation_id: String) -> Result<(), FfiError> {
1757 let operation_id = uuid::Uuid::parse_str(&operation_id).map_err(FfiError::internal)?;
1758 self.inner
1759 .release_melt_quote(&operation_id)
1760 .await
1761 .map_err(FfiError::internal)
1762 }
1763
1764 async fn reserve_mint_quote(
1765 &self,
1766 quote_id: String,
1767 operation_id: String,
1768 ) -> Result<(), FfiError> {
1769 let operation_id = uuid::Uuid::parse_str(&operation_id).map_err(FfiError::internal)?;
1770 self.inner
1771 .reserve_mint_quote("e_id, &operation_id)
1772 .await
1773 .map_err(FfiError::internal)
1774 }
1775
1776 async fn release_mint_quote(&self, operation_id: String) -> Result<(), FfiError> {
1777 let operation_id = uuid::Uuid::parse_str(&operation_id).map_err(FfiError::internal)?;
1778 self.inner
1779 .release_mint_quote(&operation_id)
1780 .await
1781 .map_err(FfiError::internal)
1782 }
1783}
1784
1785#[macro_export]
1794macro_rules! impl_ffi_wallet_database {
1795 ($wrapper_type:ty) => {
1796 #[uniffi::export(async_runtime = "tokio")]
1797 #[async_trait::async_trait]
1798 impl WalletDatabase for $wrapper_type {
1799 async fn get_proofs_by_ys(
1802 &self,
1803 ys: Vec<PublicKey>,
1804 ) -> Result<Vec<ProofInfo>, FfiError> {
1805 self.inner.get_proofs_by_ys(ys).await
1806 }
1807
1808 async fn get_mint(&self, mint_url: MintUrl) -> Result<Option<MintInfo>, FfiError> {
1809 self.inner.get_mint(mint_url).await
1810 }
1811
1812 async fn get_mints(
1813 &self,
1814 ) -> Result<std::collections::HashMap<MintUrl, Option<MintInfo>>, FfiError> {
1815 self.inner.get_mints().await
1816 }
1817
1818 async fn get_mint_keysets(
1819 &self,
1820 mint_url: MintUrl,
1821 ) -> Result<Option<Vec<KeySetInfo>>, FfiError> {
1822 self.inner.get_mint_keysets(mint_url).await
1823 }
1824
1825 async fn get_keyset_by_id(
1826 &self,
1827 keyset_id: Id,
1828 ) -> Result<Option<KeySetInfo>, FfiError> {
1829 self.inner.get_keyset_by_id(keyset_id).await
1830 }
1831
1832 async fn get_mint_quote(
1833 &self,
1834 quote_id: String,
1835 ) -> Result<Option<MintQuote>, FfiError> {
1836 self.inner.get_mint_quote(quote_id).await
1837 }
1838
1839 async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, FfiError> {
1840 self.inner.get_mint_quotes().await
1841 }
1842
1843 async fn get_unissued_mint_quotes(&self) -> Result<Vec<MintQuote>, FfiError> {
1844 self.inner.get_unissued_mint_quotes().await
1845 }
1846
1847 async fn get_melt_quote(
1848 &self,
1849 quote_id: String,
1850 ) -> Result<Option<MeltQuote>, FfiError> {
1851 self.inner.get_melt_quote(quote_id).await
1852 }
1853
1854 async fn get_melt_quotes(&self) -> Result<Vec<MeltQuote>, FfiError> {
1855 self.inner.get_melt_quotes().await
1856 }
1857
1858 async fn get_keys(&self, id: Id) -> Result<Option<Keys>, FfiError> {
1859 self.inner.get_keys(id).await
1860 }
1861
1862 async fn get_proofs(
1863 &self,
1864 mint_url: Option<MintUrl>,
1865 unit: Option<CurrencyUnit>,
1866 state: Option<Vec<ProofState>>,
1867 spending_conditions: Option<Vec<SpendingConditions>>,
1868 ) -> Result<Vec<ProofInfo>, FfiError> {
1869 self.inner
1870 .get_proofs(mint_url, unit, state, spending_conditions)
1871 .await
1872 }
1873
1874 async fn get_balance(
1875 &self,
1876 mint_url: Option<MintUrl>,
1877 unit: Option<CurrencyUnit>,
1878 state: Option<Vec<ProofState>>,
1879 ) -> Result<u64, FfiError> {
1880 self.inner.get_balance(mint_url, unit, state).await
1881 }
1882
1883 async fn get_transaction(
1884 &self,
1885 transaction_id: TransactionId,
1886 ) -> Result<Option<Transaction>, FfiError> {
1887 self.inner.get_transaction(transaction_id).await
1888 }
1889
1890 async fn list_transactions(
1891 &self,
1892 mint_url: Option<MintUrl>,
1893 direction: Option<TransactionDirection>,
1894 unit: Option<CurrencyUnit>,
1895 ) -> Result<Vec<Transaction>, FfiError> {
1896 self.inner
1897 .list_transactions(mint_url, direction, unit)
1898 .await
1899 }
1900
1901 async fn kv_read(
1902 &self,
1903 primary_namespace: String,
1904 secondary_namespace: String,
1905 key: String,
1906 ) -> Result<Option<Vec<u8>>, FfiError> {
1907 self.inner
1908 .kv_read(primary_namespace, secondary_namespace, key)
1909 .await
1910 }
1911
1912 async fn kv_list(
1913 &self,
1914 primary_namespace: String,
1915 secondary_namespace: String,
1916 ) -> Result<Vec<String>, FfiError> {
1917 self.inner
1918 .kv_list(primary_namespace, secondary_namespace)
1919 .await
1920 }
1921
1922 async fn kv_write(
1923 &self,
1924 primary_namespace: String,
1925 secondary_namespace: String,
1926 key: String,
1927 value: Vec<u8>,
1928 ) -> Result<(), FfiError> {
1929 self.inner
1930 .kv_write(primary_namespace, secondary_namespace, key, value)
1931 .await
1932 }
1933
1934 async fn kv_remove(
1935 &self,
1936 primary_namespace: String,
1937 secondary_namespace: String,
1938 key: String,
1939 ) -> Result<(), FfiError> {
1940 self.inner
1941 .kv_remove(primary_namespace, secondary_namespace, key)
1942 .await
1943 }
1944
1945 async fn update_proofs(
1948 &self,
1949 added: Vec<ProofInfo>,
1950 removed_ys: Vec<PublicKey>,
1951 ) -> Result<(), FfiError> {
1952 self.inner.update_proofs(added, removed_ys).await
1953 }
1954
1955 async fn update_proofs_state(
1956 &self,
1957 ys: Vec<PublicKey>,
1958 state: ProofState,
1959 ) -> Result<(), FfiError> {
1960 self.inner.update_proofs_state(ys, state).await
1961 }
1962
1963 async fn add_transaction(&self, transaction: Transaction) -> Result<(), FfiError> {
1964 self.inner.add_transaction(transaction).await
1965 }
1966
1967 async fn remove_transaction(
1968 &self,
1969 transaction_id: TransactionId,
1970 ) -> Result<(), FfiError> {
1971 self.inner.remove_transaction(transaction_id).await
1972 }
1973
1974 async fn update_mint_url(
1975 &self,
1976 old_mint_url: MintUrl,
1977 new_mint_url: MintUrl,
1978 ) -> Result<(), FfiError> {
1979 self.inner.update_mint_url(old_mint_url, new_mint_url).await
1980 }
1981
1982 async fn increment_keyset_counter(
1983 &self,
1984 keyset_id: Id,
1985 count: u32,
1986 ) -> Result<u32, FfiError> {
1987 self.inner.increment_keyset_counter(keyset_id, count).await
1988 }
1989
1990 async fn add_mint(
1991 &self,
1992 mint_url: MintUrl,
1993 mint_info: Option<MintInfo>,
1994 ) -> Result<(), FfiError> {
1995 self.inner.add_mint(mint_url, mint_info).await
1996 }
1997
1998 async fn remove_mint(&self, mint_url: MintUrl) -> Result<(), FfiError> {
1999 self.inner.remove_mint(mint_url).await
2000 }
2001
2002 async fn add_mint_keysets(
2003 &self,
2004 mint_url: MintUrl,
2005 keysets: Vec<KeySetInfo>,
2006 ) -> Result<(), FfiError> {
2007 self.inner.add_mint_keysets(mint_url, keysets).await
2008 }
2009
2010 async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), FfiError> {
2011 self.inner.add_mint_quote(quote).await
2012 }
2013
2014 async fn remove_mint_quote(&self, quote_id: String) -> Result<(), FfiError> {
2015 self.inner.remove_mint_quote(quote_id).await
2016 }
2017
2018 async fn add_melt_quote(&self, quote: MeltQuote) -> Result<(), FfiError> {
2019 self.inner.add_melt_quote(quote).await
2020 }
2021
2022 async fn remove_melt_quote(&self, quote_id: String) -> Result<(), FfiError> {
2023 self.inner.remove_melt_quote(quote_id).await
2024 }
2025
2026 async fn add_keys(&self, keyset: KeySet) -> Result<(), FfiError> {
2027 self.inner.add_keys(keyset).await
2028 }
2029
2030 async fn remove_keys(&self, id: Id) -> Result<(), FfiError> {
2031 self.inner.remove_keys(id).await
2032 }
2033
2034 async fn add_p2pk_key(
2037 &self,
2038 pubkey: PublicKey,
2039 derivation_path: String,
2040 derivation_index: u32,
2041 ) -> Result<(), FfiError> {
2042 self.inner
2043 .add_p2pk_key(pubkey, derivation_path, derivation_index)
2044 .await
2045 }
2046
2047 async fn get_p2pk_key(
2048 &self,
2049 pubkey: PublicKey,
2050 ) -> Result<Option<P2PKSigningKey>, FfiError> {
2051 self.inner.get_p2pk_key(pubkey).await
2052 }
2053
2054 async fn list_p2pk_keys(&self) -> Result<Vec<P2PKSigningKey>, FfiError> {
2055 self.inner.list_p2pk_keys().await
2056 }
2057
2058 async fn latest_p2pk(&self) -> Result<Option<P2PKSigningKey>, FfiError> {
2059 self.inner.latest_p2pk().await
2060 }
2061
2062 async fn add_saga(&self, saga_json: String) -> Result<(), FfiError> {
2065 self.inner.add_saga(saga_json).await
2066 }
2067
2068 async fn get_saga(&self, id: String) -> Result<Option<String>, FfiError> {
2069 self.inner.get_saga(id).await
2070 }
2071
2072 async fn update_saga(&self, saga_json: String) -> Result<bool, FfiError> {
2073 self.inner.update_saga(saga_json).await
2074 }
2075
2076 async fn delete_saga(&self, id: String) -> Result<(), FfiError> {
2077 self.inner.delete_saga(id).await
2078 }
2079
2080 async fn get_incomplete_sagas(&self) -> Result<Vec<String>, FfiError> {
2081 self.inner.get_incomplete_sagas().await
2082 }
2083
2084 async fn reserve_proofs(
2087 &self,
2088 ys: Vec<PublicKey>,
2089 operation_id: String,
2090 ) -> Result<(), FfiError> {
2091 self.inner.reserve_proofs(ys, operation_id).await
2092 }
2093
2094 async fn release_proofs(&self, operation_id: String) -> Result<(), FfiError> {
2095 self.inner.release_proofs(operation_id).await
2096 }
2097
2098 async fn get_reserved_proofs(
2099 &self,
2100 operation_id: String,
2101 ) -> Result<Vec<ProofInfo>, FfiError> {
2102 self.inner.get_reserved_proofs(operation_id).await
2103 }
2104
2105 async fn reserve_melt_quote(
2108 &self,
2109 quote_id: String,
2110 operation_id: String,
2111 ) -> Result<(), FfiError> {
2112 self.inner.reserve_melt_quote(quote_id, operation_id).await
2113 }
2114
2115 async fn release_melt_quote(&self, operation_id: String) -> Result<(), FfiError> {
2116 self.inner.release_melt_quote(operation_id).await
2117 }
2118
2119 async fn reserve_mint_quote(
2120 &self,
2121 quote_id: String,
2122 operation_id: String,
2123 ) -> Result<(), FfiError> {
2124 self.inner.reserve_mint_quote(quote_id, operation_id).await
2125 }
2126
2127 async fn release_mint_quote(&self, operation_id: String) -> Result<(), FfiError> {
2128 self.inner.release_mint_quote(operation_id).await
2129 }
2130 }
2131 };
2132}
2133
2134#[derive(uniffi::Enum, Clone)]
2136pub enum WalletDbBackend {
2137 Sqlite {
2138 path: String,
2139 },
2140 #[cfg(feature = "postgres")]
2141 Postgres {
2142 url: String,
2143 },
2144}
2145
2146#[derive(uniffi::Enum)]
2153pub enum WalletStore {
2154 Sqlite {
2155 path: String,
2156 },
2157 #[cfg(feature = "postgres")]
2158 Postgres {
2159 url: String,
2160 },
2161 Custom {
2162 db: Arc<dyn WalletDatabase>,
2163 },
2164}
2165
2166#[uniffi::export]
2168pub fn sqlite_wallet_store(path: String) -> WalletStore {
2169 WalletStore::Sqlite { path }
2170}
2171
2172#[cfg(feature = "postgres")]
2174#[uniffi::export]
2175pub fn postgres_wallet_store(url: String) -> WalletStore {
2176 WalletStore::Postgres { url }
2177}
2178
2179#[uniffi::export]
2181pub fn custom_wallet_store(db: Arc<dyn WalletDatabase>) -> WalletStore {
2182 WalletStore::Custom { db }
2183}
2184
2185pub fn resolve_wallet_store(store: WalletStore) -> Result<Arc<dyn WalletDatabase>, FfiError> {
2187 match store {
2188 WalletStore::Sqlite { path } => {
2189 let sqlite = WalletSqliteDatabase::new(path)?;
2190 Ok(sqlite as Arc<dyn WalletDatabase>)
2191 }
2192 #[cfg(feature = "postgres")]
2193 WalletStore::Postgres { url } => {
2194 let pg = WalletPostgresDatabase::new(url)?;
2195 Ok(pg as Arc<dyn WalletDatabase>)
2196 }
2197 WalletStore::Custom { db } => Ok(db),
2198 }
2199}
2200
2201#[uniffi::export]
2203pub fn create_wallet_db(backend: WalletDbBackend) -> Result<Arc<dyn WalletDatabase>, FfiError> {
2204 match backend {
2205 WalletDbBackend::Sqlite { path } => {
2206 let sqlite = WalletSqliteDatabase::new(path)?;
2207 Ok(sqlite as Arc<dyn WalletDatabase>)
2208 }
2209 #[cfg(feature = "postgres")]
2210 WalletDbBackend::Postgres { url } => {
2211 let pg = WalletPostgresDatabase::new(url)?;
2212 Ok(pg as Arc<dyn WalletDatabase>)
2213 }
2214 }
2215}
2216
2217pub fn create_cdk_database_from_ffi(
2219 ffi_db: Arc<dyn WalletDatabase>,
2220) -> Arc<dyn CdkWalletDatabase<cdk::cdk_database::Error> + Send + Sync> {
2221 Arc::new(WalletDatabaseBridge::new(ffi_db))
2222}