From 5cd088733073d6fbb0a6b4b326a49ae4ad99cbe8 Mon Sep 17 00:00:00 2001 From: AkarshSahlot Date: Fri, 13 Feb 2026 16:15:30 +0530 Subject: [PATCH] fix: NWCClient.close() hanging Jest tests The close() method in NWCClient was synchronous, which meant it didn't wait for WebSocket connections to actually close before returning. This caused Jest tests to hang because of open handles. I made close() async so it waits for the underlying WebSocket capabilities to finish closing. I also updated the dependencies and config to support the latest nostr-tools exports. Changes: - Made NWCClient.close() async - Updated imports to use specific paths from nostr-tools - Set moduleResolution to bundler in tsconfig - Updated jest.config.ts to export default --- jest.config.ts | 9 ++++++--- src/nwc/NWAClient.ts | 2 +- src/nwc/NWCClient.ts | 22 +++++++++++++++++++--- src/nwc/NWCWalletService.ts | 2 +- tsconfig.json | 2 +- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/jest.config.ts b/jest.config.ts index b413e106..b196c441 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,5 +1,8 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', +export default { + preset: "ts-jest", + testEnvironment: "node", + transform: { + "^.+\\.tsx?$": ["ts-jest", { useESM: true }], + }, }; \ No newline at end of file diff --git a/src/nwc/NWAClient.ts b/src/nwc/NWAClient.ts index 72301c59..3cad5714 100644 --- a/src/nwc/NWAClient.ts +++ b/src/nwc/NWAClient.ts @@ -7,7 +7,7 @@ import { Nip47NotificationType, } from "./types"; import { NWCClient } from "./NWCClient"; -import { SubCloser } from "nostr-tools/lib/types/abstract-pool"; +import { SubCloser } from "nostr-tools/abstract-pool"; export type NWAOptions = { relayUrls: string[]; diff --git a/src/nwc/NWCClient.ts b/src/nwc/NWCClient.ts index cc171ffa..b7c26f9a 100644 --- a/src/nwc/NWCClient.ts +++ b/src/nwc/NWCClient.ts @@ -10,6 +10,7 @@ import { EventTemplate, SimplePool, } from "nostr-tools"; +import { normalizeURL } from "nostr-tools/utils"; import { hexToBytes, bytesToHex } from "@noble/hashes/utils"; import { Nip47EncryptionType, @@ -55,7 +56,7 @@ import { Nip47CancelHoldInvoiceResponse, Nip47NetworkError, } from "./types"; -import { SubCloser } from "nostr-tools/lib/types/abstract-pool"; +import { SubCloser } from "nostr-tools/abstract-pool"; export interface NWCOptions { relayUrls: string[]; @@ -198,8 +199,23 @@ export class NWCClient { return getEventHash(event); } - close() { - return this.pool.close(this.relayUrls); + + async close(): Promise { + const closePromises: Promise[] = []; + for (const url of this.relayUrls) { + const relayUrl = normalizeURL(url); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const relay = (this.pool as any).relays.get(relayUrl); + if (relay?.ws && relay.ws.readyState !== WebSocket.CLOSED) { + closePromises.push( + new Promise((resolve) => { + relay.ws?.addEventListener("close", () => resolve(), { once: true }); + }), + ); + } + } + this.pool.close(this.relayUrls); + await Promise.all(closePromises); } async encrypt(pubkey: string, content: string) { diff --git a/src/nwc/NWCWalletService.ts b/src/nwc/NWCWalletService.ts index cbdf3264..b3db024a 100644 --- a/src/nwc/NWCWalletService.ts +++ b/src/nwc/NWCWalletService.ts @@ -8,7 +8,7 @@ import { Relay, } from "nostr-tools"; import { hexToBytes } from "@noble/hashes/utils"; -import { Subscription } from "nostr-tools/lib/types/abstract-relay"; +import { Subscription } from "nostr-tools/abstract-relay"; import { Nip47MakeInvoiceRequest, diff --git a/tsconfig.json b/tsconfig.json index 3d635736..589c4f9e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "module": "ESNext", - "moduleResolution": "node", + "moduleResolution": "bundler", "lib": ["ES2021", "DOM"], "target": "es2020", "strict": true,