Skip to content

Commit 0ca711f

Browse files
committed
pay lightning script
1 parent d520f0b commit 0ca711f

1 file changed

Lines changed: 130 additions & 0 deletions

File tree

scripts/pay-lightning-address.sh

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#!/bin/bash
2+
#
3+
# Pay a Lightning invoice via Blocktank staging regtest API
4+
#
5+
# Accepts:
6+
# BOLT11 invoice: lnbcrt1p5m4tld...
7+
# Lightning address: satoshi@domain.com
8+
# BIP21 URI: bitcoin:bcrt1q...?lightning=lnbcrt1p5m4tld...
9+
#
10+
# Usage:
11+
# ./scripts/pay-lightning-address.sh <target> [amount_sats]
12+
#
13+
# Examples:
14+
# ./scripts/pay-lightning-address.sh lnbcrt1p5m4tld...
15+
# ./scripts/pay-lightning-address.sh 'bitcoin:bcrt1q...?lightning=lnbcrt1p5m4tld...'
16+
# ./scripts/pay-lightning-address.sh satoshi@localhost:3003 500
17+
#
18+
# Environment:
19+
# BLOCKTANK_URL → override API base (default: staging)
20+
# LNURL_SCHEME → http or https for LN address resolution (default: auto)
21+
22+
set -e
23+
24+
INPUT="$1"
25+
AMOUNT_SATS="${2:-100}"
26+
BLOCKTANK_URL="${BLOCKTANK_URL:-https://api.stag0.blocktank.to/blocktank/api/v2}"
27+
28+
if [ -z "$INPUT" ]; then
29+
echo "Usage: $0 <target> [amount_sats]"
30+
echo ""
31+
echo " BOLT11: $0 lnbcrt1p5m4tld..."
32+
echo " BIP21: $0 'bitcoin:bcrt1q...?lightning=lnbcrt1p5m4tld...'"
33+
echo " LN addr: $0 satoshi@localhost:3003 500"
34+
exit 1
35+
fi
36+
37+
INVOICE=""
38+
39+
# --- Detect input type ---
40+
41+
# BIP21 URI with lightning= parameter
42+
if echo "$INPUT" | grep -qi "^bitcoin:.*lightning="; then
43+
INVOICE=$(echo "$INPUT" | sed -n 's/.*[?&]lightning=\([^&]*\).*/\1/p' | tr -d '[:space:]')
44+
if [ -z "$INVOICE" ]; then
45+
echo "✗ Could not extract lightning invoice from BIP21 URI"
46+
exit 1
47+
fi
48+
echo "→ Extracted invoice from BIP21 URI (${#INVOICE} chars)"
49+
50+
# Raw BOLT11 invoice
51+
elif echo "$INPUT" | grep -qiE "^ln(bc|tb|tbs|bcrt)"; then
52+
INVOICE=$(echo "$INPUT" | tr -d '[:space:]')
53+
echo "→ Using BOLT11 invoice (${#INVOICE} chars)"
54+
55+
# Lightning address (user@domain)
56+
elif echo "$INPUT" | grep -q "@"; then
57+
if ! command -v jq &> /dev/null; then
58+
echo "✗ jq required for LN address. Install: brew install jq"
59+
exit 1
60+
fi
61+
62+
USERNAME="${INPUT%%@*}"
63+
DOMAIN="${INPUT#*@}"
64+
65+
if [ -n "$LNURL_SCHEME" ]; then
66+
SCHEME="$LNURL_SCHEME"
67+
elif echo "$DOMAIN" | grep -qE "^(localhost|127\.0\.0\.1)"; then
68+
SCHEME="http"
69+
else
70+
SCHEME="https"
71+
fi
72+
73+
AMOUNT_MSATS=$((AMOUNT_SATS * 1000))
74+
echo "→ Resolving ${USERNAME}@${DOMAIN}..."
75+
76+
LNURL_RESPONSE=$(curl -sf "${SCHEME}://${DOMAIN}/.well-known/lnurlp/${USERNAME}")
77+
if [ $? -ne 0 ]; then
78+
echo "✗ Failed to resolve lightning address"
79+
exit 1
80+
fi
81+
82+
CALLBACK=$(echo "$LNURL_RESPONSE" | jq -r '.callback')
83+
MIN_SENDABLE=$(echo "$LNURL_RESPONSE" | jq -r '.minSendable')
84+
MAX_SENDABLE=$(echo "$LNURL_RESPONSE" | jq -r '.maxSendable')
85+
86+
if [ "$AMOUNT_MSATS" -lt "$MIN_SENDABLE" ] || [ "$AMOUNT_MSATS" -gt "$MAX_SENDABLE" ]; then
87+
echo "${AMOUNT_SATS} sats out of range [$((MIN_SENDABLE/1000))-$((MAX_SENDABLE/1000))] sats"
88+
exit 1
89+
fi
90+
91+
echo "→ Requesting invoice for ${AMOUNT_SATS} sats..."
92+
SEP="?"; echo "$CALLBACK" | grep -q "?" && SEP="&"
93+
INVOICE_RESPONSE=$(curl -sf "${CALLBACK}${SEP}amount=${AMOUNT_MSATS}")
94+
INVOICE=$(echo "$INVOICE_RESPONSE" | jq -r '.pr' | tr -d '[:space:]')
95+
96+
if [ -z "$INVOICE" ] || [ "$INVOICE" = "null" ]; then
97+
echo "✗ No invoice in callback response"
98+
echo "$INVOICE_RESPONSE" | jq .
99+
exit 1
100+
fi
101+
echo "→ Got invoice (${#INVOICE} chars)"
102+
else
103+
echo "✗ Unrecognized format. Use: BOLT11, BIP21 URI, or lightning address"
104+
exit 1
105+
fi
106+
107+
# --- Pay via Blocktank ---
108+
109+
BODY="{\"invoice\": \"${INVOICE}\""
110+
if [ -n "$AMOUNT_SATS" ] && [ "$AMOUNT_SATS" -gt 0 ] 2>/dev/null; then
111+
BODY="${BODY}, \"amountSat\": ${AMOUNT_SATS}"
112+
fi
113+
BODY="${BODY}}"
114+
115+
echo "→ Paying ${AMOUNT_SATS} sats via Blocktank..."
116+
PAY_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "${BLOCKTANK_URL}/regtest/channel/pay" \
117+
-H "Content-Type: application/json" \
118+
-d "$BODY")
119+
120+
HTTP_CODE=$(echo "$PAY_RESPONSE" | tail -n1)
121+
BODY=$(echo "$PAY_RESPONSE" | sed '$d')
122+
123+
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
124+
echo "✓ Payment sent"
125+
[ -n "$BODY" ] && echo " $BODY"
126+
else
127+
echo "✗ Payment failed: HTTP $HTTP_CODE"
128+
echo " $BODY"
129+
exit 1
130+
fi

0 commit comments

Comments
 (0)