mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29:46 +00:00
Merge branch 'cashu-test-pipeline-fast' into 'main'
Cashu test pipeline fast See merge request soapbox-pub/ditto!659
This commit is contained in:
commit
b9e50166ae
3 changed files with 361 additions and 1 deletions
|
|
@ -66,6 +66,7 @@
|
||||||
"@std/json": "jsr:@std/json@^0.223.0",
|
"@std/json": "jsr:@std/json@^0.223.0",
|
||||||
"@std/media-types": "jsr:@std/media-types@^0.224.1",
|
"@std/media-types": "jsr:@std/media-types@^0.224.1",
|
||||||
"@std/streams": "jsr:@std/streams@^0.223.0",
|
"@std/streams": "jsr:@std/streams@^0.223.0",
|
||||||
|
"@std/testing": "jsr:@std/testing@^1.0.9",
|
||||||
"blurhash": "npm:blurhash@2.0.5",
|
"blurhash": "npm:blurhash@2.0.5",
|
||||||
"comlink": "npm:comlink@^4.4.1",
|
"comlink": "npm:comlink@^4.4.1",
|
||||||
"comlink-async-generator": "npm:comlink-async-generator@^0.0.1",
|
"comlink-async-generator": "npm:comlink-async-generator@^0.0.1",
|
||||||
|
|
|
||||||
47
deno.lock
generated
47
deno.lock
generated
|
|
@ -55,6 +55,7 @@
|
||||||
"jsr:@soapbox/safe-fetch@2": "2.0.0",
|
"jsr:@soapbox/safe-fetch@2": "2.0.0",
|
||||||
"jsr:@std/assert@0.223": "0.223.0",
|
"jsr:@std/assert@0.223": "0.223.0",
|
||||||
"jsr:@std/assert@0.224": "0.224.0",
|
"jsr:@std/assert@0.224": "0.224.0",
|
||||||
|
"jsr:@std/assert@^1.0.10": "1.0.11",
|
||||||
"jsr:@std/assert@~0.213.1": "0.213.1",
|
"jsr:@std/assert@~0.213.1": "0.213.1",
|
||||||
"jsr:@std/assert@~0.225.1": "0.225.3",
|
"jsr:@std/assert@~0.225.1": "0.225.3",
|
||||||
"jsr:@std/bytes@0.223": "0.223.0",
|
"jsr:@std/bytes@0.223": "0.223.0",
|
||||||
|
|
@ -66,6 +67,7 @@
|
||||||
"jsr:@std/bytes@^1.0.2-rc.3": "1.0.2",
|
"jsr:@std/bytes@^1.0.2-rc.3": "1.0.2",
|
||||||
"jsr:@std/cli@0.223": "0.223.0",
|
"jsr:@std/cli@0.223": "0.223.0",
|
||||||
"jsr:@std/crypto@0.224": "0.224.0",
|
"jsr:@std/crypto@0.224": "0.224.0",
|
||||||
|
"jsr:@std/data-structures@^1.0.6": "1.0.6",
|
||||||
"jsr:@std/encoding@0.213.1": "0.213.1",
|
"jsr:@std/encoding@0.213.1": "0.213.1",
|
||||||
"jsr:@std/encoding@0.224": "0.224.3",
|
"jsr:@std/encoding@0.224": "0.224.3",
|
||||||
"jsr:@std/encoding@0.224.0": "0.224.0",
|
"jsr:@std/encoding@0.224.0": "0.224.0",
|
||||||
|
|
@ -73,8 +75,10 @@
|
||||||
"jsr:@std/encoding@~0.224.1": "0.224.3",
|
"jsr:@std/encoding@~0.224.1": "0.224.3",
|
||||||
"jsr:@std/fmt@0.213.1": "0.213.1",
|
"jsr:@std/fmt@0.213.1": "0.213.1",
|
||||||
"jsr:@std/fs@0.213.1": "0.213.1",
|
"jsr:@std/fs@0.213.1": "0.213.1",
|
||||||
|
"jsr:@std/fs@^1.0.9": "1.0.11",
|
||||||
"jsr:@std/fs@~0.229.3": "0.229.3",
|
"jsr:@std/fs@~0.229.3": "0.229.3",
|
||||||
"jsr:@std/internal@1": "1.0.5",
|
"jsr:@std/internal@1": "1.0.5",
|
||||||
|
"jsr:@std/internal@^1.0.5": "1.0.5",
|
||||||
"jsr:@std/io@0.223": "0.223.0",
|
"jsr:@std/io@0.223": "0.223.0",
|
||||||
"jsr:@std/io@0.224": "0.224.9",
|
"jsr:@std/io@0.224": "0.224.9",
|
||||||
"jsr:@std/json@0.223": "0.223.0",
|
"jsr:@std/json@0.223": "0.223.0",
|
||||||
|
|
@ -83,8 +87,10 @@
|
||||||
"jsr:@std/path@0.213.1": "0.213.1",
|
"jsr:@std/path@0.213.1": "0.213.1",
|
||||||
"jsr:@std/path@0.224.0": "0.224.0",
|
"jsr:@std/path@0.224.0": "0.224.0",
|
||||||
"jsr:@std/path@1.0.0-rc.1": "1.0.0-rc.1",
|
"jsr:@std/path@1.0.0-rc.1": "1.0.0-rc.1",
|
||||||
|
"jsr:@std/path@^1.0.8": "1.0.8",
|
||||||
"jsr:@std/path@~0.213.1": "0.213.1",
|
"jsr:@std/path@~0.213.1": "0.213.1",
|
||||||
"jsr:@std/streams@0.223": "0.223.0",
|
"jsr:@std/streams@0.223": "0.223.0",
|
||||||
|
"jsr:@std/testing@^1.0.9": "1.0.9",
|
||||||
"npm:@cashu/cashu-ts@^2.2.0": "2.2.0",
|
"npm:@cashu/cashu-ts@^2.2.0": "2.2.0",
|
||||||
"npm:@electric-sql/pglite@~0.2.8": "0.2.8",
|
"npm:@electric-sql/pglite@~0.2.8": "0.2.8",
|
||||||
"npm:@isaacs/ttlcache@^1.4.1": "1.4.1",
|
"npm:@isaacs/ttlcache@^1.4.1": "1.4.1",
|
||||||
|
|
@ -93,6 +99,7 @@
|
||||||
"npm:@scure/base@^1.1.6": "1.1.6",
|
"npm:@scure/base@^1.1.6": "1.1.6",
|
||||||
"npm:@scure/bip32@^1.4.0": "1.4.0",
|
"npm:@scure/bip32@^1.4.0": "1.4.0",
|
||||||
"npm:@scure/bip39@^1.3.0": "1.3.0",
|
"npm:@scure/bip39@^1.3.0": "1.3.0",
|
||||||
|
"npm:@types/node@*": "22.5.4",
|
||||||
"npm:blurhash@2.0.5": "2.0.5",
|
"npm:blurhash@2.0.5": "2.0.5",
|
||||||
"npm:comlink-async-generator@*": "0.0.1",
|
"npm:comlink-async-generator@*": "0.0.1",
|
||||||
"npm:comlink-async-generator@^0.0.1": "0.0.1",
|
"npm:comlink-async-generator@^0.0.1": "0.0.1",
|
||||||
|
|
@ -570,7 +577,13 @@
|
||||||
"@std/assert@0.225.3": {
|
"@std/assert@0.225.3": {
|
||||||
"integrity": "b3c2847aecf6955b50644cdb9cf072004ea3d1998dd7579fc0acb99dbb23bd4f",
|
"integrity": "b3c2847aecf6955b50644cdb9cf072004ea3d1998dd7579fc0acb99dbb23bd4f",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"jsr:@std/internal"
|
"jsr:@std/internal@1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"@std/assert@1.0.11": {
|
||||||
|
"integrity": "2461ef3c368fe88bc60e186e7744a93112f16fd110022e113a0849e94d1c83c1",
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@std/internal@^1.0.5"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"@std/bytes@0.223.0": {
|
"@std/bytes@0.223.0": {
|
||||||
|
|
@ -601,6 +614,9 @@
|
||||||
"jsr:@std/encoding@0.224"
|
"jsr:@std/encoding@0.224"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"@std/data-structures@1.0.6": {
|
||||||
|
"integrity": "76a7fd8080c66604c0496220a791860492ab21a04a63a969c0b9a0609bbbb760"
|
||||||
|
},
|
||||||
"@std/dotenv@0.224.0": {
|
"@std/dotenv@0.224.0": {
|
||||||
"integrity": "d9234cdf551507dcda60abb6c474289843741d8c07ee8ce540c60f5c1b220a1d"
|
"integrity": "d9234cdf551507dcda60abb6c474289843741d8c07ee8ce540c60f5c1b220a1d"
|
||||||
},
|
},
|
||||||
|
|
@ -632,6 +648,12 @@
|
||||||
"jsr:@std/path@1.0.0-rc.1"
|
"jsr:@std/path@1.0.0-rc.1"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"@std/fs@1.0.11": {
|
||||||
|
"integrity": "ba674672693340c5ebdd018b4fe1af46cb08741f42b4c538154e97d217b55bdd",
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@std/path@^1.0.8"
|
||||||
|
]
|
||||||
|
},
|
||||||
"@std/internal@1.0.0": {
|
"@std/internal@1.0.0": {
|
||||||
"integrity": "ac6a6dfebf838582c4b4f61a6907374e27e05bedb6ce276e0f1608fe84e7cd9a"
|
"integrity": "ac6a6dfebf838582c4b4f61a6907374e27e05bedb6ce276e0f1608fe84e7cd9a"
|
||||||
},
|
},
|
||||||
|
|
@ -729,6 +751,9 @@
|
||||||
"@std/path@1.0.0-rc.1": {
|
"@std/path@1.0.0-rc.1": {
|
||||||
"integrity": "b8c00ae2f19106a6bb7cbf1ab9be52aa70de1605daeb2dbdc4f87a7cbaf10ff6"
|
"integrity": "b8c00ae2f19106a6bb7cbf1ab9be52aa70de1605daeb2dbdc4f87a7cbaf10ff6"
|
||||||
},
|
},
|
||||||
|
"@std/path@1.0.8": {
|
||||||
|
"integrity": "548fa456bb6a04d3c1a1e7477986b6cffbce95102d0bb447c67c4ee70e0364be"
|
||||||
|
},
|
||||||
"@std/streams@0.223.0": {
|
"@std/streams@0.223.0": {
|
||||||
"integrity": "d6b28e498ced3960b04dc5d251f2dcfc1df244b5ec5a48dc23a8f9b490be3b99",
|
"integrity": "d6b28e498ced3960b04dc5d251f2dcfc1df244b5ec5a48dc23a8f9b490be3b99",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|
@ -736,6 +761,16 @@
|
||||||
"jsr:@std/bytes@0.223",
|
"jsr:@std/bytes@0.223",
|
||||||
"jsr:@std/io@0.223"
|
"jsr:@std/io@0.223"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"@std/testing@1.0.9": {
|
||||||
|
"integrity": "9bdd4ac07cb13e7594ac30e90f6ceef7254ac83a9aeaa089be0008f33aab5cd4",
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@std/assert@^1.0.10",
|
||||||
|
"jsr:@std/data-structures",
|
||||||
|
"jsr:@std/fs@^1.0.9",
|
||||||
|
"jsr:@std/internal@^1.0.5",
|
||||||
|
"jsr:@std/path@^1.0.8"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npm": {
|
"npm": {
|
||||||
|
|
@ -959,6 +994,12 @@
|
||||||
"@types/trusted-types"
|
"@types/trusted-types"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"@types/node@22.5.4": {
|
||||||
|
"integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==",
|
||||||
|
"dependencies": [
|
||||||
|
"undici-types"
|
||||||
|
]
|
||||||
|
},
|
||||||
"@types/trusted-types@2.0.7": {
|
"@types/trusted-types@2.0.7": {
|
||||||
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
|
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
|
||||||
},
|
},
|
||||||
|
|
@ -1720,6 +1761,9 @@
|
||||||
"type-fest@4.18.2": {
|
"type-fest@4.18.2": {
|
||||||
"integrity": "sha512-+suCYpfJLAe4OXS6+PPXjW3urOS4IoP9waSiLuXfLgqZODKw/aWwASvzqE886wA0kQgGy0mIWyhd87VpqIy6Xg=="
|
"integrity": "sha512-+suCYpfJLAe4OXS6+PPXjW3urOS4IoP9waSiLuXfLgqZODKw/aWwASvzqE886wA0kQgGy0mIWyhd87VpqIy6Xg=="
|
||||||
},
|
},
|
||||||
|
"undici-types@6.19.8": {
|
||||||
|
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
|
||||||
|
},
|
||||||
"unfurl.js@6.4.0": {
|
"unfurl.js@6.4.0": {
|
||||||
"integrity": "sha512-DogJFWPkOWMcu2xPdpmbcsL+diOOJInD3/jXOv6saX1upnWmMK8ndAtDWUfJkuInqNI9yzADud4ID9T+9UeWCw==",
|
"integrity": "sha512-DogJFWPkOWMcu2xPdpmbcsL+diOOJInD3/jXOv6saX1upnWmMK8ndAtDWUfJkuInqNI9yzADud4ID9T+9UeWCw==",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|
@ -2431,6 +2475,7 @@
|
||||||
"jsr:@std/json@0.223",
|
"jsr:@std/json@0.223",
|
||||||
"jsr:@std/media-types@~0.224.1",
|
"jsr:@std/media-types@~0.224.1",
|
||||||
"jsr:@std/streams@0.223",
|
"jsr:@std/streams@0.223",
|
||||||
|
"jsr:@std/testing@^1.0.9",
|
||||||
"npm:@cashu/cashu-ts@^2.2.0",
|
"npm:@cashu/cashu-ts@^2.2.0",
|
||||||
"npm:@electric-sql/pglite@~0.2.8",
|
"npm:@electric-sql/pglite@~0.2.8",
|
||||||
"npm:@isaacs/ttlcache@^1.4.1",
|
"npm:@isaacs/ttlcache@^1.4.1",
|
||||||
|
|
|
||||||
314
src/controllers/api/cashu.test.ts
Normal file
314
src/controllers/api/cashu.test.ts
Normal file
|
|
@ -0,0 +1,314 @@
|
||||||
|
import { Env as HonoEnv, Hono } from '@hono/hono';
|
||||||
|
import { NostrSigner, NSecSigner, NStore } from '@nostrify/nostrify';
|
||||||
|
import { generateSecretKey, getPublicKey } from 'nostr-tools';
|
||||||
|
import { bytesToString, stringToBytes } from '@scure/base';
|
||||||
|
import { stub } from '@std/testing/mock';
|
||||||
|
import { assertEquals, assertExists, assertObjectMatch } from '@std/assert';
|
||||||
|
|
||||||
|
import { createTestDB, genEvent } from '@/test.ts';
|
||||||
|
|
||||||
|
import cashuApp from '@/controllers/api/cashu.ts';
|
||||||
|
import { walletSchema } from '@/schema.ts';
|
||||||
|
|
||||||
|
interface AppEnv extends HonoEnv {
|
||||||
|
Variables: {
|
||||||
|
/** Signer to get the logged-in user's pubkey, relays, and to sign events. */
|
||||||
|
signer: NostrSigner;
|
||||||
|
/** Storage for the user, might filter out unwanted content. */
|
||||||
|
store: NStore;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Deno.test('PUT /wallet must be successful', {
|
||||||
|
sanitizeOps: false,
|
||||||
|
sanitizeResources: false,
|
||||||
|
}, async () => {
|
||||||
|
using _mock = mockFetch();
|
||||||
|
await using db = await createTestDB();
|
||||||
|
const store = db.store;
|
||||||
|
|
||||||
|
const sk = generateSecretKey();
|
||||||
|
const signer = new NSecSigner(sk);
|
||||||
|
const nostrPrivateKey = bytesToString('hex', sk);
|
||||||
|
|
||||||
|
const app = new Hono<AppEnv>().use(
|
||||||
|
async (c, next) => {
|
||||||
|
c.set('signer', signer);
|
||||||
|
await next();
|
||||||
|
},
|
||||||
|
async (c, next) => {
|
||||||
|
c.set('store', store);
|
||||||
|
await next();
|
||||||
|
},
|
||||||
|
).route('/', cashuApp);
|
||||||
|
|
||||||
|
const response = await app.request('/wallet', {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: [['content-type', 'application/json']],
|
||||||
|
body: JSON.stringify({
|
||||||
|
mints: [
|
||||||
|
'https://houston.mint.com',
|
||||||
|
'https://houston.mint.com', // duplicate on purpose
|
||||||
|
'https://cuiaba.mint.com',
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals(response.status, 200);
|
||||||
|
|
||||||
|
const pubkey = await signer.getPublicKey();
|
||||||
|
|
||||||
|
const [wallet] = await store.query([{ authors: [pubkey], kinds: [17375] }]);
|
||||||
|
|
||||||
|
assertExists(wallet);
|
||||||
|
assertEquals(wallet.kind, 17375);
|
||||||
|
|
||||||
|
const { data, success } = walletSchema.safeParse(await response.json());
|
||||||
|
|
||||||
|
assertEquals(success, true);
|
||||||
|
if (!data) return; // get rid of typescript error possibly undefined
|
||||||
|
|
||||||
|
const decryptedContent: string[][] = JSON.parse(await signer.nip44.decrypt(pubkey, wallet.content));
|
||||||
|
|
||||||
|
const privkey = decryptedContent.find(([value]) => value === 'privkey')?.[1]!;
|
||||||
|
const p2pk = getPublicKey(stringToBytes('hex', privkey));
|
||||||
|
|
||||||
|
assertEquals(nostrPrivateKey !== privkey, true);
|
||||||
|
|
||||||
|
assertEquals(data.pubkey_p2pk, p2pk);
|
||||||
|
assertEquals(data.mints, [
|
||||||
|
'https://houston.mint.com',
|
||||||
|
'https://cuiaba.mint.com',
|
||||||
|
]);
|
||||||
|
assertEquals(data.relays, [
|
||||||
|
'ws://localhost:4036/relay',
|
||||||
|
]);
|
||||||
|
assertEquals(data.balance, 0);
|
||||||
|
|
||||||
|
const [nutzap_info] = await store.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]!], [
|
||||||
|
'ws://localhost:4036/relay',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test('PUT /wallet must NOT be successful: wrong request body/schema', async () => {
|
||||||
|
using _mock = mockFetch();
|
||||||
|
await using db = await createTestDB();
|
||||||
|
const store = db.store;
|
||||||
|
|
||||||
|
const sk = generateSecretKey();
|
||||||
|
const signer = new NSecSigner(sk);
|
||||||
|
|
||||||
|
const app = new Hono<AppEnv>().use(
|
||||||
|
async (c, next) => {
|
||||||
|
c.set('signer', signer);
|
||||||
|
await next();
|
||||||
|
},
|
||||||
|
async (c, next) => {
|
||||||
|
c.set('store', store);
|
||||||
|
await next();
|
||||||
|
},
|
||||||
|
).route('/', cashuApp);
|
||||||
|
|
||||||
|
const response = await app.request('/wallet', {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: [['content-type', 'application/json']],
|
||||||
|
body: JSON.stringify({
|
||||||
|
mints: [], // no mints should throw an error
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const body = await response.json();
|
||||||
|
|
||||||
|
assertEquals(response.status, 400);
|
||||||
|
assertObjectMatch(body, { error: 'Bad schema' });
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test('PUT /wallet must NOT be successful: wallet already exists', async () => {
|
||||||
|
using _mock = mockFetch();
|
||||||
|
await using db = await createTestDB();
|
||||||
|
const store = db.store;
|
||||||
|
|
||||||
|
const sk = generateSecretKey();
|
||||||
|
const signer = new NSecSigner(sk);
|
||||||
|
|
||||||
|
const app = new Hono<AppEnv>().use(
|
||||||
|
async (c, next) => {
|
||||||
|
c.set('signer', signer);
|
||||||
|
await next();
|
||||||
|
},
|
||||||
|
async (c, next) => {
|
||||||
|
c.set('store', store);
|
||||||
|
await next();
|
||||||
|
},
|
||||||
|
).route('/', cashuApp);
|
||||||
|
|
||||||
|
await db.store.event(genEvent({ kind: 17375 }, sk));
|
||||||
|
|
||||||
|
const response = await app.request('/wallet', {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: [['content-type', 'application/json']],
|
||||||
|
body: JSON.stringify({
|
||||||
|
mints: ['https://mint.heart.com'],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const body2 = await response.json();
|
||||||
|
|
||||||
|
assertEquals(response.status, 400);
|
||||||
|
assertEquals(body2, { error: 'You already have a wallet 😏' });
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test('GET /wallet must be successful', async () => {
|
||||||
|
using _mock = mockFetch();
|
||||||
|
await using db = await createTestDB();
|
||||||
|
const store = db.store;
|
||||||
|
|
||||||
|
const sk = generateSecretKey();
|
||||||
|
const signer = new NSecSigner(sk);
|
||||||
|
const pubkey = await signer.getPublicKey();
|
||||||
|
const privkey = bytesToString('hex', sk);
|
||||||
|
const p2pk = getPublicKey(stringToBytes('hex', privkey));
|
||||||
|
|
||||||
|
const app = new Hono<AppEnv>().use(
|
||||||
|
async (c, next) => {
|
||||||
|
c.set('signer', signer);
|
||||||
|
await next();
|
||||||
|
},
|
||||||
|
async (c, next) => {
|
||||||
|
c.set('store', store);
|
||||||
|
await next();
|
||||||
|
},
|
||||||
|
).route('/', cashuApp);
|
||||||
|
|
||||||
|
// Wallet
|
||||||
|
await db.store.event(genEvent({
|
||||||
|
kind: 17375,
|
||||||
|
content: await signer.nip44.encrypt(
|
||||||
|
pubkey,
|
||||||
|
JSON.stringify([
|
||||||
|
['privkey', privkey],
|
||||||
|
['mint', 'https://mint.soul.com'],
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
}, sk));
|
||||||
|
|
||||||
|
// Nutzap information
|
||||||
|
await db.store.event(genEvent({
|
||||||
|
kind: 10019,
|
||||||
|
tags: [
|
||||||
|
['pubkey', p2pk],
|
||||||
|
['mint', 'https://mint.soul.com'],
|
||||||
|
],
|
||||||
|
}, sk));
|
||||||
|
|
||||||
|
// Unspent proofs
|
||||||
|
await db.store.event(genEvent({
|
||||||
|
kind: 7375,
|
||||||
|
content: await signer.nip44.encrypt(
|
||||||
|
pubkey,
|
||||||
|
JSON.stringify({
|
||||||
|
mint: 'https://mint.soul.com',
|
||||||
|
proofs: [
|
||||||
|
{
|
||||||
|
id: '005c2502034d4f12',
|
||||||
|
amount: 25,
|
||||||
|
secret: 'z+zyxAVLRqN9lEjxuNPSyRJzEstbl69Jc1vtimvtkPg=',
|
||||||
|
C: '0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '005c2502034d4f12',
|
||||||
|
amount: 25,
|
||||||
|
secret: 'z+zyxAVLRqN9lEjxuNPSyRJzEstbl69Jc1vtimvtkPg=',
|
||||||
|
C: '0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '005c2502034d4f12',
|
||||||
|
amount: 25,
|
||||||
|
secret: 'z+zyxAVLRqN9lEjxuNPSyRJzEstbl69Jc1vtimvtkPg=',
|
||||||
|
C: '0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '005c2502034d4f12',
|
||||||
|
amount: 25,
|
||||||
|
secret: 'z+zyxAVLRqN9lEjxuNPSyRJzEstbl69Jc1vtimvtkPg=',
|
||||||
|
C: '0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
del: [],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
}, sk));
|
||||||
|
|
||||||
|
// TODO: find a way to have a Mock mint so operations like 'swap', 'mint' and 'melt' can be tested (this will be a bit hard).
|
||||||
|
// Nutzap
|
||||||
|
const senderSk = generateSecretKey();
|
||||||
|
|
||||||
|
await db.store.event(genEvent({
|
||||||
|
kind: 9321,
|
||||||
|
content: 'Nice post!',
|
||||||
|
tags: [
|
||||||
|
['p', pubkey],
|
||||||
|
['u', 'https://mint.soul.com'],
|
||||||
|
[
|
||||||
|
'proof',
|
||||||
|
'{"amount":1,"C":"02277c66191736eb72fce9d975d08e3191f8f96afb73ab1eec37e4465683066d3f","id":"000a93d6f8a1d2c4","secret":"[\\"P2PK\\",{\\"nonce\\":\\"b00bdd0467b0090a25bdf2d2f0d45ac4e355c482c1418350f273a04fedaaee83\\",\\"data\\":\\"02eaee8939e3565e48cc62967e2fde9d8e2a4b3ec0081f29eceff5c64ef10ac1ed\\"}]"}',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
}, senderSk));
|
||||||
|
|
||||||
|
const response = await app.request('/wallet', {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
|
||||||
|
const body = await response.json();
|
||||||
|
|
||||||
|
assertEquals(response.status, 200);
|
||||||
|
assertEquals(body, {
|
||||||
|
pubkey_p2pk: p2pk,
|
||||||
|
mints: ['https://mint.soul.com'],
|
||||||
|
relays: ['ws://localhost:4036/relay'],
|
||||||
|
balance: 100,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test('GET /mints must be successful', async () => {
|
||||||
|
using _mock = mockFetch();
|
||||||
|
await using db = await createTestDB();
|
||||||
|
const store = db.store;
|
||||||
|
|
||||||
|
const app = new Hono<AppEnv>().use(
|
||||||
|
async (c, next) => {
|
||||||
|
c.set('store', store);
|
||||||
|
await next();
|
||||||
|
},
|
||||||
|
).route('/', cashuApp);
|
||||||
|
|
||||||
|
const response = await app.request('/mints', {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
|
||||||
|
const body = await response.json();
|
||||||
|
|
||||||
|
assertEquals(response.status, 200);
|
||||||
|
assertEquals(body, { mints: [] });
|
||||||
|
});
|
||||||
|
|
||||||
|
function mockFetch() {
|
||||||
|
const mock = stub(globalThis, 'fetch', () => {
|
||||||
|
return Promise.resolve(new Response());
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
[Symbol.dispose]: () => {
|
||||||
|
mock.restore();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue