Merge branch 'nip46-full' into 'main'
Support the full NIP-46 protocol See merge request soapbox-pub/soapbox!3009
This commit is contained in:
commit
1cd41450ee
2 changed files with 80 additions and 15 deletions
|
@ -5,9 +5,32 @@ import { useNostr } from 'soapbox/contexts/nostr-context';
|
||||||
import { connectRequestSchema, nwcRequestSchema } from 'soapbox/schemas/nostr';
|
import { connectRequestSchema, nwcRequestSchema } from 'soapbox/schemas/nostr';
|
||||||
import { jsonSchema } from 'soapbox/schemas/utils';
|
import { jsonSchema } from 'soapbox/schemas/utils';
|
||||||
|
|
||||||
|
/** NIP-46 [response](https://github.com/nostr-protocol/nips/blob/master/46.md#response-events-kind24133) content. */
|
||||||
|
interface NostrConnectResponse {
|
||||||
|
/** Request ID that this response is for. */
|
||||||
|
id: string;
|
||||||
|
/** Result of the call (this can be either a string or a JSON stringified object) */
|
||||||
|
result: string;
|
||||||
|
/** Error in string form, if any. Its presence indicates an error with the request. */
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
function useSignerStream() {
|
function useSignerStream() {
|
||||||
const { relay, pubkey, signer } = useNostr();
|
const { relay, pubkey, signer } = useNostr();
|
||||||
|
|
||||||
|
async function sendConnect(response: NostrConnectResponse) {
|
||||||
|
if (!relay || !pubkey || !signer) return;
|
||||||
|
|
||||||
|
const event = await signer.signEvent({
|
||||||
|
kind: 24133,
|
||||||
|
content: await signer.nip04!.encrypt(pubkey, JSON.stringify(response)),
|
||||||
|
tags: [['p', pubkey]],
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
});
|
||||||
|
|
||||||
|
relay.event(event);
|
||||||
|
}
|
||||||
|
|
||||||
async function handleConnectEvent(event: NostrEvent) {
|
async function handleConnectEvent(event: NostrEvent) {
|
||||||
if (!relay || !pubkey || !signer) return;
|
if (!relay || !pubkey || !signer) return;
|
||||||
const decrypted = await signer.nip04!.decrypt(pubkey, event.content);
|
const decrypted = await signer.nip04!.decrypt(pubkey, event.content);
|
||||||
|
@ -19,19 +42,61 @@ function useSignerStream() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const respMsg = {
|
const request = reqMsg.data;
|
||||||
id: reqMsg.data.id,
|
|
||||||
result: JSON.stringify(await signer.signEvent(JSON.parse(reqMsg.data.params[0]))),
|
|
||||||
};
|
|
||||||
|
|
||||||
const respEvent = await signer.signEvent({
|
switch (request.method) {
|
||||||
kind: 24133,
|
case 'connect':
|
||||||
content: await signer.nip04!.encrypt(pubkey, JSON.stringify(respMsg)),
|
return sendConnect({
|
||||||
tags: [['p', pubkey]],
|
id: request.id,
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
result: 'ack',
|
||||||
});
|
});
|
||||||
|
case 'sign_event':
|
||||||
relay.event(respEvent);
|
return sendConnect({
|
||||||
|
id: request.id,
|
||||||
|
result: JSON.stringify(await signer.signEvent(JSON.parse(request.params[0]))),
|
||||||
|
});
|
||||||
|
case 'ping':
|
||||||
|
return sendConnect({
|
||||||
|
id: request.id,
|
||||||
|
result: 'pong',
|
||||||
|
});
|
||||||
|
case 'get_relays':
|
||||||
|
return sendConnect({
|
||||||
|
id: request.id,
|
||||||
|
result: JSON.stringify(await signer.getRelays?.() ?? []),
|
||||||
|
});
|
||||||
|
case 'get_public_key':
|
||||||
|
return sendConnect({
|
||||||
|
id: request.id,
|
||||||
|
result: await signer.getPublicKey(),
|
||||||
|
});
|
||||||
|
case 'nip04_encrypt':
|
||||||
|
return sendConnect({
|
||||||
|
id: request.id,
|
||||||
|
result: await signer.nip04!.encrypt(request.params[0], request.params[1]),
|
||||||
|
});
|
||||||
|
case 'nip04_decrypt':
|
||||||
|
return sendConnect({
|
||||||
|
id: request.id,
|
||||||
|
result: await signer.nip04!.decrypt(request.params[0], request.params[1]),
|
||||||
|
});
|
||||||
|
case 'nip44_encrypt':
|
||||||
|
return sendConnect({
|
||||||
|
id: request.id,
|
||||||
|
result: await signer.nip44!.encrypt(request.params[0], request.params[1]),
|
||||||
|
});
|
||||||
|
case 'nip44_decrypt':
|
||||||
|
return sendConnect({
|
||||||
|
id: request.id,
|
||||||
|
result: await signer.nip44!.decrypt(request.params[0], request.params[1]),
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
return sendConnect({
|
||||||
|
id: request.id,
|
||||||
|
result: '',
|
||||||
|
error: `Unrecognized method: ${request.method}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleWalletEvent(event: NostrEvent) {
|
async function handleWalletEvent(event: NostrEvent) {
|
||||||
|
|
|
@ -24,11 +24,11 @@ const eventSchema = eventTemplateSchema.extend({
|
||||||
/** Nostr event schema that also verifies the event's signature. */
|
/** Nostr event schema that also verifies the event's signature. */
|
||||||
const signedEventSchema = eventSchema.refine(verifyEvent);
|
const signedEventSchema = eventSchema.refine(verifyEvent);
|
||||||
|
|
||||||
/** NIP-46 signer request. */
|
/** NIP-46 request content schema. */
|
||||||
const connectRequestSchema = z.object({
|
const connectRequestSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
method: z.literal('sign_event'),
|
method: z.string(),
|
||||||
params: z.tuple([z.string()]),
|
params: z.string().array(),
|
||||||
});
|
});
|
||||||
|
|
||||||
/** NIP-47 signer response. */
|
/** NIP-47 signer response. */
|
||||||
|
|
Loading…
Reference in a new issue