162 lines
3.4 KiB
Go
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
|
|
}
|