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

Commit c2a18cc

Browse files
Merge pull request #954 from MutinyWallet/nostr-contacts-fixes
Nostr contacts fixes
2 parents ae93a2b + 0692075 commit c2a18cc

File tree

6 files changed

+75
-63
lines changed

6 files changed

+75
-63
lines changed

Cargo.lock

+4-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ lightning-invoice = { git = 'https://github.com/MutinyWallet/rust-lightning.git'
2020
lightning-rapid-gossip-sync = { git = 'https://github.com/MutinyWallet/rust-lightning.git', rev = "686a84236f54bf8d7270a5fbec07801e5281691f" }
2121
lightning-background-processor = { git = 'https://github.com/MutinyWallet/rust-lightning.git', rev = "686a84236f54bf8d7270a5fbec07801e5281691f" }
2222
lightning-transaction-sync = { git = 'https://github.com/MutinyWallet/rust-lightning.git', rev = "686a84236f54bf8d7270a5fbec07801e5281691f" }
23+
nostr = { git = 'https://github.com/benthecarman/nostr.git', rev = "7195b8d537db5fe0612b3d94794893bc0021aa11" }
24+
nostr-sdk = { git = 'https://github.com/benthecarman/nostr.git', rev = "7195b8d537db5fe0612b3d94794893bc0021aa11" }

mutiny-core/src/labels.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub enum TagItem {
9999
Contact((String, Contact)),
100100
}
101101

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

@@ -284,7 +284,7 @@ impl<S: MutinyStorage> LabelStorage for S {
284284
fn get_contacts(&self) -> Result<HashMap<String, Contact>, MutinyError> {
285285
let all = self.scan::<Contact>(CONTACT_PREFIX, None)?;
286286
// remove the prefix from the keys
287-
let mut contacts = HashMap::new();
287+
let mut contacts = HashMap::with_capacity(all.len());
288288
for (key, contact) in all {
289289
let label = key.replace(CONTACT_PREFIX, "");
290290
// skip archived contacts

mutiny-core/src/lib.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ use std::{collections::HashMap, sync::atomic::AtomicBool};
8888
use std::{str::FromStr, sync::atomic::Ordering};
8989
use uuid::Uuid;
9090

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

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

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

1160+
let mut updated_contacts: Vec<(String, Value)> =
1161+
Vec::with_capacity(contacts.len() + metadata.len());
1162+
11591163
for (id, contact) in contacts {
11601164
if let Some(npub) = contact.npub {
1161-
// need to convert to nostr::XOnlyPublicKey
1162-
let npub = XOnlyPublicKey::from_slice(&npub.serialize()).unwrap();
11631165
if let Some(meta) = metadata.get(&npub) {
11641166
let updated = contact.update_with_metadata(meta.clone());
1165-
self.storage.edit_contact(id, updated)?;
11661167
metadata.remove(&npub);
1168+
updated_contacts.push((get_contact_key(id), serde_json::to_value(updated)?));
11671169
}
11681170
}
11691171
}
@@ -1179,9 +1181,18 @@ impl<S: MutinyStorage> MutinyWallet<S> {
11791181
continue;
11801182
}
11811183

1182-
self.storage.create_new_contact(contact)?;
1184+
// generate a uuid, this will be the "label" that we use to store the contact
1185+
let id = Uuid::new_v4().to_string();
1186+
let key = get_contact_key(&id);
1187+
updated_contacts.push((key, serde_json::to_value(contact)?));
1188+
1189+
let key = labels::get_label_item_key(&id);
1190+
let label_item = LabelItem::default();
1191+
updated_contacts.push((key, serde_json::to_value(label_item)?));
11831192
}
11841193

1194+
self.storage.set(updated_contacts)?;
1195+
11851196
Ok(())
11861197
}
11871198

mutiny-core/src/storage.rs

+15-21
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,7 @@ pub trait MutinyStorage: Clone + Sized + Send + Sync + 'static {
120120
fn vss_client(&self) -> Option<Arc<MutinyVssClient>>;
121121

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

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

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

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

161-
self.set(key, json)
159+
self.set(vec![(key, json)])
162160
}
163161

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

498-
fn set<T>(&self, key: String, value: T) -> Result<(), MutinyError>
499-
where
500-
T: Serialize,
501-
{
502-
let data = serde_json::to_value(value).map_err(|e| MutinyError::PersistenceFailed {
503-
source: MutinyStorageError::SerdeError { source: e },
504-
})?;
505-
let mut map = self
506-
.memory
507-
.try_write()
508-
.map_err(|e| MutinyError::write_err(e.into()))?;
509-
map.insert(key, data);
496+
fn set(&self, items: Vec<(String, impl Serialize)>) -> Result<(), MutinyError> {
497+
for (key, value) in items {
498+
let data = serde_json::to_value(value).map_err(|e| MutinyError::PersistenceFailed {
499+
source: MutinyStorageError::SerdeError { source: e },
500+
})?;
501+
let mut map = self
502+
.memory
503+
.try_write()
504+
.map_err(|e| MutinyError::write_err(e.into()))?;
505+
map.insert(key, data);
506+
}
510507

511508
Ok(())
512509
}
@@ -606,10 +603,7 @@ impl MutinyStorage for () {
606603
None
607604
}
608605

609-
fn set<T>(&self, _key: String, _value: T) -> Result<(), MutinyError>
610-
where
611-
T: Serialize,
612-
{
606+
fn set(&self, _: Vec<(String, impl Serialize)>) -> Result<(), MutinyError> {
613607
Ok(())
614608
}
615609

mutiny-wasm/src/indexed_db.rs

+37-28
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,10 @@ impl IndexedDbStorage {
139139

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

@@ -169,10 +168,12 @@ impl IndexedDbStorage {
169168
})?;
170169

171170
// save to indexed db
172-
store
173-
.put(&JsValue::from_serde(&data)?, Some(&JsValue::from(key)))
174-
.await
175-
.map_err(|_| MutinyError::write_err(MutinyStorageError::IndexedDBError))?;
171+
for (key, data) in items {
172+
store
173+
.put(&JsValue::from_serde(&data)?, Some(&JsValue::from(key)))
174+
.await
175+
.map_err(|_| MutinyError::write_err(MutinyStorageError::IndexedDBError))?;
176+
}
176177

177178
tx.done()
178179
.await
@@ -277,7 +278,7 @@ impl IndexedDbStorage {
277278
}
278279

279280
let json: Value = value.into_serde()?;
280-
map.set(key, json)?;
281+
map.set(vec![(key, json)])?;
281282
}
282283

283284
match vss {
@@ -483,32 +484,40 @@ impl MutinyStorage for IndexedDbStorage {
483484
self.vss.clone()
484485
}
485486

486-
fn set<T>(&self, key: String, value: T) -> Result<(), MutinyError>
487-
where
488-
T: Serialize,
489-
{
490-
let data = serde_json::to_value(value).map_err(|e| MutinyError::PersistenceFailed {
491-
source: MutinyStorageError::SerdeError { source: e },
492-
})?;
487+
fn set(&self, items: Vec<(String, impl Serialize)>) -> Result<(), MutinyError> {
488+
let items = items
489+
.into_iter()
490+
.map(|(k, v)| {
491+
serde_json::to_value(v)
492+
.map_err(|e| MutinyError::PersistenceFailed {
493+
source: MutinyStorageError::SerdeError { source: e },
494+
})
495+
.map(|d| (k, d))
496+
})
497+
.collect::<Result<Vec<(String, Value)>, MutinyError>>()?;
493498

494499
let indexed_db = self.indexed_db.clone();
495-
let key_clone = key.clone();
496-
let data_clone = data.clone();
500+
let items_clone = items.clone();
497501
let logger = self.logger.clone();
498502
spawn_local(async move {
499-
if let Err(e) = Self::save_to_indexed_db(&indexed_db, &key_clone, &data_clone).await {
500-
log_error!(logger, "Failed to save ({key_clone}) to indexed db: {e}");
503+
if let Err(e) = Self::save_to_indexed_db(&indexed_db, &items_clone).await {
504+
log_error!(
505+
logger,
506+
"Failed to save ({items_clone:?}) to indexed db: {e}"
507+
);
501508
};
502509
});
503510

504511
// some values only are read once, so we don't need to write them to memory,
505512
// just need them in indexed db for next time
506-
if !used_once(key.as_ref()) {
507-
let mut map = self
508-
.memory
509-
.try_write()
510-
.map_err(|e| MutinyError::write_err(e.into()))?;
511-
map.insert(key, data);
513+
for (key, data) in items {
514+
if !used_once(key.as_ref()) {
515+
let mut map = self
516+
.memory
517+
.try_write()
518+
.map_err(|e| MutinyError::write_err(e.into()))?;
519+
map.insert(key, data);
520+
}
512521
}
513522

514523
Ok(())
@@ -522,7 +531,7 @@ impl MutinyStorage for IndexedDbStorage {
522531
source: MutinyStorageError::SerdeError { source: e },
523532
})?;
524533

525-
Self::save_to_indexed_db(&self.indexed_db, &key, &data).await?;
534+
Self::save_to_indexed_db(&self.indexed_db, &[(key.clone(), data.clone())]).await?;
526535

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

774-
storage.set(key.clone(), value).unwrap();
783+
storage.set(vec![(key.clone(), value)]).unwrap();
775784

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

848-
storage.set(key.clone(), value).unwrap();
857+
storage.set(vec![(key.clone(), value)]).unwrap();
849858

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

0 commit comments

Comments
 (0)