- scripts/bitcoin-ln-node/setup.sh: one-shot installer for Bitcoin Core (pruned mainnet), LND, and LNbits on Apple Silicon Mac. Generates secrets, writes configs, installs launchd plists for auto-start. - scripts/bitcoin-ln-node/start.sh: start all services via launchctl; waits for RPC readiness and auto-unlocks LND wallet. - scripts/bitcoin-ln-node/stop.sh: graceful shutdown (lncli stop → bitcoin-cli stop). - scripts/bitcoin-ln-node/status.sh: full health check (Bitcoin sync %, LND channels/balance, LNbits HTTP, bore tunnel). Supports --json mode for machine consumption. - scripts/bitcoin-ln-node/expose.sh: opens bore tunnel from LNbits port 5000 to bore.pub for Replit access. - scripts/bitcoin-ln-node/get-lnbits-key.sh: fetches LNbits admin API key and prints Replit secret values. - artifacts/api-server/src/routes/node-diagnostics.ts: GET /api/admin/node-status (JSON) and /api/admin/node-status/html — Timmy self-diagnoses its LNbits/LND connectivity and reports issues.
107 lines
4.3 KiB
Bash
Executable File
107 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# Timmy node — fetch LNbits admin API key
|
|
# Run this after LNbits is up and has been configured.
|
|
# Prints the LNBITS_API_KEY to add to Replit secrets.
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
|
|
LNBITS_LOCAL="http://127.0.0.1:5000"
|
|
LNBITS_DATA_DIR="$HOME/.lnbits-data"
|
|
|
|
GREEN='\033[0;32m'; CYAN='\033[0;36m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; NC='\033[0m'
|
|
info() { echo -e "${CYAN}[keys]${NC} $*"; }
|
|
ok() { echo -e "${GREEN}[ok]${NC} $*"; }
|
|
warn() { echo -e "${YELLOW}[warn]${NC} $*"; }
|
|
die() { echo -e "${RED}[error]${NC} $*" >&2; exit 1; }
|
|
|
|
# Check LNbits is up
|
|
curl -sf "$LNBITS_LOCAL/api/v1/health" &>/dev/null \
|
|
|| die "LNbits not reachable at $LNBITS_LOCAL. Run 'bash start.sh' first."
|
|
|
|
# ─── Try to get super user from env file ─────────────────────────────────────
|
|
SUPER_USER=""
|
|
if [[ -f "$LNBITS_DATA_DIR/.env" ]]; then
|
|
SUPER_USER=$(grep LNBITS_SUPER_USER "$LNBITS_DATA_DIR/.env" | cut -d= -f2 | tr -d '"' || true)
|
|
fi
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
SECRETS_FILE="$SCRIPT_DIR/.node-secrets"
|
|
[[ -f "$SECRETS_FILE" ]] && source "$SECRETS_FILE"
|
|
SUPER_USER="${SUPER_USER:-${LNBITS_SUPER_USER:-}}"
|
|
|
|
if [[ -z "$SUPER_USER" ]]; then
|
|
# LNbits auto-generates a superuser on first run — find it in the SQLite DB
|
|
DB_FILE=$(find "$LNBITS_DATA_DIR" -name "*.sqlite3" 2>/dev/null | head -1 || true)
|
|
if [[ -n "$DB_FILE" ]] && command -v sqlite3 &>/dev/null; then
|
|
SUPER_USER=$(sqlite3 "$DB_FILE" "SELECT id FROM accounts WHERE is_super_user=1 LIMIT 1;" 2>/dev/null || true)
|
|
fi
|
|
fi
|
|
|
|
if [[ -z "$SUPER_USER" ]]; then
|
|
# Last resort: check LNbits log for the first-run superuser line
|
|
LOG_FILE="$HOME/Library/Logs/timmy-node/lnbits.log"
|
|
if [[ -f "$LOG_FILE" ]]; then
|
|
SUPER_USER=$(grep -oE "super user id: [a-f0-9]+" "$LOG_FILE" | tail -1 | awk '{print $4}' || true)
|
|
fi
|
|
fi
|
|
|
|
if [[ -z "$SUPER_USER" ]]; then
|
|
warn "Could not auto-detect LNbits super user ID."
|
|
echo ""
|
|
echo " Visit: $LNBITS_LOCAL"
|
|
echo " 1. Create a wallet"
|
|
echo " 2. Go to Wallet → API Info"
|
|
echo " 3. Copy the Admin key"
|
|
echo ""
|
|
echo " Then add to Replit:"
|
|
echo " LNBITS_URL = http://bore.pub:<PORT>"
|
|
echo " LNBITS_API_KEY = <admin-key>"
|
|
exit 0
|
|
fi
|
|
|
|
info "Super user: $SUPER_USER"
|
|
|
|
# Create a wallet for Timmy via superuser API
|
|
WALLET_RESPONSE=$(curl -sf -X POST "$LNBITS_LOCAL/api/v1/wallet" \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-Api-Key: $SUPER_USER" \
|
|
-d '{"name":"Timmy"}' 2>/dev/null || true)
|
|
|
|
if [[ -n "$WALLET_RESPONSE" ]]; then
|
|
ADMIN_KEY=$(echo "$WALLET_RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('adminkey',''))" 2>/dev/null || true)
|
|
INKEY=$(echo "$WALLET_RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('inkey',''))" 2>/dev/null || true)
|
|
WALLET_ID=$(echo "$WALLET_RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('id',''))" 2>/dev/null || true)
|
|
|
|
if [[ -n "$ADMIN_KEY" ]]; then
|
|
ok "Timmy wallet created (ID: $WALLET_ID)"
|
|
echo ""
|
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo -e "${GREEN} Add these to Replit secrets:${NC}"
|
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo ""
|
|
echo " LNBITS_URL = http://bore.pub:<PORT> ← from expose.sh"
|
|
echo " LNBITS_API_KEY = $ADMIN_KEY"
|
|
echo ""
|
|
echo " Invoice key (read-only): $INKEY"
|
|
echo ""
|
|
# Save to secrets file
|
|
cat >> "$SECRETS_FILE" <<EOF
|
|
LNBITS_WALLET_ID="$WALLET_ID"
|
|
LNBITS_ADMIN_KEY="$ADMIN_KEY"
|
|
LNBITS_INVOICE_KEY="$INKEY"
|
|
EOF
|
|
ok "Keys saved to $SECRETS_FILE"
|
|
return 0 2>/dev/null || true
|
|
fi
|
|
fi
|
|
|
|
# Fallback: just print the wallet URL
|
|
warn "Could not create wallet automatically."
|
|
echo ""
|
|
echo " Visit $LNBITS_LOCAL in your browser:"
|
|
echo " 1. Create an account / wallet named 'Timmy'"
|
|
echo " 2. Wallet → API Info → copy Admin key"
|
|
echo " 3. Add to Replit: LNBITS_API_KEY = <admin key>"
|
|
echo ""
|