mirror of
https://github.com/getAlby/hub.git
synced 2026-08-13 12:33:39 +02:00
* feat: add both Sat and Msat companion fields for all ambiguous balance/amount properties * feat: add sat and msat companion fields to backend API responses * chore: align frontend types and other missing fields * chore: keep old formula for calculating total fee sat * chore: remove unnecessary balance assignments in cashu and phoenix * chore: add deprecated comment to non unit fields * chore: rename callers and variable to specify units * chore: remove msat fields for channel size and liquidity fields * chore: drop msat fields from onchain channel size and liquidity responses * chore: further changes * chore: remove amount msat field onchain tx * chore: remove msats from onchain balance response * chore: remove msat fields for swaps * chore: remove msat fields for punishment reserves * chore: simplify rebalancing fee calculation * chore: remove unnecessary fields * chore: mark deprecated fields in frontend types --------- Co-authored-by: im-adithya <imadithyavardhan@gmail.com>
190 lines
5.8 KiB
Go
190 lines
5.8 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/getAlby/hub/logger"
|
|
"github.com/getAlby/hub/transactions"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func (api *api) CreateInvoice(ctx context.Context, amountMsat uint64, description string) (*MakeInvoiceResponse, error) {
|
|
lnClient := api.svc.GetLNClient()
|
|
if lnClient == nil {
|
|
return nil, ErrLNClientNotStarted
|
|
}
|
|
transaction, err := api.svc.GetTransactionsService().MakeInvoice(ctx, amountMsat, description, "", 0, nil, lnClient, nil, nil, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return toApiTransaction(transaction), nil
|
|
}
|
|
|
|
func (api *api) LookupInvoice(ctx context.Context, paymentHash string) (*LookupInvoiceResponse, error) {
|
|
lnClient := api.svc.GetLNClient()
|
|
if lnClient == nil {
|
|
return nil, ErrLNClientNotStarted
|
|
}
|
|
transaction, err := api.svc.GetTransactionsService().LookupTransaction(ctx, paymentHash, nil, lnClient, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return toApiTransaction(transaction), nil
|
|
}
|
|
|
|
func (api *api) ListTransactions(ctx context.Context, appId *uint, limit uint64, offset uint64) (*ListTransactionsResponse, error) {
|
|
lnClient := api.svc.GetLNClient()
|
|
if lnClient == nil {
|
|
return nil, ErrLNClientNotStarted
|
|
}
|
|
|
|
forceFilterByAppId := false
|
|
if appId != nil {
|
|
forceFilterByAppId = true
|
|
}
|
|
|
|
transactions, totalCount, err := api.svc.GetTransactionsService().ListTransactions(ctx, 0, 0, limit, offset, true, false, nil, lnClient, appId, forceFilterByAppId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
apiTransactions := []Transaction{}
|
|
for _, transaction := range transactions {
|
|
apiTransactions = append(apiTransactions, *toApiTransaction(&transaction))
|
|
}
|
|
|
|
return &ListTransactionsResponse{
|
|
Transactions: apiTransactions,
|
|
TotalCount: totalCount,
|
|
}, nil
|
|
}
|
|
|
|
func (api *api) SendPayment(ctx context.Context, invoice string, amountMsat *uint64, metadata map[string]interface{}) (*SendPaymentResponse, error) {
|
|
lnClient := api.svc.GetLNClient()
|
|
if lnClient == nil {
|
|
return nil, ErrLNClientNotStarted
|
|
}
|
|
|
|
transaction, err := api.svc.GetTransactionsService().SendPaymentSync(invoice, amountMsat, metadata, lnClient, nil, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return toApiTransaction(transaction), nil
|
|
}
|
|
|
|
func toApiTransaction(transaction *transactions.Transaction) *Transaction {
|
|
|
|
updatedAt := transaction.UpdatedAt.Format(time.RFC3339)
|
|
createdAt := transaction.CreatedAt.Format(time.RFC3339)
|
|
var settledAt *string
|
|
var preimage *string
|
|
if transaction.SettledAt != nil {
|
|
settledAtValue := transaction.SettledAt.Format(time.RFC3339)
|
|
settledAt = &settledAtValue
|
|
preimage = transaction.Preimage
|
|
}
|
|
|
|
var metadata Metadata
|
|
if transaction.Metadata != nil {
|
|
jsonErr := json.Unmarshal(transaction.Metadata, &metadata)
|
|
if jsonErr != nil {
|
|
logger.Logger.WithError(jsonErr).WithFields(logrus.Fields{
|
|
"payment_hash": transaction.PaymentHash,
|
|
"metadata": transaction.Metadata,
|
|
}).Error("Failed to deserialize transaction metadata")
|
|
}
|
|
}
|
|
|
|
var boostagram *Boostagram
|
|
if transaction.Boostagram != nil {
|
|
var txBoostagram transactions.Boostagram
|
|
jsonErr := json.Unmarshal(transaction.Boostagram, &txBoostagram)
|
|
if jsonErr != nil {
|
|
logger.Logger.WithError(jsonErr).WithFields(logrus.Fields{
|
|
"payment_hash": transaction.PaymentHash,
|
|
"boostagram": transaction.Boostagram,
|
|
}).Error("Failed to deserialize transaction boostagram info")
|
|
}
|
|
boostagram = toApiBoostagram(&txBoostagram)
|
|
}
|
|
|
|
return &Transaction{
|
|
Type: transaction.Type,
|
|
State: strings.ToLower(transaction.State),
|
|
Invoice: transaction.PaymentRequest,
|
|
Description: transaction.Description,
|
|
DescriptionHash: transaction.DescriptionHash,
|
|
Preimage: preimage,
|
|
PaymentHash: transaction.PaymentHash,
|
|
Amount: transaction.AmountMsat,
|
|
AmountSat: transaction.AmountMsat / 1000,
|
|
AmountMsat: transaction.AmountMsat,
|
|
AppId: transaction.AppId,
|
|
FeesPaid: transaction.FeeMsat,
|
|
FeesPaidSat: transaction.FeeMsat / 1000,
|
|
FeesPaidMsat: transaction.FeeMsat,
|
|
UpdatedAt: updatedAt,
|
|
CreatedAt: createdAt,
|
|
SettledAt: settledAt,
|
|
Metadata: metadata,
|
|
Boostagram: boostagram,
|
|
FailureReason: transaction.FailureReason,
|
|
}
|
|
}
|
|
|
|
func (api *api) Transfer(ctx context.Context, fromAppId *uint, toAppId *uint, amountMsat uint64, description string) error {
|
|
lnClient := api.svc.GetLNClient()
|
|
if lnClient == nil {
|
|
return ErrLNClientNotStarted
|
|
}
|
|
|
|
for _, appId := range []*uint{fromAppId, toAppId} {
|
|
if appId != nil {
|
|
dbApp := api.appsSvc.GetAppById(*appId)
|
|
if dbApp == nil {
|
|
return errors.New("app does not exist")
|
|
}
|
|
if !dbApp.Isolated {
|
|
return errors.New("app is not isolated")
|
|
}
|
|
}
|
|
}
|
|
|
|
// default to "transfer"
|
|
if description == "" {
|
|
description = "transfer"
|
|
}
|
|
|
|
transaction, err := api.svc.GetTransactionsService().MakeInvoice(ctx, amountMsat, description, "", 0, nil, lnClient, toAppId, nil, nil)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = api.svc.GetTransactionsService().SendPaymentSync(transaction.PaymentRequest, nil, nil, lnClient, fromAppId, nil)
|
|
return err
|
|
}
|
|
|
|
func toApiBoostagram(boostagram *transactions.Boostagram) *Boostagram {
|
|
return &Boostagram{
|
|
AppName: boostagram.AppName,
|
|
Name: boostagram.Name,
|
|
Podcast: boostagram.Podcast,
|
|
URL: boostagram.URL,
|
|
Episode: boostagram.Episode.String(),
|
|
FeedId: boostagram.FeedId.String(),
|
|
ItemId: boostagram.ItemId.String(),
|
|
Timestamp: boostagram.Timestamp,
|
|
Message: boostagram.Message,
|
|
SenderId: boostagram.SenderId.String(),
|
|
SenderName: boostagram.SenderName,
|
|
Time: boostagram.Time,
|
|
Action: boostagram.Action,
|
|
ValueSatTotal: boostagram.ValueMsatTotal / 1000,
|
|
ValueMsatTotal: boostagram.ValueMsatTotal,
|
|
}
|
|
}
|