1use crate::error::{PersistenceError, PreV1MigrationError};
2use crate::types::{ChangeSet, KeychainKind};
3
4use bdk_wallet::migration::{
5 get_pre_v1_wallet_keychains as bdk_get_pre_v1_wallet_keychains,
6 PreV1WalletKeychain as BdkPreV1WalletKeychain,
7};
8use bdk_wallet::{rusqlite::Connection as BdkConnection, WalletPersister};
9
10use std::ops::DerefMut;
11use std::sync::{Arc, Mutex};
12
13#[uniffi::export(with_foreign)]
15pub trait Persistence: Send + Sync {
16 fn initialize(&self) -> Result<Arc<ChangeSet>, PersistenceError>;
18
19 fn persist(&self, changeset: Arc<ChangeSet>) -> Result<(), PersistenceError>;
21}
22
23pub(crate) enum PersistenceType {
24 Custom(Arc<dyn Persistence>),
25 Sql(Mutex<BdkConnection>),
26}
27
28#[derive(Debug, Clone, uniffi::Record)]
31pub struct PreV1WalletKeychain {
32 pub keychain: KeychainKind,
34 pub last_derivation_index: u32,
36 pub checksum: String,
39}
40
41#[derive(uniffi::Object)]
43pub struct Persister {
44 pub(crate) inner: Mutex<PersistenceType>,
45}
46
47#[uniffi::export]
48impl Persister {
49 #[uniffi::constructor]
51 pub fn new_sqlite(path: String) -> Result<Self, PersistenceError> {
52 let conn = BdkConnection::open(path)?;
53 Ok(Self {
54 inner: PersistenceType::Sql(conn.into()).into(),
55 })
56 }
57
58 #[uniffi::constructor]
60 pub fn new_in_memory() -> Result<Self, PersistenceError> {
61 let conn = BdkConnection::open_in_memory()?;
62 Ok(Self {
63 inner: PersistenceType::Sql(conn.into()).into(),
64 })
65 }
66
67 #[uniffi::constructor]
69 pub fn custom(persistence: Arc<dyn Persistence>) -> Self {
70 Self {
71 inner: PersistenceType::Custom(persistence).into(),
72 }
73 }
74
75 pub fn get_pre_v1_wallet_keychains(
77 &self,
78 ) -> Result<Vec<PreV1WalletKeychain>, PreV1MigrationError> {
79 let mut lock = self.inner.lock().unwrap();
80 match lock.deref_mut() {
81 PersistenceType::Sql(ref conn) => {
82 let mut conn_lock = conn.lock().unwrap();
83 bdk_get_pre_v1_wallet_keychains(conn_lock.deref_mut())
84 .map(|keychains| keychains.into_iter().map(Into::into).collect())
85 .map_err(Into::into)
86 }
87 PersistenceType::Custom(_) => Err(PreV1MigrationError::SqliteOnly),
88 }
89 }
90}
91
92impl From<BdkPreV1WalletKeychain> for PreV1WalletKeychain {
93 fn from(value: BdkPreV1WalletKeychain) -> Self {
94 Self {
95 keychain: value.keychain,
96 last_derivation_index: value.last_derivation_index,
97 checksum: value.checksum,
98 }
99 }
100}
101
102impl WalletPersister for PersistenceType {
103 type Error = PersistenceError;
104
105 fn initialize(persister: &mut Self) -> Result<bdk_wallet::ChangeSet, Self::Error> {
106 match persister {
107 PersistenceType::Sql(ref conn) => {
108 let mut lock = conn.lock().unwrap();
109 let deref = lock.deref_mut();
110 Ok(BdkConnection::initialize(deref)?)
111 }
112 PersistenceType::Custom(any) => any
113 .initialize()
114 .map(|changeset| changeset.as_ref().clone().into()),
115 }
116 }
117
118 fn persist(persister: &mut Self, changeset: &bdk_wallet::ChangeSet) -> Result<(), Self::Error> {
119 match persister {
120 PersistenceType::Sql(ref conn) => {
121 let mut lock = conn.lock().unwrap();
122 let deref = lock.deref_mut();
123 Ok(BdkConnection::persist(deref, changeset)?)
124 }
125 PersistenceType::Custom(any) => {
126 let ffi_changeset: ChangeSet = changeset.clone().into();
127 any.persist(Arc::new(ffi_changeset))
128 }
129 }
130 }
131}