Why rx-nostr?
なぜ rx-nostr が必要なのか?それは短く言えば、NIP-01はシンプルであってもイージーではないからです。 rx-nostr は NIP-01 のプロトコルが持つすべての可能性を維持したまま、これを可能な限りイージーに取り扱うためのライブラリです。
より具体的に言えば、rx-nostr は REQ, EVENT, CLOSE, そして場合によっては AUTH を発行して、EVENT, OK, CLOSED を受け取るための通信クライアントです。 したがって例えば、誰かのフォローリストを取得したり、ステータスを更新したりといったアプリケーションレベルの操作を直接的に提供するものではありません。 代わりに、どんなペイロードをどこのリレーにどんな手順で送信するかといった通信レベルの操作をほとんど完全にコントロールすることができます。 この通信手順のコントロールは、アプリケーションの応答を開発者が直接最適化するために有用です。
Why NIP-01 is Not Easy?
しかし、一体 NIP-01 のどこがイージーではないというのでしょうか? 確かに仕様を一見すると、アプリケーションがすべきことは「REQ を送って EVENT を受け取り、EVENT を送って OK を受け取る」だけですから極めて単純な実装だけが求められているように思われます。 それならば標準的な WebSocket のクラスで十分そうです。 ところが実のところ、現実世界のアプリケーションでは次のような実装も求められます:
- 複数のリレーと通信する
- ただし、各リレーとの WebSocket 接続は1本までに抑える
- アプリケーションのリレー設定をユーザが変更した場合に、現在進行中の通信を再構成する
- 同時 REQ 数がリレーの制限を超過しないように必要に応じてキューイングする
- メッセージごとに通信先のリレーを指定する
- 必要であれば、OK を受け取ったあとに CLOSE する
- AUTH による認証を行う
- CLOSED をハンドルする
- リレーとの接続が意図せず切断されたとき、再接続を行った上で直前まで進行中だった通信を再構成する
- 再接続時には RFC によって推奨された方法で再接続する
- リレーから帰ってきたイベントが本当にフィルター条件に合致していることを検証する
- 期限切れのイベントを無視する
- 署名を検証する
rx-nostrはこれらすべてを透過的に処理します。 これによって、あなたがすべきことは本当に「REQ を送って EVENT を受け取り、EVENTを 送って OK を受け取る」だけになるのです。
Work with RxJS
REST のような一般的な Web API ではひとつの入力に対し、1つの非同期な出力が得られます。 これはほとんどの場合 Promise を返す非同期関数として抽象化されます。 しかし、Nostr の場合は1つ以上の非同期な入力に対して、1つ以上の非同期な出力がありえます。 これを単純な非同期関数として抽象化することはできません。 このような入出力を表現するのに最適なモデルのひとつが、RxJS が提供する Subject です。 実際、rx-nostr の中心的な API は一種の Subject として実装されています。
とは言っても、rx-nostr を利用するにあたって RxJS について知っておくことはまったく必須ではありません。 ただ、仮にあなたが RxJS に明るいならば、Operator の力を使うことによって、複雑な要件を宣言的にコード上で表現できるでしょう。