Fix leaky tests, but nutzapMiddleware is still broken

This commit is contained in:
Alex Gleason 2025-02-13 15:47:53 -06:00
parent 6473ab0f98
commit 26346b83ac
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
4 changed files with 37 additions and 27 deletions

View file

@ -18,10 +18,7 @@ interface AppEnv extends HonoEnv {
}; };
} }
Deno.test('PUT /wallet must be successful', { Deno.test('PUT /wallet must be successful', async () => {
sanitizeOps: false, // postgres.js calls 'setTimeout' without calling 'clearTimeout'
sanitizeResources: false, // postgres.js calls 'setTimeout' without calling 'clearTimeout'
}, async () => {
await using db = await createTestDB(); await using db = await createTestDB();
const store = db.store; const store = db.store;
@ -97,10 +94,7 @@ Deno.test('PUT /wallet must be successful', {
]); ]);
}); });
Deno.test('PUT /wallet must NOT be successful: wrong request body/schema', { Deno.test('PUT /wallet must NOT be successful: wrong request body/schema', async () => {
sanitizeOps: false, // postgres.js calls 'setTimeout' without calling 'clearTimeout'
sanitizeResources: false, // postgres.js calls 'setTimeout' without calling 'clearTimeout'
}, async () => {
await using db = await createTestDB(); await using db = await createTestDB();
const store = db.store; const store = db.store;
@ -132,10 +126,7 @@ Deno.test('PUT /wallet must NOT be successful: wrong request body/schema', {
assertObjectMatch(body, { error: 'Bad schema' }); assertObjectMatch(body, { error: 'Bad schema' });
}); });
Deno.test('PUT /wallet must NOT be successful: wallet already exists', { Deno.test('PUT /wallet must NOT be successful: wallet already exists', async () => {
sanitizeOps: false, // postgres.js calls 'setTimeout' without calling 'clearTimeout'
sanitizeResources: false, // postgres.js calls 'setTimeout' without calling 'clearTimeout'
}, async () => {
await using db = await createTestDB(); await using db = await createTestDB();
const store = db.store; const store = db.store;
@ -169,10 +160,7 @@ Deno.test('PUT /wallet must NOT be successful: wallet already exists', {
assertEquals(body2, { error: 'You already have a wallet 😏' }); assertEquals(body2, { error: 'You already have a wallet 😏' });
}); });
Deno.test('GET /wallet must be successful', { Deno.test('GET /wallet must be successful', async () => {
sanitizeOps: false, // postgres.js calls 'setTimeout' without calling 'clearTimeout'
sanitizeResources: false, // postgres.js calls 'setTimeout' without calling 'clearTimeout'
}, async () => {
await using db = await createTestDB(); await using db = await createTestDB();
const store = db.store; const store = db.store;
@ -284,7 +272,7 @@ Deno.test('GET /wallet must be successful', {
}); });
}); });
Deno.test('GET /mints must be successful', {}, async () => { Deno.test('GET /mints must be successful', async () => {
const app = new Hono<AppEnv>().route('/', cashuApp); const app = new Hono<AppEnv>().route('/', cashuApp);
const response = await app.request('/mints', { const response = await app.request('/mints', {

View file

@ -6,9 +6,8 @@ import { z } from 'zod';
import { Conf } from '@/config.ts'; import { Conf } from '@/config.ts';
import { createEvent, parseBody } from '@/utils/api.ts'; import { createEvent, parseBody } from '@/utils/api.ts';
import { signerMiddleware } from '@/middleware/signerMiddleware.ts';
import { requireNip44Signer } from '@/middleware/requireSigner.ts'; import { requireNip44Signer } from '@/middleware/requireSigner.ts';
import { storeMiddleware } from '@/middleware/storeMiddleware.ts'; import { requireStore } from '@/middleware/storeMiddleware.ts';
import { walletSchema } from '@/schema.ts'; import { walletSchema } from '@/schema.ts';
import { swapNutzapsMiddleware } from '@/middleware/swapNutzapsMiddleware.ts'; import { swapNutzapsMiddleware } from '@/middleware/swapNutzapsMiddleware.ts';
import { isNostrId } from '@/utils.ts'; import { isNostrId } from '@/utils.ts';
@ -17,7 +16,7 @@ import { errorJson } from '@/utils/log.ts';
type Wallet = z.infer<typeof walletSchema>; type Wallet = z.infer<typeof walletSchema>;
const app = new Hono().use('*', storeMiddleware, signerMiddleware); const app = new Hono().use('*', requireStore);
// app.delete('/wallet') -> 204 // app.delete('/wallet') -> 204
@ -46,7 +45,7 @@ const createCashuWalletAndNutzapInfoSchema = z.object({
* https://github.com/nostr-protocol/nips/blob/master/61.md#nutzap-informational-event * https://github.com/nostr-protocol/nips/blob/master/61.md#nutzap-informational-event
*/ */
app.put('/wallet', requireNip44Signer, async (c) => { app.put('/wallet', requireNip44Signer, async (c) => {
const signer = c.get('signer'); const signer = c.var.signer;
const store = c.get('store'); const store = c.get('store');
const pubkey = await signer.getPublicKey(); const pubkey = await signer.getPublicKey();
const body = await parseBody(c.req.raw); const body = await parseBody(c.req.raw);

View file

@ -4,6 +4,13 @@ import { NostrSigner, NStore } from '@nostrify/nostrify';
import { UserStore } from '@/storages/UserStore.ts'; import { UserStore } from '@/storages/UserStore.ts';
import { Storages } from '@/storages.ts'; import { Storages } from '@/storages.ts';
export const requireStore: MiddlewareHandler<{ Variables: { store: NStore } }> = async (c, next) => {
if (!c.get('store')) {
throw new Error('Store is required');
}
await next();
};
/** Store middleware. */ /** Store middleware. */
export const storeMiddleware: MiddlewareHandler<{ Variables: { signer?: NostrSigner; store: NStore } }> = async ( export const storeMiddleware: MiddlewareHandler<{ Variables: { signer?: NostrSigner; store: NStore } }> = async (
c, c,

View file

@ -2,7 +2,7 @@ import { CashuMint, CashuWallet, getEncodedToken, type Proof } from '@cashu/cash
import { MiddlewareHandler } from '@hono/hono'; import { MiddlewareHandler } from '@hono/hono';
import { HTTPException } from '@hono/hono/http-exception'; import { HTTPException } from '@hono/hono/http-exception';
import { getPublicKey } from 'nostr-tools'; import { getPublicKey } from 'nostr-tools';
import { NostrFilter, NostrSigner, NStore } from '@nostrify/nostrify'; import { NostrFilter, NostrSigner, NSchema as n, NStore } from '@nostrify/nostrify';
import { SetRequired } from 'type-fest'; import { SetRequired } from 'type-fest';
import { stringToBytes } from '@scure/base'; import { stringToBytes } from '@scure/base';
import { logi } from '@soapbox/logi'; import { logi } from '@soapbox/logi';
@ -11,6 +11,7 @@ import { isNostrId } from '@/utils.ts';
import { errorJson } from '@/utils/log.ts'; import { errorJson } from '@/utils/log.ts';
import { Conf } from '@/config.ts'; import { Conf } from '@/config.ts';
import { createEvent } from '@/utils/api.ts'; import { createEvent } from '@/utils/api.ts';
import { z } from 'zod';
/** /**
* Swap nutzaps into wallet (create new events) if the user has a wallet, otheriwse, just fallthrough. * Swap nutzaps into wallet (create new events) if the user has a wallet, otheriwse, just fallthrough.
@ -111,7 +112,22 @@ export const swapNutzapsMiddleware: MiddlewareHandler<
mintsToProofs[mint] = { proofs: [], redeemed: [] }; mintsToProofs[mint] = { proofs: [], redeemed: [] };
} }
mintsToProofs[mint].proofs = [...mintsToProofs[mint].proofs, ...JSON.parse(proof)]; const parsed = n.json().pipe(
z.object({
id: z.string(),
amount: z.number(),
secret: z.string(),
C: z.string(),
dleq: z.object({ s: z.string(), e: z.string(), r: z.string().optional() }).optional(),
dleqValid: z.boolean().optional(),
}).array(),
).safeParse(proof);
if (!parsed.success) {
continue;
}
mintsToProofs[mint].proofs = [...mintsToProofs[mint].proofs, ...parsed.data];
mintsToProofs[mint].redeemed = [ mintsToProofs[mint].redeemed = [
...mintsToProofs[mint].redeemed, ...mintsToProofs[mint].redeemed,
[ [
@ -122,8 +138,8 @@ export const swapNutzapsMiddleware: MiddlewareHandler<
], ],
['p', event.pubkey], // pubkey of the author of the 9321 event (nutzap sender) ['p', event.pubkey], // pubkey of the author of the 9321 event (nutzap sender)
]; ];
} catch (e: any) { } catch (e) {
logi({ level: 'error', ns: 'ditto.api.cashu.wallet.swap', error: e }); logi({ level: 'error', ns: 'ditto.api.cashu.wallet.swap', error: errorJson(e) });
} }
} }
@ -162,8 +178,8 @@ export const swapNutzapsMiddleware: MiddlewareHandler<
), ),
tags: mintsToProofs[mint].redeemed, tags: mintsToProofs[mint].redeemed,
}, c); }, c);
} catch (e: any) { } catch (e) {
logi({ level: 'error', ns: 'ditto.api.cashu.wallet.swap', error: e }); logi({ level: 'error', ns: 'ditto.api.cashu.wallet.swap', error: errorJson(e) });
} }
} }
} }