feat(nostr): upgrade to recent nostr version and add error handling
This commit is contained in:
parent
86680d9c21
commit
a73e7c1d68
|
@ -728,6 +728,7 @@ dependencies = [
|
||||||
"leptos_router",
|
"leptos_router",
|
||||||
"nostr-sdk",
|
"nostr-sdk",
|
||||||
"serde",
|
"serde",
|
||||||
|
"tokio",
|
||||||
"uuid",
|
"uuid",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
|
@ -1524,10 +1525,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.73"
|
version = "0.3.76"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fb15147158e79fd8b8afd0252522769c4f48725460b37338544d8379d94fc8f9"
|
checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -3247,9 +3249,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.96"
|
version = "0.2.99"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "21d3b25c3ea1126a2ad5f4f9068483c2af1e64168f847abe863a526b8dbfe00b"
|
checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
@ -3258,13 +3260,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-backend"
|
name = "wasm-bindgen-backend"
|
||||||
version = "0.2.96"
|
version = "0.2.99"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "52857d4c32e496dc6537646b5b117081e71fd2ff06de792e3577a150627db283"
|
checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.90",
|
"syn 2.0.90",
|
||||||
|
@ -3273,9 +3274,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-futures"
|
name = "wasm-bindgen-futures"
|
||||||
version = "0.4.46"
|
version = "0.4.49"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "951fe82312ed48443ac78b66fa43eded9999f738f6022e67aead7b708659e49a"
|
checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
@ -3286,9 +3287,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.96"
|
version = "0.2.99"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "920b0ffe069571ebbfc9ddc0b36ba305ef65577c94b06262ed793716a1afd981"
|
checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
|
@ -3296,9 +3297,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.96"
|
version = "0.2.99"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf59002391099644be3524e23b781fa43d2be0c5aa0719a18c0731b9d195cab6"
|
checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -3309,9 +3310,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.96"
|
version = "0.2.99"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5047c5392700766601942795a436d7d2599af60dcc3cc1248c9120bfb0827b0"
|
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-streams"
|
name = "wasm-streams"
|
||||||
|
@ -3328,9 +3329,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.73"
|
version = "0.3.76"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "476364ff87d0ae6bfb661053a9104ab312542658c3d8f963b7ace80b6f9b26b9"
|
checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
|
|
@ -15,11 +15,12 @@ leptos = { version = "0.6" }
|
||||||
leptos_meta = { version = "0.6" }
|
leptos_meta = { version = "0.6" }
|
||||||
leptos_actix = { version = "0.6", optional = true }
|
leptos_actix = { version = "0.6", optional = true }
|
||||||
leptos_router = { version = "0.6" }
|
leptos_router = { version = "0.6" }
|
||||||
wasm-bindgen = "=0.2.96"
|
wasm-bindgen = "=0.2.99"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
uuid = { version = "1.0", features = ["v4"] }
|
uuid = { version = "1.0", features = ["v4"] }
|
||||||
web-sys = { version = "0.3", features = ["Event"] }
|
web-sys = { version = "0.3", features = ["Event"] }
|
||||||
nostr-sdk = "0.37"
|
nostr-sdk = "0.37"
|
||||||
|
tokio = "1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
csr = ["leptos/csr", "leptos_meta/csr", "leptos_router/csr"]
|
csr = ["leptos/csr", "leptos_meta/csr", "leptos_router/csr"]
|
||||||
|
|
10
src/app.rs
10
src/app.rs
|
@ -5,30 +5,30 @@ use leptos_meta::*;
|
||||||
use crate::components::{item_form::ItemForm, items_list::ItemsList};
|
use crate::components::{item_form::ItemForm, items_list::ItemsList};
|
||||||
use crate::models::item::Item;
|
use crate::models::item::Item;
|
||||||
use crate::nostr::NostrClient;
|
use crate::nostr::NostrClient;
|
||||||
use std::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use leptos::spawn_local;
|
use leptos::spawn_local;
|
||||||
|
use nostr_sdk::serde_json;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn App() -> impl IntoView {
|
pub fn App() -> impl IntoView {
|
||||||
provide_meta_context();
|
provide_meta_context();
|
||||||
// Signal to store and update the list of items.
|
// Signal to store and update the list of items.
|
||||||
let (items_signal, set_items) = create_signal(Vec::<Item>::new());
|
let (items_signal, set_items) = create_signal(Vec::<Item>::new());
|
||||||
let (tx, mut rx) = mpsc::channel::<String>();
|
let (tx, mut rx) = mpsc::channel::<String>(100);
|
||||||
|
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
//initialize nostr client
|
//initialize nostr client
|
||||||
let nostr_client = NostrClient::new("wss://relay.example.com").await.unwrap();
|
let nostr_client = NostrClient::new("wss://relay.example.com").await.unwrap();
|
||||||
nostr_client.subscribe_to_items(tx.clone()).await.unwrap();
|
nostr_client.subscribe_to_items(tx.clone()).await.unwrap();
|
||||||
|
|
||||||
// Handle incoming events
|
//handle incoming events
|
||||||
while let Ok(content) = rx.recv(){
|
while let Some(content) = rx.recv().await {
|
||||||
if let Ok(item) = serde_json::from_str::<Item>(&content) {
|
if let Ok(item) = serde_json::from_str::<Item>(&content) {
|
||||||
set_items.update(|items| items.push(item));
|
set_items.update(|items| items.push(item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Function to handle adding a new item to the list.
|
// Function to handle adding a new item to the list.
|
||||||
let add_item = move |name: String, description: String, tags: Vec<(String, String)>| {
|
let add_item = move |name: String, description: String, tags: Vec<(String, String)>| {
|
||||||
set_items.update(|items| {
|
set_items.update(|items| {
|
||||||
|
|
77
src/nostr.rs
77
src/nostr.rs
|
@ -1,19 +1,47 @@
|
||||||
use nostr_sdk::client::Error;
|
use nostr_sdk::{client::Error, prelude::*, RelayPoolNotification};
|
||||||
use nostr_sdk::prelude::*;
|
use tokio::sync::mpsc;
|
||||||
use nostr_sdk::RelayPoolNotification;
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MyError {
|
||||||
|
NostrClientError(nostr_sdk::client::Error),
|
||||||
|
NostrUnsignedError(nostr_sdk::event::unsigned::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MyError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
MyError::NostrClientError(e) => write!(f, "Nostr Client Error: {}", e),
|
||||||
|
MyError::NostrUnsignedError(e) => write!(f, "Nostr Unsigned Error: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<nostr_sdk::client::Error> for MyError {
|
||||||
|
fn from(err: nostr_sdk::client::Error) -> MyError {
|
||||||
|
MyError::NostrClientError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<nostr_sdk::event::unsigned::Error> for MyError {
|
||||||
|
fn from(err: nostr_sdk::event::unsigned::Error) -> MyError {
|
||||||
|
MyError::NostrUnsignedError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct NostrClient {
|
pub struct NostrClient {
|
||||||
client: Client,
|
client: Client,
|
||||||
|
keys: Keys,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NostrClient {
|
impl NostrClient {
|
||||||
pub async fn new(relay_url: &str) -> Result<Self, Error> {
|
pub async fn new(relay_url: &str) -> Result<Self, Error> {
|
||||||
let keys = Keys::new(SecretKey::generate());
|
let keys = Keys::new(SecretKey::generate());
|
||||||
let client = Client::new(keys);
|
let client = Client::new(keys.clone());
|
||||||
client.add_relay(relay_url).await?;
|
client.add_relay(relay_url).await?;
|
||||||
client.connect().await;
|
client.connect().await;
|
||||||
|
|
||||||
Ok(Self { client })
|
Ok(Self { client, keys })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn publish_item(
|
pub async fn publish_item(
|
||||||
|
@ -21,23 +49,44 @@ impl NostrClient {
|
||||||
name: String,
|
name: String,
|
||||||
description: String,
|
description: String,
|
||||||
tags: Vec<(String, String)>
|
tags: Vec<(String, String)>
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), MyError> {
|
||||||
let content = format!("{{\"name\":\"{}\",\"description\":\"{}\",\"tags\":[{}]}}", name, description, tags.iter().map(|(k, v)| format!("(\"{}\",\"{}\")", k, v)).collect::<Vec<_>>().join(","));
|
let content = format!(
|
||||||
let event = EventBuilder::new(Kind::TextNote, content).build()?;
|
"{{\"name\":\"{}\",\"description\":\"{}\",\"tags\":[{}]}}",
|
||||||
self.client.send_event_builder(event).await?;
|
name,
|
||||||
|
description,
|
||||||
|
tags.iter()
|
||||||
|
.map(|(k, v)| format!("(\"{}\",\"{}\")", k, v))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(",")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create the event builder
|
||||||
|
let event_builder = EventBuilder::new(Kind::TextNote, content);
|
||||||
|
// Build the unsigned event
|
||||||
|
let unsigned_event = event_builder.build(self.keys.public_key());
|
||||||
|
// Sign the event and handle the error explicitly
|
||||||
|
let signed_event = match unsigned_event.sign(&self.keys).await {
|
||||||
|
Ok(event) => event,
|
||||||
|
Err(e) => return Err(MyError::from(e)), // Convert the error to the expected type
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send the event
|
||||||
|
self.client.send_event(signed_event).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn subscribe_to_items(
|
pub async fn subscribe_to_items(
|
||||||
&self,
|
&self,
|
||||||
tx: std::sync::mpsc::Sender<String>
|
tx: mpsc::Sender<String>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut notifications = self.client.notifications();
|
let mut notifications = self.client.notifications();
|
||||||
std::thread::spawn(move || {
|
// Use tokio::spawn for async context
|
||||||
|
tokio::spawn(async move {
|
||||||
while let Ok(notification) = notifications.recv().await {
|
while let Ok(notification) = notifications.recv().await {
|
||||||
if let RelayPoolNotification::Event { relay_url, subscription_id, event } = notification {
|
if let RelayPoolNotification::Event { relay_url: _, subscription_id: _, event } = notification {
|
||||||
let content = event.content.clone();
|
let content = event.content.clone();
|
||||||
tx.send(content).await.unwrap();
|
if tx.send(content).await.is_err() {
|
||||||
|
eprintln!("Failed to send message");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue