wip: update nostr sdk
Some checks failed
Rust / build (ubuntu-latest, stable) (push) Failing after 1m35s
Some checks failed
Rust / build (ubuntu-latest, stable) (push) Failing after 1m35s
This commit is contained in:
63
Cargo.lock
generated
63
Cargo.lock
generated
@@ -1264,7 +1264,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collections"
|
name = "collections"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"rustc-hash 2.1.1",
|
"rustc-hash 2.1.1",
|
||||||
@@ -1709,7 +1709,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_refineable"
|
name = "derive_refineable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -2632,7 +2632,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui"
|
name = "gpui"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"as-raw-xcb-connection",
|
"as-raw-xcb-connection",
|
||||||
@@ -2734,7 +2734,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_macros"
|
name = "gpui_macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -2745,7 +2745,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_tokio"
|
name = "gpui_tokio"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"gpui",
|
"gpui",
|
||||||
@@ -2967,7 +2967,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "http_client"
|
name = "http_client"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
@@ -2992,7 +2992,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "http_client_tls"
|
name = "http_client_tls"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-platform-verifier",
|
"rustls-platform-verifier",
|
||||||
@@ -3742,7 +3742,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "media"
|
name = "media"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bindgen",
|
"bindgen",
|
||||||
@@ -3982,7 +3982,7 @@ checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr"
|
name = "nostr"
|
||||||
version = "0.44.1"
|
version = "0.44.1"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#c25727493b52af561ed6b6aca43cf866ef7aeb16"
|
source = "git+https://github.com/rust-nostr/nostr#8b6a6d797f0a7b7fd9147860b3cb00bdd6fc92cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"base64",
|
"base64",
|
||||||
@@ -4007,7 +4007,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-connect"
|
name = "nostr-connect"
|
||||||
version = "0.44.0"
|
version = "0.44.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#c25727493b52af561ed6b6aca43cf866ef7aeb16"
|
source = "git+https://github.com/rust-nostr/nostr#8b6a6d797f0a7b7fd9147860b3cb00bdd6fc92cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -4020,7 +4020,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-database"
|
name = "nostr-database"
|
||||||
version = "0.44.0"
|
version = "0.44.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#c25727493b52af561ed6b6aca43cf866ef7aeb16"
|
source = "git+https://github.com/rust-nostr/nostr#8b6a6d797f0a7b7fd9147860b3cb00bdd6fc92cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"btreecap",
|
"btreecap",
|
||||||
"flatbuffers",
|
"flatbuffers",
|
||||||
@@ -4032,15 +4032,27 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-gossip"
|
name = "nostr-gossip"
|
||||||
version = "0.44.0"
|
version = "0.44.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#c25727493b52af561ed6b6aca43cf866ef7aeb16"
|
source = "git+https://github.com/rust-nostr/nostr#8b6a6d797f0a7b7fd9147860b3cb00bdd6fc92cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nostr",
|
"nostr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nostr-gossip-memory"
|
||||||
|
version = "0.44.0"
|
||||||
|
source = "git+https://github.com/rust-nostr/nostr#8b6a6d797f0a7b7fd9147860b3cb00bdd6fc92cd"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"lru",
|
||||||
|
"nostr",
|
||||||
|
"nostr-gossip",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-lmdb"
|
name = "nostr-lmdb"
|
||||||
version = "0.44.0"
|
version = "0.44.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#c25727493b52af561ed6b6aca43cf866ef7aeb16"
|
source = "git+https://github.com/rust-nostr/nostr#8b6a6d797f0a7b7fd9147860b3cb00bdd6fc92cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"flume",
|
"flume",
|
||||||
@@ -4054,7 +4066,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-sdk"
|
name = "nostr-sdk"
|
||||||
version = "0.44.1"
|
version = "0.44.1"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#c25727493b52af561ed6b6aca43cf866ef7aeb16"
|
source = "git+https://github.com/rust-nostr/nostr#8b6a6d797f0a7b7fd9147860b3cb00bdd6fc92cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"async-wsocket",
|
"async-wsocket",
|
||||||
@@ -4588,7 +4600,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "perf"
|
name = "perf"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"collections",
|
"collections",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -5237,7 +5249,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "refineable"
|
name = "refineable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_refineable",
|
"derive_refineable",
|
||||||
]
|
]
|
||||||
@@ -5336,7 +5348,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest_client"
|
name = "reqwest_client"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -5391,7 +5403,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "rope"
|
name = "rope"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"log",
|
"log",
|
||||||
@@ -5670,7 +5682,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "scheduler"
|
name = "scheduler"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-task",
|
"async-task",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
@@ -6189,6 +6201,7 @@ dependencies = [
|
|||||||
"gpui_tokio",
|
"gpui_tokio",
|
||||||
"log",
|
"log",
|
||||||
"nostr-connect",
|
"nostr-connect",
|
||||||
|
"nostr-gossip-memory",
|
||||||
"nostr-lmdb",
|
"nostr-lmdb",
|
||||||
"nostr-sdk",
|
"nostr-sdk",
|
||||||
"petname",
|
"petname",
|
||||||
@@ -6273,7 +6286,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "sum_tree"
|
name = "sum_tree"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"log",
|
"log",
|
||||||
@@ -7258,7 +7271,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "util"
|
name = "util"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-fs",
|
"async-fs",
|
||||||
@@ -7296,7 +7309,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "util_macros"
|
name = "util_macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"perf",
|
"perf",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -8772,7 +8785,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "zlog"
|
name = "zlog"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@@ -8789,7 +8802,7 @@ checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ztracing"
|
name = "ztracing"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@@ -8800,7 +8813,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ztracing_macro"
|
name = "ztracing_macro"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#555c002499a4676bac4c2e4aae2fa11f0a2bbddd"
|
source = "git+https://github.com/zed-industries/zed#49c777779a63a0f44abec3ba7bd490c8b1552667"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-core"
|
name = "zune-core"
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ reqwest_client = { git = "https://github.com/zed-industries/zed" }
|
|||||||
nostr-lmdb = { git = "https://github.com/rust-nostr/nostr" }
|
nostr-lmdb = { git = "https://github.com/rust-nostr/nostr" }
|
||||||
nostr-connect = { git = "https://github.com/rust-nostr/nostr" }
|
nostr-connect = { git = "https://github.com/rust-nostr/nostr" }
|
||||||
nostr-sdk = { git = "https://github.com/rust-nostr/nostr", features = [ "nip96", "nip59", "nip49", "nip44" ] }
|
nostr-sdk = { git = "https://github.com/rust-nostr/nostr", features = [ "nip96", "nip59", "nip49", "nip44" ] }
|
||||||
|
nostr-gossip-memory = { git = "https://github.com/rust-nostr/nostr" }
|
||||||
|
|
||||||
# Others
|
# Others
|
||||||
anyhow = "1.0.44"
|
anyhow = "1.0.44"
|
||||||
|
|||||||
@@ -243,12 +243,7 @@ impl AutoUpdater {
|
|||||||
.author(app_pubkey)
|
.author(app_pubkey)
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
if let Err(e) = client
|
// TODO
|
||||||
.subscribe_to(BOOTSTRAP_RELAYS, filter, Some(opts))
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
log::error!("Failed to subscribe to updates: {e}");
|
|
||||||
};
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,10 +280,7 @@ impl AutoUpdater {
|
|||||||
.author(app_pubkey)
|
.author(app_pubkey)
|
||||||
.ids(ids.clone());
|
.ids(ids.clone());
|
||||||
|
|
||||||
// Get all files for this release
|
// TODO
|
||||||
client
|
|
||||||
.subscribe_to(BOOTSTRAP_RELAYS, filter, Some(opts))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(ids)
|
Ok(ids)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -195,8 +195,8 @@ impl ChatRegistry {
|
|||||||
let mut notifications = client.notifications();
|
let mut notifications = client.notifications();
|
||||||
let mut processed_events = HashSet::new();
|
let mut processed_events = HashSet::new();
|
||||||
|
|
||||||
while let Ok(notification) = notifications.recv().await {
|
while let Some(notification) = notifications.next().await {
|
||||||
let RelayPoolNotification::Message { message, .. } = notification else {
|
let ClientNotification::Message { message, .. } = notification else {
|
||||||
// Skip non-message notifications
|
// Skip non-message notifications
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
@@ -432,7 +432,7 @@ impl ChatRegistry {
|
|||||||
let client = nostr.read(cx).client();
|
let client = nostr.read(cx).client();
|
||||||
|
|
||||||
cx.background_spawn(async move {
|
cx.background_spawn(async move {
|
||||||
let signer = client.signer().await?;
|
let signer = client.signer().context("Signer not found")?;
|
||||||
let public_key = signer.get_public_key().await?;
|
let public_key = signer.get_public_key().await?;
|
||||||
let contacts = client.database().contacts_public_keys(public_key).await?;
|
let contacts = client.database().contacts_public_keys(public_key).await?;
|
||||||
|
|
||||||
@@ -597,8 +597,8 @@ impl ChatRegistry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Try with the user's signer
|
// Try with the user's signer
|
||||||
let user_signer = client.signer().await?;
|
let user_signer = client.signer().context("Signer not found")?;
|
||||||
let unwrapped = UnwrappedGift::from_gift_wrap(&user_signer, gift_wrap).await?;
|
let unwrapped = UnwrappedGift::from_gift_wrap(user_signer, gift_wrap).await?;
|
||||||
|
|
||||||
Ok(unwrapped)
|
Ok(unwrapped)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet};
|
|||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::{Context as AnyhowContext, Error};
|
||||||
use common::EventUtils;
|
use common::EventUtils;
|
||||||
use gpui::{App, AppContext, Context, EventEmitter, SharedString, Task};
|
use gpui::{App, AppContext, Context, EventEmitter, SharedString, Task};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@@ -325,7 +325,7 @@ impl Room {
|
|||||||
let id = SubscriptionId::new(format!("room-{}", self.id));
|
let id = SubscriptionId::new(format!("room-{}", self.id));
|
||||||
|
|
||||||
cx.background_spawn(async move {
|
cx.background_spawn(async move {
|
||||||
let signer = client.signer().await?;
|
let signer = client.signer().context("Signer not found")?;
|
||||||
let public_key = signer.get_public_key().await?;
|
let public_key = signer.get_public_key().await?;
|
||||||
|
|
||||||
// Subscription options
|
// Subscription options
|
||||||
@@ -343,7 +343,9 @@ impl Room {
|
|||||||
|
|
||||||
// Subscribe to get member's gossip relays
|
// Subscribe to get member's gossip relays
|
||||||
client
|
client
|
||||||
.subscribe_with_id(id.clone(), filter, Some(opts))
|
.subscribe(filter)
|
||||||
|
.close_on(opts)
|
||||||
|
.with_id(id.clone())
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,7 +460,7 @@ impl Room {
|
|||||||
let task = self.members_with_relays(cx);
|
let task = self.members_with_relays(cx);
|
||||||
|
|
||||||
cx.background_spawn(async move {
|
cx.background_spawn(async move {
|
||||||
let signer = client.signer().await?;
|
let signer = client.signer().context("Signer not found")?;
|
||||||
let current_user_relays = current_user_relays.await;
|
let current_user_relays = current_user_relays.await;
|
||||||
let mut members = task.await;
|
let mut members = task.await;
|
||||||
|
|
||||||
@@ -484,10 +486,10 @@ impl Room {
|
|||||||
|
|
||||||
// Construct the gift wrap event
|
// Construct the gift wrap event
|
||||||
let event =
|
let event =
|
||||||
EventBuilder::gift_wrap(&signer, &receiver, rumor.clone(), vec![]).await?;
|
EventBuilder::gift_wrap(signer, &receiver, rumor.clone(), vec![]).await?;
|
||||||
|
|
||||||
// Send the gift wrap event to the messaging relays
|
// Send the gift wrap event to the messaging relays
|
||||||
match client.send_event_to(relays, &event).await {
|
match client.send_event(&event).to(&relays).await {
|
||||||
Ok(output) => {
|
Ok(output) => {
|
||||||
let id = output.id().to_owned();
|
let id = output.id().to_owned();
|
||||||
let auth = output.failed.iter().any(|(_, s)| s.starts_with("auth-"));
|
let auth = output.failed.iter().any(|(_, s)| s.starts_with("auth-"));
|
||||||
@@ -525,7 +527,7 @@ impl Room {
|
|||||||
|
|
||||||
// Construct the gift-wrapped event
|
// Construct the gift-wrapped event
|
||||||
let event =
|
let event =
|
||||||
EventBuilder::gift_wrap(&signer, ¤t_user, rumor.clone(), vec![]).await?;
|
EventBuilder::gift_wrap(signer, ¤t_user, rumor.clone(), vec![]).await?;
|
||||||
|
|
||||||
// Only send a backup message to current user if sent successfully to others
|
// Only send a backup message to current user if sent successfully to others
|
||||||
if reports.iter().all(|r| r.is_sent_success()) {
|
if reports.iter().all(|r| r.is_sent_success()) {
|
||||||
@@ -580,7 +582,7 @@ impl Room {
|
|||||||
|
|
||||||
if let Some(event) = client.database().event_by_id(id).await? {
|
if let Some(event) = client.database().event_by_id(id).await? {
|
||||||
for url in urls.into_iter() {
|
for url in urls.into_iter() {
|
||||||
let relay = client.pool().relay(url).await?;
|
let relay = client.relay(url).await?.context("Relay not found")?;
|
||||||
let id = relay.send_event(&event).await?;
|
let id = relay.send_event(&event).await?;
|
||||||
|
|
||||||
let resent: Output<EventId> = Output {
|
let resent: Output<EventId> = Output {
|
||||||
|
|||||||
@@ -72,11 +72,10 @@ pub async fn nip96_upload(
|
|||||||
let json: Value = res.json().await?;
|
let json: Value = res.json().await?;
|
||||||
|
|
||||||
let config = nip96::ServerConfig::from_json(json.to_string())?;
|
let config = nip96::ServerConfig::from_json(json.to_string())?;
|
||||||
let signer = if client.has_signer().await {
|
let signer = client
|
||||||
client.signer().await?
|
.signer()
|
||||||
} else {
|
.cloned()
|
||||||
Keys::generate().into_nostr_signer()
|
.unwrap_or(Keys::generate().into_nostr_signer());
|
||||||
};
|
|
||||||
|
|
||||||
let url = upload(&signer, &config, file, None).await?;
|
let url = upload(&signer, &config, file, None).await?;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::{Context as AnyhowContext, Error};
|
||||||
use common::{shorten_pubkey, RenderedProfile, RenderedTimestamp, BOOTSTRAP_RELAYS};
|
use common::{shorten_pubkey, RenderedProfile, RenderedTimestamp, BOOTSTRAP_RELAYS};
|
||||||
use gpui::prelude::FluentBuilder;
|
use gpui::prelude::FluentBuilder;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
@@ -45,7 +46,7 @@ impl Screening {
|
|||||||
let contact_check: Task<Result<(bool, Vec<Profile>), Error>> = cx.background_spawn({
|
let contact_check: Task<Result<(bool, Vec<Profile>), Error>> = cx.background_spawn({
|
||||||
let client = nostr.read(cx).client();
|
let client = nostr.read(cx).client();
|
||||||
async move {
|
async move {
|
||||||
let signer = client.signer().await?;
|
let signer = client.signer().context("Signer not found")?;
|
||||||
let signer_pubkey = signer.get_public_key().await?;
|
let signer_pubkey = signer.get_public_key().await?;
|
||||||
|
|
||||||
// Check if user is in contact list
|
// Check if user is in contact list
|
||||||
@@ -74,8 +75,15 @@ impl Screening {
|
|||||||
let filter = Filter::new().author(public_key).limit(1);
|
let filter = Filter::new().author(public_key).limit(1);
|
||||||
let mut activity: Option<Timestamp> = None;
|
let mut activity: Option<Timestamp> = None;
|
||||||
|
|
||||||
|
// Construct target for subscription
|
||||||
|
let target = BOOTSTRAP_RELAYS
|
||||||
|
.into_iter()
|
||||||
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
if let Ok(mut stream) = client
|
if let Ok(mut stream) = client
|
||||||
.stream_events_from(BOOTSTRAP_RELAYS, filter, Duration::from_secs(2))
|
.stream_events(target)
|
||||||
|
.timeout(Duration::from_secs(2))
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
while let Some((_url, event)) = stream.next().await {
|
while let Some((_url, event)) = stream.next().await {
|
||||||
@@ -162,12 +170,12 @@ impl Screening {
|
|||||||
let public_key = self.profile.public_key();
|
let public_key = self.profile.public_key();
|
||||||
|
|
||||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||||
let signer = client.signer().await?;
|
|
||||||
let tag = Tag::public_key_report(public_key, Report::Impersonation);
|
let tag = Tag::public_key_report(public_key, Report::Impersonation);
|
||||||
let event = EventBuilder::report(vec![tag], "").sign(&signer).await?;
|
let builder = EventBuilder::report(vec![tag], "");
|
||||||
|
let event = client.sign_event_builder(builder).await?;
|
||||||
|
|
||||||
// Send the report to the public relays
|
// Send the report to the public relays
|
||||||
client.send_event_to(BOOTSTRAP_RELAYS, &event).await?;
|
client.send_event(&event).to(BOOTSTRAP_RELAYS).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::{anyhow, Error};
|
use anyhow::{anyhow, Context as AnyhowContext, Error};
|
||||||
use dock::panel::{Panel, PanelEvent};
|
use dock::panel::{Panel, PanelEvent};
|
||||||
use gpui::prelude::FluentBuilder;
|
use gpui::prelude::FluentBuilder;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
@@ -89,7 +89,7 @@ impl MessagingRelayPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn load(client: &Client) -> Result<Vec<RelayUrl>, Error> {
|
async fn load(client: &Client) -> Result<Vec<RelayUrl>, Error> {
|
||||||
let signer = client.signer().await?;
|
let signer = client.signer().context("Signer not found")?;
|
||||||
let public_key = signer.get_public_key().await?;
|
let public_key = signer.get_public_key().await?;
|
||||||
|
|
||||||
let filter = Filter::new()
|
let filter = Filter::new()
|
||||||
@@ -162,20 +162,17 @@ impl MessagingRelayPanel {
|
|||||||
|
|
||||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||||
let urls = write_relays.await;
|
let urls = write_relays.await;
|
||||||
let signer = client.signer().await?;
|
|
||||||
|
|
||||||
let tags: Vec<Tag> = relays
|
let tags: Vec<Tag> = relays
|
||||||
.iter()
|
.iter()
|
||||||
.map(|relay| Tag::relay(relay.clone()))
|
.map(|relay| Tag::relay(relay.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let event = EventBuilder::new(Kind::InboxRelays, "")
|
let builder = EventBuilder::new(Kind::InboxRelays, "").tags(tags);
|
||||||
.tags(tags)
|
let event = client.sign_event_builder(builder).await?;
|
||||||
.sign(&signer)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Set messaging relays
|
// Set messaging relays
|
||||||
client.send_event_to(urls, &event).await?;
|
client.send_event(&event).to(urls).await?;
|
||||||
|
|
||||||
// Connect to messaging relays
|
// Connect to messaging relays
|
||||||
for relay in relays.iter() {
|
for relay in relays.iter() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::{anyhow, Error};
|
use anyhow::{anyhow, Context as AnyhowContext, Error};
|
||||||
use common::BOOTSTRAP_RELAYS;
|
use common::BOOTSTRAP_RELAYS;
|
||||||
use dock::panel::{Panel, PanelEvent};
|
use dock::panel::{Panel, PanelEvent};
|
||||||
use gpui::prelude::FluentBuilder;
|
use gpui::prelude::FluentBuilder;
|
||||||
@@ -96,7 +96,7 @@ impl RelayListPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn load(client: &Client) -> Result<Vec<(RelayUrl, Option<RelayMetadata>)>, Error> {
|
async fn load(client: &Client) -> Result<Vec<(RelayUrl, Option<RelayMetadata>)>, Error> {
|
||||||
let signer = client.signer().await?;
|
let signer = client.signer().context("Signer not found")?;
|
||||||
let public_key = signer.get_public_key().await?;
|
let public_key = signer.get_public_key().await?;
|
||||||
|
|
||||||
let filter = Filter::new()
|
let filter = Filter::new()
|
||||||
@@ -167,11 +167,11 @@ impl RelayListPanel {
|
|||||||
let relays = self.relays.clone();
|
let relays = self.relays.clone();
|
||||||
|
|
||||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||||
let signer = client.signer().await?;
|
let builder = EventBuilder::relay_list(relays);
|
||||||
let event = EventBuilder::relay_list(relays).sign(&signer).await?;
|
let event = client.sign_event_builder(builder).await?;
|
||||||
|
|
||||||
// Set relay list for current user
|
// Set relay list for current user
|
||||||
client.send_event_to(BOOTSTRAP_RELAYS, &event).await?;
|
client.send_event(&event).to(BOOTSTRAP_RELAYS).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -130,8 +130,8 @@ impl DeviceRegistry {
|
|||||||
let mut notifications = client.notifications();
|
let mut notifications = client.notifications();
|
||||||
let mut processed_events = HashSet::new();
|
let mut processed_events = HashSet::new();
|
||||||
|
|
||||||
while let Ok(notification) = notifications.recv().await {
|
while let Some(notification) = notifications.next().await {
|
||||||
if let RelayPoolNotification::Message {
|
if let ClientNotification::Message {
|
||||||
message: RelayMessage::Event { event, .. },
|
message: RelayMessage::Event { event, .. },
|
||||||
..
|
..
|
||||||
} = notification
|
} = notification
|
||||||
@@ -162,7 +162,7 @@ impl DeviceRegistry {
|
|||||||
|
|
||||||
/// Verify the author of an event
|
/// Verify the author of an event
|
||||||
async fn verify_author(client: &Client, event: &Event) -> bool {
|
async fn verify_author(client: &Client, event: &Event) -> bool {
|
||||||
if let Ok(signer) = client.signer().await {
|
if let Some(signer) = client.signer() {
|
||||||
if let Ok(public_key) = signer.get_public_key().await {
|
if let Ok(public_key) = signer.get_public_key().await {
|
||||||
return public_key == event.pubkey;
|
return public_key == event.pubkey;
|
||||||
}
|
}
|
||||||
@@ -172,7 +172,7 @@ impl DeviceRegistry {
|
|||||||
|
|
||||||
/// Encrypt and store device keys in the local database.
|
/// Encrypt and store device keys in the local database.
|
||||||
async fn set_keys(client: &Client, secret: &str) -> Result<(), Error> {
|
async fn set_keys(client: &Client, secret: &str) -> Result<(), Error> {
|
||||||
let signer = client.signer().await?;
|
let signer = client.signer().context("Signer not found")?;
|
||||||
let public_key = signer.get_public_key().await?;
|
let public_key = signer.get_public_key().await?;
|
||||||
|
|
||||||
// Encrypt the value
|
// Encrypt the value
|
||||||
@@ -193,7 +193,7 @@ impl DeviceRegistry {
|
|||||||
|
|
||||||
/// Get device keys from the local database.
|
/// Get device keys from the local database.
|
||||||
async fn get_keys(client: &Client) -> Result<Keys, Error> {
|
async fn get_keys(client: &Client) -> Result<Keys, Error> {
|
||||||
let signer = client.signer().await?;
|
let signer = client.signer().context("Signer not found")?;
|
||||||
let public_key = signer.get_public_key().await?;
|
let public_key = signer.get_public_key().await?;
|
||||||
|
|
||||||
let filter = Filter::new()
|
let filter = Filter::new()
|
||||||
@@ -278,10 +278,13 @@ impl DeviceRegistry {
|
|||||||
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(pkey);
|
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(pkey);
|
||||||
let id = SubscriptionId::new(DEVICE_GIFTWRAP);
|
let id = SubscriptionId::new(DEVICE_GIFTWRAP);
|
||||||
|
|
||||||
if let Err(e) = client
|
// Construct target for subscription
|
||||||
.subscribe_with_id_to(&urls, id, vec![filter], None)
|
let target = urls
|
||||||
.await
|
.iter()
|
||||||
{
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
if let Err(e) = client.subscribe(target).with_id(id).await {
|
||||||
log::error!("Failed to subscribe to gift wrap events: {e}");
|
log::error!("Failed to subscribe to gift wrap events: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -291,10 +294,13 @@ impl DeviceRegistry {
|
|||||||
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key);
|
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key);
|
||||||
let id = SubscriptionId::new(USER_GIFTWRAP);
|
let id = SubscriptionId::new(USER_GIFTWRAP);
|
||||||
|
|
||||||
if let Err(e) = client
|
// Construct target for subscription
|
||||||
.subscribe_with_id_to(urls, id, vec![filter], None)
|
let target = urls
|
||||||
.await
|
.iter()
|
||||||
{
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
if let Err(e) = client.subscribe(target).with_id(id).await {
|
||||||
log::error!("Failed to subscribe to gift wrap events: {e}");
|
log::error!("Failed to subscribe to gift wrap events: {e}");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -318,8 +324,15 @@ impl DeviceRegistry {
|
|||||||
.author(public_key)
|
.author(public_key)
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
|
// Construct target for subscription
|
||||||
|
let target = urls
|
||||||
|
.iter()
|
||||||
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
let mut stream = client
|
let mut stream = client
|
||||||
.stream_events_from(&urls, vec![filter], Duration::from_secs(TIMEOUT))
|
.stream_events(target)
|
||||||
|
.timeout(Duration::from_secs(TIMEOUT))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
while let Some((_url, res)) = stream.next().await {
|
while let Some((_url, res)) = stream.next().await {
|
||||||
@@ -368,20 +381,17 @@ impl DeviceRegistry {
|
|||||||
let n = keys.public_key();
|
let n = keys.public_key();
|
||||||
|
|
||||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||||
let signer = client.signer().await?;
|
|
||||||
let urls = write_relays.await;
|
let urls = write_relays.await;
|
||||||
|
|
||||||
// Construct an announcement event
|
// Construct an announcement event
|
||||||
let event = EventBuilder::new(Kind::Custom(10044), "")
|
let builder = EventBuilder::new(Kind::Custom(10044), "").tags(vec![
|
||||||
.tags(vec![
|
|
||||||
Tag::custom(TagKind::custom("n"), vec![n]),
|
Tag::custom(TagKind::custom("n"), vec![n]),
|
||||||
Tag::client(app_name()),
|
Tag::client(app_name()),
|
||||||
])
|
]);
|
||||||
.sign(&signer)
|
let event = client.sign_event_builder(builder).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Publish announcement
|
// Publish announcement
|
||||||
client.send_event_to(&urls, &event).await?;
|
client.send_event(&event).to(urls).await?;
|
||||||
|
|
||||||
// Save device keys to the database
|
// Save device keys to the database
|
||||||
Self::set_keys(&client, &secret).await?;
|
Self::set_keys(&client, &secret).await?;
|
||||||
@@ -461,8 +471,14 @@ impl DeviceRegistry {
|
|||||||
.author(public_key)
|
.author(public_key)
|
||||||
.since(Timestamp::now());
|
.since(Timestamp::now());
|
||||||
|
|
||||||
|
// Construct target for subscription
|
||||||
|
let target = urls
|
||||||
|
.iter()
|
||||||
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
// Subscribe to the device key requests on user's write relays
|
// Subscribe to the device key requests on user's write relays
|
||||||
client.subscribe_to(&urls, vec![filter], None).await?;
|
client.subscribe(target).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
@@ -487,8 +503,14 @@ impl DeviceRegistry {
|
|||||||
.author(public_key)
|
.author(public_key)
|
||||||
.since(Timestamp::now());
|
.since(Timestamp::now());
|
||||||
|
|
||||||
|
// Construct target for subscription
|
||||||
|
let target = urls
|
||||||
|
.iter()
|
||||||
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
// Subscribe to the device key requests on user's write relays
|
// Subscribe to the device key requests on user's write relays
|
||||||
client.subscribe_to(&urls, vec![filter], None).await?;
|
client.subscribe(target).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
@@ -508,7 +530,7 @@ impl DeviceRegistry {
|
|||||||
let app_pubkey = app_keys.public_key();
|
let app_pubkey = app_keys.public_key();
|
||||||
|
|
||||||
let task: Task<Result<Option<Keys>, Error>> = cx.background_spawn(async move {
|
let task: Task<Result<Option<Keys>, Error>> = cx.background_spawn(async move {
|
||||||
let signer = client.signer().await?;
|
let signer = client.signer().context("Signer not found")?;
|
||||||
let public_key = signer.get_public_key().await?;
|
let public_key = signer.get_public_key().await?;
|
||||||
|
|
||||||
let filter = Filter::new()
|
let filter = Filter::new()
|
||||||
@@ -538,16 +560,14 @@ impl DeviceRegistry {
|
|||||||
let urls = write_relays.await;
|
let urls = write_relays.await;
|
||||||
|
|
||||||
// Construct an event for device key request
|
// Construct an event for device key request
|
||||||
let event = EventBuilder::new(Kind::Custom(4454), "")
|
let builder = EventBuilder::new(Kind::Custom(4454), "").tags(vec![
|
||||||
.tags(vec![
|
|
||||||
Tag::client(app_name()),
|
Tag::client(app_name()),
|
||||||
Tag::custom(TagKind::custom("P"), vec![app_pubkey]),
|
Tag::custom(TagKind::custom("P"), vec![app_pubkey]),
|
||||||
])
|
]);
|
||||||
.sign(&signer)
|
let event = client.sign_event_builder(builder).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Send the event to write relays
|
// Send the event to write relays
|
||||||
client.send_event_to(&urls, &event).await?;
|
client.send_event(&event).to(urls).await?;
|
||||||
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
@@ -625,7 +645,7 @@ impl DeviceRegistry {
|
|||||||
|
|
||||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||||
let urls = write_relays.await;
|
let urls = write_relays.await;
|
||||||
let signer = client.signer().await?;
|
let signer = client.signer().context("Signer not found")?;
|
||||||
|
|
||||||
// Get device keys
|
// Get device keys
|
||||||
let keys = Self::get_keys(&client).await?;
|
let keys = Self::get_keys(&client).await?;
|
||||||
@@ -646,16 +666,14 @@ impl DeviceRegistry {
|
|||||||
//
|
//
|
||||||
// P tag: the current device's public key
|
// P tag: the current device's public key
|
||||||
// p tag: the requester's public key
|
// p tag: the requester's public key
|
||||||
let event = EventBuilder::new(Kind::Custom(4455), payload)
|
let builder = EventBuilder::new(Kind::Custom(4455), payload).tags(vec![
|
||||||
.tags(vec![
|
|
||||||
Tag::custom(TagKind::custom("P"), vec![keys.public_key()]),
|
Tag::custom(TagKind::custom("P"), vec![keys.public_key()]),
|
||||||
Tag::public_key(target),
|
Tag::public_key(target),
|
||||||
])
|
]);
|
||||||
.sign(&signer)
|
let event = client.sign_event_builder(builder).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Send the response event to the user's relay list
|
// Send the response event to the user's relay list
|
||||||
client.send_event_to(&urls, &event).await?;
|
client.send_event(&event).to(urls).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -139,20 +139,14 @@ impl PersonRegistry {
|
|||||||
/// Handle nostr notifications
|
/// Handle nostr notifications
|
||||||
async fn handle_notifications(client: &Client, tx: &flume::Sender<Dispatch>) {
|
async fn handle_notifications(client: &Client, tx: &flume::Sender<Dispatch>) {
|
||||||
let mut notifications = client.notifications();
|
let mut notifications = client.notifications();
|
||||||
let mut processed_events = HashSet::new();
|
|
||||||
|
|
||||||
while let Ok(notification) = notifications.recv().await {
|
while let Some(notification) = notifications.next().await {
|
||||||
let RelayPoolNotification::Message { message, .. } = notification else {
|
let ClientNotification::Message { message, .. } = notification else {
|
||||||
// Skip if the notification is not a message
|
// Skip if the notification is not a message
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let RelayMessage::Event { event, .. } = message {
|
if let RelayMessage::Event { event, .. } = message {
|
||||||
if !processed_events.insert(event.id) {
|
|
||||||
// Skip if the event has already been processed
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
match event.kind {
|
match event.kind {
|
||||||
Kind::Metadata => {
|
Kind::Metadata => {
|
||||||
let metadata = Metadata::from_json(&event.content).unwrap_or_default();
|
let metadata = Metadata::from_json(&event.content).unwrap_or_default();
|
||||||
@@ -230,9 +224,13 @@ impl PersonRegistry {
|
|||||||
.authors(authors)
|
.authors(authors)
|
||||||
.limit(limit);
|
.limit(limit);
|
||||||
|
|
||||||
client
|
// Construct target for subscription
|
||||||
.subscribe_to(BOOTSTRAP_RELAYS, filter, Some(opts))
|
let target = BOOTSTRAP_RELAYS
|
||||||
.await?;
|
.into_iter()
|
||||||
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
client.subscribe(target).close_on(opts).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use std::collections::HashSet;
|
|||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use anyhow::{anyhow, Error};
|
use anyhow::{anyhow, Context as AnyhowContext, Error};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
App, AppContext, Context, Entity, Global, IntoElement, ParentElement, SharedString, Styled,
|
App, AppContext, Context, Entity, Global, IntoElement, ParentElement, SharedString, Styled,
|
||||||
Subscription, Task, Window,
|
Subscription, Task, Window,
|
||||||
@@ -137,8 +137,8 @@ impl RelayAuth {
|
|||||||
async fn handle_notifications(client: &Client, tx: &flume::Sender<AuthRequest>) {
|
async fn handle_notifications(client: &Client, tx: &flume::Sender<AuthRequest>) {
|
||||||
let mut notifications = client.notifications();
|
let mut notifications = client.notifications();
|
||||||
|
|
||||||
while let Ok(notification) = notifications.recv().await {
|
while let Some(notification) = notifications.next().await {
|
||||||
if let RelayPoolNotification::Message {
|
if let ClientNotification::Message {
|
||||||
message: RelayMessage::Auth { challenge },
|
message: RelayMessage::Auth { challenge },
|
||||||
relay_url,
|
relay_url,
|
||||||
} = notification
|
} = notification
|
||||||
@@ -184,34 +184,33 @@ impl RelayAuth {
|
|||||||
let url_clone = url.clone();
|
let url_clone = url.clone();
|
||||||
|
|
||||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||||
let signer = client.signer().await?;
|
|
||||||
|
|
||||||
// Construct event
|
// Construct event
|
||||||
let event: Event = EventBuilder::auth(challenge_clone, url_clone.clone())
|
let builder = EventBuilder::auth(challenge_clone, url_clone.clone());
|
||||||
.sign(&signer)
|
let event = client.sign_event_builder(builder).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Get the event ID
|
// Get the event ID
|
||||||
let id = event.id;
|
let id = event.id;
|
||||||
|
|
||||||
// Get the relay
|
// Get the relay
|
||||||
let relay = client.pool().relay(url_clone).await?;
|
let relay = client.relay(url_clone).await?.context("Relay not found")?;
|
||||||
let relay_url = relay.url();
|
let relay_url = relay.url();
|
||||||
|
|
||||||
// Subscribe to notifications
|
// Subscribe to notifications
|
||||||
let mut notifications = relay.notifications();
|
let mut notifications = relay.notifications();
|
||||||
|
|
||||||
// Send the AUTH message
|
// Send the AUTH message
|
||||||
relay.send_msg(ClientMessage::Auth(Cow::Borrowed(&event)))?;
|
relay
|
||||||
|
.send_msg(ClientMessage::Auth(Cow::Borrowed(&event)))
|
||||||
|
.await?;
|
||||||
|
|
||||||
while let Ok(notification) = notifications.recv().await {
|
while let Some(notification) = notifications.next().await {
|
||||||
match notification {
|
match notification {
|
||||||
RelayNotification::Message {
|
RelayNotification::Message {
|
||||||
message: RelayMessage::Ok { event_id, .. },
|
message: RelayMessage::Ok { event_id, .. },
|
||||||
} => {
|
} => {
|
||||||
if id == event_id {
|
if id == event_id {
|
||||||
// Re-subscribe to previous subscription
|
// Re-subscribe to previous subscription
|
||||||
relay.resubscribe().await?;
|
// relay.resubscribe().await?;
|
||||||
|
|
||||||
// Get all pending events that need to be resent
|
// Get all pending events that need to be resent
|
||||||
let mut tracker = tracker().write().await;
|
let mut tracker = tracker().write().await;
|
||||||
@@ -228,7 +227,6 @@ impl RelayAuth {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
RelayNotification::AuthenticationFailed => break,
|
RelayNotification::AuthenticationFailed => break,
|
||||||
RelayNotification::Shutdown => break,
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ impl AppSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn new(cx: &mut Context<Self>) -> Self {
|
fn new(cx: &mut Context<Self>) -> Self {
|
||||||
let load_settings = Self::get_from_database(false, cx);
|
let load_settings = Self::get_from_database(cx);
|
||||||
|
|
||||||
let mut tasks = smallvec![];
|
let mut tasks = smallvec![];
|
||||||
let mut subscriptions = smallvec![];
|
let mut subscriptions = smallvec![];
|
||||||
@@ -169,12 +169,10 @@ impl AppSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get settings from the database
|
/// Get settings from the database
|
||||||
///
|
fn get_from_database(cx: &App) -> Task<Result<Settings, Error>> {
|
||||||
/// If `current_user` is true, the settings will be retrieved for current user.
|
|
||||||
/// Otherwise, Coop will load the latest settings from the database.
|
|
||||||
fn get_from_database(current_user: bool, cx: &App) -> Task<Result<Settings, Error>> {
|
|
||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
let client = nostr.read(cx).client();
|
let client = nostr.read(cx).client();
|
||||||
|
let current_user = nostr.read(cx).identity().read(cx).public_key;
|
||||||
|
|
||||||
cx.background_spawn(async move {
|
cx.background_spawn(async move {
|
||||||
// Construct a filter to get the latest settings
|
// Construct a filter to get the latest settings
|
||||||
@@ -183,10 +181,7 @@ impl AppSettings {
|
|||||||
.identifier(SETTINGS_IDENTIFIER)
|
.identifier(SETTINGS_IDENTIFIER)
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
if current_user {
|
if let Some(public_key) = current_user {
|
||||||
let signer = client.signer().await?;
|
|
||||||
let public_key = signer.get_public_key().await?;
|
|
||||||
|
|
||||||
// Push author to the filter
|
// Push author to the filter
|
||||||
filter = filter.author(public_key);
|
filter = filter.author(public_key);
|
||||||
}
|
}
|
||||||
@@ -201,7 +196,7 @@ impl AppSettings {
|
|||||||
|
|
||||||
/// Load settings
|
/// Load settings
|
||||||
pub fn load(&mut self, cx: &mut Context<Self>) {
|
pub fn load(&mut self, cx: &mut Context<Self>) {
|
||||||
let task = Self::get_from_database(true, cx);
|
let task = Self::get_from_database(cx);
|
||||||
|
|
||||||
self._tasks.push(
|
self._tasks.push(
|
||||||
// Run task in the background
|
// Run task in the background
|
||||||
@@ -221,18 +216,17 @@ impl AppSettings {
|
|||||||
pub fn save(&mut self, cx: &mut Context<Self>) {
|
pub fn save(&mut self, cx: &mut Context<Self>) {
|
||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
let client = nostr.read(cx).client();
|
let client = nostr.read(cx).client();
|
||||||
|
let public_key = nostr.read(cx).identity().read(cx).public_key();
|
||||||
|
|
||||||
if let Ok(content) = serde_json::to_string(&self.values) {
|
if let Ok(content) = serde_json::to_string(&self.values) {
|
||||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||||
let signer = client.signer().await?;
|
|
||||||
let public_key = signer.get_public_key().await?;
|
|
||||||
|
|
||||||
let event = EventBuilder::new(Kind::ApplicationSpecificData, content)
|
let event = EventBuilder::new(Kind::ApplicationSpecificData, content)
|
||||||
.tag(Tag::identifier(SETTINGS_IDENTIFIER))
|
.tag(Tag::identifier(SETTINGS_IDENTIFIER))
|
||||||
.build(public_key)
|
.build(public_key)
|
||||||
.sign(&Keys::generate())
|
.sign(&Keys::generate())
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
// Save event to the local database without sending to relays
|
||||||
client.database().save_event(&event).await?;
|
client.database().save_event(&event).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ common = { path = "../common" }
|
|||||||
nostr-sdk.workspace = true
|
nostr-sdk.workspace = true
|
||||||
nostr-lmdb.workspace = true
|
nostr-lmdb.workspace = true
|
||||||
nostr-connect.workspace = true
|
nostr-connect.workspace = true
|
||||||
|
nostr-gossip-memory.workspace = true
|
||||||
|
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
gpui_tokio.workspace = true
|
gpui_tokio.workspace = true
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ impl RelayState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Identity
|
/// Identity
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Identity {
|
pub struct Identity {
|
||||||
/// The public key of the account
|
/// Signer's public key
|
||||||
pub public_key: Option<PublicKey>,
|
pub public_key: Option<PublicKey>,
|
||||||
|
|
||||||
/// Whether the identity is owned by the user
|
/// Whether the identity is owned by the user
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::{anyhow, Error};
|
use anyhow::{anyhow, Error};
|
||||||
@@ -14,12 +15,14 @@ mod event;
|
|||||||
mod gossip;
|
mod gossip;
|
||||||
mod identity;
|
mod identity;
|
||||||
mod nip05;
|
mod nip05;
|
||||||
|
mod signer;
|
||||||
|
|
||||||
pub use device::*;
|
pub use device::*;
|
||||||
pub use event::*;
|
pub use event::*;
|
||||||
pub use gossip::*;
|
pub use gossip::*;
|
||||||
pub use identity::*;
|
pub use identity::*;
|
||||||
pub use nip05::*;
|
pub use nip05::*;
|
||||||
|
pub use signer::*;
|
||||||
|
|
||||||
use crate::identity::Identity;
|
use crate::identity::Identity;
|
||||||
|
|
||||||
@@ -68,6 +71,9 @@ pub struct NostrRegistry {
|
|||||||
/// Nostr client
|
/// Nostr client
|
||||||
client: Client,
|
client: Client,
|
||||||
|
|
||||||
|
/// Nostr signer
|
||||||
|
signer: Arc<CoopSigner>,
|
||||||
|
|
||||||
/// App keys
|
/// App keys
|
||||||
///
|
///
|
||||||
/// Used for Nostr Connect and NIP-4e operations
|
/// Used for Nostr Connect and NIP-4e operations
|
||||||
@@ -108,14 +114,6 @@ impl NostrRegistry {
|
|||||||
.install_default()
|
.install_default()
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
// Construct the nostr client options
|
|
||||||
let opts = ClientOptions::new()
|
|
||||||
.automatic_authentication(false)
|
|
||||||
.verify_subscriptions(false)
|
|
||||||
.sleep_when_idle(SleepWhenIdle::Enabled {
|
|
||||||
timeout: Duration::from_secs(600),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Construct the lmdb
|
// Construct the lmdb
|
||||||
let lmdb = cx.foreground_executor().block_on(async move {
|
let lmdb = cx.foreground_executor().block_on(async move {
|
||||||
NostrLmdb::open(config_dir().join("nostr"))
|
NostrLmdb::open(config_dir().join("nostr"))
|
||||||
@@ -123,9 +121,23 @@ impl NostrRegistry {
|
|||||||
.expect("Failed to initialize database")
|
.expect("Failed to initialize database")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Construct the nostr signer
|
||||||
|
let keys = Keys::generate();
|
||||||
|
let signer = Arc::new(CoopSigner::new(keys));
|
||||||
|
|
||||||
// Construct the nostr client
|
// Construct the nostr client
|
||||||
let client = ClientBuilder::default().database(lmdb).opts(opts).build();
|
let client = ClientBuilder::default()
|
||||||
let _ = tracker();
|
.signer(signer.clone())
|
||||||
|
.database(lmdb)
|
||||||
|
.automatic_authentication(false)
|
||||||
|
.verify_subscriptions(false)
|
||||||
|
.sleep_when_idle(SleepWhenIdle::Enabled {
|
||||||
|
timeout: Duration::from_secs(600),
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Construct the event tracker
|
||||||
|
let _tracker = tracker();
|
||||||
|
|
||||||
// Get the app keys
|
// Get the app keys
|
||||||
let app_keys = Self::create_or_init_app_keys().unwrap();
|
let app_keys = Self::create_or_init_app_keys().unwrap();
|
||||||
@@ -135,7 +147,7 @@ impl NostrRegistry {
|
|||||||
let async_gossip = gossip.downgrade();
|
let async_gossip = gossip.downgrade();
|
||||||
|
|
||||||
// Construct the identity entity
|
// Construct the identity entity
|
||||||
let identity = cx.new(|_| Identity::default());
|
let identity = cx.new(|_| Identity::new());
|
||||||
|
|
||||||
// Channel for communication between nostr and gpui
|
// Channel for communication between nostr and gpui
|
||||||
let (tx, rx) = flume::bounded::<Event>(2048);
|
let (tx, rx) = flume::bounded::<Event>(2048);
|
||||||
@@ -207,6 +219,7 @@ impl NostrRegistry {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
client,
|
client,
|
||||||
|
signer,
|
||||||
app_keys,
|
app_keys,
|
||||||
identity,
|
identity,
|
||||||
gossip,
|
gossip,
|
||||||
@@ -239,8 +252,8 @@ impl NostrRegistry {
|
|||||||
let mut notifications = client.notifications();
|
let mut notifications = client.notifications();
|
||||||
let mut processed_events = HashSet::new();
|
let mut processed_events = HashSet::new();
|
||||||
|
|
||||||
while let Ok(notification) = notifications.recv().await {
|
while let Some(notification) = notifications.next().await {
|
||||||
if let RelayPoolNotification::Message { message, relay_url } = notification {
|
if let ClientNotification::Message { message, relay_url } = notification {
|
||||||
match message {
|
match message {
|
||||||
RelayMessage::Event {
|
RelayMessage::Event {
|
||||||
event,
|
event,
|
||||||
@@ -325,9 +338,13 @@ impl NostrRegistry {
|
|||||||
.author(event.pubkey)
|
.author(event.pubkey)
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
client
|
// Construct target for subscription
|
||||||
.subscribe_to(write_relays, vec![inbox, announcement], Some(opts))
|
let target = write_relays
|
||||||
.await?;
|
.into_iter()
|
||||||
|
.map(|relay| (relay, vec![inbox.clone(), announcement.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
client.subscribe(target).close_on(opts).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -433,21 +450,21 @@ impl NostrRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the signer for the nostr client and verify the public key
|
/// Set the signer for the nostr client and verify the public key
|
||||||
pub fn set_signer<T>(&mut self, signer: T, owned: bool, cx: &mut Context<Self>)
|
pub fn set_signer<T>(&mut self, new: T, owned: bool, cx: &mut Context<Self>)
|
||||||
where
|
where
|
||||||
T: NostrSigner + 'static,
|
T: NostrSigner + 'static,
|
||||||
{
|
{
|
||||||
let client = self.client();
|
|
||||||
let identity = self.identity.downgrade();
|
let identity = self.identity.downgrade();
|
||||||
|
let signer = self.signer.clone();
|
||||||
|
|
||||||
// Create a task to update the signer and verify the public key
|
// Create a task to update the signer and verify the public key
|
||||||
let task: Task<Result<PublicKey, Error>> = cx.background_spawn(async move {
|
let task: Task<Result<PublicKey, Error>> = cx.background_spawn(async move {
|
||||||
// Update signer
|
// Update signer
|
||||||
client.set_signer(signer).await;
|
signer.switch(new).await;
|
||||||
|
|
||||||
// Verify signer
|
// Verify signer
|
||||||
let signer = client.signer().await?;
|
|
||||||
let public_key = signer.get_public_key().await?;
|
let public_key = signer.get_public_key().await?;
|
||||||
|
log::info!("test: {public_key:?}");
|
||||||
|
|
||||||
Ok(public_key)
|
Ok(public_key)
|
||||||
});
|
});
|
||||||
@@ -471,31 +488,6 @@ impl NostrRegistry {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unset the current signer
|
|
||||||
pub fn unset_signer(&mut self, cx: &mut Context<Self>) {
|
|
||||||
let client = self.client();
|
|
||||||
let async_identity = self.identity.downgrade();
|
|
||||||
|
|
||||||
self.tasks.push(cx.spawn(async move |_this, cx| {
|
|
||||||
// Unset the signer from nostr client
|
|
||||||
cx.background_executor()
|
|
||||||
.await_on_background(async move {
|
|
||||||
client.unset_signer().await;
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
// Unset the current identity
|
|
||||||
async_identity
|
|
||||||
.update(cx, |this, cx| {
|
|
||||||
this.unset_public_key();
|
|
||||||
cx.notify();
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get relay list for current user
|
// Get relay list for current user
|
||||||
fn get_relay_list(&mut self, cx: &mut Context<Self>) {
|
fn get_relay_list(&mut self, cx: &mut Context<Self>) {
|
||||||
let client = self.client();
|
let client = self.client();
|
||||||
@@ -508,8 +500,15 @@ impl NostrRegistry {
|
|||||||
.author(public_key)
|
.author(public_key)
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
|
// Construct targets for subscription
|
||||||
|
let target = BOOTSTRAP_RELAYS
|
||||||
|
.into_iter()
|
||||||
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
let mut stream = client
|
let mut stream = client
|
||||||
.stream_events_from(BOOTSTRAP_RELAYS, vec![filter], Duration::from_secs(TIMEOUT))
|
.stream_events(target)
|
||||||
|
.timeout(Duration::from_secs(TIMEOUT))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
while let Some((_url, res)) = stream.next().await {
|
while let Some((_url, res)) = stream.next().await {
|
||||||
@@ -523,10 +522,14 @@ impl NostrRegistry {
|
|||||||
.author(public_key)
|
.author(public_key)
|
||||||
.since(Timestamp::now());
|
.since(Timestamp::now());
|
||||||
|
|
||||||
|
// Construct targets for subscription
|
||||||
|
let target = BOOTSTRAP_RELAYS
|
||||||
|
.into_iter()
|
||||||
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
// Subscribe to the relay list events
|
// Subscribe to the relay list events
|
||||||
client
|
client.subscribe(target).await?;
|
||||||
.subscribe_to(BOOTSTRAP_RELAYS, vec![filter], None)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
return Ok(RelayState::Set);
|
return Ok(RelayState::Set);
|
||||||
}
|
}
|
||||||
@@ -565,8 +568,7 @@ impl NostrRegistry {
|
|||||||
let write_relays = self.write_relays(&public_key, cx);
|
let write_relays = self.write_relays(&public_key, cx);
|
||||||
|
|
||||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||||
let mut urls = vec![];
|
let mut urls = write_relays.await;
|
||||||
urls.extend(write_relays.await);
|
|
||||||
urls.extend(
|
urls.extend(
|
||||||
BOOTSTRAP_RELAYS
|
BOOTSTRAP_RELAYS
|
||||||
.iter()
|
.iter()
|
||||||
@@ -590,9 +592,13 @@ impl NostrRegistry {
|
|||||||
.limit(1)
|
.limit(1)
|
||||||
.author(public_key);
|
.author(public_key);
|
||||||
|
|
||||||
client
|
// Construct targets for subscription
|
||||||
.subscribe_to(urls, vec![metadata, contact_list], Some(opts))
|
let target = urls
|
||||||
.await?;
|
.into_iter()
|
||||||
|
.map(|relay| (relay, vec![metadata.clone(), contact_list.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
client.subscribe(target).close_on(opts).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
@@ -616,9 +622,16 @@ impl NostrRegistry {
|
|||||||
.author(public_key)
|
.author(public_key)
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
|
// Construct targets for subscription
|
||||||
|
let target = urls
|
||||||
|
.iter()
|
||||||
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
// Stream events from the write relays
|
// Stream events from the write relays
|
||||||
let mut stream = client
|
let mut stream = client
|
||||||
.stream_events_from(&urls, vec![filter], Duration::from_secs(TIMEOUT))
|
.stream_events(target)
|
||||||
|
.timeout(Duration::from_secs(TIMEOUT))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
while let Some((_url, res)) = stream.next().await {
|
while let Some((_url, res)) = stream.next().await {
|
||||||
@@ -632,8 +645,14 @@ impl NostrRegistry {
|
|||||||
.author(public_key)
|
.author(public_key)
|
||||||
.since(Timestamp::now());
|
.since(Timestamp::now());
|
||||||
|
|
||||||
|
// Construct targets for subscription
|
||||||
|
let target = urls
|
||||||
|
.iter()
|
||||||
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
// Subscribe to the relay list events
|
// Subscribe to the relay list events
|
||||||
client.subscribe_to(&urls, vec![filter], None).await?;
|
client.subscribe(target).await?;
|
||||||
|
|
||||||
return Ok(RelayState::Set);
|
return Ok(RelayState::Set);
|
||||||
}
|
}
|
||||||
@@ -687,13 +706,13 @@ impl NostrRegistry {
|
|||||||
|
|
||||||
cx.background_spawn(async move {
|
cx.background_spawn(async move {
|
||||||
let urls = write_relays.await;
|
let urls = write_relays.await;
|
||||||
let signer = client.signer().await?;
|
|
||||||
|
|
||||||
// Sign the new metadata event
|
// Build and sign the metadata event
|
||||||
let event = EventBuilder::metadata(&metadata).sign(&signer).await?;
|
let builder = EventBuilder::metadata(&metadata);
|
||||||
|
let event = client.sign_event_builder(builder).await?;
|
||||||
|
|
||||||
// Send event to user's write relayss
|
// Send event to user's write relayss
|
||||||
client.send_event_to(urls, &event).await?;
|
client.send_event(&event).to(urls).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
@@ -728,9 +747,6 @@ impl NostrRegistry {
|
|||||||
|
|
||||||
/// Create a new identity
|
/// Create a new identity
|
||||||
fn create_identity(&mut self, cx: &mut Context<Self>) {
|
fn create_identity(&mut self, cx: &mut Context<Self>) {
|
||||||
let client = self.client();
|
|
||||||
|
|
||||||
// Generate new keys
|
|
||||||
let keys = Keys::generate();
|
let keys = Keys::generate();
|
||||||
|
|
||||||
// Get write credential task
|
// Get write credential task
|
||||||
@@ -743,8 +759,7 @@ impl NostrRegistry {
|
|||||||
// Update the signer
|
// Update the signer
|
||||||
self.set_signer(keys, false, cx);
|
self.set_signer(keys, false, cx);
|
||||||
|
|
||||||
// Spawn a task to set metadata and write the credentials
|
// Generate a unique name and avatar for the identity
|
||||||
cx.background_spawn(async move {
|
|
||||||
let name = petname::petname(2, "-").unwrap_or("Cooper".to_string());
|
let name = petname::petname(2, "-").unwrap_or("Cooper".to_string());
|
||||||
let avatar = Url::parse(DEFAULT_AVATAR).unwrap();
|
let avatar = Url::parse(DEFAULT_AVATAR).unwrap();
|
||||||
|
|
||||||
@@ -754,12 +769,15 @@ impl NostrRegistry {
|
|||||||
.name(&name)
|
.name(&name)
|
||||||
.picture(avatar);
|
.picture(avatar);
|
||||||
|
|
||||||
// Set metadata for the identity
|
// Update user's metadata
|
||||||
if let Err(e) = client.set_metadata(&metadata).await {
|
let task = self.set_metadata(&metadata, cx);
|
||||||
log::error!("Failed to set metadata: {}", e);
|
|
||||||
|
// Spawn a task to write the credentials
|
||||||
|
cx.background_spawn(async move {
|
||||||
|
if let Err(e) = task.await {
|
||||||
|
log::error!("Failed to update metadata: {}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the credentials
|
|
||||||
if let Err(e) = write_credential.await {
|
if let Err(e) = write_credential.await {
|
||||||
log::error!("Failed to write credentials: {}", e);
|
log::error!("Failed to write credentials: {}", e);
|
||||||
}
|
}
|
||||||
@@ -874,10 +892,13 @@ impl NostrRegistry {
|
|||||||
.author(public_key)
|
.author(public_key)
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
// Subscribe to bootstrap relays
|
// Construct target for subscription
|
||||||
client
|
let target = BOOTSTRAP_RELAYS
|
||||||
.subscribe_to(BOOTSTRAP_RELAYS, vec![filter], Some(opts))
|
.into_iter()
|
||||||
.await?;
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
client.subscribe(target).close_on(opts).await?;
|
||||||
|
|
||||||
Ok(public_key)
|
Ok(public_key)
|
||||||
})
|
})
|
||||||
@@ -897,9 +918,16 @@ impl NostrRegistry {
|
|||||||
.kind(Kind::Metadata)
|
.kind(Kind::Metadata)
|
||||||
.limit(FIND_LIMIT);
|
.limit(FIND_LIMIT);
|
||||||
|
|
||||||
|
// Construct target for subscription
|
||||||
|
let target = SEARCH_RELAYS
|
||||||
|
.into_iter()
|
||||||
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
// Stream events from the search relays
|
// Stream events from the search relays
|
||||||
let mut stream = client
|
let mut stream = client
|
||||||
.stream_events_from(SEARCH_RELAYS, vec![filter], Duration::from_secs(3))
|
.stream_events(target)
|
||||||
|
.timeout(Duration::from_secs(TIMEOUT))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Collect the results
|
// Collect the results
|
||||||
@@ -923,28 +951,31 @@ impl NostrRegistry {
|
|||||||
let query = query.to_string();
|
let query = query.to_string();
|
||||||
|
|
||||||
cx.background_spawn(async move {
|
cx.background_spawn(async move {
|
||||||
let signer = client.signer().await?;
|
|
||||||
|
|
||||||
// Construct a vertex request event
|
// Construct a vertex request event
|
||||||
let event = EventBuilder::new(Kind::Custom(5315), "")
|
let builder = EventBuilder::new(Kind::Custom(5315), "").tags(vec![
|
||||||
.tags(vec![
|
|
||||||
Tag::custom(TagKind::custom("param"), vec!["search", &query]),
|
Tag::custom(TagKind::custom("param"), vec!["search", &query]),
|
||||||
Tag::custom(TagKind::custom("param"), vec!["limit", "10"]),
|
Tag::custom(TagKind::custom("param"), vec!["limit", "10"]),
|
||||||
])
|
]);
|
||||||
.sign(&signer)
|
let event = client.sign_event_builder(builder).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Send the event to vertex relays
|
// Send the event to vertex relays
|
||||||
let output = client.send_event_to(WOT_RELAYS, &event).await?;
|
let output = client.send_event(&event).to(WOT_RELAYS).await?;
|
||||||
|
|
||||||
// Construct a filter to get the response or error from vertex
|
// Construct a filter to get the response or error from vertex
|
||||||
let filter = Filter::new()
|
let filter = Filter::new()
|
||||||
.kinds(vec![Kind::Custom(6315), Kind::Custom(7000)])
|
.kinds(vec![Kind::Custom(6315), Kind::Custom(7000)])
|
||||||
.event(output.id().to_owned());
|
.event(output.id().to_owned());
|
||||||
|
|
||||||
// Stream events from the search relays
|
// Construct target for subscription
|
||||||
|
let target = WOT_RELAYS
|
||||||
|
.into_iter()
|
||||||
|
.map(|relay| (relay, vec![filter.clone()]))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
// Stream events from the wot relays
|
||||||
let mut stream = client
|
let mut stream = client
|
||||||
.stream_events_from(WOT_RELAYS, vec![filter], Duration::from_secs(3))
|
.stream_events(target)
|
||||||
|
.timeout(Duration::from_secs(TIMEOUT))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
while let Some((_url, res)) = stream.next().await {
|
while let Some((_url, res)) = stream.next().await {
|
||||||
|
|||||||
88
crates/state/src/signer.rs
Normal file
88
crates/state/src/signer.rs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use nostr_sdk::prelude::*;
|
||||||
|
use smol::lock::RwLock;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CoopSigner {
|
||||||
|
signer: RwLock<Arc<dyn NostrSigner>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CoopSigner {
|
||||||
|
pub fn new<T>(signer: T) -> Self
|
||||||
|
where
|
||||||
|
T: IntoNostrSigner,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
signer: RwLock::new(signer.into_nostr_signer()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get(&self) -> Arc<dyn NostrSigner> {
|
||||||
|
self.signer.read().await.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn switch<T>(&self, new: T)
|
||||||
|
where
|
||||||
|
T: IntoNostrSigner,
|
||||||
|
{
|
||||||
|
let mut signer = self.signer.write().await;
|
||||||
|
*signer = new.into_nostr_signer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NostrSigner for CoopSigner {
|
||||||
|
fn backend(&self) -> SignerBackend {
|
||||||
|
SignerBackend::Custom(Cow::Borrowed("custom"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_public_key(&self) -> BoxedFuture<Result<PublicKey, SignerError>> {
|
||||||
|
Box::pin(async move { Ok(self.get().await.get_public_key().await?) })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sign_event(
|
||||||
|
&self,
|
||||||
|
unsigned: UnsignedEvent,
|
||||||
|
) -> BoxedFuture<std::result::Result<Event, SignerError>> {
|
||||||
|
Box::pin(async move { Ok(self.get().await.sign_event(unsigned).await?) })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nip04_encrypt<'a>(
|
||||||
|
&'a self,
|
||||||
|
public_key: &'a PublicKey,
|
||||||
|
content: &'a str,
|
||||||
|
) -> BoxedFuture<'a, std::result::Result<String, SignerError>> {
|
||||||
|
Box::pin(async move { Ok(self.get().await.nip04_encrypt(public_key, content).await?) })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nip04_decrypt<'a>(
|
||||||
|
&'a self,
|
||||||
|
public_key: &'a PublicKey,
|
||||||
|
encrypted_content: &'a str,
|
||||||
|
) -> BoxedFuture<'a, std::result::Result<String, SignerError>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
Ok(self
|
||||||
|
.get()
|
||||||
|
.await
|
||||||
|
.nip04_decrypt(public_key, encrypted_content)
|
||||||
|
.await?)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nip44_encrypt<'a>(
|
||||||
|
&'a self,
|
||||||
|
public_key: &'a PublicKey,
|
||||||
|
content: &'a str,
|
||||||
|
) -> BoxedFuture<'a, std::result::Result<String, SignerError>> {
|
||||||
|
Box::pin(async move { Ok(self.get().await.nip44_encrypt(public_key, content).await?) })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nip44_decrypt<'a>(
|
||||||
|
&'a self,
|
||||||
|
public_key: &'a PublicKey,
|
||||||
|
payload: &'a str,
|
||||||
|
) -> BoxedFuture<'a, std::result::Result<String, SignerError>> {
|
||||||
|
Box::pin(async move { Ok(self.get().await.nip44_decrypt(public_key, payload).await?) })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -246,8 +246,7 @@ impl Element for ContextMenu {
|
|||||||
|
|
||||||
let menu = PopupMenu::build(window, cx, |menu, window, cx| {
|
let menu = PopupMenu::build(window, cx, |menu, window, cx| {
|
||||||
(builder)(menu, window, cx)
|
(builder)(menu, window, cx)
|
||||||
})
|
});
|
||||||
.into_element();
|
|
||||||
|
|
||||||
let _subscription = window.subscribe(&menu, cx, {
|
let _subscription = window.subscribe(&menu, cx, {
|
||||||
let shared_state = shared_state.clone();
|
let shared_state = shared_state.clone();
|
||||||
|
|||||||
Reference in New Issue
Block a user