Mostly hardening fixes, a couple of MINOR BREAKING CHANGES to note:
Experimental: SigAll (#951):
- SigAllDigests reshaped: { legacy, current } → { v0 }.
- SigAllSigningPackage.digests removed — digests are recomputed from package contents.
- deserializePackage(input, options?) → deserializePackage(input); the validateDigest option is gone, validation is now implicit.
Stable, type-level (#958):
- NUT10Option.tags required → optional.
- RawNUT10Option.t required → optional.
Both only affect TypeScript consumers who read the field, who now see | undefined Constructing gets easier, and it matches NUT-10 and NUT-18, which both call tags optional.
Stable, behavioural (#932):
- New bolt11 quote-amount check that throws, at four call sites including the read paths
checkMintQuoteBolt11and
checkMintQuoteBatchBolt11. Only affects non-compliant mints that return ln invoices that do not match the quote amounts.
What's Changed
- feat(wallet): prefer stale keysets in default proof selection [backport v4-dev] by @robwoodgate in #818
- fix(wallet): widen exact-match trim bound for selection-level fee rounding [backport v4-dev] by @robwoodgate in #819
- refactor(wallet): make RGLI exFee an integer sort key [backport v4-dev] by @robwoodgate in #821
- feat(wallet): support u64 amounts in proof selection [backport v4-dev] by @robwoodgate in #823
- refactor(model): return snapshots from MintInfo accessors [backport v4-dev] by @robwoodgate in #825
- fix(model): preserve Amount instances through MintInfo snapshot [backport v4-dev] by @robwoodgate in #827
- fix(wallet): compute NUT-08 blank count in bigint [backport v4-dev] by @robwoodgate in #829
- fix(model): bound Amount.from to the u64 range [backport v4-dev] by @robwoodgate in #831
- fix(model): cap Amount at the u64 range [backport v4-dev] by @robwoodgate in #833
- feat(wallet): prefer newest keyset version in getCheapestKeyset [backport v4-dev] by @robwoodgate in #836
- fix(wallet): return -1 from Keyset.version for unparseable ids [backport v4-dev] by @robwoodgate in #838
- fix(wallet): classify odd-length hex keyset ids as legacy [backport v4-dev] by @robwoodgate in #840
- test: raise Stryker mutation coverage across crypto, model and wallet [backport v4-dev] by @robwoodgate in #842
- fix(utils): return false from isValidHex for non-string input [backport v4-dev] by @robwoodgate in #844
- feat(utils): rename normalizeUrl to normalizeMintUrl and make it public [backport v4-dev] by @robwoodgate in #845
- feat(wallet): add getFeesToInclude fee helper [backport v4-dev] by @robwoodgate in #847
- fix(wallet): validate pubkey in locked mint quote responses [backport v4-dev] by @robwoodgate in #852
- fix(wallet): bound fee convergence loop [backport v4-dev] by @robwoodgate in #855
- fix(wallet): reject a missing pubkey in locked mint quotes [backport v4-dev] by @robwoodgate in #857
- fix(wallet): bound keyset denomination count at ingest [backport v4-dev] by @robwoodgate in #865
- refactor(wallet): move MAX_KEYSET_DENOMINATIONS to limits [backport v4-dev] by @robwoodgate in #867
- fix(utils): bound splitAmount output count [backport v4-dev] by @robwoodgate in #868
- docs(wallet): note sendOffline throws in v5 on no offline match by @robwoodgate in #872
- fix(wallet): compute keyset fees with integer arithmetic [backport v4-dev] by @robwoodgate in #870
- fix(crypto): bound untrusted P2PK witness and CBOR decode input [backport v4-dev] by @robwoodgate in #876
- fix(crypto): harden P2PK witness edge cases [backport v4-dev] by @robwoodgate in #878
- fix(wallet): tidy diagnostic log output [backport v4-dev] by @robwoodgate in #880
- fix(wallet): more debug log tidy-up [backport v4-dev] by @robwoodgate in #882
- fix(auth): tidy the OIDC debug logging [backport v4-dev] by @robwoodgate in #884
- fix: tidy response reads and number-token parsing [v4 backport] by @robwoodgate in #887
- fix(crypto): harden HTLC witness parsing edge cases [backport v4-dev] by @robwoodgate in #898
- fix(crypto): tighten NUT-10 secret and tag-integer parsing [backport v4-dev] by @robwoodgate in #899
- fix: guard CBOR and keyset map lookups against prototype-chain keys [backport v4-dev] by @robwoodgate in #901
- fix(auth): validate OIDC provider URLs use an http(s) scheme [backport v4-dev] by @robwoodgate in #902
- fix(utils): align base64 fallback chunk size to a 3-byte boundary [backport v4-dev] by @robwoodgate in #911
- fix(wallet): reject extraPayload keys reserved by the melt request [backport v4-dev] by @robwoodgate in #914
- fix(crypto): count unique signers by x-only pubkey identity [backport v4-dev] by @robwoodgate in #910
- fix(logger): escape control characters in log messages [backport v4-dev] by @robwoodgate in #912
- fix(utils): cap JSON nesting depth in JSONInt.parse [backport v4-dev] by @robwoodgate in #913
- perf(wallet): look up keyset unit by map instead of scanning ids [backport v4-dev] by @robwoodgate in #915
- fix(wallet): reject duplicate proofs before selection by @robwoodgate in #918
- fix(crypto): bound the deterministic counter to the safe integer range [backport v4-dev] by @robwoodgate in #921
- fix(wallet): slim the seed error context [backport v4-dev] by @robwoodgate in #922
- feat(wallet): claim manual counter ranges with optional CounterSource.reserveAt (v4) by @robwoodgate in #924
- fix(auth): stop following redirects on token-bearing requests [backport v4-dev] by @robwoodgate in #933
- fix(auth): drop a CAT refresh that completes after the session changes [backport v4-dev] by @robwoodgate in #934
- fix(auth): coerce the device-flow polling interval to a finite value [backport v4-dev] by @robwoodgate in #936
- fix(ws): ignore socket events from a replaced connection [backport v4-dev] by @robwoodgate in #937
- fix(wallet): check bolt11 quote amounts against the invoice [backport v4-dev] by @robwoodgate in #932
- fix(mintinfo): bound mint-advertised method and endpoint lists [backport v4-dev] by @robwoodgate in #935
- fix(crypto): bound pow2height in createNewMintKeys at runtime [backport v4-dev] by @robwoodgate in #940
- feat(token): add getTokenMetadata proofAmounts and deprecate incompleteProofs by @robwoodgate in #942
- fix(auth): detach the OIDC token listener when the provider is replaced [backport v4-dev] by @robwoodgate in #943
- chore: dual-license under MIT OR Apache-2.0 (v4) by @robwoodgate in #944
- fix(p2bk): share one ephemeral key across a blinded SIG_ALL batch [backport v4-dev] by @robwoodgate in #948
- refactor(sigall): recompute signing digests from package contents [backport v4-dev] by @robwoodgate in #951
- fix(hooks): run both pre-push checks and fail on either by @robwoodgate in #957
- fix(types): make nut08Change expressible and NUT-10 tags optional by @robwoodgate in #958
- test: type check the test tree and fix fixture drift by @robwoodgate in #959
- fix(mint): derive a missing bolt11 quote state from the accounting fields by @robwoodgate in #961
- chore(v4-dev): release 4.8.0 by @robwoodgate in #820
Full Changelog: v4.7.2...v4.8.0
Thanks to Project Loupe for suggesting some of the hardening fixes in this release