added EventSource to show a thank you message

This commit is contained in:
michael1011 2018-03-26 23:54:12 +02:00
parent 58f432d04f
commit a4ad464710
No known key found for this signature in database
GPG Key ID: 84D249BA71685D46
6 changed files with 107 additions and 8 deletions

View File

@ -1,5 +1,10 @@
package backends
import "github.com/donovanhide/eventsource"
// For callbacks when an invoice gets settled
type PublishInvoiceSettled func(invoice string, eventSrv *eventsource.Server)
type Backend interface {
Connect() error

View File

@ -4,7 +4,7 @@ import (
"context"
"encoding/hex"
"errors"
"fmt"
"github.com/donovanhide/eventsource"
"github.com/lightningnetwork/lnd/lnrpc"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
@ -90,7 +90,7 @@ func (lnd *LND) GetInvoice(message string, amount int64, expiry int64) (invoice
return response.PaymentRequest, err
}
func (lnd *LND) SubscribeInvoices() error {
func (lnd *LND) SubscribeInvoices(callback PublishInvoiceSettled, eventSrv *eventsource.Server) error {
stream, err := lnd.client.SubscribeInvoices(lnd.ctx, &lnrpc.InvoiceSubscription{})
if err != nil {
@ -101,7 +101,7 @@ func (lnd *LND) SubscribeInvoices() error {
go func() {
for {
in, streamErr := stream.Recv()
invoice, streamErr := stream.Recv()
if streamErr == io.EOF {
err = errors.New("lost connection to LND gRPC")
@ -119,8 +119,12 @@ func (lnd *LND) SubscribeInvoices() error {
return
}
fmt.Println(in)
if invoice.Settled {
callback(invoice.PaymentRequest, eventSrv)
}
}
}()
<-wait

View File

@ -115,6 +115,12 @@
float: right;
}
#lightningTipThankYou {
margin-bottom: 0.2em;
display: block;
}
.spinner {
width: 12px;
height: 12px;

View File

@ -5,6 +5,7 @@
<script async defer src="lightningTip.js"></script>
<script async defer src="https://cdn.rawgit.com/kazuhikoarase/qrcode-generator/886a247e/js/qrcode.js"></script>
<script async defer src="https://cdn.rawgit.com/emn178/js-sha256/189bb9b0/build/sha256.min.js"></script>
</head>
<div id="lightningTip">

View File

@ -11,7 +11,10 @@ var qrCode;
var defaultGetInvoice;
// TODO: listen to eventsource and show tank you when invoice settled
// TODO: show error when invoice expires
// TODO: maybe don't show full invoice
// TODO: proper url handling window.location.protocol + window.location.hostname + ":8081/getinvoice"
// TODO: show price in dollar?
function getInvoice() {
if (running === false) {
running = true;
@ -34,6 +37,16 @@ function getInvoice() {
console.log("Got invoice: " + json.Invoice);
console.log("Invoice expires in: " + json.Expiry);
var hash = sha256(json.Invoice);
console.log("Got hash of invoice: " + hash);
// TODO: find alternative for Edge and IE
console.log("Starting listening for invoice to get settled");
listenInvoiceSettled(hash);
// Update UI
invoice = json.Invoice;
var wrapper = document.getElementById("lightningTip");
@ -65,6 +78,8 @@ function getInvoice() {
}
} catch (exception) {
console.error(exception);
showErrorMessage("Failed to reach backend");
}
@ -72,7 +87,6 @@ function getInvoice() {
};
// TODO: proper url handling window.location.protocol + window.location.hostname + ":8081/getinvoice"
request.open("POST", "http://localhost:8081/getinvoice", true);
request.send(data);
@ -99,6 +113,19 @@ function getInvoice() {
}
function listenInvoiceSettled(hash) {
var eventSrc = new EventSource("http://localhost:8081/eventsource");
eventSrc.onmessage = function (event) {
if (event.data === hash) {
var wrapper = document.getElementById("lightningTip");
wrapper.innerHTML = "<p id=\"lightningTipLogo\">⚡</p>";
wrapper.innerHTML += "<a id='lightningTipThankYou'>Thank you for your tip!</a>";
}
};
}
function starTimer(duration, element) {
showTimer(duration, element);

View File

@ -1,14 +1,35 @@
package main
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/donovanhide/eventsource"
"io/ioutil"
"net/http"
"os"
"strconv"
"time"
)
const eventChannel = "invoiceSettled"
var eventSrv *eventsource.Server
var pendingInvoices []PendingInvoice
type PendingInvoice struct {
Invoice string
Hash string
Expiry time.Time
}
// To use the pendingInvoice type as event for the EventSource stream
func (pending PendingInvoice) Id() string { return "" }
func (pending PendingInvoice) Event() string { return "" }
func (pending PendingInvoice) Data() string { return pending.Hash }
type invoiceResponse struct {
Invoice string
Expiry int64
@ -32,14 +53,18 @@ func main() {
err := backend.Connect()
if err == nil {
log.Info("Starting EventSource stream")
eventSrv = eventsource.NewServer()
http.HandleFunc("/", notFoundHandler)
http.HandleFunc("/getinvoice", getInvoiceHandler)
http.HandleFunc("/eventsource", eventSrv.Handler(eventChannel))
log.Info("Subscribing to invoices")
go func() {
// TODO: let clients listen if their invoice was paid (eventsource)
err = cfg.LND.SubscribeInvoices()
err = cfg.LND.SubscribeInvoices(publishInvoiceSettled, eventSrv)
if err != nil {
log.Error("Failed to subscribe to invoices: " + fmt.Sprint(err))
@ -68,6 +93,23 @@ func main() {
}
// Callbacks when an invoice gets settled
func publishInvoiceSettled(invoice string, eventSrv *eventsource.Server) {
for index, pending := range pendingInvoices {
if pending.Invoice == invoice {
log.Info("Invoice settled: " + invoice)
eventSrv.Publish([]string{eventChannel}, pending)
pendingInvoices = append(pendingInvoices[:index], pendingInvoices[index+1:]...)
break
}
}
}
func getInvoiceHandler(writer http.ResponseWriter, request *http.Request) {
errorMessage := "Could not parse values from request"
@ -89,8 +131,22 @@ func getInvoiceHandler(writer http.ResponseWriter, request *http.Request) {
logMessage += " with message \"" + body.Message + "\""
}
sha := sha256.New()
sha.Write([]byte(invoice))
hash := hex.EncodeToString(sha.Sum(nil))
expiryDuration := time.Duration(cfg.TipExpiry) * time.Second
log.Info(logMessage)
// TODO: check every minute or so if expired
pendingInvoices = append(pendingInvoices, PendingInvoice{
Invoice: invoice,
Hash: hash,
Expiry: time.Now().Add(expiryDuration),
})
writer.Write(marshalJson(invoiceResponse{
Invoice: invoice,
Expiry: cfg.TipExpiry,