feat: suffix balance/amount fields with explicit unit (Sat or Msat) (#2153)

* 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>
This commit is contained in:
Anshuman 2026-04-17 13:53:28 +05:30 committed by GitHub
parent 46d3a8942a
commit 1d3f9ecd41
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 512 additions and 304 deletions

View file

@ -525,7 +525,7 @@ func (svc *albyOAuthService) UnlinkAccount(ctx context.Context) error {
return nil
}
func (svc *albyOAuthService) LinkAccount(ctx context.Context, lnClient lnclient.LNClient, budget uint64, renewal string) error {
func (svc *albyOAuthService) LinkAccount(ctx context.Context, lnClient lnclient.LNClient, budgetSat uint64, renewal string) error {
if lnClient == nil {
return errors.New("LNClient not available")
}
@ -551,7 +551,7 @@ func (svc *albyOAuthService) LinkAccount(ctx context.Context, lnClient lnclient.
app, _, err := apps.NewAppsService(svc.db, svc.eventPublisher, svc.keys, svc.cfg).CreateApp(
ALBY_ACCOUNT_APP_NAME,
connectionPubkey,
budget,
budgetSat,
renewal,
nil,
scopes,
@ -1325,11 +1325,11 @@ func (svc *albyOAuthService) requestAutoChannel(ctx context.Context, url string,
}
var invoice string
var fee uint64
var feeSat uint64
if newAutoChannelResponse.Payment != nil {
invoice = newAutoChannelResponse.Payment.Bolt11.Invoice
fee, err = strconv.ParseUint(newAutoChannelResponse.Payment.Bolt11.FeeTotalSat, 10, 64)
feeSat, err = strconv.ParseUint(newAutoChannelResponse.Payment.Bolt11.FeeTotalSat, 10, 64)
if err != nil {
logger.Logger.WithError(err).WithFields(logrus.Fields{
"url": url,
@ -1343,16 +1343,16 @@ func (svc *albyOAuthService) requestAutoChannel(ctx context.Context, url string,
return nil, err
}
if fee != uint64(paymentRequest.MSatoshi/1000) {
if feeSat != uint64(paymentRequest.MSatoshi/1000) {
logger.Logger.WithFields(logrus.Fields{
"invoice_amount": paymentRequest.MSatoshi / 1000,
"fee": fee,
"fee": feeSat,
}).WithError(err).Error("Invoice amount does not match LSP fee")
return nil, errors.New("invoice amount does not match LSP fee")
}
}
channelSize, err := strconv.ParseUint(newAutoChannelResponse.LspBalanceSat, 10, 64)
channelSizeSat, err := strconv.ParseUint(newAutoChannelResponse.LspBalanceSat, 10, 64)
if err != nil {
logger.Logger.WithError(err).WithFields(logrus.Fields{
"url": url,
@ -1361,9 +1361,11 @@ func (svc *albyOAuthService) requestAutoChannel(ctx context.Context, url string,
}
return &AutoChannelResponse{
Invoice: invoice,
Fee: fee,
ChannelSize: channelSize,
Invoice: invoice,
Fee: feeSat,
FeeSat: feeSat,
ChannelSize: channelSizeSat,
ChannelSizeSat: channelSizeSat,
}, nil
}

View file

@ -170,6 +170,11 @@ func (svc *albyService) GetChannelPeerSuggestions(ctx context.Context) ([]Channe
return nil, err
}
for i := range suggestions {
suggestions[i].MinimumChannelSizeSat = suggestions[i].MinimumChannelSize
suggestions[i].MaximumChannelSizeSat = suggestions[i].MaximumChannelSize
}
logger.Logger.WithFields(logrus.Fields{"channel_suggestions": suggestions}).Debug("Alby channel peer suggestions response")
return suggestions, nil
}

View file

@ -23,7 +23,7 @@ type AlbyOAuthService interface {
GetUserIdentifier() (string, error)
GetLightningAddress() (string, error)
IsConnected(ctx context.Context) bool
LinkAccount(ctx context.Context, lnClient lnclient.LNClient, budget uint64, renewal string) error
LinkAccount(ctx context.Context, lnClient lnclient.LNClient, budgetSat uint64, renewal string) error
CallbackHandler(ctx context.Context, code string) error
GetMe(ctx context.Context) (*AlbyMe, error)
UnlinkAccount(ctx context.Context) error
@ -49,9 +49,11 @@ type AutoChannelRequest struct {
}
type AutoChannelResponse struct {
Invoice string `json:"invoice"`
ChannelSize uint64 `json:"channelSize"`
Fee uint64 `json:"fee"`
Invoice string `json:"invoice"`
ChannelSize uint64 `json:"channelSize"` // deprecated
ChannelSizeSat uint64 `json:"channelSizeSat"`
Fee uint64 `json:"fee"` // deprecated
FeeSat uint64 `json:"feeSat"`
}
type AlbyInfoHub struct {
@ -102,8 +104,10 @@ type ChannelPeerSuggestion struct {
PaymentMethod string `json:"paymentMethod"`
Pubkey string `json:"pubkey"`
Host string `json:"host"`
MinimumChannelSize uint64 `json:"minimumChannelSize"`
MaximumChannelSize uint64 `json:"maximumChannelSize"`
MinimumChannelSize uint64 `json:"minimumChannelSize"` // deprecated
MinimumChannelSizeSat uint64 `json:"minimumChannelSizeSat"`
MaximumChannelSize uint64 `json:"maximumChannelSize"` // deprecated
MaximumChannelSizeSat uint64 `json:"maximumChannelSizeSat"`
MaximumChannelExpiryBlocks *uint32 `json:"maximumChannelExpiryBlocks"`
Name string `json:"name"`
Image string `json:"image"`

View file

@ -210,7 +210,7 @@ func (api *api) UpdateApp(userApp *db.App, updateAppRequest *UpdateAppRequest) e
updateAppRequest.BudgetRenewal != nil || updateAppRequest.ExpiresAt != nil || updateAppRequest.UpdateExpiresAt {
// Get current values or use provided ones
var maxAmount uint64
var maxAmountSat uint64
var budgetRenewal string
var expiresAt *time.Time
@ -225,7 +225,7 @@ func (api *api) UpdateApp(userApp *db.App, updateAppRequest *UpdateAppRequest) e
// Find pay_invoice permission for budget-related fields
for _, perm := range existingPermissions {
if perm.Scope == constants.PAY_INVOICE_SCOPE {
maxAmount = uint64(perm.MaxAmountSat)
maxAmountSat = uint64(perm.MaxAmountSat)
budgetRenewal = perm.BudgetRenewal
expiresAt = perm.ExpiresAt
break
@ -235,7 +235,7 @@ func (api *api) UpdateApp(userApp *db.App, updateAppRequest *UpdateAppRequest) e
// Override with provided values
if updateAppRequest.MaxAmountSat != nil {
maxAmount = *updateAppRequest.MaxAmountSat
maxAmountSat = *updateAppRequest.MaxAmountSat
}
if updateAppRequest.BudgetRenewal != nil {
budgetRenewal = *updateAppRequest.BudgetRenewal
@ -254,7 +254,7 @@ func (api *api) UpdateApp(userApp *db.App, updateAppRequest *UpdateAppRequest) e
// Update existing permissions with new budget and expiry
err := tx.Model(&db.AppPermission{}).Where("app_id", userApp.ID).Updates(map[string]interface{}{
"ExpiresAt": expiresAt,
"MaxAmountSat": maxAmount,
"MaxAmountSat": maxAmountSat,
"BudgetRenewal": budgetRenewal,
}).Error
if err != nil {
@ -284,7 +284,7 @@ func (api *api) UpdateApp(userApp *db.App, updateAppRequest *UpdateAppRequest) e
App: *userApp,
Scope: scope,
ExpiresAt: expiresAt,
MaxAmountSat: int(maxAmount),
MaxAmountSat: int(maxAmountSat),
BudgetRenewal: budgetRenewal,
}
if err := tx.Create(&perm).Error; err != nil {
@ -429,8 +429,8 @@ func (api *api) GetApp(dbApp *db.App) (*App, error) {
}
// renewsIn := ""
maxAmount := uint64(paySpecificPermission.MaxAmountSat)
budgetUsage, err := queries.GetBudgetUsage(api.db, &paySpecificPermission)
maxAmountSat := uint64(paySpecificPermission.MaxAmountSat)
budgetUsageMsat, err := queries.GetBudgetUsageMsat(api.db, &paySpecificPermission)
if err != nil {
logger.Logger.WithError(err).WithFields(logrus.Fields{
"app_id": dbApp.ID,
@ -463,9 +463,13 @@ func (api *api) GetApp(dbApp *db.App) (*App, error) {
UpdatedAt: dbApp.UpdatedAt,
AppPubkey: dbApp.AppPubkey,
ExpiresAt: expiresAt,
MaxAmountSat: maxAmount,
MaxAmount: maxAmountSat,
MaxAmountSat: maxAmountSat,
MaxAmountMsat: maxAmountSat * 1000,
Scopes: requestMethods,
BudgetUsage: budgetUsage / 1000,
BudgetUsage: budgetUsageMsat / 1000,
BudgetUsageSat: budgetUsageMsat / 1000,
BudgetUsageMsat: budgetUsageMsat,
BudgetRenewal: paySpecificPermission.BudgetRenewal,
Isolated: dbApp.Isolated,
Metadata: metadata,
@ -476,14 +480,16 @@ func (api *api) GetApp(dbApp *db.App) (*App, error) {
}
if dbApp.Isolated {
balance, err := queries.GetIsolatedBalance(api.db, dbApp.ID)
balanceMsat, err := queries.GetIsolatedBalanceMsat(api.db, dbApp.ID)
if err != nil {
logger.Logger.WithError(err).WithFields(logrus.Fields{
"app_id": dbApp.ID,
}).Error("Failed to get isolated app balance")
return nil, err
}
response.Balance = balance
response.Balance = balanceMsat
response.BalanceSat = balanceMsat / 1000
response.BalanceMsat = balanceMsat
}
return &response, nil
@ -539,13 +545,16 @@ func (api *api) ListApps(limit uint64, offset uint64, filters ListAppsFilters, o
}
var totalBalance *int64
var totalBalanceSat *int64
if filters.SubWallets != nil && *filters.SubWallets {
totalBalanceMsat, err := queries.GetTotalSubwalletBalance(api.db)
totalBalanceMsat, err := queries.GetTotalSubwalletBalanceMsat(api.db)
if err != nil {
logger.Logger.WithError(err).Error("Failed to calculate total subwallet balance")
return nil, err
}
totalBalance = &totalBalanceMsat
totalBalanceSatVal := totalBalanceMsat / 1000
totalBalanceSat = &totalBalanceSatVal
}
query = query.Offset(int(offset)).Limit(int(limit))
@ -597,14 +606,16 @@ func (api *api) ListApps(limit uint64, offset uint64, filters ListAppsFilters, o
}
if dbApp.Isolated {
balance, err := queries.GetIsolatedBalance(api.db, dbApp.ID)
balanceMsat, err := queries.GetIsolatedBalanceMsat(api.db, dbApp.ID)
if err != nil {
logger.Logger.WithError(err).WithFields(logrus.Fields{
"app_id": dbApp.ID,
}).Error("Failed to get isolated app balance")
return nil, err
}
apiApp.Balance = balance
apiApp.Balance = balanceMsat
apiApp.BalanceSat = balanceMsat / 1000
apiApp.BalanceMsat = balanceMsat
}
for _, appPermission := range permissionsMap[dbApp.ID] {
@ -612,15 +623,19 @@ func (api *api) ListApps(limit uint64, offset uint64, filters ListAppsFilters, o
apiApp.ExpiresAt = appPermission.ExpiresAt
if appPermission.Scope == constants.PAY_INVOICE_SCOPE {
apiApp.BudgetRenewal = appPermission.BudgetRenewal
apiApp.MaxAmount = uint64(appPermission.MaxAmountSat)
apiApp.MaxAmountSat = uint64(appPermission.MaxAmountSat)
budgetUsage, err := queries.GetBudgetUsage(api.db, &appPermission)
apiApp.MaxAmountMsat = uint64(appPermission.MaxAmountSat) * 1000
budgetUsageMsat, err := queries.GetBudgetUsageMsat(api.db, &appPermission)
if err != nil {
logger.Logger.WithError(err).WithFields(logrus.Fields{
"app_id": dbApp.ID,
}).Error("Failed to get budget usage for app")
return nil, err
}
apiApp.BudgetUsage = budgetUsage / 1000
apiApp.BudgetUsage = budgetUsageMsat / 1000
apiApp.BudgetUsageSat = budgetUsageMsat / 1000
apiApp.BudgetUsageMsat = budgetUsageMsat
}
}
@ -638,9 +653,11 @@ func (api *api) ListApps(limit uint64, offset uint64, filters ListAppsFilters, o
apiApps = append(apiApps, apiApp)
}
return &ListAppsResponse{
Apps: apiApps,
TotalCount: uint64(totalCount),
TotalBalance: totalBalance,
Apps: apiApps,
TotalCount: uint64(totalCount),
TotalBalance: totalBalance,
TotalBalanceSat: totalBalanceSat,
TotalBalanceMsat: totalBalance,
}, nil
}
@ -676,8 +693,14 @@ func (api *api) ListChannels(ctx context.Context) ([]Channel, error) {
apiChannels = append(apiChannels, Channel{
LocalBalance: channel.LocalBalance,
LocalBalanceSat: channel.LocalBalance / 1000,
LocalBalanceMsat: channel.LocalBalance,
LocalSpendableBalance: channel.LocalSpendableBalance,
LocalSpendableBalanceSat: channel.LocalSpendableBalance / 1000,
LocalSpendableBalanceMsat: channel.LocalSpendableBalance,
RemoteBalance: channel.RemoteBalance,
RemoteBalanceSat: channel.RemoteBalance / 1000,
RemoteBalanceMsat: channel.RemoteBalance,
Id: channel.Id,
RemotePubkey: channel.RemotePubkey,
FundingTxId: channel.FundingTxId,
@ -690,10 +713,12 @@ func (api *api) ListChannels(ctx context.Context) ([]Channel, error) {
ForwardingFeeBaseMsat: channel.ForwardingFeeBaseMsat,
ForwardingFeeProportionalMillionths: channel.ForwardingFeeProportionalMillionths,
UnspendablePunishmentReserve: channel.UnspendablePunishmentReserve,
UnspendablePunishmentReserveSat: channel.UnspendablePunishmentReserve,
CounterpartyUnspendablePunishmentReserve: channel.CounterpartyUnspendablePunishmentReserve,
Error: channel.Error,
IsOutbound: channel.IsOutbound,
Status: status,
CounterpartyUnspendablePunishmentReserveSat: channel.CounterpartyUnspendablePunishmentReserve,
Error: channel.Error,
IsOutbound: channel.IsOutbound,
Status: status,
})
}
@ -828,23 +853,25 @@ func (api *api) GetAutoSwapConfig() (*GetAutoSwapConfigResponse, error) {
}
swapOutEnabled := swapOutBalanceThresholdStr != "" && swapOutAmountStr != ""
var swapOutBalanceThreshold, swapOutAmount uint64
var swapOutBalanceThresholdSat, swapOutAmountSat uint64
if swapOutEnabled {
var err error
if swapOutBalanceThreshold, err = strconv.ParseUint(swapOutBalanceThresholdStr, 10, 64); err != nil {
if swapOutBalanceThresholdSat, err = strconv.ParseUint(swapOutBalanceThresholdStr, 10, 64); err != nil {
return nil, fmt.Errorf("invalid autoswap out balance threshold: %w", err)
}
if swapOutAmount, err = strconv.ParseUint(swapOutAmountStr, 10, 64); err != nil {
if swapOutAmountSat, err = strconv.ParseUint(swapOutAmountStr, 10, 64); err != nil {
return nil, fmt.Errorf("invalid autoswap out amount: %w", err)
}
}
return &GetAutoSwapConfigResponse{
Type: constants.SWAP_TYPE_OUT,
Enabled: swapOutEnabled,
BalanceThreshold: swapOutBalanceThreshold,
SwapAmount: swapOutAmount,
Destination: swapOutDestination,
Type: constants.SWAP_TYPE_OUT,
Enabled: swapOutEnabled,
BalanceThreshold: swapOutBalanceThresholdSat,
BalanceThresholdSat: swapOutBalanceThresholdSat,
SwapAmount: swapOutAmountSat,
SwapAmountSat: swapOutAmountSat,
Destination: swapOutDestination,
}, nil
}
@ -887,7 +914,9 @@ func toApiSwap(swap *swaps.Swap) *Swap {
State: swap.State,
Invoice: swap.Invoice,
SendAmount: swap.SendAmount,
SendAmountSat: swap.SendAmount,
ReceiveAmount: swap.ReceiveAmount,
ReceiveAmountSat: swap.ReceiveAmount,
PaymentHash: swap.PaymentHash,
DestinationAddress: swap.DestinationAddress,
RefundAddress: swap.RefundAddress,
@ -913,11 +942,14 @@ func (api *api) GetSwapInInfo() (*SwapInfoResponse, error) {
}
return &SwapInfoResponse{
AlbyServiceFee: swapInInfo.AlbyServiceFee,
BoltzServiceFee: swapInInfo.BoltzServiceFee,
BoltzNetworkFee: swapInInfo.BoltzNetworkFee,
MinAmount: swapInInfo.MinAmount,
MaxAmount: swapInInfo.MaxAmount,
AlbyServiceFee: swapInInfo.AlbyServiceFee,
BoltzServiceFee: swapInInfo.BoltzServiceFee,
BoltzNetworkFee: swapInInfo.BoltzNetworkFee,
BoltzNetworkFeeSat: swapInInfo.BoltzNetworkFee,
MinAmount: swapInInfo.MinAmount,
MinAmountSat: swapInInfo.MinAmount,
MaxAmount: swapInInfo.MaxAmount,
MaxAmountSat: swapInInfo.MaxAmount,
}, nil
}
@ -932,11 +964,14 @@ func (api *api) GetSwapOutInfo() (*SwapInfoResponse, error) {
}
return &SwapInfoResponse{
AlbyServiceFee: swapOutInfo.AlbyServiceFee,
BoltzServiceFee: swapOutInfo.BoltzServiceFee,
BoltzNetworkFee: swapOutInfo.BoltzNetworkFee,
MinAmount: swapOutInfo.MinAmount,
MaxAmount: swapOutInfo.MaxAmount,
AlbyServiceFee: swapOutInfo.AlbyServiceFee,
BoltzServiceFee: swapOutInfo.BoltzServiceFee,
BoltzNetworkFee: swapOutInfo.BoltzNetworkFee,
BoltzNetworkFeeSat: swapOutInfo.BoltzNetworkFee,
MinAmount: swapOutInfo.MinAmount,
MinAmountSat: swapOutInfo.MinAmount,
MaxAmount: swapOutInfo.MaxAmount,
MaxAmountSat: swapOutInfo.MaxAmount,
}, nil
}
@ -1218,12 +1253,12 @@ func (api *api) SignMessage(ctx context.Context, message string) (*SignMessageRe
}, nil
}
func (api *api) RedeemOnchainFunds(ctx context.Context, toAddress string, amount uint64, feeRate *uint64, sendAll bool) (*RedeemOnchainFundsResponse, error) {
func (api *api) RedeemOnchainFunds(ctx context.Context, toAddress string, amountSat uint64, feeRate *uint64, sendAll bool) (*RedeemOnchainFundsResponse, error) {
lnClient := api.svc.GetLNClient()
if lnClient == nil {
return nil, ErrLNClientNotStarted
}
txId, err := lnClient.RedeemOnchainFunds(ctx, toAddress, amount, feeRate, sendAll)
txId, err := lnClient.RedeemOnchainFunds(ctx, toAddress, amountSat, feeRate, sendAll)
if err != nil {
return nil, err
}
@ -1888,19 +1923,21 @@ func (api *api) GetForwards() (*GetForwardsResponse, error) {
return nil, err
}
var totalOutboundAmount uint64
var totalFeeEarned uint64
var totalOutboundAmountMsat uint64
var totalFeeEarnedMsat uint64
for _, forward := range forwards {
totalOutboundAmount += forward.OutboundAmountForwardedMsat
totalFeeEarned += forward.TotalFeeEarnedMsat
totalOutboundAmountMsat += forward.OutboundAmountForwardedMsat
totalFeeEarnedMsat += forward.TotalFeeEarnedMsat
}
numForwards := len(forwards)
return &GetForwardsResponse{
OutboundAmountForwardedMsat: totalOutboundAmount,
TotalFeeEarnedMsat: totalFeeEarned,
OutboundAmountForwardedSat: totalOutboundAmountMsat / 1000,
OutboundAmountForwardedMsat: totalOutboundAmountMsat,
TotalFeeEarnedSat: totalFeeEarnedMsat / 1000,
TotalFeeEarnedMsat: totalFeeEarnedMsat,
NumForwards: uint64(numForwards),
}, nil
}

View file

@ -57,9 +57,9 @@ func (api *api) RequestLSPOrder(ctx context.Context, request *LSPOrderRequest) (
return nil, err
}
invoice, fee, err := api.requestLSPS1Invoice(ctx, lnClient, request, nodeInfo.Network, nodeInfo.Pubkey, lspInfo.MaxChannelExpiryBlocks, lspInfo.MinRequiredChannelConfirmations, lspInfo.MinFundingConfirmsWithinBlocks)
invoiceAmount := uint64(0)
incomingLiquidity := request.Amount
invoice, feeSat, err := api.requestLSPS1Invoice(ctx, lnClient, request, nodeInfo.Network, nodeInfo.Pubkey, lspInfo.MaxChannelExpiryBlocks, lspInfo.MinRequiredChannelConfirmations, lspInfo.MinFundingConfirmsWithinBlocks)
invoiceAmountSat := uint64(0)
incomingLiquiditySat := request.Amount
if err != nil {
logger.Logger.WithError(err).Error("Failed to request invoice")
@ -73,15 +73,19 @@ func (api *api) RequestLSPOrder(ctx context.Context, request *LSPOrderRequest) (
return nil, err
}
invoiceAmount = uint64(paymentRequest.MSatoshi / 1000)
invoiceAmountSat = uint64(paymentRequest.MSatoshi / 1000)
}
newChannelResponse := &LSPOrderResponse{
Invoice: invoice,
Fee: fee,
InvoiceAmount: invoiceAmount,
IncomingLiquidity: incomingLiquidity,
OutgoingLiquidity: uint64(0), // JIT channel no longer supported
Invoice: invoice,
Fee: feeSat,
FeeSat: feeSat,
InvoiceAmount: invoiceAmountSat,
InvoiceAmountSat: invoiceAmountSat,
IncomingLiquidity: incomingLiquiditySat,
IncomingLiquiditySat: incomingLiquiditySat,
OutgoingLiquidity: uint64(0),
OutgoingLiquiditySat: uint64(0),
}
logger.Logger.WithFields(logrus.Fields{
@ -91,7 +95,7 @@ func (api *api) RequestLSPOrder(ctx context.Context, request *LSPOrderRequest) (
return newChannelResponse, nil
}
func (api *api) requestLSPS1Invoice(ctx context.Context, lnClient lnclient.LNClient, request *LSPOrderRequest, network, pubkey string, channelExpiryBlocks uint64, minRequiredChannelConfirmations uint64, minFundingConfirmsWithinBlocks uint64) (invoice string, fee uint64, err error) {
func (api *api) requestLSPS1Invoice(ctx context.Context, lnClient lnclient.LNClient, request *LSPOrderRequest, network, pubkey string, channelExpiryBlocks uint64, minRequiredChannelConfirmations uint64, minFundingConfirmsWithinBlocks uint64) (invoice string, feeSat uint64, err error) {
refundAddress, err := lnClient.GetNewOnchainAddress(ctx)
if err != nil {
logger.Logger.WithError(err).Error("Failed to request onchain address")
@ -155,7 +159,7 @@ func (api *api) requestLSPS1Invoice(ctx context.Context, lnClient lnclient.LNCli
if channelResponse.Payment != nil {
invoice = channelResponse.Payment.Bolt11.Invoice
fee, err = strconv.ParseUint(channelResponse.Payment.Bolt11.FeeTotalSat, 10, 64)
feeSat, err = strconv.ParseUint(channelResponse.Payment.Bolt11.FeeTotalSat, 10, 64)
if err != nil {
logger.Logger.WithError(err).WithFields(logrus.Fields{
"lspIdentifier": request.LSPIdentifier,
@ -164,5 +168,5 @@ func (api *api) requestLSPS1Invoice(ctx context.Context, lnClient lnclient.LNCli
}
}
return invoice, fee, nil
return invoice, feeSat, nil
}

View file

@ -41,12 +41,12 @@ type API interface {
GetNewOnchainAddress(ctx context.Context) (string, error)
GetUnusedOnchainAddress(ctx context.Context) (string, error)
SignMessage(ctx context.Context, message string) (*SignMessageResponse, error)
RedeemOnchainFunds(ctx context.Context, toAddress string, amount uint64, feeRate *uint64, sendAll bool) (*RedeemOnchainFundsResponse, error)
RedeemOnchainFunds(ctx context.Context, toAddress string, amountSat uint64, feeRate *uint64, sendAll bool) (*RedeemOnchainFundsResponse, error)
GetBalances(ctx context.Context) (*BalancesResponse, error)
ListTransactions(ctx context.Context, appId *uint, limit uint64, offset uint64) (*ListTransactionsResponse, error)
ListOnchainTransactions(ctx context.Context) ([]lnclient.OnchainTransaction, error)
SendPayment(ctx context.Context, invoice string, amountMsat *uint64, metadata map[string]interface{}) (*SendPaymentResponse, error)
CreateInvoice(ctx context.Context, amount uint64, description string) (*MakeInvoiceResponse, error)
CreateInvoice(ctx context.Context, amountMsat uint64, description string) (*MakeInvoiceResponse, error)
LookupInvoice(ctx context.Context, paymentHash string) (*LookupInvoiceResponse, error)
RequestMempoolApi(ctx context.Context, endpoint string) (interface{}, error)
GetInfo(ctx context.Context) (*InfoResponse, error)
@ -99,13 +99,19 @@ type App struct {
LastSettledTransactionAt *time.Time `json:"lastSettledTransactionAt"`
ExpiresAt *time.Time `json:"expiresAt"`
Scopes []string `json:"scopes"`
MaxAmountSat uint64 `json:"maxAmount"`
BudgetUsage uint64 `json:"budgetUsage"`
MaxAmount uint64 `json:"maxAmount"` // deprecated
MaxAmountSat uint64 `json:"maxAmountSat"`
MaxAmountMsat uint64 `json:"maxAmountMsat"`
BudgetUsage uint64 `json:"budgetUsage"` // deprecated
BudgetUsageSat uint64 `json:"budgetUsageSat"`
BudgetUsageMsat uint64 `json:"budgetUsageMsat"`
BudgetRenewal string `json:"budgetRenewal"`
Isolated bool `json:"isolated"`
WalletPubkey string `json:"walletPubkey"`
UniqueWalletPubkey bool `json:"uniqueWalletPubkey"`
Balance int64 `json:"balance"`
Balance int64 `json:"balance"` // deprecated
BalanceSat int64 `json:"balanceSat"`
BalanceMsat int64 `json:"balanceMsat"`
Metadata Metadata `json:"metadata,omitempty"`
}
@ -117,9 +123,11 @@ type ListAppsFilters struct {
}
type ListAppsResponse struct {
Apps []App `json:"apps"`
TotalCount uint64 `json:"totalCount"`
TotalBalance *int64 `json:"totalBalance,omitempty"`
Apps []App `json:"apps"`
TotalCount uint64 `json:"totalCount"`
TotalBalance *int64 `json:"totalBalance,omitempty"` // deprecated
TotalBalanceSat *int64 `json:"totalBalanceSat,omitempty"`
TotalBalanceMsat *int64 `json:"totalBalanceMsat,omitempty"`
}
type UpdateAppRequest struct {
@ -177,19 +185,24 @@ type EnableAutoSwapRequest struct {
}
type GetAutoSwapConfigResponse struct {
Type string `json:"type"`
Enabled bool `json:"enabled"`
BalanceThreshold uint64 `json:"balanceThreshold"`
SwapAmount uint64 `json:"swapAmount"`
Destination string `json:"destination"`
Type string `json:"type"`
Enabled bool `json:"enabled"`
BalanceThreshold uint64 `json:"balanceThreshold"` // deprecated
BalanceThresholdSat uint64 `json:"balanceThresholdSat"`
SwapAmount uint64 `json:"swapAmount"` // deprecated
SwapAmountSat uint64 `json:"swapAmountSat"`
Destination string `json:"destination"`
}
type SwapInfoResponse struct {
AlbyServiceFee float64 `json:"albyServiceFee"`
BoltzServiceFee float64 `json:"boltzServiceFee"`
BoltzNetworkFee uint64 `json:"boltzNetworkFee"`
MinAmount uint64 `json:"minAmount"`
MaxAmount uint64 `json:"maxAmount"`
AlbyServiceFee float64 `json:"albyServiceFee"`
BoltzServiceFee float64 `json:"boltzServiceFee"`
BoltzNetworkFee uint64 `json:"boltzNetworkFee"` // deprecated
BoltzNetworkFeeSat uint64 `json:"boltzNetworkFeeSat"`
MinAmount uint64 `json:"minAmount"` // deprecated
MinAmountSat uint64 `json:"minAmountSat"`
MaxAmount uint64 `json:"maxAmount"` // deprecated
MaxAmountSat uint64 `json:"maxAmountSat"`
}
type ListSwapsResponse struct {
@ -203,8 +216,10 @@ type Swap struct {
Type string `json:"type"`
State string `json:"state"`
Invoice string `json:"invoice"`
SendAmount uint64 `json:"sendAmount"`
ReceiveAmount uint64 `json:"receiveAmount"`
SendAmount uint64 `json:"sendAmount"` // deprecated
SendAmountSat uint64 `json:"sendAmountSat"`
ReceiveAmount uint64 `json:"receiveAmount"` // deprecated
ReceiveAmountSat uint64 `json:"receiveAmountSat"`
PaymentHash string `json:"paymentHash"`
DestinationAddress string `json:"destinationAddress"`
RefundAddress string `json:"refundAddress"`
@ -346,7 +361,8 @@ type RebalanceChannelRequest struct {
AmountSat uint64 `json:"amountSat"`
}
type RebalanceChannelResponse struct {
TotalFeeSat uint64 `json:"totalFeeSat"`
TotalFeeSat uint64 `json:"totalFeeSat"`
TotalFeeMsat uint64 `json:"totalFeeMsat"`
}
type RedeemOnchainFundsRequest struct {
@ -381,8 +397,12 @@ type Transaction struct {
DescriptionHash string `json:"descriptionHash"`
Preimage *string `json:"preimage"`
PaymentHash string `json:"paymentHash"`
Amount uint64 `json:"amount"`
FeesPaid uint64 `json:"feesPaid"`
Amount uint64 `json:"amount"` // deprecated
AmountSat uint64 `json:"amountSat"`
AmountMsat uint64 `json:"amountMsat"`
FeesPaid uint64 `json:"feesPaid"` // deprecated
FeesPaidSat uint64 `json:"feesPaidSat"`
FeesPaidMsat uint64 `json:"feesPaidMsat"`
UpdatedAt string `json:"updatedAt"`
CreatedAt string `json:"createdAt"`
SettledAt *string `json:"settledAt"`
@ -408,6 +428,7 @@ type Boostagram struct {
SenderName string `json:"senderName"`
Time string `json:"time"`
Action string `json:"action"`
ValueSatTotal int64 `json:"valueSatTotal"`
ValueMsatTotal int64 `json:"valueMsatTotal"`
}
@ -487,11 +508,15 @@ type LSPOrderRequest struct {
}
type LSPOrderResponse struct {
Invoice string `json:"invoice"`
Fee uint64 `json:"fee"`
InvoiceAmount uint64 `json:"invoiceAmount"`
IncomingLiquidity uint64 `json:"incomingLiquidity"`
OutgoingLiquidity uint64 `json:"outgoingLiquidity"`
Invoice string `json:"invoice"`
Fee uint64 `json:"fee"` // deprecated
FeeSat uint64 `json:"feeSat"`
InvoiceAmount uint64 `json:"invoiceAmount"` // deprecated
InvoiceAmountSat uint64 `json:"invoiceAmountSat"`
IncomingLiquidity uint64 `json:"incomingLiquidity"` // deprecated
IncomingLiquiditySat uint64 `json:"incomingLiquiditySat"`
OutgoingLiquidity uint64 `json:"outgoingLiquidity"` // deprecated
OutgoingLiquiditySat uint64 `json:"outgoingLiquiditySat"`
}
type WalletCapabilitiesResponse struct {
@ -501,25 +526,33 @@ type WalletCapabilitiesResponse struct {
}
type Channel struct {
LocalBalance int64 `json:"localBalance"`
LocalSpendableBalance int64 `json:"localSpendableBalance"`
RemoteBalance int64 `json:"remoteBalance"`
Id string `json:"id"`
RemotePubkey string `json:"remotePubkey"`
FundingTxId string `json:"fundingTxId"`
FundingTxVout uint32 `json:"fundingTxVout"`
Active bool `json:"active"`
Public bool `json:"public"`
InternalChannel interface{} `json:"internalChannel"`
Confirmations *uint32 `json:"confirmations"`
ConfirmationsRequired *uint32 `json:"confirmationsRequired"`
ForwardingFeeBaseMsat uint32 `json:"forwardingFeeBaseMsat"`
ForwardingFeeProportionalMillionths uint32 `json:"forwardingFeeProportionalMillionths"`
UnspendablePunishmentReserve uint64 `json:"unspendablePunishmentReserve"`
CounterpartyUnspendablePunishmentReserve uint64 `json:"counterpartyUnspendablePunishmentReserve"`
Error *string `json:"error"`
Status string `json:"status"`
IsOutbound bool `json:"isOutbound"`
LocalBalance int64 `json:"localBalance"` // deprecated
LocalBalanceSat int64 `json:"localBalanceSat"`
LocalBalanceMsat int64 `json:"localBalanceMsat"`
LocalSpendableBalance int64 `json:"localSpendableBalance"` // deprecated
LocalSpendableBalanceSat int64 `json:"localSpendableBalanceSat"`
LocalSpendableBalanceMsat int64 `json:"localSpendableBalanceMsat"`
RemoteBalance int64 `json:"remoteBalance"` // deprecated
RemoteBalanceSat int64 `json:"remoteBalanceSat"`
RemoteBalanceMsat int64 `json:"remoteBalanceMsat"`
Id string `json:"id"`
RemotePubkey string `json:"remotePubkey"`
FundingTxId string `json:"fundingTxId"`
FundingTxVout uint32 `json:"fundingTxVout"`
Active bool `json:"active"`
Public bool `json:"public"`
InternalChannel interface{} `json:"internalChannel"`
Confirmations *uint32 `json:"confirmations"`
ConfirmationsRequired *uint32 `json:"confirmationsRequired"`
ForwardingFeeBaseMsat uint32 `json:"forwardingFeeBaseMsat"` // expressed only in msat as per Lightning spec
ForwardingFeeProportionalMillionths uint32 `json:"forwardingFeeProportionalMillionths"`
UnspendablePunishmentReserve uint64 `json:"unspendablePunishmentReserve"` // deprecated
UnspendablePunishmentReserveSat uint64 `json:"unspendablePunishmentReserveSat"`
CounterpartyUnspendablePunishmentReserve uint64 `json:"counterpartyUnspendablePunishmentReserve"` // deprecated
CounterpartyUnspendablePunishmentReserveSat uint64 `json:"counterpartyUnspendablePunishmentReserveSat"`
Error *string `json:"error"`
Status string `json:"status"`
IsOutbound bool `json:"isOutbound"`
}
type MigrateNodeStorageRequest struct {
@ -572,7 +605,9 @@ type ExecuteCustomNodeCommandRequest struct {
}
type GetForwardsResponse struct {
OutboundAmountForwardedSat uint64 `json:"outboundAmountForwardedSat"`
OutboundAmountForwardedMsat uint64 `json:"outboundAmountForwardedMsat"`
TotalFeeEarnedSat uint64 `json:"totalFeeEarnedSat"`
TotalFeeEarnedMsat uint64 `json:"totalFeeEarnedMsat"`
NumForwards uint64 `json:"numForwards"`
}

View file

@ -138,7 +138,10 @@ func (api *api) RebalanceChannel(ctx context.Context, rebalanceChannelRequest *R
Properties: map[string]interface{}{},
})
totalFeeMsat := uint64(paymentRequest.MSatoshi) + payRebalanceInvoiceResponse.FeeMsat - rebalanceChannelRequest.AmountSat*1000
return &RebalanceChannelResponse{
TotalFeeSat: uint64(paymentRequest.MSatoshi)/1000 + payRebalanceInvoiceResponse.FeeMsat/1000 - rebalanceChannelRequest.AmountSat,
TotalFeeSat: totalFeeMsat / 1000,
TotalFeeMsat: totalFeeMsat,
}, nil
}

View file

@ -12,12 +12,12 @@ import (
"github.com/sirupsen/logrus"
)
func (api *api) CreateInvoice(ctx context.Context, amount uint64, description string) (*MakeInvoiceResponse, error) {
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, amount, description, "", 0, nil, lnClient, nil, nil, nil)
transaction, err := api.svc.GetTransactionsService().MakeInvoice(ctx, amountMsat, description, "", 0, nil, lnClient, nil, nil, nil)
if err != nil {
return nil, err
}
@ -121,8 +121,12 @@ func toApiTransaction(transaction *transactions.Transaction) *Transaction {
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,
@ -180,6 +184,7 @@ func toApiBoostagram(boostagram *transactions.Boostagram) *Boostagram {
SenderName: boostagram.SenderName,
Time: boostagram.Time,
Action: boostagram.Action,
ValueSatTotal: boostagram.ValueMsatTotal / 1000,
ValueMsatTotal: boostagram.ValueMsatTotal,
}
}

View file

@ -8,7 +8,7 @@ import (
"gorm.io/gorm"
)
func GetBudgetUsage(tx *gorm.DB, appPermission *db.AppPermission) (uint64, error) {
func GetBudgetUsageMsat(tx *gorm.DB, appPermission *db.AppPermission) (uint64, error) {
var result struct {
Sum uint64
}

View file

@ -45,9 +45,9 @@ func TestGetBudgetUsage_IncludesPendingAndSettledOutgoing(t *testing.T) {
FeeReserveMsat: 500,
}).Error)
budgetUsage, err := GetBudgetUsage(svc.DB, appPermission)
budgetUsageMsat, err := GetBudgetUsageMsat(svc.DB, appPermission)
require.NoError(t, err)
assert.Equal(t, uint64(79000), budgetUsage)
assert.Equal(t, uint64(79000), budgetUsageMsat)
}
func TestGetBudgetUsage_ExcludesWrongStateTypeAndApp(t *testing.T) {
@ -104,9 +104,9 @@ func TestGetBudgetUsage_ExcludesWrongStateTypeAndApp(t *testing.T) {
FeeReserveMsat: 0,
}).Error)
budgetUsage, err := GetBudgetUsage(svc.DB, appPermission)
budgetUsageMsat, err := GetBudgetUsageMsat(svc.DB, appPermission)
require.NoError(t, err)
assert.Equal(t, uint64(21000), budgetUsage)
assert.Equal(t, uint64(21000), budgetUsageMsat)
}
func TestGetBudgetUsage_BudgetWindowDaily(t *testing.T) {
@ -146,9 +146,9 @@ func TestGetBudgetUsage_BudgetWindowDaily(t *testing.T) {
CreatedAt: dailyStart.Add(2 * time.Hour),
}).Error)
budgetUsage, err := GetBudgetUsage(svc.DB, appPermissionDaily)
budgetUsageMsat, err := GetBudgetUsageMsat(svc.DB, appPermissionDaily)
require.NoError(t, err)
assert.Equal(t, uint64(42000), budgetUsage)
assert.Equal(t, uint64(42000), budgetUsageMsat)
}
func TestGetBudgetUsage_BudgetWindowWeekly(t *testing.T) {
@ -188,9 +188,9 @@ func TestGetBudgetUsage_BudgetWindowWeekly(t *testing.T) {
CreatedAt: weeklyStart.Add(-1 * time.Hour),
}).Error)
budgetUsage, err := GetBudgetUsage(svc.DB, appPermissionWeekly)
budgetUsageMsat, err := GetBudgetUsageMsat(svc.DB, appPermissionWeekly)
require.NoError(t, err)
assert.Equal(t, uint64(11000), budgetUsage)
assert.Equal(t, uint64(11000), budgetUsageMsat)
}
func TestGetBudgetUsage_BudgetWindowNever(t *testing.T) {
@ -228,7 +228,7 @@ func TestGetBudgetUsage_BudgetWindowNever(t *testing.T) {
CreatedAt: time.Now().AddDate(-1, 0, 0),
}).Error)
budgetUsage, err := GetBudgetUsage(svc.DB, appPermission)
budgetUsageMsat, err := GetBudgetUsageMsat(svc.DB, appPermission)
require.NoError(t, err)
assert.Equal(t, uint64(11000), budgetUsage)
assert.Equal(t, uint64(11000), budgetUsageMsat)
}

View file

@ -5,7 +5,7 @@ import (
"gorm.io/gorm"
)
func GetIsolatedBalance(tx *gorm.DB, appId uint) (int64, error) {
func GetIsolatedBalanceMsat(tx *gorm.DB, appId uint) (int64, error) {
var received struct {
Sum int64
}

View file

@ -36,9 +36,9 @@ func TestGetIsolatedBalance_PendingNoOverflow(t *testing.T) {
}
svc.DB.Save(&tx)
balance, err := GetIsolatedBalance(svc.DB, app.ID)
balanceMsat, err := GetIsolatedBalanceMsat(svc.DB, app.ID)
require.NoError(t, err)
assert.Equal(t, int64(-11000), balance)
assert.Equal(t, int64(-11000), balanceMsat)
}
func TestGetIsolatedBalance_SettledNoOverflow(t *testing.T) {
@ -66,7 +66,7 @@ func TestGetIsolatedBalance_SettledNoOverflow(t *testing.T) {
}
svc.DB.Save(&tx)
balance, err := GetIsolatedBalance(svc.DB, app.ID)
balanceMsat, err := GetIsolatedBalanceMsat(svc.DB, app.ID)
require.NoError(t, err)
assert.Equal(t, int64(-1000), balance)
assert.Equal(t, int64(-1000), balanceMsat)
}

View file

@ -7,7 +7,7 @@ import (
"gorm.io/gorm"
)
func GetTotalSubwalletBalance(tx *gorm.DB) (int64, error) {
func GetTotalSubwalletBalanceMsat(tx *gorm.DB) (int64, error) {
subwalletAppIDsQuery := tx.Model(&db.App{}).
Select("id").
Where(datatypes.JSONQuery("metadata").Equals(constants.SUBWALLET_APPSTORE_APP_ID, constants.METADATA_APPSTORE_APP_ID_KEY))

View file

@ -58,7 +58,7 @@ func TestGetTotalSubwalletBalance(t *testing.T) {
}
svc.DB.Save(&outgoingPendingSubwalletTx)
total, err := GetTotalSubwalletBalance(svc.DB)
totalBalanceMsat, err := GetTotalSubwalletBalanceMsat(svc.DB)
require.NoError(t, err)
assert.Equal(t, int64(1600), total)
assert.Equal(t, int64(1600), totalBalanceMsat)
}

View file

@ -106,7 +106,9 @@ function NewChannelInternal({
network,
paymentMethod: "onchain",
minimumChannelSize: 0,
minimumChannelSizeSat: 0,
maximumChannelSize: 0,
maximumChannelSizeSat: 0,
description: "",
pubkey: "",
host: "",

View file

@ -121,11 +121,17 @@ export interface App {
lastSettledTransactionAt?: string;
expiresAt?: string;
isolated: boolean;
balance: number;
balance: number; // @depreated
balanceSat: number;
balanceMsat: number;
scopes: Scope[];
maxAmount: number;
budgetUsage: number;
maxAmount: number; // @depreated
maxAmountSat: number;
maxAmountMsat: number;
budgetUsage: number; // @depreated
budgetUsageSat: number;
budgetUsageMsat: number;
budgetRenewal: BudgetRenewalType;
metadata?: AppMetadata;
}
@ -203,22 +209,28 @@ export type AppMetadata = {
export type AutoSwapConfig = {
type: "out";
enabled: boolean;
balanceThreshold: number;
swapAmount: number;
balanceThreshold: number; // @depreated
balanceThresholdSat: number;
swapAmount: number; // @depreated
swapAmountSat: number;
destination: string;
};
export type SwapInfo = {
albyServiceFee: number;
boltzServiceFee: number;
boltzNetworkFee: number;
minAmount: number;
maxAmount: number;
boltzNetworkFee: number; // @depreated
boltzNetworkFeeSat: number;
minAmount: number; // @depreated
minAmountSat: number;
maxAmount: number; // @depreated
maxAmountSat: number;
};
export type BaseSwap = {
id: string;
sendAmount: number;
sendAmount: number; // @depreated
sendAmountSat: number;
lockupAddress: string;
paymentHash: string;
invoice: string;
@ -229,7 +241,8 @@ export type BaseSwap = {
updatedAt: string;
lockupTxId?: string;
claimTxId?: string;
receiveAmount?: number;
receiveAmount?: number; // @depreated
receiveAmountSat?: number;
};
export type SwapIn = BaseSwap & {
@ -292,9 +305,15 @@ export type UpdateAppRequest = {
};
export type Channel = {
localBalance: number;
localSpendableBalance: number;
remoteBalance: number;
localBalance: number; // @depreated
localBalanceSat: number;
localBalanceMsat: number;
localSpendableBalance: number; // @depreated
localSpendableBalanceSat: number;
localSpendableBalanceMsat: number;
remoteBalance: number; // @depreated
remoteBalanceSat: number;
remoteBalanceMsat: number;
remotePubkey: string;
id: string;
fundingTxId: string;
@ -305,8 +324,10 @@ export type Channel = {
confirmationsRequired?: number;
forwardingFeeBaseMsat: number;
forwardingFeeProportionalMillionths: number;
unspendablePunishmentReserve: number;
counterpartyUnspendablePunishmentReserve: number;
unspendablePunishmentReserve: number; // @depreated
unspendablePunishmentReserveSat: number;
counterpartyUnspendablePunishmentReserve: number; // @depreated
counterpartyUnspendablePunishmentReserveSat: number;
error?: string;
status: "online" | "opening" | "offline";
isOutbound: boolean;
@ -374,16 +395,21 @@ export type CloseChannelResponse = {};
export type PendingBalancesDetails = {
channelId: string;
nodeId: string;
amount: number;
amount: number; // @depreated
amountSat: number;
fundingTxId: string;
fundingTxVout: number;
};
export type OnchainBalanceResponse = {
spendable: number;
total: number;
reserved: number;
pendingBalancesFromChannelClosures: number;
spendable: number; // @depreated
spendableSat: number;
total: number; // @depreated
totalSat: number;
reserved: number; // @depreated
reservedSat: number;
pendingBalancesFromChannelClosures: number; // @depreated
pendingBalancesFromChannelClosuresSat: number;
pendingBalancesDetails: PendingBalancesDetails[];
pendingSweepBalancesDetails: PendingBalancesDetails[];
};
@ -469,8 +495,10 @@ export type RecommendedChannelPeer = {
network: Network;
image: string;
name: string;
minimumChannelSize: number;
maximumChannelSize: number;
minimumChannelSize: number; // @depreated
minimumChannelSizeSat: number;
maximumChannelSize: number; // @depreated
maximumChannelSizeSat: number;
note: string;
publicChannelsAllowed: boolean;
description: string;
@ -546,10 +574,14 @@ export type LSPOrderRequest = {
export type LSPOrderResponse = {
invoice?: string;
fee: number;
invoiceAmount: number;
incomingLiquidity: number;
outgoingLiquidity: number;
fee: number; // @depreated
feeSat: number;
invoiceAmount: number; // @depreated
invoiceAmountSat: number;
incomingLiquidity: number; // @depreated
incomingLiquiditySat: number;
outgoingLiquidity: number; // @depreated
outgoingLiquiditySat: number;
};
export type AutoChannelRequest = {
@ -557,8 +589,10 @@ export type AutoChannelRequest = {
};
export type AutoChannelResponse = {
invoice?: string;
fee?: number;
channelSize: number;
fee?: number; // @depreated
feeSat?: number;
channelSize: number; // @depreated
channelSizeSat: number;
};
export type RedeemOnchainFundsResponse = {
@ -566,12 +600,24 @@ export type RedeemOnchainFundsResponse = {
};
export type LightningBalanceResponse = {
totalSpendable: number;
totalReceivable: number;
nextMaxSpendable: number;
nextMaxReceivable: number;
nextMaxSpendableMPP: number;
nextMaxReceivableMPP: number;
totalSpendable: number; // @depreated
totalSpendableSat: number;
totalSpendableMsat: number;
totalReceivable: number; // @depreated
totalReceivableSat: number;
totalReceivableMsat: number;
nextMaxSpendable: number; // @depreated
nextMaxSpendableSat: number;
nextMaxSpendableMsat: number;
nextMaxReceivable: number; // @depreated
nextMaxReceivableSat: number;
nextMaxReceivableMsat: number;
nextMaxSpendableMPP: number; // @depreated
nextMaxSpendableMPPSat: number;
nextMaxSpendableMPPMsat: number;
nextMaxReceivableMPP: number; // @depreated
nextMaxReceivableMPPSat: number;
nextMaxReceivableMPPMsat: number;
};
export type BalancesResponse = {
@ -588,8 +634,12 @@ export type Transaction = {
descriptionHash: string;
preimage: string | undefined;
paymentHash: string;
amount: number;
feesPaid: number;
amount: number; // @depreated
amountSat: number;
amountMsat: number;
feesPaid: number; // @depreated
feesPaidSat: number;
feesPaidMsat: number;
updatedAt: string;
createdAt: string;
settledAt: string | undefined;
@ -633,11 +683,13 @@ export type Boostagram = {
senderName: string;
time: string;
action: "boost";
valueSatTotal: number;
valueMsatTotal: number;
};
export type OnchainTransaction = {
amountSat: number;
amountMsat: number;
createdAt: number;
type: "incoming" | "outgoing";
state: "confirmed" | "unconfirmed";
@ -648,7 +700,9 @@ export type OnchainTransaction = {
export type ListAppsResponse = {
apps: App[];
totalCount: number;
totalBalance?: number;
totalBalance?: number; // @depreated
totalBalanceSat?: number;
totalBalanceMsat?: number;
};
export type ListTransactionsResponse = {
@ -685,7 +739,9 @@ export type AuthTokenResponse = {
};
export type GetForwardsResponse = {
outboundAmountForwardedSat: number;
outboundAmountForwardedMsat: number;
totalFeeEarnedSat: number;
totalFeeEarnedMsat: number;
numForwards: number;
};

View file

@ -187,10 +187,7 @@ func (cs *CashuService) GetNewOnchainAddress(ctx context.Context) (string, error
}
func (cs *CashuService) GetOnchainBalance(ctx context.Context) (*lnclient.OnchainBalanceResponse, error) {
return &lnclient.OnchainBalanceResponse{
Spendable: 0,
Total: 0,
}, nil
return &lnclient.OnchainBalanceResponse{}, nil
}
func (cs *CashuService) RedeemOnchainFunds(ctx context.Context, toAddress string, amount uint64, feeRate *uint64, sendAll bool) (string, error) {
@ -267,16 +264,18 @@ func (cs *CashuService) GetBalances(ctx context.Context, includeInactiveChannels
return &lnclient.BalancesResponse{
Onchain: lnclient.OnchainBalanceResponse{
Spendable: 0,
Total: 0,
},
PendingBalancesDetails: []lnclient.PendingBalanceDetails{},
PendingSweepBalancesDetails: []lnclient.PendingBalanceDetails{}},
Lightning: lnclient.LightningBalanceResponse{
TotalSpendable: balance,
TotalReceivable: 0,
NextMaxSpendable: balance,
NextMaxReceivable: 0,
NextMaxSpendableMPP: balance,
NextMaxReceivableMPP: 0,
TotalSpendable: balance,
TotalSpendableSat: balance / 1000,
TotalSpendableMsat: balance,
NextMaxSpendable: balance,
NextMaxSpendableSat: balance / 1000,
NextMaxSpendableMsat: balance,
NextMaxSpendableMPP: balance,
NextMaxSpendableMPPSat: balance / 1000,
NextMaxSpendableMPPMsat: balance,
},
}, nil
}

View file

@ -553,7 +553,7 @@ func (ls *LDKService) SendPaymentSync(invoice string, amount *uint64) (*lnclient
logger.Logger.WithError(err).Error("SendPayment failed")
return nil, err
}
fee := uint64(0)
feeMsat := uint64(0)
preimage := ""
for {
@ -579,18 +579,18 @@ func (ls *LDKService) SendPaymentSync(invoice string, amount *uint64) (*lnclient
preimage = *event.PaymentPreimage
if event.FeePaidMsat != nil {
fee = *event.FeePaidMsat
feeMsat = *event.FeePaidMsat
}
logger.Logger.WithFields(logrus.Fields{
"duration": time.Since(paymentStart).Milliseconds(),
"fee": fee,
"fee": feeMsat,
"payment_hash": event.PaymentHash,
}).Info("Successful payment")
return &lnclient.PayInvoiceResponse{
Preimage: preimage,
Fee: fee,
Fee: feeMsat,
}, nil
case ldk_node.EventPaymentFailed:
if event.PaymentHash != nil && *event.PaymentHash == paymentHash {
@ -640,7 +640,7 @@ func (ls *LDKService) SendKeysend(amount uint64, destination string, custom_reco
logger.Logger.WithError(err).Error("Keysend failed")
return nil, err
}
fee := uint64(0)
feeMsat := uint64(0)
for {
select {
case <-ls.ctx.Done():
@ -654,14 +654,14 @@ func (ls *LDKService) SendKeysend(amount uint64, destination string, custom_reco
logger.Logger.Info("Got payment success event")
if eventPaymentSuccessful.FeePaidMsat != nil {
fee = *eventPaymentSuccessful.FeePaidMsat
feeMsat = *eventPaymentSuccessful.FeePaidMsat
}
logger.Logger.WithFields(logrus.Fields{
"duration": time.Since(paymentStart).Milliseconds(),
"fee": fee,
"fee": feeMsat,
}).Info("Successful keysend payment")
return &lnclient.PayKeysendResponse{
Fee: fee,
Fee: feeMsat,
}, nil
}
if isEventPaymentFailedEvent && eventPaymentFailed.PaymentHash != nil && *eventPaymentFailed.PaymentHash == paymentHash {
@ -1150,6 +1150,7 @@ func (ls *LDKService) GetOnchainBalance(ctx context.Context) (*lnclient.OnchainB
NodeId: nodeId,
ChannelId: channelId,
Amount: amount,
AmountSat: amount,
FundingTxId: fundingTxId,
FundingTxVout: uint32(fundingTxIndex),
})
@ -1186,6 +1187,7 @@ func (ls *LDKService) GetOnchainBalance(ctx context.Context) (*lnclient.OnchainB
NodeId: *nodeId,
ChannelId: *channelId,
Amount: amount,
AmountSat: amount,
FundingTxId: *fundingTxId,
FundingTxVout: uint32(*fundingTxIndex),
})
@ -1210,12 +1212,16 @@ func (ls *LDKService) GetOnchainBalance(ctx context.Context) (*lnclient.OnchainB
}
return &lnclient.OnchainBalanceResponse{
Spendable: int64(balances.SpendableOnchainBalanceSats),
Total: int64(balances.TotalOnchainBalanceSats - balances.TotalAnchorChannelsReserveSats),
Reserved: int64(balances.TotalAnchorChannelsReserveSats),
PendingBalancesFromChannelClosures: pendingBalancesFromChannelClosures,
PendingBalancesDetails: pendingBalancesDetails,
PendingSweepBalancesDetails: pendingSweepBalanceDetails,
Spendable: int64(balances.SpendableOnchainBalanceSats),
SpendableSat: int64(balances.SpendableOnchainBalanceSats),
Total: int64(balances.TotalOnchainBalanceSats - balances.TotalAnchorChannelsReserveSats),
TotalSat: int64(balances.TotalOnchainBalanceSats - balances.TotalAnchorChannelsReserveSats),
Reserved: int64(balances.TotalAnchorChannelsReserveSats),
ReservedSat: int64(balances.TotalAnchorChannelsReserveSats),
PendingBalancesFromChannelClosures: pendingBalancesFromChannelClosures,
PendingBalancesFromChannelClosuresSat: pendingBalancesFromChannelClosures,
PendingBalancesDetails: pendingBalancesDetails,
PendingSweepBalancesDetails: pendingSweepBalanceDetails,
InternalBalances: map[string]interface{}{
"internal_lightning_balances": internalLightningBalances,
"all_balances": balances,
@ -1420,14 +1426,14 @@ func (ls *LDKService) ldkPaymentToTransaction(payment *ldk_node.PaymentDetails)
metadata["tlv_records"] = tlvRecords
}
var amount uint64 = 0
var amountMsat uint64 = 0
if payment.AmountMsat != nil {
amount = *payment.AmountMsat
amountMsat = *payment.AmountMsat
}
var fee uint64 = 0
var feeMsat uint64 = 0
if payment.FeePaidMsat != nil {
fee = *payment.FeePaidMsat
feeMsat = *payment.FeePaidMsat
}
return &lnclient.Transaction{
@ -1435,9 +1441,9 @@ func (ls *LDKService) ldkPaymentToTransaction(payment *ldk_node.PaymentDetails)
Preimage: preimage,
PaymentHash: paymentHash,
SettledAt: settledAt,
Amount: int64(amount),
Amount: int64(amountMsat),
Invoice: bolt11Invoice,
FeesPaid: int64(fee),
FeesPaid: int64(feeMsat),
CreatedAt: createdAt,
Description: description,
DescriptionHash: descriptionHash,
@ -1870,12 +1876,24 @@ func (ls *LDKService) GetBalances(ctx context.Context, includeInactiveChannels b
return &lnclient.BalancesResponse{
Onchain: *onchainBalance,
Lightning: lnclient.LightningBalanceResponse{
TotalSpendable: totalSpendable,
TotalReceivable: totalReceivable,
NextMaxSpendable: nextMaxSpendable,
NextMaxReceivable: nextMaxReceivable,
NextMaxSpendableMPP: nextMaxSpendableMPP,
NextMaxReceivableMPP: nextMaxReceivableMPP,
TotalSpendable: totalSpendable,
TotalSpendableSat: totalSpendable / 1000,
TotalSpendableMsat: totalSpendable,
TotalReceivable: totalReceivable,
TotalReceivableSat: totalReceivable / 1000,
TotalReceivableMsat: totalReceivable,
NextMaxSpendable: nextMaxSpendable,
NextMaxSpendableSat: nextMaxSpendable / 1000,
NextMaxSpendableMsat: nextMaxSpendable,
NextMaxReceivable: nextMaxReceivable,
NextMaxReceivableSat: nextMaxReceivable / 1000,
NextMaxReceivableMsat: nextMaxReceivable,
NextMaxSpendableMPP: nextMaxSpendableMPP,
NextMaxSpendableMPPSat: nextMaxSpendableMPP / 1000,
NextMaxSpendableMPPMsat: nextMaxSpendableMPP,
NextMaxReceivableMPP: nextMaxReceivableMPP,
NextMaxReceivableMPPSat: nextMaxReceivableMPP / 1000,
NextMaxReceivableMPPMsat: nextMaxReceivableMPP,
},
}, nil
}
@ -2332,20 +2350,20 @@ func (ls *LDKService) MakeHoldInvoice(ctx context.Context, amount int64, descrip
if *minCltvExpiryDelta > uint64(65535) {
return nil, errors.New("min_cltv_expiry_delta must be <= 65535")
}
invoiceObj, err = ls.node.Bolt11Payment().ReceiveForHashWithMinCltvExpiryDelta(
uint64(amount),
descriptionType,
uint32(expiry),
ldkPaymentHash,
uint16(*minCltvExpiryDelta),
)
invoiceObj, err = ls.node.Bolt11Payment().ReceiveForHashWithMinCltvExpiryDelta(
uint64(amount),
descriptionType,
uint32(expiry),
ldkPaymentHash,
uint16(*minCltvExpiryDelta),
)
} else {
invoiceObj, err = ls.node.Bolt11Payment().ReceiveForHash(
uint64(amount),
descriptionType,
uint32(expiry),
ldkPaymentHash,
)
invoiceObj, err = ls.node.Bolt11Payment().ReceiveForHash(
uint64(amount),
descriptionType,
uint32(expiry),
ldkPaymentHash,
)
}
if err != nil {

View file

@ -1264,6 +1264,7 @@ func (svc *LNDService) GetOnchainBalance(ctx context.Context) (*lnclient.Onchain
pendingBalancesDetails = append(pendingBalancesDetails, lnclient.PendingBalanceDetails{
NodeId: closingChannel.Channel.RemoteNodePub,
Amount: uint64(closingChannel.LimboBalance),
AmountSat: uint64(closingChannel.LimboBalance),
FundingTxId: channelPoint.GetFundingTxidStr(),
FundingTxVout: channelPoint.GetOutputIndex(),
})
@ -1273,12 +1274,16 @@ func (svc *LNDService) GetOnchainBalance(ctx context.Context) (*lnclient.Onchain
"balances": balances,
}).Debug("Listed Balances")
return &lnclient.OnchainBalanceResponse{
Spendable: int64(balances.ConfirmedBalance),
Total: int64(balances.TotalBalance),
Reserved: int64(balances.ReservedBalanceAnchorChan),
PendingBalancesFromChannelClosures: pendingBalancesFromChannelClosures,
PendingBalancesDetails: pendingBalancesDetails,
PendingSweepBalancesDetails: []lnclient.PendingBalanceDetails{},
Spendable: int64(balances.ConfirmedBalance),
SpendableSat: int64(balances.ConfirmedBalance),
Total: int64(balances.TotalBalance),
TotalSat: int64(balances.TotalBalance),
Reserved: int64(balances.ReservedBalanceAnchorChan),
ReservedSat: int64(balances.ReservedBalanceAnchorChan),
PendingBalancesFromChannelClosures: pendingBalancesFromChannelClosures,
PendingBalancesFromChannelClosuresSat: pendingBalancesFromChannelClosures,
PendingBalancesDetails: pendingBalancesDetails,
PendingSweepBalancesDetails: []lnclient.PendingBalanceDetails{},
InternalBalances: map[string]interface{}{
"balances": balances,
"pending_channels": pendingChannels,
@ -1449,12 +1454,24 @@ func (svc *LNDService) GetBalances(ctx context.Context, includeInactiveChannels
return &lnclient.BalancesResponse{
Onchain: *onchainBalance,
Lightning: lnclient.LightningBalanceResponse{
TotalSpendable: totalSpendable,
TotalReceivable: totalReceivable,
NextMaxSpendable: nextMaxSpendable,
NextMaxReceivable: nextMaxReceivable,
NextMaxSpendableMPP: nextMaxSpendableMPP,
NextMaxReceivableMPP: nextMaxReceivableMPP,
TotalSpendable: totalSpendable,
TotalSpendableSat: totalSpendable / 1000,
TotalSpendableMsat: totalSpendable,
TotalReceivable: totalReceivable,
TotalReceivableSat: totalReceivable / 1000,
TotalReceivableMsat: totalReceivable,
NextMaxSpendable: nextMaxSpendable,
NextMaxSpendableSat: nextMaxSpendable / 1000,
NextMaxSpendableMsat: nextMaxSpendable,
NextMaxReceivable: nextMaxReceivable,
NextMaxReceivableSat: nextMaxReceivable / 1000,
NextMaxReceivableMsat: nextMaxReceivable,
NextMaxSpendableMPP: nextMaxSpendableMPP,
NextMaxSpendableMPPSat: nextMaxSpendableMPP / 1000,
NextMaxSpendableMPPMsat: nextMaxSpendableMPP,
NextMaxReceivableMPP: nextMaxReceivableMPP,
NextMaxReceivableMPPSat: nextMaxReceivableMPP / 1000,
NextMaxReceivableMPPMsat: nextMaxReceivableMPP,
},
}, nil
}

View file

@ -158,19 +158,24 @@ type CloseChannelResponse struct {
type PendingBalanceDetails struct {
ChannelId string `json:"channelId"`
NodeId string `json:"nodeId"`
Amount uint64 `json:"amount"`
Amount uint64 `json:"amount"` // deprecated
AmountSat uint64 `json:"amountSat"`
FundingTxId string `json:"fundingTxId"`
FundingTxVout uint32 `json:"fundingTxVout"`
}
type OnchainBalanceResponse struct {
Spendable int64 `json:"spendable"`
Total int64 `json:"total"`
Reserved int64 `json:"reserved"`
PendingBalancesFromChannelClosures uint64 `json:"pendingBalancesFromChannelClosures"`
PendingBalancesDetails []PendingBalanceDetails `json:"pendingBalancesDetails"`
PendingSweepBalancesDetails []PendingBalanceDetails `json:"pendingSweepBalancesDetails"`
InternalBalances interface{} `json:"internalBalances"`
Spendable int64 `json:"spendable"` // deprecated
SpendableSat int64 `json:"spendableSat"`
Total int64 `json:"total"` // deprecated
TotalSat int64 `json:"totalSat"`
Reserved int64 `json:"reserved"` // deprecated
ReservedSat int64 `json:"reservedSat"`
PendingBalancesFromChannelClosures uint64 `json:"pendingBalancesFromChannelClosures"` // deprecated
PendingBalancesFromChannelClosuresSat uint64 `json:"pendingBalancesFromChannelClosuresSat"`
PendingBalancesDetails []PendingBalanceDetails `json:"pendingBalancesDetails"`
PendingSweepBalancesDetails []PendingBalanceDetails `json:"pendingSweepBalancesDetails"`
InternalBalances interface{} `json:"internalBalances"`
}
type PeerDetails struct {
@ -180,12 +185,24 @@ type PeerDetails struct {
IsConnected bool `json:"isConnected"`
}
type LightningBalanceResponse struct {
TotalSpendable int64 `json:"totalSpendable"`
TotalReceivable int64 `json:"totalReceivable"`
NextMaxSpendable int64 `json:"nextMaxSpendable"`
NextMaxReceivable int64 `json:"nextMaxReceivable"`
NextMaxSpendableMPP int64 `json:"nextMaxSpendableMPP"`
NextMaxReceivableMPP int64 `json:"nextMaxReceivableMPP"`
TotalSpendable int64 `json:"totalSpendable"` // deprecated
TotalSpendableSat int64 `json:"totalSpendableSat"`
TotalSpendableMsat int64 `json:"totalSpendableMsat"`
TotalReceivable int64 `json:"totalReceivable"` // deprecated
TotalReceivableSat int64 `json:"totalReceivableSat"`
TotalReceivableMsat int64 `json:"totalReceivableMsat"`
NextMaxSpendable int64 `json:"nextMaxSpendable"` // deprecated
NextMaxSpendableSat int64 `json:"nextMaxSpendableSat"`
NextMaxSpendableMsat int64 `json:"nextMaxSpendableMsat"`
NextMaxReceivable int64 `json:"nextMaxReceivable"` // deprecated
NextMaxReceivableSat int64 `json:"nextMaxReceivableSat"`
NextMaxReceivableMsat int64 `json:"nextMaxReceivableMsat"`
NextMaxSpendableMPP int64 `json:"nextMaxSpendableMPP"` // deprecated
NextMaxSpendableMPPSat int64 `json:"nextMaxSpendableMPPSat"`
NextMaxSpendableMPPMsat int64 `json:"nextMaxSpendableMPPMsat"`
NextMaxReceivableMPP int64 `json:"nextMaxReceivableMPP"` // deprecated
NextMaxReceivableMPPSat int64 `json:"nextMaxReceivableMPPSat"`
NextMaxReceivableMPPMsat int64 `json:"nextMaxReceivableMPPMsat"`
}
type PayInvoiceResponse struct {

View file

@ -128,16 +128,18 @@ func (svc *PhoenixService) GetBalances(ctx context.Context, includeInactiveChann
return &lnclient.BalancesResponse{
Onchain: lnclient.OnchainBalanceResponse{
Spendable: 0,
Total: 0,
},
PendingBalancesDetails: []lnclient.PendingBalanceDetails{},
PendingSweepBalancesDetails: []lnclient.PendingBalanceDetails{}},
Lightning: lnclient.LightningBalanceResponse{
TotalSpendable: balance,
TotalReceivable: 0,
NextMaxSpendable: balance,
NextMaxReceivable: 0,
NextMaxSpendableMPP: balance,
NextMaxReceivableMPP: 0,
TotalSpendable: balance,
TotalSpendableSat: balance / 1000,
TotalSpendableMsat: balance,
NextMaxSpendable: balance,
NextMaxSpendableSat: balance / 1000,
NextMaxSpendableMsat: balance,
NextMaxSpendableMPP: balance,
NextMaxSpendableMPPSat: balance / 1000,
NextMaxSpendableMPPMsat: balance,
},
}, nil
}

View file

@ -27,10 +27,10 @@ func (controller *nip47Controller) HandleGetBalanceEvent(ctx context.Context, ni
"request_event_id": requestEventId,
}).Debug("Getting balance")
balance := int64(0)
balanceMsat := int64(0)
if app.Isolated {
var err error
balance, err = queries.GetIsolatedBalance(controller.db, app.ID)
balanceMsat, err = queries.GetIsolatedBalanceMsat(controller.db, app.ID)
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"request_event_id": requestEventId,
@ -53,11 +53,11 @@ func (controller *nip47Controller) HandleGetBalanceEvent(ctx context.Context, ni
}, nostr.Tags{})
return
}
balance = balances.Lightning.TotalSpendable
balanceMsat = balances.Lightning.TotalSpendable
}
responsePayload := &getBalanceResponse{
Balance: balance,
Balance: balanceMsat,
}
// this is not part of the spec and does not seem to be used

View file

@ -28,8 +28,8 @@ func (controller *nip47Controller) HandleGetBudgetEvent(ctx context.Context, nip
appPermission := db.AppPermission{}
controller.db.Where("app_id = ? AND scope = ?", app.ID, models.PAY_INVOICE_METHOD).First(&appPermission)
maxAmount := appPermission.MaxAmountSat
if maxAmount == 0 {
maxAmountSat := appPermission.MaxAmountSat
if maxAmountSat == 0 {
publishResponse(&models.Response{
ResultType: nip47Request.Method,
Result: struct{}{},
@ -37,7 +37,7 @@ func (controller *nip47Controller) HandleGetBudgetEvent(ctx context.Context, nip
return
}
usedBudget, err := queries.GetBudgetUsage(controller.db, &appPermission)
usedBudgetMsat, err := queries.GetBudgetUsageMsat(controller.db, &appPermission)
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"request_event_id": requestEventId,
@ -50,8 +50,8 @@ func (controller *nip47Controller) HandleGetBudgetEvent(ctx context.Context, nip
}
responsePayload := &getBudgetResponse{
TotalBudget: uint64(maxAmount * 1000),
UsedBudget: usedBudget,
TotalBudget: uint64(maxAmountSat * 1000),
UsedBudget: usedBudgetMsat,
RenewalPeriod: appPermission.BudgetRenewal,
RenewsAt: queries.GetBudgetRenewsAt(appPermission.BudgetRenewal),
}

View file

@ -29,7 +29,9 @@ var MockNodeInfo = lnclient.NodeInfo{
var MockLNClientBalances = lnclient.BalancesResponse{
Lightning: lnclient.LightningBalanceResponse{
TotalSpendable: 21000,
TotalSpendable: 21000,
TotalSpendableSat: 21,
TotalSpendableMsat: 21000,
},
}

View file

@ -399,9 +399,9 @@ func TestSendKeysend_IsolatedAppToNoApp(t *testing.T) {
result := svc.DB.Find(&transactions)
assert.Equal(t, int64(3), result.RowsAffected)
// expect balance to be decreased
balance, err := queries.GetIsolatedBalance(svc.DB, app.ID)
balanceMsat, err := queries.GetIsolatedBalanceMsat(svc.DB, app.ID)
assert.NoError(t, err)
assert.Equal(t, int64(10000), balance)
assert.Equal(t, int64(10000), balanceMsat)
}
func TestSendKeysend_IsolatedAppToIsolatedApp(t *testing.T) {
@ -491,14 +491,14 @@ func TestSendKeysend_IsolatedAppToIsolatedApp(t *testing.T) {
result := svc.DB.Find(&transactions)
assert.Equal(t, int64(3), result.RowsAffected)
// expect balance to be decreased
balance, err := queries.GetIsolatedBalance(svc.DB, app.ID)
balanceMsat, err := queries.GetIsolatedBalanceMsat(svc.DB, app.ID)
assert.NoError(t, err)
assert.Equal(t, int64(10000), balance)
assert.Equal(t, int64(10000), balanceMsat)
// expect app2 to receive the payment
balance, err = queries.GetIsolatedBalance(svc.DB, app2.ID)
balanceMsat, err = queries.GetIsolatedBalanceMsat(svc.DB, app2.ID)
assert.NoError(t, err)
assert.Equal(t, int64(123000), balance)
assert.Equal(t, int64(123000), balanceMsat)
// check notifications
assert.Equal(t, 2, len(mockEventConsumer.GetConsumedEvents()))

View file

@ -107,9 +107,9 @@ func TestSendPaymentSync_SelfPayment_NoAppToIsolatedApp(t *testing.T) {
result := svc.DB.Find(&transactions)
assert.Equal(t, int64(2), result.RowsAffected)
// expect balance to be increased
balance, err := queries.GetIsolatedBalance(svc.DB, app.ID)
balanceMsat, err := queries.GetIsolatedBalanceMsat(svc.DB, app.ID)
assert.NoError(t, err)
assert.Equal(t, int64(123000), balance)
assert.Equal(t, int64(123000), balanceMsat)
}
func TestSendPaymentSync_SelfPayment_NoAppToApp(t *testing.T) {
@ -232,9 +232,9 @@ func TestSendPaymentSync_SelfPayment_IsolatedAppToNoApp(t *testing.T) {
result := svc.DB.Find(&transactions)
assert.Equal(t, int64(3), result.RowsAffected)
// expect balance to be decreased
balance, err := queries.GetIsolatedBalance(svc.DB, app.ID)
balanceMsat, err := queries.GetIsolatedBalanceMsat(svc.DB, app.ID)
assert.NoError(t, err)
assert.Equal(t, int64(0), balance)
assert.Equal(t, int64(0), balanceMsat)
}
func TestSendPaymentSync_SelfPayment_IsolatedAppToApp(t *testing.T) {
@ -310,9 +310,9 @@ func TestSendPaymentSync_SelfPayment_IsolatedAppToApp(t *testing.T) {
result := svc.DB.Find(&transactions)
assert.Equal(t, int64(3), result.RowsAffected)
// expect balance to be decreased
balance, err := queries.GetIsolatedBalance(svc.DB, app.ID)
balanceMsat, err := queries.GetIsolatedBalanceMsat(svc.DB, app.ID)
assert.NoError(t, err)
assert.Equal(t, int64(0), balance)
assert.Equal(t, int64(0), balanceMsat)
}
func TestSendPaymentSync_SelfPayment_IsolatedAppToIsolatedApp(t *testing.T) {
@ -394,9 +394,9 @@ func TestSendPaymentSync_SelfPayment_IsolatedAppToIsolatedApp(t *testing.T) {
result := svc.DB.Find(&transactions)
assert.Equal(t, int64(3), result.RowsAffected)
// expect balance to be decreased
balance, err := queries.GetIsolatedBalance(svc.DB, app.ID)
balanceMsat, err := queries.GetIsolatedBalanceMsat(svc.DB, app.ID)
assert.NoError(t, err)
assert.Equal(t, int64(0), balance)
assert.Equal(t, int64(0), balanceMsat)
// check notifications
assert.Equal(t, 2, len(mockEventConsumer.GetConsumedEvents()))
@ -489,9 +489,9 @@ func TestSendPaymentSync_SelfPayment_IsolatedAppToSelf(t *testing.T) {
assert.Equal(t, int64(3), result.RowsAffected)
// expect balance to be unchanged
balance, err := queries.GetIsolatedBalance(svc.DB, app.ID)
balanceMsat, err := queries.GetIsolatedBalanceMsat(svc.DB, app.ID)
assert.NoError(t, err)
assert.Equal(t, int64(123000), balance)
assert.Equal(t, int64(123000), balanceMsat)
}
func TestSendPaymentSync_SelfPayment_IsolatedAppToApp_AmountProvidedIgnoredOnNonZeroAmountInvoice(t *testing.T) {
@ -570,7 +570,7 @@ func TestSendPaymentSync_SelfPayment_IsolatedAppToApp_AmountProvidedIgnoredOnNon
result := svc.DB.Find(&transactions)
assert.Equal(t, int64(3), result.RowsAffected)
// expect balance to be decreased
balance, err := queries.GetIsolatedBalance(svc.DB, app.ID)
balanceMsat, err := queries.GetIsolatedBalanceMsat(svc.DB, app.ID)
assert.NoError(t, err)
assert.Equal(t, int64(0), balance)
assert.Equal(t, int64(0), balanceMsat)
}

View file

@ -1090,14 +1090,14 @@ func (svc *transactionsService) validateCanPay(tx *gorm.DB, appId *uint, amount
}
if app.Isolated {
balance, err := queries.GetIsolatedBalance(tx, appPermission.AppId)
balanceMsat, err := queries.GetIsolatedBalanceMsat(tx, appPermission.AppId)
if err != nil {
return fmt.Errorf("failed to calculate isolated balance for app: %w", err)
}
if int64(amountWithFeeReserve) > balance {
if int64(amountWithFeeReserve) > balanceMsat {
logger.Logger.WithFields(logrus.Fields{
"balance": balance,
"balance_msat": balanceMsat,
"self_payment": selfPayment,
"amount": amount,
"amount_with_fee_reserve": amountWithFeeReserve,
@ -1120,11 +1120,11 @@ func (svc *transactionsService) validateCanPay(tx *gorm.DB, appId *uint, amount
}
if appPermission.MaxAmountSat > 0 {
budgetUsage, err := queries.GetBudgetUsage(tx, &appPermission)
budgetUsageMsat, err := queries.GetBudgetUsageMsat(tx, &appPermission)
if err != nil {
return fmt.Errorf("failed to calculate budget usage for app: %w", err)
}
if int(amountWithFeeReserve/1000) > appPermission.MaxAmountSat-int(budgetUsage/1000) {
if int(amountWithFeeReserve/1000) > appPermission.MaxAmountSat-int(budgetUsageMsat/1000) {
message := NewQuotaExceededError().Error()
if description != "" {
message += " " + description
@ -1477,12 +1477,12 @@ func (svc *transactionsService) checkBudgetUsage(app *db.App, dbTransaction *db.
return
}
budgetUsage, err := queries.GetBudgetUsage(gormTransaction, &appPermission)
budgetUsageMsat, err := queries.GetBudgetUsageMsat(gormTransaction, &appPermission)
if err != nil {
logger.Logger.WithField("app_id", dbTransaction.AppId).WithError(err).Error("failed to get budget usage")
return
}
budgetUsageSat := budgetUsage / 1000
budgetUsageSat := budgetUsageMsat / 1000
warningUsage := uint64(math.Floor(float64(appPermission.MaxAmountSat) * 0.8))
if budgetUsageSat >= warningUsage && budgetUsageSat-dbTransaction.AmountMsat/1000 < warningUsage {
svc.eventPublisher.Publish(&events.Event{