Describe the bug
I am using dioxus web and
nostr-sdk = "=0.45.0-alpha.4"
To Reproduce
This is my login page code
#![allow(non_snake_case)]
use dioxus::prelude::*;
use nostr_sdk::prelude::*;
use crate::Session;
const DEFAULT_RELAYS: [&str; 3] = [
"wss://relay.damus.io",
"wss://nos.lol",
"wss://relay.primal.net",
];
#[component]
pub fn LoginPage(mut session: Signal<Option<Session>>) -> Element {
let mut mode = use_signal(|| "login".to_string()); // "login" | "create"
let mut key_input = use_signal(String::new);
let mut error = use_signal(|| Option::<String>::None);
let mut loading = use_signal(|| false);
let mut new_keys_preview: Signal<Option<Keys>> = use_signal(|| None);
// Shared by both flows: spin up a Client for these keys, connect to
// relays, and hand the resulting Session back up to the app.
let mut connect_and_enter = move |keys: Keys| {
loading.set(true);
error.set(None);
spawn(async move {
// Use the new SignerAuthenticator API from the latest nostr-sdk
let authenticator = SignerAuthenticator::new(keys.clone());
let client = Client::builder().authenticator(authenticator).build();
for relay in DEFAULT_RELAYS {
// Handle the Result explicitly. DO NOT use `?` here,
// because `spawn` expects an async block that returns `()`.
if let Err(e) = client.add_relay(relay).await {
error.set(Some(format!("Couldn't add relay {relay}: {e}")));
}
}
client.connect().await;
session.set(Some(Session { keys, client }));
loading.set(false);
});
};
rsx! {
div { class: "flex items-center justify-center min-h-screen px-4",
div { class: "w-full max-w-md bg-gray-900 border border-gray-800 rounded-2xl shadow-xl p-8",
div { class: "flex flex-col items-center mb-6",
div { class: "w-14 h-14 rounded-full bg-purple-600 flex items-center justify-center text-2xl font-bold mb-3",
"N"
}
h1 { class: "text-2xl font-semibold", "Nostr Client" }
p { class: "text-gray-400 text-sm mt-1", "Dioxus + nostr-sdk" }
}
// Tab switcher
div { class: "flex mb-6 bg-gray-800 rounded-lg p-1",
button {
class: format!(
"flex-1 py-2 rounded-md text-sm font-medium transition-colors {}",
if mode() == "login" { "bg-purple-600 text-white" } else { "text-gray-400 hover:text-gray-200" }
),
onclick: move |_| { mode.set("login".to_string()); error.set(None); },
"Log In"
}
button {
class: format!(
"flex-1 py-2 rounded-md text-sm font-medium transition-colors {}",
if mode() == "create" { "bg-purple-600 text-white" } else { "text-gray-400 hover:text-gray-200" }
),
onclick: move |_| { mode.set("create".to_string()); error.set(None); new_keys_preview.set(None); },
"Create Account"
}
}
if let Some(msg) = error() {
div { class: "mb-4 text-sm text-red-400 bg-red-950 border border-red-900 rounded-lg p-3",
"{msg}"
}
}
if mode() == "login" {
div { class: "space-y-4",
div {
label { class: "block text-sm text-gray-400 mb-1", "Private key" }
input {
class: "w-full bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-purple-600",
r#type: "password",
placeholder: "nsec1... or hex secret key",
value: "{key_input}",
oninput: move |e| key_input.set(e.value()),
}
}
button {
class: "w-full bg-purple-600 hover:bg-purple-500 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg py-2.5 font-medium transition-colors",
disabled: loading(),
onclick: move |_| {
let input = key_input().trim().to_string();
if input.is_empty() {
error.set(Some("Enter your private key first.".into()));
return;
}
match Keys::parse(&input) {
Ok(keys) => connect_and_enter(keys),
Err(e) => error.set(Some(format!("That doesn't look like a valid key: {e}"))),
}
},
if loading() { "Connecting..." } else { "Log In" }
}
p { class: "text-xs text-gray-500 text-center",
"Your key never leaves this app — it's only used locally to sign events."
}
}
} else {
div { class: "space-y-4",
if let Some(keys) = new_keys_preview() {
div { class: "space-y-3",
div { class: "bg-gray-800 rounded-lg p-3",
p { class: "text-xs text-gray-400 mb-1", "Public key (npub) — share this" }
p { class: "text-xs break-all text-green-400 font-mono",
"{keys.public_key().to_bech32().unwrap_or_default()}"
}
}
div { class: "bg-gray-800 rounded-lg p-3 border border-yellow-800",
p { class: "text-xs text-gray-400 mb-1", "Private key (nsec) — keep this secret and save it now" }
p { class: "text-xs break-all text-yellow-400 font-mono",
"{keys.secret_key().to_bech32().unwrap_or_default()}"
}
}
button {
class: "w-full bg-purple-600 hover:bg-purple-500 disabled:opacity-50 rounded-lg py-2.5 font-medium transition-colors",
disabled: loading(),
onclick: move |_| connect_and_enter(keys.clone()),
if loading() { "Connecting..." } else { "I've saved it — Continue" }
}
}
} else {
div { class: "space-y-4",
p { class: "text-sm text-gray-400",
"This generates a brand-new Nostr identity (a keypair) on your device. Nobody can recover your private key if you lose it, so save it somewhere safe on the next screen."
}
button {
class: "w-full bg-purple-600 hover:bg-purple-500 rounded-lg py-2.5 font-medium transition-colors",
onclick: move |_| new_keys_preview.set(Some(Keys::generate())),
"Generate New Keys"
}
}
}
}
}
}
}
}
}
[dependencies]
dioxus = { workspace = true, features = ["router"] }
ui = { workspace = true }
nostr-sdk = "=0.45.0-alpha.4"
# Add this line to enable WebAssembly support for getrandom
getrandom = { version = "0.4", features = ["wasm_js"] }
Build environment
nostr-sdk = "=0.45.0-alpha.4"
It gives following error:
21:46:59 [web] panicked at /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/js-sys-0.3.103/src/futures/task/singlethread.rs:142:37:
RefCell already borrowed
Stack:
__wbg_get_imports/__wbg_new_3c07cdd0b848cbc8/<@http://localhost:8080/wasm/web.js:1113:25
logError@http://localhost:8080/wasm/web.js:2037:18
__wbg_new_3c07cdd0b848cbc8@http://localhost:8080/wasm/web.js:1112:57
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[29611]:0x567725
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[17513]:0x4e92fb
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[5363]:0x36ba99
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[22616]:0x52bc3f
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[6333]:0x3a1098
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[8904]:0x412bca
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[30130]:0x56901c
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[22785]:0x52d953
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[22788]:0x52d9dc
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[14978]:0x4bcf70
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[30135]:0x56904f
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[10125]:0x43ed74
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[3504]:0x2e6fd6
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[3314]:0x2d6bbd
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[15326]:0x4c3ae9
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[13819]:0x4a4845
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[13166]:0x49575a
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[18782]:0x4fc539
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[4234]:0x320c15
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[29399]:0x566734
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[24311]:0x53d180
_ZN12wasm_bindgen7convert8closures1_6invoke17h59a5801588d3aaa2E@http://localhost:8080/wasm/web.js:1874:22
real@http://localhost:8080/wasm/web.js:2087:20
VoidFunction*__wbg_get_imports/__wbg_queueMicrotask_6a09b7bc46549209/<@http://localhost:8080/wasm/web.js:1277:27
logError@http://localhost:8080/wasm/web.js:2037:18
__wbg_queueMicrotask_6a09b7bc46549209@http://localhost:8080/wasm/web.js:1276:68
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[30277]:0x5695b1
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[17673]:0x4ebad2
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[6230]:0x39bce2
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[22282]:0x5282ce
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[22279]:0x528244
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[24195]:0x53be4a
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[26823]:0x55439b
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[13517]:0x49dab8
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[20864]:0x517bdc
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[14372]:0x4b08e9
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[10975]:0x45a38a
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[16259]:0x4d4a91
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[20526]:0x513827
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[18437]:0x4f74d6
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[22094]:0x525f71
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[21410]:0x51e1a1
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[22090]:0x525eb3
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[22092]:0x525f0f
@http://localhost:8080/wasm/web_bg.wasm:wasm-function[11867]:0x474320
_ZN12wasm_bindgen7convert8closures1_6invoke17hfda2cc28ca75afffE@http://localhost:8080/wasm/web.js:1819:10
real@http://localhost:8080/wasm/web.js:2087:20
21:46:59 [web] %cERROR%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:799%c Connection failed. url = error = timeout;r.band;
21:46:59 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:636%c Reconnecting to 'wss://relay.nostr.band' relay in 13 secs
21:47:12 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:223%c Connecting to 'wss://relay.nostr.band'
21:47:27 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:636%c Reconnecting to 'wss://relay.nostr.band' relay in 19 secs
21:47:46 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:223%c Connecting to 'wss://relay.nostr.band'
21:48:01 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:636%c Reconnecting to 'wss://relay.nostr.band' relay in 17 secs
21:48:18 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:223%c Connecting to 'wss://relay.nostr.band'
21:48:33 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:636%c Reconnecting to 'wss://relay.nostr.band' relay in 31 secs
21:49:04 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:223%c Connecting to 'wss://relay.nostr.band'
21:49:19 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:636%c Reconnecting to 'wss://relay.nostr.band' relay in 31 secs
21:49:51 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:223%c Connecting to 'wss://relay.nostr.band'
21:50:07 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:636%c Reconnecting to 'wss://relay.nostr.band' relay in 43 secs
21:50:51 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:223%c Connecting to 'wss://relay.nostr.band'
21:51:06 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:636%c Reconnecting to 'wss://relay.nostr.band' relay in 41 secs
21:51:48 [web] %cDEBUG%c /home/amiya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nostr-sdk-0.45.0-alpha.4/src/relay/inner.rs:223%c Connecting to 'wss://relay.nostr.band'
21:51:53 [dev] Build completed in 5.71s
Describe the bug
I am using dioxus web and
nostr-sdk = "=0.45.0-alpha.4"
To Reproduce
This is my login page code
Build environment
nostr-sdk = "=0.45.0-alpha.4"
It gives following error: