event_handler_test.go raw

   1  package nip47
   2  
   3  import (
   4  	"context"
   5  	"encoding/json"
   6  	"slices"
   7  	"testing"
   8  	"time"
   9  
  10  	"github.com/getAlby/go-nostr"
  11  	"github.com/stretchr/testify/assert"
  12  	"github.com/stretchr/testify/require"
  13  
  14  	"github.com/getAlby/hub/alby"
  15  	"github.com/getAlby/hub/constants"
  16  	"github.com/getAlby/hub/db"
  17  	"github.com/getAlby/hub/nip47/cipher"
  18  	"github.com/getAlby/hub/nip47/models"
  19  	"github.com/getAlby/hub/nip47/permissions"
  20  	"github.com/getAlby/hub/tests"
  21  )
  22  
  23  // TODO: test if an app doesn't exist it returns the right error code
  24  
  25  func TestCreateResponse_Nip04(t *testing.T) {
  26  	svc, err := tests.CreateTestService(t)
  27  	require.NoError(t, err)
  28  	defer svc.Remove()
  29  
  30  	doTestCreateResponse(t, svc, constants.ENCRYPTION_TYPE_NIP04)
  31  }
  32  
  33  func TestCreateResponse_Nip44(t *testing.T) {
  34  	svc, err := tests.CreateTestService(t)
  35  	require.NoError(t, err)
  36  	defer svc.Remove()
  37  
  38  	doTestCreateResponse(t, svc, constants.ENCRYPTION_TYPE_NIP44_V2)
  39  }
  40  
  41  func doTestCreateResponse(t *testing.T, svc *tests.TestService, nip47Encryption string) {
  42  	reqPrivateKey := nostr.GeneratePrivateKey()
  43  	reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
  44  	assert.NoError(t, err)
  45  
  46  	reqEvent := &nostr.Event{
  47  		Kind:    models.REQUEST_KIND,
  48  		PubKey:  reqPubkey,
  49  		Content: "1",
  50  	}
  51  
  52  	reqEvent.ID = "12345"
  53  
  54  	nip47Cipher, err := cipher.NewNip47Cipher(nip47Encryption, reqPubkey, svc.Keys.GetNostrSecretKey())
  55  	assert.NoError(t, err)
  56  
  57  	type dummyResponse struct {
  58  		Foo int
  59  	}
  60  
  61  	nip47Response := &models.Response{
  62  		ResultType: "dummy_method",
  63  		Result: dummyResponse{
  64  			Foo: 1000,
  65  		},
  66  	}
  67  
  68  	albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
  69  	nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
  70  
  71  	res, err := nip47svc.CreateResponse(reqEvent, nip47Response, nostr.Tags{}, nip47Cipher, svc.Keys.GetNostrSecretKey())
  72  	assert.NoError(t, err)
  73  	assert.Equal(t, reqPubkey, res.Tags.Find("p")[1])
  74  	assert.Equal(t, reqEvent.ID, res.Tags.Find("e")[1])
  75  	assert.Equal(t, svc.Keys.GetNostrPublicKey(), res.PubKey)
  76  
  77  	decrypted, err := nip47Cipher.Decrypt(res.Content)
  78  	assert.NoError(t, err)
  79  	unmarshalledResponse := models.Response{
  80  		Result: &dummyResponse{},
  81  	}
  82  
  83  	err = json.Unmarshal([]byte(decrypted), &unmarshalledResponse)
  84  	assert.NoError(t, err)
  85  	assert.Nil(t, nip47Response.Error)
  86  	assert.Equal(t, nip47Response.ResultType, unmarshalledResponse.ResultType)
  87  	assert.Equal(t, nip47Response.Result, *unmarshalledResponse.Result.(*dummyResponse))
  88  }
  89  
  90  func TestHandleResponse_Nip04_WithPermission(t *testing.T) {
  91  	svc, err := tests.CreateTestService(t)
  92  	require.NoError(t, err)
  93  	defer svc.Remove()
  94  
  95  	doTestHandleResponse_WithPermission(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP04)
  96  }
  97  
  98  func TestHandleResponse_Nip44_WithPermission(t *testing.T) {
  99  	svc, err := tests.CreateTestService(t)
 100  	require.NoError(t, err)
 101  	defer svc.Remove()
 102  
 103  	doTestHandleResponse_WithPermission(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
 104  }
 105  
 106  func doTestHandleResponse_WithPermission(t *testing.T, svc *tests.TestService, createAppFn tests.CreateAppFn, encryption string) {
 107  	albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
 108  	nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
 109  
 110  	reqPrivateKey := nostr.GeneratePrivateKey()
 111  	reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
 112  	assert.NoError(t, err)
 113  
 114  	app, cipher, err := createAppFn(svc, reqPrivateKey, encryption)
 115  	assert.NoError(t, err)
 116  
 117  	appPermission := &db.AppPermission{
 118  		AppId: app.ID,
 119  		App:   *app,
 120  		Scope: constants.GET_BALANCE_SCOPE,
 121  	}
 122  	err = svc.DB.Create(appPermission).Error
 123  	assert.NoError(t, err)
 124  
 125  	content := map[string]interface{}{
 126  		"method": models.GET_INFO_METHOD,
 127  	}
 128  
 129  	payloadBytes, err := json.Marshal(content)
 130  	assert.NoError(t, err)
 131  
 132  	msg, err := cipher.Encrypt(string(payloadBytes))
 133  	assert.NoError(t, err)
 134  
 135  	reqEvent := &nostr.Event{
 136  		Kind:      models.REQUEST_KIND,
 137  		PubKey:    reqPubkey,
 138  		CreatedAt: nostr.Now(),
 139  		Tags:      nostr.Tags{},
 140  		Content:   msg,
 141  	}
 142  
 143  	if encryption != constants.ENCRYPTION_TYPE_NIP04 {
 144  		reqEvent.Tags = append(reqEvent.Tags, []string{"encryption", encryption})
 145  	}
 146  
 147  	err = reqEvent.Sign(reqPrivateKey)
 148  	assert.NoError(t, err)
 149  
 150  	pool := tests.NewMockSimplePool()
 151  
 152  	nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
 153  
 154  	assert.NotNil(t, pool.PublishedEvents[0])
 155  	assert.NotEmpty(t, pool.PublishedEvents[0].Content)
 156  
 157  	decrypted, err := cipher.Decrypt(pool.PublishedEvents[0].Content)
 158  	assert.NoError(t, err)
 159  
 160  	type getInfoResult struct {
 161  		Methods []string `json:"methods"`
 162  	}
 163  
 164  	type getInfoResponseWrapper struct {
 165  		models.Response
 166  		Result getInfoResult `json:"result"`
 167  	}
 168  
 169  	unmarshalledResponse := getInfoResponseWrapper{}
 170  
 171  	err = json.Unmarshal([]byte(decrypted), &unmarshalledResponse)
 172  	assert.NoError(t, err)
 173  	assert.Nil(t, unmarshalledResponse.Error)
 174  	assert.Equal(t, models.GET_INFO_METHOD, unmarshalledResponse.ResultType)
 175  	expectedMethods := slices.Concat([]string{constants.GET_BALANCE_SCOPE}, permissions.GetAlwaysGrantedMethods())
 176  	assert.ElementsMatch(t, expectedMethods, unmarshalledResponse.Result.Methods)
 177  }
 178  
 179  func TestHandleResponse_Nip04_DuplicateRequest(t *testing.T) {
 180  	svc, err := tests.CreateTestService(t)
 181  	require.NoError(t, err)
 182  	defer svc.Remove()
 183  
 184  	doTestHandleResponse_DuplicateRequest(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP04)
 185  }
 186  
 187  func TestHandleResponse_Nip44_DuplicateRequest(t *testing.T) {
 188  	svc, err := tests.CreateTestService(t)
 189  	require.NoError(t, err)
 190  	defer svc.Remove()
 191  
 192  	doTestHandleResponse_DuplicateRequest(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
 193  }
 194  
 195  func doTestHandleResponse_DuplicateRequest(t *testing.T, svc *tests.TestService, createAppFn tests.CreateAppFn, encryption string) {
 196  	albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
 197  	nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
 198  
 199  	reqPrivateKey := nostr.GeneratePrivateKey()
 200  	reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
 201  	assert.NoError(t, err)
 202  
 203  	app, cipher, err := createAppFn(svc, reqPrivateKey, encryption)
 204  	assert.NoError(t, err)
 205  
 206  	appPermission := &db.AppPermission{
 207  		AppId: app.ID,
 208  		App:   *app,
 209  		Scope: constants.GET_BALANCE_SCOPE,
 210  	}
 211  	err = svc.DB.Create(appPermission).Error
 212  	assert.NoError(t, err)
 213  
 214  	content := map[string]interface{}{
 215  		"method": models.GET_INFO_METHOD,
 216  	}
 217  
 218  	payloadBytes, err := json.Marshal(content)
 219  	assert.NoError(t, err)
 220  
 221  	msg, err := cipher.Encrypt(string(payloadBytes))
 222  	assert.NoError(t, err)
 223  
 224  	reqEvent := &nostr.Event{
 225  		Kind:      models.REQUEST_KIND,
 226  		PubKey:    reqPubkey,
 227  		CreatedAt: nostr.Now(),
 228  		Tags:      nostr.Tags{},
 229  		Content:   msg,
 230  	}
 231  
 232  	if encryption != constants.ENCRYPTION_TYPE_NIP04 {
 233  		reqEvent.Tags = append(reqEvent.Tags, []string{"encryption", encryption})
 234  	}
 235  
 236  	err = reqEvent.Sign(reqPrivateKey)
 237  	assert.NoError(t, err)
 238  
 239  	pool := tests.NewMockSimplePool()
 240  
 241  	nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
 242  
 243  	assert.NotNil(t, pool.PublishedEvents[0])
 244  	assert.NotEmpty(t, pool.PublishedEvents[0].Content)
 245  
 246  	pool.PublishedEvents = nil
 247  
 248  	nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
 249  
 250  	// second time it should not publish
 251  	assert.Nil(t, pool.PublishedEvents)
 252  }
 253  
 254  func TestHandleResponse_Nip04_NoPermission(t *testing.T) {
 255  	svc, err := tests.CreateTestService(t)
 256  	require.NoError(t, err)
 257  	defer svc.Remove()
 258  
 259  	doTestHandleResponse_NoPermission(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP04)
 260  }
 261  
 262  func TestHandleResponse_Nip44_NoPermission(t *testing.T) {
 263  	svc, err := tests.CreateTestService(t)
 264  	require.NoError(t, err)
 265  	defer svc.Remove()
 266  
 267  	doTestHandleResponse_NoPermission(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
 268  }
 269  
 270  func doTestHandleResponse_NoPermission(t *testing.T, svc *tests.TestService, createAppFn tests.CreateAppFn, encryption string) {
 271  	albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
 272  	nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
 273  
 274  	reqPrivateKey := nostr.GeneratePrivateKey()
 275  	reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
 276  	assert.NoError(t, err)
 277  
 278  	_, cipher, err := createAppFn(svc, reqPrivateKey, encryption)
 279  	assert.NoError(t, err)
 280  
 281  	content := map[string]interface{}{
 282  		"method": models.GET_BALANCE_METHOD,
 283  	}
 284  
 285  	payloadBytes, err := json.Marshal(content)
 286  	assert.NoError(t, err)
 287  
 288  	msg, err := cipher.Encrypt(string(payloadBytes))
 289  	assert.NoError(t, err)
 290  
 291  	reqEvent := &nostr.Event{
 292  		Kind:      models.REQUEST_KIND,
 293  		PubKey:    reqPubkey,
 294  		CreatedAt: nostr.Now(),
 295  		Tags:      nostr.Tags{},
 296  		Content:   msg,
 297  	}
 298  
 299  	if encryption != constants.ENCRYPTION_TYPE_NIP04 {
 300  		reqEvent.Tags = append(reqEvent.Tags, []string{"encryption", encryption})
 301  	}
 302  
 303  	err = reqEvent.Sign(reqPrivateKey)
 304  	assert.NoError(t, err)
 305  
 306  	pool := tests.NewMockSimplePool()
 307  
 308  	nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
 309  
 310  	assert.NotNil(t, pool.PublishedEvents[0])
 311  	assert.NotEmpty(t, pool.PublishedEvents[0].Content)
 312  
 313  	decrypted, err := cipher.Decrypt(pool.PublishedEvents[0].Content)
 314  	assert.NoError(t, err)
 315  
 316  	unmarshalledResponse := models.Response{}
 317  
 318  	err = json.Unmarshal([]byte(decrypted), &unmarshalledResponse)
 319  	assert.NoError(t, err)
 320  	assert.Nil(t, unmarshalledResponse.Result)
 321  	assert.Equal(t, models.GET_BALANCE_METHOD, unmarshalledResponse.ResultType)
 322  	assert.Equal(t, "RESTRICTED", unmarshalledResponse.Error.Code)
 323  	assert.Equal(t, "This app does not have the get_balance scope", unmarshalledResponse.Error.Message)
 324  }
 325  
 326  func TestHandleResponse_Nip04_OldRequestForPayment(t *testing.T) {
 327  	svc, err := tests.CreateTestService(t)
 328  	require.NoError(t, err)
 329  	defer svc.Remove()
 330  
 331  	doTestHandleResponse_OldRequestForPayment(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP04)
 332  }
 333  
 334  func TestHandleResponse_Nip44_OldRequestForPayment(t *testing.T) {
 335  	svc, err := tests.CreateTestService(t)
 336  	require.NoError(t, err)
 337  	defer svc.Remove()
 338  
 339  	doTestHandleResponse_OldRequestForPayment(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
 340  }
 341  
 342  func doTestHandleResponse_OldRequestForPayment(t *testing.T, svc *tests.TestService, createAppFn tests.CreateAppFn, encryption string) {
 343  	albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
 344  	nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
 345  
 346  	reqPrivateKey := nostr.GeneratePrivateKey()
 347  	reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
 348  	assert.NoError(t, err)
 349  
 350  	app, cipher, err := createAppFn(svc, reqPrivateKey, encryption)
 351  	assert.NoError(t, err)
 352  
 353  	content := map[string]interface{}{
 354  		"method": models.PAY_INVOICE_METHOD,
 355  	}
 356  
 357  	appPermission := &db.AppPermission{
 358  		AppId: app.ID,
 359  		App:   *app,
 360  		Scope: constants.PAY_INVOICE_SCOPE,
 361  	}
 362  	err = svc.DB.Create(appPermission).Error
 363  	assert.NoError(t, err)
 364  
 365  	payloadBytes, err := json.Marshal(content)
 366  	assert.NoError(t, err)
 367  
 368  	msg, err := cipher.Encrypt(string(payloadBytes))
 369  	assert.NoError(t, err)
 370  
 371  	reqEvent := &nostr.Event{
 372  		Kind:      models.REQUEST_KIND,
 373  		PubKey:    reqPubkey,
 374  		CreatedAt: nostr.Timestamp(time.Now().Add(time.Duration(-6) * time.Hour).Unix()),
 375  		Tags:      nostr.Tags{},
 376  		Content:   msg,
 377  	}
 378  
 379  	if encryption != constants.ENCRYPTION_TYPE_NIP04 {
 380  		reqEvent.Tags = append(reqEvent.Tags, []string{"encryption", encryption})
 381  	}
 382  
 383  	err = reqEvent.Sign(reqPrivateKey)
 384  	assert.NoError(t, err)
 385  
 386  	pool := tests.NewMockSimplePool()
 387  
 388  	nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
 389  
 390  	// it shouldn't return anything for an old request
 391  	assert.Nil(t, pool.PublishedEvents)
 392  
 393  	// change the request to now
 394  	reqEvent.CreatedAt = nostr.Now()
 395  	err = reqEvent.Sign(reqPrivateKey)
 396  	assert.NoError(t, err)
 397  
 398  	nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
 399  	assert.NotNil(t, pool.PublishedEvents)
 400  }
 401  
 402  func TestHandleResponse_Nip04_IncorrectPubkey(t *testing.T) {
 403  	svc, err := tests.CreateTestService(t)
 404  	require.NoError(t, err)
 405  	defer svc.Remove()
 406  
 407  	doTestHandleResponse_IncorrectPubkey(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP04)
 408  }
 409  
 410  func TestHandleResponse_Nip44_IncorrectPubkey(t *testing.T) {
 411  	svc, err := tests.CreateTestService(t)
 412  	require.NoError(t, err)
 413  	defer svc.Remove()
 414  
 415  	doTestHandleResponse_IncorrectPubkey(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
 416  }
 417  
 418  func doTestHandleResponse_IncorrectPubkey(t *testing.T, svc *tests.TestService, createAppFn tests.CreateAppFn, encryption string) {
 419  	albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
 420  	nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
 421  
 422  	reqPrivateKey := nostr.GeneratePrivateKey()
 423  	reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
 424  	assert.NoError(t, err)
 425  
 426  	reqPrivateKey2 := nostr.GeneratePrivateKey()
 427  
 428  	app, cipher, err := createAppFn(svc, reqPrivateKey, encryption)
 429  	assert.NoError(t, err)
 430  
 431  	appPermission := &db.AppPermission{
 432  		AppId: app.ID,
 433  		App:   *app,
 434  		Scope: constants.GET_BALANCE_SCOPE,
 435  	}
 436  	err = svc.DB.Create(appPermission).Error
 437  	assert.NoError(t, err)
 438  
 439  	content := map[string]interface{}{
 440  		"method": models.GET_BALANCE_METHOD,
 441  	}
 442  
 443  	payloadBytes, err := json.Marshal(content)
 444  	assert.NoError(t, err)
 445  
 446  	msg, err := cipher.Encrypt(string(payloadBytes))
 447  	assert.NoError(t, err)
 448  
 449  	reqEvent := &nostr.Event{
 450  		Kind:      models.REQUEST_KIND,
 451  		CreatedAt: nostr.Now(),
 452  		Tags:      nostr.Tags{},
 453  		Content:   msg,
 454  	}
 455  
 456  	if encryption != constants.ENCRYPTION_TYPE_NIP04 {
 457  		reqEvent.Tags = append(reqEvent.Tags, []string{"encryption", encryption})
 458  	}
 459  
 460  	err = reqEvent.Sign(reqPrivateKey2)
 461  	assert.NoError(t, err)
 462  
 463  	// set a different pubkey (this will not pass validation)
 464  	reqEvent.PubKey = reqPubkey
 465  
 466  	pool := tests.NewMockSimplePool()
 467  
 468  	nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
 469  
 470  	assert.Nil(t, pool.PublishedEvents)
 471  }
 472  
 473  func TestHandleResponse_NoApp(t *testing.T) {
 474  	svc, err := tests.CreateTestService(t)
 475  	require.NoError(t, err)
 476  	defer svc.Remove()
 477  	albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
 478  	nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
 479  
 480  	reqPrivateKey := nostr.GeneratePrivateKey()
 481  	reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
 482  	assert.NoError(t, err)
 483  
 484  	app, cipher, err := tests.CreateAppWithPrivateKey(svc, reqPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
 485  	assert.NoError(t, err)
 486  
 487  	// delete the app
 488  	err = svc.DB.Delete(app).Error
 489  	assert.NoError(t, err)
 490  
 491  	content := map[string]interface{}{
 492  		"method": models.GET_BALANCE_METHOD,
 493  	}
 494  
 495  	payloadBytes, err := json.Marshal(content)
 496  	assert.NoError(t, err)
 497  
 498  	msg, err := cipher.Encrypt(string(payloadBytes))
 499  	assert.NoError(t, err)
 500  
 501  	reqEvent := &nostr.Event{
 502  		Kind:      models.REQUEST_KIND,
 503  		PubKey:    reqPubkey,
 504  		CreatedAt: nostr.Now(),
 505  		Tags:      nostr.Tags{[]string{"encryption", constants.ENCRYPTION_TYPE_NIP44_V2}},
 506  		Content:   msg,
 507  	}
 508  	err = reqEvent.Sign(reqPrivateKey)
 509  	assert.NoError(t, err)
 510  
 511  	pool := tests.NewMockSimplePool()
 512  
 513  	nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
 514  
 515  	// it shouldn't return anything for an invalid app key
 516  	assert.Nil(t, pool.PublishedEvents)
 517  }
 518  
 519  func TestHandleResponse_UnknownEncryptionTag(t *testing.T) {
 520  	svc, err := tests.CreateTestService(t)
 521  	require.NoError(t, err)
 522  	defer svc.Remove()
 523  	doTestHandleResponse_UnknownEncryptionTag(t, svc, "nip44")
 524  	doTestHandleResponse_UnknownEncryptionTag(t, svc, "nip44v2")
 525  	doTestHandleResponse_UnknownEncryptionTag(t, svc, "nip44_v3")
 526  	doTestHandleResponse_UnknownEncryptionTag(t, svc, "")
 527  }
 528  
 529  func doTestHandleResponse_UnknownEncryptionTag(t *testing.T, svc *tests.TestService, requestEncryptionTag string) {
 530  	albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
 531  	nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
 532  
 533  	reqPrivateKey := nostr.GeneratePrivateKey()
 534  	reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
 535  	assert.NoError(t, err)
 536  
 537  	app, cipher, err := tests.CreateAppWithPrivateKey(svc, reqPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
 538  	assert.NoError(t, err)
 539  
 540  	appPermission := &db.AppPermission{
 541  		AppId: app.ID,
 542  		App:   *app,
 543  		Scope: constants.GET_BALANCE_SCOPE,
 544  	}
 545  	err = svc.DB.Create(appPermission).Error
 546  	assert.NoError(t, err)
 547  
 548  	content := map[string]interface{}{
 549  		"method": models.GET_INFO_METHOD,
 550  	}
 551  
 552  	payloadBytes, err := json.Marshal(content)
 553  	assert.NoError(t, err)
 554  
 555  	msg, err := cipher.Encrypt(string(payloadBytes))
 556  	assert.NoError(t, err)
 557  
 558  	// don't pass correct encryption
 559  	reqEvent := &nostr.Event{
 560  		Kind:      models.REQUEST_KIND,
 561  		PubKey:    reqPubkey,
 562  		CreatedAt: nostr.Now(),
 563  		Tags:      nostr.Tags{[]string{"encryption", requestEncryptionTag}},
 564  		Content:   msg,
 565  	}
 566  
 567  	err = reqEvent.Sign(reqPrivateKey)
 568  	assert.NoError(t, err)
 569  
 570  	pool := tests.NewMockSimplePool()
 571  
 572  	nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
 573  
 574  	assert.NotNil(t, pool.PublishedEvents)
 575  	responseContent := pool.PublishedEvents[0].Content
 576  	msg, err = cipher.Decrypt(responseContent)
 577  	assert.NoError(t, err)
 578  	assert.NotEqual(t, "", msg)
 579  
 580  	unmarshalledResponse := models.Response{}
 581  
 582  	err = json.Unmarshal([]byte(msg), &unmarshalledResponse)
 583  	assert.NoError(t, err)
 584  	assert.Nil(t, unmarshalledResponse.Result)
 585  	// assert.Equal(t, models.GET_INFO_METHOD, unmarshalledResponse.ResultType)
 586  	assert.Equal(t, constants.ERROR_UNSUPPORTED_ENCRYPTION, unmarshalledResponse.Error.Code)
 587  	assert.Contains(t, unmarshalledResponse.Error.Message, "invalid encryption:")
 588  }
 589  
 590  func TestHandleResponse_EncryptionTagDoesNotMatchPayload(t *testing.T) {
 591  	svc, err := tests.CreateTestService(t)
 592  	require.NoError(t, err)
 593  	defer svc.Remove()
 594  	// encryption specifies what cipher will use. If constants.ENCRYPTION_TYPE_NIP44_V2 is passed,
 595  	// cipher must be NIP-44, otherwise cipher MUST be NIP-04
 596  	doTestHandleResponse_EncryptionTagDoesNotMatchPayload(t, svc, constants.ENCRYPTION_TYPE_NIP44_V2, constants.ENCRYPTION_TYPE_NIP04)
 597  	doTestHandleResponse_EncryptionTagDoesNotMatchPayload(t, svc, constants.ENCRYPTION_TYPE_NIP04, constants.ENCRYPTION_TYPE_NIP44_V2)
 598  	doTestHandleResponse_EncryptionTagDoesNotMatchPayload(t, svc, constants.ENCRYPTION_TYPE_NIP44_V2, "")
 599  }
 600  
 601  func doTestHandleResponse_EncryptionTagDoesNotMatchPayload(t *testing.T, svc *tests.TestService, requestEncryption, requestEncryptionTag string) {
 602  	albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
 603  	nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
 604  
 605  	reqPrivateKey := nostr.GeneratePrivateKey()
 606  	reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
 607  	assert.NoError(t, err)
 608  
 609  	app, _, err := tests.CreateAppWithPrivateKey(svc, reqPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
 610  	assert.NoError(t, err)
 611  
 612  	appPermission := &db.AppPermission{
 613  		AppId: app.ID,
 614  		App:   *app,
 615  		Scope: constants.GET_BALANCE_SCOPE,
 616  	}
 617  	err = svc.DB.Create(appPermission).Error
 618  	assert.NoError(t, err)
 619  
 620  	content := map[string]interface{}{
 621  		"method": models.GET_INFO_METHOD,
 622  	}
 623  
 624  	payloadBytes, err := json.Marshal(content)
 625  	assert.NoError(t, err)
 626  
 627  	reqCipher, err := cipher.NewNip47Cipher(requestEncryption, *app.WalletPubkey, reqPrivateKey)
 628  	assert.NoError(t, err)
 629  	// whenever we are unable to handle the request encryption, we always respond with our preferred encryption (NIP44)
 630  	nip44Cipher, err := cipher.NewNip47Cipher(constants.ENCRYPTION_TYPE_NIP44_V2, *app.WalletPubkey, reqPrivateKey)
 631  	assert.NoError(t, err)
 632  	msg, err := reqCipher.Encrypt(string(payloadBytes))
 633  	assert.NoError(t, err)
 634  
 635  	// don't pass correct encryption
 636  	reqEvent := &nostr.Event{
 637  		Kind:      models.REQUEST_KIND,
 638  		PubKey:    reqPubkey,
 639  		CreatedAt: nostr.Now(),
 640  		Tags:      nostr.Tags{},
 641  		Content:   msg,
 642  	}
 643  
 644  	if requestEncryptionTag != "" {
 645  		reqEvent.Tags = append(reqEvent.Tags, []string{"encryption", requestEncryptionTag})
 646  	}
 647  
 648  	err = reqEvent.Sign(reqPrivateKey)
 649  	assert.NoError(t, err)
 650  
 651  	pool := tests.NewMockSimplePool()
 652  
 653  	nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
 654  
 655  	assert.NotNil(t, pool.PublishedEvents)
 656  	responseContent := pool.PublishedEvents[0].Content
 657  	msg, err = nip44Cipher.Decrypt(responseContent)
 658  	assert.NoError(t, err)
 659  	assert.NotEqual(t, "", msg)
 660  
 661  	unmarshalledResponse := models.Response{}
 662  	err = json.Unmarshal([]byte(msg), &unmarshalledResponse)
 663  	assert.NoError(t, err)
 664  	assert.Nil(t, unmarshalledResponse.Result)
 665  	// assert.Equal(t, models.GET_INFO_METHOD, unmarshalledResponse.ResultType)
 666  	assert.Equal(t, constants.ERROR_BAD_REQUEST, unmarshalledResponse.Error.Code)
 667  	assert.Contains(t, unmarshalledResponse.Error.Message, "failed to decrypt:")
 668  }
 669