bit4sat/ln/invoice.go
2019-04-04 02:27:09 +02:00

162 lines
3.4 KiB
Go

package ln
import (
"encoding/hex"
"encoding/json"
"fmt"
"log"
"strconv"
"time"
"github.com/lightningnetwork/lnd/lnrpc"
)
type Currency int
const (
CurMSat Currency = iota
CurSat
CurBTC
CurUSD
CurEur
)
const (
Paid int = iota
UnPaid
Expired
)
var InvoiceStatus = map[int]string{
UnPaid: "unpaid",
Paid: "paid",
Expired: "expired",
}
const (
InfoEndpoint = "info"
InvoiceEndpoint = "invoice"
)
var (
CurrencyString = map[Currency]string{
CurUSD: "USD",
CurSat: "SAT",
CurBTC: "BTC",
CurMSat: "MSAT",
CurEur: "EUR",
}
CurrencyID = map[string]Currency{
"USD": CurUSD,
"SAT": CurSat,
"MSAT": CurMSat,
"BTC": CurBTC,
"EUR": CurEur,
}
)
type timestamp time.Time
func (t *timestamp) UnmarshalJSON(in []byte) error {
if string(in) == "null" {
*t = timestamp(time.Unix(0, 0))
return nil
}
val, err := strconv.Atoi(string(in))
if err != nil {
return fmt.Errorf("cannot unmarshal timestamp int")
}
parsedTime := time.Unix(int64(val), 0)
*t = timestamp(parsedTime)
return nil
}
func (t timestamp) MarshalJSON() ([]byte, error) {
str := strconv.Itoa(int(time.Time(t).Unix()))
return []byte(str), nil
}
func (t timestamp) String() string {
return time.Time(t).Format(time.RFC3339)
}
type Invoice struct {
AddIndex uint64 `json:"-"`
SettleIndex uint64 `json:"-"`
Description string `json:"description"`
Msatoshi float64 `json:"msatoshi"`
Payreq string `json:"payreq"`
RHash string `json:"rhash"`
PreImage string `json:"-"` // used as secret admin token
Status string `json:"status"`
PaidAt timestamp `json:"paid_at"`
CreatedAt timestamp `json:"created_at"`
ExpiresAt timestamp `json:"expires_at"`
Expired bool `json:"-"`
QuotedCurrency string `json:"quoted_currency"`
QuotedAmount float64 `json:"quoted_amount"`
}
func (i Invoice) MarshalBinary() ([]byte, error) {
return json.Marshal(i)
}
func (i *Invoice) UnmarshalBinary(b []byte) error {
return json.Unmarshal(b, &i)
}
// Create new Invoice from lnrpc.Invoice
func InvoiceFromLndIn(lndInvoice *lnrpc.Invoice) *Invoice {
log.Println(hex.EncodeToString(lndInvoice.RPreimage))
invoice := Invoice{
AddIndex: lndInvoice.AddIndex,
Description: lndInvoice.GetMemo(),
Msatoshi: float64(lndInvoice.Value * 1000),
Payreq: lndInvoice.PaymentRequest,
RHash: hex.EncodeToString(lndInvoice.RHash),
PreImage: hex.EncodeToString(lndInvoice.RPreimage),
CreatedAt: timestamp(time.Unix(lndInvoice.CreationDate, 0)),
Status: InvoiceStatus[UnPaid],
}
invoice.ExpiresAt = timestamp(time.Time(invoice.CreatedAt).Add(time.Second * time.Duration(lndInvoice.Expiry)))
// Calculate status
if lndInvoice.Settled {
invoice.Status = InvoiceStatus[Paid]
}
if time.Now().After(time.Time(invoice.ExpiresAt)) {
invoice.Status = InvoiceStatus[Expired]
invoice.Expired = true
}
return &invoice
}
// Update stored invoice from lnd invoice
func UpdateInvoiceFromLnd(storedIn *Invoice, newIn *lnrpc.Invoice) *Invoice {
storedIn.SettleIndex = newIn.SettleIndex
storedIn.PaidAt = timestamp(time.Unix(newIn.SettleDate, 0))
// Calculate status
if newIn.Settled {
storedIn.Status = InvoiceStatus[Paid]
}
// Handle expired status
if time.Now().After(time.Time(storedIn.ExpiresAt)) {
storedIn.Status = InvoiceStatus[Expired]
storedIn.Expired = true
}
return storedIn
}