Skip to content

Commit a721120

Browse files
Andréclaude
andcommitted
feat: bundle all service binaries in nix CLI package
The nix package now includes hathor-core, cpuminer, tx-mining-service, and wallet-headless. Python/Node services are lazily installed into ~/.cache/hathor-forge/ on first run. `nix run github:HathorNetwork/hathor-forge -- --start` now starts all services end-to-end. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 7924332 commit a721120

File tree

4 files changed

+171
-67
lines changed

4 files changed

+171
-67
lines changed

flake.nix

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
description = "Hathor Forge - Local development environment for Hathor Network";
33

44
inputs = {
5-
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
5+
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
66
flake-utils.url = "github:numtide/flake-utils";
77
rust-overlay = {
88
url = "github:oxalica/rust-overlay";
@@ -61,22 +61,56 @@ nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
6161
src = hathor-core-src;
6262
};
6363

64-
# CLI binary (no Tauri, no GUI dependencies)
65-
hathorForgeCli = import ./nix/cli.nix {
64+
# Build tx-mining-service from GitHub
65+
txMiningService = import ./nix/tx-mining-service.nix {
66+
inherit pkgs;
67+
src = tx-mining-service-src;
68+
};
69+
70+
# Build wallet-headless from GitHub
71+
walletHeadless = import ./nix/wallet-headless.nix {
72+
inherit pkgs;
73+
src = wallet-headless-src;
74+
};
75+
76+
# CLI binary (Rust, no Tauri)
77+
cliUnwrapped = import ./nix/cli.nix {
6678
inherit pkgs rustToolchain;
6779
};
6880

81+
# Assemble a binaries directory that the CLI can find
82+
binariesDir = pkgs.linkFarm "hathor-forge-binaries" [
83+
{ name = "hathor-core"; path = "${hathorCore}/bin/hathor-core"; }
84+
{ name = "cpuminer"; path = "${cpuminer}/bin/minerd"; }
85+
{ name = "tx-mining-service"; path = "${txMiningService}/bin/tx-mining-service"; }
86+
];
87+
88+
# Wrapped CLI with all service binaries and lazy setup
89+
hathorForgeCli = pkgs.writeShellScriptBin "hathor-forge-cli" ''
90+
export HATHOR_FORGE_BINARIES_DIR="${binariesDir}"
91+
export PATH="${pkgs.nodejs_22}/bin:${pkgs.python312}/bin:$PATH"
92+
93+
# Lazy-setup wallet-headless on first use
94+
HEADLESS_DIR=$(${walletHeadless}/bin/wallet-headless-setup)
95+
export HATHOR_FORGE_HEADLESS_DIR="$HEADLESS_DIR"
96+
97+
exec ${cliUnwrapped}/bin/hathor-forge-cli "$@"
98+
'';
99+
69100
in {
70101
packages = {
71102
default = self.packages.${system}.hathor-forge-cli;
72103
hathor-forge-cli = hathorForgeCli;
104+
hathor-forge-cli-unwrapped = cliUnwrapped;
73105
hathor-core = hathorCore;
74106
cpuminer = cpuminer;
107+
tx-mining-service = txMiningService;
108+
wallet-headless = walletHeadless;
75109

76110
# Combined runtime bundle
77111
runtime = pkgs.symlinkJoin {
78112
name = "hathor-forge-runtime";
79-
paths = [ hathorCore cpuminer ];
113+
paths = [ hathorCore cpuminer txMiningService ];
80114
};
81115

82116
# Placeholder for the full Tauri app (will be built via cargo)
@@ -124,6 +158,10 @@ nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
124158

125159
# Runnable apps
126160
apps = {
161+
default = {
162+
type = "app";
163+
program = "${hathorForgeCli}/bin/hathor-forge-cli";
164+
};
127165
dev = {
128166
type = "app";
129167
program = toString (pkgs.writeShellScript "dev" ''

nix/hathor-core.nix

Lines changed: 30 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,32 @@
11
{ pkgs, src }:
22

3-
let
4-
python = pkgs.python312;
5-
in
6-
pkgs.stdenv.mkDerivation rec {
7-
pname = "hathor-core";
8-
version = "0.69.0";
9-
10-
inherit src;
11-
12-
nativeBuildInputs = with pkgs; [
13-
python
14-
poetry
15-
pkg-config
16-
cmake
17-
];
18-
19-
buildInputs = with pkgs; [
20-
rocksdb
21-
snappy
22-
openssl
23-
readline
24-
zlib
25-
xz
26-
bzip2
27-
lz4
28-
];
29-
30-
# Don't run the normal build phases - we'll use poetry
31-
dontBuild = true;
32-
dontConfigure = true;
33-
34-
installPhase = ''
35-
mkdir -p $out/bin $out/lib/hathor-core
36-
37-
# Copy source
38-
cp -r . $out/lib/hathor-core/
39-
40-
# Create wrapper script that sets up the environment
41-
cat > $out/bin/hathor-cli << EOF
42-
#!/usr/bin/env bash
43-
SCRIPT_DIR="\$(cd "\$(dirname "\''${BASH_SOURCE[0]}")" && pwd)"
44-
HATHOR_DIR="\$SCRIPT_DIR/../lib/hathor-core"
45-
46-
# Set up environment
47-
export CFLAGS="-I${pkgs.rocksdb}/include"
48-
export LDFLAGS="-L${pkgs.rocksdb}/lib"
49-
export LD_LIBRARY_PATH="${pkgs.lib.makeLibraryPath [ pkgs.rocksdb pkgs.openssl pkgs.snappy ]}:\$LD_LIBRARY_PATH"
50-
export DYLD_LIBRARY_PATH="${pkgs.lib.makeLibraryPath [ pkgs.rocksdb pkgs.openssl pkgs.snappy ]}:\$DYLD_LIBRARY_PATH"
51-
52-
# Use poetry to run hathor-cli
53-
cd "\$HATHOR_DIR"
54-
exec ${pkgs.poetry}/bin/poetry run hathor-cli "\$@"
55-
EOF
56-
chmod +x $out/bin/hathor-cli
57-
'';
58-
59-
meta = with pkgs.lib; {
60-
description = "Hathor Network full-node";
61-
homepage = "https://github.com/HathorNetwork/hathor-core";
62-
license = licenses.asl20;
63-
platforms = platforms.unix;
64-
};
65-
}
3+
# hathor-core wrapper that sets up a Python venv on first run.
4+
# The venv is cached in ~/.cache/hathor-forge/hathor-core-venv/
5+
pkgs.writeShellScriptBin "hathor-core" ''
6+
set -euo pipefail
7+
8+
CACHE_DIR="''${XDG_CACHE_HOME:-$HOME/.cache}/hathor-forge"
9+
VENV_DIR="$CACHE_DIR/hathor-core-venv"
10+
STAMP="$VENV_DIR/.installed-0.69.0"
11+
12+
if [ ! -f "$STAMP" ]; then
13+
echo "Setting up hathor-core (first run, may take a minute)..." >&2
14+
rm -rf "$VENV_DIR"
15+
mkdir -p "$CACHE_DIR"
16+
17+
export CFLAGS="-I${pkgs.rocksdb}/include -I${pkgs.snappy}/include"
18+
export LDFLAGS="-L${pkgs.rocksdb}/lib -L${pkgs.snappy}/lib"
19+
export ROCKSDB_INCLUDE_DIR="${pkgs.rocksdb}/include"
20+
export ROCKSDB_LIB_DIR="${pkgs.rocksdb}/lib"
21+
22+
${pkgs.python312}/bin/python3 -m venv "$VENV_DIR"
23+
"$VENV_DIR/bin/pip" install --upgrade pip wheel setuptools >&2
24+
"$VENV_DIR/bin/pip" install "${src}" >&2
25+
26+
touch "$STAMP"
27+
echo "hathor-core ready." >&2
28+
fi
29+
30+
export LD_LIBRARY_PATH="${pkgs.lib.makeLibraryPath [ pkgs.rocksdb pkgs.openssl pkgs.snappy pkgs.zlib ]}''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
31+
exec "$VENV_DIR/bin/hathor-cli" "$@"
32+
''

nix/tx-mining-service.nix

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{ pkgs, src }:
2+
3+
# tx-mining-service wrapper that sets up a Python venv on first run.
4+
# The venv is cached in ~/.cache/hathor-forge/tx-mining-venv/
5+
pkgs.writeShellScriptBin "tx-mining-service" ''
6+
set -euo pipefail
7+
8+
CACHE_DIR="''${XDG_CACHE_HOME:-$HOME/.cache}/hathor-forge"
9+
VENV_DIR="$CACHE_DIR/tx-mining-venv"
10+
STAMP="$VENV_DIR/.installed-0.22.0"
11+
SRC="${src}"
12+
13+
if [ ! -f "$STAMP" ]; then
14+
echo "Setting up tx-mining-service (first run, may take a minute)..." >&2
15+
rm -rf "$VENV_DIR"
16+
mkdir -p "$CACHE_DIR"
17+
18+
${pkgs.python312}/bin/python3 -m venv "$VENV_DIR"
19+
"$VENV_DIR/bin/pip" install --upgrade pip wheel setuptools >&2
20+
21+
# Install deps
22+
"$VENV_DIR/bin/pip" install configargparse colorama aiohttp base58 structlog prometheus-client requests "hathorlib[client]" python-healthchecklib >&2
23+
24+
# Install txstratum from source
25+
TMPDIR=$(mktemp -d)
26+
cp -r "$SRC"/* "$TMPDIR/"
27+
chmod -R u+w "$TMPDIR"
28+
cd "$TMPDIR"
29+
30+
# Make it installable
31+
if [ ! -f setup.py ]; then
32+
cat > setup.py << 'SETUP'
33+
from setuptools import setup, find_packages
34+
setup(
35+
name="tx-mining-service",
36+
version="0.22.0",
37+
packages=find_packages(),
38+
entry_points={"console_scripts": ["tx-mining-service=txstratum.cli:main"]},
39+
)
40+
SETUP
41+
fi
42+
43+
"$VENV_DIR/bin/pip" install . >&2
44+
rm -rf "$TMPDIR"
45+
46+
# Copy log.conf
47+
cp "$SRC/log.conf" "$VENV_DIR/" 2>/dev/null || true
48+
49+
touch "$STAMP"
50+
echo "tx-mining-service ready." >&2
51+
fi
52+
53+
# tx-mining-service looks for log.conf in cwd
54+
cd "$VENV_DIR"
55+
exec "$VENV_DIR/bin/tx-mining-service" "$@"
56+
''

nix/wallet-headless.nix

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{ pkgs, src }:
2+
3+
# wallet-headless wrapper that builds the Node.js app on first run.
4+
# The build is cached in ~/.cache/hathor-forge/wallet-headless/
5+
pkgs.writeShellScriptBin "wallet-headless-setup" ''
6+
set -euo pipefail
7+
8+
CACHE_DIR="''${XDG_CACHE_HOME:-$HOME/.cache}/hathor-forge"
9+
BUILD_DIR="$CACHE_DIR/wallet-headless"
10+
STAMP="$BUILD_DIR/.installed-0.36.1"
11+
SRC="${src}"
12+
13+
if [ ! -f "$STAMP" ]; then
14+
echo "Setting up wallet-headless (first run, may take a minute)..." >&2
15+
rm -rf "$BUILD_DIR"
16+
mkdir -p "$BUILD_DIR"
17+
18+
cp -r "$SRC"/* "$BUILD_DIR/"
19+
chmod -R u+w "$BUILD_DIR"
20+
cd "$BUILD_DIR"
21+
22+
# Remove patch-package from postinstall
23+
${pkgs.gnused}/bin/sed -i 's/"postinstall": "patch-package"/"postinstall": "echo skipping patches"/' package.json || true
24+
${pkgs.gnused}/bin/sed -i 's/"postinstall": "npx patch-package"/"postinstall": "echo skipping patches"/' package.json || true
25+
26+
# Force CommonJS output for Node 22 compat
27+
cat > babel.config.json << 'EOF'
28+
{
29+
"presets": [["@babel/preset-env", {"targets": {"node": "18"}, "modules": "commonjs"}]],
30+
"plugins": ["@babel/plugin-proposal-class-properties"]
31+
}
32+
EOF
33+
34+
${pkgs.nodejs_22}/bin/npm install --ignore-scripts >&2
35+
${pkgs.nodejs_22}/bin/npm install >&2
36+
${pkgs.nodejs_22}/bin/npm run build >&2
37+
38+
touch "$STAMP"
39+
echo "wallet-headless ready." >&2
40+
fi
41+
42+
echo "$BUILD_DIR"
43+
''

0 commit comments

Comments
 (0)