该提交新增了完整的 Nostr 去中心化社交网络适配器实现,包含以下核心功能: 1. 基础加密与密钥处理:支持 nsec/npub/hex 格式密钥转换,实现 NIP-04/NIP-17 加解密 2. Relay 管理与健康监控:支持多 Relay 连接、自动重连、健康评分与自动选优 3. 事件与消息处理:实现事件校验、去重、速率限制、消息缓存与状态持久化 4. 个人资料管理:支持发布/导入/合并 Nostr Kind 0 元数据事件 5. 配对机制:实现安全的双向配对通信流程 6. Zap 功能:支持 NIP-57 打赏请求与收据解析 7. NIP-05 验证:实现域名身份验证 8. 配置系统:完整的配置校验与多账户支持 9. 监控与指标:提供连接监控、事件统计与健康快照 10. HTTP API:提供个人资料管理的 RESTful 接口 11. 安装向导:命令行配置向导与初始化流程 所有模块均遵循 Nostr 协议规范,支持多账户、多 Relay 部署,内置安全防护与流量控制机制。
71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
from yuxi.channels.adapters.nostr.crypto import NostrCrypto
|
|
from yuxi.channels.adapters.nostr.relay_manager import RelayManager
|
|
from yuxi.utils.logging_config import logger
|
|
|
|
|
|
class NostrZapManager:
|
|
def __init__(self, crypto: NostrCrypto, relay_manager: RelayManager):
|
|
self._crypto = crypto
|
|
self._relay_manager = relay_manager
|
|
|
|
def parse_zap_receipt(self, raw_event: dict) -> dict | None:
|
|
kind = raw_event.get("kind", 0)
|
|
if kind != 9735:
|
|
return None
|
|
|
|
tags: list[list[str]] = raw_event.get("tags", [])
|
|
bolt11 = ""
|
|
amount_msat = 0
|
|
zapped_pubkey = ""
|
|
zapped_event_id = ""
|
|
|
|
for tag in tags:
|
|
if not tag or len(tag) < 2:
|
|
continue
|
|
if tag[0] == "bolt11":
|
|
bolt11 = tag[1]
|
|
elif tag[0] == "amount":
|
|
try:
|
|
amount_msat = int(tag[1])
|
|
except (ValueError, IndexError):
|
|
pass
|
|
elif tag[0] == "p":
|
|
zapped_pubkey = tag[1]
|
|
elif tag[0] == "e":
|
|
zapped_event_id = tag[1]
|
|
|
|
return {
|
|
"event_id": raw_event.get("id", ""),
|
|
"sender_pubkey": raw_event.get("pubkey", ""),
|
|
"amount_msat": amount_msat,
|
|
"amount_sats": amount_msat // 1000 if amount_msat > 0 else 0,
|
|
"bolt11": bolt11,
|
|
"zapped_pubkey": zapped_pubkey,
|
|
"zapped_event_id": zapped_event_id,
|
|
}
|
|
|
|
def build_zap_request(self, receiver_pubkey: str, event_id: str = "", amount_msat: int = 0) -> dict | None:
|
|
tags = [["p", receiver_pubkey]]
|
|
if event_id:
|
|
tags.append(["e", event_id])
|
|
if amount_msat > 0:
|
|
tags.append(["amount", str(amount_msat)])
|
|
|
|
event = self._crypto.build_and_sign_event(kind=9734, content="", tags=tags)
|
|
return event
|
|
|
|
async def broadcast_zap_request(self, receiver_pubkey: str, event_id: str = "", amount_msat: int = 0) -> int:
|
|
event = self.build_zap_request(receiver_pubkey, event_id, amount_msat)
|
|
if event is None:
|
|
return 0
|
|
success_count = await self._relay_manager.broadcast(event)
|
|
logger.info(
|
|
"[NostrZap] Zap request sent: receiver=%s, amount=%s msat, relays=%s",
|
|
receiver_pubkey[:12],
|
|
amount_msat,
|
|
success_count,
|
|
)
|
|
return success_count
|