Version 4 is a major step forward for Cashu TS: It adds precision-safe amounts across the API, first-class proof serialization utilities, custom mint/melt methods, NUT-29 batch minting, and stronger security and rate-limit handling throughout the stack.
New features include:
- Exact amount handling with Amount and bigint support across the API, eliminating silent precision loss (eg large millisat amounts).
- Generic mint/melt APIs for custom payment methods, so apps can integrate new rails without waiting on library-specific support.
- NUT-29 batch minting support for more efficient multi-quote mint workflows.
- Better production resilience with explicit 429 handling,
Retry-Afterparsing, and response metadata for rate-limit-aware clients. - Stronger security defaults via DLEQ verification hardening, optional strict signature enforcement, and tighter P2PK validation.
- Improved privacy and compatibility through hardened request fingerprinting behavior and more flexible request-header overrides.
- Slimmer ESM only package (ESM can finally be loaded from common.js on node)
Migration Guide
Please see the full migration guide for detailed instructions on upgrading your code.
What's Changed
Detailed changes below - for a summary, see the changelog.
- chore!: remove support for CJS build by @KvngMikey in #524
- chore: update react tsconfig for TS6.0 by @robwoodgate in #541
- feat!: migrate amount-bearing APIs to use Amount VO by @robwoodgate in #533
- feat!: tighten mint/melt API; remove MeltBlanks and prefer_async by @robwoodgate in #534
- feat!: Proof.amount → bigint, strip crypto primitives, consolidate melt by @robwoodgate in #537
- feat!: Add bigint support to CBOR for creqA payment requests by @KvngMikey in #538
- feat: bigint roundtrip for v3/v4 tokens, wire in the enhanced CBOR by @robwoodgate in #539
- feat!: multi-unit KeyChain, cache API cleanup, deprecation removal by @robwoodgate in #540
- fix!: prevent getEncodedToken from mutating input token proofs by @gudnuf in #536
- chore: remove deprecated mint/wallet/model types. Clean up test LSP issues by @robwoodgate in #542
- chore: remove remaining deprecated methods/types/functions by @robwoodgate in #543
- chore: update docs - v3 is now the lts version. Add v4 base64 tests by @robwoodgate in #547
- chore: update version workflow to allow rc releases by @robwoodgate in #548
- chore(docs): update release info by @robwoodgate in #549
- fix: harden fetch RequestInit against client fingerprinting by @robwoodgate in #545
- fix: normalize and dedup p2pk pubkeys / refund keys at edges by @robwoodgate in #546
- refactor: narrow Proof params to Pick<> where full object isn't needed by @robwoodgate in #550
- feat!: generic mint/melt methods for custom payment types by @robwoodgate in #544
- refactor: split wallet tests file by feature by @robwoodgate in #551
- ci: add Codecov integration and deduplicate workflow triggers by @robwoodgate in #554
- ci: include integration tests in codecov by @robwoodgate in #555
- chore: add swap/improvement test for RGLI by @robwoodgate in #556
- chore: cleanup redundant files, tidy tsdocs by @robwoodgate in #557
- refactor: remove ConnectionManager singleton by @robwoodgate in #552
- refactor!: tidy and harden core utils by @robwoodgate in #553
- feat!: remove v3 token encoding; accept raw proofs in receive flows by @robwoodgate in #558
- chore: update dev toolchain and vite/vitest config by @robwoodgate in #559
- chore(tests): increase coverage for transport module by @robwoodgate in #560
- chore(tests): increase coverage of Mint.ts by @robwoodgate in #561
- fix(p2pk): add sigflag validation by @robwoodgate in #563
- refactor(p2pk)!: add normalizeP2PKOptions by @robwoodgate in #564
- fix: remove Pragma and Cache-Control headers. by @robwoodgate in #566
- fix: verify DLEQ proofs and amounts on mint BlindSignature responses (NUT-12) by @robwoodgate in #567
- refactor!: remove handleTokens from public API by @robwoodgate in #569
- chore!: remove internal core utils from public API by @robwoodgate in #570
- fix: reject zero blinding factor in NUT-13 derivation and blindMessage by @robwoodgate in #572
- fix: use constant time byte check for verifyDLEQProof by @robwoodgate in #574
- chore: update cache example by @robwoodgate in #582
- fix: update release-please-action to v4.4.0 for Node.js 24 support by @robwoodgate in #583
- feat: witness normalization checks proof secret type by @robwoodgate in #579
- refactor: P2PK hardening by @robwoodgate in #578
- feat: allow consumers to override anti-fingerprinting headers by @robwoodgate in #580
- feat: extend Amount utils, update migration docs by @robwoodgate in #584
- fix: switch to GH releases for renovate by @robwoodgate in #585
- chore: cdk now adds v prefix to docker builds by @robwoodgate in #587
- chore(docker): update CDK_IMAGE to cashubtc/mintd:v0.16.0 by @robwoodgate in #586
- chore: add tests for serializeProofs/deserializeProofs by @robwoodgate in #588
- refactor: refine deserializeProofs/serializeProofs to handle proofs individually by @robwoodgate in #589
- chore: add core util tests by @robwoodgate in #590
- chore: update docs for removal of getEncodedTokenv4 from api by @robwoodgate in #591
- chore(docker): update NUT_IMAGE to cashubtc/nutshell:0.20.0 by @robwoodgate in #592
- feat: add JSONInt to public api. Update migration docs by @robwoodgate in #593
- feat(errors): add RateLimitError and parseRetryAfter for explicit 429 by @KvngMikey in #594
- docs: tighten coding style in AGENTS.md by @robwoodgate in #598
- refactor: add ProofLike type. Make deserializeProofs more robust by @robwoodgate in #597
- feat: ResponseMeta callback and per-mint rate-limit header exposure by @KvngMikey in #596
- chore: fix lsp errors in test suite by @robwoodgate in #601
- fix: Align maxPerMint with desiredPoolSize in createAuthWallet. by @KvngMikey in #602
- feat: Support NUT-29 Batch Minting by @Egge21M in #478
- chore: codecov settings tweak by @robwoodgate in #604
- chore: standardize formatting and import ordering by @robwoodgate in #603
- chore: update migration doc by @robwoodgate in #605
- feat(nut29): wire NUT-06 max_batch_size into prepareBatchMint enforcement by @KvngMikey in #607
- refactor: replace raw bigint with Amount VO on Proof and BlindedMessage by @robwoodgate in #609
- refactor(wallet): inject output data creators while preserving OutputData helpers by @Egge21M in #608
- docs: add getDecodedToken / getTokenMetadata info by @robwoodgate in #611
- chore: fix typedoc issues by @robwoodgate in #612
- chore: update typedocs by @robwoodgate in #613
- fix: point docs breadcrumbs to site root by @robwoodgate in #614
- chore: restrict typedocs to manual or non-prerelease on main by @robwoodgate in #615
- fix: retain p2bk_e in offline send by @robwoodgate in #616
- chore: remove deps from ci playwright for speed by @robwoodgate in #621
- refactor(output): restore OutputData as canonical creator implementation by @robwoodgate in #620
- docs: add warning to treat tokens as untrusted input by @robwoodgate in #623
- chore: add 7 days npm min release age by @robwoodgate in #625
- feat: add requireSigDleq option to Wallet for signature DLEQ enforcement by @robwoodgate in #622
- chore(main): release 4.0.0 by @robwoodgate in #531
Full Changelog: v3.6.1...v4.0.0