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

Timestamp NWC filters #981

Merged
merged 1 commit into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mutiny-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -953,7 +953,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {
_ = filter_check_fut => {
// Check if the filters have changed
if let Ok(current_filters) = nostr.get_filters() {
if current_filters != last_filters {
if !utils::compare_filters_vec(&current_filters, &last_filters) {
log_debug!(logger, "subscribing to new nwc filters");
client.subscribe(current_filters.clone()).await;
last_filters = current_filters;
Expand Down
25 changes: 20 additions & 5 deletions mutiny-core/src/nostr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,27 @@ impl<S: MutinyStorage> NostrManager<S> {
relays
}

fn get_nwc_filters(&self) -> Vec<Filter> {
self.nwc
fn get_nwc_filters(&self) -> Result<Vec<Filter>, MutinyError> {
// if we haven't synced before, use now and save to storage
let time_stamp = match self.storage.get_nwc_sync_time()? {
None => {
let now = Timestamp::now();
self.storage.set_nwc_sync_time(now.as_u64())?;
now
}
Some(time) => Timestamp::from(time),
};

let vec = self
.nwc
.read()
.unwrap()
.iter()
.filter(|x| x.profile.active())
.map(|nwc| nwc.create_nwc_filter())
.collect()
.map(|nwc| nwc.create_nwc_filter(time_stamp))
.collect();

Ok(vec)
}

/// Filters for getting DMs from our contacts
Expand Down Expand Up @@ -168,7 +181,7 @@ impl<S: MutinyStorage> NostrManager<S> {
}

pub fn get_filters(&self) -> Result<Vec<Filter>, MutinyError> {
let mut nwc = self.get_nwc_filters();
let mut nwc = self.get_nwc_filters()?;
let dm = self.get_dm_filter()?;
nwc.push(dm);

Expand Down Expand Up @@ -918,6 +931,8 @@ impl<S: MutinyStorage> NostrManager<S> {
.cloned()
};

self.storage.set_nwc_sync_time(event.created_at.as_u64())?;

if let Some(mut nwc) = nwc {
let event = nwc.handle_nwc_request(event, invoice_handler, self).await?;
Ok(event)
Expand Down
5 changes: 3 additions & 2 deletions mutiny-core/src/nostr/nwc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use lightning_invoice::Bolt11Invoice;
use nostr::key::XOnlyPublicKey;
use nostr::nips::nip47::*;
use nostr::prelude::{decrypt, encrypt};
use nostr::{Event, EventBuilder, EventId, Filter, JsonUtil, Keys, Kind, Tag};
use nostr::{Event, EventBuilder, EventId, Filter, JsonUtil, Keys, Kind, Tag, Timestamp};
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
use std::str::FromStr;
Expand Down Expand Up @@ -266,11 +266,12 @@ impl NostrWalletConnect {
self.server_key.public_key()
}

pub fn create_nwc_filter(&self) -> Filter {
pub fn create_nwc_filter(&self, timestamp: Timestamp) -> Filter {
Filter::new()
.kinds(vec![Kind::WalletConnectRequest])
.author(self.client_pubkey())
.pubkey(self.server_pubkey())
.since(timestamp)
}

/// Create Nostr Wallet Connect Info event
Expand Down
15 changes: 15 additions & 0 deletions mutiny-core/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub const FEDERATIONS_KEY: &str = "federations";
const FEE_ESTIMATES_KEY: &str = "fee_estimates";
pub const BITCOIN_PRICE_CACHE_KEY: &str = "bitcoin_price_cache";
const FIRST_SYNC_KEY: &str = "first_sync";
pub const LAST_NWC_SYNC_TIME_KEY: &str = "last_nwc_sync_time";
pub(crate) const DEVICE_ID_KEY: &str = "device_id";
pub const DEVICE_LOCK_KEY: &str = "device_lock";
pub(crate) const EXPECTED_NETWORK_KEY: &str = "network";
Expand Down Expand Up @@ -424,6 +425,20 @@ pub trait MutinyStorage: Clone + Sized + Send + Sync + 'static {
}
}

fn get_nwc_sync_time(&self) -> Result<Option<u64>, MutinyError> {
self.get_data(LAST_NWC_SYNC_TIME_KEY)
}

fn set_nwc_sync_time(&self, time: u64) -> Result<(), MutinyError> {
// only update if the time is newer
let current = self.get_nwc_sync_time()?.unwrap_or_default();
if current < time {
self.set_data(LAST_NWC_SYNC_TIME_KEY.to_string(), time, None)
} else {
Ok(())
}
}

fn get_device_id(&self) -> Result<String, MutinyError> {
match self.get_data(DEVICE_ID_KEY)? {
Some(id) => Ok(id),
Expand Down
31 changes: 29 additions & 2 deletions mutiny-core/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ use lightning::util::ser::Writeable;
use lightning::util::ser::Writer;
use nostr::key::XOnlyPublicKey;
use nostr::nips::nip05;
use nostr::{Event, FromBech32, JsonUtil, Metadata};
use nostr::{Event, Filter, FromBech32, JsonUtil, Kind, Metadata};
use reqwest::Client;
use serde_json::Value;
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::str::FromStr;

pub const FETCH_TIMEOUT: i32 = 30_000;
Expand Down Expand Up @@ -213,6 +213,33 @@ pub async fn parse_npub_or_nip05(str: &str) -> Result<XOnlyPublicKey, MutinyErro
}
}

/// Compares a list of filters and checks if they are effectively equal
/// The main thing we do not care about is the timestamps
pub fn compare_filters_vec(a: &[Filter], b: &[Filter]) -> bool {
if a.len() != b.len() {
return false;
}

// compare that we have all the same kinds
let agg_kinds_a: HashSet<Kind> = a.iter().flat_map(|i| i.kinds.clone()).collect();
let agg_kinds_b: HashSet<Kind> = b.iter().flat_map(|i| i.kinds.clone()).collect();

if agg_kinds_a != agg_kinds_b {
return false;
}

// compare same authors
let agg_authors_a: HashSet<XOnlyPublicKey> = a.iter().flat_map(|i| i.authors.clone()).collect();
let agg_authors_b: HashSet<XOnlyPublicKey> = b.iter().flat_map(|i| i.authors.clone()).collect();

if agg_authors_a != agg_authors_b {
return false;
}

// if we have the same authors and kinds they are effectively the same filters to us
true
}

/// Returns the version of a channel monitor from a serialized version
/// of a channel monitor.
pub fn get_monitor_version(bytes: &[u8]) -> u64 {
Expand Down
Loading