A complete C# implementation of the Cashu protocol - privacy-preserving electronic cash built on Bitcoin.
Cashu is a free and open-source Chaumian e-cash system built for Bitcoin. It offers near-perfect privacy for users and can serve as an excellent custodial scaling solution. DotNut provides a full-featured C# client library for interacting with Cashu mints.
dotnet add package DotNutusing DotNut;
using DotNut.Api;
// Connect to a Cashu mint
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("https://testnut.cashu.space/");
var client = new CashuHttpClient(httpClient);
// Get mint information
var info = await client.GetInfo();
Console.WriteLine($"Connected to: {info.Name}");using DotNut.Encoding;
// Create a token from proofs (obtained from minting)
var token = new CashuToken
{
Unit = "sat",
Memo = "Payment for coffee ☕",
Tokens = new List<CashuToken.Token>
{
new CashuToken.Token
{
Mint = "https://testnut.cashu.space",
Proofs = myProofs // Your token proofs
}
}
};
// Encode for sharing (creates a cashu token string)
string encodedToken = token.Encode("B"); // V4 format (compact)
Console.WriteLine($"Token to share: {encodedToken}");
// Receive and decode a token
var receivedToken = CashuTokenHelper.Decode(encodedToken, out string version);
Console.WriteLine($"Received {receivedToken.TotalAmount()} sats");using DotNut.ApiModels.Mint;
// Create a mint quote for 1000 sats via Lightning
var mintQuote = await client.CreateMintQuote<PostMintQuoteBolt11Response, PostMintQuoteBolt11Request>(
"bolt11",
new PostMintQuoteBolt11Request { Amount = 1000, Unit = "sat" }
);
Console.WriteLine($"Pay this invoice: {mintQuote.Request}");
// After paying the Lightning invoice, mint your tokens...
// Create a melt quote to convert tokens back to Lightning
var meltQuote = await client.CreateMeltQuote<PostMeltQuoteBolt11Response, PostMeltQuoteBolt11Request>(
"bolt11",
new PostMeltQuoteBolt11Request
{
Request = "lnbc1000n1...", // Lightning invoice to pay
Unit = "sat"
}
);- CashuToken: Container for one or more tokens from different mints
- Proof: Cryptographic proof representing a specific amount
- Secret: The secret behind each proof (can be simple strings or complex conditions)
- Blind Signatures: Mint doesn't know which tokens belong to whom
- DLEQ Proofs: Verify mint behavior without compromising privacy
- Token Swapping: Change denominations while maintaining privacy
- P2PK (Pay-to-Public-Key): Multi-signature spending conditions
- HTLCs: Hash Time-Locked Contracts for atomic swaps
- Deterministic Secrets: Generate secrets from mnemonic phrases
using DotNut;
// Simple string secret
var secret = new StringSecret("my-random-secret");
// Deterministic secret from mnemonic (NUT-13)
var mnemonic = new Mnemonic("abandon abandon abandon...");
var deterministicSecret = mnemonic.DeriveSecret(keysetId, counter: 0);
// Pay-to-Public-Key secret (NUT-11)
var p2pkBuilder = new P2PkBuilder
{
Pubkeys = new[] { pubkey1, pubkey2 },
SignatureThreshold = 1, // 1-of-2 multisig
SigFlag = "SIG_INPUTS"
};
var p2pkSecret = new Nut10Secret(P2PKProofSecret.Key, p2pkBuilder.Build());// Check if proofs are still valid
var stateRequest = new PostCheckStateRequest { Ys = proofs.Select(p => p.Y).ToArray() };
var stateResponse = await client.CheckState(stateRequest);
// Swap tokens to different denominations
var swapRequest = new PostSwapRequest
{
Inputs = inputProofs,
Outputs = newBlindedMessages
};
var swapResponse = await client.Swap(swapRequest);
// Restore tokens from secrets (if you've lost proofs)
var restoreRequest = new PostRestoreRequest { Outputs = blindedMessages };
var restoreResponse = await client.Restore(restoreRequest);DotNut supports multiple token encoding formats:
// V3 format (JSON-based)
string v3Token = token.Encode("A");
// V4 format (CBOR-based, more compact)
string v4Token = token.Encode("B");
// As URI for easy sharing
string tokenUri = token.Encode("B", makeUri: true);
// Result: "cashu:cashuB..."try
{
var response = await client.Swap(swapRequest);
}
catch (CashuProtocolException ex)
{
Console.WriteLine($"Mint error: {ex.Error.Detail}");
Console.WriteLine($"Error code: {ex.Error.Code}");
}DotNut includes a separate package for Nostr integration:
dotnet add package DotNut.NostrThis enables payment requests over Nostr (NUT-18) and other Nostr-based features.
Complete implementation of the Cashu protocol specifications:
| NUT | Description | Status |
|---|---|---|
| 00 | Cryptographic primitives | ✅ |
| 01 | Mint public key distribution | ✅ |
| 02 | Keysets and keyset IDs | ✅ |
| 03 | Swapping tokens | ✅ |
| 04 | Minting tokens | ✅ |
| 05 | Melting tokens | ✅ |
| 06 | Mint info | ✅ |
| 07 | Token state check | ✅ |
| 08 | Lightning fee return | ✅ |
| 09 | Token restoration | ✅ |
| 10 | Spending conditions | ✅ |
| 11 | Pay-to-Public-Key (P2PK) | ✅ |
| 12 | DLEQ proofs | ✅ |
| 13 | Deterministic secrets | ✅ |
| 14 | Hash Time-Locked Contracts | ✅ |
| 15 | Multipath payments | ✅ |
| 18 | Payment requests | ✅ |
- .NET 8.0 or later
- HTTP client for mint communication
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests.
This project is licensed under the MIT License - see the LICENSE file for details.