Skip to content

Commit 2d8ac36

Browse files
committed
sdk: update the code to use nostr-gossip crate
Signed-off-by: Yuki Kishimoto <[email protected]>
1 parent e9bf064 commit 2d8ac36

File tree

11 files changed

+407
-736
lines changed

11 files changed

+407
-736
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ The project is split up into several crates:
1414
- [**nostr-ndb**](./database/nostr-ndb): [nostrdb](https://github.com/damus-io/nostrdb) storage backend
1515
- [**nostr-indexeddb**](./database/nostr-indexeddb): IndexedDB storage backend
1616
- [**nostr-gossip**](./gossip/nostr-gossip): Gossip traits
17+
- [**nostr-gossip-sqlite**](./gossip/nostr-gossip-sqlite): SQLite storage for gossip
1718
- Remote File Storage implementations:
1819
- [**nostr-blossom**](./rfs/nostr-blossom): A library for interacting with the Blossom protocol
1920
- [**nostr-http-file-storage**](./rfs/nostr-http-file-storage): HTTP File Storage client (NIP-96)

crates/nostr-sdk/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,16 @@ nip98 = ["nostr/nip98"]
3535
async-utility.workspace = true
3636
nostr = { workspace = true, features = ["std"] }
3737
nostr-database.workspace = true
38+
nostr-gossip.workspace = true
3839
nostr-relay-pool.workspace = true
3940
tokio = { workspace = true, features = ["sync"] }
4041

4142
[dev-dependencies]
4243
nostr-connect.workspace = true
4344
nostr-lmdb.workspace = true
4445
nostr-ndb.workspace = true
46+
nostr-gossip-sqlite.workspace = true
47+
tempfile.workspace = true
4548
tokio = { workspace = true, features = ["macros"] }
4649
tracing = { workspace = true, features = ["std"] }
4750
tracing-subscriber = { workspace = true, features = ["env-filter"] }

crates/nostr-sdk/examples/gossip.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@
44

55
use std::time::Duration;
66

7+
use nostr_gossip_sqlite::prelude::*;
78
use nostr_sdk::prelude::*;
89

910
#[tokio::main]
1011
async fn main() -> Result<()> {
1112
tracing_subscriber::fmt::init();
1213

1314
let keys = Keys::parse("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")?;
14-
let opts = ClientOptions::new().gossip(true);
15-
let client = Client::builder().signer(keys).opts(opts).build();
15+
let gossip = NostrGossipSqlite::open("db/gossip.db").await?;
16+
let client = Client::builder().signer(keys).gossip(gossip).build();
1617

1718
client.add_discovery_relay("wss://relay.damus.io").await?;
1819
client.add_discovery_relay("wss://purplepag.es").await?;

crates/nostr-sdk/src/client/builder.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::sync::Arc;
99
use nostr::signer::{IntoNostrSigner, NostrSigner};
1010
use nostr_database::memory::MemoryDatabase;
1111
use nostr_database::{IntoNostrDatabase, NostrDatabase};
12+
use nostr_gossip::NostrGossip;
1213
use nostr_relay_pool::monitor::Monitor;
1314
use nostr_relay_pool::policy::AdmitPolicy;
1415
use nostr_relay_pool::transport::websocket::{
@@ -29,6 +30,8 @@ pub struct ClientBuilder {
2930
pub admit_policy: Option<Arc<dyn AdmitPolicy>>,
3031
/// Database
3132
pub database: Arc<dyn NostrDatabase>,
33+
/// Gossip
34+
pub gossip: Option<Arc<dyn NostrGossip>>,
3235
/// Relay monitor
3336
pub monitor: Option<Monitor>,
3437
/// Client options
@@ -42,6 +45,7 @@ impl Default for ClientBuilder {
4245
websocket_transport: Arc::new(DefaultWebsocketTransport),
4346
admit_policy: None,
4447
database: Arc::new(MemoryDatabase::default()),
48+
gossip: None,
4549
monitor: None,
4650
opts: ClientOptions::default(),
4751
}
@@ -106,6 +110,16 @@ impl ClientBuilder {
106110
self
107111
}
108112

113+
/// Set a gossip database
114+
#[inline]
115+
pub fn gossip<T>(mut self, gossip: T) -> Self
116+
where
117+
T: NostrGossip + 'static,
118+
{
119+
self.gossip = Some(Arc::new(gossip));
120+
self
121+
}
122+
109123
/// Set monitor
110124
#[inline]
111125
pub fn monitor(mut self, monitor: Monitor) -> Self {

crates/nostr-sdk/src/client/error.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::fmt;
77
use nostr::prelude::*;
88
use nostr::serde_json;
99
use nostr_database::prelude::*;
10+
use nostr_gossip::error::GossipError;
1011
use nostr_relay_pool::__private::SharedStateError;
1112
use nostr_relay_pool::prelude::*;
1213

@@ -21,6 +22,8 @@ pub enum Error {
2122
Database(DatabaseError),
2223
/// Signer error
2324
Signer(SignerError),
25+
/// Gossip error
26+
Gossip(GossipError),
2427
/// [`EventBuilder`] error
2528
EventBuilder(event::builder::Error),
2629
/// Json error
@@ -45,6 +48,7 @@ impl fmt::Display for Error {
4548
Self::RelayPool(e) => e.fmt(f),
4649
Self::Database(e) => e.fmt(f),
4750
Self::Signer(e) => e.fmt(f),
51+
Self::Gossip(e) => e.fmt(f),
4852
Self::EventBuilder(e) => e.fmt(f),
4953
Self::Json(e) => e.fmt(f),
5054
Self::SharedState(e) => e.fmt(f),
@@ -82,6 +86,12 @@ impl From<SignerError> for Error {
8286
}
8387
}
8488

89+
impl From<GossipError> for Error {
90+
fn from(e: GossipError) -> Self {
91+
Self::Gossip(e)
92+
}
93+
}
94+
8595
impl From<event::builder::Error> for Error {
8696
fn from(e: event::builder::Error) -> Self {
8797
Self::EventBuilder(e)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use std::sync::Arc;
2+
3+
use nostr::prelude::BoxedFuture;
4+
use nostr::{Event, RelayUrl, SubscriptionId};
5+
use nostr_gossip::NostrGossip;
6+
use nostr_relay_pool::policy::{AdmitPolicy, AdmitStatus, PolicyError};
7+
8+
#[derive(Debug)]
9+
pub(crate) struct AdmissionPolicyMiddleware {
10+
pub(crate) gossip: Option<Arc<dyn NostrGossip>>,
11+
pub(crate) external_policy: Option<Arc<dyn AdmitPolicy>>,
12+
}
13+
14+
impl AdmitPolicy for AdmissionPolicyMiddleware {
15+
fn admit_connection<'a>(
16+
&'a self,
17+
relay_url: &'a RelayUrl,
18+
) -> BoxedFuture<'a, Result<AdmitStatus, PolicyError>> {
19+
Box::pin(async move {
20+
match &self.external_policy {
21+
Some(policy) => policy.admit_connection(relay_url).await,
22+
None => Ok(AdmitStatus::Success),
23+
}
24+
})
25+
}
26+
27+
fn admit_event<'a>(
28+
&'a self,
29+
relay_url: &'a RelayUrl,
30+
subscription_id: &'a SubscriptionId,
31+
event: &'a Event,
32+
) -> BoxedFuture<'a, Result<AdmitStatus, PolicyError>> {
33+
Box::pin(async move {
34+
// Process event in gossip
35+
if let Some(gossip) = &self.gossip {
36+
gossip
37+
.process(event, Some(relay_url))
38+
.await
39+
.map_err(PolicyError::backend)?;
40+
}
41+
42+
// Check if event is allowed by external policy
43+
match &self.external_policy {
44+
Some(policy) => policy.admit_event(relay_url, subscription_id, event).await,
45+
None => Ok(AdmitStatus::Success),
46+
}
47+
})
48+
}
49+
}

0 commit comments

Comments
 (0)