soapbox/src/api/hooks/nostr/useSignerStream.ts

90 wiersze
2.4 KiB
TypeScript
Czysty Zwykły widok Historia

import { type NostrEvent } from '@soapbox/nspec';
import { NiceRelay } from 'nostr-machina';
import { useEffect, useMemo } from 'react';
2023-08-27 04:24:18 +00:00
2024-02-11 18:40:14 +00:00
import { signer } from 'soapbox/features/nostr/sign';
2023-08-27 04:24:18 +00:00
import { useInstance } from 'soapbox/hooks';
import { connectRequestSchema, nwcRequestSchema } from 'soapbox/schemas/nostr';
2023-08-27 04:24:18 +00:00
import { jsonSchema } from 'soapbox/schemas/utils';
function useSignerStream() {
2023-09-24 01:41:24 +00:00
const instance = useInstance();
2023-08-27 04:24:18 +00:00
2023-09-24 01:41:24 +00:00
const relayUrl = instance.nostr?.relay;
const pubkey = instance.nostr?.pubkey;
2023-08-27 04:24:18 +00:00
const relay = useMemo(() => {
if (relayUrl && signer) {
return new NiceRelay(relayUrl);
}
}, [relayUrl, !!signer]);
async function handleConnectEvent(event: NostrEvent) {
if (!relay || !pubkey || !signer) return;
2024-02-11 18:40:14 +00:00
const decrypted = await signer.nip04!.decrypt(pubkey, event.content);
const reqMsg = jsonSchema.pipe(connectRequestSchema).safeParse(decrypted);
if (!reqMsg.success) {
console.warn(decrypted);
console.warn(reqMsg.error);
return;
}
const respMsg = {
id: reqMsg.data.id,
2024-02-11 18:40:14 +00:00
result: await signer.signEvent(reqMsg.data.params[0]),
};
2024-02-11 18:40:14 +00:00
const respEvent = await signer.signEvent({
kind: 24133,
2024-02-11 18:40:14 +00:00
content: await signer.nip04!.encrypt(pubkey, JSON.stringify(respMsg)),
tags: [['p', pubkey]],
created_at: Math.floor(Date.now() / 1000),
});
relay.send(['EVENT', respEvent]);
}
async function handleWalletEvent(event: NostrEvent) {
if (!relay || !pubkey || !signer) return;
2024-02-11 18:40:14 +00:00
const decrypted = await signer.nip04!.decrypt(pubkey, event.content);
const reqMsg = jsonSchema.pipe(nwcRequestSchema).safeParse(decrypted);
if (!reqMsg.success) {
console.warn(decrypted);
console.warn(reqMsg.error);
return;
}
await window.webln?.enable();
await window.webln?.sendPayment(reqMsg.data.params.invoice);
}
useEffect(() => {
if (!relay || !pubkey) return;
const sub = relay.req([{ kinds: [24133, 23194], authors: [pubkey], limit: 0 }]);
const readEvents = async () => {
for await (const event of sub) {
switch (event.kind) {
case 24133:
await handleConnectEvent(event);
break;
case 23194:
await handleWalletEvent(event);
break;
}
}
};
readEvents();
2023-08-27 04:24:18 +00:00
return () => {
relay?.close();
};
}, [relay, pubkey]);
2023-08-27 04:24:18 +00:00
}
export { useSignerStream };