mirror of
https://github.com/aljazceru/plugins.git
synced 2025-12-24 08:34:18 +01:00
request-invoice: Remove the plugin
It's utterly outdated, and has been replaced by a number of other plugins, no point in keeping it around.
This commit is contained in:
@@ -1,47 +0,0 @@
|
||||
# Http Invoice Request Server plugin
|
||||
|
||||
|
||||
This plugin starts a minimal, rate limited HTTP Server and returns a invoice on the following GET request:
|
||||
|
||||
``/invoice/<amount>/<description>``
|
||||
|
||||
```
|
||||
$ lightning-cli invoiceserver start
|
||||
started server successfully on port 8089
|
||||
|
||||
$ curl http://localhost:8809/invoice/100000/some-text-here
|
||||
{"bolt11":"lnbc100000n1p0yr9sxpp50t9rnvw5slcjn6m97fmujpp9xd6w0h26dpvajcv8xwhu42xk5vlqdq8vej8xcgxqyj...","expires_at":1581961350,"payment_hash":"7aca39b1d487f129eb65f277c904253374e7dd5a6859d9618733afcaa8d6a33e", ...}
|
||||
```
|
||||
|
||||
The webserver is rate-limited, meaning that only a certain amount of request per minute is allowed (to prevent DoS attacks).
|
||||
|
||||
The json invoice can be used by other services, for example a service for tipping, donations, PoS devices, ...
|
||||
|
||||
|
||||
Once the plugin is active you can run `lightning-cli help invoiceserver` to
|
||||
learn about the command line API:
|
||||
|
||||
Commands: `start`/`stop`/`restart`/`status`.
|
||||
|
||||
In the file `.lightning/bitcoin/.env` the `port` can be set (default 8089).
|
||||
|
||||
##### Onion routing
|
||||
Exposing the url using Onion routing is easy. Install tor and
|
||||
add the service to `/etc/tor/torrc`
|
||||
```
|
||||
HiddenServiceDir /home/bitcoin/tor/request-invoice-service_v2/
|
||||
HiddenServicePort 80 127.0.0.1:8809
|
||||
|
||||
```
|
||||
and restart tor to create the url
|
||||
```
|
||||
$ systemctl stop tor && systemctl start tor
|
||||
$ cat /home/bitcoin/tor/request-invoice-service_v2/hostname
|
||||
fkfuvjrbj6cfqppq6xcgfwmp4p23wq2unzlnqmdi6ibqtg2aq7thp2qd.onion
|
||||
```
|
||||
|
||||
Use tor browser to visit the url and create a invoice (and make a donation?).
|
||||
http://fkfuvjrbj6cfqppq6xcgfwmp4p23wq2unzlnqmdi6ibqtg2aq7thp2qd.onion/invoice/1000/donation
|
||||
|
||||
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from flask import Flask
|
||||
from flask_limiter import Limiter
|
||||
from flask_limiter.util import get_remote_address
|
||||
from pathlib import Path
|
||||
from pyln.client import Plugin
|
||||
from tornado.httpserver import HTTPServer
|
||||
from tornado.ioloop import IOLoop
|
||||
from tornado.wsgi import WSGIContainer
|
||||
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import threading
|
||||
import uuid
|
||||
|
||||
plugin = Plugin()
|
||||
app = Flask(__name__)
|
||||
limiter = Limiter(
|
||||
app,
|
||||
key_func=get_remote_address,
|
||||
default_limits=["2000 per day", "20 per minute"]
|
||||
)
|
||||
|
||||
jobs = {}
|
||||
|
||||
|
||||
|
||||
@limiter.limit("20 per minute")
|
||||
@app.route('/invoice/<int:amount>/<description>')
|
||||
def getinvoice(amount, description):
|
||||
global plugin
|
||||
label = "ln-getinvoice-{}".format(uuid.uuid4())
|
||||
invoice = plugin.rpc.invoice(int(amount)*1000, label, description)
|
||||
return invoice
|
||||
|
||||
def worker(port):
|
||||
asyncio.set_event_loop(asyncio.new_event_loop())
|
||||
|
||||
print('Starting server on port {port}'.format(
|
||||
port=port
|
||||
))
|
||||
app.config['SECRET_KEY'] = os.getenv(
|
||||
"REQUEST_INVOICE_SECRET",
|
||||
default=uuid.uuid4())
|
||||
|
||||
http_server = HTTPServer(WSGIContainer(app))
|
||||
http_server.listen(port)
|
||||
IOLoop.instance().start()
|
||||
|
||||
|
||||
def start_server(port):
|
||||
if port in jobs:
|
||||
raise ValueError("server already running on port {port}".format(port=port))
|
||||
|
||||
p = threading.Thread(
|
||||
target=worker, args=(port,), daemon=True)
|
||||
|
||||
jobs[port] = p
|
||||
p.start()
|
||||
|
||||
|
||||
def stop_server(port):
|
||||
if port in jobs:
|
||||
jobs[port].terminate()
|
||||
del jobs[port]
|
||||
else:
|
||||
raise ValueError("No server listening on port {port}".format(port=port))
|
||||
|
||||
|
||||
@plugin.method('invoiceserver')
|
||||
def invoiceserver(request, command="start"):
|
||||
"""Starts a server for requestiong invoices.
|
||||
|
||||
A rate limited HTTP Server returns a invoice on the following GET request:
|
||||
/invoice/<amount>/<description>
|
||||
where amount is in Satoshis.
|
||||
The plugin takes one of the following commands:
|
||||
{start/stop/status/restart}.
|
||||
"""
|
||||
commands = {"start", "stop", "status","restart"}
|
||||
port = os.getenv("FLASKPORT", default = 8809)
|
||||
|
||||
# if command unknown make start our default command
|
||||
if command not in commands:
|
||||
command = "start"
|
||||
|
||||
if command == "start":
|
||||
try:
|
||||
start_server(port)
|
||||
return "Invoice server started successfully on port {}".format(port)
|
||||
except Exception as e:
|
||||
return "Error starting server on port {port}: {e}".format(
|
||||
port=port, e=e
|
||||
)
|
||||
|
||||
if command == "stop":
|
||||
try:
|
||||
stop_server(port)
|
||||
return "Invoice server stopped on port {}".format(port)
|
||||
except Exception as e:
|
||||
return "Could not stop server on port {port}: {e}".format(
|
||||
port=port, e=e
|
||||
)
|
||||
|
||||
if command == "status":
|
||||
if port in jobs:
|
||||
return "Invoice server active on port {}".format(port)
|
||||
else:
|
||||
return "Invoice server not active."
|
||||
|
||||
if command == "restart":
|
||||
stop_server(port)
|
||||
start_server(port)
|
||||
return "Invoice server restarted"
|
||||
|
||||
|
||||
@plugin.init()
|
||||
def init(options, configuration, plugin):
|
||||
port = os.getenv("REQUEST_INVOICE_PORT", default = 8809)
|
||||
start_server(port)
|
||||
|
||||
|
||||
plugin.run()
|
||||
@@ -1,6 +0,0 @@
|
||||
python-dotenv>=0.13.0
|
||||
flask==1.1.4
|
||||
flask-limiter
|
||||
tornado
|
||||
pyln-client
|
||||
requests
|
||||
@@ -1,37 +0,0 @@
|
||||
import os
|
||||
from pyln.testing.fixtures import * # noqa: F401,F403
|
||||
import requests
|
||||
from subprocess import check_output
|
||||
|
||||
plugin_path = os.path.join(os.path.dirname(__file__), "requestinvoice.py")
|
||||
|
||||
|
||||
def test_requestinvoice_starts(node_factory):
|
||||
l1 = node_factory.get_node()
|
||||
# Test dynamically
|
||||
l1.rpc.plugin_start(plugin_path)
|
||||
l1.rpc.plugin_stop(plugin_path)
|
||||
l1.rpc.plugin_start(plugin_path)
|
||||
l1.stop()
|
||||
# Then statically
|
||||
l1.daemon.opts["plugin"] = plugin_path
|
||||
l1.start()
|
||||
|
||||
l1.daemon.logsearch_start = 0
|
||||
l1.daemon.wait_for_log(r'Starting server on port 8809')
|
||||
|
||||
r = requests.get('http://localhost:8809/invoice/1000/text')
|
||||
|
||||
# check for hanging process if status_code = 500
|
||||
assert(r.status_code == 200)
|
||||
|
||||
# returned valid invoice?
|
||||
b = r.json()
|
||||
assert(b['bolt11'][:8] == "lnbcrt10")
|
||||
|
||||
|
||||
# test rate-limit
|
||||
for i in range(0,20):
|
||||
r = requests.get('http://localhost:8809/invoice/1000/text')
|
||||
assert(r.status_code == 429)
|
||||
assert("429 Too Many Requests" in r.text )
|
||||
Reference in New Issue
Block a user