prepare for nostr 0.45

This commit is contained in:
daywalker90 2026-02-03 22:33:00 +01:00 committed by daywalker90
parent 5c5f49de29
commit 78ac7cac05
18 changed files with 132 additions and 157 deletions

90
Cargo.lock generated
View file

@ -86,12 +86,6 @@ dependencies = [
"web-sys",
]
[[package]]
name = "atomic-destructor"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef49f5882e4b6afaac09ad239a4f8c70a24b8f2b0897edb1f706008efd109cf4"
[[package]]
name = "atomic-waker"
version = "1.1.2"
@ -215,6 +209,12 @@ dependencies = [
"generic-array",
]
[[package]]
name = "btreecap"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6160c957d8aa33d0a8ba1dbab98e3cb57023ad9374c501441e88559f99e6c4c9"
[[package]]
name = "bumpalo"
version = "3.20.2"
@ -294,9 +294,11 @@ dependencies = [
"anyhow",
"cln-plugin",
"cln-rpc",
"futures",
"hex",
"log",
"log-panics",
"nostr",
"nostr-sdk",
"parking_lot",
"prost",
@ -363,7 +365,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"rand_core 0.6.4",
"typenum",
]
@ -561,10 +562,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi",
"wasm-bindgen",
]
[[package]]
@ -911,9 +910,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
@ -1043,9 +1039,8 @@ checksum = "f0efe882e02d206d8d279c20eb40e03baf7cb5136a1476dc084a324fbc3ec42d"
[[package]]
name = "nostr"
version = "0.44.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3aa5e3b6a278ed061835fe1ee293b71641e6bf8b401cfe4e1834bbf4ef0a34e1"
version = "0.44.1"
source = "git+https://github.com/rust-nostr/nostr.git?rev=bf3028eb11b4e324c0c660b4e4c83348cdcc00c2#bf3028eb11b4e324c0c660b4e4c83348cdcc00c2"
dependencies = [
"aes",
"base64",
@ -1055,9 +1050,10 @@ dependencies = [
"cbc",
"chacha20",
"chacha20poly1305",
"getrandom 0.2.17",
"hex",
"instant",
"once_cell",
"rand",
"scrypt",
"secp256k1",
"serde",
@ -1069,9 +1065,9 @@ dependencies = [
[[package]]
name = "nostr-database"
version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7462c9d8ae5ef6a28d66a192d399ad2530f1f2130b13186296dbb11bdef5b3d1"
source = "git+https://github.com/rust-nostr/nostr.git?rev=bf3028eb11b4e324c0c660b4e4c83348cdcc00c2#bf3028eb11b4e324c0c660b4e4c83348cdcc00c2"
dependencies = [
"btreecap",
"lru",
"nostr",
"tokio",
@ -1080,42 +1076,27 @@ dependencies = [
[[package]]
name = "nostr-gossip"
version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade30de16869618919c6b5efc8258f47b654a98b51541eb77f85e8ec5e3c83a6"
source = "git+https://github.com/rust-nostr/nostr.git?rev=bf3028eb11b4e324c0c660b4e4c83348cdcc00c2#bf3028eb11b4e324c0c660b4e4c83348cdcc00c2"
dependencies = [
"nostr",
]
[[package]]
name = "nostr-relay-pool"
version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b1073ccfbaea5549fb914a9d52c68dab2aecda61535e5143dd73e95445a804b"
dependencies = [
"async-utility",
"async-wsocket",
"atomic-destructor",
"hex",
"lru",
"negentropy",
"nostr",
"nostr-database",
"tokio",
"tracing",
]
[[package]]
name = "nostr-sdk"
version = "0.44.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "471732576710e779b64f04c55e3f8b5292f865fea228436daf19694f0bf70393"
source = "git+https://github.com/rust-nostr/nostr.git?rev=bf3028eb11b4e324c0c660b4e4c83348cdcc00c2#bf3028eb11b4e324c0c660b4e4c83348cdcc00c2"
dependencies = [
"async-utility",
"async-wsocket",
"futures",
"hex",
"lru",
"negentropy",
"nostr",
"nostr-database",
"nostr-gossip",
"nostr-relay-pool",
"tokio",
"tokio-stream",
"tracing",
]
@ -1369,37 +1350,16 @@ version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "rand"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
dependencies = [
"rand_chacha 0.9.0",
"rand_chacha",
"rand_core 0.9.5",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
@ -1568,7 +1528,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113"
dependencies = [
"bitcoin_hashes",
"rand 0.8.6",
"secp256k1-sys",
"serde",
]
@ -1874,6 +1833,7 @@ dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
"tokio-util",
]
[[package]]
@ -2083,7 +2043,7 @@ dependencies = [
"http",
"httparse",
"log",
"rand 0.9.4",
"rand",
"rustls",
"rustls-pki-types",
"sha1",

View file

@ -18,8 +18,15 @@ cln-plugin = "0.6"
# cln-plugin = { path = "../lightning/plugins/", version = "^0.6" }
parking_lot = "0.12"
# nostr-sdk = { git = "https://github.com/rust-nostr/nostr.git", rev = "f7122f5", features = ["nip47", "nip04", "nip44"]}
nostr-sdk = { version = "0.44", features = ["nip47", "nip04", "nip44"] }
nostr-sdk = { git = "https://github.com/rust-nostr/nostr.git", rev = "bf3028eb11b4e324c0c660b4e4c83348cdcc00c2" }
nostr = { git = "https://github.com/rust-nostr/nostr.git", rev = "bf3028eb11b4e324c0c660b4e4c83348cdcc00c2", features = [
"nip47",
"nip04",
"nip44",
] }
# nostr-sdk = { version = "0.44", features = ["nip47", "nip04", "nip44"] }
futures = "0.3"
uuid = { version = "1", features = ["v4"] }

View file

@ -11,7 +11,7 @@ use cln_plugin::{
options::{ConfigOption, DefaultBooleanConfigOption, StringArrayConfigOption},
};
use cln_rpc::{ClnRpc, model::requests::ListdatastoreRequest};
use nostr_sdk::nips::nip47;
use nostr::nips::nip47;
use nwc::run_nwc;
use nwc_notifications::{payment_received_handler, payment_sent_handler};
use parse::read_startup_options;
@ -23,7 +23,7 @@ use tonic::transport::{Certificate, ClientTlsConfig, Endpoint, Identity};
use util::{load_nwc_store, update_nwc_store};
use crate::{
hold::{hold_client::HoldClient, InvoiceState, ListRequest},
hold::{InvoiceState, ListRequest, hold_client::HoldClient},
nwc_notifications::holdinvoice_accepted_handler,
};

View file

@ -2,24 +2,27 @@ use std::{borrow::Cow, time::Duration};
use anyhow::anyhow;
use cln_plugin::Plugin;
use nostr_sdk::{
use futures::StreamExt;
use nostr::{
Alphabet,
Client,
Event,
EventBuilder,
EventId,
Filter,
Keys,
Kind,
PublicKey,
RelayPoolNotification,
RelayStatus,
SecretKey,
SignerError,
SingleLetterTag,
Tag,
TagKind,
Timestamp,
client,
nips::{nip04, nip44, nip47},
nostr::{Filter, Kind, Tag},
};
use nostr_sdk::{
client::{self, Client, ClientNotification, Error},
relay::RelayStatus,
};
use tokio::{sync::oneshot, time};
@ -46,16 +49,16 @@ pub async fn run_nwc(
plugin: Plugin<PluginState>,
label: String,
nwc_store: NwcStore,
) -> Result<(), client::Error> {
) -> Result<(), Error> {
let (method_capabilities, _) = build_capabilities(is_read_only_nwc(&nwc_store), &plugin);
let wallet_keys = Keys::new(
SecretKey::from_hex(&nwc_store.walletkey)
.map_err(|e| client::Error::Signer(SignerError::backend(e)))?,
.map_err(|e| Error::Signer(SignerError::backend(e)))?,
);
let client_pubkey = Keys::new(nwc_store.uri.secret.clone()).public_key();
let nostr_client = Client::new(wallet_keys.clone());
let nostr_client = Client::builder().signer(wallet_keys.clone()).build();
log::debug!("relay_count:{}", nwc_store.uri.relays.len());
@ -73,9 +76,9 @@ pub async fn run_nwc(
let label_clone = label.clone();
tokio::spawn(async move {
loop {
nostr_client_clone.connect().await;
nostr_client_clone
.wait_for_connection(Duration::from_secs(30))
.connect()
.and_wait(Duration::from_secs(30))
.await;
let relays = nostr_client_clone.relays().await;
if relays.is_empty() {
@ -115,37 +118,41 @@ pub async fn run_nwc(
.author(client_pubkey)
.since(Timestamp::now() - STARTUP_DELAY - 1);
if let Err(e) = nostr_client_clone.subscribe(filter, None).await {
log::warn!("Could not subscribe to nwc events! {e}");
nostr_client_clone.disconnect().await;
time::sleep(Duration::from_secs(5)).await;
continue;
let mut notifications = nostr_client_clone.notifications();
match nostr_client_clone.subscribe(filter).await {
Ok(o) => {
if o.success.is_empty() {
log::warn!("Could not subscribe to any relay!");
nostr_client_clone.disconnect().await;
time::sleep(Duration::from_secs(5)).await;
continue;
}
}
Err(e) => {
log::warn!("Error subscribing to relays: {e}");
nostr_client_clone.disconnect().await;
time::sleep(Duration::from_secs(5)).await;
continue;
}
}
let client_clone_handler = nostr_client_clone.clone();
match nostr_client_clone
.handle_notifications(|notification| {
let client_clone_handler = client_clone_handler.clone();
let plugin_clone = plugin_clone.clone();
let label_clone = label_clone.clone();
let wallet_keys_clone = wallet_keys.clone();
nwc_request_handler(
notification,
client_clone_handler,
plugin_clone,
label_clone,
wallet_keys_clone,
client_pubkey,
)
})
while let Some(notification) = notifications.next().await {
if let Err(e) = nwc_request_handler(
notification,
&nostr_client_clone,
&plugin_clone,
&label_clone,
&wallet_keys,
client_pubkey,
)
.await
{
Ok(()) => {
log::info!("NWC handler for `{label_clone}` stopped");
break;
}
Err(e) => log::warn!("NWC handler for `{label_clone}` had an error: {e}"),
{
log::warn!("NWC handler for `{label_clone}` had an error: {e}");
};
}
{};
}
});
@ -226,29 +233,29 @@ pub fn stop_nwc_budget_job(plugin: &Plugin<PluginState>, label: &String) {
}
async fn nwc_request_handler(
notification: RelayPoolNotification,
nostr_client: client::Client,
plugin: Plugin<PluginState>,
label: String,
wallet_keys: Keys,
notification: ClientNotification,
nostr_client: &client::Client,
plugin: &Plugin<PluginState>,
label: &String,
wallet_keys: &Keys,
client_pubkey: PublicKey,
) -> Result<bool, Box<dyn std::error::Error>> {
) -> Result<(), Box<dyn std::error::Error>> {
let (relay_url, subscription_id, event) = match notification {
RelayPoolNotification::Event {
ClientNotification::Event {
relay_url,
subscription_id,
event,
} => (relay_url, subscription_id, event),
RelayPoolNotification::Message {
ClientNotification::Message {
relay_url: _,
message: _,
} => return Ok(false),
RelayPoolNotification::Shutdown => return Ok(true),
} => return Ok(()),
ClientNotification::Shutdown => return Ok(()),
};
if let Some(expi) = event.tags.expiration() {
if *expi < Timestamp::now() {
return Ok(false);
return Ok(());
}
}
log::debug!("relay_url:{relay_url} subscription_id:{subscription_id} {event:?}");
@ -264,7 +271,7 @@ async fn nwc_request_handler(
multi_pay_invoice(plugin.clone(), multi_pay_invoice_request, &label).await
}
nip47::RequestParams::PayKeysend(pay_keysend_request) => {
pay_keysend_response(plugin, pay_keysend_request, &label).await
pay_keysend_response(plugin.clone(), pay_keysend_request, &label).await
}
nip47::RequestParams::MultiPayKeysend(multi_pay_keysend_request) => {
multi_pay_keysend(plugin.clone(), multi_pay_keysend_request, &label).await
@ -330,7 +337,7 @@ async fn nwc_request_handler(
log::debug!("SENT RESPONSE {response_event:?}");
}
Ok(false)
Ok(())
}
fn check_nip44_support(event: &Event) -> bool {

View file

@ -1,6 +1,6 @@
use cln_plugin::Plugin;
use cln_rpc::{model::requests::ListpeerchannelsRequest, primitives::ChannelState};
use nostr_sdk::nips::nip47;
use nostr::nips::nip47;
use crate::{structs::PluginState, util::load_nwc_store};

View file

@ -2,7 +2,7 @@ use std::str::FromStr;
use cln_plugin::Plugin;
use cln_rpc::primitives::Sha256;
use nostr_sdk::{nips::nip47, Timestamp};
use nostr::{nips::nip47, Timestamp};
use crate::{
hold::{invoice_request::Description, CancelRequest, InvoiceRequest, SettleRequest},
@ -93,7 +93,7 @@ async fn make_hold_invoice(
payment_hash: payment_hash.clone(),
amount_msat: params.amount,
expiry: Some(expiry),
min_final_cltv_expiry: params.cltv_expiry_delta.map(u64::from),
min_final_cltv_expiry: params.min_cltv_expiry_delta.map(u64::from),
routing_hints: Vec::new(),
description,
};

View file

@ -1,6 +1,6 @@
use cln_plugin::Plugin;
use cln_rpc::model::requests::GetinfoRequest;
use nostr_sdk::nips::nip47;
use nostr::nips::nip47;
use crate::{
structs::PluginState,

View file

@ -5,7 +5,7 @@ use cln_rpc::{
model::requests::InvoiceRequest,
primitives::{Amount, AmountOrAny, Sha256},
};
use nostr_sdk::nips::nip47;
use nostr::{nips::nip47, types::Timestamp};
use uuid::Uuid;
use crate::structs::PluginState;
@ -94,8 +94,8 @@ async fn make_invoice(
description_hash: params.description_hash,
preimage: None,
amount: Some(params.amount),
created_at: Some(nostr_sdk::nostr::Timestamp::now()),
expires_at: Some(nostr_sdk::nostr::Timestamp::from_secs(o.expires_at)),
created_at: Some(Timestamp::now()),
expires_at: Some(Timestamp::from_secs(o.expires_at)),
}),
Err(e) => Err(nip47::NIP47Error {
code: nip47::ErrorCode::Internal,

View file

@ -5,7 +5,7 @@ use cln_rpc::{
model::requests::KeysendRequest,
primitives::{Amount, PublicKey, TlvEntry, TlvStream},
};
use nostr_sdk::nips::nip47;
use nostr::nips::nip47;
use tokio::time;
use crate::{

View file

@ -15,7 +15,7 @@ use cln_rpc::{
primitives::Sha256,
ClnRpc,
};
use nostr_sdk::{nips::nip47, Timestamp};
use nostr::{nips::nip47, Timestamp};
use crate::{
hold::{self, list_request::Constraint, ListRequest},

View file

@ -3,6 +3,7 @@ use std::str::FromStr;
use anyhow::anyhow;
use cln_plugin::Plugin;
use cln_rpc::{
ClnRpc,
model::{
requests::{DecodeRequest, ListinvoicesRequest, ListpaysRequest, ListpeerchannelsRequest},
responses::{
@ -14,19 +15,14 @@ use cln_rpc::{
},
},
primitives::Sha256,
ClnRpc,
};
use nostr_sdk::{
nips::nip47,
nostr::{key::PublicKey, EventBuilder, Kind, Tag},
Client,
Timestamp,
};
use nostr::{EventBuilder, Kind, Tag, Timestamp, key::PublicKey, nips::nip47};
use nostr_sdk::client::Client;
use crate::{
hold::{list_request::Constraint, InvoiceState, ListRequest, TrackRequest},
structs::{PluginState, NOT_INV_ERR},
OPT_NOTIFICATIONS,
hold::{InvoiceState, ListRequest, TrackRequest, list_request::Constraint},
structs::{NOT_INV_ERR, PluginState},
};
pub async fn payment_received_handler(
@ -341,7 +337,7 @@ async fn send_notification(
client: &Client,
client_pubkey: &PublicKey,
) -> Result<(), anyhow::Error> {
let signer = client.signer().await?;
let signer = client.signer().unwrap().clone();
log::debug!("NOTIFICATION: {notification}");
let content_encrypted_nip04 = signer.nip04_encrypt(client_pubkey, notification).await?;
let event_nip04 = EventBuilder::new(Kind::from_u16(23196), content_encrypted_nip04)
@ -460,6 +456,7 @@ pub async fn holdinvoice_accepted_handler(
.call_typed(&ListpeerchannelsRequest {
id: None,
short_channel_id: None,
channel_id: None,
})
.await?
.channels;
@ -497,6 +494,7 @@ pub async fn holdinvoice_accepted_handler(
expires_at,
settle_deadline: lowest_htlc_expiry,
metadata: None,
state: Some(nip47::TransactionState::Accepted),
},
),
};

View file

@ -10,7 +10,7 @@ use cln_rpc::{
ClnRpc,
RpcError,
};
use nostr_sdk::nips::nip47;
use nostr::nips::nip47;
use tokio::time;
use crate::{

View file

@ -3,6 +3,7 @@ use std::path::Path;
use anyhow::anyhow;
use cln_plugin::ConfiguredPlugin;
use cln_rpc::{model::requests::GetinfoRequest, ClnRpc};
use nostr::types::RelayUrl;
use crate::{
structs::{PluginState, TimeUnit},
@ -37,7 +38,7 @@ pub async fn read_startup_options(
config.my_cln_version = version;
for relay in relays_str {
log::debug!("RELAY:{relay}");
config.relays.push(nostr_sdk::RelayUrl::parse(&relay)?);
config.relays.push(RelayUrl::parse(&relay)?);
}
Ok(())
}

View file

@ -6,7 +6,7 @@ use cln_rpc::model::requests::{
DeldatastoreRequest,
ListdatastoreRequest,
};
use nostr_sdk::{Keys, SecretKey, Timestamp, nips::nip47::NostrWalletConnectURI};
use nostr::{Keys, SecretKey, Timestamp, nips::nip47::NostrWalletConnectUri};
use serde_json::json;
use crate::{
@ -29,7 +29,7 @@ pub async fn nwc_create(
let wallet_keys = Keys::generate();
let client_keys = Keys::generate();
let uri = NostrWalletConnectURI::new(
let uri = NostrWalletConnectUri::new(
wallet_keys.public_key(),
config.relays.clone(),
client_keys.secret_key().clone(),

View file

@ -1,7 +1,8 @@
use std::{collections::HashMap, path::PathBuf, str::FromStr, sync::Arc};
use cln_rpc::ClnRpc;
use nostr_sdk::{client, nips::nip47, nostr};
use nostr::{nips::nip47::NostrWalletConnectUri, types::RelayUrl};
use nostr_sdk::client;
use parking_lot::Mutex;
use serde::{Deserialize, Serialize};
use tokio::sync::oneshot;
@ -33,7 +34,7 @@ impl PluginState {
#[derive(Clone, Debug)]
pub struct Config {
pub relays: Vec<nostr_sdk::RelayUrl>,
pub relays: Vec<RelayUrl>,
pub my_cln_version: String,
}
impl Config {
@ -77,7 +78,7 @@ pub struct BudgetIntervalConfig {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NwcStore {
pub uri: nip47::NostrWalletConnectURI,
pub uri: NostrWalletConnectUri,
pub walletkey: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub budget_msat: Option<u64>,

View file

@ -3,7 +3,7 @@ use std::{path::Path, time::Duration};
use anyhow::anyhow;
use cln_plugin::Plugin;
use cln_rpc::ClnRpc;
use nostr_sdk::Timestamp;
use nostr::types::Timestamp;
use tokio::{sync::oneshot, time};
use crate::{

View file

@ -4,7 +4,7 @@ use cln_rpc::{
model::requests::{DatastoreMode, DatastoreRequest, ListdatastoreRequest},
ClnRpc,
};
use nostr_sdk::nips::nip47;
use nostr::nips::nip47;
use crate::{
structs::{NwcStore, PluginState},

View file

@ -1484,6 +1484,7 @@ async def test_hold_invoice(
"important-plugin": get_hold,
"nip47-relays": url,
"may_reconnect": True,
"broken_log": r"Relay receiver exited with error",
},
],
)
@ -1672,10 +1673,10 @@ async def test_hold_invoice(
)
wait_for(
lambda: l1.rpc.call("listpays", {"payment_hash": payment_hash})["pays"][0][
"status"
]
== "complete"
lambda: (
l1.rpc.call("listpays", {"payment_hash": payment_hash})["pays"][0]["status"]
== "complete"
)
)
preimage = secrets.token_hex(32)
@ -1687,7 +1688,7 @@ async def test_hold_invoice(
"payment_hash": payment_hash,
"description": "cancel_hold",
"expiry": 1000,
"cltv_expiry_delta": 200,
"min_cltv_expiry_delta": 200,
},
}
content = json.dumps(content)
@ -1815,10 +1816,10 @@ async def test_hold_invoice(
assert invoice2_decoded["min_final_cltv_expiry"] == 200
wait_for(
lambda: l1.rpc.call("listpays", {"payment_hash": payment_hash})["pays"][0][
"status"
]
== "failed"
lambda: (
l1.rpc.call("listpays", {"payment_hash": payment_hash})["pays"][0]["status"]
== "failed"
)
)
nwc = Nwc(uri)