Skip to content

Commit

Permalink
Add get_budget implementation (#726)
Browse files Browse the repository at this point in the history
* Add get_budget implementation

* Always granted scope

* Don't show always_granted in the UI or save it in the DB.

* chore: get budget feedback

- replace always granted scope with always granted method list
- return nil for budget renews at for "never" budget renewal
- add extra tests

* fix: add omitempty to renews_at in get_budget response

---------

Co-authored-by: Roland Bewick <roland.bewick@gmail.com>
  • Loading branch information
jklein24 and rolznz authored Oct 28, 2024
1 parent 373965a commit 430c9fe
Show file tree
Hide file tree
Showing 19 changed files with 446 additions and 22 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ nostr-wallet-connect
nwc.db
.breez
.data
.idea

frontend/dist
frontend/node_modules
Expand All @@ -21,6 +22,7 @@ build/bin
# generated by platform-specific files
frontend/src/utils/request.ts
frontend/src/utils/openLink.ts
frontend/.yarn

# generated by rust go bindings for local development
glalby
Expand Down
23 changes: 23 additions & 0 deletions db/queries/get_budget_usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,26 @@ func getStartOfBudget(budget_type string) time.Time {
return time.Time{}
}
}

func GetBudgetRenewsAt(budgetRenewal string) *uint64 {
budgetStart := getStartOfBudget(budgetRenewal)
switch budgetRenewal {
case constants.BUDGET_RENEWAL_DAILY:
renewal := uint64(budgetStart.AddDate(0, 0, 1).Unix())
return &renewal
case constants.BUDGET_RENEWAL_WEEKLY:
renewal := uint64(budgetStart.AddDate(0, 0, 7).Unix())
return &renewal

case constants.BUDGET_RENEWAL_MONTHLY:
renewal := uint64(budgetStart.AddDate(0, 1, 0).Unix())
return &renewal

case constants.BUDGET_RENEWAL_YEARLY:
renewal := uint64(budgetStart.AddDate(1, 0, 0).Unix())
return &renewal

default: //"never"
return nil
}
}
1 change: 1 addition & 0 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type BackendType =
export type Nip47RequestMethod =
| "get_info"
| "get_balance"
| "get_budget"
| "make_invoice"
| "pay_invoice"
| "pay_keysend"
Expand Down
2 changes: 1 addition & 1 deletion lnclient/breez/breez.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ func (bs *BreezService) DisconnectPeer(ctx context.Context, peerId string) error
}

func (bs *BreezService) GetSupportedNIP47Methods() []string {
return []string{"pay_invoice" /*"pay_keysend",*/, "get_balance", "get_info", "make_invoice", "lookup_invoice", "list_transactions", "multi_pay_invoice", "multi_pay_keysend", "sign_message"}
return []string{"pay_invoice" /*"pay_keysend",*/, "get_balance", "get_budget", "get_info", "make_invoice", "lookup_invoice", "list_transactions", "multi_pay_invoice", "multi_pay_keysend", "sign_message"}
}

func (bs *BreezService) GetSupportedNIP47NotificationTypes() []string {
Expand Down
2 changes: 1 addition & 1 deletion lnclient/cashu/cashu.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ func (cs *CashuService) checkInvoice(cashuInvoice *storage.Invoice) {
}

func (cs *CashuService) GetSupportedNIP47Methods() []string {
return []string{"pay_invoice", "get_balance", "get_info", "make_invoice", "lookup_invoice", "list_transactions", "multi_pay_invoice"}
return []string{"pay_invoice", "get_balance", "get_budget", "get_info", "make_invoice", "lookup_invoice", "list_transactions", "multi_pay_invoice"}
}

func (cs *CashuService) GetSupportedNIP47NotificationTypes() []string {
Expand Down
2 changes: 1 addition & 1 deletion lnclient/greenlight/greenlight.go
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ func (gs *GreenlightService) DisconnectPeer(ctx context.Context, peerId string)
}

func (gs *GreenlightService) GetSupportedNIP47Methods() []string {
return []string{"pay_invoice" /*"pay_keysend",*/, "get_balance", "get_info", "make_invoice", "lookup_invoice", "list_transactions", "multi_pay_invoice", "multi_pay_keysend", "sign_message"}
return []string{"pay_invoice" /*"pay_keysend",*/, "get_balance", "get_budget", "get_info", "make_invoice", "lookup_invoice", "list_transactions", "multi_pay_invoice", "multi_pay_keysend", "sign_message"}
}

func (gs *GreenlightService) GetSupportedNIP47NotificationTypes() []string {
Expand Down
2 changes: 1 addition & 1 deletion lnclient/ldk/ldk.go
Original file line number Diff line number Diff line change
Expand Up @@ -1647,7 +1647,7 @@ func (ls *LDKService) UpdateLastWalletSyncRequest() {
}

func (ls *LDKService) GetSupportedNIP47Methods() []string {
return []string{"pay_invoice", "pay_keysend", "get_balance", "get_info", "make_invoice", "lookup_invoice", "list_transactions", "multi_pay_invoice", "multi_pay_keysend", "sign_message"}
return []string{"pay_invoice", "pay_keysend", "get_balance", "get_budget", "get_info", "make_invoice", "lookup_invoice", "list_transactions", "multi_pay_invoice", "multi_pay_keysend", "sign_message"}
}

func (ls *LDKService) GetSupportedNIP47NotificationTypes() []string {
Expand Down
2 changes: 1 addition & 1 deletion lnclient/lnd/lnd.go
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ func (svc *LNDService) DisconnectPeer(ctx context.Context, peerId string) error

func (svc *LNDService) GetSupportedNIP47Methods() []string {
return []string{
"pay_invoice", "pay_keysend", "get_balance", "get_info", "make_invoice", "lookup_invoice", "list_transactions", "multi_pay_invoice", "multi_pay_keysend", "sign_message",
"pay_invoice", "pay_keysend", "get_balance", "get_budget", "get_info", "make_invoice", "lookup_invoice", "list_transactions", "multi_pay_invoice", "multi_pay_keysend", "sign_message",
}
}

Expand Down
2 changes: 1 addition & 1 deletion lnclient/phoenixd/phoenixd.go
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ func (svc *PhoenixService) UpdateChannel(ctx context.Context, updateChannelReque
}

func (svc *PhoenixService) GetSupportedNIP47Methods() []string {
return []string{"pay_invoice", "get_balance", "get_info", "make_invoice", "lookup_invoice", "list_transactions", "multi_pay_invoice"}
return []string{"pay_invoice", "get_balance", "get_budget", "get_info", "make_invoice", "lookup_invoice", "list_transactions", "multi_pay_invoice"}
}

func (svc *PhoenixService) GetSupportedNIP47NotificationTypes() []string {
Expand Down
52 changes: 52 additions & 0 deletions nip47/controllers/get_budget_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package controllers

import (
"context"

"github.com/getAlby/hub/db/queries"
"github.com/nbd-wtf/go-nostr"

"github.com/getAlby/hub/db"
"github.com/getAlby/hub/logger"
"github.com/getAlby/hub/nip47/models"
"github.com/sirupsen/logrus"
)

type getBudgetResponse struct {
UsedBudget uint64 `json:"used_budget"`
TotalBudget uint64 `json:"total_budget"`
RenewsAt *uint64 `json:"renews_at,omitempty"`
RenewalPeriod string `json:"renewal_period"`
}

func (controller *nip47Controller) HandleGetBudgetEvent(ctx context.Context, nip47Request *models.Request, requestEventId uint, app *db.App, publishResponse publishFunc) {

logger.Logger.WithFields(logrus.Fields{
"request_event_id": requestEventId,
}).Debug("Getting budget")

appPermission := db.AppPermission{}
controller.db.Where("app_id = ? AND scope = ?", app.ID, models.PAY_INVOICE_METHOD).First(&appPermission)

maxAmount := appPermission.MaxAmountSat
if maxAmount == 0 {
publishResponse(&models.Response{
ResultType: nip47Request.Method,
Result: struct{}{},
}, nostr.Tags{})
return
}

usedBudget := queries.GetBudgetUsageSat(controller.db, &appPermission)
responsePayload := &getBudgetResponse{
TotalBudget: uint64(maxAmount * 1000),
UsedBudget: usedBudget * 1000,
RenewalPeriod: appPermission.BudgetRenewal,
RenewsAt: queries.GetBudgetRenewsAt(appPermission.BudgetRenewal),
}

publishResponse(&models.Response{
ResultType: nip47Request.Method,
Result: responsePayload,
}, nostr.Tags{})
}
Loading

0 comments on commit 430c9fe

Please sign in to comment.