mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 03:19:46 +00:00
feat: allow to edit the wallet mints and relays (with tests updated)
This commit is contained in:
parent
7c1297e865
commit
feff31f094
2 changed files with 91 additions and 19 deletions
|
|
@ -35,6 +35,9 @@ Deno.test('PUT /wallet must be successful', async () => {
|
|||
'https://houston.mint.com', // duplicate on purpose
|
||||
'https://cuiaba.mint.com',
|
||||
],
|
||||
relays: [
|
||||
'wss://manager.com/relay',
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
|
|
@ -65,7 +68,7 @@ Deno.test('PUT /wallet must be successful', async () => {
|
|||
'https://cuiaba.mint.com',
|
||||
]);
|
||||
assertEquals(data.relays, [
|
||||
'ws://localhost:4036/relay',
|
||||
'wss://manager.com/relay',
|
||||
]);
|
||||
assertEquals(data.balance, 0);
|
||||
|
||||
|
|
@ -79,7 +82,7 @@ Deno.test('PUT /wallet must be successful', async () => {
|
|||
|
||||
assertEquals(nutzap_p2pk, p2pk);
|
||||
assertEquals([nutzap_info.tags.find(([name]) => name === 'relay')?.[1]!], [
|
||||
'ws://localhost:4036/relay',
|
||||
'wss://manager.com/relay',
|
||||
]);
|
||||
|
||||
mock.restore();
|
||||
|
|
@ -111,31 +114,87 @@ Deno.test('PUT /wallet must NOT be successful: wrong request body/schema', async
|
|||
mock.restore();
|
||||
});
|
||||
|
||||
Deno.test('PUT /wallet must NOT be successful: wallet already exists', async () => {
|
||||
Deno.test('PUT /wallet must be successful: edit wallet', async () => {
|
||||
const mock = stub(globalThis, 'fetch', () => {
|
||||
return Promise.resolve(new Response());
|
||||
});
|
||||
|
||||
await using test = await createTestRoute();
|
||||
const { route, sk, relay } = test;
|
||||
const { route, sk, relay, signer } = test;
|
||||
|
||||
await relay.event(genEvent({ kind: 17375 }, sk));
|
||||
const pubkey = await signer.getPublicKey();
|
||||
const privkey = bytesToString('hex', generateSecretKey());
|
||||
const p2pk = getPublicKey(stringToBytes('hex', privkey));
|
||||
|
||||
// Wallet
|
||||
await relay.event(genEvent({
|
||||
kind: 17375,
|
||||
content: await signer.nip44.encrypt(
|
||||
pubkey,
|
||||
JSON.stringify([
|
||||
['privkey', privkey],
|
||||
['mint', 'https://mint.soul.com'],
|
||||
]),
|
||||
),
|
||||
}, sk));
|
||||
|
||||
// Nutzap information
|
||||
await relay.event(genEvent({
|
||||
kind: 10019,
|
||||
tags: [
|
||||
['pubkey', p2pk],
|
||||
['mint', 'https://mint.soul.com'],
|
||||
['relay', 'ws://localhost:4036/relay'],
|
||||
],
|
||||
}, sk));
|
||||
|
||||
const response = await route.request('/wallet', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'authorization': `Bearer ${nip19.nsecEncode(sk)}`,
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
mints: ['https://mint.heart.com'],
|
||||
mints: [
|
||||
'https://new-vampire-mint.com',
|
||||
'https://new-age-mint.com',
|
||||
],
|
||||
relays: [
|
||||
'wss://law-of-the-universe/relay',
|
||||
'wss://law-of-the-universe/relay',
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
const body2 = await response.json();
|
||||
const body = await response.json();
|
||||
|
||||
assertEquals(response.status, 400);
|
||||
assertEquals(body2, { error: 'You already have a wallet 😏' });
|
||||
const data = walletSchema.parse(body);
|
||||
|
||||
assertEquals(response.status, 200);
|
||||
|
||||
assertEquals(bytesToString('hex', sk) !== privkey, true);
|
||||
|
||||
assertEquals(data.pubkey_p2pk, p2pk);
|
||||
assertEquals(data.mints, [
|
||||
'https://new-vampire-mint.com',
|
||||
'https://new-age-mint.com',
|
||||
]);
|
||||
assertEquals(data.relays, [
|
||||
'wss://law-of-the-universe/relay',
|
||||
]);
|
||||
assertEquals(data.balance, 0);
|
||||
|
||||
const [nutzap_info] = await relay.query([{ authors: [pubkey], kinds: [10019] }]);
|
||||
|
||||
assertExists(nutzap_info);
|
||||
assertEquals(nutzap_info.kind, 10019);
|
||||
assertEquals(nutzap_info.tags.length, 4);
|
||||
|
||||
const nutzap_p2pk = nutzap_info.tags.find(([value]) => value === 'pubkey')?.[1]!;
|
||||
|
||||
assertEquals(nutzap_p2pk, p2pk);
|
||||
assertEquals([nutzap_info.tags.find(([name]) => name === 'relay')?.[1]!], [
|
||||
'wss://law-of-the-universe/relay',
|
||||
]);
|
||||
|
||||
mock.restore();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { userMiddleware } from '@ditto/mastoapi/middleware';
|
|||
import { DittoRoute } from '@ditto/mastoapi/router';
|
||||
import { generateSecretKey, getPublicKey } from 'nostr-tools';
|
||||
import { NostrEvent, NSchema as n } from '@nostrify/nostrify';
|
||||
import { bytesToString } from '@scure/base';
|
||||
import { bytesToString, stringToBytes } from '@scure/base';
|
||||
import { logi } from '@soapbox/logi';
|
||||
import { z } from 'zod';
|
||||
|
||||
|
|
@ -159,6 +159,9 @@ const createWalletSchema = z.object({
|
|||
mints: z.array(z.string().url()).nonempty().transform((val) => {
|
||||
return [...new Set(val)];
|
||||
}),
|
||||
relays: z.array(z.string().url()).transform((val) => {
|
||||
return [...new Set(val)];
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
@ -167,7 +170,7 @@ const createWalletSchema = z.object({
|
|||
* https://github.com/nostr-protocol/nips/blob/master/61.md#nutzap-informational-event
|
||||
*/
|
||||
route.put('/wallet', userMiddleware({ enc: 'nip44' }), async (c) => {
|
||||
const { conf, user, relay, signal } = c.var;
|
||||
const { user, relay, signal } = c.var;
|
||||
|
||||
const pubkey = await user.signer.getPublicKey();
|
||||
const body = await parseBody(c.req.raw);
|
||||
|
|
@ -177,18 +180,28 @@ route.put('/wallet', userMiddleware({ enc: 'nip44' }), async (c) => {
|
|||
return c.json({ error: 'Bad schema', schema: result.error }, 400);
|
||||
}
|
||||
|
||||
const { mints } = result.data;
|
||||
const { mints, relays } = result.data;
|
||||
let previousPrivkey: string | undefined;
|
||||
|
||||
const [event] = await relay.query([{ authors: [pubkey], kinds: [17375] }], { signal });
|
||||
if (event) {
|
||||
return c.json({ error: 'You already have a wallet 😏' }, 400);
|
||||
const walletContentSchema = z.string().array().min(2).array();
|
||||
|
||||
const { data: walletContent, success, error } = n.json().pipe(walletContentSchema).safeParse(
|
||||
await user.signer.nip44.decrypt(pubkey, event.content),
|
||||
);
|
||||
|
||||
if (!success) {
|
||||
return c.json({ error: 'Your wallet is in an invalid format', schema: error }, 400);
|
||||
}
|
||||
|
||||
previousPrivkey = walletContent.find(([name]) => name === 'privkey')?.[1];
|
||||
}
|
||||
|
||||
const walletContentTags: string[][] = [];
|
||||
|
||||
const sk = generateSecretKey();
|
||||
const privkey = bytesToString('hex', sk);
|
||||
const p2pk = getPublicKey(sk);
|
||||
const privkey = previousPrivkey ?? bytesToString('hex', generateSecretKey());
|
||||
const p2pk = getPublicKey(stringToBytes('hex', privkey));
|
||||
|
||||
walletContentTags.push(['privkey', privkey]);
|
||||
|
||||
|
|
@ -209,7 +222,7 @@ route.put('/wallet', userMiddleware({ enc: 'nip44' }), async (c) => {
|
|||
kind: 10019,
|
||||
tags: [
|
||||
...mints.map((mint) => ['mint', mint, 'sat']),
|
||||
['relay', conf.relay], // TODO: add more relays once things get more stable
|
||||
...relays.map((relay) => ['relay', relay]),
|
||||
['pubkey', p2pk],
|
||||
],
|
||||
}, c);
|
||||
|
|
@ -218,7 +231,7 @@ route.put('/wallet', userMiddleware({ enc: 'nip44' }), async (c) => {
|
|||
const walletEntity: Wallet = {
|
||||
pubkey_p2pk: p2pk,
|
||||
mints,
|
||||
relays: [conf.relay],
|
||||
relays,
|
||||
balance: 0, // Newly created wallet, balance is zero.
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue