delphi.market/lnd/invoice.go

127 lines
3.3 KiB
Go

package lnd
import (
"context"
"log"
"time"
"git.ekzyis.com/ekzyis/delphi.market/db"
"github.com/lightninglabs/lndclient"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
)
func (lnd *LNDClient) CreateInvoice(d *db.DB, pubkey string, msats int64, description string) (*db.Invoice, error) {
var (
expiry time.Duration = time.Hour
preimage lntypes.Preimage
hash lntypes.Hash
paymentRequest string
lnInvoice *lndclient.Invoice
dbInvoice *db.Invoice
err error
)
if preimage, err = generateNewPreimage(); err != nil {
return nil, err
}
hash = preimage.Hash()
if paymentRequest, err = lnd.Invoices.AddHoldInvoice(context.TODO(), &invoicesrpc.AddInvoiceData{
Hash: &hash,
Value: lnwire.MilliSatoshi(msats),
Expiry: int64(expiry / time.Millisecond),
}); err != nil {
return nil, err
}
if lnInvoice, err = lnd.Client.LookupInvoice(context.TODO(), hash); err != nil {
return nil, err
}
dbInvoice = &db.Invoice{
Pubkey: pubkey,
Msats: msats,
Preimage: preimage.String(),
PaymentRequest: paymentRequest,
Hash: hash.String(),
CreatedAt: lnInvoice.CreationDate,
ExpiresAt: lnInvoice.CreationDate.Add(expiry),
Description: description,
}
if err := d.CreateInvoice(dbInvoice); err != nil {
return nil, err
}
return dbInvoice, nil
}
func (lnd *LNDClient) CheckInvoice(d *db.DB, hash lntypes.Hash) {
var (
pollInterval = 5 * time.Second
invoice db.Invoice
lnInvoice *lndclient.Invoice
preimage lntypes.Preimage
err error
)
if err = d.FetchInvoice(&db.FetchInvoiceWhere{Hash: hash.String()}, &invoice); err != nil {
log.Println(err)
return
}
handleLoopError := func(err error) {
log.Println(err)
time.Sleep(pollInterval)
}
for {
log.Printf("lookup invoice: hash=%s", hash)
if lnInvoice, err = lnd.Client.LookupInvoice(context.TODO(), hash); err != nil {
handleLoopError(err)
continue
}
if time.Now().After(invoice.ExpiresAt) {
// cancel invoices after expiration if no matching order found yet
if err = lnd.Invoices.CancelInvoice(context.TODO(), hash); err != nil {
handleLoopError(err)
continue
}
log.Printf("invoice expired: hash=%s", hash)
break
}
if lnInvoice.AmountPaid > 0 {
if preimage, err = lntypes.MakePreimageFromStr(invoice.Preimage); err != nil {
handleLoopError(err)
continue
}
// TODO settle invoice after matching order was found
if err = lnd.Invoices.SettleInvoice(context.TODO(), preimage); err != nil {
handleLoopError(err)
continue
}
if err = d.ConfirmInvoice(hash.String(), time.Now(), int(lnInvoice.AmountPaid)); err != nil {
handleLoopError(err)
continue
}
log.Printf("invoice confirmed: hash=%s", hash)
break
}
time.Sleep(pollInterval)
}
}
func (lnd *LNDClient) CheckInvoices(d *db.DB) error {
var (
invoices []db.Invoice
err error
hash lntypes.Hash
)
if err = d.FetchInvoices(&db.FetchInvoicesWhere{Unconfirmed: true}, &invoices); err != nil {
return err
}
for _, invoice := range invoices {
if hash, err = lntypes.MakeHashFromStr(invoice.Hash); err != nil {
return err
}
go lnd.CheckInvoice(d, hash)
}
return nil
}