mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 03:19:46 +00:00
feat: endpoint for creating NIP-60 wallet
This commit is contained in:
parent
49735ce1fe
commit
d5ff66a542
2 changed files with 65 additions and 0 deletions
|
|
@ -43,6 +43,7 @@ import { captchaController, captchaVerifyController } from '@/controllers/api/ca
|
||||||
import {
|
import {
|
||||||
adminRelaysController,
|
adminRelaysController,
|
||||||
adminSetRelaysController,
|
adminSetRelaysController,
|
||||||
|
createCashuWalletController,
|
||||||
deleteZapSplitsController,
|
deleteZapSplitsController,
|
||||||
getZapSplitsController,
|
getZapSplitsController,
|
||||||
nameRequestController,
|
nameRequestController,
|
||||||
|
|
@ -400,6 +401,8 @@ app.delete('/api/v1/admin/ditto/zap_splits', requireRole('admin'), deleteZapSpli
|
||||||
app.post('/api/v1/ditto/zap', requireSigner, zapController);
|
app.post('/api/v1/ditto/zap', requireSigner, zapController);
|
||||||
app.get('/api/v1/ditto/statuses/:id{[0-9a-f]{64}}/zapped_by', zappedByController);
|
app.get('/api/v1/ditto/statuses/:id{[0-9a-f]{64}}/zapped_by', zappedByController);
|
||||||
|
|
||||||
|
app.post('/api/v1/ditto/wallet/create', requireSigner, createCashuWalletController);
|
||||||
|
|
||||||
app.post('/api/v1/reports', requireSigner, reportController);
|
app.post('/api/v1/reports', requireSigner, reportController);
|
||||||
app.get('/api/v1/admin/reports', requireSigner, requireRole('admin'), adminReportsController);
|
app.get('/api/v1/admin/reports', requireSigner, requireRole('admin'), adminReportsController);
|
||||||
app.get('/api/v1/admin/reports/:id{[0-9a-f]{64}}', requireSigner, requireRole('admin'), adminReportController);
|
app.get('/api/v1/admin/reports/:id{[0-9a-f]{64}}', requireSigner, requireRole('admin'), adminReportController);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { NostrEvent, NostrFilter, NSchema as n } from '@nostrify/nostrify';
|
import { NostrEvent, NostrFilter, NSchema as n } from '@nostrify/nostrify';
|
||||||
|
import { bytesToString } from '@scure/base';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
|
|
@ -19,6 +20,7 @@ import { accountFromPubkey } from '@/views/mastodon/accounts.ts';
|
||||||
import { renderAccount } from '@/views/mastodon/accounts.ts';
|
import { renderAccount } from '@/views/mastodon/accounts.ts';
|
||||||
import { Storages } from '@/storages.ts';
|
import { Storages } from '@/storages.ts';
|
||||||
import { updateListAdminEvent } from '@/utils/api.ts';
|
import { updateListAdminEvent } from '@/utils/api.ts';
|
||||||
|
import { generateSecretKey } from 'nostr-tools';
|
||||||
|
|
||||||
const markerSchema = z.enum(['read', 'write']);
|
const markerSchema = z.enum(['read', 'write']);
|
||||||
|
|
||||||
|
|
@ -342,3 +344,63 @@ export const updateInstanceController: AppController = async (c) => {
|
||||||
|
|
||||||
return c.json(204);
|
return c.json(204);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const createCashuWalletSchema = z.object({
|
||||||
|
description: z.string(),
|
||||||
|
relays: z.set(z.string().url()),
|
||||||
|
mints: z.set(z.string().url()).nonempty(), // must contain at least one item
|
||||||
|
name: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createCashuWalletController: AppController = async (c) => {
|
||||||
|
const signer = c.get('signer')!;
|
||||||
|
const store = c.get('store');
|
||||||
|
const pubkey = await signer.getPublicKey();
|
||||||
|
const body = await parseBody(c.req.raw);
|
||||||
|
const { signal } = c.req.raw;
|
||||||
|
const result = createCashuWalletSchema.safeParse(body);
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
return c.json({ error: 'Bad request', schema: result.error }, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
const event = await store.query([{ authors: [pubkey], kinds: [37375] }], { signal });
|
||||||
|
if (event) {
|
||||||
|
return c.json({ error: 'You already have a wallet 😏', schema: result.error }, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { description, relays, mints, name } = result.data;
|
||||||
|
relays.add(Conf.relay);
|
||||||
|
|
||||||
|
const tags: string[][] = [];
|
||||||
|
|
||||||
|
tags.push(['d', Math.random().toString(36).substring(3)]);
|
||||||
|
tags.push(['name', name]);
|
||||||
|
tags.push(['description', description]);
|
||||||
|
tags.push(['unit', 'sat']);
|
||||||
|
|
||||||
|
for (const mint of mints) {
|
||||||
|
tags.push(['mint', mint]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const relay of relays) {
|
||||||
|
tags.push(['relay', relay]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sk = generateSecretKey();
|
||||||
|
const privkey = bytesToString('hex', sk);
|
||||||
|
|
||||||
|
const contentTags = [
|
||||||
|
['privkey', privkey],
|
||||||
|
];
|
||||||
|
const encryptedContentTags = await signer.nip44?.encrypt(pubkey, JSON.stringify(contentTags));
|
||||||
|
|
||||||
|
// Wallet
|
||||||
|
await createEvent({
|
||||||
|
kind: 37375,
|
||||||
|
content: encryptedContentTags,
|
||||||
|
tags,
|
||||||
|
}, c);
|
||||||
|
|
||||||
|
return c.json(201);
|
||||||
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue