Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
307 changes: 1 addition & 306 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/wasm-miniscript/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ declare module "./wasm/wasm_miniscript" {

export { WrapDescriptor as Descriptor } from "./wasm/wasm_miniscript";
export { WrapMiniscript as Miniscript } from "./wasm/wasm_miniscript";
export { WrapPsbt as Psbt } from "./wasm/wasm_miniscript";
1 change: 1 addition & 0 deletions packages/wasm-miniscript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"check-fmt": "prettier --check ."
},
"devDependencies": {
"@bitgo/utxo-lib": "^10.1.0",
"@types/mocha": "^10.0.7",
"@types/node": "^20.14.10",
"mocha": "^10.6.0",
Expand Down
4 changes: 3 additions & 1 deletion packages/wasm-miniscript/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ mod try_into_js_value;
mod miniscript;
mod error;
mod descriptor;
mod psbt;

pub use miniscript::WrapMiniscript;
pub use descriptor::WrapDescriptor;
pub use descriptor::WrapDescriptor;
pub use psbt::WrapPsbt;
17 changes: 17 additions & 0 deletions packages/wasm-miniscript/src/psbt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use miniscript::bitcoin::Psbt;
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::{JsError};

#[wasm_bindgen]
pub struct WrapPsbt(Psbt);

#[wasm_bindgen()]
impl WrapPsbt {
pub fn deserialize(psbt: Vec<u8>) -> Result<WrapPsbt, JsError> {
Ok(WrapPsbt(Psbt::deserialize(&psbt).map_err(JsError::from)?))
}

pub fn serialize(&self) -> Vec<u8> {
self.0.serialize()
}
}
36 changes: 36 additions & 0 deletions packages/wasm-miniscript/test/psbt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as utxolib from "@bitgo/utxo-lib";
import * as assert from "node:assert";
import { getPsbtFixtures } from "./psbtFixtures";
import { Psbt } from "../js";

getPsbtFixtures().forEach(({ psbt, name }) => {
describe(`PSBT fixture ${name}`, function () {
let buf: Buffer;
let wrappedPsbt: Psbt;

before(function () {
buf = psbt.toBuffer();
wrappedPsbt = Psbt.deserialize(buf);
});

it("should map to same hex", function () {
assert.strictEqual(
buf.toString("hex"),
// it seems that the utxolib impl sometimes adds two extra bytes zero bytes at the end
// they probably are insignificant so we just add them here
Buffer.from(wrappedPsbt.serialize()).toString("hex") + (name === "empty" ? "0000" : ""),
);
});

it("should round-trip utxolib -> ms -> utxolib", function () {
assert.strictEqual(
buf.toString("hex"),
utxolib.bitgo.UtxoPsbt.fromBuffer(Buffer.from(wrappedPsbt.serialize()), {
network: utxolib.networks.bitcoin,
})
.toBuffer()
.toString("hex"),
);
});
});
});
51 changes: 51 additions & 0 deletions packages/wasm-miniscript/test/psbtFixtures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as utxolib from "@bitgo/utxo-lib";

function getEmptyPsbt() {
return new utxolib.bitgo.UtxoPsbt();
}

function getPsbtWithScriptTypeAndStage(
seed: string,
scriptType: utxolib.bitgo.outputScripts.ScriptType2Of3,
stage: "unsigned" | "halfsigned" | "fullsigned",
) {
const keys = new utxolib.bitgo.RootWalletKeys(utxolib.testutil.getKeyTriple(seed));
return utxolib.testutil.constructPsbt(
[
{
scriptType,
value: BigInt(1e8),
},
],
[
{
value: BigInt(1e8 - 1000),
scriptType: "p2sh",
},
],
utxolib.networks.bitcoin,
keys,
"unsigned",
);
}

export type PsbtFixture = {
psbt: utxolib.bitgo.UtxoPsbt;
name: string;
};

export function getPsbtFixtures(): PsbtFixture[] {
const testMatrixScriptTypes = ["p2sh", "p2shP2wsh", "p2wsh"] as const;
const testMatrixStages = ["unsigned", "halfsigned", "fullsigned"] as const;

const fixturesBitGo2Of3 = testMatrixStages.flatMap((stage) => {
return testMatrixScriptTypes.map((scriptType) => {
return {
psbt: getPsbtWithScriptTypeAndStage("wasm", scriptType, stage),
name: `${scriptType}-${stage}`,
};
});
});

return [{ psbt: getEmptyPsbt(), name: "empty" }, ...fixturesBitGo2Of3];
}