Skip to content

Repository files navigation

Bitcoin Descriptors Library

This library is designed to parse and create Bitcoin Descriptors, including Miniscript and Taproot script trees and generate Partially Signed Bitcoin Transactions (PSBTs). It also provides PSBT signers and finalizers for single-key, BIP32 and hardware-wallet flows.

This library uses an underlying Bitcoin library for creating, signing & decoding transactions. Users can pick:

  • @bitcoinerlab/descriptors for the bitcoinjs-lib and bitcoinjs family of libraries: battle-tested and broadly used.
  • @bitcoinerlab/descriptors-scure for @scure/btc-signer and the noble/scure family of libraries: audited, fast and minimal.
  • @bitcoinerlab/descriptors-core as the low-level package used under the preset packages. Most users should treat it as internal, but advanced users can use it directly when they need explicit control over backend setup.

TL;DR (quick start)

Using @bitcoinerlab/descriptors-scure? See the scure variant right below.

npm install @bitcoinerlab/descriptors @bitcoinerlab/miniscript-policies

This quick example compiles a timelocked Miniscript policy, creates a descriptor address to fund, then builds, signs, and finalizes a PSBT that spends that funded UTXO and prints the final transaction hex.

import { ECPair, Output, Psbt, signers } from '@bitcoinerlab/descriptors'; // bitcoinjs-ready package

const ecpair = ECPair.makeRandom(); // Creates a signer for a single-key wallet

// Timelocked policy: signature + relative timelock (older)
const { miniscript } = compilePolicy('and(pk(@bob),older(10))');

const descriptor = `wsh(${miniscript.replace('@bob', toHex(ecpair.publicKey))})`;

// 1) Build the output description
const fundedOutput = new Output({ descriptor });
const address = fundedOutput.getAddress(); // Fund this address

// 2) Prepare PSBT input/output
const psbt = new Psbt();

const txHex = 'FUNDING_TX_HEX'; // hex of the tx that funded the address above
const vout = 0; // Output index (vout) of that UTXO within FUNDING_TX_HEX
const finalizeInput = fundedOutput.updatePsbtAsInput({ psbt, txHex, vout });

const recipient = new Output({
  descriptor: 'addr(bc1qgw6xanldsz959z45y4dszehx4xkuzf7nfhya8x)'
}); // Final address where we'll send the funds after timelock
recipient.updatePsbtAsOutput({ psbt, value: 10000n }); // input covers this+fees

// 3) Sign and finalize
signers.signECPair({ psbt, ecpair });
finalizeInput({ psbt });

console.log('Push this: ' + psbt.extractTransaction().toHex());
Click to see the scure variant
npm install @bitcoinerlab/descriptors-scure @bitcoinerlab/miniscript-policies
import { Output, btc, secp256k1, signers } from '@bitcoinerlab/descriptors-scure';

const privKey = btc.utils.randomPrivateKeyBytes();
const pubkey = secp256k1.getPublicKey(privKey, true);

// Timelocked policy: signature + relative timelock (older)
const { miniscript } = compilePolicy('and(pk(@bob),older(10))');

const descriptor = `wsh(${miniscript.replace('@bob', toHex(pubkey))})`;

// 1) Build the output description
const fundedOutput = new Output({ descriptor });
const address = fundedOutput.getAddress(); // Fund this address

// 2) Prepare transaction input/output
const psbt = new btc.Transaction();

const txHex = 'FUNDING_TX_HEX'; // hex of the tx that funded the address above
const vout = 0; // Output index (vout) of that UTXO within FUNDING_TX_HEX
const finalizeInput = fundedOutput.updatePsbtAsInput({ psbt, txHex, vout });

const recipient = new Output({
  descriptor: 'addr(bc1qgw6xanldsz959z45y4dszehx4xkuzf7nfhya8x)'
});
recipient.updatePsbtAsOutput({ psbt, value: 10000n }); // input covers this+fees

// 3) Sign and finalize
signers.signPrivKey({ psbt, privKey });
finalizeInput({ psbt });

console.log('Push this: ' + psbt.hex);

Features

  • Parses and creates Bitcoin Descriptors (including those based on the Miniscript language).
  • Supports Taproot descriptors with trees: tr(KEY,TREE) (tapscript).
  • Generates Partially Signed Bitcoin Transactions (PSBTs).
  • Provides PSBT finalizers and signers for single-signature, BIP32 and hardware-wallet flows.
  • Provides optional Ledger and BitBox integrations for both bitcoinjs and Scure.

Version Compatibility

Starting in 3.x, @bitcoinerlab/descriptors is aligned with the modern bitcoinjs stack (bitcoinjs-lib 7.x).

In practical terms, this means:

  • byte arrays are represented as Uint8Array;
  • satoshi values are represented as bigint.

If you need older bitcoinjs versions, keep using @bitcoinerlab/descriptors 2.x. If you want Taproot trees (tr(KEY,TREE)), use 3.x+.

Starting in 3.1.x, scure users can install @bitcoinerlab/descriptors-scure.

Version 3.2.0 requires Node.js >=20.19.0.

Concepts

This library has two main capabilities related to Bitcoin descriptors. Firstly, it can generate addresses and scriptPubKeys from descriptors. These addresses and scriptPubKeys can be used to receive funds from other parties. Secondly, the library is able to sign transactions and spend unspent outputs described by those same descriptors. In order to do this, the descriptors must first be set into a PSBT.

If you are not familiar with Bitcoin descriptors and partially signed Bitcoin transactions (PSBTs), click on the section below to expand and read more about these concepts.

Concepts

Descriptors

In Bitcoin, a transaction consists of a set of inputs that are spent into a different set of outputs. Each input spends an output in a previous transaction. A Bitcoin descriptor is a string of text that describes the rules and conditions required to spend an output in a transaction.

For example, wpkh(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9) is a descriptor that describes a pay-to-witness-public-key-hash (P2WPKH) type of output with the specified public key. If you know the corresponding private key for the transaction for which this descriptor is an output, you can spend it.

Descriptors can express much more complex conditions, such as multi-party cooperation, time-locked outputs and more. These conditions can be expressed using the Bitcoin Miniscript language, which is a way of writing Bitcoin Scripts in a structured and more easily understandable way.

Partially Signed Bitcoin Transactions (PSBTs)

A PSBT (Partially Signed Bitcoin Transaction) is a format for sharing Bitcoin transactions between different parties.

PSBTs come in handy when working with descriptors, especially when using scripts, because they allow multiple parties to collaborate in the signing process. This is especially useful when using hardware wallets or other devices that require separate signatures or authorizations.

Usage

Before we dive in, it's worth mentioning that we have several comprehensive guides available covering different aspects of the library. These guides provide explanations and code examples in interactive playgrounds, allowing you to see the changes in the output as you modify the code. This hands-on learning experience, combined with clear explanations, helps you better understand how to use the library effectively. Check out the available guides here.

Furthermore, we've meticulously documented our API. For an in-depth look into Classes, functions and types, head over here.

For most users, install the package that matches your preferred Bitcoin library.

Bitcoinjs backend:

npm install @bitcoinerlab/descriptors

Scure/noble backend:

npm install @bitcoinerlab/descriptors-scure

Choose one backend for an application. Loading both preset packages together is not supported because existing Outputs and PSBTs must keep using the backend that created them. If you need both, isolate them in separate processes or workers.

If you plan to compile policy strings into Miniscript in your app, also install:

npm install @bitcoinerlab/miniscript-policies

The examples below keep the bitcoinjs stack visible by default. When backend-specific code differs, a collapsible scure variant is shown right below.

Compatibility note for existing @bitcoinerlab/descriptors users

The root @bitcoinerlab/descriptors package still keeps a few 3.x compatibility shims, but they are deprecated and planned for removal in the next major release:

  • DescriptorsFactory() and DescriptorsFactory(ecc) on the root package

For new code, prefer the preset top-level exports directly. DescriptorsFactory(...) on @bitcoinerlab/descriptors is kept only for 3.x backwards compatibility and is planned to stop being a public preset-package API in the next major release, including the custom ecc initialization path.

For a minimal end-to-end scure example, see test/integration/scure.ts.

The library can be split into four main parts:

  • The Output class is the central component for managing descriptors. It facilitates the creation of outputs to receive funds and enables the signing and finalization of PSBTs (Partially Signed Bitcoin Transactions) for spending UTXOs (Unspent Transaction Outputs).
  • PSBT signers and finalizers, which are used to manage the signing and finalization of PSBTs.
  • keyExpressions and scriptExpressions, which provide functions to create key and standard descriptor expressions (strings) from structured data.
  • Hardware wallet integration, covered in its own section below.

Output class

For normal usage, import Output directly from the preset package you chose.

import { Output } from '@bitcoinerlab/descriptors'; // bitcoinjs-ready package
import { Output } from '@bitcoinerlab/descriptors-scure'; // scure-ready package
Advanced: custom bitcoinjs-compatible ecc implementation

Most users do not need DescriptorsFactory(...) directly. It remains useful if you want to swap the default @bitcoinerlab/secp256k1 binding for another tiny-secp256k1-compatible implementation.

import * as ecc from '@bitcoinerlab/secp256k1'; // or another tiny-secp256k1-compatible implementation
import {
  DescriptorsFactory,
  createBitcoinjsLib
} from '@bitcoinerlab/descriptors';

const { Output } = DescriptorsFactory(createBitcoinjsLib(ecc));

Once set up, you can obtain an instance for an output, described by a descriptor such as a wpkh, as follows:

const wpkhOutput = new Output({
  descriptor:
    'wpkh(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9)'
});

For advanced spend-path control (for example signersPubKeys, taprootSpendPath, and tapLeaf), see Spending-path selection: from WSH Miniscript to Taproot.

Detailed information about constructor parameters can be found in the API documentation and in this Stack Exchange answer.

Some commonly used constructor parameters are:

  • index: for ranged descriptors ending in *.
  • change: for multipath key expressions such as /** or /<0;1>/*. For example, in /<0;1>/*, use change: 0 or change: 1.

The Output class offers various helpful methods, including getAddress(), which returns the address associated with the descriptor, getScriptPubKey(), which returns the scriptPubKey for the descriptor, expand(), which decomposes a descriptor into its elemental parts, updatePsbtAsInput() and updatePsbtAsOutput().

The library supports a wide range of descriptor types, including:

  • Pay-to-Public-Key-Hash (P2PKH): pkh(KEY)
  • Pay-to-Witness-Public-Key-Hash (P2WPKH): wpkh(KEY)
  • Pay-to-Script-Hash (P2SH): sh(SCRIPT)
  • Pay-to-Witness-Script-Hash (P2WSH): wsh(SCRIPT)
  • Pay-to-Taproot (P2TR) with key-only or script tree: tr(KEY) and tr(KEY,TREE)
  • Address-based descriptors: addr(ADDRESS)

These descriptors can be used with various key expressions, including raw public keys, BIP32 derivation paths and more.

For example, a Taproot descriptor with script leaves can look like:

tr(INTERNAL_KEY,{pk(KEY_A),{pk(KEY_B),and_v(v:pk(KEY_C),older(144))}})

This means the output has an internal-key spend path and additional script-path options inside the tree.

The updatePsbtAsInput() method is an essential part of the library, responsible for adding an input to the PSBT corresponding to the UTXO described by the descriptor. Additionally, when the descriptor expresses an absolute time-spending condition, such as "This UTXO can only be spent after block N", updatePsbtAsInput() adds timelock information to the PSBT.

To call updatePsbtAsInput(), use the following syntax:

import { Psbt } from '@bitcoinerlab/descriptors';
const psbt = new Psbt();
const inputFinalizer = output.updatePsbtAsInput({ psbt, txHex, vout, rbf });
Click to see the scure variant
import { btc } from '@bitcoinerlab/descriptors-scure';

const psbt = new btc.Transaction();
const inputFinalizer = output.updatePsbtAsInput({ psbt, txHex, vout, rbf });

Here, psbt refers to either a bitcoinjs-lib Psbt class instance or an @scure/btc-signer Transaction, depending on the backend you chose. The parameter txHex denotes a hex string that serializes the previous transaction containing this output. Meanwhile, vout is an integer that marks the position of the output within that transaction. Finally, rbf is an optional parameter (defaulting to true) used to indicate whether the transaction uses Replace-By-Fee (RBF). When RBF is enabled, transactions can be replaced while they are in the mempool with others that have higher fees. Note that RBF is enabled for the entire transaction if at least one input signals it. Also, note that transactions using relative time locks inherently opt into RBF due to the nSequence range used.

The method returns the inputFinalizer() function. This finalizer function completes a PSBT input by adding the unlocking script (scriptWitness or scriptSig) that satisfies the previous output's spending conditions. Bear in mind that both scriptSig and scriptWitness incorporate signatures. As such, you should complete all necessary signing operations before calling inputFinalizer(). Detailed explanations on the inputFinalizer method can be found in the Signers and Finalizers section.

Similarly, updatePsbtAsOutput allows you to add an output to a PSBT. For instance, to configure a psbt that sends 10,000 sats to the SegWit address bc1qgw6xanldsz959z45y4dszehx4xkuzf7nfhya8x:

const recipientOutput = new Output({
  descriptor: `addr(bc1qgw6xanldsz959z45y4dszehx4xkuzf7nfhya8x)`
});
recipientOutput.updatePsbtAsOutput({ psbt, value: 10000n });

For further information on using the Output class, refer to the comprehensive guides that offer explanations and playgrounds to help learn the module. For specific details on the methods, refer directly to the API.

Parsing Descriptors with expand()

Most applications do not need expand() for normal receive/spend flows. It is mainly useful for debugging and introspection (for example, checking expanded expressions, key mappings, scripts, and parsed metadata).

import { expand } from '@bitcoinerlab/descriptors'; // or '@bitcoinerlab/descriptors-scure' for scure

const info = expand({ descriptor });

For full details on returned fields, refer to the API.

Spending-path selection: from WSH Miniscript to Taproot

When a descriptor has more than one valid way to spend, the library needs to know which path you intend to use.

For wsh(miniscript) and sh(wsh(miniscript)), this is usually done with signersPubKeys: you pass the public keys expected to sign and the library selects the most optimal satisfiable branch.

signersPubKeys is passed as an array of public keys (Uint8Array[]). If omitted, the library assumes all descriptor keys may sign.

Example with two BIP32-derived keys and one preferred signer:

import { randomBytes } from 'crypto';
import { BIP32, Output, keyExpressionBIP32 } from '@bitcoinerlab/descriptors';

const masterNode = BIP32.fromSeed(randomBytes(32));

const originPath = "/84'/0'/0'";

const keyPathA = '/0/0';
const keyPathB = '/0/1';

const keyExprA = keyExpressionBIP32({ masterNode, originPath, keyPath: keyPathA });
const keyExprB = keyExpressionBIP32({ masterNode, originPath, keyPath: keyPathB });

const signerPubKeyA = masterNode.derivePath(`m${originPath}${keyPathA}`).publicKey;

// Two possible branches:
// - branch 1: signature by keyA + older(10)
// - branch 2: signature by keyB (no timelock)
const output = new Output({
  descriptor: `wsh(andor(pk(${keyExprA}),older(10),pk(${keyExprB})))`,
  signersPubKeys: [signerPubKeyA] // choose the keyA (timelock branch)
});
Click to see the scure variant
import { randomBytes } from '@noble/hashes/utils.js';
import { HDKey, Output, keyExpressionBIP32 } from '@bitcoinerlab/descriptors-scure';

const masterNode = HDKey.fromMasterSeed(randomBytes(32));

const originPath = "/84'/0'/0'";

const keyPathA = '/0/0';
const keyPathB = '/0/1';

const keyExprA = keyExpressionBIP32({ masterNode, originPath, keyPath: keyPathA });
const keyExprB = keyExpressionBIP32({ masterNode, originPath, keyPath: keyPathB });

const signerPubKeyA = masterNode.derive(`m${originPath}${keyPathA}`).publicKey;

const output = new Output({
  descriptor: `wsh(andor(pk(${keyExprA}),older(10),pk(${keyExprB})))`,
  signersPubKeys: [signerPubKeyA]
});

Taproot uses the same idea. For tr(KEY,TREE), signersPubKeys helps determine which leaves are satisfiable and which satisfiable path is more optimal. In addition, Taproot provides two optional controls:

  • taprootSpendPath ('key' | 'script') to force key-path or script-path spending.

  • tapLeaf to force a specific script leaf when using script path.

    If taprootSpendPath is omitted for tr(KEY,TREE), the library uses script path and auto-selects the most optimal satisfiable leaf from available spending data (including signersPubKeys and preimages when relevant).

If you specifically plan to spend from the internal key, set:

new Output({
  descriptor: 'tr(INTERNAL_KEY,{pk(KEY_A),pk(KEY_B)})',
  taprootSpendPath: 'key'
});

If you want to force a specific script leaf:

new Output({
  descriptor: 'tr(INTERNAL_KEY,{pk(KEY_A),pk(KEY_B)})',
  taprootSpendPath: 'script',
  tapLeaf: 'pk(KEY_A)'
});

These spending-path parameters (signersPubKeys, taprootSpendPath, tapLeaf) are only needed when spending/finalizing UTXOs with multiple candidate paths. They are not needed just to derive addresses or scriptPubKeys.

For a focused walkthrough of constructor choices (including signersPubKeys) and practical usage of updatePsbtAsInput, getAddress and getScriptPubKey, see this Stack Exchange answer.

Signers and Finalizers

This library encompasses a PSBT finalizer as well as signer helpers for single-key and BIP32 flows. Device-backed signing uses the same PSBT model, but the device setup is separate.

To incorporate these functionalities, use the following import statement:

import { signers } from '@bitcoinerlab/descriptors'; // or '@bitcoinerlab/descriptors-scure' for scure

For signing operations, utilize the methods provided by the signers:

// `psbt` here is a bitcoinjs-lib `Psbt` (for example: `const psbt = new Psbt()`)

// For BIP32 - https://github.com/bitcoinjs/bip32
signers.signBIP32({ psbt, masterNode }); // Here, `masterNode` is a bitcoinjs `BIP32Interface` (see examples above)

// For ECPair - https://github.com/bitcoinjs/ecpair
signers.signECPair({ psbt, ecpair }); // Here, `ecpair` is a bitcoinjs `ECPairInterface`
Click to see the scure variant
// `psbt` here is an `@scure/btc-signer` `Transaction`
// (for example: `const psbt = new btc.Transaction()`)

// For BIP32 with @scure/bip32
signers.signBIP32({ psbt, masterNode }); // Here, `masterNode` is an `HDKey` (see examples above)

// For raw private keys
signers.signPrivKey({ psbt, privKey }); // Here, `privKey` is a 32-byte `Uint8Array`
signers.signInputPrivKey({ psbt, index: 0, privKey }); // Same `privKey` type as above

Hardware-wallet signers follow the same pattern after the device session has been created.

Finalizing the psbt

When finalizing the psbt, the updatePsbtAsInput method plays a key role. When invoked, the output.updatePsbtAsInput() sets up the psbt by designating the output as an input and, if required, adjusts the transaction locktime. In addition, it returns a inputFinalizer function tailored for this specific psbt input.

Procedure
  1. For each unspent output from a previous transaction that you're referencing in a psbt as an input to be spent, call the updatePsbtAsInput method:

    const inputFinalizer = output.updatePsbtAsInput({ psbt, txHex, vout });
  2. Once you've completed the necessary signing operations on the psbt, use the returned finalizer function on each input:

    inputFinalizer({ psbt });
Important Notes
  • The finalizer function returned from updatePsbtAsInput adds the necessary unlocking script (scriptWitness or scriptSig) that satisfies the Output's spending conditions. Remember, both scriptSig and scriptWitness contain signatures. Ensure that all necessary signing operations are completed before finalizing.

  • txHex is required for non-Segwit inputs. For Segwit inputs, the API also accepts txId and value, but using the full txHex is strongly recommended for security because it lets the library verify more of the previous transaction and helps protect against fee attacks. See Trezor's explanation of why hardware wallets need the previous transaction. For supported hardware-wallet signing, always pass the full txHex, including for Segwit inputs.

Key Expressions and Script Expressions

This library also provides a series of function helpers designed to streamline the generation of descriptor strings. These strings can serve as input parameters in the Output class constructor. These helpers are nested within the scriptExpressions module. You can import them as illustrated below:

import { scriptExpressions } from '@bitcoinerlab/descriptors'; // or '@bitcoinerlab/descriptors-scure' for scure

Within the root scriptExpressions module, there are functions designed to generate descriptors for commonly used BIP32-based scripts, such as pkhBIP32(), shWpkhBIP32() and wpkhBIP32(). Refer to the API for a detailed list and further information.

When using BIP32-based descriptors, the following parameters are required for the scriptExpressions functions:

pkhBIP32(params: {
  masterNode: BIP32Interface; //bitcoinjs-lib BIP32 - https://github.com/bitcoinjs/bip32
  network?: Network; //A bitcoinjs-lib network
  account: number;
  change?: number | undefined; //0 -> external (receive), 1 -> internal (change)
  index?: number | undefined | '*';
  keyPath?: string; //You can use change & index or a keyPath such as "/0/0"
  isPublic?: boolean; //Whether to use xpub or xprv
})
Click to see the scure variant
pkhBIP32(params: {
  masterNode: HDKey; // @scure/bip32 - https://github.com/paulmillr/scure-bip32
  network?: Network;
  account: number;
  change?: number | undefined;
  index?: number | undefined | '*';
  keyPath?: string;
  isPublic?: boolean;
})

The keyExpressions category includes functions that generate string representations of key expressions for public keys.

This library includes keyExpressionBIP32 for BIP32 key expressions. It can be imported as follows:

import { keyExpressionBIP32 } from '@bitcoinerlab/descriptors'; // or '@bitcoinerlab/descriptors-scure' for scure

The parameters required for these functions are:

function keyExpressionBIP32({
  masterNode: BIP32Interface; //bitcoinjs-lib BIP32 - https://github.com/bitcoinjs/bip32
  originPath: string;
  change?: number | undefined; //0 -> external (receive), 1 -> internal (change)
  index?: number | undefined | '*';
  keyPath?: string | undefined;
  isPublic?: boolean;
});
Click to see the scure variant
function keyExpressionBIP32({
  masterNode: HDKey; // @scure/bip32 - https://github.com/paulmillr/scure-bip32
  originPath: string;
  change?: number | undefined;
  index?: number | undefined | '*';
  keyPath?: string | undefined;
  isPublic?: boolean;
});

This function generates strings that fully define BIP32 keys. For example:

[d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*

Read Bitcoin Core descriptors documentation to learn more about Key Expressions.

Hardware Wallet Integration

Ledger and BitBox support is available through separate entrypoints:

Backend Ledger BitBox
bitcoinjs @bitcoinerlab/descriptors/ledger @bitcoinerlab/descriptors/bitbox
Scure @bitcoinerlab/descriptors-scure/ledger @bitcoinerlab/descriptors-scure/bitbox

Applications import only the device support they use, so unused hardware-wallet code and vendor packages are not loaded with the main package.

connect(...) returns a Session that owns the device connection. Pass that session to hardware-wallet operations and close it when finished. Persist the JSON-safe Store, not the live session, so cached keys and policy information can be reused after reconnecting.

See the Hardware Wallets guide for setup, policy registration, signing, React Native support, device limitations and real-device tests.

Additional Resources

For more information, refer to the following resources:

  • Guides: Comprehensive explanations and playgrounds to help you learn how to use the module.

  • API: Dive into the details of the Classes, functions and types.

  • Stack Exchange answer: Focused explanation on the constructor, specifically the signersPubKeys parameter and the usage of updatePsbtAsInput, getAddress and getScriptPubKey.

  • Integration tests: End-to-end examples for representative software and hardware-wallet flows.

  • Local Documentation: Generate comprehensive API documentation from the source code:

    git clone https://github.com/bitcoinerlab/descriptors
    cd descriptors/
    npm install
    npm run docs

    The generated documentation will be available in the docs/ directory. Open the index.html file to view the documentation.

Authors and Contributors

The project was initially developed and is currently maintained by Jose-Luis Landabaso. Contributions and help from other developers are welcome.

Here are some resources to help you get started with contributing:

Building from source

To download the source code and build the project, follow these steps:

  1. Clone the repository:
git clone https://github.com/bitcoinerlab/descriptors.git
  1. Install the dependencies:
npm install
  1. Build the project:
npm run build

This will build the project and generate the necessary files in the dist directory.

Testing

Before committing any code, make sure it passes all tests.

Run unit tests:

npm run test:unit

Run the full test pipeline (lint + build + unit + integration):

npm run test

Integration tests require Docker. Make sure the docker command is installed and available in your PATH. When integration tests run, they automatically start or reuse a local container with the regtest services needed by this repository.

Hardware-wallet tests require real devices and are not part of the normal test pipeline. Run npm run test:ledger or npm run test:bitbox for manual device checks. Both commands run lint and build first, then test the bitcoinjs and Scure backends.

License

This project is licensed under the MIT License.

About

A TypeScript library for parsing Bitcoin Descriptors, including Miniscript-based ones. Streamlines creating Partially Signed Bitcoin Transactions (PSBTs) from Descriptors. Features BIP32, single-signature, and Hardware Wallet signing capabilities, and facilitates finalizing transactions.

Topics

Resources

Security policy

Stars

59 stars

Watchers

4 watching

Forks

Releases

Used by

Contributors

Languages