Skip to content

Kukks/DotNut

Repository files navigation

DotNut 🥜

A complete C# implementation of the Cashu protocol - privacy-preserving electronic cash built on Bitcoin.

NuGet License: MIT

What is Cashu?

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.

Installation

dotnet add package DotNut

Quick Start

1. Connect to a Mint

using 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}");

2. Create and Send Tokens

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");

3. Basic Mint Operations

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" 
    }
);

Core Concepts

Tokens and Proofs

  • 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)

Privacy Features

  • 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

Advanced Features

  • P2PK (Pay-to-Public-Key): Multi-signature spending conditions
  • HTLCs: Hash Time-Locked Contracts for atomic swaps
  • Deterministic Secrets: Generate secrets from mnemonic phrases

Working with Secrets

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());

Token Operations

// 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);

Token Encoding Formats

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..."

Error Handling

try
{
    var response = await client.Swap(swapRequest);
}
catch (CashuProtocolException ex)
{
    Console.WriteLine($"Mint error: {ex.Error.Detail}");
    Console.WriteLine($"Error code: {ex.Error.Code}");
}

Nostr Integration

DotNut includes a separate package for Nostr integration:

dotnet add package DotNut.Nostr

This enables payment requests over Nostr (NUT-18) and other Nostr-based features.

Implemented Specifications

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

Requirements

  • .NET 8.0 or later
  • HTTP client for mint communication

Contributing

Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Resources

About

A C# Cashu library

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages

No packages published

Languages