This guide shows a secure workflow for a 2-of-3 multisig wallet using htnwallet. The key property: every cosigner keeps their private mnemonic locally and only shares extended public keys (xpub). The coordinator (daemon) uses the xpubs to create unsigned (partially-signed) transactions. Cosigners sign locally and exchange the partially-signed hex until the threshold is reached.
Contents
keys.json (encrypted mnemonic).minimumSignatures threshold.Actors: Alice, Bob, Carol (three cosigners). Threshold: 2 signatures required.
# On Alice's machine (creates a keys file and prints an extended public key)
htnwallet create --num-private-keys 1 --num-public-keys 1 --keys-file ~/alice/keys.json
# Enter a strong password when prompted.
# The command prints a line like:
# Extended public key of mnemonic #1:
# xpub6C... (copy this xpub and securely share with the coordinator)
Repeat on Bob's and Carol's machines, keeping ~/bob/keys.json and ~/carol/keys.json private.
Share only the printed extended public keys (xpub) over a secure channel. Do NOT share mnemonics or keys.json files.
Coordinator builds the multisig keys file from the xpubs. Two common options:
# On the coordinator machine (no private keys kept locally)
htnwallet create --num-private-keys 0 --num-public-keys 3 --min-signatures 2 --keys-file ~/multisig/keys.json
# When prompted, paste public key #1 (Alice xpub), public key #2 (Bob xpub), public key #3 (Carol xpub).
# Result: "Wrote the keys into ~/multisig/keys.json"
# Coordinator keeps its own key and adds two external xpubs
htnwallet create --num-private-keys 1 --num-public-keys 3 --min-signatures 2 --keys-file ~/coordinator/keys.json
# The command prints your own xpub, then prompts to paste the other two xpubs.
htnwallet start-daemon --keys-file ~/multisig/keys.json --rpcserver <full-node-host:port> --listen localhost:4282
htnwallet new-address --daemonaddress localhost:4282 --address-type p2sh
# Send funds to the returned address from an exchange or other wallet.
Workflow summary: coordinator (daemon) creates an unsigned transaction → cosigner A signs → cosigner B signs → broadcast.
# Create unsigned tx and save hex to a file
htnwallet create-unsigned-transaction --daemonaddress localhost:4282 --to-address <recipient-address> --send-amount 1.23 > unsigned.hex
keys.json:htnwallet sign --keys-file ~/alice/keys.json --transaction-file unsigned.hex > signed-by-alice.hex
The command prints status to stderr. If the tx is not yet fully-signed it prints "Successfully signed transaction"; when the final threshold is reached it prints "The transaction is signed and ready to broadcast".
htnwallet sign --keys-file ~/bob/keys.json --transaction-file signed-by-alice.hex > signed-by-bob.hex
After Bob's signing the hex should reach the 2-of-3 threshold and be ready to broadcast.
htnwallet parse --transaction-file signed-by-bob.hex --verbose
htnwallet broadcast --daemonaddress localhost:4282 --transaction-file signed-by-bob.hex
# The command replies with one or more transaction IDs.
keys.json.keys.json file; keys are encrypted with Argon2 + ChaCha20-Poly1305.--num-private-keys 0 when creating its keys file (read-only wallet).--import at htnwallet create.htnwallet create --num-private-keys 1 --num-public-keys 1 → share xpub.htnwallet create --num-private-keys 0 --num-public-keys 3 --min-signatures 2 → paste xpubs.keys.json.If you want, I can:
--public-keys option to htnwallet create so xpubs can be passed on the command line, or