Add test infrastructure helpers for e2e testing

New devenv.nix scripts:
- test-setup: Validates entire test environment (services, connectivity,
  blockchain state, channels, and runs a payment test)
- fund-atm: Funds ATM Lightning.Pub account via Alice
- test-payment: Quick e2e payment test (ATM → customer)
- alice-invoice: Create invoice on Alice's node
- node-info: Display node pubkeys and channel information

Script improvements:
- fund-dev.mjs: Use FUND_AMOUNT env var instead of hardcoded value
- test-pay.mjs: Use NOSTR_RELAY_URL env var with localhost fallback
- Both scripts now use localhost:7777 by default instead of hardcoded IP

Updated shell hook to document new testing commands.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-01-24 18:23:54 -05:00
commit 6d0485bfb5
3 changed files with 236 additions and 4 deletions

View file

@ -278,6 +278,228 @@
echo "Paying invoice from Alice's node..."
docker exec lamassu-lnd-alice lncli --network=regtest payinvoice --force "$1"
'';
# Create invoice on Alice's node (for testing ATM payouts)
alice-invoice.exec = ''
AMOUNT=''${1:-1000}
MEMO=''${2:-"Test invoice"}
docker exec lamassu-lnd-alice lncli --network=regtest addinvoice --amt="$AMOUNT" --memo="$MEMO" | jq -r '.payment_request'
'';
# Fund ATM account in Lightning.Pub
fund-atm.exec = ''
AMOUNT=''${1:-100000}
echo "Funding ATM account with $AMOUNT sats..."
echo ""
# Run the funding script from nostr-client package
cd packages/nostr-client
FUND_AMOUNT=$AMOUNT node fund-dev.mjs 2>&1 | tee /tmp/fund-atm-output.txt
# Extract the invoice
INVOICE=$(grep -o 'lnbcrt[a-zA-Z0-9]*' /tmp/fund-atm-output.txt | head -1)
if [ -z "$INVOICE" ]; then
echo "Failed to create invoice. Check the output above."
exit 1
fi
echo ""
echo "Invoice created. Paying from Alice..."
docker exec lamassu-lnd-alice lncli --network=regtest payinvoice --force "$INVOICE"
echo ""
echo "ATM account funded with $AMOUNT sats!"
'';
# Validate entire test setup
test-setup.exec = ''
echo ""
echo "═══════════════════════════════════════════════════════════"
echo " Lamassu Next - Test Setup Validation"
echo "═══════════════════════════════════════════════════════════"
echo ""
PASSED=0
FAILED=0
check() {
if [ $1 -eq 0 ]; then
echo " ✓ $2"
PASSED=$((PASSED + 1))
else
echo " ✗ $2"
FAILED=$((FAILED + 1))
fi
}
echo "1. Services"
echo "───────────────────────────────────────────────────────────"
# Check containers
docker ps --format '{{.Names}}' | grep -q lamassu-relay
check $? "strfry relay running"
docker ps --format '{{.Names}}' | grep -q lamassu-bitcoind
check $? "bitcoind running"
docker ps --format '{{.Names}}' | grep -q lamassu-lnd
check $? "LND running"
docker ps --format '{{.Names}}' | grep -q lamassu-lnd-alice
check $? "LND Alice running"
docker ps --format '{{.Names}}' | grep -q lamassu-lightning-pub
check $? "Lightning.Pub running"
echo ""
echo "2. Connectivity"
echo "───────────────────────────────────────────────────────────"
# Check relay port is open
timeout 2 bash -c 'echo > /dev/tcp/localhost/7777' 2>/dev/null
check $? "Nostr relay port open"
# Check bitcoind RPC
docker exec lamassu-bitcoind bitcoin-cli -regtest -rpcuser=lamassu -rpcpassword=lamassu getblockchaininfo >/dev/null 2>&1
check $? "Bitcoin RPC responding"
# Check LND
docker exec lamassu-lnd lncli --network=regtest getinfo >/dev/null 2>&1
check $? "LND RPC responding"
# Check Alice
docker exec lamassu-lnd-alice lncli --network=regtest getinfo >/dev/null 2>&1
check $? "LND Alice RPC responding"
echo ""
echo "3. Blockchain State"
echo "───────────────────────────────────────────────────────────"
BLOCKS=$(docker exec lamassu-bitcoind bitcoin-cli -regtest -rpcuser=lamassu -rpcpassword=lamassu getblockcount 2>/dev/null)
[ "$BLOCKS" -ge 100 ]
check $? "Block height >= 100 (current: $BLOCKS)"
# Check LND synced
LND_SYNCED=$(docker exec lamassu-lnd lncli --network=regtest getinfo 2>/dev/null | jq -r '.synced_to_chain')
[ "$LND_SYNCED" = "true" ]
check $? "LND synced to chain"
# Check Alice synced
ALICE_SYNCED=$(docker exec lamassu-lnd-alice lncli --network=regtest getinfo 2>/dev/null | jq -r '.synced_to_chain')
[ "$ALICE_SYNCED" = "true" ]
check $? "LND Alice synced to chain"
echo ""
echo "4. Lightning Channels"
echo "───────────────────────────────────────────────────────────"
# Check Alice has active channels
ALICE_CHANNELS=$(docker exec lamassu-lnd-alice lncli --network=regtest listchannels 2>/dev/null | jq '.channels | length')
[ "$ALICE_CHANNELS" -ge 1 ]
check $? "Alice has active channels (count: $ALICE_CHANNELS)"
# Check channel is active
ACTIVE_CHANNEL=$(docker exec lamassu-lnd-alice lncli --network=regtest listchannels 2>/dev/null | jq '.channels[0].active')
[ "$ACTIVE_CHANNEL" = "true" ]
check $? "Channel is active"
# Check Alice has outbound capacity
ALICE_LOCAL=$(docker exec lamassu-lnd-alice lncli --network=regtest listchannels 2>/dev/null | jq -r '.channels[0].local_balance // 0')
[ "$ALICE_LOCAL" -ge 10000 ]
check $? "Alice has outbound capacity ($ALICE_LOCAL sats)"
echo ""
echo "5. Payment Test"
echo "───────────────────────────────────────────────────────────"
# Create test invoice on LND and pay from Alice
TEST_INVOICE=$(docker exec lamassu-lnd lncli --network=regtest addinvoice --amt=100 --memo="test-setup validation" 2>/dev/null | jq -r '.payment_request')
if [ -n "$TEST_INVOICE" ]; then
check 0 "Created 100 sat test invoice"
# Pay it
PAY_RESULT=$(docker exec lamassu-lnd-alice lncli --network=regtest payinvoice --force "$TEST_INVOICE" 2>&1)
if echo "$PAY_RESULT" | grep -q "SUCCEEDED"; then
check 0 "Payment Alice → LND succeeded"
else
check 1 "Payment Alice → LND failed"
fi
else
check 1 "Failed to create test invoice"
check 1 "Payment test skipped"
fi
echo ""
echo "═══════════════════════════════════════════════════════════"
echo " Results: $PASSED passed, $FAILED failed"
echo "═══════════════════════════════════════════════════════════"
echo ""
if [ $FAILED -gt 0 ]; then
echo "Some checks failed. Run 'infra-up' and 'setup-channel' first."
exit 1
else
echo "All checks passed! Ready for testing."
exit 0
fi
'';
# Quick e2e payment test (ATM pays customer invoice)
test-payment.exec = ''
AMOUNT=''${1:-1000}
echo "Testing e2e payment flow ($AMOUNT sats)..."
echo ""
# Create invoice on Alice (simulating customer's wallet)
echo "1. Creating invoice on Alice's wallet..."
INVOICE=$(docker exec lamassu-lnd-alice lncli --network=regtest addinvoice --amt="$AMOUNT" --memo="E2E test" | jq -r '.payment_request')
echo " Invoice: ''${INVOICE:0:40}..."
# Use test-pay.mjs to pay via Lightning.Pub
echo ""
echo "2. Paying via Lightning.Pub (ATM flow)..."
cd packages/nostr-client
node test-pay.mjs "$INVOICE"
echo ""
echo "3. Verifying payment on Alice..."
sleep 2
PAID=$(docker exec lamassu-lnd-alice lncli --network=regtest listinvoices 2>/dev/null | jq '.invoices[-1].settled')
if [ "$PAID" = "true" ]; then
echo " ✓ Payment received!"
else
echo " ✗ Payment not received"
exit 1
fi
'';
# Show node info
node-info.exec = ''
echo ""
echo "Node Information"
echo "════════════════════════════════════════════════════════"
echo ""
echo "LND (Lightning.Pub's node):"
docker exec lamassu-lnd lncli --network=regtest getinfo 2>/dev/null | jq '{pubkey: .identity_pubkey, alias: .alias, channels: .num_active_channels, peers: .num_peers}'
echo ""
echo "LND Alice (Payment source):"
docker exec lamassu-lnd-alice lncli --network=regtest getinfo 2>/dev/null | jq '{pubkey: .identity_pubkey, alias: .alias, channels: .num_active_channels, peers: .num_peers}'
echo ""
echo "Channel Details:"
docker exec lamassu-lnd-alice lncli --network=regtest listchannels 2>/dev/null | jq '.channels[] | {peer: .remote_pubkey[0:16], capacity, local: .local_balance, remote: .remote_balance, active}'
echo ""
echo "Lightning.Pub Nostr pubkey:"
echo " f454c5eec4ec4474128e19b57b45e49c3d0851d01eea960b39ce391cdba76fc6"
echo ""
echo "ATM Dev Identity:"
echo " 4646ae5047316b4230d0086c8acec687f00b1cd9d1dc634f6cb358ac0a9a8fff"
'';
};
# ============================================
@ -312,5 +534,12 @@
echo " alice-pay Pay invoice from Alice's node"
echo " relay-test Test Nostr relay connection"
echo ""
echo " Testing (E2E):"
echo " test-setup Validate test environment (services, channels, payments)"
echo " test-payment Quick e2e payment test (ATM → customer)"
echo " fund-atm Fund ATM account (default: 100k sats)"
echo " alice-invoice Create invoice on Alice's node"
echo " node-info Show node pubkeys and channel info"
echo ""
'';
}

View file

@ -4,7 +4,8 @@ import { randomUUID } from 'crypto'
const DEV_PRIVATE_KEY = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
const LIGHTNING_PUB_PUBKEY = 'f454c5eec4ec4474128e19b57b45e49c3d0851d01eea960b39ce391cdba76fc6'
const RELAY_URL = 'ws://192.168.1.122:7777'
const RELAY_URL = process.env.NOSTR_RELAY_URL || 'ws://localhost:7777'
const FUND_AMOUNT = parseInt(process.env.FUND_AMOUNT || '100000', 10)
async function main() {
const identity = loadIdentityFromHex(DEV_PRIVATE_KEY)
@ -26,13 +27,15 @@ async function main() {
params: {},
query: {},
body: {
amountSats: 100000,
memo: 'Fund dev account',
amountSats: FUND_AMOUNT,
memo: `Fund dev account (${FUND_AMOUNT} sats)`,
},
authIdentifier: identity.publicKey,
requestId,
}
console.log('Creating invoice for', FUND_AMOUNT, 'sats')
console.log('Request structure:', JSON.stringify(rpcRequest, null, 2))
const encryptedContent = encryptContent(identity, LIGHTNING_PUB_PUBKEY, rpcRequest)

View file

@ -5,7 +5,7 @@ import { randomUUID } from 'crypto'
const DEV_PRIVATE_KEY = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
const LIGHTNING_PUB_PUBKEY = 'f454c5eec4ec4474128e19b57b45e49c3d0851d01eea960b39ce391cdba76fc6'
const RELAY_URL = 'ws://192.168.1.122:7777'
const RELAY_URL = process.env.NOSTR_RELAY_URL || 'ws://localhost:7777'
// Get a fresh invoice from Alice first:
// docker exec lamassu-lnd-alice lncli --network=regtest addinvoice --amt 1000