Rust去中心化社交协议库nostr-sdk的使用,支持Nostr协议的客户端开发与事件交互
Rust去中心化社交协议库nostr-sdk的使用,支持Nostr协议的客户端开发与事件交互
Nostr SDK
这是一个用Rust编写的高层Nostr客户端库。如果你正在编写一个典型的Nostr客户端或机器人,这个库很可能就是你需要的。
快速开始
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use nostr_sdk::prelude::*;
#[tokio::main]
async fn main() -> Result<()> {
// 生成新的随机密钥
let keys = Keys::generate();
// 或者使用已有的密钥(从hex或bech32格式)
let keys = Keys::parse("hex-or-bech32-secret-key")?;
// 显示bech32格式的公钥
let bech32_pubkey: String = keys.public_key().to_bech32()?;
println!("Bech32 PubKey: {}", bech32_pubkey);
// 配置客户端使用代理连接.onion中继
let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9050));
let connection: Connection = Connection::new()
.proxy(addr) // 使用`.embedded_tor()`替代以启用嵌入式tor客户端(需要`tor`特性)
.target(ConnectionTarget::Onion);
let opts = ClientOptions::new().connection(connection);
// 创建带有自定义选项的新客户端
let client = Client::builder().signer(keys.clone()).opts(opts).build();
// 添加中继
client.add_relay("wss://relay.damus.io").await?;
client.add_relay("ws://jgqaglhautb4k6e6i2g34jakxiemqp6z4wynlirltuukgkft2xuglmqd.onion").await?;
// 添加只读中继
client.add_read_relay("wss://relay.nostr.info").await?;
// 连接到中继
client.connect().await;
let metadata = Metadata::new()
.name("username")
.display_name("My Username")
.about("Description")
.picture(Url::parse("https://example.com/avatar.png")?)
.banner(Url::parse("https://example.com/banner.png")?)
.nip05("username@example.com")
.lud16("pay@yukikishimoto.com")
.custom_field("custom_field", "my value");
// 更新元数据
client.set_metadata(&metadata).await?;
// 发布一条文本笔记
let builder = EventBuilder::text_note("My first text note from rust-nostr!");
client.send_event_builder(builder).await?;
// 创建一条POW文本笔记
let builder = EventBuilder::text_note("POW text note from nostr-sdk").pow(20);
client.send_event_builder(builder).await?; // 发送到所有中继
// client.send_event_builder_to(["wss://relay.damus.io"], builder).await?; // 发送到特定中继
Ok(())
}
WASM支持
这个库支持wasm32
目标。在macOS上,你需要安装llvm
:
brew install llvm
LLVM_PATH=$(brew --prefix llvm)
AR="${LLVM_PATH}/bin/llvm-ar" CC="${LLVM_PATH}/bin/clang" cargo build --target wasm32-unknown-unknown
注意: 目前nip03
特性不支持WASM。
特性标志
以下是可用的特性标志:
特性 | 默认 | 描述 |
---|---|---|
tor |
否 | 启用嵌入式tor客户端支持 |
lmdb |
否 | 启用LMDB存储后端 |
ndb |
否 | 启用nostrdb存储后端 |
indexeddb |
否 | 启用Web的IndexedDb存储后端 |
all-nips |
否 | 启用所有NIPs |
nip03 |
否 | 启用NIP-03: 事件的时间戳证明 |
nip04 |
否 | 启用NIP-04: 加密直接消息 |
nip06 |
否 | 启用NIP-06: 从助记词派生基本密钥 |
nip44 |
否 | 启用NIP-44: 加密载荷(版本化) |
nip47 |
否 | 启用NIP-47: Nostr钱包连接 |
nip49 |
否 | 启用NIP-49: 私钥加密 |
nip57 |
否 | 启用NIP-57: 打赏 |
nip59 |
否 | 启用NIP-59: 礼物包装 |
状态
这个库处于ALPHA状态,已实现的功能通常可以工作,但API可能会有重大变更。
许可证
这个项目采用MIT软件许可证。
完整示例代码
基于上述内容,这里是一个更完整的Nostr客户端开发示例:
use nostr_sdk::prelude::*;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<()> {
// 1. 密钥管理
let keys = Keys::generate(); // 生成新密钥
println!("公钥: {}", keys.public_key().to_bech32()?);
// 2. 客户端配置
let opts = ClientOptions::new()
.send_timeout(Some(Duration::from_secs(10))) // 设置超时
.wait_for_send(true); // 等待发送确认
let client = Client::builder()
.signer(keys.clone())
.opts(opts)
.build();
// 3. 连接中继
client.add_relay("wss://relay.damus.io").await?;
client.add_relay("wss://nostr-relay.wlvs.space").await?;
client.connect().await;
// 4. 发布元数据
let metadata = Metadata::new()
.name("rust-nostr-example")
.display_name("Rust Nostr示例")
.about("使用nostr-sdk的示例客户端");
client.set_metadata(&metadata).await?;
// 5. 发布文本笔记
let event_id = client
.publish_text_note("Hello from Rust Nostr SDK!", &[])
.await?;
println!("发布的事件ID: {}", event_id);
// 6. 订阅和接收事件
let subscription = Filter::new()
.author(keys.public_key())
.limit(10);
client.subscribe(vec![subscription]).await;
let mut notifications = client.notifications();
while let Ok(notification) = notifications.recv().await {
if let RelayPoolNotification::Event(_url, event) = notification {
println!("收到新事件: {:?}", event);
}
}
Ok(())
}
这个示例展示了:
- 密钥生成和管理
- 客户端配置
- 中继连接
- 元数据发布
- 文本笔记发布
- 事件订阅和接收
你可以根据需要扩展这个基本框架,添加更多Nostr协议功能。
1 回复
以下是基于您提供的内容整理的Rust去中心化社交协议库nostr-sdk使用指南,包含完整示例代码:
Rust去中心化社交协议库nostr-sdk使用指南
简介
nostr-sdk是一个Rust实现的Nostr协议库,用于开发支持Nostr协议的客户端应用。Nostr是一个简单的、去中心化的社交网络协议,基于事件(event)和密钥对(key pair)运作。
主要功能
- 创建和管理Nostr密钥对
- 构建和解析Nostr事件
- 与中继服务器(relay)交互
- 处理Nostr协议的各种消息类型
安装
在Cargo.toml中添加依赖:
[dependencies]
nostr-sdk = "0.10"
tokio = { version = "1.0", features = ["full"] }
futures = "0.3"
完整示例代码
1. 密钥管理和基本事件发送
use nostr_sdk::{Keys, Event, Client};
use std::time::Duration;
#[tokio::main]
async fn main() {
// 1. 生成密钥对
let keys = Keys::generate();
println!("生成的私钥: {}", keys.secret_key().unwrap());
println!("生成的公钥: {}", keys.public_key());
// 2. 创建文本事件
let event = Event::new_text_note(&keys, "这是我的第一条Nostr消息!").unwrap();
println!("创建的事件: {:?}", event);
// 3. 连接中继并发送事件
let client = Client::new();
client.add_relay("wss://relay.damus.io").await.unwrap();
client.connect().await;
// 发送事件
match client.send_event(event).await {
Ok(_) => println!("事件发送成功!"),
Err(e) => println!("发送失败: {:?}", e),
}
// 等待5秒后断开连接
tokio::time::sleep(Duration::from_secs(5)).await;
client.disconnect().await.unwrap();
}
2. 完整客户端实现(订阅+发送)
use nostr_sdk::{Client, Keys, Event, Filter, Kind};
use futures::stream::StreamExt;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 初始化客户端和密钥
let keys = Keys::generate();
let client = Client::new();
// 2. 添加多个中继
let relays = vec![
"wss://relay.damus.io",
"wss://nostr-pub.wellorder.net",
];
for relay in relays {
client.add_relay(relay).await?;
}
// 3. 连接所有中继
client.connect().await;
// 4. 订阅事件
let filter = Filter::new()
.kind(Kind::TextNote)
.limit(10);
let mut notifications = client.notifications();
client.subscribe(vec![filter]).await;
// 5. 在单独任务中发送测试事件
let client_clone = client.clone();
let keys_clone = keys.clone();
tokio::spawn(async move {
let event = Event::new_text_note(&keys_clone, "Hello from Rust SDK!").unwrap();
tokio::time::sleep(Duration::from_secs(2)).await;
client_clone.send_event(event).await.unwrap();
});
// 6. 处理接收的事件
while let Some(notification) = notifications.next().await {
match notification {
Ok(event) => {
println!("收到新事件: {}", event.content);
println!("作者: {}", event.pubkey);
println!("时间: {}", event.created_at);
}
Err(e) => eprintln!("错误: {:?}", e),
}
}
// 7. 断开连接
client.disconnect().await?;
Ok(())
}
3. 个人资料管理和加密私信
use nostr_sdk::{Keys, EventBuilder, Kind};
use serde_json::json;
fn main() {
// 1. 创建密钥对
let user_keys = Keys::generate();
let friend_keys = Keys::generate();
// 2. 更新个人资料
let profile_event = EventBuilder::new(Kind::Metadata)
.content(&json!({
"name": "Rust开发者",
"about": "nostr-sdk测试账号",
"picture": "https://example.com/avatar.png"
}).to_string())
.to_event(&user_keys)
.unwrap();
println!("个人资料事件: {:?}", profile_event);
// 3. 创建加密私信
let dm_content = "这是一个加密的私密消息";
let dm_event = EventBuilder::new_encrypted_direct_msg(
&user_keys,
&friend_keys.public_key(),
dm_content,
).unwrap()
.to_event(&user_keys)
.unwrap();
println!("加密私信: {:?}", dm_event);
}
注意事项
- 妥善保管私钥,丢失后无法恢复
- 中继服务器可能会限制某些操作
- 网络请求是异步的,需要使用async/await
- 生产环境应考虑错误处理和重试机制
- 建议使用env_logger或类似库添加日志记录
- 对于长时间运行的客户端,需要处理重新连接逻辑
nostr-sdk提供了完整的Nostr协议实现,开发者可以基于此构建各种去中心化社交应用。