alby-hub/nip47/notifications/nip47_notifier_test.go

312 lines
11 KiB
Go

package notifications
import (
"context"
"encoding/json"
"testing"
"time"
"github.com/getAlby/go-nostr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/getAlby/hub/constants"
"github.com/getAlby/hub/db"
"github.com/getAlby/hub/events"
"github.com/getAlby/hub/lnclient"
"github.com/getAlby/hub/nip47/permissions"
"github.com/getAlby/hub/tests"
)
type mockConsumer struct {
nip47NotificationQueue Nip47NotificationQueue
}
func NewMockConsumer(nip47NotificationQueue Nip47NotificationQueue) *mockConsumer {
return &mockConsumer{
nip47NotificationQueue: nip47NotificationQueue,
}
}
func (svc *mockConsumer) ConsumeEvent(ctx context.Context, event *events.Event, globalProperties map[string]interface{}) {
svc.nip47NotificationQueue.AddToQueue(event)
}
func doTestSendNotificationPaymentReceived(t *testing.T, svc *tests.TestService, createAppFn tests.CreateAppFn, nip47Encryption string) {
ctx := context.TODO()
app, cipher, err := createAppFn(svc, nostr.GeneratePrivateKey(), nip47Encryption)
assert.NoError(t, err)
appPermission := &db.AppPermission{
AppId: app.ID,
App: *app,
Scope: constants.NOTIFICATIONS_SCOPE,
}
err = svc.DB.Create(appPermission).Error
assert.NoError(t, err)
settledAt := time.Unix(*tests.MockLNClientTransaction.SettledAt, 0)
initialTransaction := db.Transaction{
Type: constants.TRANSACTION_TYPE_INCOMING,
PaymentRequest: tests.MockLNClientTransaction.Invoice,
Description: tests.MockLNClientTransaction.Description,
DescriptionHash: tests.MockLNClientTransaction.DescriptionHash,
Preimage: &tests.MockLNClientTransaction.Preimage,
PaymentHash: tests.MockLNClientTransaction.PaymentHash,
AmountMsat: uint64(tests.MockLNClientTransaction.AmountMsat),
FeeMsat: uint64(tests.MockLNClientTransaction.FeesPaidMsat),
SettledAt: &settledAt,
AppId: &app.ID,
State: constants.TRANSACTION_STATE_SETTLED,
}
err = svc.DB.Create(&initialTransaction).Error
assert.NoError(t, err)
nip47NotificationQueue := NewNip47NotificationQueue()
svc.EventPublisher.RegisterSubscriber(NewMockConsumer(nip47NotificationQueue))
testEvent := &events.Event{
Event: "nwc_payment_received",
Properties: &initialTransaction,
}
svc.EventPublisher.Publish(testEvent)
receivedEvent := <-nip47NotificationQueue.Channel()
assert.Equal(t, testEvent, receivedEvent)
pool := tests.NewMockSimplePool()
permissionsSvc := permissions.NewPermissionsService(svc.DB, svc.EventPublisher)
notifier := NewNip47Notifier(pool, svc.DB, svc.Cfg, svc.Keys, permissionsSvc)
notifier.ConsumeEvent(ctx, receivedEvent)
var publishedEvent *nostr.Event
if nip47Encryption == constants.ENCRYPTION_TYPE_NIP04 {
publishedEvent = pool.PublishedEvents[0]
} else {
publishedEvent = pool.PublishedEvents[1]
}
assert.NotNil(t, publishedEvent)
assert.NotEmpty(t, publishedEvent.Content)
decrypted, err := cipher.Decrypt(publishedEvent.Content)
assert.NoError(t, err)
unmarshalledResponse := Notification{
Notification: &PaymentReceivedNotification{},
}
err = json.Unmarshal([]byte(decrypted), &unmarshalledResponse)
assert.NoError(t, err)
assert.Equal(t, PAYMENT_RECEIVED_NOTIFICATION, unmarshalledResponse.NotificationType)
transaction := (unmarshalledResponse.Notification.(*PaymentReceivedNotification))
assert.Equal(t, constants.TRANSACTION_TYPE_INCOMING, transaction.Type)
assert.Equal(t, tests.MockLNClientTransaction.Invoice, transaction.Invoice)
assert.Equal(t, tests.MockLNClientTransaction.Description, transaction.Description)
assert.Equal(t, tests.MockLNClientTransaction.DescriptionHash, transaction.DescriptionHash)
assert.Equal(t, tests.MockLNClientTransaction.Preimage, transaction.Preimage)
assert.Equal(t, tests.MockLNClientTransaction.PaymentHash, transaction.PaymentHash)
assert.Equal(t, tests.MockLNClientTransaction.AmountMsat, transaction.Amount)
assert.Equal(t, tests.MockLNClientTransaction.FeesPaidMsat, transaction.FeesPaid)
assert.Equal(t, tests.MockLNClientTransaction.SettledAt, transaction.SettledAt)
}
func TestSendNotification_Nip04_PaymentReceived(t *testing.T) {
svc, err := tests.CreateTestService(t)
require.NoError(t, err)
defer svc.Remove()
doTestSendNotificationPaymentReceived(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP04)
}
func TestSendNotification_Nip44_PaymentReceived(t *testing.T) {
svc, err := tests.CreateTestService(t)
require.NoError(t, err)
defer svc.Remove()
doTestSendNotificationPaymentReceived(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
}
func TestSendNotification_SharedWalletPubkey_Nip04_PaymentReceived(t *testing.T) {
svc, err := tests.CreateTestService(t)
defer svc.Remove()
require.NoError(t, err)
doTestSendNotificationPaymentReceived(t, svc, tests.CreateAppWithSharedWalletPubkey, constants.ENCRYPTION_TYPE_NIP04)
}
func TestSendNotification_SharedWalletPubkey_Nip44_PaymentReceived(t *testing.T) {
svc, err := tests.CreateTestService(t)
defer svc.Remove()
require.NoError(t, err)
doTestSendNotificationPaymentReceived(t, svc, tests.CreateAppWithSharedWalletPubkey, constants.ENCRYPTION_TYPE_NIP44_V2)
}
func doTestSendNotificationPaymentSent(t *testing.T, svc *tests.TestService, createAppFn tests.CreateAppFn, nip47Encryption string) {
ctx := context.TODO()
app, cipher, err := createAppFn(svc, nostr.GeneratePrivateKey(), nip47Encryption)
assert.NoError(t, err)
appPermission := &db.AppPermission{
AppId: app.ID,
App: *app,
Scope: constants.NOTIFICATIONS_SCOPE,
}
err = svc.DB.Create(appPermission).Error
assert.NoError(t, err)
settledAt := time.Unix(*tests.MockLNClientTransaction.SettledAt, 0)
initialTransaction := db.Transaction{
Type: constants.TRANSACTION_TYPE_OUTGOING,
PaymentRequest: tests.MockLNClientTransaction.Invoice,
Description: tests.MockLNClientTransaction.Description,
DescriptionHash: tests.MockLNClientTransaction.DescriptionHash,
Preimage: &tests.MockLNClientTransaction.Preimage,
PaymentHash: tests.MockLNClientTransaction.PaymentHash,
AmountMsat: uint64(tests.MockLNClientTransaction.AmountMsat),
FeeMsat: uint64(tests.MockLNClientTransaction.FeesPaidMsat),
SettledAt: &settledAt,
AppId: &app.ID,
}
err = svc.DB.Create(&initialTransaction).Error
assert.NoError(t, err)
nip47NotificationQueue := NewNip47NotificationQueue()
svc.EventPublisher.RegisterSubscriber(NewMockConsumer(nip47NotificationQueue))
testEvent := &events.Event{
Event: "nwc_payment_sent",
Properties: &initialTransaction,
}
svc.EventPublisher.Publish(testEvent)
receivedEvent := <-nip47NotificationQueue.Channel()
assert.Equal(t, testEvent, receivedEvent)
pool := tests.NewMockSimplePool()
permissionsSvc := permissions.NewPermissionsService(svc.DB, svc.EventPublisher)
notifier := NewNip47Notifier(pool, svc.DB, svc.Cfg, svc.Keys, permissionsSvc)
notifier.ConsumeEvent(ctx, receivedEvent)
var publishedEvent *nostr.Event
if nip47Encryption == constants.ENCRYPTION_TYPE_NIP04 {
publishedEvent = pool.PublishedEvents[0]
} else {
publishedEvent = pool.PublishedEvents[1]
}
assert.NotNil(t, publishedEvent)
assert.NotEmpty(t, publishedEvent.Content)
decrypted, err := cipher.Decrypt(publishedEvent.Content)
assert.NoError(t, err)
unmarshalledResponse := Notification{
Notification: &PaymentReceivedNotification{},
}
err = json.Unmarshal([]byte(decrypted), &unmarshalledResponse)
assert.NoError(t, err)
assert.Equal(t, PAYMENT_SENT_NOTIFICATION, unmarshalledResponse.NotificationType)
transaction := (unmarshalledResponse.Notification.(*PaymentReceivedNotification))
assert.Equal(t, constants.TRANSACTION_TYPE_OUTGOING, transaction.Type)
assert.Equal(t, tests.MockLNClientTransaction.Invoice, transaction.Invoice)
assert.Equal(t, tests.MockLNClientTransaction.Description, transaction.Description)
assert.Equal(t, tests.MockLNClientTransaction.DescriptionHash, transaction.DescriptionHash)
assert.Equal(t, tests.MockLNClientTransaction.Preimage, transaction.Preimage)
assert.Equal(t, tests.MockLNClientTransaction.PaymentHash, transaction.PaymentHash)
assert.Equal(t, tests.MockLNClientTransaction.AmountMsat, transaction.Amount)
assert.Equal(t, tests.MockLNClientTransaction.FeesPaidMsat, transaction.FeesPaid)
assert.Equal(t, tests.MockLNClientTransaction.SettledAt, transaction.SettledAt)
}
func TestSendNotification_Nip04_PaymentSent(t *testing.T) {
svc, err := tests.CreateTestService(t)
require.NoError(t, err)
defer svc.Remove()
doTestSendNotificationPaymentSent(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP04)
}
func TestSendNotification_Nip44_PaymentSent(t *testing.T) {
svc, err := tests.CreateTestService(t)
require.NoError(t, err)
defer svc.Remove()
doTestSendNotificationPaymentSent(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
}
func TestSendNotification_SharedWalletPubkey_Nip04_PaymentSent(t *testing.T) {
svc, err := tests.CreateTestService(t)
require.NoError(t, err)
defer svc.Remove()
doTestSendNotificationPaymentSent(t, svc, tests.CreateAppWithSharedWalletPubkey, constants.ENCRYPTION_TYPE_NIP04)
}
func TestSendNotification_SharedWalletPubkey_Nip44_PaymentSent(t *testing.T) {
svc, err := tests.CreateTestService(t)
require.NoError(t, err)
defer svc.Remove()
doTestSendNotificationPaymentSent(t, svc, tests.CreateAppWithSharedWalletPubkey, constants.ENCRYPTION_TYPE_NIP44_V2)
}
func doTestSendNotificationNoPermission(t *testing.T, svc *tests.TestService) {
ctx := context.TODO()
svc.DB.Create(&db.Transaction{
PaymentHash: tests.MockPaymentHash,
})
nip47NotificationQueue := NewNip47NotificationQueue()
svc.EventPublisher.RegisterSubscriber(NewMockConsumer(nip47NotificationQueue))
testEvent := &events.Event{
Event: "nwc_payment_received",
Properties: &lnclient.Transaction{
PaymentHash: tests.MockPaymentHash,
},
}
svc.EventPublisher.Publish(testEvent)
receivedEvent := <-nip47NotificationQueue.Channel()
assert.Equal(t, testEvent, receivedEvent)
pool := tests.NewMockSimplePool()
permissionsSvc := permissions.NewPermissionsService(svc.DB, svc.EventPublisher)
notifier := NewNip47Notifier(pool, svc.DB, svc.Cfg, svc.Keys, permissionsSvc)
notifier.ConsumeEvent(ctx, receivedEvent)
assert.Nil(t, pool.PublishedEvents)
}
func TestSendNotification_NoPermission(t *testing.T) {
svc, err := tests.CreateTestService(t)
require.NoError(t, err)
defer svc.Remove()
_, _, err = tests.CreateAppWithPrivateKey(svc, nostr.GeneratePrivateKey(), constants.ENCRYPTION_TYPE_NIP44_V2)
assert.NoError(t, err)
doTestSendNotificationNoPermission(t, svc)
}
func TestSendNotification_SharedWalletPubkey_NoPermission(t *testing.T) {
svc, err := tests.CreateTestService(t)
require.NoError(t, err)
defer svc.Remove()
_, _, err = tests.CreateAppWithSharedWalletPubkey(svc, nostr.GeneratePrivateKey(), constants.ENCRYPTION_TYPE_NIP44_V2)
assert.NoError(t, err)
doTestSendNotificationNoPermission(t, svc)
}