@lightninglabs/lightning-mcp-server 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/.claude-plugin/marketplace.json +36 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/README.md +307 -0
  4. package/bin/lightning-mcp-server +15 -0
  5. package/docs/architecture.md +455 -0
  6. package/docs/commerce.md +357 -0
  7. package/docs/l402-and-lnget.md +267 -0
  8. package/docs/mcp-server.md +285 -0
  9. package/docs/quickref.md +263 -0
  10. package/docs/security.md +298 -0
  11. package/docs/two-agent-setup.md +394 -0
  12. package/package.json +52 -0
  13. package/postinstall.js +160 -0
  14. package/skills/aperture/SKILL.md +330 -0
  15. package/skills/aperture/scripts/install.sh +68 -0
  16. package/skills/aperture/scripts/setup.sh +155 -0
  17. package/skills/aperture/scripts/start.sh +81 -0
  18. package/skills/aperture/scripts/stop.sh +57 -0
  19. package/skills/aperture/templates/aperture-regtest.yaml +36 -0
  20. package/skills/aperture/templates/aperture.yaml.template +64 -0
  21. package/skills/aperture/templates/docker-compose-aperture.yml +59 -0
  22. package/skills/commerce/SKILL.md +211 -0
  23. package/skills/lib/config-gen.sh +127 -0
  24. package/skills/lib/rest.sh +69 -0
  25. package/skills/lightning-security-module/SKILL.md +253 -0
  26. package/skills/lightning-security-module/references/architecture.md +133 -0
  27. package/skills/lightning-security-module/scripts/docker-start.sh +117 -0
  28. package/skills/lightning-security-module/scripts/docker-stop.sh +53 -0
  29. package/skills/lightning-security-module/scripts/export-credentials.sh +268 -0
  30. package/skills/lightning-security-module/scripts/install.sh +178 -0
  31. package/skills/lightning-security-module/scripts/setup-signer.sh +307 -0
  32. package/skills/lightning-security-module/scripts/start-signer.sh +152 -0
  33. package/skills/lightning-security-module/scripts/stop-signer.sh +240 -0
  34. package/skills/lightning-security-module/templates/docker-compose-signer.yml +35 -0
  35. package/skills/lightning-security-module/templates/signer-lnd.conf.template +69 -0
  36. package/skills/lnd/SKILL.md +441 -0
  37. package/skills/lnd/profiles/debug.env +4 -0
  38. package/skills/lnd/profiles/default.env +3 -0
  39. package/skills/lnd/profiles/regtest.env +4 -0
  40. package/skills/lnd/profiles/taproot.env +3 -0
  41. package/skills/lnd/profiles/wumbo.env +3 -0
  42. package/skills/lnd/references/security.md +156 -0
  43. package/skills/lnd/scripts/create-wallet.sh +464 -0
  44. package/skills/lnd/scripts/docker-start.sh +256 -0
  45. package/skills/lnd/scripts/docker-stop.sh +109 -0
  46. package/skills/lnd/scripts/import-credentials.sh +145 -0
  47. package/skills/lnd/scripts/install.sh +195 -0
  48. package/skills/lnd/scripts/lncli.sh +150 -0
  49. package/skills/lnd/scripts/start-lnd.sh +241 -0
  50. package/skills/lnd/scripts/stop-lnd.sh +218 -0
  51. package/skills/lnd/scripts/unlock-wallet.sh +134 -0
  52. package/skills/lnd/templates/docker-compose-regtest.yml +122 -0
  53. package/skills/lnd/templates/docker-compose-watchonly.yml +71 -0
  54. package/skills/lnd/templates/docker-compose.yml +49 -0
  55. package/skills/lnd/templates/litd-regtest.conf.template +61 -0
  56. package/skills/lnd/templates/litd-watchonly.conf.template +57 -0
  57. package/skills/lnd/templates/litd.conf.template +88 -0
  58. package/skills/lnd/templates/lnd.conf.template +91 -0
  59. package/skills/lnget/SKILL.md +288 -0
  60. package/skills/lnget/scripts/install.sh +69 -0
  61. package/skills/macaroon-bakery/SKILL.md +179 -0
  62. package/skills/macaroon-bakery/scripts/bake.sh +337 -0
  63. package/skills/mcp-lnc/SKILL.md +280 -0
  64. package/skills/mcp-lnc/scripts/configure.sh +130 -0
  65. package/skills/mcp-lnc/scripts/install.sh +103 -0
  66. package/skills/mcp-lnc/scripts/setup-claude-config.sh +162 -0
  67. package/skills/mcp-lnc/templates/env.template +16 -0
  68. package/versions.env +23 -0
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env bash
2
+ # Wrapper for lncli (and other litd CLIs) with container auto-detection.
3
+ #
4
+ # Auto-detects a running litd container and routes commands through it.
5
+ # Falls back to local lncli if no container is found.
6
+ #
7
+ # Usage:
8
+ # lncli.sh getinfo # Auto-detect container
9
+ # lncli.sh walletbalance
10
+ # lncli.sh --container litd getinfo # Explicit container
11
+ # lncli.sh --cli loop quote out 100000 # Use loop CLI
12
+ # lncli.sh --cli tapcli assets list # Use tapcli
13
+ # lncli.sh --cli litcli getinfo # Use litcli
14
+ # lncli.sh --network testnet getinfo # Override network
15
+ # lncli.sh --rpcserver remote:10009 \ # Remote node
16
+ # --tlscertpath ~/tls.cert \
17
+ # --macaroonpath ~/admin.macaroon getinfo
18
+
19
+ set -e
20
+
21
+ LND_DIR="${LND_DIR:-}"
22
+ NETWORK="${NETWORK:-testnet}"
23
+ CONTAINER=""
24
+ CLI="lncli"
25
+ RPCSERVER=""
26
+ TLSCERTPATH=""
27
+ MACAROONPATH=""
28
+ LNCLI_ARGS=()
29
+
30
+ # Parse our arguments (pass everything else to the CLI).
31
+ while [[ $# -gt 0 ]]; do
32
+ case $1 in
33
+ --network)
34
+ NETWORK="$2"
35
+ shift 2
36
+ ;;
37
+ --lnddir)
38
+ LND_DIR="$2"
39
+ shift 2
40
+ ;;
41
+ --container)
42
+ CONTAINER="$2"
43
+ shift 2
44
+ ;;
45
+ --cli)
46
+ CLI="$2"
47
+ shift 2
48
+ ;;
49
+ --rpcserver)
50
+ RPCSERVER="$2"
51
+ shift 2
52
+ ;;
53
+ --tlscertpath)
54
+ TLSCERTPATH="$2"
55
+ shift 2
56
+ ;;
57
+ --macaroonpath)
58
+ MACAROONPATH="$2"
59
+ shift 2
60
+ ;;
61
+ -h|--help)
62
+ echo "Usage: lncli.sh [options] <command> [args]"
63
+ echo ""
64
+ echo "Wrapper for lncli with container auto-detection."
65
+ echo ""
66
+ echo "Options:"
67
+ echo " --network NETWORK Bitcoin network (default: testnet)"
68
+ echo " --lnddir DIR lnd data directory (default: ~/.lnd)"
69
+ echo " --container NAME Run CLI inside a specific Docker container"
70
+ echo " --cli CLI CLI to use (default: lncli)"
71
+ echo " Available: lncli, litcli, loop, pool, tapcli, frcli"
72
+ echo " --rpcserver HOST:PORT Connect to a remote lnd node"
73
+ echo " --tlscertpath PATH TLS certificate for remote connection"
74
+ echo " --macaroonpath PATH Macaroon for remote authentication"
75
+ echo ""
76
+ echo "Container auto-detection order:"
77
+ echo " litd > litd-shared > lnd > lnd-shared"
78
+ echo ""
79
+ echo "All other arguments are passed directly to the CLI."
80
+ exit 0
81
+ ;;
82
+ *)
83
+ LNCLI_ARGS+=("$1")
84
+ shift
85
+ ;;
86
+ esac
87
+ done
88
+
89
+ if [ ${#LNCLI_ARGS[@]} -eq 0 ]; then
90
+ echo "Error: No command specified." >&2
91
+ echo "Usage: lncli.sh <command> [args]" >&2
92
+ exit 1
93
+ fi
94
+
95
+ # Auto-detect container if not explicitly specified.
96
+ if [ -z "$CONTAINER" ] && [ -z "$RPCSERVER" ] && command -v docker &>/dev/null; then
97
+ for candidate in litd litd-shared lnd lnd-shared; do
98
+ if docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "$candidate"; then
99
+ CONTAINER="$candidate"
100
+ break
101
+ fi
102
+ done
103
+ fi
104
+
105
+ # Apply default lnddir if not set.
106
+ if [ -z "$LND_DIR" ]; then
107
+ if [ -n "$CONTAINER" ]; then
108
+ LND_DIR="/root/.lnd"
109
+ else
110
+ LND_DIR="$HOME/.lnd"
111
+ fi
112
+ fi
113
+
114
+ # Build connection flags (only for lncli, not other CLIs).
115
+ CONN_FLAGS=()
116
+ if [ "$CLI" = "lncli" ]; then
117
+ CONN_FLAGS+=("--network=$NETWORK" "--lnddir=$LND_DIR")
118
+ if [ -n "$RPCSERVER" ]; then
119
+ CONN_FLAGS+=("--rpcserver=$RPCSERVER")
120
+ fi
121
+ if [ -n "$TLSCERTPATH" ]; then
122
+ CONN_FLAGS+=("--tlscertpath=$TLSCERTPATH")
123
+ fi
124
+ if [ -n "$MACAROONPATH" ]; then
125
+ CONN_FLAGS+=("--macaroonpath=$MACAROONPATH")
126
+ fi
127
+ fi
128
+
129
+ # Execute the command.
130
+ if [ -n "$CONTAINER" ]; then
131
+ # Container mode: run CLI inside the container.
132
+ if ! docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "$CONTAINER"; then
133
+ echo "Error: Container '$CONTAINER' is not running." >&2
134
+ echo "Start it with: skills/lnd/scripts/docker-start.sh" >&2
135
+ exit 1
136
+ fi
137
+
138
+ exec docker exec "$CONTAINER" "$CLI" "${CONN_FLAGS[@]}" "${LNCLI_ARGS[@]}"
139
+ else
140
+ # Local mode: run CLI on the host.
141
+ if ! command -v "$CLI" &>/dev/null; then
142
+ echo "Error: $CLI not found locally and no litd container detected." >&2
143
+ echo "" >&2
144
+ echo "Either:" >&2
145
+ echo " 1. Start a litd container: skills/lnd/scripts/docker-start.sh" >&2
146
+ echo " 2. Install from source: skills/lnd/scripts/install.sh --source" >&2
147
+ exit 1
148
+ fi
149
+ exec "$CLI" "${CONN_FLAGS[@]}" "${LNCLI_ARGS[@]}"
150
+ fi
@@ -0,0 +1,241 @@
1
+ #!/usr/bin/env bash
2
+ # Start litd (Lightning Terminal) — delegates to Docker by default.
3
+ #
4
+ # Usage:
5
+ # start-lnd.sh # Docker (default)
6
+ # start-lnd.sh --watchonly # Watch-only + signer
7
+ # start-lnd.sh --regtest # Regtest with bitcoind
8
+ # start-lnd.sh --network mainnet # Override network
9
+ # start-lnd.sh --profile taproot # Load profile
10
+ # start-lnd.sh --native # Native lnd (no Docker)
11
+ # start-lnd.sh --native --mode standalone # Native standalone
12
+ # start-lnd.sh --native --signer-host 10.0.0.5:10012 # Native watch-only
13
+ #
14
+ # By default, this script delegates to docker-start.sh. Use --native to
15
+ # run lnd as a local process (requires lnd built from source).
16
+
17
+ set -e
18
+
19
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
20
+ NATIVE=false
21
+
22
+ # Check for --native flag before parsing other args.
23
+ PASS_ARGS=()
24
+ for arg in "$@"; do
25
+ if [ "$arg" = "--native" ]; then
26
+ NATIVE=true
27
+ else
28
+ PASS_ARGS+=("$arg")
29
+ fi
30
+ done
31
+
32
+ # If not native mode, delegate to docker-start.sh.
33
+ if [ "$NATIVE" = false ]; then
34
+ if command -v docker &>/dev/null; then
35
+ exec "$SCRIPT_DIR/docker-start.sh" "${PASS_ARGS[@]}"
36
+ else
37
+ echo "Docker not available. Falling back to native mode." >&2
38
+ echo "Install Docker or use --native explicitly." >&2
39
+ echo ""
40
+ NATIVE=true
41
+ fi
42
+ fi
43
+
44
+ # --- Native mode: original lnd startup logic ---
45
+
46
+ LNGET_LND_DIR="${LNGET_LND_DIR:-$HOME/.lnget/lnd}"
47
+ LND_DIR="${LND_DIR:-$HOME/.lnd}"
48
+ NETWORK="testnet"
49
+ FOREGROUND=false
50
+ EXTRA_ARGS=""
51
+ CONF_FILE="$LNGET_LND_DIR/lnd.conf"
52
+ MODE="watchonly"
53
+ SIGNER_HOST="${LND_SIGNER_HOST:-}"
54
+
55
+ # Parse arguments.
56
+ set -- "${PASS_ARGS[@]}"
57
+ while [[ $# -gt 0 ]]; do
58
+ case $1 in
59
+ --mode)
60
+ MODE="$2"
61
+ shift 2
62
+ ;;
63
+ --signer-host)
64
+ SIGNER_HOST="$2"
65
+ shift 2
66
+ ;;
67
+ --network)
68
+ NETWORK="$2"
69
+ shift 2
70
+ ;;
71
+ --lnddir)
72
+ LND_DIR="$2"
73
+ shift 2
74
+ ;;
75
+ --foreground)
76
+ FOREGROUND=true
77
+ shift
78
+ ;;
79
+ --extra-args)
80
+ EXTRA_ARGS="$2"
81
+ shift 2
82
+ ;;
83
+ -h|--help)
84
+ echo "Usage: start-lnd.sh [options]"
85
+ echo ""
86
+ echo "Start lnd natively (without Docker)."
87
+ echo ""
88
+ echo "Options:"
89
+ echo " --native Run lnd as a local process (required)"
90
+ echo " --mode MODE Node mode: watchonly (default) or standalone"
91
+ echo " --signer-host HOST Signer RPC address (e.g., 10.0.0.5:10012)"
92
+ echo " --network NETWORK Bitcoin network (default: testnet)"
93
+ echo " --lnddir DIR lnd data directory (default: ~/.lnd)"
94
+ echo " --foreground Run in foreground (default: background)"
95
+ echo " --extra-args ARGS Additional lnd arguments"
96
+ echo ""
97
+ echo "Modes:"
98
+ echo " watchonly Connect to remote signer (no keys on this machine)"
99
+ echo " standalone Full lnd with local keys (for testing)"
100
+ echo ""
101
+ echo "Environment:"
102
+ echo " LND_SIGNER_HOST Default signer host (overridden by --signer-host)"
103
+ exit 0
104
+ ;;
105
+ *)
106
+ echo "Unknown option: $1" >&2
107
+ exit 1
108
+ ;;
109
+ esac
110
+ done
111
+
112
+ # Validate mode.
113
+ if [ "$MODE" != "watchonly" ] && [ "$MODE" != "standalone" ]; then
114
+ echo "Error: Invalid mode '$MODE'. Use 'watchonly' or 'standalone'." >&2
115
+ exit 1
116
+ fi
117
+
118
+ # Verify lnd is installed.
119
+ if ! command -v lnd &>/dev/null; then
120
+ echo "Error: lnd not found. Run install.sh --source first." >&2
121
+ exit 1
122
+ fi
123
+
124
+ # Check if lnd is already running.
125
+ if pgrep -x lnd &>/dev/null; then
126
+ echo "lnd is already running (PID: $(pgrep -x lnd))."
127
+ echo "Use stop-lnd.sh to stop it first."
128
+ exit 1
129
+ fi
130
+
131
+ # Watch-only mode requires signer host.
132
+ if [ "$MODE" = "watchonly" ]; then
133
+ if [ -z "$SIGNER_HOST" ]; then
134
+ echo "Error: --signer-host is required in watchonly mode." >&2
135
+ echo "Example: start-lnd.sh --native --signer-host 10.0.0.5:10012" >&2
136
+ echo "Or set LND_SIGNER_HOST environment variable." >&2
137
+ exit 1
138
+ fi
139
+
140
+ CREDS_DIR="$LNGET_LND_DIR/signer-credentials"
141
+ if [ ! -f "$CREDS_DIR/tls.cert" ] || [ ! -f "$CREDS_DIR/admin.macaroon" ]; then
142
+ echo "Error: Signer credentials not found at $CREDS_DIR" >&2
143
+ echo "Run import-credentials.sh first." >&2
144
+ exit 1
145
+ fi
146
+ fi
147
+
148
+ # Create config directory if needed.
149
+ mkdir -p "$LNGET_LND_DIR"
150
+
151
+ # Copy config template if no config exists.
152
+ if [ ! -f "$CONF_FILE" ]; then
153
+ TEMPLATE="$SCRIPT_DIR/../templates/lnd.conf.template"
154
+ if [ -f "$TEMPLATE" ]; then
155
+ echo "Creating config from template..."
156
+ # Replace network placeholder in template.
157
+ sed "s/bitcoin\.mainnet=true/bitcoin.$NETWORK=true/g" "$TEMPLATE" > "$CONF_FILE"
158
+
159
+ # Replace password file path.
160
+ sed -i.bak "s|wallet-unlock-password-file=.*|wallet-unlock-password-file=$LNGET_LND_DIR/wallet-password.txt|g" "$CONF_FILE"
161
+ rm -f "$CONF_FILE.bak"
162
+ else
163
+ echo "Warning: No config template found. lnd will use defaults." >&2
164
+ fi
165
+ fi
166
+
167
+ # Configure remote signer in config if watchonly mode.
168
+ if [ "$MODE" = "watchonly" ] && [ -f "$CONF_FILE" ]; then
169
+ CREDS_DIR="$LNGET_LND_DIR/signer-credentials"
170
+
171
+ # Remove any existing remotesigner lines.
172
+ sed -i.bak '/^\# \[remotesigner\]/,/^\# remotesigner\./d' "$CONF_FILE"
173
+ rm -f "$CONF_FILE.bak"
174
+
175
+ # Append active remotesigner configuration.
176
+ cat >> "$CONF_FILE" <<EOF
177
+
178
+ [remotesigner]
179
+ remotesigner.enable=true
180
+ remotesigner.rpchost=$SIGNER_HOST
181
+ remotesigner.tlscertpath=$CREDS_DIR/tls.cert
182
+ remotesigner.macaroonpath=$CREDS_DIR/admin.macaroon
183
+ EOF
184
+
185
+ echo "Remote signer configured: $SIGNER_HOST"
186
+ fi
187
+
188
+ echo "=== Starting lnd (native) ==="
189
+ echo "Mode: $MODE"
190
+ echo "Network: $NETWORK"
191
+ echo "Data dir: $LND_DIR"
192
+ echo "Config: $CONF_FILE"
193
+ if [ "$MODE" = "watchonly" ]; then
194
+ echo "Signer: $SIGNER_HOST"
195
+ fi
196
+ echo ""
197
+
198
+ if [ "$MODE" = "standalone" ]; then
199
+ echo "WARNING: Running in standalone mode. Private keys are on this machine."
200
+ echo "For production use, set up a remote signer with the lightning-security-module skill."
201
+ echo ""
202
+ fi
203
+
204
+ LOG_FILE="$LNGET_LND_DIR/lnd-start.log"
205
+
206
+ if [ "$FOREGROUND" = true ]; then
207
+ exec lnd \
208
+ --lnddir="$LND_DIR" \
209
+ --configfile="$CONF_FILE" \
210
+ $EXTRA_ARGS
211
+ else
212
+ nohup lnd \
213
+ --lnddir="$LND_DIR" \
214
+ --configfile="$CONF_FILE" \
215
+ $EXTRA_ARGS \
216
+ > "$LOG_FILE" 2>&1 &
217
+ LND_PID=$!
218
+ echo "lnd started in background (PID: $LND_PID)"
219
+ echo "Log file: $LOG_FILE"
220
+ echo ""
221
+
222
+ # Wait briefly and verify it's running.
223
+ sleep 2
224
+ if kill -0 "$LND_PID" 2>/dev/null; then
225
+ echo "lnd is running."
226
+ else
227
+ echo "Error: lnd exited immediately. Check $LOG_FILE" >&2
228
+ tail -20 "$LOG_FILE" 2>/dev/null
229
+ exit 1
230
+ fi
231
+
232
+ echo ""
233
+ echo "Next steps:"
234
+ echo " # Check status"
235
+ echo " skills/lnd/scripts/lncli.sh getinfo"
236
+ echo ""
237
+ if [ "$MODE" = "standalone" ]; then
238
+ echo " # If wallet not yet created"
239
+ echo " skills/lnd/scripts/create-wallet.sh --mode standalone"
240
+ fi
241
+ fi
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env bash
2
+ # Stop litd / lnd — delegates to Docker by default.
3
+ #
4
+ # Usage:
5
+ # stop-lnd.sh # Docker stop (auto-detect)
6
+ # stop-lnd.sh --clean # Docker stop + remove volumes
7
+ # stop-lnd.sh --watchonly # Docker stop watch-only mode
8
+ # stop-lnd.sh --native # Stop native lnd process
9
+ # stop-lnd.sh --native --force # SIGTERM native process
10
+ # stop-lnd.sh --container sam # Stop specific container
11
+ # stop-lnd.sh --rpcserver remote:10009 --tlscertpath ~/tls.cert --macaroonpath ~/admin.macaroon
12
+ #
13
+ # By default, this script delegates to docker-stop.sh. Use --native for
14
+ # stopping a local lnd process.
15
+
16
+ set -e
17
+
18
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19
+ NATIVE=false
20
+
21
+ # Check for --native flag before parsing other args.
22
+ PASS_ARGS=()
23
+ for arg in "$@"; do
24
+ if [ "$arg" = "--native" ]; then
25
+ NATIVE=true
26
+ else
27
+ PASS_ARGS+=("$arg")
28
+ fi
29
+ done
30
+
31
+ # If not native mode, delegate to docker-stop.sh.
32
+ if [ "$NATIVE" = false ]; then
33
+ # Check if we have Docker-specific args or a running container.
34
+ HAS_CONTAINER_ARG=false
35
+ for arg in "${PASS_ARGS[@]}"; do
36
+ if [ "$arg" = "--container" ]; then
37
+ HAS_CONTAINER_ARG=true
38
+ break
39
+ fi
40
+ done
41
+
42
+ # If --container is specified, use the old container-specific stop logic.
43
+ if [ "$HAS_CONTAINER_ARG" = true ]; then
44
+ NATIVE=true
45
+ elif command -v docker &>/dev/null; then
46
+ # Check if any litd containers are running.
47
+ if docker ps --format '{{.Names}}' 2>/dev/null | grep -qE '^litd'; then
48
+ exec "$SCRIPT_DIR/docker-stop.sh" "${PASS_ARGS[@]}"
49
+ fi
50
+ # No litd containers found, fall through to native.
51
+ NATIVE=true
52
+ else
53
+ NATIVE=true
54
+ fi
55
+ fi
56
+
57
+ # --- Native / container-specific stop logic ---
58
+
59
+ LND_DIR="${LND_DIR:-}"
60
+ NETWORK="${NETWORK:-testnet}"
61
+ FORCE=false
62
+ CONTAINER=""
63
+ RPCSERVER=""
64
+ TLSCERTPATH=""
65
+ MACAROONPATH=""
66
+
67
+ # Parse arguments.
68
+ set -- "${PASS_ARGS[@]}"
69
+ while [[ $# -gt 0 ]]; do
70
+ case $1 in
71
+ --force)
72
+ FORCE=true
73
+ shift
74
+ ;;
75
+ --network)
76
+ NETWORK="$2"
77
+ shift 2
78
+ ;;
79
+ --container)
80
+ CONTAINER="$2"
81
+ shift 2
82
+ ;;
83
+ --rpcserver)
84
+ RPCSERVER="$2"
85
+ shift 2
86
+ ;;
87
+ --tlscertpath)
88
+ TLSCERTPATH="$2"
89
+ shift 2
90
+ ;;
91
+ --macaroonpath)
92
+ MACAROONPATH="$2"
93
+ shift 2
94
+ ;;
95
+ --clean|-v|--watchonly|--regtest|--all)
96
+ # These are docker-stop.sh flags; pass through.
97
+ echo "Forwarding to docker-stop.sh (flag: $1)..."
98
+ exec "$SCRIPT_DIR/docker-stop.sh" "${PASS_ARGS[@]}"
99
+ ;;
100
+ -h|--help)
101
+ echo "Usage: stop-lnd.sh [options]"
102
+ echo ""
103
+ echo "Stop litd / lnd."
104
+ echo ""
105
+ echo "Docker options (default):"
106
+ echo " --clean, -v Remove volumes (clean state)"
107
+ echo " --watchonly Stop watch-only + signer containers"
108
+ echo " --regtest Stop regtest containers"
109
+ echo " --all Stop all litd containers"
110
+ echo ""
111
+ echo "Native options (--native):"
112
+ echo " --native Stop native lnd process"
113
+ echo " --force Send SIGTERM immediately"
114
+ echo " --container NAME Stop lnd in a specific container"
115
+ echo " --rpcserver HOST:PORT Remote lnd node"
116
+ echo " --tlscertpath PATH TLS certificate for remote"
117
+ echo " --macaroonpath PATH Macaroon for remote"
118
+ exit 0
119
+ ;;
120
+ *)
121
+ echo "Unknown option: $1" >&2
122
+ exit 1
123
+ ;;
124
+ esac
125
+ done
126
+
127
+ # Apply default lnddir if not set.
128
+ if [ -z "$LND_DIR" ]; then
129
+ if [ -n "$CONTAINER" ]; then
130
+ LND_DIR="/root/.lnd"
131
+ else
132
+ LND_DIR="$HOME/.lnd"
133
+ fi
134
+ fi
135
+
136
+ if [ -n "$CONTAINER" ]; then
137
+ # Docker container mode.
138
+ if ! docker ps --format '{{.Names}}' | grep -qx "$CONTAINER"; then
139
+ echo "Container '$CONTAINER' is not running."
140
+ exit 0
141
+ fi
142
+
143
+ echo "Stopping lnd in container '$CONTAINER'..."
144
+
145
+ if [ "$FORCE" = true ]; then
146
+ docker stop "$CONTAINER"
147
+ echo "Container stopped."
148
+ else
149
+ if docker exec "$CONTAINER" lncli --network="$NETWORK" --lnddir="$LND_DIR" stop 2>/dev/null; then
150
+ echo "Graceful shutdown initiated."
151
+ else
152
+ echo "lncli stop failed, stopping container..."
153
+ docker stop "$CONTAINER"
154
+ echo "Container stopped."
155
+ fi
156
+ fi
157
+ exit 0
158
+ fi
159
+
160
+ # Build connection flags for lncli.
161
+ CONN_FLAGS=(--network="$NETWORK" --lnddir="$LND_DIR")
162
+ if [ -n "$RPCSERVER" ]; then
163
+ CONN_FLAGS+=("--rpcserver=$RPCSERVER")
164
+ fi
165
+ if [ -n "$TLSCERTPATH" ]; then
166
+ CONN_FLAGS+=("--tlscertpath=$TLSCERTPATH")
167
+ fi
168
+ if [ -n "$MACAROONPATH" ]; then
169
+ CONN_FLAGS+=("--macaroonpath=$MACAROONPATH")
170
+ fi
171
+
172
+ # Remote mode — stop via lncli only (no PID access).
173
+ if [ -n "$RPCSERVER" ]; then
174
+ echo "Stopping remote lnd at $RPCSERVER..."
175
+ if lncli "${CONN_FLAGS[@]}" stop; then
176
+ echo "Graceful shutdown initiated."
177
+ else
178
+ echo "Error: lncli stop failed for remote node." >&2
179
+ exit 1
180
+ fi
181
+ exit 0
182
+ fi
183
+
184
+ # Local mode — check if lnd is running.
185
+ LND_PID=$(pgrep -x lnd 2>/dev/null || true)
186
+ if [ -z "$LND_PID" ]; then
187
+ echo "lnd is not running."
188
+ exit 0
189
+ fi
190
+
191
+ echo "Stopping lnd (PID: $LND_PID)..."
192
+
193
+ if [ "$FORCE" = true ]; then
194
+ kill "$LND_PID"
195
+ echo "Sent SIGTERM."
196
+ else
197
+ # Try graceful shutdown via lncli.
198
+ if lncli "${CONN_FLAGS[@]}" stop 2>/dev/null; then
199
+ echo "Graceful shutdown initiated."
200
+ else
201
+ echo "lncli stop failed, sending SIGTERM..."
202
+ kill "$LND_PID"
203
+ fi
204
+ fi
205
+
206
+ # Wait for process to exit.
207
+ echo "Waiting for lnd to exit..."
208
+ for i in {1..15}; do
209
+ if ! kill -0 "$LND_PID" 2>/dev/null; then
210
+ echo "lnd stopped."
211
+ exit 0
212
+ fi
213
+ sleep 1
214
+ done
215
+
216
+ echo "Warning: lnd did not exit within 15 seconds." >&2
217
+ echo "Use --force or kill -9 $LND_PID" >&2
218
+ exit 1