diff --git a/packages/snap/snap.manifest.json b/packages/snap/snap.manifest.json index 587e05ff..d4585009 100644 --- a/packages/snap/snap.manifest.json +++ b/packages/snap/snap.manifest.json @@ -1,5 +1,5 @@ { - "version": "2.0.11", + "version": "2.1.0", "description": "BOB: Metamask snap to manage your Bitcoin", "proposedName": "BOB", "repository": { @@ -7,7 +7,7 @@ "url": "https://github.com/bob-collective/bob-snap" }, "source": { - "shasum": "Ea+2ea/YTw965c+UA8zhzQIQ8CWIV3yEt5llK6YUjkE=", + "shasum": "RxgmYv7eYlRsqDEBd1D8ilbcfoA6zXd0U6qr+qsPEBw=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/snap/src/bitcoin/__tests__/index.test.ts b/packages/snap/src/bitcoin/__tests__/index.test.ts index 119f2f63..b870380f 100644 --- a/packages/snap/src/bitcoin/__tests__/index.test.ts +++ b/packages/snap/src/bitcoin/__tests__/index.test.ts @@ -106,7 +106,10 @@ changeAddress: tb1qx5wzl3f27d6dgzk9u7h47pqdts60xdpax4w5rf it('should be able to sign transaction and extract txId and txHex', () => { const tx = new BtcPsbt(psbtFixture.base64, BitcoinNetwork.Test); - const { txId, txHex } = tx.signPsbt(signer); + const psbt = Psbt.fromBase64(tx.signPsbt(signer)); + expect(psbt.data.inputs[0].finalScriptWitness).toBeDefined(); + const txId = psbt.extractTransaction().getId(); + const txHex = psbt.extractTransaction().toHex(); expect(txId).toBe( '4db856b1b7049cce26dc298458796f66d0dee39a5d0651b4c51aa0c66326adec', ); @@ -115,6 +118,12 @@ changeAddress: tb1qx5wzl3f27d6dgzk9u7h47pqdts60xdpax4w5rf ); }); + it('should be able to sign transaction without finalizing', () => { + const tx = new BtcPsbt(psbtFixture.base64, BitcoinNetwork.Test); + const psbt = Psbt.fromBase64(tx.signPsbt(signer, { autoFinalize: false })); + expect(psbt.data.inputs[0].finalScriptWitness).toBeUndefined(); + }); + it('should be able to sign taproot transaction and extract txId and txHex', () => { bitcoin.initEccLib(ecc); @@ -154,7 +163,9 @@ changeAddress: tb1qx5wzl3f27d6dgzk9u7h47pqdts60xdpax4w5rf .toBase64(); const tx = new BtcPsbt(psbtBase64, BitcoinNetwork.Test); - const { txId, txHex } = tx.signPsbt(signer); + const psbt = Psbt.fromBase64(tx.signPsbt(signer)); + const txId = psbt.extractTransaction().getId(); + const txHex = psbt.extractTransaction().toHex(); expect(txId).toBe( 'e0a70feca465add48d89fade7c66b68589fc95f21c8e69e3121a4bd6cee3302d', ); diff --git a/packages/snap/src/bitcoin/index.ts b/packages/snap/src/bitcoin/index.ts index d42b1273..9576b9a3 100644 --- a/packages/snap/src/bitcoin/index.ts +++ b/packages/snap/src/bitcoin/index.ts @@ -117,18 +117,15 @@ export class BtcPsbt { } } - signPsbt(accountSigner: AccountSigner, opts: SignPsbtOptions = {}) { + signPsbt(accountSigner: AccountSigner, opts: SignPsbtOptions = { autoFinalize: true }) { try { const signInputOpts = opts.signInputOpts !== undefined ? opts.signInputOpts : new Array(this.psbt.data.inputs.length).fill({}); signAllInputsHD(this.psbt, accountSigner, signInputOpts); - if (validateSignaturesOfAllInputs(this.psbt, validator, schnorrValidator)) { + if (!opts.autoFinalize) { + return this.psbt.toBase64(); + } else if (validateSignaturesOfAllInputs(this.psbt, validator, schnorrValidator)) { this.psbt.finalizeAllInputs(); - const txId = this.psbt.extractTransaction().getId(); - const txHex = this.psbt.extractTransaction().toHex(); - return { - txId, - txHex - } + return this.psbt.toBase64(); } else { throw new Error('Signature verification failed'); } diff --git a/packages/snap/src/index.ts b/packages/snap/src/index.ts index a8fa14f3..0714ee1c 100644 --- a/packages/snap/src/index.ts +++ b/packages/snap/src/index.ts @@ -44,7 +44,6 @@ export const onRpcRequest = async ({ origin, request }: RpcRequest) => { origin, snap, ); - // keep this for backwards compatibility case 'btc_signPsbt': return signPsbt( origin, diff --git a/packages/snap/src/interface.ts b/packages/snap/src/interface.ts index 9ded88e1..efc7fa61 100644 --- a/packages/snap/src/interface.ts +++ b/packages/snap/src/interface.ts @@ -12,6 +12,7 @@ export interface GetAllXpubsRequest { } export interface SignPsbtOptions { + autoFinalize: boolean, signInputOpts?: SignInputOptions[]; } diff --git a/packages/snap/src/rpc/signPSBT.ts b/packages/snap/src/rpc/signPSBT.ts index 3a918ffd..2520588b 100644 --- a/packages/snap/src/rpc/signPSBT.ts +++ b/packages/snap/src/rpc/signPSBT.ts @@ -9,17 +9,17 @@ import { heading, panel, text, divider } from "@metamask/snaps-ui"; export async function signPsbt( domain: string, snap: Snap, - psbt: string, + psbtBase64: string, network: BitcoinNetwork, scriptType: ScriptType, opts?: SignPsbtOptions -): Promise<{ txId: string, txHex: string }> { +): Promise { const snapNetwork = await getPersistedData(snap, "network", '' as BitcoinNetwork); if (snapNetwork != network) { throw SnapError.of(RequestErrors.NetworkNotMatch); } - const btcPsbt = new BtcPsbt(psbt, snapNetwork); + const btcPsbt = new BtcPsbt(psbtBase64, snapNetwork); const txDetails = btcPsbt.extractPsbtJson() const result = await snap.request({