From 7b75237a09e27bdabab147b094f36004b83c17bf Mon Sep 17 00:00:00 2001 From: iamboss Date: Tue, 23 Jun 2026 00:19:39 +0900 Subject: [PATCH] fix: HTTPWalletWire uses injected httpClient instead of global fetch transmitToWallet called the global fetch directly, silently dropping the injected httpClient. This prevented wrapping requests with AuthFetch for BRC-103 mutual auth and prevented injecting a custom/mock fetch. The sibling HTTPWalletJSON already uses its injected httpClient. With the default constructor httpClient defaults to global fetch, so existing behavior is preserved. Adds a regression test asserting the injected client is used; fixes a stale comment/test name that documented the old behavior. --- .../src/wallet/substrates/HTTPWalletWire.ts | 2 +- .../substrates/__tests/HTTPWalletWire.test.ts | 31 +++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/packages/sdk/src/wallet/substrates/HTTPWalletWire.ts b/packages/sdk/src/wallet/substrates/HTTPWalletWire.ts index d46fe7fd1..809b10721 100644 --- a/packages/sdk/src/wallet/substrates/HTTPWalletWire.ts +++ b/packages/sdk/src/wallet/substrates/HTTPWalletWire.ts @@ -37,7 +37,7 @@ export default class HTTPWalletWire implements WalletWire { originator = Utils.toUTF8(originatorBytes) } const payload = messageReader.read() - const response = await fetch(`${this.baseUrl}/${callName}`, { + const response = await this.httpClient(`${this.baseUrl}/${callName}`, { method: 'POST', headers: { 'Content-Type': 'application/octet-stream', diff --git a/packages/sdk/src/wallet/substrates/__tests/HTTPWalletWire.test.ts b/packages/sdk/src/wallet/substrates/__tests/HTTPWalletWire.test.ts index fbc9d8abe..56db90f85 100644 --- a/packages/sdk/src/wallet/substrates/__tests/HTTPWalletWire.test.ts +++ b/packages/sdk/src/wallet/substrates/__tests/HTTPWalletWire.test.ts @@ -30,7 +30,8 @@ function toArrayBuffer(bytes: number[]): ArrayBuffer { /** * Replace the global `fetch` with a jest mock that returns the given bytes. - * HTTPWalletWire.transmitToWallet calls the *global* fetch, not this.httpClient. + * With the default constructor, `this.httpClient` is bound to the global `fetch` + * at construction time, so replacing `global.fetch` before constructing works. */ function mockGlobalFetch(responseBytes: number[]): jest.Mock { const mock = jest.fn().mockResolvedValue({ @@ -79,7 +80,7 @@ describe('HTTPWalletWire – constructor', () => { expect(wire.originator).toBeUndefined() }) - it('stores a custom httpClient (even though transmitToWallet uses global fetch)', () => { + it('stores a custom httpClient', () => { const mockFetch = jest.fn() const wire = new HTTPWalletWire( 'example.com', @@ -271,3 +272,29 @@ describe('HTTPWalletWire – call-name routing', () => { expect(url).toBe(`http://localhost:3301/${callName}`) }) }) + +// --------------------------------------------------------------------------- +// transmitToWallet – httpClient injection (BRC-103 / custom transport) +// --------------------------------------------------------------------------- + +describe('HTTPWalletWire – httpClient injection', () => { + it('uses the injected httpClient instead of the global fetch', async () => { + const globalMock = jest.fn() // must NOT be called + global.fetch = globalMock + const injected = jest.fn().mockResolvedValue({ + arrayBuffer: () => Promise.resolve(toArrayBuffer([])), + } as unknown as Response) + + const wire = new HTTPWalletWire( + undefined, + 'http://localhost:3301', + injected as unknown as typeof fetch + ) + await wire.transmitToWallet(buildFrame('getVersion')) + + expect(injected).toHaveBeenCalledTimes(1) + expect(globalMock).not.toHaveBeenCalled() + const [url] = injected.mock.calls[0] as [string] + expect(url).toBe('http://localhost:3301/getVersion') + }) +})