settle_hold_invoice_controller_test.go raw
1 package controllers
2
3 import (
4 "context"
5 "encoding/json"
6 "testing"
7
8 "github.com/getAlby/go-nostr"
9 "github.com/stretchr/testify/assert"
10 "github.com/stretchr/testify/require"
11
12 "time"
13
14 "github.com/getAlby/hub/constants"
15 "github.com/getAlby/hub/db"
16
17 "crypto/sha256"
18 "encoding/hex"
19
20 "github.com/getAlby/hub/nip47/models"
21 "github.com/getAlby/hub/tests"
22 )
23
24 const nip47SettleHoldInvoiceJson = `
25 {
26 "method": "settle_hold_invoice",
27 "params": {
28 "preimage": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
29 }
30 }
31 `
32
33 const testSettlePreimage = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
34 const testSettlePaymentHash = "b7e060a60bb7a82f536a73c17bde37a1b6cf5769ee4a8325bff76c55a95b6aa4"
35
36 type settleHoldInvoiceTestSetup struct {
37 ctx context.Context
38 svc *tests.TestService
39 nip47Request *models.Request
40 app *db.App
41 dbRequestEvent *db.RequestEvent
42 publishCalled bool
43 response *models.Response
44 }
45
46 func setupSettleHoldInvoiceTest(t *testing.T, preimage string, paymentHashToCreate string, initialTransactionState string) *settleHoldInvoiceTestSetup {
47 ctx := context.TODO()
48 svc, err := tests.CreateTestService(t)
49 require.NoError(t, err)
50
51 nip47Request := &models.Request{}
52 requestJson := `
53 {
54 "method": "settle_hold_invoice",
55 "params": {
56 "preimage": "` + preimage + `"
57 }
58 }
59 `
60 err = json.Unmarshal([]byte(requestJson), nip47Request)
61 require.NoError(t, err)
62
63 app, _, err := tests.CreateApp(svc)
64 require.NoError(t, err)
65
66 appPermission := &db.AppPermission{
67 AppId: app.ID,
68 Scope: constants.MAKE_INVOICE_SCOPE,
69 }
70 err = svc.DB.Create(appPermission).Error
71 require.NoError(t, err)
72
73 if paymentHashToCreate != "" && initialTransactionState != "" {
74 expiresAtVar := time.Now().Add(1 * time.Hour)
75 appIDForTx := app.ID
76 holdInvoice := &db.Transaction{
77 AppId: &appIDForTx,
78 Type: constants.TRANSACTION_TYPE_INCOMING,
79 State: initialTransactionState,
80 PaymentHash: paymentHashToCreate,
81 AmountMsat: 1000,
82 ExpiresAt: &expiresAtVar,
83 }
84 err = svc.DB.Create(holdInvoice).Error
85 require.NoError(t, err)
86 }
87
88 dbRequestEvent := &db.RequestEvent{
89 AppId: &app.ID,
90 }
91 err = svc.DB.Create(&dbRequestEvent).Error
92 require.NoError(t, err)
93
94 setup := &settleHoldInvoiceTestSetup{
95 ctx: ctx,
96 svc: svc,
97 nip47Request: nip47Request,
98 app: app,
99 dbRequestEvent: dbRequestEvent,
100 }
101 return setup
102 }
103
104 func (s *settleHoldInvoiceTestSetup) TearDown() {
105 s.svc.Remove()
106 }
107
108 func (s *settleHoldInvoiceTestSetup) PublishResponse(response *models.Response, tags nostr.Tags) {
109 s.publishCalled = true
110 s.response = response
111 }
112
113 func TestHandleSettleHoldInvoiceEvent(t *testing.T) {
114 preimageBytesForCheck, err := hex.DecodeString(testSettlePreimage)
115 require.NoError(t, err)
116 calculatedHashBytesForCheck := sha256.Sum256(preimageBytesForCheck)
117 calculatedPaymentHashForCheck := hex.EncodeToString(calculatedHashBytesForCheck[:])
118 assert.Equal(t, testSettlePaymentHash, calculatedPaymentHashForCheck)
119
120 setup := setupSettleHoldInvoiceTest(t, testSettlePreimage, testSettlePaymentHash, constants.TRANSACTION_STATE_ACCEPTED)
121 defer setup.TearDown()
122
123 controller := NewTestNip47Controller(setup.svc)
124
125 controller.HandleSettleHoldInvoiceEvent(setup.ctx, setup.nip47Request, setup.dbRequestEvent.ID, *setup.dbRequestEvent.AppId, setup.PublishResponse)
126
127 assert.True(t, setup.publishCalled)
128 assert.Nil(t, setup.response.Error)
129 assert.Equal(t, &settleHoldInvoiceResponse{}, setup.response.Result)
130
131 var settledTx db.Transaction
132 err = setup.svc.DB.First(&settledTx, "payment_hash = ?", testSettlePaymentHash).Error
133 assert.NoError(t, err)
134 assert.Equal(t, constants.TRANSACTION_STATE_SETTLED, settledTx.State)
135 assert.NotNil(t, settledTx.Preimage)
136 assert.Equal(t, testSettlePreimage, *settledTx.Preimage)
137 }
138
139 func TestHandleSettleHoldInvoiceEvent_InvalidPreimage(t *testing.T) {
140 invalidPreimage := "invalidpreimageinvalidpreimageinvalidpreimageinvalidpreimageinvalid"
141 setup := setupSettleHoldInvoiceTest(t, invalidPreimage, testSettlePaymentHash, constants.TRANSACTION_STATE_ACCEPTED)
142 defer setup.TearDown()
143
144 controller := NewTestNip47Controller(setup.svc)
145
146 controller.HandleSettleHoldInvoiceEvent(setup.ctx, setup.nip47Request, setup.dbRequestEvent.ID, *setup.dbRequestEvent.AppId, setup.PublishResponse)
147
148 assert.True(t, setup.publishCalled)
149 require.NotNil(t, setup.response.Error)
150 assert.Equal(t, constants.ERROR_INTERNAL, setup.response.Error.Code)
151 }
152