get_info_controller.go raw
1 package controllers
2
3 import (
4 "context"
5 "encoding/json"
6
7 "github.com/getAlby/go-nostr"
8 "github.com/getAlby/hub/constants"
9 "github.com/getAlby/hub/db"
10 "github.com/getAlby/hub/logger"
11 "github.com/getAlby/hub/nip47/models"
12 "github.com/sirupsen/logrus"
13 )
14
15 type getInfoResponse struct {
16 Alias *string `json:"alias"`
17 Color *string `json:"color"`
18 Pubkey *string `json:"pubkey"`
19 Network *string `json:"network"`
20 BlockHeight *uint32 `json:"block_height"`
21 BlockHash *string `json:"block_hash"`
22 Methods []string `json:"methods"`
23 Notifications []string `json:"notifications"`
24 Metadata interface{} `json:"metadata,omitempty"`
25 LightningAddress *string `json:"lud16"`
26 }
27
28 func (controller *nip47Controller) HandleGetInfoEvent(ctx context.Context, nip47Request *models.Request, requestEventId uint, app *db.App, publishResponse publishFunc) {
29 supportedNotifications := []string{}
30 if controller.permissionsService.PermitsNotifications(app) {
31 supportedNotifications = controller.lnClient.GetSupportedNIP47NotificationTypes()
32 }
33
34 responsePayload := &getInfoResponse{
35 Methods: controller.permissionsService.GetPermittedMethods(app, controller.lnClient),
36 Notifications: supportedNotifications,
37 }
38
39 if app != nil {
40 metadata := map[string]interface{}{}
41 if app.Metadata != nil {
42 jsonErr := json.Unmarshal(app.Metadata, &metadata)
43 if jsonErr != nil {
44 logger.Logger.WithError(jsonErr).WithFields(logrus.Fields{
45 "id": app.ID,
46 "metadata": app.Metadata,
47 }).Error("Failed to deserialize app metadata")
48 }
49 }
50 if metadata["id"] == nil {
51 metadata["id"] = app.ID
52 }
53 if metadata["name"] == nil {
54 metadata["name"] = app.Name
55 }
56 if !app.Isolated {
57 lightningAddress, _ := controller.albyOAuthService.GetLightningAddress()
58 responsePayload.LightningAddress = &lightningAddress
59 } else if metadata[constants.METADATA_APPSTORE_APP_ID_KEY] == constants.SUBWALLET_APPSTORE_APP_ID && metadata["lud16"] != nil {
60 lightningAddress := metadata["lud16"].(string)
61 responsePayload.LightningAddress = &lightningAddress
62 }
63
64 responsePayload.Metadata = metadata
65 }
66
67 // basic permissions check
68 // this is inconsistent with other methods. Ideally we move fetching node info to a separate method,
69 // so that get_info does not require its own scope. This would require a change in the NIP-47 spec.
70 hasPermission, _, _ := controller.permissionsService.HasPermission(app, constants.GET_INFO_SCOPE)
71 if hasPermission {
72 logger.Logger.WithFields(logrus.Fields{
73 "request_event_id": requestEventId,
74 }).Debug("Getting info")
75
76 info, err := controller.lnClient.GetInfo(ctx)
77 if err != nil {
78 logger.Logger.WithFields(logrus.Fields{
79 "request_event_id": requestEventId,
80 }).Infof("Failed to fetch node info: %v", err)
81
82 publishResponse(&models.Response{
83 ResultType: nip47Request.Method,
84 Error: mapNip47Error(err),
85 }, nostr.Tags{})
86 return
87 }
88
89 network := info.Network
90 // Some implementations return "bitcoin" while NIP47 expects "mainnet"
91 if network == "bitcoin" {
92 network = "mainnet"
93 }
94
95 responsePayload.Alias = &info.Alias
96 responsePayload.Color = &info.Color
97 responsePayload.Pubkey = &info.Pubkey
98 responsePayload.Network = &network
99 responsePayload.BlockHeight = &info.BlockHeight
100 responsePayload.BlockHash = &info.BlockHash
101 }
102
103 publishResponse(&models.Response{
104 ResultType: nip47Request.Method,
105 Result: responsePayload,
106 }, nostr.Tags{})
107 }
108