Skip to content

Commit

Permalink
simple implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ec2 committed Aug 12, 2024
1 parent 5b57fbc commit 45a8d1b
Show file tree
Hide file tree
Showing 10 changed files with 245 additions and 8 deletions.
112 changes: 112 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ getrandom = { version = "0.2", features = ["js"] }
thiserror = "1.0.63"
console_error_panic_hook = { version = "0.1.7", optional = true }
wasm-bindgen-futures = "0.4.42"
indexed_db_futures = "0.5.0"
web-sys = { version = "0.3.69", features = ["console"] }

[dev-dependencies]
wasm-bindgen-test = "0.3.42"
Expand Down
16 changes: 16 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ pub enum Error {
// DecodingError(#[from] zcash_keys::keys::DecodingError),
#[error("Javascript error")]
JsError(JsValue),
#[error("DomException {name} ({code}): {message}")]
DomException {
name: String,
message: String,
code: u16,
},
}

impl From<Error> for JsValue {
Expand All @@ -26,3 +32,13 @@ impl From<JsValue> for Error {
Error::JsError(e)
}
}

impl From<indexed_db_futures::web_sys::DomException> for Error {
fn from(e: indexed_db_futures::web_sys::DomException) -> Self {
Self::DomException {
name: e.name(),
message: e.message(),
code: e.code(),
}
}
}
73 changes: 73 additions & 0 deletions src/store/indexed_db_store.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright 2024 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use crate::error::Error;
use crate::store::WalletStore;
use indexed_db_futures::prelude::*;
use js_sys::Uint8Array;
use wasm_bindgen::JsValue;

static DB_NAME: &str = "test_db";
static KV_STORE: &str = "kv_store";
/// A simple IndexedDb store for wallet data
pub struct IdbStore {
pub inner: indexed_db_futures::IdbDatabase,
}

impl WalletStore for IdbStore {
async fn update(&mut self, key: &str, value: &[u8]) -> Result<(), Error> {
let tx = self
.inner
.transaction_on_one_with_mode(KV_STORE, IdbTransactionMode::Readwrite)?;
let store = tx.object_store(KV_STORE)?;

store.put_key_val_owned(JsValue::from_str(key), &Uint8Array::from(value))?;
tx.await.into_result()?;
Ok(())
}

async fn get(&self, key: &str) -> Result<Option<Vec<u8>>, Error> {
let tx = self
.inner
.transaction_on_one_with_mode(KV_STORE, IdbTransactionMode::Readonly)?;
let store = tx.object_store(KV_STORE)?;
match store.get(&JsValue::from_str(key))?.await? {
Some(v) => {
let v = Uint8Array::from(v);
Ok(Some(v.to_vec()))
}
None => Ok(None),
}
}

async fn clear(&mut self, key: &str) -> Result<(), Error> {
let tx = self
.inner
.transaction_on_one_with_mode(KV_STORE, IdbTransactionMode::Readwrite)?;
let store = tx.object_store(KV_STORE)?;
store.delete_owned(&JsValue::from_str(key))?;
tx.await.into_result()?;
Ok(())
}
}

impl IdbStore {
pub async fn new() -> Result<Self, Error> {
let mut db_req = IdbDatabase::open_u32(DB_NAME, 1)?;
// let db = open.await?;
db_req.set_on_upgrade_needed(Some(|evt: &IdbVersionChangeEvent| -> Result<(), JsValue> {
let create_store_if_needed =
|evt: &IdbVersionChangeEvent, store_key: &'static str| -> Result<(), JsValue> {
if let None = evt.db().object_store_names().find(|n| n == store_key) {
evt.db().create_object_store(store_key)?;
}
Ok(())
};
create_store_if_needed(evt, &KV_STORE)?;
Ok(())
}));
Ok(Self {
inner: db_req.await?,
})
}
}
9 changes: 6 additions & 3 deletions src/store/injected_store.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Copyright 2024 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use crate::store::WalletStore;
use crate::error::Error;
use crate::store::WalletStore;
use wasm_bindgen::prelude::*;

#[wasm_bindgen(typescript_custom_section)]
Expand Down Expand Up @@ -50,9 +50,12 @@ impl WalletStore for InjectedStore {
Ok(())
}

async fn get(&self, key: &str) -> Result<Vec<u8>, Error> {
async fn get(&self, key: &str) -> Result<Option<Vec<u8>>, Error> {
let result = InjectedStore::get(self, key).await?;
Ok(js_sys::Uint8Array::new(&result).to_vec())
if result.is_null() {
return Ok(None);
}
Ok(Some(js_sys::Uint8Array::new(&result).to_vec()))
}

async fn clear(&mut self, key: &str) -> Result<(), Error> {
Expand Down
6 changes: 3 additions & 3 deletions src/store/memory_store.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Copyright 2024 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use crate::store::WalletStore;
use crate::error::Error;
use crate::store::WalletStore;

/// A simple in-memory store for wallet data. Useful for testing
pub struct MemoryStore {
Expand All @@ -15,8 +15,8 @@ impl WalletStore for MemoryStore {
Ok(())
}

async fn get(&self, key: &str) -> Result<Vec<u8>, Error> {
Ok(self.inner.get(key).unwrap().to_vec())
async fn get(&self, key: &str) -> Result<Option<Vec<u8>>, Error> {
Ok(self.inner.get(key).cloned())
}

async fn clear(&mut self, key: &str) -> Result<(), Error> {
Expand Down
2 changes: 2 additions & 0 deletions src/store/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod indexed_db_store;
mod injected_store;
mod memory_store;
mod wallet_store;

pub use indexed_db_store::IdbStore;
pub use injected_store::InjectedStore;
pub use memory_store::MemoryStore;
pub use wallet_store::WalletStore;
2 changes: 1 addition & 1 deletion src/store/wallet_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ use crate::error::Error;

pub trait WalletStore {
async fn update(&mut self, key: &str, value: &[u8]) -> Result<(), Error>;
async fn get(&self, key: &str) -> Result<Vec<u8>, Error>;
async fn get(&self, key: &str) -> Result<Option<Vec<u8>>, Error>;
async fn clear(&mut self, key: &str) -> Result<(), Error>;
}
2 changes: 1 addition & 1 deletion src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl<S: WalletStore> Wallet<S> {
pub fn add(&self, _account: Account) {}

pub async fn get(&self, _index: AccountIndex) -> Result<Account, Error> {
Account::from_bytes(&self.store.get("yer").await?)
Account::from_bytes(&self.store.get("yer").await?.unwrap())
}
}

Expand Down
29 changes: 29 additions & 0 deletions tests/indexed_db_store.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use wasm_bindgen_test::*;
use web_sys::console;
wasm_bindgen_test_configure!(run_in_browser);
use webz_core::store::{self, WalletStore as _};
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1, 1);
}

#[wasm_bindgen_test]
async fn idb() {
let k = "key";
let v = vec![1, 2, 3];
let v2 = vec![1, 2, 3, 4];
// Add to store
let mut store = store::IdbStore::new().await.unwrap();
store.update(k, &v).await.unwrap();

// Get from store
assert_eq!(store.get(k).await.unwrap().unwrap(), v);

// Update Key
store.update(k, &v2).await.unwrap();
assert_eq!(store.get(k).await.unwrap().unwrap(), v2);

// Clear Key
store.clear(k).await.unwrap();
assert_eq!(store.get(k).await.unwrap(), None);
}

0 comments on commit 45a8d1b

Please sign in to comment.