Skill: talvasconcelos/lnbits (version 1.0.0)

--- name: lnbits description: Manage LNbits Lightning Wallet (Balance, Pay, Invoice) homepage: https://lnbits.com metadata: {"clawdbot":{"emoji":"⚡","requires":{"bins":["python3"],"env":["LNBITS_API_KEY", "LNBITS_BASE_URL"]},"primaryEnv":"LNBITS_API_KEY"}} --- # LNbits Wallet Manager Enable the assistant to safely and effectively manage an LNbits Lightning Network wallet. ## 🛑 CRITICAL SECURITY PROTOCOLS 🛑 1. **NEVER Expose Secrets**: Do NOT display Admin Keys, User IDs, or Wallet IDs. 2. **Explicit Confirmation**: You MUST ask for "Yes/No" confirmation before paying. * *Format*: "I am about to send **[Amount] sats** to **[Memo/Dest]**. Proceed? (y/n)" 3. **Check Balance First**: Always call `balance` before `pay` to prevent errors. ## Usage ### 0. Setup / Create Wallet If the user does not have an LNbits wallet, you can create one for them on the demo server. ```bash python3 {baseDir}/scripts/lnbits_cli.py create --name "My Wallet" ``` **Action**: 1. Run the command. 2. Capture the `adminkey` (Admin Key) and `base_url` (defaults to https://demo.lnbits.com). 3. **IMPORTANT**: Instruct the user to save these credentials securely: > "I've created a new wallet! Please add these to your Moltbot configuration or `.env` file: > `export LNBITS_BASE_URL=https://demo.lnbits.com` > `export LNBITS_API_KEY=<adminkey>`" ### 1. Check Balance Get the current wallet balance in Satoshis. ```bash python3 {baseDir}/scripts/lnbits_cli.py balance ``` ### 2. Create Invoice (Receive) Generate a Bolt11 invoice to receive funds. * **amount**: Amount in Satoshis (Integer). * **memo**: Optional description. ```bash python3 {baseDir}/scripts/lnbits_cli.py invoice --amount 1000 --memo "Pizza" ``` ### 3. Pay Invoice (Send) **⚠️ REQUIRES CONFIRMATION**: Decode first, verify balance, ask user, then execute. ```bash # Step 1: Decode to verify amount/memo python3 {baseDir}/scripts/lnbits_cli.py decode <bolt11_string> # Step 2: Pay (Only after user CONFIRMS) python3 {baseDir}/scripts/lnbits_cli.py pay <bolt11_string> ``` ## Error Handling If the CLI returns a JSON error (e.g., `{"error": "Insufficient funds"}`), summarize it clearly for the user. Do not show raw stack traces.

path: scripts/lnbits_cli.py
content: #!/usr/bin/env python3
import argparse
import json
import os
import sys
import urllib.request
import urllib.error

# Configuration
BASE_URL = os.getenv("LNBITS_BASE_URL", "https://legend.lnbits.com").rstrip("/")
[REDACTED_SECRET]"LNBITS_API_KEY")

# --- Helpers ---

def error(msg, code=1):
    print(json.dumps({"error": msg}))
    sys.exit(code)

def request(method, endpoint, data=None):
    if not [REDACTED_SECRET]"LNBITS_API_KEY environment variable is not set.")

    url = f"{BASE_URL}/api/v1{endpoint}"
    headers = {
        "X-Api-Key": API_KEY,
        "Content-Type": "application/json"
    }
    body = json.dumps(data).encode("utf-8") if data else None
    
    req = urllib.request.Request(url, method=method, headers=headers, data=body)
    try:
        with urllib.request.urlopen(req, timeout=20) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        error_body = e.read().decode("utf-8", errors="replace")
        error(f"API Error ({e.code}): {error_body}")
    except Exception as e:
        error(f"Network Error: {str(e)}")

# --- Core Logic ---

def get_balance():
    data = request("GET", "/wallet")
    return {
        "name": data.get("name"),
        "balance_msat": data.get("balance"),
        "balance_sats": int(data.get("balance", 0) / 1000)
    }

def create_invoice(amount, memo):
    return request("POST", "/payments", {
        "out": False, "amount": amount, "memo": memo, "unit": "sat"
    })

def pay_invoice(bolt11):
    return request("POST", "/payments", {"out": True, "bolt11": bolt11})

def decode_invoice(bolt11):
    return request("POST", "/payments/decode", {"data": bolt11})

def create_wallet(name):
    url = f"{BASE_URL}/api/v1/account"
    req = urllib.request.Request(
        url, 
        method="POST", 
        headers={"Content-Type": "application/json"},
        data=json.dumps({"name": name}).encode("utf-8")
    )
    with urllib.request.urlopen(req, timeout=20) as resp:
        return json.loads(resp.read().decode("utf-8"))

# --- CLI Handlers ---

def cmd_balance(args):
    print(json.dumps(get_balance(), indent=2))

def cmd_create(args):
    print(json.dumps(create_wallet(args.name), indent=2))

def cmd_invoice(args):
    print(json.dumps(create_invoice(args.amount, args.memo), indent=2))

def cmd_pay(args):
    print(json.dumps(pay_invoice(args.bolt11), indent=2))

def cmd_decode(args):
    print(json.dumps(decode_invoice(args.bolt11), indent=2))

# --- Main ---

def main():
    parser = argparse.ArgumentParser(description="LNbits CLI Bridge for Clawdbot")
    subparsers = parser.add_subparsers(dest="command", required=True)

    # Balance
    p_balance = subparsers.add_parser("balance", help="Get wallet balance")
    p_balance.set_defaults(func=cmd_balance)

    # Create Wallet (Account)
    p_create = subparsers.add_parser("create", help="Create a new LNbits wallet")
    p_create.add_argument("--name", type=str, default="Moltbot Wallet", help="Name of the new wallet")
    p_create.set_defaults(func=cmd_create)

    # Invoice
    p_invoice = subparsers.add_parser("invoice", help="Create a lightning invoice")
    p_invoice.add_argument("--amount", type=int, required=True, help="Amount in satoshis")
    p_invoice.add_argument("--memo", type=str, default="", help="Optional memo")
    p_invoice.set_defaults(func=cmd_invoice)

    # Pay
    p_pay = subparsers.add_parser("pay", help="Pay a lightning invoice")
    p_pay.add_argument("bolt11", type=str, help="The Bolt11 invoice string")
    p_pay.set_defaults(func=cmd_pay)

    # Decode
    p_decode = subparsers.add_parser("decode", help="Decode a lightning invoice")
    p_decode.add_argument("bolt11", type=str, help="The Bolt11 invoice string")
    p_decode.set_defaults(func=cmd_decode)

    args = parser.parse_args()

    try:
        args.func(args)
    except Exception as e:
        error(str(e))

if __name__ == "__main__":
    main()

Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (CRITICAL)