Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into task-add-alerts
Browse files Browse the repository at this point in the history
  • Loading branch information
rolznz committed Jul 19, 2024
2 parents f1fb388 + dfa8e44 commit f8f3484
Show file tree
Hide file tree
Showing 105 changed files with 5,875 additions and 2,054 deletions.
2 changes: 1 addition & 1 deletion .do/deploy.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ spec:
instance_size_slug: basic-xxs
envs:
- key: LDK_ESPLORA_SERVER
value: "https://electrs.getalby.com"
value: "https://electrs.getalbypro.com"
- key: LOG_EVENTS
value: "true"
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ frontend/src/utils/request.ts
frontend/src/utils/openLink.ts

# generated by rust go bindings for local development
glalby
glalby

*.db-shm
*.db-wal
*.db-journal
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ If the client creates the secret the client only needs to share the public key o
- `budget_renewal` (optional) reset the budget at the end of the given budget renewal. Can be `never` (default), `daily`, `weekly`, `monthly`, `yearly`
- `request_methods` (optional) url encoded, space separated list of request types that you need permission for: `pay_invoice` (default), `get_balance` (see NIP47). For example: `..&request_methods=pay_invoice%20get_balance`
- `notification_types` (optional) url encoded, space separated list of notification types that you need permission for: For example: `..&notification_types=payment_received%20payment_sent`
- `isolated` (optional) makes an isolated app connection with its own balance and only access to its own transaction list. e.g. `&isolated=true`. If using this option, you should not pass any custom request methods or notification types, nor set a budget or expiry.

Example:

Expand Down
66 changes: 50 additions & 16 deletions alby/alby_oauth_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ import (
"gorm.io/gorm"

"github.com/getAlby/hub/config"
"github.com/getAlby/hub/constants"
"github.com/getAlby/hub/db"
"github.com/getAlby/hub/events"
"github.com/getAlby/hub/lnclient"
"github.com/getAlby/hub/logger"
"github.com/getAlby/hub/nip47/permissions"
"github.com/getAlby/hub/service/keys"
"github.com/getAlby/hub/transactions"
)

type albyOAuthService struct {
Expand Down Expand Up @@ -273,13 +275,13 @@ func (svc *albyOAuthService) DrainSharedWallet(ctx context.Context, lnClient lnc

logger.Logger.WithField("amount", amount).WithError(err).Error("Draining Alby shared wallet funds")

transaction, err := lnClient.MakeInvoice(ctx, amount, "Send shared wallet funds to Alby Hub", "", 120)
transaction, err := transactions.NewTransactionsService(svc.db).MakeInvoice(ctx, amount, "Send shared wallet funds to Alby Hub", "", 120, lnClient, nil, nil)
if err != nil {
logger.Logger.WithField("amount", amount).WithError(err).Error("Failed to make invoice")
return err
}

err = svc.SendPayment(ctx, transaction.Invoice)
err = svc.SendPayment(ctx, transaction.PaymentRequest)
if err != nil {
logger.Logger.WithField("amount", amount).WithError(err).Error("Failed to pay invoice from shared node")
return err
Expand Down Expand Up @@ -393,7 +395,7 @@ func (svc *albyOAuthService) LinkAccount(ctx context.Context, lnClient lnclient.
}
notificationTypes := lnClient.GetSupportedNIP47NotificationTypes()
if len(notificationTypes) > 0 {
scopes = append(scopes, permissions.NOTIFICATIONS_SCOPE)
scopes = append(scopes, constants.NOTIFICATIONS_SCOPE)
}

app, _, err := db.NewDBService(svc.db, svc.eventPublisher).CreateApp(
Expand All @@ -403,6 +405,7 @@ func (svc *albyOAuthService) LinkAccount(ctx context.Context, lnClient lnclient.
renewal,
nil,
scopes,
false,
)

if err != nil {
Expand All @@ -423,25 +426,58 @@ func (svc *albyOAuthService) LinkAccount(ctx context.Context, lnClient lnclient.
return nil
}

func (svc *albyOAuthService) ConsumeEvent(ctx context.Context, event *events.Event, globalProperties map[string]interface{}) error {
func (svc *albyOAuthService) ConsumeEvent(ctx context.Context, event *events.Event, globalProperties map[string]interface{}) {
// run non-blocking
go svc.consumeEvent(ctx, event, globalProperties)
}

func (svc *albyOAuthService) consumeEvent(ctx context.Context, event *events.Event, globalProperties map[string]interface{}) {
// TODO: rename this config option to be specific to the alby API
if !svc.cfg.GetEnv().LogEvents {
logger.Logger.WithField("event", event).Debug("Skipped sending to alby events API")
return nil
return
}

if event.Event == "nwc_backup_channels" {
if err := svc.backupChannels(ctx, event); err != nil {
logger.Logger.WithError(err).Error("Failed to backup channels")
return err
}
return nil
return
}

if event.Event == "nwc_payment_received" {
type paymentReceivedEventProperties struct {
PaymentHash string `json:"payment_hash"`
}
// pass a new custom event with less detail
event = &events.Event{
Event: event.Event,
Properties: &paymentReceivedEventProperties{
PaymentHash: event.Properties.(*lnclient.Transaction).PaymentHash,
},
}
}

if event.Event == "nwc_payment_sent" {
type paymentSentEventProperties struct {
PaymentHash string `json:"payment_hash"`
Duration uint64 `json:"duration"`
}

// pass a new custom event with less detail
event = &events.Event{
Event: event.Event,
Properties: &paymentSentEventProperties{
PaymentHash: event.Properties.(*lnclient.Transaction).PaymentHash,
Duration: uint64(*event.Properties.(*lnclient.Transaction).SettledAt - event.Properties.(*lnclient.Transaction).CreatedAt),
},
}
}

token, err := svc.fetchUserToken(ctx)
if err != nil {
logger.Logger.WithError(err).Error("Failed to fetch user token")
return err
return
}

client := svc.oauthConf.Client(ctx, token)
Expand All @@ -452,7 +488,7 @@ func (svc *albyOAuthService) ConsumeEvent(ctx context.Context, event *events.Eve

if err != nil {
logger.Logger.WithError(err).Error("Failed to encode request payload")
return err
return
}

type eventWithPropertiesMap struct {
Expand All @@ -464,7 +500,7 @@ func (svc *albyOAuthService) ConsumeEvent(ctx context.Context, event *events.Eve
err = json.Unmarshal(originalEventBuffer.Bytes(), &eventWithGlobalProperties)
if err != nil {
logger.Logger.WithError(err).Error("Failed to decode request payload")
return err
return
}
if eventWithGlobalProperties.Properties == nil {
eventWithGlobalProperties.Properties = map[string]interface{}{}
Expand All @@ -485,13 +521,13 @@ func (svc *albyOAuthService) ConsumeEvent(ctx context.Context, event *events.Eve

if err != nil {
logger.Logger.WithError(err).Error("Failed to encode request payload")
return err
return
}

req, err := http.NewRequest("POST", fmt.Sprintf("%s/events", svc.cfg.GetEnv().AlbyAPIURL), body)
if err != nil {
logger.Logger.WithError(err).Error("Error creating request /events")
return err
return
}

req.Header.Set("User-Agent", "NWC-next")
Expand All @@ -502,18 +538,16 @@ func (svc *albyOAuthService) ConsumeEvent(ctx context.Context, event *events.Eve
logger.Logger.WithFields(logrus.Fields{
"event": eventWithGlobalProperties,
}).WithError(err).Error("Failed to send request to /events")
return err
return
}

if resp.StatusCode >= 300 {
logger.Logger.WithFields(logrus.Fields{
"event": eventWithGlobalProperties,
"status": resp.StatusCode,
}).Error("Request to /events returned non-success status")
return errors.New("request to /events returned non-success status")
return
}

return nil
}

func (svc *albyOAuthService) backupChannels(ctx context.Context, event *events.Event) error {
Expand Down
Loading

0 comments on commit f8f3484

Please sign in to comment.