Skip to content

Instantly share code, notes, and snippets.

@adrienemery
Last active October 26, 2019 07:34
Show Gist options
  • Select an option

  • Save adrienemery/0506f487da101a0e81e77c6e860cb502 to your computer and use it in GitHub Desktop.

Select an option

Save adrienemery/0506f487da101a0e81e77c6e860cb502 to your computer and use it in GitHub Desktop.

Revisions

  1. adrienemery revised this gist Mar 28, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion lightning_api.py
    Original file line number Diff line number Diff line change
    @@ -28,7 +28,7 @@

    # Setup the Flask-JWT-Simple extension
    JWT_SECRET_KEY = os.getenv('JWT_SECRET_KEY')
    app.config['JWT_SECRET_KEY'] = 'secret'
    app.config['JWT_SECRET_KEY'] = JWT_SECRET_KEY
    jwt = JWTManager(app)

    # Setup the grpc stub
  2. adrienemery revised this gist Mar 28, 2018. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions lightning_api.py
    Original file line number Diff line number Diff line change
    @@ -7,9 +7,9 @@
    But for now I just wanted to show how simple it could be to add a paywall to an api service.
    To use this api:
    1. Make a POST request to get a new token and invoice at `/token` by
    2. pay the invoice that comes along with the token on the lightning network
    3. make a GET request to `/payme`
    1. Make a POST request to get a new token and invoice at `/token`
    2. Pay the invoice that comes along with the token on the lightning network
    3. Make a GET request to `/payme`
    """
    import os
    import binascii
  3. adrienemery revised this gist Mar 28, 2018. 1 changed file with 6 additions and 1 deletion.
    7 changes: 6 additions & 1 deletion lightning_api.py
    Original file line number Diff line number Diff line change
    @@ -5,6 +5,11 @@
    imagined (bulk payments/pay per call etc).
    But for now I just wanted to show how simple it could be to add a paywall to an api service.
    To use this api:
    1. Make a POST request to get a new token and invoice at `/token` by
    2. pay the invoice that comes along with the token on the lightning network
    3. make a GET request to `/payme`
    """
    import os
    import binascii
    @@ -73,7 +78,7 @@ def obtain_token():
    return jsonify(data), 200


    @app.route('/protected', methods=['GET'])
    @app.route('/payme', methods=['GET'])
    @jwt_required
    @invoice_paid
    def protected():
  4. adrienemery created this gist Mar 28, 2018.
    84 changes: 84 additions & 0 deletions lightning_api.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,84 @@
    """
    This app is an example of how you could charge for access to an API using
    the lightning network and LND. The example uses a JWT token that grants 1-hour access
    (the default jwt token expirey) but many different payment schemes could be
    imagined (bulk payments/pay per call etc).
    But for now I just wanted to show how simple it could be to add a paywall to an api service.
    """
    import os
    import binascii
    from functools import wraps

    import grpc
    import rpc_pb2 as ln
    import rpc_pb2_grpc as lnrpc

    from flask import Flask, jsonify, request
    from flask_jwt_simple import JWTManager, jwt_required, create_jwt, get_jwt_identity

    os.environ["GRPC_SSL_CIPHER_SUITES"] = 'HIGH+ECDSA'

    app = Flask(__name__)

    # Setup the Flask-JWT-Simple extension
    JWT_SECRET_KEY = os.getenv('JWT_SECRET_KEY')
    app.config['JWT_SECRET_KEY'] = 'secret'
    jwt = JWTManager(app)

    # Setup the grpc stub
    with open(os.path.expanduser('~/Library/Application Support/Lnd/tls.cert'), 'rb') as f:
    cert = f.read()

    with open(os.path.expanduser('~/Library/Application Support/Lnd/admin.macaroon'), 'rb') as f:
    macaroon_bytes = f.read()
    macaroon_hex = binascii.hexlify(macaroon_bytes).decode()

    creds = grpc.ssl_channel_credentials(cert)
    channel = grpc.secure_channel('127.0.0.1:10009', creds)
    stub = lnrpc.LightningStub(channel)


    def invoice_paid(fn):
    """Decorator to ensure invoice has been paid
    Raises:
    HTTP 402 Error if payment not settled
    """
    @wraps(fn)
    def wrapper(*args, **kwargs):
    r_hash_str = get_jwt_identity()
    rpc_request = ln.PaymentHash(r_hash_str=r_hash_str)
    invoice = stub.LookupInvoice(rpc_request, metadata=[('macaroon', macaroon_hex)])
    if invoice.settled is False:
    return jsonify({"msg": "Payment required"}), 402
    return fn(*args, **kwargs)
    return wrapper


    @app.route('/token', methods=['POST'])
    def obtain_token():
    """Create a JWT with the r_hash of a lightning invoice encoded as the indentity
    """
    # geneate a lightning invoice
    rpc_request = ln.Invoice(value=100, memo='api access')
    response = stub.AddInvoice(rpc_request, metadata=[('macaroon', macaroon_hex)])
    r_hash_str = binascii.hexlify(response.r_hash).decode()

    # use the r_hash as the itentity
    data = {
    'jwt': create_jwt(identity=r_hash_str),
    'invoice': response.payment_request
    }
    return jsonify(data), 200


    @app.route('/protected', methods=['GET'])
    @jwt_required
    @invoice_paid
    def protected():
    return jsonify({'msg': "You Paid!"}), 200


    if __name__ == '__main__':
    app.run()