added EventSource to show a thank you message
This commit is contained in:
parent
58f432d04f
commit
a4ad464710
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -115,6 +115,12 @@
|
|||
float: right;
|
||||
}
|
||||
|
||||
#lightningTipThankYou {
|
||||
margin-bottom: 0.2em;
|
||||
|
||||
display: block;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue