get_budget_controller.go raw
1 package controllers
2
3 import (
4 "context"
5 "errors"
6
7 "github.com/getAlby/go-nostr"
8 "github.com/getAlby/hub/db/queries"
9 "gorm.io/gorm"
10
11 "github.com/getAlby/hub/constants"
12 "github.com/getAlby/hub/db"
13 "github.com/getAlby/hub/logger"
14 "github.com/getAlby/hub/nip47/models"
15 "github.com/sirupsen/logrus"
16 )
17
18 type getBudgetResponse struct {
19 UsedBudget uint64 `json:"used_budget"`
20 TotalBudget uint64 `json:"total_budget"`
21 RenewsAt *uint64 `json:"renews_at,omitempty"`
22 RenewalPeriod string `json:"renewal_period"`
23 }
24
25 func (controller *nip47Controller) HandleGetBudgetEvent(ctx context.Context, nip47Request *models.Request, requestEventId uint, app *db.App, publishResponse publishFunc) {
26
27 logger.Logger.WithFields(logrus.Fields{
28 "request_event_id": requestEventId,
29 }).Debug("Getting budget")
30
31 appPermission := db.AppPermission{}
32 result := controller.db.Where("app_id = ? AND scope = ?", app.ID, constants.PAY_INVOICE_SCOPE).First(&appPermission)
33 if result.Error != nil && !errors.Is(result.Error, gorm.ErrRecordNotFound) {
34 logger.Logger.WithFields(logrus.Fields{
35 "request_event_id": requestEventId,
36 }).WithError(result.Error).Error("Failed to fetch pay_invoice permission")
37 publishResponse(&models.Response{
38 ResultType: nip47Request.Method,
39 Error: mapNip47Error(result.Error),
40 }, nostr.Tags{})
41 return
42 }
43
44 // On ErrRecordNotFound appPermission stays zero-valued and maxAmountSat == 0,
45 // which returns the same empty "no budget" response as a permission with no
46 // budget set.
47 maxAmountSat := appPermission.MaxAmountSat
48 if maxAmountSat == 0 {
49 publishResponse(&models.Response{
50 ResultType: nip47Request.Method,
51 Result: struct{}{},
52 }, nostr.Tags{})
53 return
54 }
55
56 usedBudgetMsat, err := queries.GetBudgetUsageMsat(controller.db, &appPermission)
57 if err != nil {
58 logger.Logger.WithFields(logrus.Fields{
59 "request_event_id": requestEventId,
60 }).WithError(err).Error("Failed to fetch budget usage")
61 publishResponse(&models.Response{
62 ResultType: nip47Request.Method,
63 Error: mapNip47Error(err),
64 }, nostr.Tags{})
65 return
66 }
67
68 responsePayload := &getBudgetResponse{
69 TotalBudget: uint64(maxAmountSat * 1000),
70 UsedBudget: usedBudgetMsat,
71 RenewalPeriod: appPermission.BudgetRenewal,
72 RenewsAt: queries.GetBudgetRenewsAt(appPermission.BudgetRenewal),
73 }
74
75 publishResponse(&models.Response{
76 ResultType: nip47Request.Method,
77 Result: responsePayload,
78 }, nostr.Tags{})
79 }
80