mirror of
https://github.com/getAlby/lndhub.go.git
synced 2026-02-20 12:24:36 +01:00
Implement addinvoice call
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"net/http"
|
||||
|
||||
"github.com/getAlby/lndhub.go/lib/service"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/gommon/random"
|
||||
)
|
||||
|
||||
// AddInvoiceController : Add invoice controller struct
|
||||
@@ -22,7 +20,7 @@ func NewAddInvoiceController(svc *service.LndhubService) *AddInvoiceController {
|
||||
func (controller *AddInvoiceController) AddInvoice(c echo.Context) error {
|
||||
userID := c.Get("UserID").(int64)
|
||||
type RequestBody struct {
|
||||
Amt uint `json:"amt" validate:"required"`
|
||||
Amt int64 `json:"amt" validate:"required,gte=0"` // amount in Satoshi
|
||||
Memo string `json:"memo"`
|
||||
DescriptionHash string `json:"description_hash"`
|
||||
}
|
||||
@@ -30,41 +28,41 @@ func (controller *AddInvoiceController) AddInvoice(c echo.Context) error {
|
||||
var body RequestBody
|
||||
|
||||
if err := c.Bind(&body); err != nil {
|
||||
c.Logger().Errorf("Failed to load addinvoice request body: %v", err)
|
||||
return c.JSON(http.StatusBadRequest, echo.Map{
|
||||
"message": "failed to bind json, amt field with positive value is required",
|
||||
"error": true,
|
||||
"code": 8,
|
||||
"message": "Bad arguments",
|
||||
})
|
||||
}
|
||||
|
||||
if err := c.Validate(&body); err != nil {
|
||||
c.Logger().Errorf("Invalid addinvoice request body: %v", err)
|
||||
return c.JSON(http.StatusBadRequest, echo.Map{
|
||||
"message": "amt with positive value is required",
|
||||
"error": true,
|
||||
"code": 8,
|
||||
"message": "Bad arguments",
|
||||
})
|
||||
}
|
||||
|
||||
c.Logger().Infof("Adding invoice: user_id=%v memo=%s value=%v description_hash=%s", userID, body.Memo, body.Amt, body.DescriptionHash)
|
||||
|
||||
invoice, err := controller.svc.AddInvoice(userID, body.Amt, body.Memo, body.DescriptionHash)
|
||||
if err != nil {
|
||||
c.Logger().Errorf("error saving an invoice: %v", err)
|
||||
c.Logger().Errorf("Error creating invoice: %v", err)
|
||||
// TODO: sentry notification
|
||||
return c.JSON(http.StatusInternalServerError, nil)
|
||||
}
|
||||
|
||||
var responseBody struct {
|
||||
RHash string `json:"r_hash"`
|
||||
PaymentRequest string `json:"payment_request"`
|
||||
PayReq string `json:"pay_req"`
|
||||
}
|
||||
|
||||
//TODO
|
||||
responseBody.PayReq = makePreimageHex()
|
||||
responseBody.RHash = invoice.RHash
|
||||
responseBody.PaymentRequest = invoice.PaymentRequest
|
||||
responseBody.PayReq = invoice.PaymentRequest
|
||||
|
||||
return c.JSON(http.StatusOK, &responseBody)
|
||||
}
|
||||
|
||||
const hexBytes = random.Hex
|
||||
|
||||
func makePreimageHex() string {
|
||||
b := make([]byte, 32)
|
||||
for i := range b {
|
||||
b[i] = hexBytes[rand.Intn(len(hexBytes))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
@@ -9,20 +9,20 @@ import (
|
||||
|
||||
// Invoice : Invoice Model
|
||||
type Invoice struct {
|
||||
ID uint `json:"id" bun:",pk,autoincrement"`
|
||||
Type string `json:"type"`
|
||||
UserID int64 `json:"user_id"`
|
||||
User *User `bun:"rel:belongs-to,join:user_id=id"`
|
||||
TransactionEntryID uint `json:"transaction_entry_id"`
|
||||
Amount uint `json:"amount"`
|
||||
Memo string `json:"memo"`
|
||||
DescriptionHash string `json:"description_hash"`
|
||||
PaymentRequest string `json:"payment_request"`
|
||||
RHash string `json:"r_hash"`
|
||||
State string `json:"state"`
|
||||
CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"`
|
||||
UpdatedAt bun.NullTime `json:"updated_at"`
|
||||
SettledAt bun.NullTime `json:"settled_at"`
|
||||
ID uint `json:"id" bun:",pk,autoincrement"`
|
||||
Type string `json:"type"`
|
||||
UserID int64 `json:"user_id"`
|
||||
User *User `bun:"rel:belongs-to,join:user_id=id"`
|
||||
Amount int64 `json:"amount"`
|
||||
Memo string `json:"memo"`
|
||||
DescriptionHash string `json:"description_hash"`
|
||||
PaymentRequest string `json:"payment_request"`
|
||||
RHash string `json:"r_hash"`
|
||||
State string `json:"state"`
|
||||
AddIndex uint64 `json:"add_index"`
|
||||
CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"`
|
||||
UpdatedAt bun.NullTime `json:"updated_at"`
|
||||
SettledAt bun.NullTime `json:"settled_at"`
|
||||
}
|
||||
|
||||
func (i *Invoice) BeforeAppendModel(ctx context.Context, query bun.Query) error {
|
||||
|
||||
@@ -2,8 +2,12 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"math/rand"
|
||||
|
||||
"github.com/getAlby/lndhub.go/db/models"
|
||||
"github.com/labstack/gommon/random"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
)
|
||||
|
||||
func (svc *LndhubService) Payinvoice(userId int64, invoice string) error {
|
||||
@@ -27,23 +31,57 @@ func (svc *LndhubService) Payinvoice(userId int64, invoice string) error {
|
||||
|
||||
}
|
||||
|
||||
func (svc *LndhubService) AddInvoice(userID int64, amount uint, memo, descriptionHash string) (*models.Invoice, error) {
|
||||
invoice := &models.Invoice{
|
||||
Type: "",
|
||||
UserID: userID,
|
||||
TransactionEntryID: 0,
|
||||
Amount: amount,
|
||||
Memo: memo,
|
||||
DescriptionHash: descriptionHash,
|
||||
PaymentRequest: "",
|
||||
RHash: "",
|
||||
State: "",
|
||||
func (svc *LndhubService) AddInvoice(userID int64, amount int64, memo, descriptionHash string) (*models.Invoice, error) {
|
||||
// Initialize new DB invoice
|
||||
invoice := models.Invoice{
|
||||
Type: "incoming",
|
||||
UserID: userID,
|
||||
Amount: amount,
|
||||
Memo: memo,
|
||||
DescriptionHash: descriptionHash,
|
||||
State: "initialized",
|
||||
}
|
||||
|
||||
// TODO: move this to a service layer and call a method
|
||||
_, err := svc.DB.NewInsert().Model(invoice).Exec(context.TODO())
|
||||
// Save invoice - we save the invoice early to have a record in case the LN call fails
|
||||
_, err := svc.DB.NewInsert().Model(&invoice).Exec(context.TODO())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return invoice, nil
|
||||
|
||||
// Initialize lnrpc invoice
|
||||
lnInvoice := lnrpc.Invoice{
|
||||
Memo: memo,
|
||||
Value: amount,
|
||||
RPreimage: makePreimageHex(),
|
||||
Expiry: 3600 * 24, // 24h
|
||||
}
|
||||
lndClient := *svc.LndClient
|
||||
// Call LND
|
||||
lnInvoiceResult, err := lndClient.AddInvoice(context.TODO(), &lnInvoice)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update the DB invoice with the data from the LND gRPC call
|
||||
invoice.PaymentRequest = lnInvoiceResult.PaymentRequest
|
||||
invoice.RHash = hex.EncodeToString(lnInvoiceResult.RHash)
|
||||
invoice.AddIndex = lnInvoiceResult.AddIndex
|
||||
invoice.State = "created"
|
||||
|
||||
_, err = svc.DB.NewUpdate().Model(&invoice).WherePK().Exec(context.TODO())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &invoice, nil
|
||||
}
|
||||
|
||||
const hexBytes = random.Hex
|
||||
|
||||
func makePreimageHex() []byte {
|
||||
b := make([]byte, 32)
|
||||
for i := range b {
|
||||
b[i] = hexBytes[rand.Intn(len(hexBytes))]
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user