archy/core/archipelago/src/api/rpc/handshake.rs
Dorian f3976ba03a refactor: centralize constants, eliminate unwraps, remove dead code, resolve TODOs
- R13+R16: Replace .expect() with .context()? in main.rs and identity.rs
- R17+R18+R19: Fix unwrap() calls in helpers and js-engine
- R20+R21: Remove #[allow(dead_code)] annotations and delete truly dead code
- R22-R26: Create constants.rs module, replace 21 hardcoded values across 12 files
- R28+R29: LND/DWN timeouts already present — verified
- R30-R33: Remove TODO comments, implement marketplace payment check

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 01:54:35 +00:00

150 lines
5.6 KiB
Rust

use super::RpcHandler;
use crate::{nostr_handshake, peers};
use anyhow::Result;
use nostr_sdk::FromBech32;
impl RpcHandler {
/// Discover nodes (presence-only — returns Nostr pubkeys + DIDs, no onion addresses).
pub(super) async fn handle_handshake_discover(&self) -> Result<serde_json::Value> {
let identity_dir = self.config.data_dir.join("identity");
let nodes = nostr_handshake::discover_nodes(
&identity_dir,
&self.config.nostr_relays,
self.config.nostr_tor_proxy.as_deref(),
)
.await?;
Ok(serde_json::json!({ "nodes": nodes }))
}
/// Send encrypted connection request to a peer's Nostr pubkey.
/// Params: { recipient_nostr_pubkey }
pub(super) async fn handle_handshake_connect(
&self,
params: Option<serde_json::Value>,
) -> Result<serde_json::Value> {
let params = params.ok_or_else(|| anyhow::anyhow!("Missing params"))?;
// Accept either hex pubkey or npub1... bech32 format
let recipient_raw = params
.get("recipient_nostr_pubkey")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing recipient_nostr_pubkey"))?;
let recipient = if recipient_raw.starts_with("npub1") {
nostr_sdk::PublicKey::from_bech32(recipient_raw)
.map_err(|e| anyhow::anyhow!("Invalid npub: {}", e))?
.to_hex()
} else {
recipient_raw.to_string()
};
let recipient = recipient.as_str();
let (data, _) = self.state_manager.get_snapshot().await;
let our_onion = data
.server_info
.tor_address
.as_deref()
.ok_or_else(|| anyhow::anyhow!("No Tor address available — is Tor running?"))?;
let our_node_pubkey = &data.server_info.pubkey;
let our_did = crate::identity::did_key_from_pubkey_hex(our_node_pubkey)
.unwrap_or_default();
let our_version = &data.server_info.version;
let our_name = data.server_info.name.as_deref();
let identity_dir = self.config.data_dir.join("identity");
nostr_handshake::send_connect_request(
&identity_dir,
recipient,
our_onion,
our_node_pubkey,
&our_did,
our_version,
our_name,
&self.config.nostr_relays,
self.config.nostr_tor_proxy.as_deref(),
)
.await?;
Ok(serde_json::json!({ "ok": true, "sent_to": recipient }))
}
/// Poll for incoming encrypted handshake messages (connect requests/responses).
/// Auto-adds peers and auto-responds to requests.
pub(super) async fn handle_handshake_poll(&self) -> Result<serde_json::Value> {
let identity_dir = self.config.data_dir.join("identity");
let handshakes = nostr_handshake::poll_handshakes(
&identity_dir,
&self.config.nostr_relays,
self.config.nostr_tor_proxy.as_deref(),
None,
)
.await?;
let (data, _) = self.state_manager.get_snapshot().await;
let mut added_peers = Vec::new();
for hs in &handshakes {
let (onion, node_pubkey, name) = match &hs.message {
nostr_handshake::HandshakeMessage::ConnectRequest {
onion,
node_pubkey,
name,
..
} => {
// Auto-respond with our details
if let Some(our_onion) = data.server_info.tor_address.as_deref() {
let our_did = crate::identity::did_key_from_pubkey_hex(
&data.server_info.pubkey,
)
.unwrap_or_default();
let _ = nostr_handshake::send_connect_response(
&identity_dir,
&hs.from_nostr_pubkey,
our_onion,
&data.server_info.pubkey,
&our_did,
&data.server_info.version,
data.server_info.name.as_deref(),
&self.config.nostr_relays,
self.config.nostr_tor_proxy.as_deref(),
)
.await;
}
(onion.clone(), node_pubkey.clone(), name.clone())
}
nostr_handshake::HandshakeMessage::ConnectResponse {
onion,
node_pubkey,
name,
..
} => (onion.clone(), node_pubkey.clone(), name.clone()),
};
// Auto-add as peer
let peer = peers::KnownPeer {
onion,
pubkey: node_pubkey.clone(),
name,
added_at: Some(chrono::Utc::now().to_rfc3339()),
};
let _ = peers::add_peer(&self.config.data_dir, peer).await;
added_peers.push(node_pubkey);
}
let serialized: Vec<serde_json::Value> = handshakes
.iter()
.map(|hs| {
serde_json::json!({
"from_nostr_pubkey": hs.from_nostr_pubkey,
"from_nostr_npub": hs.from_nostr_npub,
"message": hs.message,
"timestamp": hs.timestamp,
})
})
.collect();
Ok(serde_json::json!({
"handshakes": serialized,
"added_peers": added_peers,
}))
}
}