From 409ce26c0320d1557853dab95d3df5725abd85aa Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 4 Aug 2026 02:06:55 +0200 Subject: [PATCH 1/7] fix(bitcoin-wallet-snap): return Json directly from onKeyringRequest (v2 protocol) --- packages/bitcoin-wallet-snap/CHANGELOG.md | 9 ++- packages/bitcoin-wallet-snap/package.json | 2 +- .../bitcoin-wallet-snap/snap.manifest.json | 4 +- .../src/handlers/KeyringHandler.test.ts | 3 +- .../src/handlers/KeyringHandler.ts | 5 +- .../handlers/KeyringRequestHandler.test.ts | 78 +++++-------------- .../src/handlers/KeyringRequestHandler.ts | 63 ++++++--------- 7 files changed, 54 insertions(+), 110 deletions(-) diff --git a/packages/bitcoin-wallet-snap/CHANGELOG.md b/packages/bitcoin-wallet-snap/CHANGELOG.md index 8bb5167a..b4776235 100644 --- a/packages/bitcoin-wallet-snap/CHANGELOG.md +++ b/packages/bitcoin-wallet-snap/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [2.0.1] + +### Fixed + +- Fix `onKeyringRequest` responses to return `Json` directly (v2 protocol) instead of the v1 `{ pending: false, result }` envelope ([#82](https://github.com/MetaMask/internal-snaps/pull/82)) + ## [2.0.0] ### Added @@ -40,7 +46,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - This package was migrated from [snap-bitcoin-wallet](https://github.com/MetaMask/snap-bitcoin-wallet). See the source repository for the original [changelog](https://github.com/MetaMask/snap-bitcoin-wallet/blob/main/packages/snap/CHANGELOG.md). -[Unreleased]: https://github.com/MetaMask/internal-snaps/compare/@metamask/bitcoin-wallet-snap@2.0.0...HEAD +[Unreleased]: https://github.com/MetaMask/internal-snaps/compare/@metamask/bitcoin-wallet-snap@2.0.1...HEAD +[2.0.1]: https://github.com/MetaMask/internal-snaps/compare/@metamask/bitcoin-wallet-snap@2.0.0...@metamask/bitcoin-wallet-snap@2.0.1 [2.0.0]: https://github.com/MetaMask/internal-snaps/compare/@metamask/bitcoin-wallet-snap@1.15.2...@metamask/bitcoin-wallet-snap@2.0.0 [1.15.2]: https://github.com/MetaMask/internal-snaps/compare/@metamask/bitcoin-wallet-snap@1.15.1...@metamask/bitcoin-wallet-snap@1.15.2 [1.15.1]: https://github.com/MetaMask/internal-snaps/releases/tag/@metamask/bitcoin-wallet-snap@1.15.1 diff --git a/packages/bitcoin-wallet-snap/package.json b/packages/bitcoin-wallet-snap/package.json index 70ad47ba..6948870e 100644 --- a/packages/bitcoin-wallet-snap/package.json +++ b/packages/bitcoin-wallet-snap/package.json @@ -1,6 +1,6 @@ { "name": "@metamask/bitcoin-wallet-snap", - "version": "2.0.0", + "version": "2.0.1", "description": "A Bitcoin wallet Snap", "keywords": [ "Ethereum", diff --git a/packages/bitcoin-wallet-snap/snap.manifest.json b/packages/bitcoin-wallet-snap/snap.manifest.json index 9d682594..5b3d7ad7 100644 --- a/packages/bitcoin-wallet-snap/snap.manifest.json +++ b/packages/bitcoin-wallet-snap/snap.manifest.json @@ -1,5 +1,5 @@ { - "version": "2.0.0", + "version": "2.0.1", "description": "Manage Bitcoin using MetaMask", "proposedName": "Bitcoin", "repository": { @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/internal-snaps.git" }, "source": { - "shasum": "ye8FAG8Punj6snX/zr6AwKJCidDHdim1FUHqKwjTQog=", + "shasum": "qCj2B0mJ4g4nEvyxo4ZedFmIb40C18hRGdLQisJuZ4M=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/bitcoin-wallet-snap/src/handlers/KeyringHandler.test.ts b/packages/bitcoin-wallet-snap/src/handlers/KeyringHandler.test.ts index a94d33f5..3dc0a342 100644 --- a/packages/bitcoin-wallet-snap/src/handlers/KeyringHandler.test.ts +++ b/packages/bitcoin-wallet-snap/src/handlers/KeyringHandler.test.ts @@ -11,7 +11,6 @@ import type { import { Address } from '@metamask/bitcoindevkit'; import type { KeyringAccount, - KeyringResponse, Transaction as KeyringTransaction, KeyringRequest, } from '@metamask/keyring-api'; @@ -962,7 +961,7 @@ describe('KeyringHandler', () => { describe('submitRequest', () => { it('calls KeyringRequestHandler', async () => { const mockRequest = mock(); - const expectedResponse = mock(); + const expectedResponse = { signature: 'mockSig' }; mockKeyringRequest.route.mockResolvedValue(expectedResponse); const result = await handler.submitRequest(mockRequest); diff --git a/packages/bitcoin-wallet-snap/src/handlers/KeyringHandler.ts b/packages/bitcoin-wallet-snap/src/handlers/KeyringHandler.ts index 903427ef..600cd7e4 100644 --- a/packages/bitcoin-wallet-snap/src/handlers/KeyringHandler.ts +++ b/packages/bitcoin-wallet-snap/src/handlers/KeyringHandler.ts @@ -12,7 +12,6 @@ import type { CreateAccountOptions, KeyringAccount, KeyringRequest, - KeyringResponse, Paginated, Pagination, ResolvedAccountAddress, @@ -24,7 +23,7 @@ import type { KeyringSnapRpc, } from '@metamask/keyring-api/v2'; import { SnapError } from '@metamask/snaps-sdk'; -import type { CaipChainId, JsonRpcRequest } from '@metamask/snaps-sdk'; +import type { CaipChainId, Json, JsonRpcRequest } from '@metamask/snaps-sdk'; import { sensitive } from '@metamask/superstruct'; import { assert, is, string } from 'superstruct'; import { encode } from 'wif'; @@ -337,7 +336,7 @@ export class KeyringHandler implements KeyringSnapRpc { }; } - async submitRequest(request: KeyringRequest): Promise { + async submitRequest(request: KeyringRequest): Promise { return this.#keyringRequest.route(request); } diff --git a/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.test.ts b/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.test.ts index f396be20..f081e61a 100644 --- a/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.test.ts +++ b/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.test.ts @@ -155,12 +155,9 @@ describe('KeyringRequestHandler', () => { 3, ); expect(result).toStrictEqual({ - pending: false, - result: { - psbt: 'psbtBase64', - txid: 'txid', - canBeMalleable: false, - }, + psbt: 'psbtBase64', + txid: 'txid', + canBeMalleable: false, }); }); @@ -183,10 +180,7 @@ describe('KeyringRequestHandler', () => { const result = await handler.route(noBroadcastRequest); - expect(result).toStrictEqual({ - pending: false, - result: { psbt: 'psbtBase64', txid: null }, - }); + expect(result).toStrictEqual({ psbt: 'psbtBase64', txid: null }); }); it('throws AssertionError if usecase returns txid without canBeMalleable', async () => { @@ -215,12 +209,9 @@ describe('KeyringRequestHandler', () => { const result = await handler.route(mockRequest); expect(result).toStrictEqual({ - pending: false, - result: { - psbt: 'psbtBase64', - txid: 'txid', - canBeMalleable: true, - }, + psbt: 'psbtBase64', + txid: 'txid', + canBeMalleable: true, }); }); @@ -303,10 +294,7 @@ describe('KeyringRequestHandler', () => { const result = await handler.route(mockRequest); - expect(result).toStrictEqual({ - pending: false, - result: { psbt: 'psbtBase64', txid: null }, - }); + expect(result).toStrictEqual({ psbt: 'psbtBase64', txid: null }); }); it('does not sign if user cancels confirmation', async () => { @@ -409,10 +397,7 @@ describe('KeyringRequestHandler', () => { mockPsbt, 3, ); - expect(result).toStrictEqual({ - pending: false, - result: { fee: '1000' }, - }); + expect(result).toStrictEqual({ fee: '1000' }); }); it('propagates errors from parsePsbt', async () => { @@ -474,10 +459,7 @@ describe('KeyringRequestHandler', () => { mockPsbt, 3, ); - expect(result).toStrictEqual({ - pending: false, - result: { psbt: 'filledPsbtBase64' }, - }); + expect(result).toStrictEqual({ psbt: 'filledPsbtBase64' }); }); it('propagates errors from parsePsbt', async () => { @@ -543,10 +525,7 @@ describe('KeyringRequestHandler', () => { mockPsbt, origin, ); - expect(result).toStrictEqual({ - pending: false, - result: { txid: 'txid', canBeMalleable: false }, - }); + expect(result).toStrictEqual({ txid: 'txid', canBeMalleable: false }); }); it('passes canBeMalleable=true through for legacy P2PKH accounts', async () => { @@ -560,10 +539,7 @@ describe('KeyringRequestHandler', () => { const result = await handler.route(mockRequest); - expect(result).toStrictEqual({ - pending: false, - result: { txid: 'txid', canBeMalleable: true }, - }); + expect(result).toStrictEqual({ txid: 'txid', canBeMalleable: true }); }); it('propagates errors from parsePsbt', async () => { @@ -636,10 +612,7 @@ describe('KeyringRequestHandler', () => { origin, 3, ); - expect(result).toStrictEqual({ - pending: false, - result: { txid: 'txid', canBeMalleable: false }, - }); + expect(result).toStrictEqual({ txid: 'txid', canBeMalleable: false }); }); it('passes canBeMalleable=true through for legacy P2PKH accounts', async () => { @@ -653,10 +626,7 @@ describe('KeyringRequestHandler', () => { const result = await handler.route(mockRequest); - expect(result).toStrictEqual({ - pending: false, - result: { txid: 'txid', canBeMalleable: true }, - }); + expect(result).toStrictEqual({ txid: 'txid', canBeMalleable: true }); }); it('propagates errors from sendTransfer', async () => { @@ -704,10 +674,7 @@ describe('KeyringRequestHandler', () => { GetUtxoRequest, ); expect(mockAccountsUseCases.get).toHaveBeenCalledWith('account-id'); - expect(result).toStrictEqual({ - pending: false, - result: expectedUtxo, - }); + expect(result).toStrictEqual(expectedUtxo); }); it('throws NotFoundError when UTXO does not exist', async () => { @@ -750,10 +717,7 @@ describe('KeyringRequestHandler', () => { const result = await handler.route(mockRequest); expect(mockAccountsUseCases.get).toHaveBeenCalledWith('account-id'); - expect(result).toStrictEqual({ - pending: false, - result: [mockUtxo, mockUtxo], - }); + expect(result).toStrictEqual([mockUtxo, mockUtxo]); }); }); @@ -774,10 +738,7 @@ describe('KeyringRequestHandler', () => { const result = await handler.route(mockRequest); expect(mockAccountsUseCases.get).toHaveBeenCalledWith('account-id'); - expect(result).toStrictEqual({ - pending: false, - result: 'publicDescriptor', - }); + expect(result).toStrictEqual('publicDescriptor'); }); }); @@ -803,10 +764,7 @@ describe('KeyringRequestHandler', () => { 'message', 'metamask', ); - expect(result).toStrictEqual({ - pending: false, - result: { signature: 'signature' }, - }); + expect(result).toStrictEqual({ signature: 'signature' }); }); }); }); diff --git a/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.ts b/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.ts index 360151b1..2b8ef9ed 100644 --- a/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.ts +++ b/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.ts @@ -1,4 +1,4 @@ -import type { KeyringRequest, KeyringResponse } from '@metamask/keyring-api'; +import type { KeyringRequest } from '@metamask/keyring-api'; import type { Json } from '@metamask/snaps-sdk'; import { assert } from 'superstruct'; @@ -64,7 +64,7 @@ export class KeyringRequestHandler { this.#confirmationRepository = confirmationRepository; } - async route(request: KeyringRequest): Promise { + async route(request: KeyringRequest): Promise { const { account, request: requestData, origin } = request; const { method, params } = requestData; @@ -127,7 +127,7 @@ export class KeyringRequestHandler { origin: string, options: { fill: boolean; broadcast: boolean }, feeRate?: number, - ): Promise { + ): Promise { const account = await this.#accountsUseCases.get(id); const psbtBase64ToSign = options.fill @@ -173,53 +173,46 @@ export class KeyringRequestHandler { if (canBeMalleable !== undefined) { response.canBeMalleable = canBeMalleable; } - return this.#toKeyringResponse(response); + return response as unknown as Json; } async #fillPsbt( id: string, psbtBase64: string, feeRate?: number, - ): Promise { + ): Promise { const psbt = await this.#accountsUseCases.fillPsbt( id, parsePsbt(psbtBase64), feeRate, ); - return this.#toKeyringResponse({ - psbt: psbt.toString(), - } as FillPsbtResponse); + return { psbt: psbt.toString() } as unknown as Json; } async #computeFee( id: string, psbtBase64: string, feeRate?: number, - ): Promise { + ): Promise { const fee = await this.#accountsUseCases.computeFee( id, parsePsbt(psbtBase64), feeRate, ); - return this.#toKeyringResponse({ - fee: fee.to_sat().toString(), - } as ComputeFeeResponse); + return { fee: fee.to_sat().toString() } as unknown as Json; } async #broadcastPsbt( id: string, psbtBase64: string, origin: string, - ): Promise { + ): Promise { const { txid, canBeMalleable } = await this.#accountsUseCases.broadcastPsbt( id, parsePsbt(psbtBase64), origin, ); - return this.#toKeyringResponse({ - txid: txid.toString(), - canBeMalleable, - } as BroadcastPsbtResponse); + return { txid: txid.toString(), canBeMalleable } as unknown as Json; } async #sendTransfer( @@ -227,59 +220,47 @@ export class KeyringRequestHandler { recipients: { address: string; amount: string }[], origin: string, feeRate?: number, - ): Promise { + ): Promise { const { txid, canBeMalleable } = await this.#accountsUseCases.sendTransfer( id, recipients, origin, feeRate, ); - return this.#toKeyringResponse({ - txid: txid.toString(), - canBeMalleable, - } as BroadcastPsbtResponse); + return { txid: txid.toString(), canBeMalleable } as unknown as Json; } - async #getUtxo(id: string, outpoint: string): Promise { + async #getUtxo(id: string, outpoint: string): Promise { const account = await this.#accountsUseCases.get(id); const utxo = account.getUtxo(outpoint); if (!utxo) { throw new NotFoundError('UTXO not found', { id }); } - return this.#toKeyringResponse(mapToUtxo(utxo, account.network)); + return mapToUtxo(utxo, account.network) as unknown as Json; } - async #listUtxos(id: string): Promise { + async #listUtxos(id: string): Promise { const account = await this.#accountsUseCases.get(id); - return this.#toKeyringResponse( - account.listUnspent().map((utxo) => mapToUtxo(utxo, account.network)), - ); + return account + .listUnspent() + .map((utxo) => mapToUtxo(utxo, account.network)) as unknown as Json; } - async #publicDescriptor(id: string): Promise { + async #publicDescriptor(id: string): Promise { const account = await this.#accountsUseCases.get(id); - return this.#toKeyringResponse(account.publicDescriptor); + return account.publicDescriptor as unknown as Json; } async #signMessage( id: string, message: string, origin: string, - ): Promise { + ): Promise { const signature = await this.#accountsUseCases.signMessage( id, message, origin, ); - return this.#toKeyringResponse({ - signature, - } as SignMessageResponse); - } - - #toKeyringResponse(result: Json): KeyringResponse { - return { - pending: false, - result, - }; + return { signature } as unknown as Json; } } From 249a0d2425b92e0e6891ce74ffb7b0fad9200649 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 4 Aug 2026 03:58:28 +0200 Subject: [PATCH 2/7] fix: lint fix --- .../src/handlers/KeyringRequestHandler.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.test.ts b/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.test.ts index f081e61a..26962c49 100644 --- a/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.test.ts +++ b/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.test.ts @@ -738,7 +738,7 @@ describe('KeyringRequestHandler', () => { const result = await handler.route(mockRequest); expect(mockAccountsUseCases.get).toHaveBeenCalledWith('account-id'); - expect(result).toStrictEqual('publicDescriptor'); + expect(result).toBe('publicDescriptor'); }); }); From 2683ac952447070a50a6d53e7c7bb3591a43c14f Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 4 Aug 2026 04:02:18 +0200 Subject: [PATCH 3/7] fix: undo version changes and fix changelog --- packages/bitcoin-wallet-snap/CHANGELOG.md | 4 +--- packages/bitcoin-wallet-snap/package.json | 2 +- packages/bitcoin-wallet-snap/snap.manifest.json | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/bitcoin-wallet-snap/CHANGELOG.md b/packages/bitcoin-wallet-snap/CHANGELOG.md index b4776235..3eed84d8 100644 --- a/packages/bitcoin-wallet-snap/CHANGELOG.md +++ b/packages/bitcoin-wallet-snap/CHANGELOG.md @@ -7,11 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [2.0.1] - ### Fixed -- Fix `onKeyringRequest` responses to return `Json` directly (v2 protocol) instead of the v1 `{ pending: false, result }` envelope ([#82](https://github.com/MetaMask/internal-snaps/pull/82)) +- Fix `onKeyringRequest` responses to return `Json` directly (v2 protocol) instead of the v1 `{ pending: false, result }` envelope ([#100](https://github.com/MetaMask/internal-snaps/pull/100)) ## [2.0.0] diff --git a/packages/bitcoin-wallet-snap/package.json b/packages/bitcoin-wallet-snap/package.json index 6948870e..70ad47ba 100644 --- a/packages/bitcoin-wallet-snap/package.json +++ b/packages/bitcoin-wallet-snap/package.json @@ -1,6 +1,6 @@ { "name": "@metamask/bitcoin-wallet-snap", - "version": "2.0.1", + "version": "2.0.0", "description": "A Bitcoin wallet Snap", "keywords": [ "Ethereum", diff --git a/packages/bitcoin-wallet-snap/snap.manifest.json b/packages/bitcoin-wallet-snap/snap.manifest.json index 5b3d7ad7..8345fd7c 100644 --- a/packages/bitcoin-wallet-snap/snap.manifest.json +++ b/packages/bitcoin-wallet-snap/snap.manifest.json @@ -1,5 +1,5 @@ { - "version": "2.0.1", + "version": "2.0.0", "description": "Manage Bitcoin using MetaMask", "proposedName": "Bitcoin", "repository": { From 2a85165fafbcb9ed5db9f7b3c2b623a25b9f69e9 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 4 Aug 2026 04:10:50 +0200 Subject: [PATCH 4/7] fix: changelog --- packages/bitcoin-wallet-snap/CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/bitcoin-wallet-snap/CHANGELOG.md b/packages/bitcoin-wallet-snap/CHANGELOG.md index 3eed84d8..0767b979 100644 --- a/packages/bitcoin-wallet-snap/CHANGELOG.md +++ b/packages/bitcoin-wallet-snap/CHANGELOG.md @@ -44,8 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - This package was migrated from [snap-bitcoin-wallet](https://github.com/MetaMask/snap-bitcoin-wallet). See the source repository for the original [changelog](https://github.com/MetaMask/snap-bitcoin-wallet/blob/main/packages/snap/CHANGELOG.md). -[Unreleased]: https://github.com/MetaMask/internal-snaps/compare/@metamask/bitcoin-wallet-snap@2.0.1...HEAD -[2.0.1]: https://github.com/MetaMask/internal-snaps/compare/@metamask/bitcoin-wallet-snap@2.0.0...@metamask/bitcoin-wallet-snap@2.0.1 +[Unreleased]: https://github.com/MetaMask/internal-snaps/compare/@metamask/bitcoin-wallet-snap@2.0.0...HEAD [2.0.0]: https://github.com/MetaMask/internal-snaps/compare/@metamask/bitcoin-wallet-snap@1.15.2...@metamask/bitcoin-wallet-snap@2.0.0 [1.15.2]: https://github.com/MetaMask/internal-snaps/compare/@metamask/bitcoin-wallet-snap@1.15.1...@metamask/bitcoin-wallet-snap@1.15.2 [1.15.1]: https://github.com/MetaMask/internal-snaps/releases/tag/@metamask/bitcoin-wallet-snap@1.15.1 From 2b8faf9e8f065012e36732f1501df2dd235bb2d7 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 4 Aug 2026 04:11:31 +0200 Subject: [PATCH 5/7] fix: update bitcoin shasum --- packages/bitcoin-wallet-snap/snap.manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bitcoin-wallet-snap/snap.manifest.json b/packages/bitcoin-wallet-snap/snap.manifest.json index 8345fd7c..ae4143e3 100644 --- a/packages/bitcoin-wallet-snap/snap.manifest.json +++ b/packages/bitcoin-wallet-snap/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/internal-snaps.git" }, "source": { - "shasum": "qCj2B0mJ4g4nEvyxo4ZedFmIb40C18hRGdLQisJuZ4M=", + "shasum": "nmBUkNRCyH60zI0wMFb9HzlW6ZVjCRxnLZdWOKcp88s=", "location": { "npm": { "filePath": "dist/bundle.js", From cc5be2b23e8a83909605ba274cd6a7a98901e125 Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 4 Aug 2026 11:37:12 +0200 Subject: [PATCH 6/7] refactor: remove casts --- .../src/handlers/KeyringRequestHandler.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.ts b/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.ts index 2b8ef9ed..a9e3ebeb 100644 --- a/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.ts +++ b/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.ts @@ -173,7 +173,7 @@ export class KeyringRequestHandler { if (canBeMalleable !== undefined) { response.canBeMalleable = canBeMalleable; } - return response as unknown as Json; + return response; } async #fillPsbt( @@ -186,7 +186,7 @@ export class KeyringRequestHandler { parsePsbt(psbtBase64), feeRate, ); - return { psbt: psbt.toString() } as unknown as Json; + return { psbt: psbt.toString() }; } async #computeFee( @@ -199,7 +199,7 @@ export class KeyringRequestHandler { parsePsbt(psbtBase64), feeRate, ); - return { fee: fee.to_sat().toString() } as unknown as Json; + return { fee: fee.to_sat().toString() }; } async #broadcastPsbt( @@ -212,7 +212,7 @@ export class KeyringRequestHandler { parsePsbt(psbtBase64), origin, ); - return { txid: txid.toString(), canBeMalleable } as unknown as Json; + return { txid: txid.toString(), canBeMalleable }; } async #sendTransfer( @@ -227,7 +227,7 @@ export class KeyringRequestHandler { origin, feeRate, ); - return { txid: txid.toString(), canBeMalleable } as unknown as Json; + return { txid: txid.toString(), canBeMalleable }; } async #getUtxo(id: string, outpoint: string): Promise { @@ -236,19 +236,19 @@ export class KeyringRequestHandler { if (!utxo) { throw new NotFoundError('UTXO not found', { id }); } - return mapToUtxo(utxo, account.network) as unknown as Json; + return mapToUtxo(utxo, account.network); } async #listUtxos(id: string): Promise { const account = await this.#accountsUseCases.get(id); return account .listUnspent() - .map((utxo) => mapToUtxo(utxo, account.network)) as unknown as Json; + .map((utxo) => mapToUtxo(utxo, account.network)); } async #publicDescriptor(id: string): Promise { const account = await this.#accountsUseCases.get(id); - return account.publicDescriptor as unknown as Json; + return account.publicDescriptor; } async #signMessage( @@ -261,6 +261,6 @@ export class KeyringRequestHandler { message, origin, ); - return { signature } as unknown as Json; + return { signature }; } } From be6d7f2c5b998006dff18920835a26de9c70d40d Mon Sep 17 00:00:00 2001 From: Hassan Malik Date: Tue, 4 Aug 2026 12:14:10 +0200 Subject: [PATCH 7/7] refactor: make response types more specific --- .../src/handlers/KeyringRequestHandler.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.ts b/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.ts index a9e3ebeb..8bec111c 100644 --- a/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.ts +++ b/packages/bitcoin-wallet-snap/src/handlers/KeyringRequestHandler.ts @@ -11,6 +11,7 @@ import { } from '../entities'; import type { AccountUseCases } from '../use-cases/AccountUseCases'; import { mapToUtxo } from './mappings'; +import type { Utxo } from './mappings'; import { parsePsbt } from './parsers'; import { BroadcastPsbtRequest, @@ -127,7 +128,7 @@ export class KeyringRequestHandler { origin: string, options: { fill: boolean; broadcast: boolean }, feeRate?: number, - ): Promise { + ): Promise { const account = await this.#accountsUseCases.get(id); const psbtBase64ToSign = options.fill @@ -180,7 +181,7 @@ export class KeyringRequestHandler { id: string, psbtBase64: string, feeRate?: number, - ): Promise { + ): Promise { const psbt = await this.#accountsUseCases.fillPsbt( id, parsePsbt(psbtBase64), @@ -193,7 +194,7 @@ export class KeyringRequestHandler { id: string, psbtBase64: string, feeRate?: number, - ): Promise { + ): Promise { const fee = await this.#accountsUseCases.computeFee( id, parsePsbt(psbtBase64), @@ -206,7 +207,7 @@ export class KeyringRequestHandler { id: string, psbtBase64: string, origin: string, - ): Promise { + ): Promise { const { txid, canBeMalleable } = await this.#accountsUseCases.broadcastPsbt( id, parsePsbt(psbtBase64), @@ -220,7 +221,7 @@ export class KeyringRequestHandler { recipients: { address: string; amount: string }[], origin: string, feeRate?: number, - ): Promise { + ): Promise { const { txid, canBeMalleable } = await this.#accountsUseCases.sendTransfer( id, recipients, @@ -230,7 +231,7 @@ export class KeyringRequestHandler { return { txid: txid.toString(), canBeMalleable }; } - async #getUtxo(id: string, outpoint: string): Promise { + async #getUtxo(id: string, outpoint: string): Promise { const account = await this.#accountsUseCases.get(id); const utxo = account.getUtxo(outpoint); if (!utxo) { @@ -239,14 +240,14 @@ export class KeyringRequestHandler { return mapToUtxo(utxo, account.network); } - async #listUtxos(id: string): Promise { + async #listUtxos(id: string): Promise { const account = await this.#accountsUseCases.get(id); return account .listUnspent() .map((utxo) => mapToUtxo(utxo, account.network)); } - async #publicDescriptor(id: string): Promise { + async #publicDescriptor(id: string): Promise { const account = await this.#accountsUseCases.get(id); return account.publicDescriptor; } @@ -255,7 +256,7 @@ export class KeyringRequestHandler { id: string, message: string, origin: string, - ): Promise { + ): Promise { const signature = await this.#accountsUseCases.signMessage( id, message,