Rust docs (#681)

This commit is contained in:
thesimplekid
2025-03-25 23:27:38 +00:00
committed by GitHub
parent 1e20e8fc2b
commit 7b4951041e
77 changed files with 795 additions and 80 deletions

View File

@@ -410,3 +410,20 @@ jobs:
uses: Swatinem/rust-cache@v2
- name: Run doc tests
run: nix develop -i -L .#stable --command cargo test --doc
strict-docs:
name: "Strict Documentation Check"
runs-on: ubuntu-latest
timeout-minutes: 15
needs: doc-tests
steps:
- name: checkout
uses: actions/checkout@v4
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@v11
- name: Nix Cache
uses: DeterminateSystems/magic-nix-cache-action@v6
- name: Rust Cache
uses: Swatinem/rust-cache@v2
- name: Check docs with strict warnings
run: nix develop -i -L .#stable --command just docs-strict

View File

@@ -4,6 +4,29 @@ members = [
]
resolver = "2"
[workspace.lints.rust]
unsafe_code = "forbid"
unreachable_pub = "warn"
missing_debug_implementations = "warn"
large_enum_variant = "warn"
[workspace.lints.clippy]
pedantic = "warn"
unwrap_used = "warn"
clone_on_ref_ptr = "warn"
missing_errors_doc = "warn"
missing_panics_doc = "warn"
missing_safety_doc = "warn"
nursery = "warn"
redundant_else = "warn"
redundant_closure_for_method_calls = "warn"
unneeded_field_pattern = "warn"
use_debug = "warn"
[workspace.lints.rustdoc]
missing_docs = "warn"
bare_urls = "warn"
[workspace.package]
edition = "2021"
rust-version = "1.75.0"
@@ -11,6 +34,7 @@ license = "MIT"
homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
version = "0.8.1"
readme = "README.md"
[workspace.dependencies]
anyhow = "1"

View File

@@ -35,6 +35,22 @@ The project is split up into several crates in the `crates/` directory:
For a guide to settings up a development environment see [DEVELOPMENT.md](./DEVELOPMENT.md)
### Code Style Guidelines
- **Large Enum Variants**: When an enum variant contains a large type (>100 bytes), box it using `Box<T>` to reduce the overall enum size. This improves memory efficiency, especially for error types.
```rust
// Instead of this:
enum Error {
SomeLargeError(LargeType), // LargeType is >100 bytes
}
// Do this:
enum Error {
SomeLargeError(Box<LargeType>),
}
```
## Implemented [NUTs](https://github.com/cashubtc/nuts/):
### Mandatory

View File

@@ -8,6 +8,7 @@ homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
rust-version.workspace = true # MSRV
license.workspace = true
readme = "README.md"
[features]
default = ["mint", "wallet", "auth"]

102
crates/cashu/README.md Normal file
View File

@@ -0,0 +1,102 @@
# Cashu
[![crates.io](https://img.shields.io/crates/v/cashu.svg)](https://crates.io/crates/cashu)
[![Documentation](https://docs.rs/cashu/badge.svg)](https://docs.rs/cashu)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/cashubtc/cdk/blob/main/LICENSE)
A Rust implementation of the [Cashu](https://github.com/cashubtc) protocol, providing the core functionality for Cashu e-cash operations.
## Overview
This crate implements the core Cashu protocol as defined in the [Cashu NUTs (Notation, Usage, and Terminology)](https://github.com/cashubtc/nuts/).
## Features
- **Cryptographic Operations**: Secure blind signatures and verification
- **Token Management**: Creation, validation, and manipulation of Cashu tokens
- **NUTs Implementation**: Support for the core Cashu protocol specifications
- **Type-safe API**: Strongly-typed interfaces for working with Cashu primitives
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
cashu = "*"
```
### Basic Example
```rust
use cashu::amount::Amount;
use cashu::nuts::nut00::Token;
use std::str::FromStr;
// Parse a Cashu token from a string
let token_str = "cashuBo2FteCJodHRwczovL25vZmVlcy50ZXN0bnV0LmNhc2h1LnNwYWNlYXVjc2F0YXSBomFpSAC0zSfYhhpEYXCCpGFhAmFzeEAzYzNlOWRhMDU3ZjQzNmExOTc2MmRhOWYyYTBjMzc5YzE5N2RlNDMzZDY5MWU1NDI0ZmRjODcxNjZjMmNlMjZmYWNYIQKKtwESLR-yn5rqNAL3_8_H5BtpwjSPs7uOJ18kPn2mV2Fko2FlWCCsMAK1xoLlwVRxpv8hfsxKYXlXTOomiVt3JCbzNgQpUmFzWCD9MfRUr0asiF_jUJMSylphLvKUd2SLz9oSpcvuLCXPp2FyWCA_1toQ_l158xW0zorqTBXvh76o-_D3e-Ru1Ea-51UrFaRhYQhhc3hAMTM5YWRjZDJlY2Q5MWQyNjNjMDhhMzdhNjBmODZjNDVkYWE3NjNmNjM4NTY0NzEyMmFiZjhlMDM3OGQ0NjA5OGFjWCECHZh5Qx9o-8PaY6t0d5hRTbWeez1dh3md7ehfE25f2N5hZKNhZVgg5MLkVzIw2tDzdUpYwFe-MLhIPJ4hkCpPGL0X7RxpPIRhc1ggyEtcsq3FX8wZOGpwTXOP7BsqfdYdMhGG1X8jVjncDcVhclggyLVOc2xy4m1_YeYGef2HQ8WyJX7LjZq403CS9Dt_eME=";
let token = Token::from_str(token_str).expect("Valid token");
// Get the total amount
let amount: Amount = token.value().expect("Value");
println!("Token amount: {}", amount);
```
## Implemented NUTs
### Mandatory
| NUT # | Description |
|----------|-----------------------------------|
| [00][00] | Cryptography and Models |
| [01][01] | Mint public keys |
| [02][02] | Keysets and fees |
| [03][03] | Swapping tokens |
| [04][04] | Minting tokens |
| [05][05] | Melting tokens |
| [06][06] | Mint info |
### Optional
| # | Description | Status
| --- | --- | --- |
| [07][07] | Token state check | Implemented |
| [08][08] | Overpaid Lightning fees | Implemented |
| [09][09] | Signature restore | Implemented |
| [10][10] | Spending conditions | Implemented |
| [11][11] | Pay-To-Pubkey (P2PK) | Implemented |
| [12][12] | DLEQ proofs | Implemented |
| [13][13] | Deterministic secrets | Implemented |
| [14][14] | Hashed Timelock Contracts (HTLCs) | Implemented |
| [15][15] | Partial multi-path payments (MPP) | Implemented |
| [16][16] | Animated QR codes | Not implemented |
| [17][17] | WebSocket subscriptions | Implemented |
| [18][18] | Payment Requests | Implemented |
| [19][19] | Cached responses | Implemented |
| [20][20] | Signature on Mint Quote | Implemented |
## License
This project is licensed under the [MIT License](https://github.com/cashubtc/cdk/blob/main/LICENSE).
[00]: https://github.com/cashubtc/nuts/blob/main/00.md
[01]: https://github.com/cashubtc/nuts/blob/main/01.md
[02]: https://github.com/cashubtc/nuts/blob/main/02.md
[03]: https://github.com/cashubtc/nuts/blob/main/03.md
[04]: https://github.com/cashubtc/nuts/blob/main/04.md
[05]: https://github.com/cashubtc/nuts/blob/main/05.md
[06]: https://github.com/cashubtc/nuts/blob/main/06.md
[07]: https://github.com/cashubtc/nuts/blob/main/07.md
[08]: https://github.com/cashubtc/nuts/blob/main/08.md
[09]: https://github.com/cashubtc/nuts/blob/main/09.md
[10]: https://github.com/cashubtc/nuts/blob/main/10.md
[11]: https://github.com/cashubtc/nuts/blob/main/11.md
[12]: https://github.com/cashubtc/nuts/blob/main/12.md
[13]: https://github.com/cashubtc/nuts/blob/main/13.md
[14]: https://github.com/cashubtc/nuts/blob/main/14.md
[15]: https://github.com/cashubtc/nuts/blob/main/15.md
[16]: https://github.com/cashubtc/nuts/blob/main/16.md
[17]: https://github.com/cashubtc/nuts/blob/main/17.md
[18]: https://github.com/cashubtc/nuts/blob/main/18.md
[19]: https://github.com/cashubtc/nuts/blob/main/19.md
[20]: https://github.com/cashubtc/nuts/blob/main/20.md

View File

@@ -49,7 +49,7 @@ impl Amount {
/// Amount zero
pub const ZERO: Amount = Amount(0);
// Amount one
/// Amount one
pub const ONE: Amount = Amount(1);
/// Split into parts that are powers of two
@@ -126,12 +126,12 @@ impl Amount {
pub fn split_with_fee(&self, fee_ppk: u64) -> Result<Vec<Self>, Error> {
let without_fee_amounts = self.split();
let fee_ppk = fee_ppk * without_fee_amounts.len() as u64;
let fee = Amount::from((fee_ppk + 999) / 1000);
let fee = Amount::from(fee_ppk.div_ceil(1000));
let new_amount = self.checked_add(fee).ok_or(Error::AmountOverflow)?;
let split = new_amount.split();
let split_fee_ppk = split.len() as u64 * fee_ppk;
let split_fee = Amount::from((split_fee_ppk + 999) / 1000);
let split_fee = Amount::from(split_fee_ppk.div_ceil(1000));
if let Some(net_amount) = new_amount.checked_sub(split_fee) {
if net_amount >= *self {

View File

@@ -1,4 +1,7 @@
//! CDK common types and traits
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]
pub mod amount;
pub mod dhke;
pub mod mint_url;
@@ -9,6 +12,7 @@ pub mod util;
pub use lightning_invoice::{self, Bolt11Invoice};
pub use self::amount::Amount;
pub use self::mint_url::MintUrl;
pub use self::nuts::*;
pub use self::util::SECP256K1;

View File

@@ -103,7 +103,7 @@ pub struct ProtectedEndpoint {
}
impl ProtectedEndpoint {
/// Create [`CachedEndpoint`]
/// Create [`ProtectedEndpoint`]
pub fn new(method: Method, path: RoutePath) -> Self {
Self { method, path }
}
@@ -151,6 +151,7 @@ pub enum RoutePath {
MintBlindAuth,
}
/// Returns [`RoutePath`]s that match regex
pub fn matching_route_paths(pattern: &str) -> Result<Vec<RoutePath>, Error> {
let regex = Regex::from_str(pattern)?;

View File

@@ -267,6 +267,9 @@ impl TokenV3 {
mint_urls
}
/// Checks if a token has multiple mints
///
/// These tokens are not supported by this crate
pub fn is_multi_mint(&self) -> bool {
self.token.len() > 1
}

View File

@@ -158,8 +158,9 @@ mod tests {
}
}
#[cfg(feature = "bench")]
#[cfg(all(feature = "bench", test))]
mod benches {
extern crate test;
use test::{black_box, Bencher};
use super::*;

View File

@@ -60,7 +60,7 @@ pub enum MeltOptions {
}
impl MeltOptions {
/// Create new [`Options::Mpp`]
/// Create new [`MeltOptions::Mpp`]
pub fn new_mpp<A>(amount: A) -> Self
where
A: Into<Amount>,

View File

@@ -1,3 +1,5 @@
//! Cashu utils
#[cfg(not(target_arch = "wasm32"))]
use std::time::{SystemTime, UNIX_EPOCH};

View File

@@ -7,6 +7,7 @@ homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
rust-version.workspace = true # MSRV
description = "Cashu CDK axum webserver"
readme = "README.md"
[features]

31
crates/cdk-axum/README.md Normal file
View File

@@ -0,0 +1,31 @@
# CDK Axum
[![crates.io](https://img.shields.io/crates/v/cdk-axum.svg)](https://crates.io/crates/cdk-axum) [![Documentation](https://docs.rs/cdk-axum/badge.svg)](https://docs.rs/cdk-axum)
The CDK Axum crate is a component of the [Cashu Development Kit](https://github.com/cashubtc/cdk) that provides a web server implementation for Cashu mints using the [Axum](https://github.com/tokio-rs/axum) web framework.
## Overview
This crate implements the HTTP API for Cashu mints, providing endpoints for all the Cashu NUTs (Notation, Usage, and Terminology) specifications. It handles routing, request validation, response formatting, and includes features like WebSocket support and HTTP caching.
## Features
- Complete implementation of Cashu mint HTTP API
- WebSocket support for real-time notifications (NUT-17)
- HTTP response caching for improved performance (NUT-19)
- CORS support for browser-based clients
- Compression and decompression of HTTP payloads
- Configurable logging and tracing
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
cdk-axum = "*"
```
## License
This project is licensed under the [MIT License](https://github.com/cashubtc/cdk/blob/main/LICENSE).

View File

@@ -69,7 +69,7 @@ const DEFAULT_TTI_SECS: u64 = 60;
/// Http cache key.
///
/// This type ensures no Vec<u8> is used as a key, which is error-prone.
/// This type ensures no `Vec<u8>` is used as a key, which is error-prone.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct HttpCacheKey([u8; 32]);

View File

@@ -1,5 +1,6 @@
//! Axum server for Mint
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]

View File

@@ -8,6 +8,7 @@ homepage.workspace = true
repository.workspace = true
edition.workspace = true
rust-version.workspace = true
readme = "README.md"
[features]
sqlcipher = ["cdk-sqlite/sqlcipher"]

View File

@@ -8,6 +8,7 @@ homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
rust-version.workspace = true # MSRV
description = "CDK ln backend for cln"
readme = "README.md"
[dependencies]
async-trait.workspace = true

View File

@@ -1,5 +1,6 @@
//! CDK lightning backend for CLN
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]

View File

@@ -8,6 +8,7 @@ repository = "https://github.com/cashubtc/cdk.git"
edition.workspace = true
rust-version.workspace = true # MSRV
license.workspace = true
readme = "README.md"
[features]
default = ["mint", "wallet"]

View File

@@ -0,0 +1,41 @@
# CDK Common
[![crates.io](https://img.shields.io/crates/v/cdk-common.svg)](https://crates.io/crates/cdk-common)
[![Documentation](https://docs.rs/cdk-common/badge.svg)](https://docs.rs/cdk-common)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/cashubtc/cdk/blob/main/LICENSE)
Common types, traits, and utilities for the Cashu Development Kit (CDK).
## Overview
The `cdk-common` crate provides shared functionality used across the CDK crates. It contains core data structures, error types, and utility functions that are essential for implementing Cashu wallets and mints.
## Features
- **Core Data Types**: Implementations of fundamental Cashu types like `MintUrl`, `ProofInfo`, and `Melted`
- **Error Handling**: Comprehensive error types for Cashu operations
- **Database Abstractions**: Traits for database operations used by wallets and mints
- **NUT Implementations**: Common functionality for Cashu NUTs (Notation, Usage, and Terminology)
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
cdk-common = "*"
```
## Components
The crate includes several key modules:
- **common**: Core data structures used throughout the CDK
- **database**: Traits for database operations
- **error**: Error types and handling
- **mint_url**: Implementation of the MintUrl type
- **nuts**: Common functionality for Cashu NUTs
## License
This project is licensed under the [MIT License](https://github.com/cashubtc/cdk/blob/main/LICENSE).

View File

@@ -155,7 +155,7 @@ pub struct PaymentProcessorKey {
}
impl PaymentProcessorKey {
/// Create new [`LnKey`]
/// Create new [`PaymentProcessorKey`]
pub fn new(unit: CurrencyUnit, method: PaymentMethod) -> Self {
Self { unit, method }
}

View File

@@ -27,11 +27,11 @@ pub trait MintAuthDatabase {
/// Get [`MintKeySetInfo`]s
async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, Self::Err>;
/// Add spent [`Proofs`]
/// Add spent [`AuthProof`]
async fn add_proof(&self, proof: AuthProof) -> Result<(), Self::Err>;
/// Get [`Proofs`] state
/// Get [`AuthProof`] state
async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result<Vec<Option<State>>, Self::Err>;
/// Get [`Proofs`] state
/// Update [`AuthProof`]s state
async fn update_proof_state(
&self,
y: &PublicKey,

View File

@@ -1,11 +1,13 @@
//! Cashu shared types and functions.
//!
//! This crate is the base foundation to build things that can interact with the CDK (Cashu
//! Development Kit) and their internal crates.
//!
//! This is meant to contain the shared types, traits and common functions that are used across the
//! internal crates.
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]
pub mod common;
pub mod database;
pub mod error;

View File

@@ -54,7 +54,7 @@ impl MintQuote {
}
}
// Melt Quote Info
/// Melt Quote Info
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub struct MeltQuote {
/// Quote id
@@ -117,7 +117,7 @@ pub struct MintKeySetInfo {
/// Keyset [`CurrencyUnit`]
pub unit: CurrencyUnit,
/// Keyset active or inactive
/// Mint will only issue new [`BlindSignature`] on active keysets
/// Mint will only issue new signatures on active keysets
pub active: bool,
/// Starting unix time Keyset is valid from
pub valid_from: u64,

View File

@@ -1,3 +1,7 @@
//! WS Index
//!
//!
use std::fmt::Debug;
use std::ops::Deref;
use std::sync::atomic::{AtomicUsize, Ordering};

View File

@@ -1,7 +1,7 @@
//! Publishsubscribe pattern.
//!
//! This is a generic implementation for
//! [NUT-17(https://github.com/cashubtc/nuts/blob/main/17.md) with a type
//! [NUT-17(<https://github.com/cashubtc/nuts/blob/main/17.md>) with a type
//! agnostic Publish-subscribe manager.
//!
//! The manager has a method for subscribers to subscribe to events with a

View File

@@ -12,19 +12,41 @@ use uuid::Uuid;
use crate::pub_sub::SubId;
/// Request to unsubscribe from a websocket subscription
pub type WsUnsubscribeRequest = nut17::ws::WsUnsubscribeRequest<SubId>;
/// Notification message sent over websocket
pub type WsNotification = nut17::ws::WsNotification<SubId>;
/// Response to a subscription request
pub type WsSubscribeResponse = nut17::ws::WsSubscribeResponse<SubId>;
/// Result part of a websocket response
pub type WsResponseResult = nut17::ws::WsResponseResult<SubId>;
/// Response to an unsubscribe request
pub type WsUnsubscribeResponse = nut17::ws::WsUnsubscribeResponse<SubId>;
/// Generic websocket request
pub type WsRequest = nut17::ws::WsRequest<SubId>;
/// Generic websocket response
pub type WsResponse = nut17::ws::WsResponse<SubId>;
/// Method-specific websocket request
pub type WsMethodRequest = nut17::ws::WsMethodRequest<SubId>;
/// Error body for websocket responses
pub type WsErrorBody = nut17::ws::WsErrorBody;
/// Either a websocket message or a response
pub type WsMessageOrResponse = nut17::ws::WsMessageOrResponse<SubId>;
/// Inner content of a notification with generic payload type
pub type NotificationInner<T> = nut17::ws::NotificationInner<T, SubId>;
#[cfg(feature = "mint")]
/// Converts a notification with UUID identifiers to a notification with string identifiers
pub fn notification_uuid_to_notification_string(
notification: NotificationInner<Uuid>,
) -> NotificationInner<String> {
@@ -43,6 +65,7 @@ pub fn notification_uuid_to_notification_string(
}
#[cfg(feature = "mint")]
/// Converts a notification to a websocket message that can be sent to clients
pub fn notification_to_ws_message(notification: NotificationInner<Uuid>) -> WsMessageOrResponse {
nut17::ws::WsMessageOrResponse::Notification(nut17::ws::WsNotification {
jsonrpc: JSON_RPC_VERSION.to_owned(),

View File

@@ -8,6 +8,7 @@ homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
rust-version.workspace = true # MSRV
description = "CDK fake ln backend"
readme = "README.md"
[dependencies]
async-trait.workspace = true

View File

@@ -0,0 +1,35 @@
# CDK Fake Wallet
[![crates.io](https://img.shields.io/crates/v/cdk-fake-wallet.svg)](https://crates.io/crates/cdk-fake-wallet) [![Documentation](https://docs.rs/cdk-fake-wallet/badge.svg)](https://docs.rs/cdk-fake-wallet)
The CDK Fake Wallet is a component of the [Cashu Development Kit](https://github.com/cashubtc/cdk) that provides a simulated Lightning Network backend for testing Cashu mints.
## Overview
This crate implements the `MintPayment` trait with a fake Lightning backend that automatically completes payments without requiring actual Lightning Network transactions. It's designed for development and testing purposes only.
## Features
- Simulated Lightning Network payments
- Automatic completion of payment quotes
- Support for testing mint functionality without real funds
- Implementation of the standard `MintPayment` interface
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
cdk-fake-wallet = "*"
```
## Warning
**This is for testing purposes only!**
The fake wallet should never be used in production environments as it does not perform actual Lightning Network transactions. It simply simulates the payment flow by automatically marking invoices as paid.
## License
This project is licensed under the [MIT License](https://github.com/cashubtc/cdk/blob/main/LICENSE).

View File

@@ -2,6 +2,7 @@
//!
//! Used for testing where quotes are auto filled
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]

View File

@@ -8,6 +8,7 @@ homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
rust-version.workspace = true # MSRV
description = "CDK ln backend for lnbits"
readme = "README.md"
[dependencies]
async-trait.workspace = true

View File

@@ -0,0 +1,30 @@
# CDK LNbits
[![crates.io](https://img.shields.io/crates/v/cdk-lnbits.svg)](https://crates.io/crates/cdk-lnbits) [![Documentation](https://docs.rs/cdk-lnbits/badge.svg)](https://docs.rs/cdk-lnbits)
The CDK LNbits crate is a component of the [Cashu Development Kit](https://github.com/cashubtc/cdk) that provides integration with [LNbits](https://lnbits.com/) as a Lightning Network backend for Cashu mints.
## Overview
This crate implements the `MintPayment` trait for LNbits, allowing Cashu mints to use LNbits as a payment backend for handling Lightning Network transactions.
## Features
- Create and pay Lightning invoices via LNbits
- Handle webhook callbacks for payment notifications
- Manage fee reserves for Lightning transactions
- Support for invoice descriptions
- MPP (Multi-Path Payment) support
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
cdk-lnbits = "*"
```
## License
This project is licensed under the [MIT License](https://github.com/cashubtc/cdk/blob/main/LICENSE).

View File

@@ -1,5 +1,6 @@
//! CDK lightning backend for lnbits
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]

View File

@@ -8,6 +8,7 @@ homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
rust-version.workspace = true # MSRV
description = "CDK ln backend for lnd"
readme = "README.md"
[dependencies]
async-trait.workspace = true

View File

@@ -2,6 +2,7 @@
// Copyright (c) 2023 Steffen (MIT)
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]

View File

@@ -8,6 +8,11 @@ license.workspace = true
homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
rust-version.workspace = true # MSRV
readme = "README.md"
# Disable missing docs warnings for generated code
[package.metadata]
rustdoc-args = ["--allow-missing-docs"]
[[bin]]
name = "cdk-mint-cli"

View File

@@ -1,7 +1,15 @@
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("cargo:rerun-if-changed=src/proto/cdk-mint-rpc.proto");
// Tell cargo to tell rustc to allow missing docs in generated code
println!("cargo:rustc-env=RUSTDOC_ARGS=--allow-missing-docs");
// Configure tonic build to generate code with documentation
tonic_build::configure()
.protoc_arg("--experimental_allow_proto3_optional")
.type_attribute(".", "#[allow(missing_docs)]")
.field_attribute(".", "#[allow(missing_docs)]")
.compile_protos(&["src/proto/cdk-mint-rpc.proto"], &["src/proto"])?;
Ok(())
}

View File

@@ -1,3 +1,6 @@
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]
pub mod proto;
pub mod mint_rpc_cli;

View File

@@ -1 +1,7 @@
//! Module containing command-line interface functionality for the mint RPC client
//!
//! This module provides the CLI interface for interacting with the mint server via RPC
//!
/// Subcommands for cli
pub mod subcommands;

View File

@@ -1,14 +1,26 @@
/// Module for rotating to the next keyset
mod rotate_next_keyset;
/// Module for updating mint contact information
mod update_contact;
/// Module for updating the mint's icon URL
mod update_icon_url;
/// Module for updating the mint's long description
mod update_long_description;
/// Module for updating the mint's message of the day
mod update_motd;
/// Module for updating the mint's name
mod update_name;
/// Module for updating NUT-04 settings (mint process)
mod update_nut04;
/// Module for updating NUT-04 quote state
mod update_nut04_quote;
/// Module for updating NUT-05 settings (melt process)
mod update_nut05;
/// Module for updating the mint's short description
mod update_short_description;
/// Module for updating quote time-to-live settings
mod update_ttl;
/// Module for managing mint URLs
mod update_urls;
pub use rotate_next_keyset::{rotate_next_keyset, RotateNextKeysetCommand};

View File

@@ -6,17 +6,32 @@ use tonic::Request;
use crate::cdk_mint_client::CdkMintClient;
use crate::RotateNextKeysetRequest;
/// Command to rotate to the next keyset for the mint
///
/// This command instructs the mint to rotate to a new keyset, which generates new keys
/// for signing tokens of the specified unit type.
#[derive(Args)]
pub struct RotateNextKeysetCommand {
/// The unit type for the keyset (e.g., "sat")
#[arg(short, long)]
#[arg(default_value = "sat")]
unit: String,
/// The maximum order (power of 2) for tokens that can be minted with this keyset
#[arg(short, long)]
max_order: Option<u8>,
/// The input fee in parts per thousand to apply when minting with this keyset
#[arg(short, long)]
input_fee_ppk: Option<u64>,
}
/// Executes the rotate_next_keyset command against the mint server
///
/// This function sends an RPC request to the mint to rotate to a new keyset with the
/// specified parameters and prints the resulting keyset information.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The arguments specifying how the new keyset should be configured
pub async fn rotate_next_keyset(
client: &mut CdkMintClient<Channel>,
sub_command_args: &RotateNextKeysetCommand,

View File

@@ -6,12 +6,25 @@ use tonic::Request;
use crate::cdk_mint_client::CdkMintClient;
use crate::UpdateContactRequest;
/// Command to add a contact method to the mint
///
/// This command adds a new contact method with associated information to the mint.
/// Contact methods allow users to reach the mint operators through various channels.
#[derive(Args)]
pub struct AddContactCommand {
/// The contact method type (e.g., "email", "twitter", "telegram")
method: String,
/// The contact information for the specified method
info: String,
}
/// Executes the add_contact command against the mint server
///
/// This function sends an RPC request to add a new contact method to the mint.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The contact method and information to add
pub async fn add_contact(
client: &mut CdkMintClient<Channel>,
sub_command_args: &AddContactCommand,
@@ -26,12 +39,25 @@ pub async fn add_contact(
Ok(())
}
/// Command to remove a contact method from the mint
///
/// This command removes an existing contact method and its associated information
/// from the mint's available contact methods.
#[derive(Args)]
pub struct RemoveContactCommand {
/// The contact method type to remove (e.g., "email", "twitter", "telegram")
method: String,
/// The specific contact information to remove for the specified method
info: String,
}
/// Executes the remove_contact command against the mint server
///
/// This function sends an RPC request to remove an existing contact method from the mint.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The contact method and information to remove
pub async fn remove_contact(
client: &mut CdkMintClient<Channel>,
sub_command_args: &RemoveContactCommand,

View File

@@ -6,11 +6,23 @@ use tonic::Request;
use crate::cdk_mint_client::CdkMintClient;
use crate::UpdateIconUrlRequest;
/// Command to update the mint's icon URL
///
/// This command sets a new icon URL for the mint, which is used to visually
/// identify the mint in wallet applications and other client interfaces.
#[derive(Args)]
pub struct UpdateIconUrlCommand {
/// The URL to the mint's icon image
name: String,
}
/// Executes the update_icon_url command against the mint server
///
/// This function sends an RPC request to update the mint's icon URL.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The new icon URL to set
pub async fn update_icon_url(
client: &mut CdkMintClient<Channel>,
sub_command_args: &UpdateIconUrlCommand,

View File

@@ -6,11 +6,23 @@ use tonic::Request;
use crate::cdk_mint_client::CdkMintClient;
use crate::UpdateDescriptionRequest;
/// Command to update the mint's long description
///
/// This command sets a new long description for the mint, which provides detailed
/// information about the mint's purpose, operation, and policies.
#[derive(Args)]
pub struct UpdateLongDescriptionCommand {
/// The new long description text for the mint
description: String,
}
/// Executes the update_long_description command against the mint server
///
/// This function sends an RPC request to update the mint's long description.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The new long description to set
pub async fn update_long_description(
client: &mut CdkMintClient<Channel>,
sub_command_args: &UpdateLongDescriptionCommand,

View File

@@ -6,11 +6,23 @@ use tonic::Request;
use crate::cdk_mint_client::CdkMintClient;
use crate::UpdateMotdRequest;
/// Command to update the mint's message of the day
///
/// This command sets a new message of the day (MOTD) for the mint, which can be used
/// to communicate important announcements, updates, or status information to users.
#[derive(Args)]
pub struct UpdateMotdCommand {
/// The new message of the day text
motd: String,
}
/// Executes the update_motd command against the mint server
///
/// This function sends an RPC request to update the mint's message of the day.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The new message of the day to set
pub async fn update_motd(
client: &mut CdkMintClient<Channel>,
sub_command_args: &UpdateMotdCommand,

View File

@@ -6,11 +6,23 @@ use tonic::Request;
use crate::cdk_mint_client::CdkMintClient;
use crate::UpdateNameRequest;
/// Command to update the mint's name
///
/// This command sets a new display name for the mint, which is used to identify
/// the mint in wallet applications and other client interfaces.
#[derive(Args)]
pub struct UpdateNameCommand {
/// The new name for the mint
name: String,
}
/// Executes the update_name command against the mint server
///
/// This function sends an RPC request to update the mint's display name.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The new name to set for the mint
pub async fn update_name(
client: &mut CdkMintClient<Channel>,
sub_command_args: &UpdateNameCommand,

View File

@@ -6,24 +6,42 @@ use tonic::Request;
use crate::cdk_mint_client::CdkMintClient;
use crate::UpdateNut04Request;
/// Command to update NUT-04 (mint process) settings for the mint
///
/// NUT-04 defines how tokens are minted in exchange for external payments. This command
/// allows configuring the available token units, payment methods, amounts, and other settings
/// for the minting process.
#[derive(Args)]
pub struct UpdateNut04Command {
/// The token unit type (e.g., "sat")
#[arg(short, long)]
#[arg(default_value = "sat")]
unit: String,
/// The payment method for minting (e.g., "bolt11" for Lightning payments)
#[arg(short, long)]
#[arg(default_value = "bolt11")]
method: String,
/// The minimum amount that can be minted in a single transaction
#[arg(long)]
min_amount: Option<u64>,
/// The maximum amount that can be minted in a single transaction
#[arg(long)]
max_amount: Option<u64>,
/// Whether this mint method is disabled (true) or enabled (false)
#[arg(long)]
disabled: Option<bool>,
/// Whether the mint should include description fields in Lightning invoices
#[arg(long)]
description: Option<bool>,
}
/// Executes the update_nut04 command against the mint server
///
/// This function sends an RPC request to update the mint's NUT-04 settings for token minting.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The NUT-04 configuration parameters to update
pub async fn update_nut04(
client: &mut CdkMintClient<Channel>,
sub_command_args: &UpdateNut04Command,

View File

@@ -6,13 +6,27 @@ use tonic::Request;
use crate::cdk_mint_client::CdkMintClient;
use crate::UpdateNut04QuoteRequest;
/// Command to update the state of a NUT-04 quote
///
/// NUT-04 quotes represent pending mint operations. This command allows updating
/// the state of a quote (e.g., marking it as paid) to process the minting of tokens.
#[derive(Args)]
pub struct UpdateNut04QuoteCommand {
/// The ID of the quote to update
quote_id: String,
/// The new state to set for the quote (default: "PAID")
#[arg(default_value = "PAID")]
state: String,
}
/// Executes the update_nut04_quote_state command against the mint server
///
/// This function sends an RPC request to update the state of a NUT-04 quote,
/// which can trigger the minting of tokens once a quote is marked as paid.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The quote ID and new state to set
pub async fn update_nut04_quote_state(
client: &mut CdkMintClient<Channel>,
sub_command_args: &UpdateNut04QuoteCommand,

View File

@@ -6,22 +6,39 @@ use tonic::Request;
use crate::cdk_mint_client::CdkMintClient;
use crate::UpdateNut05Request;
/// Command to update NUT-05 (melt process) settings for the mint
///
/// NUT-05 defines how tokens are melted (redeemed) in exchange for external payments.
/// This command allows configuring the available token units, payment methods, amounts,
/// and other settings for the melting process.
#[derive(Args)]
pub struct UpdateNut05Command {
/// The token unit type (e.g., "sat")
#[arg(short, long)]
#[arg(default_value = "sat")]
unit: String,
/// The payment method for melting (e.g., "bolt11" for Lightning payments)
#[arg(short, long)]
#[arg(default_value = "bolt11")]
method: String,
/// The minimum amount that can be melted in a single transaction
#[arg(long)]
min_amount: Option<u64>,
/// The maximum amount that can be melted in a single transaction
#[arg(long)]
max_amount: Option<u64>,
/// Whether this melt method is disabled (true) or enabled (false)
#[arg(long)]
disabled: Option<bool>,
}
/// Executes the update_nut05 command against the mint server
///
/// This function sends an RPC request to update the mint's NUT-05 settings for token melting.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The NUT-05 configuration parameters to update
pub async fn update_nut05(
client: &mut CdkMintClient<Channel>,
sub_command_args: &UpdateNut05Command,

View File

@@ -6,11 +6,24 @@ use tonic::Request;
use crate::cdk_mint_client::CdkMintClient;
use crate::UpdateDescriptionRequest;
/// Command to update the mint's short description
///
/// This command sets a new short description for the mint, which provides a brief
/// summary of the mint's purpose or characteristics. The short description is typically
/// displayed in wallets and client interfaces.
#[derive(Args)]
pub struct UpdateShortDescriptionCommand {
/// The new short description text for the mint
description: String,
}
/// Executes the update_short_description command against the mint server
///
/// This function sends an RPC request to update the mint's short description.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The new short description to set
pub async fn update_short_description(
client: &mut CdkMintClient<Channel>,
sub_command_args: &UpdateShortDescriptionCommand,

View File

@@ -6,13 +6,27 @@ use tonic::Request;
use crate::cdk_mint_client::CdkMintClient;
use crate::UpdateQuoteTtlRequest;
/// Command to update the time-to-live (TTL) settings for quotes
///
/// This command configures how long mint and melt quotes remain valid before
/// automatically expiring. Quote TTL settings help manage pending operations and
/// resource usage on the mint.
#[derive(Args)]
pub struct UpdateQuoteTtlCommand {
/// The TTL (in seconds) for mint quotes
#[arg(long)]
mint_ttl: Option<u64>,
/// The TTL (in seconds) for melt quotes
#[arg(long)]
melt_ttl: Option<u64>,
}
/// Executes the update_quote_ttl command against the mint server
///
/// This function sends an RPC request to update the TTL settings for mint and melt quotes.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The new TTL values to set for quotes
pub async fn update_quote_ttl(
client: &mut CdkMintClient<Channel>,
sub_command_args: &UpdateQuoteTtlCommand,

View File

@@ -6,11 +6,24 @@ use tonic::Request;
use crate::cdk_mint_client::CdkMintClient;
use crate::UpdateUrlRequest;
/// Command to add a URL to the mint's list of endpoints
///
/// This command adds a new URL to the mint's list of available endpoints.
/// Multiple URLs allow clients to access the mint through different endpoints,
/// providing redundancy and flexibility.
#[derive(Args)]
pub struct AddUrlCommand {
/// The URL to add to the mint's endpoints
url: String,
}
/// Executes the add_url command against the mint server
///
/// This function sends an RPC request to add a new URL to the mint's list of endpoints.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The URL to add to the mint
pub async fn add_url(
client: &mut CdkMintClient<Channel>,
sub_command_args: &AddUrlCommand,
@@ -24,11 +37,23 @@ pub async fn add_url(
Ok(())
}
/// Command to remove a URL from the mint's list of endpoints
///
/// This command removes an existing URL from the mint's list of available endpoints.
/// This can be used to retire endpoints that are no longer in use or available.
#[derive(Args)]
pub struct RemoveUrlCommand {
/// The URL to remove from the mint's endpoints
url: String,
}
/// Executes the remove_url command against the mint server
///
/// This function sends an RPC request to remove an existing URL from the mint's list of endpoints.
///
/// # Arguments
/// * `client` - The RPC client used to communicate with the mint
/// * `sub_command_args` - The URL to remove from the mint
pub async fn remove_url(
client: &mut CdkMintClient<Channel>,
sub_command_args: &RemoveUrlCommand,

View File

@@ -1,3 +1,5 @@
//! CDK mint proto types
tonic::include_proto!("cdk_mint_rpc");
mod server;

View File

@@ -48,6 +48,12 @@ pub struct MintRPCServer {
}
impl MintRPCServer {
/// Creates a new MintRPCServer instance
///
/// # Arguments
/// * `addr` - The address to bind to
/// * `port` - The port to listen on
/// * `mint` - The Mint instance to serve
pub fn new(addr: &str, port: u16, mint: Arc<Mint>) -> Result<Self, Error> {
Ok(Self {
socket_addr: format!("{addr}:{port}").parse()?,
@@ -57,6 +63,15 @@ impl MintRPCServer {
})
}
/// Starts the RPC server
///
/// # Arguments
/// * `tls_dir` - Optional directory containing TLS certificates
///
/// If TLS directory is provided, it must contain:
/// - server.pem: Server certificate
/// - server.key: Server private key
/// - ca.pem: CA certificate for client authentication
pub async fn start(&mut self, tls_dir: Option<PathBuf>) -> Result<(), Error> {
tracing::info!("Starting RPC server {}", self.socket_addr);
@@ -137,6 +152,7 @@ impl MintRPCServer {
Ok(())
}
/// Stops the RPC server gracefully
pub async fn stop(&self) -> Result<(), Error> {
self.shutdown.notify_one();
if let Some(handle) = &self.handle {
@@ -160,6 +176,7 @@ impl Drop for MintRPCServer {
#[tonic::async_trait]
impl CdkMint for MintRPCServer {
/// Returns information about the mint
async fn get_info(
&self,
_request: Request<GetInfoRequest>,
@@ -212,6 +229,7 @@ impl CdkMint for MintRPCServer {
}))
}
/// Updates the mint's message of the day
async fn update_motd(
&self,
request: Request<UpdateMotdRequest>,
@@ -232,6 +250,7 @@ impl CdkMint for MintRPCServer {
Ok(Response::new(UpdateResponse {}))
}
/// Updates the mint's short description
async fn update_short_description(
&self,
request: Request<UpdateDescriptionRequest>,
@@ -252,6 +271,7 @@ impl CdkMint for MintRPCServer {
Ok(Response::new(UpdateResponse {}))
}
/// Updates the mint's long description
async fn update_long_description(
&self,
request: Request<UpdateDescriptionRequest>,
@@ -272,6 +292,7 @@ impl CdkMint for MintRPCServer {
Ok(Response::new(UpdateResponse {}))
}
/// Updates the mint's name
async fn update_name(
&self,
request: Request<UpdateNameRequest>,
@@ -292,6 +313,7 @@ impl CdkMint for MintRPCServer {
Ok(Response::new(UpdateResponse {}))
}
/// Updates the mint's icon URL
async fn update_icon_url(
&self,
request: Request<UpdateIconUrlRequest>,
@@ -313,6 +335,7 @@ impl CdkMint for MintRPCServer {
Ok(Response::new(UpdateResponse {}))
}
/// Adds a URL to the mint's list of URLs
async fn add_url(
&self,
request: Request<UpdateUrlRequest>,
@@ -335,6 +358,7 @@ impl CdkMint for MintRPCServer {
Ok(Response::new(UpdateResponse {}))
}
/// Removes a URL from the mint's list of URLs
async fn remove_url(
&self,
request: Request<UpdateUrlRequest>,
@@ -357,6 +381,7 @@ impl CdkMint for MintRPCServer {
Ok(Response::new(UpdateResponse {}))
}
/// Adds a contact method to the mint's contact information
async fn add_contact(
&self,
request: Request<UpdateContactRequest>,
@@ -381,6 +406,7 @@ impl CdkMint for MintRPCServer {
.map_err(|err| Status::internal(err.to_string()))?;
Ok(Response::new(UpdateResponse {}))
}
/// Removes a contact method from the mint's contact information
async fn remove_contact(
&self,
request: Request<UpdateContactRequest>,
@@ -405,6 +431,7 @@ impl CdkMint for MintRPCServer {
Ok(Response::new(UpdateResponse {}))
}
/// Updates the mint's NUT-04 (mint) settings
async fn update_nut04(
&self,
request: Request<UpdateNut04Request>,
@@ -465,6 +492,7 @@ impl CdkMint for MintRPCServer {
Ok(Response::new(UpdateResponse {}))
}
/// Updates the mint's NUT-05 (melt) settings
async fn update_nut05(
&self,
request: Request<UpdateNut05Request>,
@@ -518,6 +546,7 @@ impl CdkMint for MintRPCServer {
Ok(Response::new(UpdateResponse {}))
}
/// Updates the mint's quote time-to-live settings
async fn update_quote_ttl(
&self,
request: Request<UpdateQuoteTtlRequest>,
@@ -543,6 +572,7 @@ impl CdkMint for MintRPCServer {
Ok(Response::new(UpdateResponse {}))
}
/// Updates a specific NUT-04 quote's state
async fn update_nut04_quote(
&self,
request: Request<UpdateNut04QuoteRequest>,
@@ -597,6 +627,7 @@ impl CdkMint for MintRPCServer {
}))
}
/// Rotates to the next keyset for the specified currency unit
async fn rotate_next_keyset(
&self,
request: Request<RotateNextKeysetRequest>,

View File

@@ -8,6 +8,7 @@ homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
description = "CDK mint binary"
rust-version.workspace = true
readme = "README.md"
[features]
default = ["management-rpc", "cln", "lnd", "lnbits", "fakewallet", "grpc-processor", "auth"]

View File

@@ -8,6 +8,7 @@ homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
rust-version.workspace = true # MSRV
license.workspace = true
readme = "README.md"
[[bin]]
name = "cdk-payment-processor"

View File

@@ -2,6 +2,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("cargo:rerun-if-changed=src/proto/payment_processor.proto");
tonic_build::configure()
.protoc_arg("--experimental_allow_proto3_optional")
.type_attribute(".", "#[allow(missing_docs)]")
.field_attribute(".", "#[allow(missing_docs)]")
.compile_protos(&["src/proto/payment_processor.proto"], &["src/proto"])?;
Ok(())
}

View File

@@ -1,3 +1,7 @@
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]
pub mod error;
pub mod proto;

View File

@@ -1,3 +1,5 @@
//! Proto types for payment processor
use std::str::FromStr;
use cdk_common::payment::{

View File

@@ -32,6 +32,7 @@ pub struct PaymentProcessorServer {
}
impl PaymentProcessorServer {
/// Create new [`PaymentProcessorServer`]
pub fn new(
payment_processor: Arc<dyn MintPayment<Err = cdk_common::payment::Error> + Send + Sync>,
addr: &str,

View File

@@ -8,6 +8,7 @@ license.workspace = true
homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
rust-version.workspace = true # MSRV
readme = "README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]

View File

@@ -9,22 +9,22 @@ use thiserror::Error;
pub enum Error {
/// Redb Error
#[error(transparent)]
Redb(#[from] redb::Error),
Redb(#[from] Box<redb::Error>),
/// Redb Database Error
#[error(transparent)]
Database(#[from] redb::DatabaseError),
Database(#[from] Box<redb::DatabaseError>),
/// Redb Transaction Error
#[error(transparent)]
Transaction(#[from] redb::TransactionError),
Transaction(#[from] Box<redb::TransactionError>),
/// Redb Commit Error
#[error(transparent)]
Commit(#[from] redb::CommitError),
Commit(#[from] Box<redb::CommitError>),
/// Redb Table Error
#[error(transparent)]
Table(#[from] redb::TableError),
Table(#[from] Box<redb::TableError>),
/// Redb Storage Error
#[error(transparent)]
Storage(#[from] redb::StorageError),
Storage(#[from] Box<redb::StorageError>),
/// Serde Json Error
#[error(transparent)]
Serde(#[from] serde_json::Error),
@@ -71,3 +71,40 @@ impl From<Error> for cdk_common::database::Error {
Self::Database(Box::new(e))
}
}
// Implement From for boxed redb errors
impl From<redb::Error> for Error {
fn from(e: redb::Error) -> Self {
Self::Redb(Box::new(e))
}
}
impl From<redb::DatabaseError> for Error {
fn from(e: redb::DatabaseError) -> Self {
Self::Database(Box::new(e))
}
}
impl From<redb::TransactionError> for Error {
fn from(e: redb::TransactionError) -> Self {
Self::Transaction(Box::new(e))
}
}
impl From<redb::CommitError> for Error {
fn from(e: redb::CommitError) -> Self {
Self::Commit(Box::new(e))
}
}
impl From<redb::TableError> for Error {
fn from(e: redb::TableError) -> Self {
Self::Table(Box::new(e))
}
}
impl From<redb::StorageError> for Error {
fn from(e: redb::StorageError) -> Self {
Self::Storage(Box::new(e))
}
}

View File

@@ -1,5 +1,6 @@
//! SQLite Storage backend for CDK
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]

View File

@@ -33,7 +33,7 @@ pub struct MintRedbAuthDatabase {
const DATABASE_VERSION: u32 = 0;
impl MintRedbAuthDatabase {
/// Create new [`MintRedbDatabase`]
/// Create new [`MintRedbAuthDatabase`]
pub fn new(path: &Path) -> Result<Self, Error> {
{
// Check database version

View File

@@ -722,7 +722,7 @@ impl MintDatabase for MintRedbDatabase {
}
// Check if any proofs are spent
if states.iter().any(|state| *state == Some(State::Spent)) {
if states.contains(&Some(State::Spent)) {
write_txn.abort().map_err(Error::from)?;
return Err(database::Error::AttemptUpdateSpentProof);
}

View File

@@ -8,6 +8,7 @@ license.workspace = true
homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
rust-version.workspace = true # MSRV
readme = "README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]

View File

@@ -8,6 +8,7 @@ license.workspace = true
homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
rust-version.workspace = true # MSRV
readme = "README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]

View File

@@ -24,7 +24,7 @@ pub struct MintSqliteAuthDatabase {
}
impl MintSqliteAuthDatabase {
/// Create new [`MintSqliteDatabase`]
/// Create new [`MintSqliteAuthDatabase`]
pub async fn new(path: &Path) -> Result<Self, Error> {
let path = path.to_str().ok_or(Error::InvalidDbPath)?;
let db_options = SqliteConnectOptions::from_str(path)?
@@ -41,7 +41,7 @@ impl MintSqliteAuthDatabase {
Ok(Self { pool })
}
/// Migrate [`MintSqliteDatabase`]
/// Migrate [`MintSqliteAuthDatabase`]
pub async fn migrate(&self) {
sqlx::migrate!("./src/mint/auth/migrations")
.run(&self.pool)

View File

@@ -1,9 +1,12 @@
# CDK (Cashu Development Kit)
# Cashu Development Kit
[![crates.io](https://img.shields.io/crates/v/cdk.svg)](https://crates.io/crates/cdk)
[![Documentation](https://docs.rs/cdk/badge.svg)](https://docs.rs/cdk)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/cashubtc/cdk/blob/main/LICENSE)
**ALPHA** This library is in early development, the api will change and should be used with caution.
**ALPHA** This library is in early development, the API will change and should be used with caution.
CDK is the core crate implementing the cashu protocol for both the Wallet and Mint.
The core implementation of the Cashu protocol for building wallets and mints. It builds upon the primitives defined in the `cashu` crate and provides higher-level abstractions for working with the Cashu ecosystem.
## Crate Feature Flags
@@ -13,70 +16,96 @@ The following crate feature flags are available:
|-------------|:-------:|------------------------------------|
| `wallet` | Yes | Enable cashu wallet features |
| `mint` | Yes | Enable cashu mint wallet features |
| `auth` | Yes | Enable blind and clear auth |
## Implemented [NUTs](https://github.com/cashubtc/nuts/):
See <https://github.com/cashubtc/cdk/blob/main/README.md>
## Examples
## Components
```rust
The crate includes several key modules:
- **wallet**: Implementation of the Cashu wallet
- **mint**: Implementation of the Cashu mint
- **database**: Database abstractions for persistent storage
- **payment**: Payment processing functionality
- **nuts**: Implementation of the Cashu NUTs
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
cdk = "*"
```
## Example
```rust,no_run
//! Wallet example with memory store
//! Note: This example requires the "wallet" feature to be enabled (enabled by default)
use std::sync::Arc;
use std::time::Duration;
#[cfg(feature = "wallet")]
use cdk::amount::SplitTarget;
use cdk_sqlite::wallet::memory;
use cdk::nuts::{CurrencyUnit, MintQuoteState};
#[cfg(feature = "wallet")]
use cdk::wallet::Wallet;
#[cfg(feature = "wallet")]
use cdk::wallet::SendOptions;
use cdk::Amount;
use rand::Rng;
use tokio::time::sleep;
#[tokio::main]
async fn main() {
let seed = rand::thread_rng().gen::<[u8; 32]>();
#[cfg(feature = "wallet")]
{
let seed = rand::thread_rng().gen::<[u8; 32]>();
let mint_url = "https://testnut.cashu.space";
let unit = CurrencyUnit::Sat;
let amount = Amount::from(10);
let mint_url = "https://testnut.cashu.space";
let unit = CurrencyUnit::Sat;
let amount = Amount::from(10);
let localstore = memory::empty().await.unwrap();
let localstore = memory::empty().await.unwrap();
let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None, None);
let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None).unwrap();
let quote = wallet.mint_quote(amount).await.unwrap();
let quote = wallet.mint_quote(amount, None).await.unwrap();
println!("Pay request: {}", quote.request);
println!("Pay request: {}", quote.request);
loop {
let status = wallet.mint_quote_state(&quote.id).await.unwrap();
loop {
let status = wallet.mint_quote_state(&quote.id).await.unwrap();
if status.state == MintQuoteState::Paid {
break;
if status.state == MintQuoteState::Paid {
break;
}
println!("Quote state: {}", status.state);
sleep(Duration::from_secs(5)).await;
}
println!("Quote state: {}", status.state);
let receive_amount = wallet
.mint(&quote.id, SplitTarget::default(), None)
.await
.unwrap();
sleep(Duration::from_secs(5)).await;
println!("Minted {:?}", receive_amount);
// Send the token
let prepared_send = wallet.prepare_send(Amount::ONE, SendOptions::default()).await.unwrap();
let token = wallet.send(prepared_send, None).await.unwrap();
println!("{}", token);
}
let receive_amount = wallet
.mint(&quote.id, SplitTarget::default(), None)
.await
.unwrap();
println!("Minted {}", receive_amount);
let token = wallet
.send(amount, None, None, &SplitTarget::None)
.await
.unwrap();
println!("{}", token);
}
```
See more examples in the [examples](./examples) folder.
@@ -88,17 +117,17 @@ The `cdk` library should always compile with any combination of features on Rust
To build and test with the MSRV you will need to pin the below dependency versions:
```shell
cargo update -p half --precise 2.2.1
cargo update -p tokio --precise 1.38.1
cargo update -p reqwest --precise 0.12.4
cargo update -p serde_with --precise 3.1.0
cargo update -p regex --precise 1.9.6
cargo update -p backtrace --precise 0.3.58
# For wasm32-unknown-unknown target
cargo update -p bumpalo --precise 3.12.0
cargo update -p async-compression --precise 0.4.3
cargo update -p zstd-sys --precise 2.0.8+zstd.1.5.5
cargo update -p flate2 --precise 1.0.35
cargo update -p home --precise 0.5.5
cargo update -p zerofrom --precise 0.1.5
cargo update -p half --precise 2.4.1
cargo update -p url --precise 2.5.2
# For wasm32-unknown-unknown target
cargo update -p triomphe --precise 0.1.11
```
## License
This project is distributed under the MIT software license - see the [LICENSE](../../LICENSE) file for details
This project is licensed under the [MIT License](https://github.com/cashubtc/cdk/blob/main/LICENSE).

View File

@@ -1,5 +1,5 @@
//! Rust implementation of the Cashu Protocol
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![warn(rustdoc::bare_urls)]

View File

@@ -361,7 +361,7 @@ impl Mint {
/// Process unpaid melt request
/// In the event that a melt request fails and the lighthing payment is not
/// made The [`Proofs`] should be returned to an unspent state and the
/// made The proofs should be returned to an unspent state and the
/// quote should be unpaid
#[instrument(skip_all)]
pub async fn process_unpaid_melt(
@@ -600,7 +600,7 @@ impl Mint {
Ok(res)
}
/// Process melt request marking [`Proofs`] as spent
/// Process melt request marking proofs as spent
/// The melt request must be verifyed using [`Self::verify_melt_request`]
/// before calling [`Self::process_melt_request`]
#[instrument(skip_all)]

View File

@@ -1,7 +1,7 @@
//! Publishsubscribe pattern.
//!
//! This is a generic implementation for
//! [NUT-17(https://github.com/cashubtc/nuts/blob/main/17.md) with a type
//! [NUT-17(<https://github.com/cashubtc/nuts/blob/main/17.md>) with a type
//! agnostic Publish-subscribe manager.
//!
//! The manager has a method for subscribers to subscribe to events with a
@@ -243,7 +243,7 @@ where
/// Active Subscription
///
/// This struct is a wrapper around the mpsc::Receiver<Event> and it also used
/// This struct is a wrapper around the `mpsc::Receiver<Event>` and it also used
/// to keep track of the subscription itself. When this struct goes out of
/// scope, it will notify the Manager about it, so it can be removed from the
/// list of active listeners

View File

@@ -6,7 +6,7 @@ use cdk_common::{AuthToken, MintInfo};
use super::Error;
use crate::nuts::{Id, KeySet, KeysetResponse, MintAuthRequest, MintBolt11Response};
/// Interface that connects a wallet to a mint. Typically represents an [HttpClient].
/// Interface that connects a wallet to a mint. Typically represents an HttpClient.
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait AuthMintConnector: Debug {

View File

@@ -17,7 +17,7 @@ use crate::{Amount, Error, Wallet};
impl Wallet {
/// Mint Quote
/// # Synopsis
/// ```rust
/// ```rust,no_run
/// use std::sync::Arc;
///
/// use cdk::amount::Amount;
@@ -138,7 +138,7 @@ impl Wallet {
/// Mint
/// # Synopsis
/// ```rust
/// ```rust,no_run
/// use std::sync::Arc;
///
/// use anyhow::Result;

View File

@@ -184,7 +184,7 @@ pub enum Error {
}
impl SubscriptionClient {
/// Create new [`WebSocketClient`]
/// Create new [`SubscriptionClient`]
pub fn new(
url: MintUrl,
http_client: Arc<dyn MintConnector + Send + Sync>,

View File

@@ -174,3 +174,31 @@ check-docs:
cargo doc $arg --all-features
echo
done
# Build docs for all crates and error on warnings
docs-strict:
#!/usr/bin/env bash
set -euo pipefail
args=(
"-p cashu"
"-p cdk-common"
"-p cdk"
"-p cdk-redb"
"-p cdk-sqlite"
"-p cdk-axum"
"-p cdk-rexie"
"-p cdk-cln"
"-p cdk-lnd"
"-p cdk-lnbits"
"-p cdk-fake-wallet"
"-p cdk-mint-rpc"
"-p cdk-payment-processor"
"-p cdk-cli"
"-p cdk-mintd"
)
for arg in "${args[@]}"; do
echo "Building docs for $arg with strict warnings"
RUSTDOCFLAGS="-D warnings" cargo doc $arg --all-features --no-deps
echo
done