Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ node_modules

# Local SSL certificates
/certs/

# CDK mint data directory
/.cdk-mint/
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,39 @@ or run the certificate script directly by executing `generate-ssl-cert`.
`master` is the main branch. When working on a feature, branch of `master` and when ready make a PR back to `master`.
Try to make feature branches short-lived and concise (avoid implementing multiple features in one PR).

### Running a local CDK mint

Start the mint in background using devenv:

```bash
devenv processes up -d
```

Or you can simply run `cdk-mintd` from your devenv shell.

Either of these methods will create a new directory called `.cdk-mintd` in the root of this project and clone the repository specified by the `CDK_REPO` env variable in [devenv.nix](devenv.nix). After the specified repository is cloned, the script will build and run cdk-mintd on http://localhost:8085. You can configure cdk by modifying the [cdk-mint.config.toml](tools/devenv/cdk/cdk-mint.config.toml)

Once the mint is running and you are in your devenv shell, you can tail the mint's logs with `cdk-logs`.

#### Keycloak

Keycloak is the auth provider that we use when auth is enabled in the mint's config. If auth is enabled, then the `cdk-mintd` script will also use docker compose to start keycloak on http://localhost:8080. Keycloak will be initialized with the data found [here](https://github.com/cashubtc/cdk/tree/main/misc/keycloak/keycloak-export), and then any changes made in the keycloak UI will be persisted in the docker volume.

###### Admin login

To log in to the admin interface the username is `admin` and password is `admin`

###### Creating a new user

Once you are logged into the Keycloak UI, make sure you are in the "cdk-test-realm", then navigate to "Users" and "Add user". Once you create a user go to "Credentials" and set a password. Now you can authenticate with the mint using these credentials.

###### Access settings

You will need to specify the URL of your wallet in "Clients" -> "cashu-client" -> "Access settings". Set the "Valid redirect URIs" to the OIDC callback endpoint of the wallet and "Web origins" to the base URL of your wallet. For example, if your wallet runs on localhost:3000 you would set something like:
- "Valid redirect URIs": http://localhost:3000/oidc-callback
- "Web origins": http://localhost:3000


### Updating development environment

To update devenv packages run `devenv update`. When updating `bun`, make sure to update the `engines` version in
Expand Down
34 changes: 22 additions & 12 deletions devenv.nix
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{ pkgs, lib, config, inputs, ... }:

{
# https://devenv.sh/basics/
env.GREET = "devenv";
{
# CDK repository configuration
env.CDK_REPO = "https://github.com/cashubtc/cdk.git";
env.CDK_REF = "aa624d3afd739a82aa31dfde2632480934004fc2"; # Can be branch, tag, or commit hash

# https://devenv.sh/packages/
packages = [
Expand All @@ -16,26 +17,35 @@
];

# https://devenv.sh/languages/
# languages.rust.enable = true;
languages.rust.enable = true;

# https://devenv.sh/processes/
# processes.cargo-watch.exec = "cargo-watch";
processes.cdk-mint.exec = ''
cdk-mint
'';

# https://devenv.sh/services/
# services.postgres.enable = true;

# https://devenv.sh/scripts/
scripts.hello.exec = ''
echo Hello from $GREET
'';
scripts.webstorm.exec = "$DEVENV_ROOT/tools/devenv/webstorm.sh $@";
scripts.generate-ssl-cert.exec = "$DEVENV_ROOT/tools/devenv/generate-ssl-cert.sh";
scripts.cdk-mint.exec = "$DEVENV_ROOT/tools/devenv/cdk/cdk-mint.sh";
scripts.cdk-logs.exec = "$DEVENV_ROOT/tools/devenv/cdk/cdk-logs.sh $@";

enterShell = ''
hello
git --version
echo Bun version: $(bun --version)
generate-ssl-cert

echo ""
echo "Local CDK Mint:"
echo "🔧 $CDK_REPO (ref: $CDK_REF)"
echo "📝 Mint logs: 'cdk-logs'"
echo "🚀 Start CDK mint: 'devenv processes up' (or 'devenv processes up -d' for background)"
echo " This will start cdk-mintd and Keycloak if auth is enabled in config"
echo "Configure cdk by changing $DEVENV_ROOT/tools/devenv/cdk/cdk-mint.config.toml"
echo ""
'';

# https://devenv.sh/tasks/
Expand All @@ -51,19 +61,19 @@
'';

# https://devenv.sh/pre-commit-hooks/
pre-commit.hooks.generate-db-types = {
git-hooks.hooks.generate-db-types = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there has been a warning for a while that pre-commit was renamed to git-hooks

enable = true;
name = "Generate database types from local db";
entry = "bun run db:generate-types";
};

pre-commit.hooks.typecheck = {
git-hooks.hooks.typecheck = {
enable = true;
entry = "bun run typecheck";
pass_filenames = false;
};

pre-commit.hooks.biome = {
git-hooks.hooks.biome = {
enable = true;
entry = "bun run fix:staged";
};
Expand Down
39 changes: 39 additions & 0 deletions tools/devenv/cdk/cdk-logs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash

# Default number of lines to show
DEFAULT_LINES=50

# Parse command line arguments
LINES=${1:-$DEFAULT_LINES}

# Validate that LINES is a number
if ! [[ "$LINES" =~ ^[0-9]+$ ]]; then
echo "❌ Invalid number of lines: $LINES"
echo "Usage: cdk-logs [number_of_lines]"
echo "Example: cdk-logs 100"
echo "Default: $DEFAULT_LINES lines"
exit 1
fi

LOGS_DIR="$DEVENV_ROOT/.cdk-mint/logs"

# Check if logs directory exists
if [ ! -d "$LOGS_DIR" ]; then
echo "❌ No logs directory found. Start the mint first with 'cdk-mint'"
exit 1
fi

# Find the latest log file (format: cdk-mintd.log.YYYY-MM-DD)
LATEST_LOG=$(ls -t "$LOGS_DIR"/cdk-mintd.log.* 2>/dev/null | head -n 1)

if [ -n "$LATEST_LOG" ] && [ -f "$LATEST_LOG" ]; then
echo "📖 Showing latest CDK mint logs from $(basename "$LATEST_LOG") (last $LINES lines):"
echo "📁 $LATEST_LOG"
echo ""

tail -n "$LINES" -f "$LATEST_LOG"
else
echo "❌ No CDK mint log files found in $LOGS_DIR"
echo "📁 Available files:"
ls -la "$LOGS_DIR/" 2>/dev/null || echo " (directory is empty)"
fi
70 changes: 70 additions & 0 deletions tools/devenv/cdk/cdk-mint.config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# see https://github.com/cashubtc/cdk/blob/main/crates/cdk-mintd/example.config.toml for more options

[info]
url = "http://127.0.0.1:8085/"
listen_host = "127.0.0.1"
listen_port = 8085
mnemonic = "solar decline pole link deposit coconut region race flame truck correct yard"
enable_swagger_ui = true

[mint_management_rpc]
enabled = false

[info.http_cache]
backend = "memory"
ttl = 60
tti = 60


[info.logging]
# Where to output logs: "stdout", "file", or "both" (default: "both")
# Note: "stdout" actually outputs to stderr (standard error stream)
# output = "both"
# Log level for console output (default: "info")
# console_level = "info"
# Log level for file output (default: "debug")
# file_level = "debug"

[mint_info]
name = "Agicash local mint"
description = "Local development mint for testing!"
description_long = ""
motd = ""

[database]
engine = "sqlite"

[ln]
ln_backend = "fakewallet"
min_mint = 1
max_mint = 500000
min_melt = 1
max_melt = 500000

[fake_wallet]
supported_units = ["sat"]
fee_percent = 0.02
reserve_fee_min = 1
min_delay_time = 1
max_delay_time = 3

[auth]
auth_enabled = false
openid_discovery = "http://127.0.0.1:8080/realms/cdk-test-realm/.well-known/openid-configuration"
openid_client_id = "cashu-client"
mint_max_bat=50

# Authentication settings for endpoints
# Options: "clear", "blind", "none" (none = disabled)
mint = "blind"
get_mint_quote = "none"
check_mint_quote = "none"

melt = "none"
get_melt_quote = "none"
check_melt_quote = "none"

swap = "blind"
restore = "blind"
check_proof_state = "none"

158 changes: 158 additions & 0 deletions tools/devenv/cdk/cdk-mint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
#!/bin/bash

echo "🪙 Starting CDK Mint..."

# Fallback to main if not set
CDK_REF="${CDK_REF:-main}"
echo "📍 Using CDK reference: $CDK_REF"

ensure_docker_compose() {
command -v docker &> /dev/null || {
echo "❌ Docker not found. Install Docker to use Keycloak authentication"
return 1
}
docker compose version &> /dev/null || {
echo "❌ Docker Compose not available"
return 1
}
}

# Function to check if auth is enabled in config
check_auth_enabled() {
local config_file="$DEVENV_ROOT/tools/devenv/cdk/cdk-mint.config.toml"
[ -f "$config_file" ] && grep -q "^auth_enabled = true" "$config_file"
}

start_keycloak() {
local cdk_dir="$1"
local keycloak_compose="$cdk_dir/misc/keycloak/docker-compose-recover.yml"
local keycloak_export="$cdk_dir/misc/keycloak/keycloak-export"

ensure_docker_compose || return 1

[ -f "$keycloak_compose" ] && [ -d "$keycloak_export" ] || {
echo "❌ Keycloak files not found:"
echo " Expected: $keycloak_compose"
echo " Expected: $keycloak_export"
return 1
}

echo "🔐 Starting Keycloak..."
cd "$cdk_dir/misc/keycloak"
docker compose -f docker-compose-recover.yml up -d || {
echo "❌ Failed to start Keycloak"
return 1
}

sleep 2
echo "📋 Monitoring Keycloak logs..."
docker compose -f docker-compose-recover.yml logs -f &
echo $! > "$DEVENV_ROOT/.cdk-mint/keycloak-logs.pid"

echo "✅ Keycloak started at http://127.0.0.1:8080"
}

cleanup() {
echo "🧹 Cleaning up..."

# Kill Keycloak logs if running
if [ -f "$DEVENV_ROOT/.cdk-mint/keycloak-logs.pid" ]; then
local logs_pid=$(cat "$DEVENV_ROOT/.cdk-mint/keycloak-logs.pid")
kill -0 "$logs_pid" 2>/dev/null && kill "$logs_pid" 2>/dev/null
rm -f "$DEVENV_ROOT/.cdk-mint/keycloak-logs.pid"
fi

# Stop Keycloak if it was started
if [ -f "$DEVENV_ROOT/.cdk-mint/keycloak-started" ]; then
echo "🔐 Stopping Keycloak..."
cd "$CDK_DIR/misc/keycloak" 2>/dev/null && docker compose -f docker-compose-recover.yml down
rm -f "$DEVENV_ROOT/.cdk-mint/keycloak-started"
fi

exit 0
}

# Set up signal handlers for cleanup
trap cleanup SIGINT SIGTERM

mkdir -p "$DEVENV_ROOT/.cdk-mint"
CDK_DIR="$DEVENV_ROOT/.cdk-mint/cdk-source"

# Function to extract GitHub org/user from URL
get_github_remote_name() {
local url="$1"
# Extract org/user from GitHub URL (handles both https and git formats)
echo "$url" | sed -E 's|.*github\.com[:/]([^/]+)/.*|\1|'
}

# Check if we need to clone or update the repository
if [ ! -d "$CDK_DIR" ]; then
echo "📦 Cloning CDK repository..."
git clone "$CDK_REPO" "$CDK_DIR"
cd "$CDK_DIR"
git checkout "$CDK_REF"
else
cd "$CDK_DIR"

# Get the remote name based on GitHub org/user
remote_name=$(get_github_remote_name "$CDK_REPO")
current_origin=$(git remote get-url origin 2>/dev/null || echo "")

if [ "$current_origin" != "$CDK_REPO" ]; then
echo "🔄 Switching from $(get_github_remote_name "$current_origin") to $remote_name"

# Check if we already have this remote
if git remote get-url "$remote_name" &>/dev/null; then
echo "📡 Remote '$remote_name' already exists, updating URL..."
git remote set-url "$remote_name" "$CDK_REPO"
else
echo "📡 Adding new remote '$remote_name'..."
git remote add "$remote_name" "$CDK_REPO"
fi

# Fetch from the new remote
echo "📥 Fetching from $remote_name..."
git fetch "$remote_name" --tags

# Set the new remote as origin
git remote set-url origin "$CDK_REPO"

# Try to checkout the ref from the new remote
echo "🔄 Switching to $CDK_REF from $remote_name..."
git checkout "$CDK_REF" 2>/dev/null || {
# If the ref doesn't exist locally, try to create it from the remote
git checkout -b "$CDK_REF" "$remote_name/$CDK_REF" 2>/dev/null || {
# If it's a tag or commit, just checkout directly
git fetch "$remote_name" "$CDK_REF:$CDK_REF" 2>/dev/null || true
git checkout "$CDK_REF"
}
}
else
echo "🔄 Updating CDK repository from $remote_name..."
git fetch --all --tags
git checkout "$CDK_REF"
if git show-ref --verify --quiet "refs/heads/$CDK_REF" || git show-ref --verify --quiet "refs/remotes/origin/$CDK_REF"; then
git pull origin "$CDK_REF" 2>/dev/null || true
fi
fi
fi

cd "$CDK_DIR"

# Check if auth is enabled and start Keycloak if needed
if check_auth_enabled; then start_keycloak "$CDK_DIR" || {
echo "❌ Failed to start Keycloak. Cannot start CDK mint with auth enabled."
exit 1
}
touch "$DEVENV_ROOT/.cdk-mint/keycloak-started"
FEATURES="auth,fakewallet"
else
FEATURES="fakewallet"
fi

echo "🚀 Starting CDK mint with features: $FEATURES"

cargo run --package cdk-mintd --features "$FEATURES" -- \
--config "$DEVENV_ROOT/tools/devenv/cdk/cdk-mint.config.toml" \
--work-dir "$DEVENV_ROOT/.cdk-mint" \
2>&1