Skip to content
This repository was archived by the owner on Feb 3, 2025. It is now read-only.

Commit

Permalink
Merge pull request #954 from MutinyWallet/nostr-contacts-fixes
Browse files Browse the repository at this point in the history
Nostr contacts fixes
  • Loading branch information
AnthonyRonning authored Jan 10, 2024
2 parents ae93a2b + 0692075 commit c2a18cc
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 63 deletions.
12 changes: 4 additions & 8 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 @@ -20,3 +20,5 @@ lightning-invoice = { git = 'https://github.com/MutinyWallet/rust-lightning.git'
lightning-rapid-gossip-sync = { git = 'https://github.com/MutinyWallet/rust-lightning.git', rev = "686a84236f54bf8d7270a5fbec07801e5281691f" }
lightning-background-processor = { git = 'https://github.com/MutinyWallet/rust-lightning.git', rev = "686a84236f54bf8d7270a5fbec07801e5281691f" }
lightning-transaction-sync = { git = 'https://github.com/MutinyWallet/rust-lightning.git', rev = "686a84236f54bf8d7270a5fbec07801e5281691f" }
nostr = { git = 'https://github.com/benthecarman/nostr.git', rev = "7195b8d537db5fe0612b3d94794893bc0021aa11" }
nostr-sdk = { git = 'https://github.com/benthecarman/nostr.git', rev = "7195b8d537db5fe0612b3d94794893bc0021aa11" }
4 changes: 2 additions & 2 deletions mutiny-core/src/labels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub enum TagItem {
Contact((String, Contact)),
}

fn get_label_item_key(label: impl AsRef<str>) -> String {
pub(crate) fn get_label_item_key(label: impl AsRef<str>) -> String {
format!("{}{}", LABEL_PREFIX, label.as_ref())
}

Expand Down Expand Up @@ -284,7 +284,7 @@ impl<S: MutinyStorage> LabelStorage for S {
fn get_contacts(&self) -> Result<HashMap<String, Contact>, MutinyError> {
let all = self.scan::<Contact>(CONTACT_PREFIX, None)?;
// remove the prefix from the keys
let mut contacts = HashMap::new();
let mut contacts = HashMap::with_capacity(all.len());
for (key, contact) in all {
let label = key.replace(CONTACT_PREFIX, "");
// skip archived contacts
Expand Down
19 changes: 15 additions & 4 deletions mutiny-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ use std::{collections::HashMap, sync::atomic::AtomicBool};
use std::{str::FromStr, sync::atomic::Ordering};
use uuid::Uuid;

use crate::labels::LabelItem;
#[cfg(test)]
use mockall::{automock, predicate::*};

Expand Down Expand Up @@ -1156,14 +1157,15 @@ impl<S: MutinyStorage> MutinyWallet<S> {

let contacts = self.storage.get_contacts()?;

let mut updated_contacts: Vec<(String, Value)> =
Vec::with_capacity(contacts.len() + metadata.len());

for (id, contact) in contacts {
if let Some(npub) = contact.npub {
// need to convert to nostr::XOnlyPublicKey
let npub = XOnlyPublicKey::from_slice(&npub.serialize()).unwrap();
if let Some(meta) = metadata.get(&npub) {
let updated = contact.update_with_metadata(meta.clone());
self.storage.edit_contact(id, updated)?;
metadata.remove(&npub);
updated_contacts.push((get_contact_key(id), serde_json::to_value(updated)?));
}
}
}
Expand All @@ -1179,9 +1181,18 @@ impl<S: MutinyStorage> MutinyWallet<S> {
continue;
}

self.storage.create_new_contact(contact)?;
// generate a uuid, this will be the "label" that we use to store the contact
let id = Uuid::new_v4().to_string();
let key = get_contact_key(&id);
updated_contacts.push((key, serde_json::to_value(contact)?));

let key = labels::get_label_item_key(&id);
let label_item = LabelItem::default();
updated_contacts.push((key, serde_json::to_value(label_item)?));
}

self.storage.set(updated_contacts)?;

Ok(())
}

Expand Down
36 changes: 15 additions & 21 deletions mutiny-core/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,7 @@ pub trait MutinyStorage: Clone + Sized + Send + Sync + 'static {
fn vss_client(&self) -> Option<Arc<MutinyVssClient>>;

/// Set a value in the storage, the value will already be encrypted if needed
fn set<T>(&self, key: String, value: T) -> Result<(), MutinyError>
where
T: Serialize;
fn set(&self, items: Vec<(String, impl Serialize)>) -> Result<(), MutinyError>;

/// Set a value in the storage, the value will already be encrypted if needed
/// This is an async version of set, it is not required to implement this
Expand All @@ -131,7 +129,7 @@ pub trait MutinyStorage: Clone + Sized + Send + Sync + 'static {
where
T: Serialize + Send,
{
self.set(key, value)
self.set(vec![(key, value)])
}

/// Set a value in the storage, the function will encrypt the value if needed
Expand All @@ -158,7 +156,7 @@ pub trait MutinyStorage: Clone + Sized + Send + Sync + 'static {

let json: Value = encrypt_value(&key, data, self.cipher())?;

self.set(key, json)
self.set(vec![(key, json)])
}

/// Set a value in the storage, the function will encrypt the value if needed
Expand Down Expand Up @@ -495,18 +493,17 @@ impl MutinyStorage for MemoryStorage {
self.vss_client.clone()
}

fn set<T>(&self, key: String, value: T) -> Result<(), MutinyError>
where
T: Serialize,
{
let data = serde_json::to_value(value).map_err(|e| MutinyError::PersistenceFailed {
source: MutinyStorageError::SerdeError { source: e },
})?;
let mut map = self
.memory
.try_write()
.map_err(|e| MutinyError::write_err(e.into()))?;
map.insert(key, data);
fn set(&self, items: Vec<(String, impl Serialize)>) -> Result<(), MutinyError> {
for (key, value) in items {
let data = serde_json::to_value(value).map_err(|e| MutinyError::PersistenceFailed {
source: MutinyStorageError::SerdeError { source: e },
})?;
let mut map = self
.memory
.try_write()
.map_err(|e| MutinyError::write_err(e.into()))?;
map.insert(key, data);
}

Ok(())
}
Expand Down Expand Up @@ -606,10 +603,7 @@ impl MutinyStorage for () {
None
}

fn set<T>(&self, _key: String, _value: T) -> Result<(), MutinyError>
where
T: Serialize,
{
fn set(&self, _: Vec<(String, impl Serialize)>) -> Result<(), MutinyError> {
Ok(())
}

Expand Down
65 changes: 37 additions & 28 deletions mutiny-wasm/src/indexed_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,10 @@ impl IndexedDbStorage {

async fn save_to_indexed_db(
indexed_db: &Arc<RwLock<RexieContainer>>,
key: &str,
data: &Value,
items: &[(String, Value)],
) -> Result<(), MutinyError> {
// Device lock is only saved to VSS
if key == DEVICE_LOCK_KEY {
if items.len() == 1 && items.iter().all(|(k, _)| k == DEVICE_LOCK_KEY) {
return Ok(());
}

Expand All @@ -169,10 +168,12 @@ impl IndexedDbStorage {
})?;

// save to indexed db
store
.put(&JsValue::from_serde(&data)?, Some(&JsValue::from(key)))
.await
.map_err(|_| MutinyError::write_err(MutinyStorageError::IndexedDBError))?;
for (key, data) in items {
store
.put(&JsValue::from_serde(&data)?, Some(&JsValue::from(key)))
.await
.map_err(|_| MutinyError::write_err(MutinyStorageError::IndexedDBError))?;
}

tx.done()
.await
Expand Down Expand Up @@ -277,7 +278,7 @@ impl IndexedDbStorage {
}

let json: Value = value.into_serde()?;
map.set(key, json)?;
map.set(vec![(key, json)])?;
}

match vss {
Expand Down Expand Up @@ -483,32 +484,40 @@ impl MutinyStorage for IndexedDbStorage {
self.vss.clone()
}

fn set<T>(&self, key: String, value: T) -> Result<(), MutinyError>
where
T: Serialize,
{
let data = serde_json::to_value(value).map_err(|e| MutinyError::PersistenceFailed {
source: MutinyStorageError::SerdeError { source: e },
})?;
fn set(&self, items: Vec<(String, impl Serialize)>) -> Result<(), MutinyError> {
let items = items
.into_iter()
.map(|(k, v)| {
serde_json::to_value(v)
.map_err(|e| MutinyError::PersistenceFailed {
source: MutinyStorageError::SerdeError { source: e },
})
.map(|d| (k, d))
})
.collect::<Result<Vec<(String, Value)>, MutinyError>>()?;

let indexed_db = self.indexed_db.clone();
let key_clone = key.clone();
let data_clone = data.clone();
let items_clone = items.clone();
let logger = self.logger.clone();
spawn_local(async move {
if let Err(e) = Self::save_to_indexed_db(&indexed_db, &key_clone, &data_clone).await {
log_error!(logger, "Failed to save ({key_clone}) to indexed db: {e}");
if let Err(e) = Self::save_to_indexed_db(&indexed_db, &items_clone).await {
log_error!(
logger,
"Failed to save ({items_clone:?}) to indexed db: {e}"
);
};
});

// some values only are read once, so we don't need to write them to memory,
// just need them in indexed db for next time
if !used_once(key.as_ref()) {
let mut map = self
.memory
.try_write()
.map_err(|e| MutinyError::write_err(e.into()))?;
map.insert(key, data);
for (key, data) in items {
if !used_once(key.as_ref()) {
let mut map = self
.memory
.try_write()
.map_err(|e| MutinyError::write_err(e.into()))?;
map.insert(key, data);
}
}

Ok(())
Expand All @@ -522,7 +531,7 @@ impl MutinyStorage for IndexedDbStorage {
source: MutinyStorageError::SerdeError { source: e },
})?;

Self::save_to_indexed_db(&self.indexed_db, &key, &data).await?;
Self::save_to_indexed_db(&self.indexed_db, &[(key.clone(), data.clone())]).await?;

// some values only are read once, so we don't need to write them to memory,
// just need them in indexed db for next time
Expand Down Expand Up @@ -771,7 +780,7 @@ mod tests {
let result: Option<String> = storage.get(&key).unwrap();
assert_eq!(result, None);

storage.set(key.clone(), value).unwrap();
storage.set(vec![(key.clone(), value)]).unwrap();

let result: Option<String> = storage.get(&key).unwrap();
assert_eq!(result, Some(value.to_string()));
Expand Down Expand Up @@ -845,7 +854,7 @@ mod tests {
.await
.unwrap();

storage.set(key.clone(), value).unwrap();
storage.set(vec![(key.clone(), value)]).unwrap();

IndexedDbStorage::clear().await.unwrap();

Expand Down

0 comments on commit c2a18cc

Please sign in to comment.