Partially implement NIP-47 and pay for zaps with WebLN

This commit is contained in:
Alex Gleason 2024-01-16 18:35:00 -06:00
parent d20d08bc8f
commit 459bc72365
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
2 changed files with 63 additions and 25 deletions

View file

@ -1,9 +1,10 @@
import { NiceRelay } from 'nostr-machina';
import { type Event } from 'nostr-tools';
import { useEffect, useMemo } from 'react';
import { nip04, signEvent } from 'soapbox/features/nostr/sign';
import { useInstance } from 'soapbox/hooks';
import { connectRequestSchema } from 'soapbox/schemas/nostr';
import { connectRequestSchema, nwcRequestSchema } from 'soapbox/schemas/nostr';
import { jsonSchema } from 'soapbox/schemas/utils';
function useSignerStream() {
@ -18,35 +19,64 @@ function useSignerStream() {
}
}, [relayUrl]);
useEffect(() => {
async function handleConnectEvent(event: Event) {
if (!relay || !pubkey) return;
const decrypted = await 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,
result: await signEvent(reqMsg.data.params[0], reqMsg.data.params[1]),
};
const respEvent = await signEvent({
kind: 24133,
content: await nip04.encrypt(pubkey, JSON.stringify(respMsg)),
tags: [['p', pubkey]],
created_at: Math.floor(Date.now() / 1000),
});
relay.send(['EVENT', respEvent]);
}
async function handleWalletEvent(event: Event) {
if (!relay || !pubkey) return;
const sub = relay.req([{ kinds: [24133], authors: [pubkey], limit: 0 }]);
const decrypted = await nip04.decrypt(pubkey, event.content);
const reqMsg = jsonSchema.pipe(nwcRequestSchema).safeParse(decrypted);
if (!reqMsg.success) {
console.warn(decrypted);
console.warn(reqMsg.error);
return;
}
// @ts-ignore
await window.webln?.enable();
// @ts-ignore
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) {
const decrypted = await nip04.decrypt(pubkey, event.content);
const reqMsg = jsonSchema.pipe(connectRequestSchema).safeParse(decrypted);
if (!reqMsg.success) {
console.warn(decrypted);
console.warn(reqMsg.error);
return;
switch (event.kind) {
case 24133:
await handleConnectEvent(event);
break;
case 23194:
await handleWalletEvent(event);
break;
}
const respMsg = {
id: reqMsg.data.id,
result: await signEvent(reqMsg.data.params[0], reqMsg.data.params[1]),
};
const respEvent = await signEvent({
kind: 24133,
content: await nip04.encrypt(pubkey, JSON.stringify(respMsg)),
tags: [['p', pubkey]],
created_at: Math.floor(Date.now() / 1000),
});
relay.send(['EVENT', respEvent]);
}
};

View file

@ -36,4 +36,12 @@ const connectRequestSchema = z.object({
params: z.tuple([eventTemplateSchema]).or(z.tuple([eventTemplateSchema, signEventOptsSchema])),
});
export { nostrIdSchema, kindSchema, eventSchema, signedEventSchema, connectRequestSchema };
/** NIP-47 signer response. */
const nwcRequestSchema = z.object({
method: z.literal('pay_invoice'),
params: z.object({
invoice: z.string(),
}),
});
export { nostrIdSchema, kindSchema, eventSchema, signedEventSchema, connectRequestSchema, nwcRequestSchema };