Cleanup, Threading, minor fixes

This commit is contained in:
Dr. Tobias Baur
2023-03-02 15:13:48 +01:00
parent 228cbd644a
commit a909264d02
2 changed files with 74 additions and 48 deletions
+39 -14
View File
@@ -11,6 +11,7 @@ import (
"github.com/fiatjaf/go-lnurl"
"github.com/gorilla/mux"
"github.com/nbd-wtf/go-nostr"
decodepay "github.com/nbd-wtf/ln-decodepay"
)
var allowNostr bool = false
@@ -34,6 +35,19 @@ type LNURLPayParamsCustom struct {
Metadata lnurl.Metadata `json:"-"`
}
type LNURLPayValuesCustom struct {
lnurl.LNURLResponse
SuccessAction *lnurl.SuccessAction `json:"successAction"`
Routes interface{} `json:"routes"` // ignored
PR string `json:"pr"`
Disposable *bool `json:"disposable,omitempty"`
ParsedInvoice decodepay.Bolt11 `json:"-"`
PayerDataJSON string `json:"-"`
nip57Receipt nostr.Event `json:"nip57Receipt"`
nip57ReceiptRelays []string `json:"nip57ReceiptRelays"`
}
func handleLNURL(w http.ResponseWriter, r *http.Request) {
var err error
var response interface{}
@@ -160,7 +174,8 @@ func handleLNURL(w http.ResponseWriter, r *http.Request) {
//we outsource the second part in a function, we should do this for the first one too.
response, err = serveLNURLpSecond(w, params, username, msat, comment, payerData, zapEvent)
var payvalues = response.(*lnurl.LNURLPayValues)
var payvaluescustom = response.(LNURLPayValuesCustom)
//var payvalues = response.(*lnurl.LNURLPayValues)
if err != nil {
if response != nil {
// there is a valid error response
@@ -168,29 +183,36 @@ func handleLNURL(w http.ResponseWriter, r *http.Request) {
}
return
}
err = json.NewEncoder(w).Encode(response)
json.NewEncoder(w).Encode(lnurl.LNURLPayValues{
LNURLResponse: payvaluescustom.LNURLResponse,
PR: payvaluescustom.PR,
Routes: payvaluescustom.Routes,
SuccessAction: payvaluescustom.SuccessAction,
})
//err = json.NewEncoder(w).Encode(payvalues)
if err != nil {
json.NewEncoder(w).Encode(response)
return
}
if allowNostr {
WaitForInvoicePaid(payvalues, params)
go WaitForInvoicePaid(payvaluescustom, params)
}
}
}
func serveLNURLpSecond(w http.ResponseWriter, params *Params, username string, amount_msat int, comment string, payerData lnurl.PayerDataValues, zapEvent nostr.Event) (*lnurl.LNURLPayValues, error) {
func serveLNURLpSecond(w http.ResponseWriter, params *Params, username string, amount_msat int, comment string, payerData lnurl.PayerDataValues, zapEvent nostr.Event) (LNURLPayValuesCustom, error) {
log.Debug().Any("Serving invoice for user %s", username)
if amount_msat < minSendable || amount_msat > maxSendable {
// amount is not ok
return &lnurl.LNURLPayValues{
return LNURLPayValuesCustom{
LNURLResponse: lnurl.LNURLResponse{
Status: "Error",
Reason: fmt.Sprintf("Amount out of bounds (min: %d sat, max: %d sat).", minSendable/1000, maxSendable/1000)},
}, fmt.Errorf("amount out of bounds")
}
var resp *lnurl.LNURLPayValues
// NIP57 ZAPs
// for nip57 use the nostr event as the descriptionHash
@@ -202,7 +224,7 @@ func serveLNURLpSecond(w http.ResponseWriter, params *Params, username string, a
zapEventSerializedStr = fmt.Sprintf("%s", zapEventSerialized)
if err != nil {
//log.Println(err)
return &lnurl.LNURLPayValues{
return LNURLPayValuesCustom{
LNURLResponse: lnurl.LNURLResponse{
Status: "Error",
Reason: "Couldn't serialize zap event."},
@@ -228,15 +250,16 @@ func serveLNURLpSecond(w http.ResponseWriter, params *Params, username string, a
params.zapEventSerializedStr = ""
}
var response LNURLPayValuesCustom
invoice, err := makeInvoice(params, amount_msat, nil)
if err != nil {
err = fmt.Errorf("Couldn't create invoice: %v", err.Error())
resp = &lnurl.LNURLPayValues{
response = LNURLPayValuesCustom{
LNURLResponse: lnurl.LNURLResponse{
Status: "Error",
Reason: "Couldn't create invoice."},
}
return resp, err
return response, err
}
// nip57 - we need to store the newly created invoice in the zap receipt
if zapEvent.Sig != "" {
@@ -258,11 +281,13 @@ func serveLNURLpSecond(w http.ResponseWriter, params *Params, username string, a
nip57Receipt.Sign(pk)
}
return &lnurl.LNURLPayValues{
LNURLResponse: lnurl.LNURLResponse{Status: "OK"},
PR: invoice,
Routes: make([]struct{}, 0),
SuccessAction: &lnurl.SuccessAction{Message: "Payment Received!", Tag: "message"},
return LNURLPayValuesCustom{
LNURLResponse: lnurl.LNURLResponse{Status: "OK"},
PR: invoice,
Routes: make([]struct{}, 0),
SuccessAction: &lnurl.SuccessAction{Message: "Payment Received!", Tag: "message"},
nip57Receipt: nip57Receipt,
nip57ReceiptRelays: nip57ReceiptRelays,
}, nil
}
+35 -34
View File
@@ -14,7 +14,6 @@ import (
"strings"
"time"
"github.com/fiatjaf/go-lnurl"
decodepay "github.com/nbd-wtf/ln-decodepay"
"github.com/tidwall/gjson"
)
@@ -45,7 +44,7 @@ type CommandoParams struct {
}
func (l CommandoParams) getCert() string { return "" }
func (l CommandoParams) isTor() bool { return strings.Index(l.Host, ".onion") != -1 }
func (l CommandoParams) isTor() bool { return strings.Contains(l.Host, ".onion") }
type SparkoParams struct {
Cert string
@@ -54,7 +53,7 @@ type SparkoParams struct {
}
func (l SparkoParams) getCert() string { return l.Cert }
func (l SparkoParams) isTor() bool { return strings.Index(l.Host, ".onion") != -1 }
func (l SparkoParams) isTor() bool { return strings.Contains(l.Host, ".onion") }
type LNDParams struct {
Cert string
@@ -63,7 +62,7 @@ type LNDParams struct {
}
func (l LNDParams) getCert() string { return l.Cert }
func (l LNDParams) isTor() bool { return strings.Index(l.Host, ".onion") != -1 }
func (l LNDParams) isTor() bool { return strings.Contains(l.Host, ".onion") }
type LNBitsParams struct {
Cert string
@@ -72,7 +71,7 @@ type LNBitsParams struct {
}
func (l LNBitsParams) getCert() string { return l.Cert }
func (l LNBitsParams) isTor() bool { return strings.Index(l.Host, ".onion") != -1 }
func (l LNBitsParams) isTor() bool { return strings.Contains(l.Host, ".onion") }
type LNPayParams struct {
PublicAccessKey string
@@ -89,7 +88,7 @@ type EclairParams struct {
}
func (l EclairParams) getCert() string { return l.Cert }
func (l EclairParams) isTor() bool { return strings.Index(l.Host, ".onion") != -1 }
func (l EclairParams) isTor() bool { return strings.Contains(l.Host, ".onion") }
type StrikeParams struct {
Key string
@@ -105,7 +104,7 @@ type BackendParams interface {
isTor() bool
}
func WaitForInvoicePaid(payvalues *lnurl.LNURLPayValues, params *Params) {
func WaitForInvoicePaid(payvalues LNURLPayValuesCustom, params *Params) {
//Check for a minute if invoice is paid
//Do we have an easier way to do this? How does it work for other backends than lnbits.
go func() {
@@ -182,9 +181,11 @@ func WaitForInvoicePaid(payvalues *lnurl.LNURLPayValues, params *Params) {
case <-ticker.C:
bolt11, _ := decodepay.Decodepay(payvalues.PR)
var isPaid bool = false
switch backend := mip.Backend.(type) {
case SparkoParams:
//TODO
case LNDParams:
req, err := http.NewRequest("GET",
backend.Host+"/v1/invoice/"+bolt11.PaymentHash,
@@ -196,7 +197,6 @@ func WaitForInvoicePaid(payvalues *lnurl.LNURLPayValues, params *Params) {
if b, err := base64.StdEncoding.DecodeString(backend.Macaroon); err == nil {
backend.Macaroon = hex.EncodeToString(b)
}
req.Header.Set("Grpc-Metadata-macaroon", backend.Macaroon)
resp, err := Client.Do(req)
if err != nil {
@@ -204,14 +204,6 @@ func WaitForInvoicePaid(payvalues *lnurl.LNURLPayValues, params *Params) {
return
}
defer resp.Body.Close()
if resp.StatusCode >= 300 {
body, _ := ioutil.ReadAll(resp.Body)
text := string(body)
if len(text) > 300 {
text = text[:300]
}
return
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
@@ -219,11 +211,8 @@ func WaitForInvoicePaid(payvalues *lnurl.LNURLPayValues, params *Params) {
return
}
if gjson.ParseBytes(b).Get("settled").String() == "true" && bolt11.DescriptionHash == Nip57DescriptionHash(zapEventSerializedStr) {
log.Debug().Str("ZAP", "Published on Nostr").Msg("zapped")
publishNostrEvent(nip57Receipt, nip57ReceiptRelays)
close(quit)
return
if gjson.ParseBytes(b).Get("settled").String() == "true" {
isPaid = true
}
case LNBitsParams:
@@ -240,25 +229,37 @@ func WaitForInvoicePaid(payvalues *lnurl.LNURLPayValues, params *Params) {
}
var jsonMap map[string]interface{}
json.Unmarshal([]byte(string(responseData)), &jsonMap)
//If invoice is paid and DescriptionHash matches Nip57 DescriptionHash, publish Zap Nostr Event
if jsonMap["paid"].(bool) && bolt11.DescriptionHash == Nip57DescriptionHash(zapEventSerializedStr) {
if jsonMap["paid"].(bool) {
isPaid = true
}
case LNPayParams:
//TODO
case EclairParams:
//TODO
case CommandoParams:
//TODO
}
//Timeout waiting for payment after maxiterations
if maxiterations == 0 {
log.Debug().Str("NIP57", bolt11.PaymentHash).Msg("Timed out")
close(quit)
}
//If invoice is paid and DescriptionHash matches Nip57 DescriptionHash, publish Zap Nostr Event. This is rather a sanity check.
if isPaid {
var descriptionTag = *payvalues.nip57Receipt.Tags.GetFirst([]string{"description"})
if bolt11.DescriptionHash == Nip57DescriptionHash(descriptionTag.Value()) {
log.Debug().Str("ZAP", "Published on Nostr").Msg("zapped")
publishNostrEvent(nip57Receipt, nip57ReceiptRelays)
publishNostrEvent(payvalues.nip57Receipt, payvalues.nip57ReceiptRelays)
close(quit)
return
}
case LNPayParams:
case EclairParams:
case CommandoParams:
maxiterations--
}
if maxiterations == 0 {
log.Debug().Str("ZAP", bolt11.PaymentHash).Msg("Timed out")
close(quit)
}
maxiterations--
case <-quit:
ticker.Stop()
return