Add DVM module, process domain name requests

This commit is contained in:
Alex Gleason 2024-03-26 17:35:08 -05:00
parent e1bc55fcf4
commit 940fc7a305
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
2 changed files with 109 additions and 0 deletions

View File

@ -6,6 +6,7 @@ import { deleteAttachedMedia } from '@/db/unattached-media.ts';
import { Debug, LNURL, type NostrEvent } from '@/deps.ts';
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
import { isEphemeralKind } from '@/kinds.ts';
import { DVM } from '@/pipeline/DVM.ts';
import { getAuthor } from '@/queries.ts';
import { updateStats } from '@/stats.ts';
import { purifyEvent } from '@/storages/hydrate.ts';
@ -36,6 +37,7 @@ async function handleEvent(event: DittoEvent, signal: AbortSignal): Promise<void
storeEvent(event, signal),
parseMetadata(event, signal),
processDeletions(event, signal),
DVM.event(event),
trackRelays(event),
trackHashtags(event),
fetchRelatedEvents(event, signal),

107
src/pipeline/DVM.ts Normal file
View File

@ -0,0 +1,107 @@
import { NIP05, NostrEvent } from '@soapbox/nspec';
import { Conf } from '@/config.ts';
import * as pipeline from '@/pipeline.ts';
import { AdminSigner } from '@/signers/AdminSigner.ts';
import { eventsDB } from '@/storages.ts';
export class DVM {
static async event(event: NostrEvent): Promise<void> {
if (event.kind < 5000 || event.kind > 5999) {
throw new Error('Unsupported event kind');
}
switch (event.kind) {
case 5950:
await DVM.nameRegistration(event);
break;
}
}
static async nameRegistration(event: NostrEvent): Promise<void> {
const admin = await new AdminSigner().getPublicKey();
if (event.kind !== 5950 && event.pubkey !== admin) {
throw new Error('Only NIP-05 job requests are permitted');
}
const input = event.tags.find(([name]) => name === 'i')?.[1];
const tagged = !!event.tags.find(([name, value]) => name === 'p' && value === admin);
if (!input || !NIP05.regex().test(input)) {
return DVM.feedback(event, 'error', `Invalid name: ${input}`);
}
const [user, host] = input.split('@');
const nip05 = `${user}@${host}`;
if ((Conf.url.host !== host) && tagged) {
return DVM.feedback(event, 'error', `Unsupported domain: ${host}`);
}
if (user === '_') {
return DVM.feedback(event, 'error', `Forbidden user: ${user}`);
}
const [label] = await eventsDB.query([{
kinds: [1985],
authors: [admin],
'#L': ['nip05'],
'#l': [nip05],
}]);
if (label) {
return DVM.feedback(event, 'error', `Name already taken: ${nip05}`);
}
await DVM.label(nip05, event.pubkey);
await DVM.result(event, nip05);
}
static async feedback(
event: NostrEvent,
status: 'payment-required' | 'processing' | 'error' | 'success' | 'partial',
info = '',
): Promise<void> {
const feedback = await new AdminSigner().signEvent({
kind: 7000,
content: '',
tags: [
['status', status, info],
['e', event.id],
['p', event.pubkey],
],
created_at: Math.floor(Date.now() / 1000),
});
return pipeline.handleEvent(feedback, AbortSignal.timeout(1000));
}
static async label(nip05: string, pubkey: string): Promise<void> {
const label = await new AdminSigner().signEvent({
kind: 1985,
tags: [
['L', 'nip05'],
['l', nip05],
['p', pubkey],
],
content: '',
created_at: Math.floor(Date.now() / 1000),
});
return pipeline.handleEvent(label, AbortSignal.timeout(1000));
}
static async result(event: NostrEvent, nip05: string): Promise<void> {
const result = await new AdminSigner().signEvent({
kind: 6950,
content: nip05,
tags: [
['request', JSON.stringify(event)],
['i', nip05, 'text'],
['e', event.id],
['p', event.pubkey],
],
created_at: Math.floor(Date.now() / 1000),
});
return pipeline.handleEvent(result, AbortSignal.timeout(1000));
}
}