作者:d-central.tech

来源:https://d-central.tech/nostr-wallet-connect-guide/

“Nostr Wallet Connect(NWC)”是一套开放的协议,由 NIP-47 定义,它让任何 app 都能通过交换加密的消息来控制一个闪电钱包 —— 不需要托管商的 API 密钥、不需要登录交易所,也不需要交出你的资金控制权。钱包服务端和客户端 app 各自持有自己的 secp256k1 密钥对,通过一个彼此都知晓的 Nostr relay 来通话:app 要求 “支付这张发票” 或者询问 “我有多少余额”,然后你的钱包软件就回答,节点和资金都没有脱离你的控制。因为每一个连接都是独一无二的、可以撤销的,有自己的花费预算和权限集合,你可以给一个 Nostr 客户端、账单页面或自动化的脚本安排或宽或窄的访问你的钱包的权限,而不必暴露你的私钥。

NWC 解决的问题

很长一段时间以来,对于闪电钱包来说,让一个 app 能够从你的钱包花费,意味着在两种糟糕的选择中二选一。要么,你建立一个托管账户,然后把一个 API 密钥交给这个 app(服务商拿着你的钱,而这个密钥可以移动这些资金);要么,你要手动为每一笔支付 复制-粘贴 发票或者 QR 码。没有哪一种选择适合人们实际使用 Nostr(以及闪电钱包)的场景,也就是 “Zap” —— 小额的闪电网络打赏,它需要能在社交信息流中以零点几秒触发。

NWC 最初由 Alby 团队以及广大的 Nostr 开发者社区提出,在 NIP-47 中标准化。它定义了一种共同的语言,从而一个客户端 app 可以驱使一个自身并不控制的钱包,并且依靠的是两端都无需私密运行的基础设施,而钱包主人可以提前设置访问限制。这塑造了一种便捷的连接方式,可以在数十款 app 和钱包软件上工作 —— 只需设置一次,然后你的 zap、结账和自动化都能跑起来,而你的私钥从未离开你的钱包。这跟自己持有比特币签名设备所代表的自治精神是一样的:使用你喜欢的工具,但私钥必须掌握在自己手里。

NWC 的架构

NWC 协议中有两种角色。钱包服务端,指的是实际持有资金并且可以移动资金(聪)的软件,比如说一个自己运营的节点,或者一个托管式钱包。客户端则是希望请求行动的 app —— 比如一个 Nostr 社交网络客户端,一个网上商铺,或者一个脚本。两边都有自己的 Nostr 密钥对(标准的 secp256k1 密钥,跟比特币密钥一样), 并且双方绝不分享这个私钥。他们完全是通过加密的 Nostr 事件来沟通的,而这些 Nostr 事件则通过一个或多个双方都连接了的中继服务(relay)来转发。

NWC 协议用到了以下四种事件类型:

  • Kind 13194 —— info 事件。 这是一种可以替换的事件,钱包服务端用来广告自己支持哪些指令和通知,以及接受哪种加密方案。
  • Kind 23194 —— 请求。 客户端发送的一种加密事件,指定一种方法(比如 pay_invoice 支付发票)及其参数。
  • Kind 23195 —— 响应。钱包服务端解密请求,检查这个连接是否有授权、请求金额是否在预算之内,然后执行动作,并回复以一个结果或故障代码。
  • Kind 23197 —— 通知。(在传统方法中是 kind 23196),让钱包可以推送 “收到支付” 这样的消息给客户端。

消息的内容是加密的。NIP-47 倾向于使用 NIP-44(版本2)加密方案,仅仅是为后向兼容性而保留旧的 NIP-04 方案; ifo 事件就包含了一个 encryption 标签,列出了钱包服务端支持的方案。如果你想深入了解这些砖块是怎么砌在一起的,请看 Nostr NIP 参考

连接口令

要连接你的钱包,app 所需的一切信息都可以放到一个使用 nostr+walletconnect:// 前缀的 URI 中。其中的 host 是钱包服务端的公钥,然后是查询参数:

  • relay —— 钱包服务端正在监听的一个 relay 的 URL(比如说 wss://relay.example.com)。你可以指定多个 relay 。
  • secret —— 一个 32 字节的、随机生成的、16 进制编码的字符串。这就是客户端要用在这个连接中的私钥;客户端要用它来签名和加密请求。
  • lud16(可选的)—— 一个 Lightning address ,一些钱包软件会用它来预填充详细信息。

因此,一个连接口令看起来就是这样的:nostr+walletconnect://?relay=wss%3A%2F%2Frelay.example.com&secret=<32-byte-hex> 。这个 secret 秘密值就像一个口令:任何人只要得到了它就能向你的钱包发送请求,只要请求内容在你设定的预算和许可范围内(你的钱包就会执行)。这个关键设计抉择意味着,每一个 app 都要有 单独的 连接口令。绝对不应该在多个 app 中使用同一个秘密值,这样你只需要删除一个连接就能撤销一个 app 的权限,而不需要重置你的钱包。

指令

NIP-47 定义了一个紧凑的方法集。钱包可以在 info 事件中广告自己支持的方法集,NWC 连接将只能调用你保证了的方法。

命令含义
pay_invoice支付一个 BOLT-11 闪电发票。
multi_pay_invoice在一个请求中支付多个发票。
pay_keysend发送一笔 keysend 支付到某个节点,不需要提供发票。
make_invoice创建一个新的闪电发票以收取一笔支付。
lookup_invoice通过哈希值或字符串来检索一个发票(或者说一笔支付)的状态和细节。
list_transactions列出过往的发票和支付,并且可以过滤和分页。
get_balance返回钱包的余额,以 “微聪” 为单位。
get_info返回节点信息和钱包服务端所支持的方法和通知。

协议规范还包含了 “暂缓兑付(hold-invoice)” 方法(make_hold_invoicesettle_hold_invoicecancel_hold_invoice)以支持更高级的支付特性,以及可选的通知:payment_receivedpayment_sent 以及 hold_invoice_accepted。当遇上障碍的时候,钱包服务端会返回一条结构化的报错消息,比如 INSUFFICIENT_BALANCE(余额不足)、QUOTA_EXCEEDED(超过配额)、RESTRICTEDNAUTHORIZED(这个连接缺乏相应许可)、RATE_LIMITED(触发支出速率限制)、PAYMENT_FAILED(支付失败),还有 NOT_FOUND(未发现支付路径)—— 这样客户端就能针对性地作出反应,而不是瞎猜。

许可与预算

在第三方 app 上使用 NWC 是安全的,因为它可以为每一个连接单独设置权限。每一个连接都有一个单独的密钥,带有 “按钱包主人想要的任何限制”,比如:

  • 允许使用的方法清单 —— 比如,可以通过 get_balancelist_transactions 获得仪表板,但是不能支付。
  • 支出预算 —— 支付的最大限额,通常有刷新窗口(每日刷新、周更、月度刷新,或者年度刷新)。一旦一个连接用尽其预算,进一步的支出就会返回 QUOTA_EXCEEDED,直到额度刷新。
  • 过期日期 —— 这个时间点之后,这个连接将停止工作。
  • 通知许可 —— app 可以收到才通知类型。

如果 app 行为不轨,或者被劫持了,你可以直接停止使用它、删掉安排给它的连接。你的钱包、其它 app 和资金,都是安全的。这种撤销能力是 NWC 信任模型的核心。

自主保管与托管的钱包服务

NWC 无法让托管式钱包变成非托管钱包,也无法让自主运营的节点变成代运营的节点 —— 它只是一个控制层协议,假设在你指定的钱包装置之上。 钱包

方法Who holds the funds例子取舍
自主运营的节点你 —— 你自己的闪电节点Alby Hub(嵌入了 LDK,或者 LND/Core Lightning/Phoenixd 后台)、搭配 LND 和 CLN 的单独 NWC app完全自治;你运行和维护一个节点及其通道。
托管式钱包服务商Coinos、Primal Wallet更容易上手;你信任服务商会保管好你的钱。
Ecash 钱包铸币厂(托管式的),通过 Cashu Wallet Connect 协议Cashu.me、Minibits在用户之间快速且私密地转账;铸币厂依然可以审查或拒绝服务。

对于 “想要使用 app 但希望自己持有私钥” 的人来说,Alby Hub 是一个常见的起点:它可以运行在桌面系统(macOS、Windows、Linux)上、通过 Docker 运行在服务器上、或者一个云主机上;它有一个内置的 LDK 节点,或者,可以连接你已有的 LND 节点或 Core Lightning、Phoenixd 节点。从它的仪表板上,你可以生成 NWC 连接口令、为每一个连接设定方法清单、预算、刷新时间,以及过期日期。UmbrelStart9 这样的自主运营平台可以帮你运行一个闪电节点以及搭建 NWC 服务端。 至于搭配 ecash 的用法 —— 使用 Cashu Wallet Connect —— 我放在《Cashu 和 Fedimint 指南》里面了(中文译本)。

支持 NWC 的 app 和钱包软件

NWC 的效用会随着采用它的项目增加而不断增加,这里就提供一个由社区维护的公开清单。在钱包服务端实现上,你可以找到 Alby Hub(Alby 的浏览器插件)以及 Alby Go、Coinos、Primal Wallet、LNbits(通过其 NWC 插件),以及 ecash 钱包 Cashu.me 和 Minibits 。Zeus 钱包既添加了 NWC 客户端实现,又添加了钱包服务端实现,所以一个自主运营的 Zeus 节点可以帮你的社交媒体应用打赏。在客户端实现上,诸多 Nostr 应用,比如 Amethyst、Damus、Primal、Snort、noStrudel 和 Nostur,都允许你通过 NWC 来附加一个钱包;此外还有 Zapple Pay、Zap Planner、Zap Stream 和 Wavlake 这样的应用。两种 SDK 让开发者的集成工作变得很简单:JavaScript 语言的 Alby(getalby/sdk) ,以及 Nostr 库中的 Rust 实现。因为这些信息经常更新,在你开始使用之前,请手动确认一款 app 的最新情况。

应用场景

  • Zap。一个重要的应用场景 —— 从一个 Nostr 客户端直接给一个帖子或者作者打赏,用你自己的钱包来支付,还能设置每日限额。
  • 电子商务支付。一家网上的商店可以在 app 内让你的钱包支付,不需要你扫 QR 码,也无需跳转应用。
  • 自动化和 DVM 。脚本和 Nostr DVM 协议可以在受限的许可内,按需付费获得计算服务或数据,这样一个日常运行的程序就不会吸干你的钱包。
  • 仅供视察的仪表盘。让一个监控 app 只能看到资金的流动,而没有花费的权限。

这种可组合性,正是广大的电子化自治工具箱所围绕的免许可的互操作性的体现 —— 而它跟自治的传输层天然可以结合(我们在《Reticulum network 指南》中有所介绍)。

安全性、信任模式及其局限性。

NWC 是真的强大,也也有局限,我们两方面都要搞清楚。好的一面:你的钱包的主私钥从未离开钱包;每个 app 都只持有一个受到限制的、有预算约束的、可以撤销权限的密钥;并且通信内容是使用 NIP-44 端到端加密的。钱包服务端自身是最终的权威 —— 它会根据各个连接的权限,独立检查每一个请求,然后再执行动作。

其局限性是:一个口令秘密值就是一个能够转移限额内金额的不记名权威,所以任何人只要得到了它,都能支出限额以内的资金,直到你撤销这个秘密值的权限 —— 所以,要谨慎设置预算、设置较短的有效期。此外,Relay 可以看到两个密钥在交换加密的 NWC 事件,并且可以观察到通信时机和元信息,虽然 TA 无法读取内容;运行自己的 relay、谨慎挑选 relay,可以降低风险。然哈,NWC 不会改变与之搭配的钱包的保管模式:连接一个托管服务,意味着依然是服务商控制着你的资金。谨慎地使用 —— 自主运营的节点、较低的预算、每个 app 使用专门的秘密值、运行自己的 relay —— NWC 将让你既能获得第三方 app 的便利,又能可靠地持有私钥。你可以在我们的公开数据中心看到生态系统底层的数据和相关工具。

常见问题

NWC 是托管的吗?

NWC 自身谈不上托管或者非托管 —— 它是一种控制协议。资金保管模式完全取决于你使用的钱包本身。如果连接的是你自己运营的节点(比如说通过 Alby Hub 运行 LDK、LND 或 Core Lightning),你就是完全自主保管的。如果连接的是一个代运营服务,比如 Coinos 或 Primal Wallet,那就是服务商保管你的资金。

我需要一个 Nostr 账户来使用 NWC 吗?

不需要。NWC 利用 Nostr relay 和事件格式来传输信息,但连接是使用一个专门为此生成的密钥对来建立的。你无需创建,也无需关联一个 Nostr 社交身份,不影响你使用 app 连接钱包的能力,虽然许多人使用 NWC 就是为了在 Nostr 客户端内给别人打赏。

我如何限制一个 app 可以花多少钱?

在你的钱包服务端中创建一个连接口令的时候,你可以设置预算 —— 就是一个限额,通常可以带上一个刷新周期,比如每日、每周或每个月 —— 并且你可以选择这个连接可以调用哪些方法。一旦超过预算,钱包服务端就会返回 QUOTA_EXCEEDED 错误,并拒绝进一步支付,直到刷新。你还可以设置一个过期日期,以及手动随时作废一个连接。

如果一个得到连接的 app 被劫持了,会怎么样?

首先,影响会限制在其连接的预算范围内,你的钱包主私钥永远不会暴露,因为每一个 app 都只持有自己那个受限制的秘密值。你可以在钱包中作废这个被劫持的 app 的秘密值,这会立即切断连接;并且,你的其它 app 和你的资金本身不会受到影响。这也是为什么建议的习惯是为每个 app 专设一个连接,并设置较少的预算和较短的有效期。

今天有哪些钱包和 app 支持 NQC ?

在钱包这一边,Alby Hub、Coinos、Zeus、Primal Wallet、LNbits,还有 ecash 钱包 Cashu.me 和 Minibits ,都支持 NWC 。想要搭配自主运营的节点,可以选择 LND、Core Lightning 和 Phoenixd 节点。

在 app 这一边, Amethyst、Damus、Primal、Snort 和 noStrudel 这些 Nostr 客户端都支持 NWC,还有 Zapple Pay 和 Zap Planner 这样的工具可以作为 NWC 客户端。这个领域在快速发展,所以在使用之前还是得自己检查一下最新状况。

NWC 与 Lightning API 密钥(LNDhub 或 LNbits 密钥)有何不同?

传统的 API 密钥通常是一个长期有效的证书,对应一个具体的服务端,通常带有宽泛的权限。NWC 与此不同,它为每一个连接发行一个独一无二的、可撤销的密钥对,通过 Nostr relay 而非私有网络端点来传输消息;还可以为每个连接设置单独的预算、方法许可以及过期时间。其实际效果是更精细、更便携的控制,在诸多钱包和 app 上都可以使用。

(完)