diff --git a/modules/abstract-utxo/src/descriptor/NamedDescriptor.ts b/modules/abstract-utxo/src/descriptor/NamedDescriptor.ts index d9d2773e23..9ea7b485db 100644 --- a/modules/abstract-utxo/src/descriptor/NamedDescriptor.ts +++ b/modules/abstract-utxo/src/descriptor/NamedDescriptor.ts @@ -1,6 +1,6 @@ import * as t from 'io-ts'; -import { Descriptor, DescriptorPkType } from '@bitgo/wasm-miniscript'; -import { BIP32Interface, networks } from '@bitgo/utxo-lib'; +import type { Descriptor, DescriptorPkType } from '@bitgo/wasm-miniscript'; +import { BIP32Interface, miniscript, networks } from '@bitgo/utxo-lib'; import { signMessage, verifyMessage } from '@bitgo/sdk-core'; export const NamedDescriptor = t.intersection( @@ -30,7 +30,7 @@ export function createNamedDescriptorWithSignature( signingKey: BIP32Interface ): NamedDescriptor { if (typeof descriptor === 'string') { - descriptor = Descriptor.fromString(descriptor, 'derivable'); + descriptor = miniscript.Descriptor.fromString(descriptor, 'derivable'); } const value = descriptor.toString(); const signature = signMessage(value, signingKey, networks.bitcoin).toString('hex'); @@ -38,12 +38,12 @@ export function createNamedDescriptorWithSignature( } export function toNamedDescriptorNative(e: NamedDescriptor, pkType: DescriptorPkType): NamedDescriptorNative { - return { ...e, value: Descriptor.fromString(e.value, pkType) }; + return { ...e, value: miniscript.Descriptor.fromString(e.value, pkType) }; } export function hasValidSignature(descriptor: string | Descriptor, key: BIP32Interface, signatures: string[]): boolean { if (typeof descriptor === 'string') { - descriptor = Descriptor.fromString(descriptor, 'derivable'); + descriptor = miniscript.Descriptor.fromString(descriptor, 'derivable'); } const message = descriptor.toString(); diff --git a/modules/abstract-utxo/src/descriptor/assertDescriptorWalletAddress.ts b/modules/abstract-utxo/src/descriptor/assertDescriptorWalletAddress.ts index 9c9bc41128..6f4dc9714a 100644 --- a/modules/abstract-utxo/src/descriptor/assertDescriptorWalletAddress.ts +++ b/modules/abstract-utxo/src/descriptor/assertDescriptorWalletAddress.ts @@ -1,7 +1,7 @@ import assert from 'assert'; import * as utxolib from '@bitgo/utxo-lib'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; import { DescriptorMap } from '@bitgo/utxo-core/descriptor'; import { UtxoCoinSpecific, VerifyAddressOptions } from '../abstractUtxoCoin'; diff --git a/modules/abstract-utxo/src/descriptor/builder/builder.ts b/modules/abstract-utxo/src/descriptor/builder/builder.ts index dcc44c4f60..347f8ce088 100644 --- a/modules/abstract-utxo/src/descriptor/builder/builder.ts +++ b/modules/abstract-utxo/src/descriptor/builder/builder.ts @@ -1,5 +1,5 @@ -import { BIP32Interface } from '@bitgo/utxo-lib'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import { BIP32Interface, miniscript } from '@bitgo/utxo-lib'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; type DescriptorWithKeys = { name: TName; @@ -50,5 +50,5 @@ function getDescriptorString(builder: DescriptorBuilder): string { } export function getDescriptorFromBuilder(builder: DescriptorBuilder): Descriptor { - return Descriptor.fromString(getDescriptorString(builder), 'derivable'); + return miniscript.Descriptor.fromString(getDescriptorString(builder), 'derivable'); } diff --git a/modules/abstract-utxo/src/descriptor/builder/parse.ts b/modules/abstract-utxo/src/descriptor/builder/parse.ts index 8b6a120693..9fd6ec598c 100644 --- a/modules/abstract-utxo/src/descriptor/builder/parse.ts +++ b/modules/abstract-utxo/src/descriptor/builder/parse.ts @@ -1,6 +1,6 @@ import { BIP32Interface } from '@bitgo/utxo-lib'; import * as utxolib from '@bitgo/utxo-lib'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; import { DescriptorBuilder, getDescriptorFromBuilder } from './builder'; diff --git a/modules/abstract-utxo/src/descriptor/index.ts b/modules/abstract-utxo/src/descriptor/index.ts index 8f37cea966..0860014454 100644 --- a/modules/abstract-utxo/src/descriptor/index.ts +++ b/modules/abstract-utxo/src/descriptor/index.ts @@ -1,4 +1,3 @@ -export { Miniscript, Descriptor } from '@bitgo/wasm-miniscript'; export { DescriptorMap } from '@bitgo/utxo-core/descriptor'; export { assertDescriptorWalletAddress } from './assertDescriptorWalletAddress'; export { diff --git a/modules/abstract-utxo/test/transaction/descriptor/parse.ts b/modules/abstract-utxo/test/transaction/descriptor/parse.ts index be7cc565ea..91503fe5e2 100644 --- a/modules/abstract-utxo/test/transaction/descriptor/parse.ts +++ b/modules/abstract-utxo/test/transaction/descriptor/parse.ts @@ -1,7 +1,7 @@ import assert from 'assert'; import * as utxolib from '@bitgo/utxo-lib'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import * as WasmMiniscript from '@bitgo/wasm-miniscript'; import { getDefaultXPubs, getDescriptor, @@ -23,6 +23,8 @@ import { BaseOutput } from '../../../src'; import { getFixtureRoot } from './fixtures.utils'; +utxolib.initializeMiniscript(WasmMiniscript); + const { assertEqualFixture } = getFixtureRoot(__dirname + '/fixtures'); type OutputWithValue = { @@ -58,7 +60,7 @@ describe('parse', function () { const descriptorOther = getDescriptor('Wsh2Of3', getDefaultXPubs('b')); const psbt = mockPsbtDefault({ descriptorSelf, descriptorOther }); - function recipient(descriptor: Descriptor, index: number, value = 1000) { + function recipient(descriptor: WasmMiniscript.Descriptor, index: number, value = 1000) { return { value, address: createAddressFromDescriptor(descriptor, index, utxolib.networks.bitcoin) }; } diff --git a/modules/abstract-utxo/tsconfig.json b/modules/abstract-utxo/tsconfig.json index 7590532354..cf56cde6ec 100644 --- a/modules/abstract-utxo/tsconfig.json +++ b/modules/abstract-utxo/tsconfig.json @@ -9,7 +9,7 @@ "module": "node16", "typeRoots": ["../../types", "./node_modules/@types", "../../node_modules/@types"] }, - "include": ["src/**/*", "test/**/*"], + "include": ["src/**/*", "test/**/*", "../utxo-lib/src/shim"], "exclude": ["node_modules"], "references": [ { diff --git a/modules/bitgo/package.json b/modules/bitgo/package.json index 699f772431..141589adc8 100644 --- a/modules/bitgo/package.json +++ b/modules/bitgo/package.json @@ -127,6 +127,7 @@ "@bitgo/statics": "^54.5.0", "@bitgo/unspents": "^0.48.3", "@bitgo/utxo-lib": "^11.6.1", + "@bitgo/wasm-miniscript": "2.0.0-beta.7", "@types/superagent": "^4.1.3", "bignumber.js": "^9.1.1", "fs-extra": "^9.1.0", diff --git a/modules/bitgo/test/v2/unit/coins/utxo/descriptorAddress.ts b/modules/bitgo/test/v2/unit/coins/utxo/descriptorAddress.ts index f9577d07e2..9dc2b98943 100644 --- a/modules/bitgo/test/v2/unit/coins/utxo/descriptorAddress.ts +++ b/modules/bitgo/test/v2/unit/coins/utxo/descriptorAddress.ts @@ -4,12 +4,15 @@ import { TestBitGo } from '@bitgo/sdk-test'; import { AbstractUtxoCoin, descriptor as utxod } from '@bitgo/abstract-utxo'; import * as utxolib from '@bitgo/utxo-lib'; import { IWallet, WalletCoinSpecific } from '@bitgo/sdk-core'; +import * as WasmMiniscript from '@bitgo/wasm-miniscript'; import { BitGo } from '../../../../../src'; +utxolib.initializeMiniscript(WasmMiniscript); + export function getDescriptorAddress(d: string, index: number, network: utxolib.Network): string { const derivedScript = Buffer.from( - utxod.Descriptor.fromString(d, 'derivable').atDerivationIndex(index).scriptPubkey() + utxolib.miniscript.Descriptor.fromString(d, 'derivable').atDerivationIndex(index).scriptPubkey() ); return utxolib.address.fromOutputScript(derivedScript, network); } @@ -20,7 +23,7 @@ describe('descriptor wallets', function () { const xpubs = utxolib.testutil.getKeyTriple('setec astronomy').map((k) => k.neutered().toBase58()); function withChecksum(descriptor: string): string { - return utxod.Descriptor.fromString(descriptor, 'derivable').toString(); + return utxolib.miniscript.Descriptor.fromString(descriptor, 'derivable').toString(); } function getNamedDescriptor2Of2(name: string, a: string, b: string): utxod.NamedDescriptor { diff --git a/modules/utxo-bin/test/cmdPsbt.ts b/modules/utxo-bin/test/cmdPsbt.ts index ce18926232..b2556ea957 100644 --- a/modules/utxo-bin/test/cmdPsbt.ts +++ b/modules/utxo-bin/test/cmdPsbt.ts @@ -3,13 +3,15 @@ import * as fs from 'fs/promises'; import yargs from 'yargs'; import * as utxolib from '@bitgo/utxo-lib'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import * as WasmMiniscript from '@bitgo/wasm-miniscript'; import { cmdPsbt } from '../src/commands'; import { formatTreeNoColor, getFixtureString } from './fixtures'; import { getKeyTriple } from './bip32.util'; import { TxParser } from '../src/TxParser'; +utxolib.initializeMiniscript(WasmMiniscript); + async function runPsbtCommand(args: string[]) { return cmdPsbt.builder(yargs([])).strict().exitProcess(false).parse(args); } @@ -30,7 +32,7 @@ function multi(n: number, xpubs: string[], path: string) { return 'multi(' + n + ',' + xpubs.map((xpub) => xpub + path).join(',') + ')'; } -function getAddressFromDescriptor(descriptor: Descriptor, network: utxolib.Network) { +function getAddressFromDescriptor(descriptor: WasmMiniscript.Descriptor, network: utxolib.Network) { return utxolib.address.fromOutputScript(Buffer.from(descriptor.scriptPubkey()), network); } @@ -38,7 +40,7 @@ describe('cmdPsbt commands', function () { const keys = getKeyTriple('cmdPsbt'); const xpubs = keys.map((k) => k.neutered().toBase58()); const descriptorString = `wsh(${multi(2, xpubs, '/*')})`; - const descriptor = Descriptor.fromString(descriptorString, 'derivable'); + const descriptor = WasmMiniscript.Descriptor.fromString(descriptorString, 'derivable'); it('creates empty psbt', async function () { await fs.rm('/tmp/test.psbt', { force: true }); diff --git a/modules/utxo-core/src/descriptor/DescriptorMap.ts b/modules/utxo-core/src/descriptor/DescriptorMap.ts index 4be02ee72d..27beb1ccea 100644 --- a/modules/utxo-core/src/descriptor/DescriptorMap.ts +++ b/modules/utxo-core/src/descriptor/DescriptorMap.ts @@ -1,4 +1,5 @@ -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; +import { miniscript } from '@bitgo/utxo-lib'; /** Map from descriptor name to descriptor */ export type DescriptorMap = Map; @@ -6,6 +7,9 @@ export type DescriptorMap = Map; /** Convert an array of descriptor name-value pairs to a descriptor map */ export function toDescriptorMap(descriptors: { name: string; value: Descriptor | string }[]): DescriptorMap { return new Map( - descriptors.map((d) => [d.name, d.value instanceof Descriptor ? d.value : Descriptor.fromStringDetectType(d.value)]) + descriptors.map((d) => [ + d.name, + d.value instanceof miniscript.Descriptor ? d.value : miniscript.Descriptor.fromStringDetectType(d.value), + ]) ); } diff --git a/modules/utxo-core/src/descriptor/Output.ts b/modules/utxo-core/src/descriptor/Output.ts index 9d2f5b875f..8e62831545 100644 --- a/modules/utxo-core/src/descriptor/Output.ts +++ b/modules/utxo-core/src/descriptor/Output.ts @@ -1,6 +1,7 @@ import assert from 'assert'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; +import { miniscript } from '@bitgo/utxo-lib'; import { getFixedOutputSum, MaxOutput, Output, PrevOutput } from '../Output'; @@ -46,7 +47,7 @@ export function toDerivedDescriptorWalletOutput( if (!descriptor) { throw new Error(`Descriptor not found: ${output.descriptorName}`); } - assert(descriptor instanceof Descriptor); + assert(descriptor instanceof miniscript.Descriptor); const descriptorAtIndex = getDescriptorAtIndexCheckScript( descriptor, output.descriptorIndex, diff --git a/modules/utxo-core/src/descriptor/VirtualSize.ts b/modules/utxo-core/src/descriptor/VirtualSize.ts index 01af5369a1..3d31c40257 100644 --- a/modules/utxo-core/src/descriptor/VirtualSize.ts +++ b/modules/utxo-core/src/descriptor/VirtualSize.ts @@ -1,6 +1,7 @@ import * as utxolib from '@bitgo/utxo-lib'; import { Dimensions, VirtualSizes } from '@bitgo/unspents'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; +import { miniscript } from '@bitgo/utxo-lib'; import { DescriptorMap } from './DescriptorMap'; import { findDescriptorForInput } from './psbt'; @@ -86,7 +87,7 @@ export function getVirtualSize( ): number { const lookup = descriptorMap ? getInputVSizesForDescriptors(descriptorMap) : undefined; const inputVSize = tx.inputs.reduce((sum, input) => { - if (input instanceof Descriptor) { + if (input instanceof miniscript.Descriptor) { return sum + getInputVSizeForDescriptor(input); } if ('descriptorName' in input) { diff --git a/modules/utxo-core/src/descriptor/address.ts b/modules/utxo-core/src/descriptor/address.ts index 84ab36e953..da0052a00b 100644 --- a/modules/utxo-core/src/descriptor/address.ts +++ b/modules/utxo-core/src/descriptor/address.ts @@ -1,4 +1,4 @@ -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; import * as utxolib from '@bitgo/utxo-lib'; export function createScriptPubKeyFromDescriptor(descriptor: Descriptor, index: number | undefined): Buffer { diff --git a/modules/utxo-core/src/descriptor/derive.ts b/modules/utxo-core/src/descriptor/derive.ts index 6dbf46f470..b4139f0ef3 100644 --- a/modules/utxo-core/src/descriptor/derive.ts +++ b/modules/utxo-core/src/descriptor/derive.ts @@ -1,6 +1,7 @@ import assert from 'assert'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; +import { miniscript } from '@bitgo/utxo-lib'; /** * Get a descriptor at a specific derivation index. @@ -12,9 +13,9 @@ import { Descriptor } from '@bitgo/wasm-miniscript'; * @throws {Error} If index is undefined for a wildcard descriptor or if index is provided for a definite descriptor */ export function getDescriptorAtIndex(descriptor: Descriptor, index: number | undefined): Descriptor { - assert(descriptor instanceof Descriptor); - Descriptor.fromString(descriptor.toString(), 'derivable'); - descriptor = Descriptor.fromStringDetectType(descriptor.toString()); + assert(descriptor instanceof miniscript.Descriptor); + miniscript.Descriptor.fromString(descriptor.toString(), 'derivable'); + descriptor = miniscript.Descriptor.fromStringDetectType(descriptor.toString()); if (descriptor.hasWildcard()) { if (index === undefined) { throw new Error('Derivable descriptor requires an index'); @@ -34,11 +35,11 @@ export function getDescriptorAtIndexCheckScript( script: Buffer, descriptorString = descriptor.toString() ): Descriptor { - assert(descriptor instanceof Descriptor); + assert(descriptor instanceof miniscript.Descriptor); const descriptorAtIndex = getDescriptorAtIndex(descriptor, index); if (!script.equals(descriptorAtIndex.scriptPubkey())) { throw new Error(`Script mismatch: descriptor ${descriptorString} script=${script.toString('hex')}`); } - assert(descriptorAtIndex instanceof Descriptor); + assert(descriptorAtIndex instanceof miniscript.Descriptor); return descriptorAtIndex; } diff --git a/modules/utxo-core/src/descriptor/fromFixedScriptWallet.ts b/modules/utxo-core/src/descriptor/fromFixedScriptWallet.ts index b79ba658ae..b163fb1ae6 100644 --- a/modules/utxo-core/src/descriptor/fromFixedScriptWallet.ts +++ b/modules/utxo-core/src/descriptor/fromFixedScriptWallet.ts @@ -1,5 +1,6 @@ import * as utxolib from '@bitgo/utxo-lib'; -import { Descriptor, ast } from '@bitgo/wasm-miniscript'; +import type { Descriptor, ast } from '@bitgo/wasm-miniscript'; +import { miniscript } from '@bitgo/utxo-lib'; /** Expand a template with the given root wallet keys and chain code */ function expand(rootWalletKeys: utxolib.bitgo.RootWalletKeys, keyIndex: number, chainCode: number): string { @@ -30,11 +31,11 @@ export function getDescriptorForScriptType( }; switch (scriptType) { case 'p2sh': - return Descriptor.fromString(ast.formatNode({ sh: multi }), 'derivable'); + return miniscript.Descriptor.fromString(miniscript.ast.formatNode({ sh: multi }), 'derivable'); case 'p2shP2wsh': - return Descriptor.fromString(ast.formatNode({ sh: { wsh: multi } }), 'derivable'); + return miniscript.Descriptor.fromString(miniscript.ast.formatNode({ sh: { wsh: multi } }), 'derivable'); case 'p2wsh': - return Descriptor.fromString(ast.formatNode({ wsh: multi }), 'derivable'); + return miniscript.Descriptor.fromString(miniscript.ast.formatNode({ wsh: multi }), 'derivable'); default: throw new Error(`Unsupported script type ${scriptType}`); } diff --git a/modules/utxo-core/src/descriptor/psbt/assertSatisfiable.ts b/modules/utxo-core/src/descriptor/psbt/assertSatisfiable.ts index 46e7eefbb9..ae0a28cc05 100644 --- a/modules/utxo-core/src/descriptor/psbt/assertSatisfiable.ts +++ b/modules/utxo-core/src/descriptor/psbt/assertSatisfiable.ts @@ -8,8 +8,9 @@ * * The goal is not an exhaustive check, but to catch common mistakes. */ -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; import * as utxolib from '@bitgo/utxo-lib'; +import { miniscript } from '@bitgo/utxo-lib'; export const FINAL_SEQUENCE = 0xffffffff; @@ -18,7 +19,7 @@ export const FINAL_SEQUENCE = 0xffffffff; * @param descriptor */ export function getRequiredLocktime(descriptor: Descriptor | unknown): number | undefined { - if (descriptor instanceof Descriptor) { + if (descriptor instanceof miniscript.Descriptor) { return getRequiredLocktime(descriptor.node()); } if (typeof descriptor !== 'object' || descriptor === null) { diff --git a/modules/utxo-core/src/descriptor/psbt/createPsbt.ts b/modules/utxo-core/src/descriptor/psbt/createPsbt.ts index 618940ed39..8c6eb59e91 100644 --- a/modules/utxo-core/src/descriptor/psbt/createPsbt.ts +++ b/modules/utxo-core/src/descriptor/psbt/createPsbt.ts @@ -1,5 +1,5 @@ import * as utxolib from '@bitgo/utxo-lib'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; import { DerivedDescriptorWalletOutput, WithOptDescriptor } from '../Output'; import { Output } from '../../Output'; diff --git a/modules/utxo-core/src/descriptor/psbt/findDescriptors.ts b/modules/utxo-core/src/descriptor/psbt/findDescriptors.ts index 8326165a50..3bddee3663 100644 --- a/modules/utxo-core/src/descriptor/psbt/findDescriptors.ts +++ b/modules/utxo-core/src/descriptor/psbt/findDescriptors.ts @@ -10,7 +10,7 @@ We should take a look at a more robust and standard approach like this: https:// */ import { PsbtInput, PsbtOutput } from 'bip174/src/lib/interfaces'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; import { DescriptorMap } from '../DescriptorMap'; diff --git a/modules/utxo-core/src/descriptor/psbt/parse.ts b/modules/utxo-core/src/descriptor/psbt/parse.ts index 6e9822efbc..37061abe54 100644 --- a/modules/utxo-core/src/descriptor/psbt/parse.ts +++ b/modules/utxo-core/src/descriptor/psbt/parse.ts @@ -1,4 +1,4 @@ -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; import * as utxolib from '@bitgo/utxo-lib'; import { DescriptorMap } from '../DescriptorMap'; diff --git a/modules/utxo-core/src/descriptor/psbt/sign.ts b/modules/utxo-core/src/descriptor/psbt/sign.ts index eded1afceb..9c9ae457e1 100644 --- a/modules/utxo-core/src/descriptor/psbt/sign.ts +++ b/modules/utxo-core/src/descriptor/psbt/sign.ts @@ -1,7 +1,7 @@ import assert from 'assert'; import * as utxolib from '@bitgo/utxo-lib'; -import { Psbt as WasmPsbt } from '@bitgo/wasm-miniscript'; +import type { Psbt as WasmPsbt } from '@bitgo/wasm-miniscript'; /** These can be replaced when @bitgo/wasm-miniscript is updated */ export type SignPsbtInputResult = { Schnorr: string[] } | { Ecdsa: string[] }; diff --git a/modules/utxo-core/src/descriptor/psbt/wrap.ts b/modules/utxo-core/src/descriptor/psbt/wrap.ts index c94699e6f5..9c6d142d04 100644 --- a/modules/utxo-core/src/descriptor/psbt/wrap.ts +++ b/modules/utxo-core/src/descriptor/psbt/wrap.ts @@ -1,18 +1,19 @@ -import { Psbt as WasmPsbt } from '@bitgo/wasm-miniscript'; +import type { Psbt as WasmPsbt } from '@bitgo/wasm-miniscript'; import * as utxolib from '@bitgo/utxo-lib'; +import { miniscript } from '@bitgo/utxo-lib'; export function toWrappedPsbt(psbt: utxolib.bitgo.UtxoPsbt | utxolib.Psbt | Buffer | Uint8Array): WasmPsbt { if (psbt instanceof utxolib.bitgo.UtxoPsbt || psbt instanceof utxolib.Psbt) { psbt = psbt.toBuffer(); } if (psbt instanceof Buffer || psbt instanceof Uint8Array) { - return WasmPsbt.deserialize(psbt); + return miniscript.Psbt.deserialize(psbt); } throw new Error('Invalid input'); } export function toUtxoPsbt(psbt: WasmPsbt | Buffer | Uint8Array, network: utxolib.Network): utxolib.bitgo.UtxoPsbt { - if (psbt instanceof WasmPsbt) { + if (psbt instanceof miniscript.Psbt) { psbt = psbt.serialize(); } if (psbt instanceof Buffer || psbt instanceof Uint8Array) { diff --git a/modules/utxo-core/test/descriptor/fromFixedScriptWallet.ts b/modules/utxo-core/test/descriptor/fromFixedScriptWallet.ts index a1a100162f..8f92bcbb7b 100644 --- a/modules/utxo-core/test/descriptor/fromFixedScriptWallet.ts +++ b/modules/utxo-core/test/descriptor/fromFixedScriptWallet.ts @@ -1,13 +1,15 @@ import * as assert from 'node:assert/strict'; import * as utxolib from '@bitgo/utxo-lib'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import * as WasmMiniscript from '@bitgo/wasm-miniscript'; import { getDescriptorForScriptType, getNamedDescriptorsForRootWalletKeys, } from '../../src/descriptor/fromFixedScriptWallet'; +utxolib.initializeMiniscript(WasmMiniscript); + function getRootWalletKeys(derivationPrefixes?: utxolib.bitgo.Triple): utxolib.bitgo.RootWalletKeys { // This is a fixed script wallet, so we use a fixed key triple. // In practice, this would be derived from the wallet's root keys. @@ -77,7 +79,7 @@ function runTestGetDescriptorWithScriptType( scriptType ).scriptPubKey; - let descriptor: Descriptor; + let descriptor: WasmMiniscript.Descriptor; before(function () { descriptor = getDescriptorForScriptType(rootWalletKeys, scriptType, scope); @@ -124,7 +126,7 @@ function runTestGetDescriptorMap(customPrefix: utxolib.bitgo.Triple | un }); } -customPrefixes.forEach((customPrefix) => { +customPrefixes.forEach(async (customPrefix) => { scriptTypes.forEach((scriptType) => { index.forEach((index) => { scope.forEach((scope) => { diff --git a/modules/utxo-core/test/descriptor/psbt/assertSatisfiable.ts b/modules/utxo-core/test/descriptor/psbt/assertSatisfiable.ts index 4263ae88dd..8e89b2abb6 100644 --- a/modules/utxo-core/test/descriptor/psbt/assertSatisfiable.ts +++ b/modules/utxo-core/test/descriptor/psbt/assertSatisfiable.ts @@ -1,12 +1,15 @@ import * as assert from 'assert'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import * as utxolib from '@bitgo/utxo-lib'; +import * as WasmMiniscript from '@bitgo/wasm-miniscript'; import { getDefaultXPubs } from '../../../src/testutil/descriptor'; import { getRequiredLocktime } from '../../../src/descriptor'; -function d(s: string): Descriptor { - return Descriptor.fromString(s, 'derivable'); +utxolib.initializeMiniscript(WasmMiniscript); + +function d(s: string): WasmMiniscript.Descriptor { + return WasmMiniscript.Descriptor.fromString(s, 'derivable'); } describe('assertSatisfiable', function () { diff --git a/modules/utxo-core/test/descriptor/psbt/psbt.ts b/modules/utxo-core/test/descriptor/psbt/psbt.ts index 3e5d0372c5..d0a2446694 100644 --- a/modules/utxo-core/test/descriptor/psbt/psbt.ts +++ b/modules/utxo-core/test/descriptor/psbt/psbt.ts @@ -2,7 +2,7 @@ import assert from 'assert'; import * as utxolib from '@bitgo/utxo-lib'; import { BIP32Interface, ECPair, ECPairInterface } from '@bitgo/utxo-lib'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import * as WasmMiniscript from '@bitgo/wasm-miniscript'; import { PsbtParams, parse, toUtxoPsbt, toWrappedPsbt, ParsedDescriptorTransaction } from '../../../src/descriptor'; import { getFixture, getKeyTriple } from '../../../src/testutil'; @@ -17,11 +17,13 @@ import { } from '../../../src/testutil/descriptor'; import { getNewSignatureCount, signWithKey } from '../../../src/descriptor/psbt/sign'; +utxolib.initializeMiniscript(WasmMiniscript); + function normalize(v: unknown): unknown { if (typeof v === 'bigint') { return v.toString(); } - if (v instanceof Descriptor) { + if (v instanceof WasmMiniscript.Descriptor) { return v.toString(); } if (v instanceof Buffer) { @@ -104,7 +106,7 @@ function getStages( } type TestParams = { - descriptorSelf: Descriptor; + descriptorSelf: WasmMiniscript.Descriptor; stages: PsbtStage[]; } & ( | { diff --git a/modules/utxo-core/tsconfig.json b/modules/utxo-core/tsconfig.json index 6616905289..d7846c999d 100644 --- a/modules/utxo-core/tsconfig.json +++ b/modules/utxo-core/tsconfig.json @@ -7,7 +7,7 @@ "allowJs": false, "strict": true }, - "include": ["src/**/*", "test/**/*"], + "include": ["src/**/*", "test/**/*", "../utxo-lib/src/miniscript"], "exclude": ["node_modules"], "references": [ { diff --git a/modules/utxo-lib/package.json b/modules/utxo-lib/package.json index 24faf43f02..e1eb1de9db 100644 --- a/modules/utxo-lib/package.json +++ b/modules/utxo-lib/package.json @@ -47,6 +47,7 @@ ], "dependencies": { "@bitgo/blake2b": "^3.2.4", + "@bitgo/wasm-miniscript": "2.0.0-beta.7", "@brandonblack/musig": "^0.0.1-alpha.0", "@noble/curves": "1.8.1", "@noble/secp256k1": "1.6.3", diff --git a/modules/utxo-lib/src/index.ts b/modules/utxo-lib/src/index.ts index 1383bd6515..a72ab17895 100644 --- a/modules/utxo-lib/src/index.ts +++ b/modules/utxo-lib/src/index.ts @@ -18,6 +18,8 @@ export * from './noble_ecc'; export * as p2trPayments from './payments'; +export { initializeMiniscript, miniscript } from './miniscript'; + export { networks, Network, diff --git a/modules/utxo-lib/src/miniscript/index.ts b/modules/utxo-lib/src/miniscript/index.ts new file mode 100644 index 0000000000..deb5a22e55 --- /dev/null +++ b/modules/utxo-lib/src/miniscript/index.ts @@ -0,0 +1,66 @@ +import type { + ast as AstType, + Descriptor as DescriptorType, + Miniscript as MiniscriptType, + Psbt as PsbtType, +} from '@bitgo/wasm-miniscript'; + +interface WasmModule { + ast: typeof AstType; + Descriptor: typeof DescriptorType; + Miniscript: typeof MiniscriptType; + Psbt: typeof PsbtType; +} + +/** + * Shim class that provides synchronous access to the WASM module exports + */ +export class MiniscriptShim { + private static _instance: MiniscriptShim | null = null; + private _module: WasmModule | null = null; + + static getInstance(): MiniscriptShim { + if (!MiniscriptShim._instance) { + MiniscriptShim._instance = new MiniscriptShim(); + } + return MiniscriptShim._instance; + } + + /** + * Initialize the shim by loading the WASM module + */ + initialize(module: WasmModule): void { + this._module = module; + } + + private get module(): WasmModule { + if (!this._module) { + throw new Error('MiniscriptShim not initialized. Call initializeMiniscript() first.'); + } + return this._module; + } + + get ast(): typeof AstType { + return this.module.ast; + } + get Descriptor(): typeof DescriptorType { + return this.module.Descriptor; + } + get Miniscript(): typeof MiniscriptType { + return this.module.Miniscript; + } + get Psbt(): typeof PsbtType { + return this.module.Psbt; + } + get isInitialized(): boolean { + return this._module !== null; + } +} + +// Create singleton instance +export const miniscript = MiniscriptShim.getInstance(); + +// Export initialization function for consumers +export function initializeMiniscript(module: WasmModule): void { + miniscript.initialize(module); +} diff --git a/modules/utxo-staking/src/babylon/delegationMessage.ts b/modules/utxo-staking/src/babylon/delegationMessage.ts index 9878d79a0e..ff632336e6 100644 --- a/modules/utxo-staking/src/babylon/delegationMessage.ts +++ b/modules/utxo-staking/src/babylon/delegationMessage.ts @@ -8,7 +8,7 @@ import * as vendor from '@bitgo/babylonlabs-io-btc-staking-ts'; import * as babylonProtobuf from '@babylonlabs-io/babylon-proto-ts'; import * as bitcoinjslib from 'bitcoinjs-lib'; import * as utxolib from '@bitgo/utxo-lib'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; import { toXOnlyPublicKey } from '@bitgo/utxo-core'; import { signWithKey, toWrappedPsbt } from '@bitgo/utxo-core/descriptor'; diff --git a/modules/utxo-staking/src/babylon/descriptor.ts b/modules/utxo-staking/src/babylon/descriptor.ts index c938214751..acdebc5224 100644 --- a/modules/utxo-staking/src/babylon/descriptor.ts +++ b/modules/utxo-staking/src/babylon/descriptor.ts @@ -4,7 +4,8 @@ * https://github.com/babylonlabs-io/babylon/blob/v1.99.0-snapshot.250211/btcstaking/staking.go */ -import { Descriptor, ast } from '@bitgo/wasm-miniscript'; +import type { Descriptor, ast } from '@bitgo/wasm-miniscript'; +import { miniscript } from '@bitgo/utxo-lib'; import { StakingParams } from '@bitgo/babylonlabs-io-btc-staking-ts'; export function getUnspendableKey(): string { @@ -26,7 +27,7 @@ function multiArgs(threshold: number, keys: Buffer[]): [number, ...string[]] { } function taprootScriptOnlyFromAst(n: ast.TapTreeNode): Descriptor { - return Descriptor.fromString(ast.formatNode({ tr: [getUnspendableKey(), n] }), 'definite'); + return miniscript.Descriptor.fromString(miniscript.ast.formatNode({ tr: [getUnspendableKey(), n] }), 'definite'); } export class BabylonDescriptorBuilder { diff --git a/modules/utxo-staking/src/coreDao/descriptor.ts b/modules/utxo-staking/src/coreDao/descriptor.ts index a807731a86..caa1fd4754 100644 --- a/modules/utxo-staking/src/coreDao/descriptor.ts +++ b/modules/utxo-staking/src/coreDao/descriptor.ts @@ -1,5 +1,5 @@ -import { BIP32Interface } from '@bitgo/utxo-lib'; -import { ast } from '@bitgo/wasm-miniscript'; +import { BIP32Interface, miniscript } from '@bitgo/utxo-lib'; +import type { ast } from '@bitgo/wasm-miniscript'; /** * Script type for a descriptor. @@ -43,10 +43,10 @@ export function createMultiSigDescriptor( const inner: ast.MiniscriptNode = { and_v: [{ 'r:after': locktime }, { multi: [m, ...keys] }] }; switch (scriptType) { case 'sh': - return ast.formatNode({ sh: inner }); + return miniscript.ast.formatNode({ sh: inner }); case 'sh-wsh': - return ast.formatNode({ sh: { wsh: inner } }); + return miniscript.ast.formatNode({ sh: { wsh: inner } }); case 'wsh': - return ast.formatNode({ wsh: inner }); + return miniscript.ast.formatNode({ wsh: inner }); } } diff --git a/modules/utxo-staking/src/coreDao/transaction.ts b/modules/utxo-staking/src/coreDao/transaction.ts index ad2d8f5618..851b8d8cf0 100644 --- a/modules/utxo-staking/src/coreDao/transaction.ts +++ b/modules/utxo-staking/src/coreDao/transaction.ts @@ -1,5 +1,5 @@ import { Output } from '@bitgo/utxo-core'; -import { Descriptor } from '@bitgo/wasm-miniscript'; +import type { Descriptor } from '@bitgo/wasm-miniscript'; import { createCoreDaoOpReturnOutputScript, OpReturnParams } from './opReturn'; diff --git a/modules/utxo-staking/test/unit/babylon/bug71.ts b/modules/utxo-staking/test/unit/babylon/bug71.ts index 622868cfd3..1f8a48d5fb 100644 --- a/modules/utxo-staking/test/unit/babylon/bug71.ts +++ b/modules/utxo-staking/test/unit/babylon/bug71.ts @@ -5,6 +5,8 @@ import * as bitcoinjs from 'bitcoinjs-lib'; import * as utxolib from '@bitgo/utxo-lib'; import * as wasmMiniscript from '@bitgo/wasm-miniscript'; +utxolib.initializeMiniscript(wasmMiniscript); + // demonstrate https://github.com/babylonlabs-io/btc-staking-ts/issues/71 describe('btc-staking-ts bug #71', function () { let buf: Buffer; diff --git a/modules/utxo-staking/test/unit/babylon/transactions.ts b/modules/utxo-staking/test/unit/babylon/transactions.ts index 870043abfc..0f10fdef15 100644 --- a/modules/utxo-staking/test/unit/babylon/transactions.ts +++ b/modules/utxo-staking/test/unit/babylon/transactions.ts @@ -4,7 +4,7 @@ import * as vendor from '@bitgo/babylonlabs-io-btc-staking-ts'; import * as bitcoinjslib from 'bitcoinjs-lib'; import * as utxolib from '@bitgo/utxo-lib'; import { ECPairInterface } from '@bitgo/utxo-lib'; -import { ast, Descriptor, Miniscript } from '@bitgo/wasm-miniscript'; +import * as WasmMiniscript from '@bitgo/wasm-miniscript'; import { createAddressFromDescriptor, createPsbt, @@ -29,6 +29,8 @@ import { normalize } from '../fixtures.utils'; import { fromXOnlyPublicKey, getECKey, getECKeys, getXOnlyPubkey } from './key.utils'; import { getBitGoUtxoStakingMsgCreateBtcDelegation, getVendorMsgCreateBtcDelegation } from './vendor.utils'; +utxolib.initializeMiniscript(WasmMiniscript); + type WithFee = T & { fee: number }; type TransactionWithFee = WithFee<{ transaction: bitcoinjslib.Transaction }>; type PsbtWithFee = WithFee<{ psbt: bitcoinjslib.Psbt }>; @@ -112,7 +114,7 @@ function getStakingTransactionTreeVendor( function createUnstakingTransaction( stakingTx: vendor.TransactionResult, - stakingDescriptor: Descriptor, + stakingDescriptor: WasmMiniscript.Descriptor, changeAddress: string, { sequence }: { sequence: number } ): utxolib.Psbt { @@ -154,11 +156,14 @@ function getTestnetStakingParamsWithCovenant( }; } -function wpkhDescriptor(key: utxolib.ECPairInterface): Descriptor { - return Descriptor.fromString(ast.formatNode({ wpkh: key.publicKey.toString('hex') }), 'definite'); +function wpkhDescriptor(key: utxolib.ECPairInterface): WasmMiniscript.Descriptor { + return WasmMiniscript.Descriptor.fromString( + WasmMiniscript.ast.formatNode({ wpkh: key.publicKey.toString('hex') }), + 'definite' + ); } -function mockUtxo(descriptor: Descriptor): vendor.UTXO { +function mockUtxo(descriptor: WasmMiniscript.Descriptor): vendor.UTXO { const scriptPubKey = Buffer.from(descriptor.scriptPubkey()); const witnessScript = Buffer.from(descriptor.encode()); return { @@ -176,11 +181,11 @@ function parseScript(key: string, script: unknown) { if (!Buffer.isBuffer(script)) { throw new Error('script must be a buffer'); } - const ms = Miniscript.fromBitcoinScript(script, 'tap'); + const ms = WasmMiniscript.Miniscript.fromBitcoinScript(script, 'tap'); return { script: script.toString('hex'), miniscript: ms.toString(), - miniscriptAst: ast.fromMiniscript(ms), + miniscriptAst: WasmMiniscript.ast.fromMiniscript(ms), scriptASM: utxolib.script.toASM(script).split(/\s+/), }; } @@ -219,12 +224,14 @@ async function assertTransactionEqualsFixture(fixtureName: string, tx: unknown): await assertEqualsFixture(fixtureName, normalize(tx)); } -function assertEqualsMiniscript(script: Buffer, miniscript: ast.MiniscriptNode): void { - const ms = Miniscript.fromBitcoinScript(script, 'tap'); - assert.deepStrictEqual(ast.fromMiniscript(ms), miniscript); +function assertEqualsMiniscript(script: Buffer, miniscript: WasmMiniscript.ast.MiniscriptNode): void { + const ms = WasmMiniscript.Miniscript.fromBitcoinScript(script, 'tap'); + assert.deepStrictEqual(WasmMiniscript.ast.fromMiniscript(ms), miniscript); assert.deepStrictEqual( script.toString('hex'), - Buffer.from(Miniscript.fromString(ast.formatNode(miniscript), 'tap').encode()).toString('hex') + Buffer.from( + WasmMiniscript.Miniscript.fromString(WasmMiniscript.ast.formatNode(miniscript), 'tap').encode() + ).toString('hex') ); } @@ -249,7 +256,7 @@ function assertEqualScripts(descriptorBuilder: BabylonDescriptorBuilder, builder } } -function assertEqualOutputScript(outputInfo: { scriptPubKey: Buffer }, descriptor: Descriptor) { +function assertEqualOutputScript(outputInfo: { scriptPubKey: Buffer }, descriptor: WasmMiniscript.Descriptor) { assert.strictEqual(outputInfo.scriptPubKey.toString('hex'), Buffer.from(descriptor.scriptPubkey()).toString('hex')); } diff --git a/modules/utxo-staking/test/unit/coreDao/descriptor.ts b/modules/utxo-staking/test/unit/coreDao/descriptor.ts index 31a736e2a8..ab41028c60 100644 --- a/modules/utxo-staking/test/unit/coreDao/descriptor.ts +++ b/modules/utxo-staking/test/unit/coreDao/descriptor.ts @@ -1,14 +1,16 @@ import * as assert from 'assert'; +import * as WasmMiniscript from '@bitgo/wasm-miniscript'; import * as utxolib from '@bitgo/utxo-lib'; -import { Descriptor } from '@bitgo/wasm-miniscript'; import { getFixture } from '@bitgo/utxo-core/testutil'; import { createMultiSigDescriptor, decodeTimelock } from '../../../src/coreDao'; import { finalizePsbt, updateInputWithDescriptor } from './utils'; -describe('descriptor', function () { +utxolib.initializeMiniscript(WasmMiniscript); + +describe('descriptor', async function () { const baseFixturePath = 'test/fixtures/coreDao/descriptor/'; const rootWalletKeys = utxolib.testutil.getDefaultWalletKeys(); const key1 = rootWalletKeys.triple[0]; @@ -45,7 +47,7 @@ describe('descriptor', function () { }); it('has expected AST', async function () { - const descriptor = Descriptor.fromString( + const descriptor = WasmMiniscript.Descriptor.fromString( createMultiSigDescriptor(scriptType, validLocktime, m, keys, false), 'derivable' ); @@ -54,7 +56,7 @@ describe('descriptor', function () { }); it('has expected asm', async function () { - const descriptor = Descriptor.fromString( + const descriptor = WasmMiniscript.Descriptor.fromString( createMultiSigDescriptor(scriptType, validLocktime, m, keys, false), 'derivable' ); @@ -64,7 +66,7 @@ describe('descriptor', function () { it('can be signed', async function () { // Derive the script from the descriptor - const descriptor = Descriptor.fromString( + const descriptor = WasmMiniscript.Descriptor.fromString( createMultiSigDescriptor(scriptType, validLocktime, m, keys, false), 'derivable' ); @@ -147,7 +149,7 @@ describe('descriptor', function () { [Buffer.from(pubkey1, 'hex'), Buffer.from(pubkey2, 'hex')], false ); - const descriptorASM = Descriptor.fromString(descriptor, 'definite').toAsmString(); + const descriptorASM = WasmMiniscript.Descriptor.fromString(descriptor, 'definite').toAsmString(); assert.deepStrictEqual(redeemScriptASM, descriptorASM); }); }); diff --git a/modules/utxo-staking/test/unit/coreDao/utils.ts b/modules/utxo-staking/test/unit/coreDao/utils.ts index c96edec608..bfe45339f4 100644 --- a/modules/utxo-staking/test/unit/coreDao/utils.ts +++ b/modules/utxo-staking/test/unit/coreDao/utils.ts @@ -1,8 +1,14 @@ -import { Descriptor, Psbt } from '@bitgo/wasm-miniscript'; import * as utxolib from '@bitgo/utxo-lib'; +import * as WasmMiniscript from '@bitgo/wasm-miniscript'; -export function updateInputWithDescriptor(psbt: utxolib.Psbt, inputIndex: number, descriptor: Descriptor): void { - const wrappedPsbt = Psbt.deserialize(psbt.toBuffer()); +utxolib.initializeMiniscript(WasmMiniscript); + +export function updateInputWithDescriptor( + psbt: utxolib.Psbt, + inputIndex: number, + descriptor: WasmMiniscript.Descriptor +): void { + const wrappedPsbt = WasmMiniscript.Psbt.deserialize(psbt.toBuffer()); wrappedPsbt.updateInputWithDescriptor(inputIndex, descriptor); psbt.data.inputs[inputIndex] = utxolib.bitgo.UtxoPsbt.fromBuffer(Buffer.from(wrappedPsbt.serialize()), { network: utxolib.networks.bitcoin, @@ -10,7 +16,7 @@ export function updateInputWithDescriptor(psbt: utxolib.Psbt, inputIndex: number } export function finalizePsbt(psbt: utxolib.Psbt): utxolib.bitgo.UtxoPsbt { - const wrappedPsbt = Psbt.deserialize(psbt.toBuffer()); + const wrappedPsbt = WasmMiniscript.Psbt.deserialize(psbt.toBuffer()); wrappedPsbt.finalize(); return utxolib.bitgo.UtxoPsbt.fromBuffer(Buffer.from(wrappedPsbt.serialize()), { network: utxolib.networks.bitcoin, diff --git a/modules/utxo-staking/test/unit/fixtures.utils.ts b/modules/utxo-staking/test/unit/fixtures.utils.ts index b548b77842..3a4f8309ae 100644 --- a/modules/utxo-staking/test/unit/fixtures.utils.ts +++ b/modules/utxo-staking/test/unit/fixtures.utils.ts @@ -1,4 +1,4 @@ -import { Descriptor } from '@bitgo/wasm-miniscript'; +import * as wasmMiniscript from '@bitgo/wasm-miniscript'; import * as utxolib from '@bitgo/utxo-lib'; import * as bitcoinjslib from 'bitcoinjs-lib'; import { toPlainObjectFromTx, toPlainObjectFromPsbt } from '@bitgo/utxo-core/testutil/descriptor'; @@ -7,7 +7,7 @@ export function normalize(v: unknown): unknown { if (typeof v === 'bigint') { return v.toString(); } - if (v instanceof Descriptor) { + if (v instanceof wasmMiniscript.Descriptor) { return v.toString(); } if (v instanceof Uint8Array) { diff --git a/modules/web-demo/package.json b/modules/web-demo/package.json index 5ca96da03d..610c155270 100644 --- a/modules/web-demo/package.json +++ b/modules/web-demo/package.json @@ -24,7 +24,6 @@ "precommit": "yarn lint-staged" }, "dependencies": { - "@bitgo/abstract-utxo": "^9.21.3", "@bitgo/key-card": "^0.24.10", "@bitgo/sdk-api": "^1.64.1", "@bitgo/sdk-coin-ada": "^4.11.3", @@ -63,6 +62,7 @@ "@bitgo/sdk-lib-mpc": "^10.5.0", "@bitgo/sdk-opensslbytes": "^2.0.0", "@bitgo/statics": "^54.5.0", + "@bitgo/utxo-lib": "^11.6.1", "bitgo": "^48.2.0", "lodash": "^4.17.15", "react": "^17.0.2", diff --git a/modules/web-demo/src/components/WasmMiniscript/index.tsx b/modules/web-demo/src/components/WasmMiniscript/index.tsx index 7bf8ba1e57..6f4d6b5f86 100644 --- a/modules/web-demo/src/components/WasmMiniscript/index.tsx +++ b/modules/web-demo/src/components/WasmMiniscript/index.tsx @@ -1,6 +1,5 @@ import React, { useState } from 'react'; - -import * as AbstractUtxo from '@bitgo/abstract-utxo'; +import * as utxolib from '@bitgo/utxo-lib'; const defaultDescriptor = 'wpkh(xpub661MyMwAqRbcFQpwd6c6aaioiXWuygdeknqE8v6PSNusNjwZypj1uXTVNysfsFPEDL6X3yS1kL6JeWyy9bAiR97Gz8KD9Z1W54uBw9U9j2t/*)'; @@ -8,7 +7,7 @@ const defaultDescriptor = export default function () { const [descriptorString] = useState(defaultDescriptor); - const descriptor = AbstractUtxo.descriptor.Descriptor.fromString( + const descriptor = utxolib.miniscript.Descriptor.fromString( descriptorString, 'derivable', );