話題になりそうな Nostr 触ってみた
動機
つい先日 Damus という分散型SNSが出てきました。
どうやら、Nostrという新しいプロトコルを使ってるみたいなので、何かに使えないかととりあえず触ってみました。
私は普段 typescript を書いているので nostr-react, nostr-tools あたりがいいかなと。
とりあえずここら辺から触ってみようと思います。
現在では Starが34と少なめなため古参ぶるためにスクショ貼っておきます。
-
yarn create next-app --typescript nostr-test
で next プロジェクトの作成 -
cd nostr-test
で移動して -
yarn add nostr-react
で追加
NostrProvider
で Wrap する必要があるみたいです。
その際に Relay サーバーを1つ以上指定する必要もあるとのこと。
今回はチュートリアルに書いてあるものをそのまま使用しています。
import "@/styles/globals.css";
import type { AppProps } from "next/app";
import { NostrProvider } from "nostr-react";
const relayUrls = ["wss://nostr-pub.wellorder.net", "wss://relay.nostr.ch"];
export default function App({ Component, pageProps }: AppProps) {
return (
<NostrProvider relayUrls={relayUrls} debug={true}>
<Component {...pageProps} />
</NostrProvider>
);
}
適当なページを作成して、チュートリアルのコードを写経。
useNostrEvents
で Nostr を使って送信されたメッセージ (Event) を取得できるみたいです。
その際にフィルターをかけることができ、今回は
- 表示時以降に投稿
- kinds が 1 ???
のEventを持ってきている様です。
import { useRef } from "react";
import { useNostrEvents, dateToUnix } from "nostr-react";
const Test = () => {
const now = useRef(new Date()); // Make sure current time isn't re-rendered
const { events } = useNostrEvents({
filter: {
since: dateToUnix(now.current), // all new events from now
kinds: [1],
},
});
return (
<>
{events.map((event) => (
<p key={event.id}>
{event.pubkey} posted: {event.content}
</p>
))}
</>
);
};
export default Test;
kind はどうやら使用しているチャンネル見たいなものっぽいです。多分。
ドキュメントは探し中。。。
というかこんな簡単にEventの取得ができちゃうことにびっくりです。
Nostr はProfile なるものを設定できます。
といっても,名前とアイコン画像ぐらいではあります。
そのためのIDとして公開鍵が使用されています。
秘密鍵についてはパスワードとして使用されています。
ここら辺はDatum などを触ってみると実感できるかと
この公開鍵を使って Profile を取得できるみたいなんですが、どうもうまくいかないですね。
Datum で作成した時の公開鍵を使用するとError: hexToBytes: received invalid unpadded hex63
と怒られます。
どうやら文字列だとダメで16進数にしないといけないみたいです。
単純に文字列を16進数に変換して試してみるとErrorは出ませんが、ユーザ名等は表示されません...
どうやらその公開鍵のユーザはいないっぽいのですが、僕の公開鍵のはずなんですよね...
うーむ... とりあえず次に進みます。
Nostr Implementation Possibilities; NIP と呼ばれる実装上の注意点的なものがあるらしく,
どうやらNIP19にencode 方法について書かれていました。。。お恥ずかしい。
しかし、 Profile はうまく表示されない模様。。。
うむむ...
メッセージの送信は滞りなくできました。
ほぼチュートリアルのコピペですが、イベントを作成して Relay に送信するだけでOK。
1点注意なのが、Datum で得られる秘密鍵については、先ほどの NIP19 での decode が必要な点ですね。
import { useNostr, dateToUnix } from "nostr-react";
import {
type Event as NostrEvent,
getEventHash,
getPublicKey,
signEvent,
nip19,
} from "nostr-tools";
const PostButton = () => {
const { publish } = useNostr();
const onPost = async () => {
const privKey = prompt("Paste your private key:");
if (!privKey) {
alert("no private key provided");
return;
}
const message = prompt("Enter the message you want to send:");
if (!message) {
alert("no message provided");
return;
}
const { data: nsec } = nip19.decode(privKey);
const event: NostrEvent = {
content: message,
kind: 1,
tags: [],
created_at: dateToUnix(),
pubkey: getPublicKey(nsec.toString()),
};
event.id = getEventHash(event);
event.sig = signEvent(event, nsec.toString());
publish(event);
};
return <button onClick={onPost}>Post a message!</button>;
};
export default PostButton;