Signers

In LWK, the management of private keys is delegated to a specialized component called Signer.

Signers

In LWK, the management of private keys is delegated to a specialized component called Signer.

The primary tasks of a signer are:

  • provide xpubs, which are used to create wallets
  • sign transactions

Types of Signers

LWK has two signer types:

  • Software Signers: store the private keys in memory. This is the simplest signer to integrate and interact with.
  • Hardware Signers: LWK provides specific integrations for hardware wallets, such as the Blockstream Jade. These signers keep the private keys completely isolated from the computer.

While hardware signers are inherently more secure, LWK's design allows you to enhance the security of software signers as well. For example, a software signer can be run on an isolated machine or a mobile app might store the mnemonic (seed) encrypted, only decrypting it when a signature is required.

This guide will focus on software signers. For more details on hardware signers, please see the Jade documentation.

Create Signer

To create a signer you need a mnemonic.
You can generate a new one with bip39::Mnemonic::generate().
Then you can create a software signer with SwSigner::new().

use lwk_signer::{bip39::Mnemonic, SwSigner};

let mnemonic = Mnemonic::generate(12)?;
let is_mainnet = false;

let signer = SwSigner::new(&mnemonic.to_string(), is_mainnet)?;
mnemonic = Mnemonic.from_random(12)
network = Network.testnet()
signer = Signer(mnemonic, network)
const mnemonic = lwk.Mnemonic.fromRandom(12);
const network = lwk.Network.testnet();
const signer = new lwk.Signer(mnemonic, network);
	mnemonic, err := lwk.MnemonicFromRandom(12)
	if err != nil {
		log.Fatal(err)
	}
	network := lwk.NetworkTestnet()
	signer, err := lwk.NewSigner(mnemonic, network)
	if err != nil {
		log.Fatal(err)
	}

Get Xpub

Once you have a signer you need to get some an extended public key (xpub),
which can be used to create a wallet that requires signature from the signer.

The xpub is obtained with Signer::keyorigin_xpub(), which also includes the keyorigin information: signer fingerprint and derivation path from master key to the returned xpub, e.g. [ffffffff/84h/1h/0h]xpub....

let bip = lwk_common::Bip::Bip84;
let xpub = signer.keyorigin_xpub(bip, is_mainnet);
xpub = signer.keyorigin_xpub(Bip.new_bip84())
const xpub = signer.keyoriginXpub(lwk.Bip.bip84());
	xpub, err := signer.KeyoriginXpub(lwk.BipNewBip84())
	if err != nil {
		log.Fatal(err)
	}

For particularly simple cases, such as single sig, you can get the CT descriptor directly from the signer, for instance using Signer::wpkh_slip77_descriptor().


Next: Watch-Only Wallets


The Liquid Network is a production Bitcoin sidechain built with Elements, supporting confidential transactions, asset issuance and programmable smart contracts.

© 2026 Liquid Network
All rights reserved.

Feedback and Requests

We'd be happy to hear your suggestions on how to improve this site.

Simplicity Forum

Discuss SimplicityHL, tooling and applications on Liquid at community.simplicity-lang.org.

Liquid Dev Community

Community Telegram group where most of the Liquid developers hang out. Go to t.me/liquid_devel to join.