* pubsub: consolidate into Spec, adopt Arc<SubscriptionId>, and wire through wallet/mint/WS/FFI
Refactor the pub/sub engine to a single Spec trait, move Event alongside it,
and propagate Arc-backed subscription IDs across the stack. This simplifies
generics, clarifies responsibilities, and preserves coalescing +
latest-on-subscribe semantics.
- **Single source of truth:** `Spec` owns `Topic`, `Event`, `SubscriptionId`,
`Context`, new_instance, and fetch_events.
- **Lean & explicit API:** Remove Topic trait split;
`Subscriber::send(Event)` carries sub-ID internally.
- **Performance/ergonomics:** `Arc<SubscriptionId>` avoids heavy clones and
makes channel/task hops trivial.
- Introduce `pub_sub/typ.rs` with:
- trait `Spec`
- trait `Event` colocated with Spec.
- Remove `pub_sub/event.rs` fold `Event` into `typ.rs`.
- Make `Pubsub<S>` generic over `Spec` and store `Arc<S>`.
- The subscriber holds `Arc<SubscriptionId>` and deduplicates the latest
entry per subscription.
- SubscriptionRequest: rename SubscriptionName → SubscriptionId; return
`Arc<...>` from `subscription_name()`.
- Remote consumer (Transport) now parameterized by `Spec`; control types
updated:
- `StreamCtrl<S>`, `SubscribeMessage<S>`, internal caches keyed by
`S::Topic`.
- Mint/wallet:
- Mint: `MintPubSubSpec` (Context = `DynMintDatabase`),
`PubSubManager(Pubsub<MintPubSubSpec>)`.
- Wallet: lightweight MintSubTopics Spec with `Context = ()`.
- IDs go Arc end-to-end:
- cdk-axum WS maps `HashMap<Arc<SubId>, JoinHandle<()>>`, publisher sends
`(Arc<SubId>, NotificationPayload)`.
- `subscription::{Params, WalletParams}` now use `Arc<...>`.
- cdk-ffi conversions & wallet glue updated.
- Integration tests updated for new types.
- Coalescing unchanged: multiple local subs to the same topic are combined
into a single remote sub.
- Backfill via `Spec::fetch_events(topics, Subscriber)`; Subscriber enforces
latest-only dedupe per subscription.
**Result:** a slimmer, more maintainable pub/sub core that’s easier to embed
across mint, wallet, transports, and FFI without sacrificing performance or
semantics.
---------
Co-authored-by: thesimplekid <tsk@thesimplekid.com>
Add is_empty method to nut15::Settings and configure skip_serializing_if
attribute to prevent empty NUT15 objects from appearing in serialized
mint info responses.
* token: add Token::token_secrets() and spending-condition helpers
- New helpers on Token that do not require mint keysets:
- spending_conditions()
- p2pk_pubkeys()
- p2pk_refund_pubkeys()
- htlc_hashes()
- locktimes()
- Introduce token_secrets() to unify V3/V4 proof traversal and avoid duplication
- Bypass short->long keyset-id mapping since only Secret is needed for conditions
- Use &Secret for TryFrom to fix compile error
* feat(cdk): add WebSocket authentication support with comprehensive configuration
- Add WebSocket auth token injection for client connections
- Implement server-side WebSocket authentication verification
- Add configuration options for per-endpoint WebSocket auth types
- Include comprehensive documentation and example configuration
- Support clear, blind, and no-auth modes for WebSocket endpoin
* Include supported amounts instead of assuming the power of 2
The mint's signatory defines the amounts and the wallet, and the mint, when
paying, should use them instead of assuming the supported amounts are
2^(0..32), which is not part of the spec.
* Introduce FeeAndAmount struct
* feat(cdk): add generic key-value store functionality for mint databases
Implements a comprehensive KV store system with transaction support,
namespace-based organization, and validation for mint databases.
- Add KVStoreDatabase and KVStoreTransaction traits for generic storage
- Include namespace and key validation with ASCII character restrictions
- Add database migrations for kv_store table in SQLite and PostgreSQL
- Implement comprehensive test suite for KV store functionality
- Integrate KV store traits into existing Database and Transaction bounds
* Abstract the HTTP Transport
This PR allows replacing the HTTP transport layer with another library,
allowing wallet ffi to provide a better-suited HTTP library that would be used
instead of Reqwest.
with a few serde directive we can get the same behaviour we had with
Option<Vec<Transport>> but only using Vec<Transport>
No need to change protocol specification
* feat(cdk): add Bolt12 mint quote subscription support
Extends subscription to handle Bolt12 payment method alongside existing Bolt11 support across wallet, mint, and CLI components.
The codebase was used to correctly perform signatory calls during a database
transaction, as the signatory was previously exclusively in process. However, a
few months ago, it was changed to be a trait that can be either local or
remote. Making external calls to services, adding latency, during an ongoing
database transaction is a bad idea because it will lock the rows until the
service call is finalized, which is unpredictable.
The issue is even worse in our pipeline where the SQLite storage driver is used
with the ":memory:" path, which forces the Database pool to have a size of 1.
Since our tests run in parallel, they would randomly fail.
This issue was failing in the CI, but the error was not making the pipeline
fail. This bug was fixed as well.
* feat: add keyset u32 mapping migration and duplicate handling
- Add new database migration (version 3) to include u32 representation for keysets
- Implement migration for both redb and SQL databases
- Add duplicate detection and handling for keyset entries
- Create unique index constraint for keyset_u32 column in SQL
- Update keyset storage to include u32 identifiers
- Handle backwards compatibility for existing databases
* chore: clippy
* refactor(cashu): simplify keyset ID verification logic
- Consolidate match expression into a single expression
- Use direct comparison with ensure_cdk macro
- Improve readability of keyset ID validation
* refactor(cdk): rename `fetch_keyset_keys` to `load_keyset_keys` for clarity
- Renamed `fetch_keyset_keys` to `load_keyset_keys` across multiple modules to better reflect its behavior of loading keys from local storage or fetching from mint when missing.
- Added debug logging to indicate when keys are being fetched from the mint.
- Simplified key loading logic in `update_mint_keysets` by removing redundant existence checks.
* chore: remove unused vec
Custom currency units were incorrectly being converted to uppercase
during deserialization. This change ensures custom units maintain
their original case while still allowing case-insensitive matching
for standard units.
* refactor: add getters to Secret and SecretData
* refactor: use new getters for Secret and SecretData in wallet receive
* refactor: using SecretData constructor
---------
Co-authored-by: thesimplekid <tsk@thesimplekid.com>
* WIP: Introduce a SignatoryManager service.
The SignatoryManager manager provides an API to interact with keysets, private
keys, and all key-related operations, offering segregation between the mint and
the most sensible part of the mind: the private keys.
Although the default signatory runs in memory, it is completely isolated from
the rest of the system and can only be communicated through the interface
offered by the signatory manager. Only messages can be sent from the mintd to
the Signatory trait through the Signatory Manager.
This pull request sets the foundation for eventually being able to run the
Signatory and all the key-related operations in a separate service, possibly in
a foreign service, to offload risks, as described in #476.
The Signatory manager is concurrent and deferred any mechanism needed to handle
concurrency to the Signatory trait.
* Fixed missing default feature for signatory
* Do not read keys from the DB
* Removed KeysDatabase Trait from MintDatabase
All Keys operations should be done through the signatory
* Make sure signatory has all the keys in memory
Drop also foreign constraints on sqlite
* Fix race condition
* Adding debug info to failing test
* Add `sleep` in test
* Fixed issue with active auth keyset
* Fixed dependency
* Move all keys and keysets to an ArcSwap.
Since the keys and keysets exist in RAM, most wrapping functions are infallible
and synchronous, improving performance and adding breaking API changes.
The signatory will provide this information on the boot and update when the
`rotate_keyset` is executed.
Todo: Implement a subscription key to reload the keys when the GRPC server
changes the keys. For the embedded mode, that makes no sense since there is a
single way to rotate keys, and that bit is already covered.
* Implementing https://github.com/cashubtc/nuts/pull/250
* Add CLI for cdk-signatory to spawn an external signatory
Add to the pipeline the external signatory
* Update tests
* Apply suggestions from code review
Co-authored-by: ok300 <106775972+ok300@users.noreply.github.com>
Co-authored-by: thesimplekid <tsk@thesimplekid.com>
* Minor change
* Update proto buf to use the newest format
* Rename binary
* Add instrumentations
* Add more comments
* Use a single database for the signatory
Store all keys, even auth keys, in a single database. Leave the MintAuthDatabse
trait implementation for the CDK but not the signagtory
This commit also moves the cli mod to its own file
* Update dep
* Add `test_mint_keyset_gen` test
---------
Co-authored-by: ok300 <106775972+ok300@users.noreply.github.com>
Co-authored-by: thesimplekid <tsk@thesimplekid.com>