breez_sdk_spark/persist/backend/
mod.rs1use std::sync::Arc;
14
15use macros::async_trait;
16use spark_wallet::{SessionStore, TokenOutputStore, TreeStore};
17
18use crate::{Network, SdkError, persist::Storage};
19
20mod prebuilt;
21
22pub use prebuilt::PrebuiltBackend;
23
24#[cfg(feature = "sqlite")]
25mod sqlite;
26
27#[cfg(feature = "postgres")]
28mod postgres;
29
30#[cfg(feature = "mysql")]
31mod mysql;
32
33#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
38pub struct ResolvedStores {
39 pub(crate) storage: Arc<dyn Storage>,
40 pub(crate) tree_store: Option<Arc<dyn TreeStore>>,
41 pub(crate) token_output_store: Option<Arc<dyn TokenOutputStore>>,
42 pub(crate) session_store: Option<Arc<dyn SessionStore>>,
43}
44
45#[cfg_attr(feature = "uniffi", uniffi::export)]
52#[async_trait]
53pub trait StorageBackend: Send + Sync {
54 async fn create_stores(
55 &self,
56 network: Network,
57 identity: Vec<u8>,
58 ) -> Result<Arc<ResolvedStores>, SdkError>;
59}
60
61#[cfg_attr(feature = "uniffi", uniffi::export)]
64#[must_use]
65pub fn custom_storage(storage: Arc<dyn Storage>) -> Arc<dyn StorageBackend> {
66 Arc::new(prebuilt::PrebuiltBackend::new(storage, None, None, None))
67}
68
69#[cfg_attr(feature = "uniffi", uniffi::export(async_runtime = "tokio"))]
80pub async fn default_session_store(
81 backend: Arc<dyn StorageBackend>,
82 network: Network,
83 identity: Vec<u8>,
84) -> Result<Arc<dyn crate::session_store::SessionStore>, SdkError> {
85 let stores = backend.create_stores(network, identity).await?;
86 let inner = stores
87 .session_store
88 .clone()
89 .unwrap_or_else(|| Arc::new(spark_wallet::InMemorySessionStore::default()));
90 Ok(Arc::new(crate::session_store::SparkSessionStoreAdapter(
91 inner,
92 )))
93}
94
95#[cfg(feature = "sqlite")]
99#[cfg_attr(feature = "uniffi", uniffi::export)]
100#[must_use]
101pub fn default_storage(storage_dir: String) -> Arc<dyn StorageBackend> {
102 Arc::new(sqlite::SqliteBackend::new(storage_dir))
103}
104
105#[cfg(any(feature = "postgres", feature = "db-storage-api"))]
109#[cfg_attr(feature = "uniffi", uniffi::export)]
110#[allow(clippy::needless_pass_by_value)]
111pub fn postgres_storage(
112 config: crate::persist::postgres::PostgresStorageConfig,
113) -> Result<Arc<dyn StorageBackend>, SdkError> {
114 #[cfg(feature = "postgres")]
115 {
116 let run_migration = config.run_migration;
117 let pool = crate::persist::postgres::create_pool(&config)?;
118 Ok(Arc::new(postgres::PostgresBackend::new(
119 pool,
120 run_migration,
121 )))
122 }
123 #[cfg(not(feature = "postgres"))]
124 {
125 let _ = config;
126 Err(backend_unavailable("PostgreSQL"))
127 }
128}
129
130#[cfg(any(feature = "mysql", feature = "db-storage-api"))]
134#[cfg_attr(feature = "uniffi", uniffi::export)]
135#[allow(clippy::needless_pass_by_value)]
136pub fn mysql_storage(
137 config: crate::persist::mysql::MysqlStorageConfig,
138) -> Result<Arc<dyn StorageBackend>, SdkError> {
139 #[cfg(feature = "mysql")]
140 {
141 let run_migration = config.run_migration;
142 let foreign_key_mode = config.foreign_key_mode;
143 let pool = crate::persist::mysql::create_pool(&config)?;
144 Ok(Arc::new(mysql::MysqlBackend::new(
145 pool,
146 run_migration,
147 foreign_key_mode,
148 )))
149 }
150 #[cfg(not(feature = "mysql"))]
151 {
152 let _ = config;
153 Err(backend_unavailable("MySQL"))
154 }
155}
156
157#[cfg(all(
161 feature = "db-storage-api",
162 any(not(feature = "postgres"), not(feature = "mysql"))
163))]
164fn backend_unavailable(backend: &str) -> SdkError {
165 SdkError::Generic(format!(
166 "{backend} storage is not available in this build of the SDK"
167 ))
168}