Release notes

Notable changes are documented here. CHANGELOG.md is the record behind them: this file says what a user has to act on, that one says what changed.

Versions are calendar versions, YYYY.M.D: the number says when a release was cut, and promises nothing about compatibility, so a breaking change is announced in this file — read it before upgrading, rather than a digit.

v2026.10.9

  • Descriptor.expand(index, prv_keys) is new. It returns the scripts and the provider at index, what script_pub_keys and provider return, from one derivation of each key, as Bitcoin Core’s Descriptor::Expand does. A caller that needs both can call it instead of the two, and derive every key once rather than twice (ISS 303). provider called alone also derives each key once now. Nothing is removed or changed in what the existing methods return.

CHANGELOG.md’s own v2026.10.9 section has the rest.

v2026.10.8

  • A refused multipath step in a key origin is no longer quoted. In v2026.10.7, a step such as [deadbeef/<WIF;1>] was put in the error message of descriptors.parse and descriptors.multipath_descriptors, so a private key (WIF) in it was echoed. This release leaves the step out (PR 285). Upgrade if you parse descriptors that may hold a private key and log or show the errors. No advisory is published.

  • multipath_descriptors and parse refuse a multipath step that is not a whole path element. <0;1>h, <0;1>', 0<0;1>, <0;1>> and <<0;1>, in a key path or a key origin, raise BTClibValueError “Key path value is not a valid uint32” (ISS 280). Bitcoin Core refuses each, with that message except <0;1>> and <<0;1> in a key origin, which it refuses as a multipath step. v2026.10.7’s multipath_descriptors expanded them, except <0;1>> and <<0;1> in a key origin, which it refused as Core does. Write a hardened step as <0h;1h>. A caller that matches on the message of another step in a key origin finds the step gone from it: the message is “Key path value specifies multipath in a section where multipath is not allowed”.

CHANGELOG.md’s own v2026.10.8 section has the rest.

v2026.10.7

  • btclib-wallet requires btclib 2026.10.5, which fixes GHSA-9r97-9x22-2pp4 and GHSA-rw95-w37r-537w: verifying a taproot input took time linear in the transaction’s inputs, and each legacy or segwit v0 signature check computed its hash from scratch. bip322.verify runs that verification on a signature it was given. Upgrading btclib-wallet installs it.

  • request_signatures refuses to send a psbt asking for a sig_hash type other than SIGHASH_ALL or SIGHASH_DEFAULT. It raises on an input asking for SIGHASH_NONE, SINGLE or ANYONECANPAY, before the signer is called; pass the types you accept as allowed_sig_hash_types. SoftwareSigner applies its own allow-list, so to sign such a psbt with it, call its sign_psbt directly with allowed_sig_hash_types.

  • musig2.partial_sign and frost.partial_sign refuse an input without its non_witness_utxo, unless every input is taproot and none asks for ANYONECANPAY (GHSA-v4gq-j2v2-c4jp). Give each input the transaction it spends as its non_witness_utxo. Pass require_non_witness_utxo=False only where you know every witness_utxo amount is right.

  • A psbt updated from a descriptor carries a derivation for every key, as Bitcoin Core’s does. A key the descriptor gives no origin has an entry under its own fingerprint, so hd_key_paths and taproot_hd_key_paths are not empty for such a descriptor.

  • HwiSigner.sign_psbt refuses a psbt asking for a sig_hash type other than SIGHASH_ALL or SIGHASH_DEFAULT. It raises before hwi runs; pass the types you accept as its keyword-only allowed_sig_hash_types. request_signatures does not pass its allow-list on, so to send such a psbt to a device, call sign_psbt directly and hold its answer with assert_signatures_only(psbt, answer) before combine.

  • A ScriptWallet psbt carries a derivation for every key, as a descriptor’s does. A key of a KeyGroup given no origin has an entry under its own fingerprint, so hd_key_paths is not empty for such a group. Of two explicit origins for one key, the first is written, not the last.

  • The attestation bundle is attached as v<version>.intoto.jsonl from v2026.10.4 on, where earlier releases attach v<version>.attestation.jsonl. A script that downloads it by name, or passes it to gh attestation verify --bundle, uses the new name.

  • sign, request_signatures and HwiSigner.sign_psbt raise on an input asking for SIGHASH_SINGLE with no output at its index, whatever allowed_sig_hash_types says. Such a signature commits to no output, so whoever holds it can spend the input to any output. Give the input an output at its index, or ask for another type. finalize still checks a signature of this kind.

  • A regtest silent payment address starts with sprt1, as Bitcoin Core’s regtest requires, where earlier releases give tsp1. keys_from_address reads both, with the network type "test". Make a stored regtest tsp1 address again with address_from_keys(..., "regtest"), and update any tsp1 string a test compares against.

  • Bolt11Invoice.from_invoice refuses malformed or repeated fields. A p, s, h or n of the wrong length, a second p, s, d, h or n, an x, c or 9 starting with a zero word, and an amount with a leading zero raise BTClibValueError, where earlier releases skipped a wrong-length field, read the first of a repeated one, or read an amount without its leading zeros. This includes an invoice that an earlier sign wrote with expiry=0 or min_final_cltv_expiry=0: sign it again.

  • A psbt keeps an explicit sig_hash_type of 0 through serialize and combine. sign refuses an ECDSA input asking for it after a round trip through bytes too, where it signed SIGHASH_ALL. HwiSigner.sign_psbt and request_signatures refuse SIGHASH_DEFAULT on an input not known to be taproot, where a device signed SIGHASH_ALL. To sign such a psbt, ask its creator for SIGHASH_ALL or remove the field.

  • silent_payments.output_keys refuses an address of another network than its network argument, "mainnet" by default, as Bitcoin Core’s decoder does. An sprt, tsp or sp address that is not that network’s raises BTClibValueError, so a caller paying testnet, signet or regtest passes the network too.

  • wallet_policy_descriptor, wallet_policy_address and wallet_policy refuse a template BIP388 does not allow. A top-level multi() or sortedmulti(), and a pk() inside sh(), raise BTClibValueError; so do a top-level pk(), combo() or rawtr() in the first two, where earlier releases gave a descriptor or an address. Read such a descriptor with descriptors.parse.

CHANGELOG.md’s own v2026.10.7 section has the rest.

v2026.10.4

  • Signing refuses a sig_hash type other than SIGHASH_ALL or SIGHASH_DEFAULT unless the caller allows it (GHSA-qq38-77mp-j6wr). sign, SoftwareSigner.sign_psbt, musig2.partial_sign and frost.partial_sign raise on an input asking for SIGHASH_NONE, SINGLE or ANYONECANPAY; pass the types you accept as allowed_sig_hash_types. request_signatures passes none, so call SoftwareSigner.sign_psbt directly to sign such a psbt. A legacy SIGHASH_SINGLE input with no output at its index is refused whatever is allowed, and ecdsa_sig_hash and PsbtView.ecdsa_sig_hash refuse it too. finalize, assert_signed and assert_signatures_only refuse an ECDSA signature other than SIGHASH_ALL on an input without PSBT_IN_SIGHASH_TYPE; set the field on a psbt whose signatures use another type.

  • sign, SoftwareSigner.sign_psbt and Psbt.assert_signable refuse an input without its non_witness_utxo, unless every input is taproot and none asks for ANYONECANPAY (GHSA-v4gq-j2v2-c4jp). Give each input the transaction it spends as its non_witness_utxo. Pass require_non_witness_utxo=False only where you know every witness_utxo amount is right: a wrong one can be spent as fee.

  • btclib-wallet requires btclib 2026.10.4, btclib-ecc 2026.10.2 and btclib-secp256k1 0.8.0.10. btclib 2026.10.4 fixes GHSA-9fr5-46w5-5f9r, which made bip322.verify run for minutes on a crafted signature; 0.8.0.10 fixes GHSA-8h6f-34jj-7p6c, an invalid-curve oracle in silentpayments.scan_outputs. Upgrading btclib-wallet installs btclib and btclib-ecc; the secp256k1 extra installs the bindings.

  • Verifying a release’s attestation names a new signer and the tag. gh attestation verify takes --signer-workflow btclib-org/.github/.github/workflows/reusable-build.yml@refs/heads/main and --source-ref refs/tags/v<version>; SECURITY.md has the command. Earlier releases keep reusable-attest.yml.

  • descriptors.parse refuses a key of another network. A WIF or an extended key whose prefix is not the network’s raises BTClibValueError there, where the WIF was accepted and the extended key was refused only by script_pub_keys(). A caller that parses a descriptor for a network its keys are not of has to pass the right network.

  • bip39.mxprv_from_mnemonic and electrum.mxprv_from_mnemonic refuse a falsy passphrase of another type. An empty bytes, 0, False or [] derived the wallet without a passphrase; pass None or "" for that.

  • A miniscript repeating a public key is refused under different spellings of it. descriptors.parse does so as Bitcoin Core does, except for a key with a hardened step.

  • A malleable miniscript keeps neither “s”, “f” nor “e”. Miniscript.properties drops them, and is_signature_required is false for it.

  • join empties the signatures of a version 0 psbt, and sign updates a version 2 psbt’s modifiable flags. Sign the joined psbt again. join refuses a version 2 psbt signed with anything but SIGHASH_NONE|ANYONECANPAY.

  • extract_tx verifies by default. It runs every input’s scripts and checks that the outputs do not exceed the inputs, so it raises on a psbt it extracted before: one with a bad signature, a missing utxo or outputs above the inputs. Pass verify_scripts=False to extract without the check.

  • join refuses to change the lock time or the tx version of a signed version 2 psbt. The signatures would stop verifying. Join the psbts before they are signed, or give them the same lock time and tx version.

  • Miniscript.has_duplicate_keys, is_sane, is_sane_subexpression and insane_sub are methods. Call them with parentheses; without them, if node.is_sane: is always true, and mypy reports it as truthy-function. Pass prv_keys, the mapping parse fills, to derive a hardened step: descriptors.parse refuses wsh(or_i(pk(XPRV/1h),pk(<the key it derives>))). Without its private key, a key with a hardened step is still compared as written.

  • descriptors.parse refuses a threshold no script can meet. A multi() or sortedmulti() threshold of zero or above its key count, and a multi_a() or sortedmulti_a() one of zero, above its key count, or of more than 999 keys, raise BTClibValueError, where they were stored. A thresh() of more than 1000 arguments is refused too, a limit of this library.

  • A number of over 4300 digits is a BTClibValueError. A derivation index, a threshold, an older() or after() number and a @N of that size raised the built-in ValueError; they are refused at ten digits now. Bolt11Invoice.from_invoice refuses an amount of more than 20 digits, which its amount parser read up to 4300 digits.

  • A prv_keys that is not a mapping raises BTClibTypeError. The descriptor, KeyExpression, Miniscript and DescriptorWallet methods taking it, and descriptors.normalized, check it as parse does, where a string raised AttributeError.

  • SilentPaymentOutput’s repr leaves out prv_key_tweak. The tweak is a secret; read the field, not the repr, where you need it.

CHANGELOG.md’s own v2026.10.4 section has the rest.

v2026.9.30

A binary-string entropy passed as bytes is refused with a BTClibTypeError by mnemonic.entropy’s functions taking one, which read it as the digits it spells; pass the str instead. A mnemonic that is not a str is refused with a BTClibTypeError rather than a bare TypeError or AttributeError.

mnemonic.slip39.master_secret_from_mnemonics and mxprv_from_mnemonics refuse shares passed as an iterable that is not a sequence – a set, a generator, an iterator, dict.keys() – with a BTClibTypeError, where they read it; pass a list or a tuple instead.

mnemonic.slip39.mnemonics_from_master_secret refuses with a BTClibTypeError a groups passed as a set or a dict, and a bool as a threshold, a member count or the iteration exponent, where it read them; pass a list or a tuple of integer pairs, and integers. mnemonic.entropy.bin_str_entropy_from_rolls refuses the same way rolls passed as a set or a generator and a bool as a roll or as bits.

mnemonic.slip39.Share refuses with a BTClibTypeError a value that is not bytes – a bytearray or a list of ints included – and a bool as an integer field or a non-bool as extendable, where it held them; pass bytes, integers and a bool. mxprv_from_mnemonics refuses a falsy passphrase of another type, 0, [] or b"", where it read the empty passphrase; pass None or "". mnemonics_from_master_secret refuses an entropy_source answering anything but bytes or a bytearray of the length asked – a 1-of-1 backup read a list, a memoryview or a draw of another length; return exactly that.

fetch.BitcoinCoreFetcher and fetch.BitcoinCoreRestFetcher refuse with a BTClibTypeError a client that is not a BitcoinCoreRpcClient or a BitcoinCoreRestClient respectively, where a stand-in answering the methods they call worked; pass an instance of that class or a subclass. fetch.ElectrumFetcher refuses a timeout that is no number, a bool, not positive, or above threading.TIMEOUT_MAX, which it handed as given to a transport of the caller’s; pass a positive number of seconds. fetch.EsploraFetcher refuses a base_url carrying a user or a password, or without a host, which a transport of the caller’s received; pass the url without them, and let that transport add the credentials.

tx_builder.build_psbt, coin_selection.select_coins, knapsack and single_random_draw require change_script_pub_key: a call that left it out, and so sent every leftover satoshi to the fee, raises a TypeError; pass the change script, or None for a sweep.

tx_builder.build_psbt refuses with a BTClibValueError a fee above max_fee, 0.10 BTC unless raised, and an output being paid below its dust threshold. It refuses a non-zero lock_time too when every input’s sequence is final: set a non-final PsbtIn.sequence, such as 0xfffffffe, on an input for the lock time to bind.

psbt.sign refuses with a BTClibValueError a psbt paying a silent payment it used to sign: one whose silent payment output has no script yet – run psbt.silent_payments.set_input_share or set_global_share, then set_output_scripts, before signing – one with an input’s sighash other than SIGHASH_ALL, and one whose shares, scripts or modifiable flags psbt.silent_payments.assert_as_valid refuses. psbt.extract_tx refuses what that function refuses, and a silent payment output with no script; check_validity=False extracts as before. psbt.combine refuses two psbts carrying different scripts for one silent payment output.

tx_builder.build_psbt also refuses with a BTClibValueError a fee above what max_fee_rate, 0.10 BTC/kvB unless raised, asks of the estimated virtual size, however far below max_fee it is; pass a higher max_fee_rate where such a fee is meant.

A psbt with an input whose witness_utxo is not, in amount and script, the output of its non_witness_utxo the outpoint names is refused with a BTClibValueError by Psbt.assert_valid, and so by Psbt.parse and every function validating the psbt, where it was accepted and the witness_utxo read; set it to that output, or drop it. bip322.assert_as_valid refuses a proof of funds in which it contradicts the transaction an earlier input carries.

psbt.estimated_input_sizes refuses with a BTClibValueError a psbt_in whose non_witness_utxo is not the transaction the tx_in’s outpoint names, and one whose witness_utxo differs from the output that outpoint names, where it answered an estimate; pass the TxIn the input is spent by, and a witness_utxo equal to that output.

psbt_signer.request_signatures refuses a psbt paying a silent payment that psbt.sign would refuse, before the signer is asked, where it sent it on. psbt.silent_payments counts an input by the script it spends, and refuses with a BTClibValueError a counted input whose key the psbt does not carry where it left the input out: give every p2wpkh, p2pkh and p2sh-p2wpkh input a PSBT_IN_BIP32_DERIVATION whose key the script commits to, and a p2sh input its redeem script. A taproot input whose internal key is BIP341’s NUMS point is counted unless PSBT_IN_TAP_MERKLE_ROOT or a control block proves it. set_output_scripts refuses until every counted input has a share, where it derived the scripts from the shares there were.

hwi.HwiSigner.sign_psbt called directly refuses such a psbt the same way, before hwi runs, where it sent it to the device; and it refuses a request that is no Psbt with a BTClibTypeError rather than an AttributeError.

psbt.combine refuses with a BTClibValueError psbts whose merge Psbt.assert_valid refuses, where it returned that psbt; drop from the copies the field that contradicts the others – a witness_utxo differing from another copy’s non_witness_utxo output – before combining. It refuses with a BTClibTypeError a psbts that is not a sequence – a generator, an iterator – where it read it; pass a list or a tuple.

psbt.join refuses with a BTClibTypeError a psbts that is not a sequence – a dict view, any container that is only iterable – where it joined it; pass a list or a tuple.

descriptors.KeyExpression refuses with a BTClibValueError an extended private key as xkey, where it held it; pass its xpub, and the xprv under that xpub in prv_keys where a hardened step needs it.

descriptors.KeyExpression’s xkey holds an extended public key of a version btclib decodes, a wallet-policy placeholder wallet_policy writes – @N, @N/**, @N/<M;N>/*, musig(@N,...) with one of those suffixes, K – or nothing. Any other str is refused with a BTClibValueError and any other type with a BTClibTypeError, where they were held; pass an xpub.

silent_payments.keys_from_address refuses with a BTClibValueError a mixed-case address and one holding a character outside ASCII, where it read the address the string lowers to; pass the address all lower case or all upper case. For such a spelling of an address a wallet handed out, address in wallet answers False and Wallet.address_info raises, where both found the address.

silent_payments.keys_from_address and silent_payments.output_keys, which reads each address through it, BIP32KeyData.b58decode and what reads an extended key through it, bip32.derive among them, bip322.Sig.b64decode, bip322.verify and assert_as_valid for the signature, Psbt.b64decode, tx_or_psbt.tx_or_psbt_from_any, BIP32KeyOrigin.from_description and bip32.str_from_der_path’s fingerprint strip only space, tab, newline, carriage return, vertical tab and form feed. Text padded with U+00A0, U+3000, U+2028, U+0085 or another character outside ASCII that str.isspace counts is refused with a BTClibValueError, where it was read as the value it wraps, and so is text padded with U+001C to U+001F. For such a spelling of an address a wallet handed out, address in wallet answers False and Wallet.address_info raises. Strip that padding before passing the text.

mnemonic.entropy.bin_str_entropy_from_int refuses with a BTClibValueError a string entropy that is not ASCII digits – binary after 0b, hex after 0x, decimal otherwise – once space, tab, newline, carriage return, vertical tab and form feed are stripped around it, where int read 0x1_0, 1_6, +16 and fullwidth or Arabic-Indic digits as 16 and U+00A0 or U+3000 was stripped too. The functions reading a binary-string entropy, bin_str_entropy_from_str, bytes_entropy_from_str and bin_str_entropy_from_entropy among them, refuse one holding anything but ASCII 0 and 1 – a sign, 0b, whitespace, an underscore – which int read as binary; bytes_entropy_from_str raised a bare OverflowError on a leading -. Pass ASCII digits alone. The refusals read invalid entropy: what follows 0x is not ASCII hex digits and invalid entropy: not ASCII decimal digits, where they said not a base 16 number and not a base 10 number, and a negative entropy’s reads negative entropy, without the number. bin_str_entropy_from_wordlist_indexes and bin_str_entropy_from_rolls name the range and not the value of an index or a roll outside it: invalid index: not in [0, 2048), invalid roll: not in [1-6]. Match invalid entropy, negative entropy, invalid index and invalid roll alone.

descriptors.parse refuses with a BTClibValueError a bare multi() or sortedmulti() of more than three keys, one inside sh() whose redeem script is over 520 bytes – sixteen compressed keys are 547 – and one of more than twenty keys anywhere, where it parsed them; put the keys of the first two inside wsh() or sh(wsh()) instead. wallet_policy_descriptor refuses the same, the descriptor it builds being read by parse.

Psbt.b64decode refuses with a BTClibValueError text holding a character outside the base64 alphabet – a line break, a space, U+001C, ! – anywhere past the ASCII whitespace it strips from either end, where it decoded the psbt the rest of the text spells. Remove the line breaks from a wrapped psbt, or pass it to tx_or_psbt.tx_or_psbt_from_any, which removes them.

bip32.indexes_from_der_path, hardenings_from_der_path, int_from_index_str and every function reading a path string through them, bip32.derive and BIP32KeyOrigin.from_description among them, refuse with a BTClibValueError a step whose number is not ASCII decimal digits – 1_0, +1, -0, fullwidth or Arabic-Indic digits – or that is padded with anything but space, tab, newline, carriage return, vertical tab and form feed, where it was read as the number. With bip380_enforced=True they refuse a step padded at all, and so descriptors.parse refuses a step with a space around it. BIP32KeyOrigin.from_description refuses text whose ninth character is not /, where it dropped that character and read deadbeef0/1 as deadbeef/1. int_from_index_str refuses a step that is not a str with a BTClibTypeError, and reads a step with ASCII whitespace after its symbol, "0h ", which it refused. Pass each step as ASCII digits. The refusals read invalid derivation index: not ASCII decimal digits and invalid index: not below 2**31, where they quoted the step or its number; match those. bip85’s functions write their index into a path string, and refuse a negative one with the first and one of 2**31 or more with the second.

descriptors.parse and miniscript.parse refuse with a BTClibValueError a / followed by no path step, in a key origin, after an extended key or after a musig() – [deadbeef/], xpub.../, xpub...//*, musig(...)/ – where they read the key expression as though that / were absent. Remove the /; the refusal reads invalid derivation index. BIP32KeyOrigin.from_description, whose reading of a path is the lenient one, reads deadbeef/ as deadbeef.

Psbt.b64decode, bip322.Sig.b64decode, and bip322.verify and assert_as_valid for the signature, refuse with a BTClibValueError base64 that is not the text base64.b64encode writes for its bytes, where they read those bytes: a bit set in what the last character leaves over, YR== read as YQ==, and on CPython and PyPy 3.11 an = after a whole group. The refusal reads invalid base64 encoding: not canonical, and bip322.verify raises it for a legacy signature so encoded, where it answered False. tx_or_psbt.tx_or_psbt_from_any refuses such a str as neither hex nor base64, and reads such bytes as a raw transaction, where both were read as the psbt. Pass the text base64.b64encode writes, which is the text Bitcoin Core writes and the only text it reads.

A refusal in mnemonic no longer quotes secret material, so its text changed: an unknown word reads unknown '<lang>' word at position <n>, where it was unknown '<lang>' word: '<word>', and a SLIP-0039 one not in the SLIP-0039 word-list: words at positions [<n>, ...]. A BIP39 checksum reads invalid checksum: <n> words, a SLIP-0039 padding invalid padding: must be all zeros, and an unrecognized Electrum sentence unknown electrum mnemonic version; not in [...]. Match the new text if you match these. mnemonic.mnemonic_from_indexes refuses an index outside the word-list, a negative one included, which read from the end of the list; pass indexes in [0, len(wordlist)). WordLists.langs_of_words refuses a lone str, which it read one character at a time; pass the list of words.

mnemonic.mnemonic_from_indexes and WordLists.langs_of_words refuse with a BTClibTypeError an iterable that is not a sequence – a generator, a set, an iterator – where they read it; pass a list or a tuple. mnemonic_from_indexes refuses too an index that is a bool or an integer of a type other than int, numpy.int64 or an object with __index__ included, where it read it; pass ints. dispatch.seed_type_from_mnemonic and all_seed_types_from_mnemonic refuse a lang that is not a str with a BTClibTypeError, where they answered "" and []; pass the language code.

The BIP39, SLIP39 and Electrum mnemonic schemes are btclib-mnemonics’, a dependency of this package, and btclib_wallet.mnemonic keeps what builds a key from their seed: bip39.mxprv_from_mnemonic, slip39.mxprv_from_mnemonics, electrum.mxprv_from_mnemonic and electrum.old_master_pub_key_from_mnemonic. Every path below stops resolving, and nothing re-exports it; import the name from btclib_mnemonics instead. A refusal those four functions pass on from btclib_mnemonics, of a mnemonic, a share or a passphrase, is that package’s own BTClibMnemonicsTypeError or BTClibMnemonicsValueError, a TypeError or a ValueError and no BTClibException, where it was a BTClibTypeError or a BTClibValueError; catch TypeError and ValueError. electrum.mxprv_from_mnemonic still refuses a 2fa, a 2fa_segwit or an old mnemonic with its own BTClibValueError, and for an old one that refusal now ends use old_master_pub_key_from_mnemonic, where it named old_master_prv_key_from_mnemonic. The paragraphs above that name a function that moved describe it as it is under btclib_mnemonics, where each BTClibTypeError or BTClibValueError they name for it is a BTClibMnemonicsTypeError or a BTClibMnemonicsValueError, and where the entropy conversions they name are private.

  • btclib_wallet.mnemonic.dispatch is btclib_mnemonics.dispatch.

  • btclib_wallet.mnemonic.entropy is btclib_mnemonics.entropy, less the functions the bullets below make private.

  • btclib_wallet.mnemonic.mnemonic is btclib_mnemonics.mnemonic.

  • btclib_wallet.mnemonic’s BinStr is btclib_mnemonics.entropy.BinStr.

  • btclib_wallet.mnemonic’s Entropy is btclib_mnemonics.entropy.Entropy.

  • btclib_wallet.mnemonic’s bin_str_entropy_from_random is btclib_mnemonics.entropy.bin_str_entropy_from_random.

  • btclib_wallet.mnemonic’s bin_str_entropy_from_rolls is btclib_mnemonics.entropy.bin_str_entropy_from_rolls.

  • btclib_wallet.mnemonic’s collect_rolls is btclib_mnemonics.entropy.collect_rolls.

  • btclib_wallet.mnemonic’s Mnemonic is btclib_mnemonics.mnemonic.Mnemonic.

  • btclib_wallet.mnemonic’s WORDLISTS is btclib_mnemonics.mnemonic.WORDLISTS.

  • btclib_wallet.mnemonic’s indexes_from_mnemonic is btclib_mnemonics.mnemonic.indexes_from_mnemonic.

  • btclib_wallet.mnemonic’s mnemonic_from_indexes is btclib_mnemonics.mnemonic.mnemonic_from_indexes.

  • btclib_wallet.mnemonic’s normalize_mnemonic is btclib_mnemonics.mnemonic.normalize_mnemonic.

  • btclib_wallet.mnemonic’s bin_str_entropy_from_bytes is gone, private in btclib_mnemonics: pass the bytes to the scheme’s mnemonic_from_entropy, which reads them.

  • btclib_wallet.mnemonic’s bin_str_entropy_from_entropy is gone, private in btclib_mnemonics: pass the entropy to the scheme’s mnemonic_from_entropy, which reads it.

  • btclib_wallet.mnemonic’s bin_str_entropy_from_int is gone, private in btclib_mnemonics: pass the integer to the scheme’s mnemonic_from_entropy, which reads it.

  • btclib_wallet.mnemonic’s bin_str_entropy_from_str is gone, private in btclib_mnemonics: pass the binary string itself.

  • btclib_wallet.mnemonic’s bin_str_entropy_from_wordlist_indexes is gone, private in btclib_mnemonics: use btclib_mnemonics.mnemonic.mnemonic_from_indexes and the scheme’s entropy_from_mnemonic.

  • btclib_wallet.mnemonic’s bytes_entropy_from_str is gone, private in btclib_mnemonics: int(entropy, 2).to_bytes(len(entropy) // 8, "big") is the conversion.

  • btclib_wallet.mnemonic’s wordlist_indexes_from_bin_str_entropy is gone, private in btclib_mnemonics: use the scheme’s mnemonic_from_entropy and btclib_mnemonics.mnemonic.indexes_from_mnemonic.

  • btclib_wallet.mnemonic.bip39’s entropy_from_mnemonic is btclib_mnemonics.bip39.entropy_from_mnemonic.

  • btclib_wallet.mnemonic.bip39’s lang_from_mnemonic is btclib_mnemonics.bip39.lang_from_mnemonic.

  • btclib_wallet.mnemonic.bip39’s mnemonic_from_entropy is btclib_mnemonics.bip39.mnemonic_from_entropy.

  • btclib_wallet.mnemonic.bip39’s seed_from_mnemonic is btclib_mnemonics.bip39.seed_from_mnemonic.

  • btclib_wallet.mnemonic.electrum’s ELECTRUM_WORDLISTS is btclib_mnemonics.electrum.ELECTRUM_WORDLISTS.

  • btclib_wallet.mnemonic.electrum’s entropy_from_mnemonic is btclib_mnemonics.electrum.entropy_from_mnemonic.

  • btclib_wallet.mnemonic.electrum’s hex_seed_from_old_mnemonic is btclib_mnemonics.electrum.hex_seed_from_old_mnemonic.

  • btclib_wallet.mnemonic.electrum’s lang_from_mnemonic is btclib_mnemonics.electrum.lang_from_mnemonic.

  • btclib_wallet.mnemonic.electrum’s mnemonic_from_entropy is btclib_mnemonics.electrum.mnemonic_from_entropy.

  • btclib_wallet.mnemonic.electrum’s old_master_prv_key_from_mnemonic is btclib_mnemonics.electrum.old_master_prv_key_from_mnemonic.

  • btclib_wallet.mnemonic.electrum’s old_mnemonic_from_hex_seed is btclib_mnemonics.electrum.old_mnemonic_from_hex_seed.

  • btclib_wallet.mnemonic.electrum’s version_from_mnemonic is btclib_mnemonics.electrum.version_from_mnemonic.

  • btclib_wallet.mnemonic.slip39’s Share is btclib_mnemonics.slip39.Share.

  • btclib_wallet.mnemonic.slip39’s master_secret_from_mnemonics is btclib_mnemonics.slip39.master_secret_from_mnemonics.

  • btclib_wallet.mnemonic.slip39’s mnemonic_from_share is btclib_mnemonics.slip39.mnemonic_from_share.

  • btclib_wallet.mnemonic.slip39’s mnemonics_from_master_secret is btclib_mnemonics.slip39.mnemonics_from_master_secret.

  • btclib_wallet.mnemonic.slip39’s share_from_mnemonic is btclib_mnemonics.slip39.share_from_mnemonic.

The bound on a timeout that fetch.ElectrumFetcher refuses is fetch.transport.MAX_TIMEOUT, 2147483 seconds, where the paragraph above names threading.TIMEOUT_MAX; pass at most that many seconds.

fetch.EsploraFetcher refuses at construction, with a BTClibTypeError or a BTClibValueError, a timeout that is no number, a bool, not positive, or above fetch.transport.MAX_TIMEOUT, 2147483 seconds, where its first fetch raised a FetchError and a timeout above that bound reached a transport of the caller’s. fetch.transport.TlsLineTransport refuses a timeout above that bound with a BTClibValueError, where it waited with one up to what the platform’s socket took and failed past it, with an OverflowError or, where the socket’s wait refused it, a FetchError; its refusals read non-numeric timeout: <type> and timeout is not a positive number of seconds up to 2147483, where they quoted the value. Pass a positive number of seconds up to that bound.

CHANGELOG.md’s own v2026.9.30 section has the rest.

v2026.9.24

The first release of btclib-wallet, whose modules leave btclib (issue btclib-org/btclib#2129). A caller importing one of them from btclib installs this package and imports it from btclib_wallet instead, the path below the package unchanged: btclib.bip32 becomes btclib_wallet.bip32, btclib.mnemonic.bip39 becomes btclib_wallet.mnemonic.bip39.

CHANGELOG.md’s own v2026.9.24 section has the rest.