diff --git a/moksha-wallet/src/error.rs b/moksha-wallet/src/error.rs index f1693a3a..ead4d511 100644 --- a/moksha-wallet/src/error.rs +++ b/moksha-wallet/src/error.rs @@ -42,6 +42,7 @@ pub enum MokshaWalletError { #[cfg(not(target_arch = "wasm32"))] #[error("Sqlite Error {0}")] Sqlite(#[from] sqlx::sqlite::SqliteError), + #[error("Utf8 Error {0}")] Utf8(#[from] FromUtf8Error), diff --git a/moksha-wallet/src/localstore/mod.rs b/moksha-wallet/src/localstore/mod.rs index e0e0ce43..2a83183f 100644 --- a/moksha-wallet/src/localstore/mod.rs +++ b/moksha-wallet/src/localstore/mod.rs @@ -26,6 +26,27 @@ pub struct WalletKeyset { pub active: bool, } +impl WalletKeyset { + pub fn new( + keyset_id: &str, + mint_url: &Url, + currency_unit: &CurrencyUnit, + last_index: u64, + public_keys: HashMap, + active: bool, + ) -> Self { + Self { + id: None, + keyset_id: keyset_id.to_owned(), + mint_url: mint_url.to_owned(), + currency_unit: currency_unit.clone(), + last_index, + public_keys, + active, + } + } +} + #[cfg(not(target_arch = "wasm32"))] #[async_trait(?Send)] pub trait LocalStore { @@ -46,10 +67,18 @@ pub trait LocalStore { tx: &mut sqlx::Transaction, ) -> Result; - async fn get_keysets(&self) -> Result, MokshaWalletError>; - async fn add_keyset(&self, keyset: &WalletKeyset) -> Result<(), MokshaWalletError>; + async fn get_keysets( + &self, + tx: &mut sqlx::Transaction, + ) -> Result, MokshaWalletError>; + async fn upsert_keyset( + &self, + tx: &mut sqlx::Transaction, + keyset: &WalletKeyset, + ) -> Result<(), MokshaWalletError>; async fn update_keyset_last_index( &self, + tx: &mut sqlx::Transaction, keyset: &WalletKeyset, ) -> Result<(), MokshaWalletError>; } diff --git a/moksha-wallet/src/localstore/sqlite.rs b/moksha-wallet/src/localstore/sqlite.rs index 791b7748..b40fe0a9 100644 --- a/moksha-wallet/src/localstore/sqlite.rs +++ b/moksha-wallet/src/localstore/sqlite.rs @@ -92,9 +92,15 @@ impl LocalStore for SqliteLocalStore { .into()) } - async fn add_keyset(&self, keyset: &WalletKeyset) -> Result<(), MokshaWalletError> { + async fn upsert_keyset( + &self, + tx: &mut sqlx::Transaction, + keyset: &WalletKeyset, + ) -> Result<(), MokshaWalletError> { let row: (i64,) = sqlx::query_as( - r#"INSERT INTO keysets (keyset_id, mint_url, currency_unit, last_index, public_keys, active) VALUES ($1, $2, $3, $4, $5, $6);SELECT last_insert_rowid() as id; + r#"INSERT INTO keysets (keyset_id, mint_url, currency_unit, last_index, public_keys, active) VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT(keyset_id, mint_url) DO UPDATE SET currency_unit = $3, last_index = $4, public_keys = $5, active = $6; + SELECT last_insert_rowid() as id; "#) .bind(keyset.keyset_id.to_owned()) .bind(keyset.mint_url.as_str()) @@ -102,28 +108,31 @@ impl LocalStore for SqliteLocalStore { .bind(keyset.last_index as i64) .bind(serde_json::to_string(&keyset.public_keys)?) .bind(keyset.active) - .fetch_one(&self.pool) + .fetch_one(&mut **tx) .await?; println!("row: {:?}", row.0); Ok(()) } - async fn get_keysets(&self) -> Result, MokshaWalletError> { + async fn get_keysets( + &self, + tx: &mut sqlx::Transaction, + ) -> Result, MokshaWalletError> { let rows = sqlx::query("SELECT * FROM keysets;") - .fetch_all(&self.pool) + .fetch_all(&mut **tx) .await?; Ok(rows .iter() .map(|row| { let id: i64 = row.get(0); - let mint_url: Url = Url::parse(row.get(1)).unwrap(); // FIXME + let mint_url: Url = Url::parse(row.get(1)).expect("invalid url in localstore"); let keyset_id: String = row.get(2); let currency_unit: String = row.get(3); let active: bool = row.get(4); let last_index: i64 = row.get(5); let public_keys: HashMap = - serde_json::from_str(row.get(6)).unwrap(); // FIXME unwrap + serde_json::from_str(row.get(6)).expect("invalid json in localstore"); Ok(WalletKeyset { id: Some(id as u64), mint_url, @@ -139,6 +148,7 @@ impl LocalStore for SqliteLocalStore { async fn update_keyset_last_index( &self, + tx: &mut sqlx::Transaction, keyset: &WalletKeyset, ) -> Result<(), MokshaWalletError> { let id = match keyset.id { @@ -149,7 +159,7 @@ impl LocalStore for SqliteLocalStore { sqlx::query(r#"UPDATE keysets SET last_index = $1 WHERE id = $2;"#) .bind(keyset.last_index as i64) .bind(id) - .execute(&self.pool) + .execute(&mut **tx) .await?; Ok(()) } diff --git a/moksha-wallet/src/wallet.rs b/moksha-wallet/src/wallet.rs index 3af5c2a4..40b1f3b4 100644 --- a/moksha-wallet/src/wallet.rs +++ b/moksha-wallet/src/wallet.rs @@ -85,34 +85,28 @@ where return Err(MokshaWalletError::UnsupportedApiVersion); } - let load_keysets = localstore.get_keysets().await?; - + let mut tx = localstore.begin_tx().await?; let mint_keysets = client.get_keysets(&mint_url).await?; - if load_keysets.is_empty() { - for m in mint_keysets.keysets.iter() { - let public_keys = client - .get_keys_by_id(&mint_url, m.id.clone()) - .await? - .keysets - .into_iter() - .find(|k| k.id == m.id) - .expect("no valid keyset found") - .keys - .clone(); - - let wallet_keyset = WalletKeyset { - id: None, - keyset_id: m.clone().id, - mint_url: mint_url.clone(), - currency_unit: m.unit.clone(), - last_index: 0, - public_keys, - active: true, - }; - localstore.add_keyset(&wallet_keyset).await?; - } + + for m in mint_keysets.keysets.iter() { + let public_keys = client + .get_keys_by_id(&mint_url, m.id.clone()) + .await? + .keysets + .into_iter() + .find(|k| k.id == m.id) + .expect("no valid keyset found") + .keys + .clone(); + + let wallet_keyset = WalletKeyset::new(&m.id, &mint_url, &m.unit, 0, public_keys, true); + localstore.upsert_keyset(&mut tx, &wallet_keyset).await?; } + let load_keysets = localstore.get_keysets(&mut tx).await?; + print!("keysets {:?}", load_keysets); + tx.commit().await?; + // FIXME store all keysets let keys = client.get_keys(&mint_url).await?;