Skip to content
This repository has been archived by the owner on Sep 2, 2024. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/master' into release-wails
Browse files Browse the repository at this point in the history
  • Loading branch information
rolznz committed Jun 21, 2024
2 parents f1ad3df + 474c1ca commit f31cc33
Show file tree
Hide file tree
Showing 13 changed files with 249 additions and 67 deletions.
File renamed without changes.
6 changes: 4 additions & 2 deletions events/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ type Event struct {

type PaymentReceivedEventProperties struct {
PaymentHash string `json:"payment_hash"`
Amount uint64 `json:"amount"`
NodeType string `json:"node_type"`
}

type PaymentSentEventProperties struct {
PaymentHash string `json:"payment_hash"`
}

type ChannelBackupEvent struct {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/EmptyState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const EmptyState: React.FC<Props> = ({
buttonLink,
}) => {
return (
<div className="flex flex-1 items-center justify-center rounded-lg border border-dashed shadow-sm">
<div className="flex flex-1 items-center justify-center rounded-lg border border-dashed shadow-sm py-8">
<div className="flex flex-col items-center gap-1 text-center max-w-sm">
<Icon className="w-10 h-10 text-muted-foreground" />
<h3 className="mt-4 text-lg font-semibold">{message}</h3>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/SidebarHint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ function SidebarHint() {
if (
albyMe &&
nodeConnectionInfo &&
albyMe?.keysend_pubkey !== nodeConnectionInfo?.pubkey
albyMe?.keysend_pubkey !== nodeConnectionInfo?.pubkey &&
!location.pathname.startsWith("/apps")
) {
return (
<SidebarHintCard
Expand Down
20 changes: 11 additions & 9 deletions frontend/src/components/connections/AlbyConnectionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,17 @@ function AlbyConnectionCard({ connection }: { connection?: App }) {
</ExternalLink>
</div>
</div>
<div>
<Link
to={`/apps/${connection?.nostrPubkey}`}
className="absolute top-0 right-0"
>
<EditIcon className="w-4 h-4 hidden group-hover:inline text-muted-foreground hover:text-card-foreground" />
</Link>
{connection && <AppCardConnectionInfo connection={connection} />}
</div>
{connection && (
<div>
<Link
to={`/apps/${connection.nostrPubkey}`}
className="absolute top-0 right-0"
>
<EditIcon className="w-4 h-4 hidden group-hover:inline text-muted-foreground hover:text-card-foreground" />
</Link>
<AppCardConnectionInfo connection={connection} />
</div>
)}
</div>
</CardContent>
</Card>
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/hooks/useLinkAccount.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useState } from "react";
import { toast } from "src/components/ui/use-toast";
import { useAlbyMe } from "src/hooks/useAlbyMe";
import { useApps } from "src/hooks/useApps";
import { useCSRF } from "src/hooks/useCSRF";
import { useNodeConnectionInfo } from "src/hooks/useNodeConnectionInfo";
import { request } from "src/utils/request";
Expand All @@ -14,6 +15,7 @@ export enum LinkStatus {
export function useLinkAccount() {
const { data: csrf } = useCSRF();
const { data: me, mutate: reloadAlbyMe } = useAlbyMe();
const { mutate: reloadApps } = useApps();
const { data: nodeConnectionInfo } = useNodeConnectionInfo();
const [loading, setLoading] = useState(false);

Expand Down Expand Up @@ -43,7 +45,8 @@ export function useLinkAccount() {
"Content-Type": "application/json",
},
});
await reloadAlbyMe();
// update the link status and get the newly-created Alby Account app
await Promise.all([reloadAlbyMe(), reloadApps()]);
toast({
title:
"Your Alby Hub has successfully been linked to your Alby Account",
Expand Down
13 changes: 7 additions & 6 deletions lnclient/ldk/ldk.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,10 +370,6 @@ func (ls *LDKService) resetRouterInternal() {
logger.Logger.WithFields(logrus.Fields{
"rowsAffected": rowsAffected,
}).Info("Reset router")

if err != nil {
logger.Logger.WithField("key", key).WithError(err).Error("ResetRouter failed")
}
}
}

Expand Down Expand Up @@ -1225,8 +1221,13 @@ func (ls *LDKService) handleLdkEvent(event *ldk_node.Event) {
Event: "nwc_payment_received",
Properties: &events.PaymentReceivedEventProperties{
PaymentHash: eventType.PaymentHash,
Amount: eventType.AmountMsat / 1000,
NodeType: config.LDKBackendType,
},
})
case ldk_node.EventPaymentSuccessful:
ls.eventPublisher.Publish(&events.Event{
Event: "nwc_payment_sent",
Properties: &events.PaymentSentEventProperties{
PaymentHash: eventType.PaymentHash,
},
})
}
Expand Down
38 changes: 24 additions & 14 deletions nip47/controllers/get_info_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,27 @@ package controllers

import (
"context"
"strings"

"github.com/getAlby/nostr-wallet-connect/db"
"github.com/getAlby/nostr-wallet-connect/lnclient"
"github.com/getAlby/nostr-wallet-connect/logger"
"github.com/getAlby/nostr-wallet-connect/nip47/models"
"github.com/getAlby/nostr-wallet-connect/nip47/notifications"
permissions "github.com/getAlby/nostr-wallet-connect/nip47/permissions"
"github.com/nbd-wtf/go-nostr"
"github.com/sirupsen/logrus"
)

type getInfoResponse struct {
Alias string `json:"alias"`
Color string `json:"color"`
Pubkey string `json:"pubkey"`
Network string `json:"network"`
BlockHeight uint32 `json:"block_height"`
BlockHash string `json:"block_hash"`
Methods []string `json:"methods"`
Alias string `json:"alias"`
Color string `json:"color"`
Pubkey string `json:"pubkey"`
Network string `json:"network"`
BlockHeight uint32 `json:"block_height"`
BlockHash string `json:"block_hash"`
Methods []string `json:"methods"`
Notifications []string `json:"notifications"`
}

type getInfoController struct {
Expand Down Expand Up @@ -68,14 +71,21 @@ func (controller *getInfoController) HandleGetInfoEvent(ctx context.Context, nip
network = "mainnet"
}

supportedNotifications := []string{}
if controller.permissionsService.PermitsNotifications(app) {
// TODO: this needs to be LNClient-specific
supportedNotifications = strings.Split(notifications.NOTIFICATION_TYPES, " ")
}

responsePayload := &getInfoResponse{
Alias: info.Alias,
Color: info.Color,
Pubkey: info.Pubkey,
Network: network,
BlockHeight: info.BlockHeight,
BlockHash: info.BlockHash,
Methods: controller.permissionsService.GetPermittedMethods(app),
Alias: info.Alias,
Color: info.Color,
Pubkey: info.Pubkey,
Network: network,
BlockHeight: info.BlockHeight,
BlockHash: info.BlockHash,
Methods: controller.permissionsService.GetPermittedMethods(app),
Notifications: supportedNotifications,
}

publishResponse(&models.Response{
Expand Down
62 changes: 62 additions & 0 deletions nip47/controllers/get_info_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,66 @@ func TestHandleGetInfoEvent_WithPermission(t *testing.T) {
assert.Equal(t, tests.MockNodeInfo.BlockHeight, nodeInfo.BlockHeight)
assert.Equal(t, tests.MockNodeInfo.BlockHash, nodeInfo.BlockHash)
assert.Equal(t, []string{"get_info"}, nodeInfo.Methods)
assert.Equal(t, []string{}, nodeInfo.Notifications)
}

func TestHandleGetInfoEvent_WithNotifications(t *testing.T) {
ctx := context.TODO()
defer tests.RemoveTestService()
svc, err := tests.CreateTestService()
assert.NoError(t, err)

app, _, err := tests.CreateApp(svc)
assert.NoError(t, err)

nip47Request := &models.Request{}
err = json.Unmarshal([]byte(nip47GetInfoJson), nip47Request)
assert.NoError(t, err)

dbRequestEvent := &db.RequestEvent{}
err = svc.DB.Create(&dbRequestEvent).Error
assert.NoError(t, err)

appPermission := &db.AppPermission{
AppId: app.ID,
RequestMethod: models.GET_INFO_METHOD,
ExpiresAt: nil,
}
err = svc.DB.Create(appPermission).Error
assert.NoError(t, err)

// TODO: AppPermission RequestMethod needs to change to scope
appPermission = &db.AppPermission{
AppId: app.ID,
RequestMethod: "notifications",
ExpiresAt: nil,
}
err = svc.DB.Create(appPermission).Error
assert.NoError(t, err)

checkPermission := func(amountMsat uint64) *models.Response {
return nil
}

var publishedResponse *models.Response

publishResponse := func(response *models.Response, tags nostr.Tags) {
publishedResponse = response
}

permissionsSvc := permissions.NewPermissionsService(svc.DB, svc.EventPublisher)

NewGetInfoController(permissionsSvc, svc.LNClient).
HandleGetInfoEvent(ctx, nip47Request, dbRequestEvent.ID, app, checkPermission, publishResponse)

assert.Nil(t, publishedResponse.Error)
nodeInfo := publishedResponse.Result.(*getInfoResponse)
assert.Equal(t, tests.MockNodeInfo.Alias, nodeInfo.Alias)
assert.Equal(t, tests.MockNodeInfo.Color, nodeInfo.Color)
assert.Equal(t, tests.MockNodeInfo.Pubkey, nodeInfo.Pubkey)
assert.Equal(t, tests.MockNodeInfo.Network, nodeInfo.Network)
assert.Equal(t, tests.MockNodeInfo.BlockHeight, nodeInfo.BlockHeight)
assert.Equal(t, tests.MockNodeInfo.BlockHash, nodeInfo.BlockHash)
assert.Equal(t, []string{"get_info"}, nodeInfo.Methods)
assert.Equal(t, []string{"payment_received", "payment_sent"}, nodeInfo.Notifications)
}
7 changes: 6 additions & 1 deletion nip47/notifications/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ type Notification struct {
}

const (
NOTIFICATION_TYPES = "payment_received" // e.g. "payment_received payment_sent balance_updated payment_sent channel_opened channel_closed ..."
NOTIFICATION_TYPES = "payment_received payment_sent"
PAYMENT_RECEIVED_NOTIFICATION = "payment_received"
PAYMENT_SENT_NOTIFICATION = "payment_sent"
)

type PaymentSentNotification struct {
models.Transaction
}

type PaymentReceivedNotification struct {
models.Transaction
}
65 changes: 46 additions & 19 deletions nip47/notifications/nip47_notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,29 +44,56 @@ func NewNip47Notifier(relay Relay, db *gorm.DB, cfg config.Config, keys keys.Key
}

func (notifier *Nip47Notifier) ConsumeEvent(ctx context.Context, event *events.Event) error {
if event.Event != "nwc_payment_received" {
return nil
}
switch event.Event {
case "nwc_payment_received":
paymentReceivedEventProperties, ok := event.Properties.(*events.PaymentReceivedEventProperties)
if !ok {
logger.Logger.WithField("event", event).Error("Failed to cast event")
return errors.New("failed to cast event")
}

paymentReceivedEventProperties, ok := event.Properties.(*events.PaymentReceivedEventProperties)
if !ok {
logger.Logger.WithField("event", event).Error("Failed to cast event")
return errors.New("failed to cast event")
}
transaction, err := notifier.lnClient.LookupInvoice(ctx, paymentReceivedEventProperties.PaymentHash)
if err != nil {
logger.Logger.
WithField("paymentHash", paymentReceivedEventProperties.PaymentHash).
WithError(err).
Error("Failed to lookup invoice by payment hash")
return err
}
notification := PaymentReceivedNotification{
Transaction: *transaction,
}

transaction, err := notifier.lnClient.LookupInvoice(ctx, paymentReceivedEventProperties.PaymentHash)
if err != nil {
logger.Logger.
WithField("paymentHash", paymentReceivedEventProperties.PaymentHash).
WithError(err).
Error("Failed to lookup invoice by payment hash")
return err
notifier.notifySubscribers(ctx, &Notification{
Notification: notification,
NotificationType: PAYMENT_RECEIVED_NOTIFICATION,
}, nostr.Tags{})

case "nwc_payment_sent":
paymentSentEventProperties, ok := event.Properties.(*events.PaymentSentEventProperties)
if !ok {
logger.Logger.WithField("event", event).Error("Failed to cast event")
return errors.New("failed to cast event")
}

transaction, err := notifier.lnClient.LookupInvoice(ctx, paymentSentEventProperties.PaymentHash)
if err != nil {
logger.Logger.
WithField("paymentHash", paymentSentEventProperties.PaymentHash).
WithError(err).
Error("Failed to lookup invoice by payment hash")
return err
}
notification := PaymentSentNotification{
Transaction: *transaction,
}

notifier.notifySubscribers(ctx, &Notification{
Notification: notification,
NotificationType: PAYMENT_SENT_NOTIFICATION,
}, nostr.Tags{})
}

notifier.notifySubscribers(ctx, &Notification{
Notification: transaction,
NotificationType: PAYMENT_RECEIVED_NOTIFICATION,
}, nostr.Tags{})
return nil
}

Expand Down
Loading

0 comments on commit f31cc33

Please sign in to comment.