pay_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 "github.com/getAlby/hub/constants"
13 "github.com/getAlby/hub/db"
14 "github.com/getAlby/hub/nip47/models"
15 "github.com/getAlby/hub/tests"
16 "github.com/getAlby/hub/transactions"
17 )
18
19 const nip47PayInvoiceJson = `
20 {
21 "method": "pay_invoice",
22 "params": {
23 "invoice": "lntbs1230n1pnkqautdqyw3jsnp4q09a0z84kg4a2m38zjllw43h953fx5zvqe8qxfgw694ymkq26u8zcpp5yvnh6hsnlnj4xnuh2trzlnunx732dv8ta2wjr75pdfxf6p2vlyassp5hyeg97a3ft5u769kjwsn7p0e85h79pzz8kladmnqhpcypz2uawjs9qyysgqcqpcxq8zals8sq9yeg2pa9eywkgj50cyzxd5elatujuc0c0wh6j9nat5mn34pgk8u9ufpgs99tw9ldlfk42cqlkr48au3lmuh09269prg4qkggh4a8cyqpfl0y6j",
24 "metadata": {"a": 123}
25 }
26 }
27 `
28 const nip47PayInvoiceZeroAmountJson = `
29 {
30 "method": "pay_invoice",
31 "params": {
32 "invoice": "` + tests.MockZeroAmountInvoice + `",
33 "amount": 1234
34 }
35 }
36 `
37
38 const nip47PayJsonNoInvoice = `
39 {
40 "method": "pay_invoice",
41 "params": {
42 "something": "else"
43 }
44 }
45 `
46
47 const nip47PayJsonExpiredInvoice = `
48 {
49 "method": "pay_invoice",
50 "params": {
51 "invoice": "lntb1230n1pjypux0pp5xgxzcks5jtx06k784f9dndjh664wc08ucrganpqn52d0ftrh9n8sdqyw3jscqzpgxqyz5vqsp5rkx7cq252p3frx8ytjpzc55rkgyx2mfkzzraa272dqvr2j6leurs9qyyssqhutxa24r5hqxstchz5fxlslawprqjnarjujp5sm3xj7ex73s32sn54fthv2aqlhp76qmvrlvxppx9skd3r5ut5xutgrup8zuc6ay73gqmra29m"
52 }
53 }
54 `
55
56 func TestHandlePayInvoiceEvent(t *testing.T) {
57 ctx := context.TODO()
58 svc, err := tests.CreateTestService(t)
59 require.NoError(t, err)
60 defer svc.Remove()
61
62 app, _, err := tests.CreateApp(svc)
63 assert.NoError(t, err)
64
65 appPermission := &db.AppPermission{
66 AppId: app.ID,
67 App: *app,
68 Scope: constants.PAY_INVOICE_SCOPE,
69 }
70 err = svc.DB.Create(appPermission).Error
71 assert.NoError(t, err)
72
73 nip47Request := &models.Request{}
74 err = json.Unmarshal([]byte(nip47PayInvoiceJson), nip47Request)
75 assert.NoError(t, err)
76
77 dbRequestEvent := &db.RequestEvent{}
78 err = svc.DB.Create(&dbRequestEvent).Error
79 assert.NoError(t, err)
80
81 var publishedResponse *models.Response
82
83 publishResponse := func(response *models.Response, tags nostr.Tags) {
84 publishedResponse = response
85 }
86
87 NewTestNip47Controller(svc).
88 HandlePayInvoiceEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse, nostr.Tags{})
89
90 assert.Equal(t, "123preimage", publishedResponse.Result.(payResponse).Preimage)
91
92 transactionType := constants.TRANSACTION_TYPE_OUTGOING
93 transactionsSvc := transactions.NewTransactionsService(svc.DB, svc.EventPublisher)
94 transaction, err := transactionsSvc.LookupTransaction(ctx, "23277d5e13fce5534f9752c62fcf9337a2a6b0ebea9d21fa816a4c9d054cf93b", &transactionType, svc.LNClient, &app.ID)
95 assert.NoError(t, err)
96
97 type dummyMetadata struct {
98 A int `json:"a"`
99 }
100 var decodedMetadata dummyMetadata
101 err = json.Unmarshal(transaction.Metadata, &decodedMetadata)
102 assert.NoError(t, err)
103 assert.Equal(t, 123, decodedMetadata.A)
104 }
105
106 func TestHandlePayInvoiceEvent_ZeroAmount(t *testing.T) {
107 ctx := context.TODO()
108 svc, err := tests.CreateTestService(t)
109 require.NoError(t, err)
110 defer svc.Remove()
111
112 app, _, err := tests.CreateApp(svc)
113 assert.NoError(t, err)
114
115 appPermission := &db.AppPermission{
116 AppId: app.ID,
117 App: *app,
118 Scope: constants.PAY_INVOICE_SCOPE,
119 }
120 err = svc.DB.Create(appPermission).Error
121 assert.NoError(t, err)
122
123 nip47Request := &models.Request{}
124 err = json.Unmarshal([]byte(nip47PayInvoiceZeroAmountJson), nip47Request)
125 assert.NoError(t, err)
126
127 dbRequestEvent := &db.RequestEvent{}
128 err = svc.DB.Create(&dbRequestEvent).Error
129 assert.NoError(t, err)
130
131 var publishedResponse *models.Response
132
133 publishResponse := func(response *models.Response, tags nostr.Tags) {
134 publishedResponse = response
135 }
136
137 NewTestNip47Controller(svc).
138 HandlePayInvoiceEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse, nostr.Tags{})
139
140 assert.Equal(t, "123preimage", publishedResponse.Result.(payResponse).Preimage)
141
142 transactionType := constants.TRANSACTION_TYPE_OUTGOING
143 transactionsSvc := transactions.NewTransactionsService(svc.DB, svc.EventPublisher)
144 transaction, err := transactionsSvc.LookupTransaction(ctx, tests.MockZeroAmountPaymentHash, &transactionType, svc.LNClient, &app.ID)
145 assert.NoError(t, err)
146 // from the request amount
147 assert.Equal(t, uint64(1234), transaction.AmountMsat)
148 }
149
150 func TestHandlePayInvoiceEvent_MalformedInvoice(t *testing.T) {
151 ctx := context.TODO()
152 svc, err := tests.CreateTestService(t)
153 require.NoError(t, err)
154 defer svc.Remove()
155
156 app, _, err := tests.CreateApp(svc)
157 assert.NoError(t, err)
158
159 appPermission := &db.AppPermission{
160 AppId: app.ID,
161 App: *app,
162 Scope: constants.PAY_INVOICE_SCOPE,
163 }
164 err = svc.DB.Create(appPermission).Error
165 assert.NoError(t, err)
166
167 nip47Request := &models.Request{}
168 err = json.Unmarshal([]byte(nip47PayJsonNoInvoice), nip47Request)
169 assert.NoError(t, err)
170
171 dbRequestEvent := &db.RequestEvent{}
172 err = svc.DB.Create(&dbRequestEvent).Error
173 assert.NoError(t, err)
174
175 var publishedResponse *models.Response
176
177 publishResponse := func(response *models.Response, tags nostr.Tags) {
178 publishedResponse = response
179 }
180
181 NewTestNip47Controller(svc).
182 HandlePayInvoiceEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse, nostr.Tags{})
183
184 assert.Nil(t, publishedResponse.Result)
185 assert.Equal(t, constants.ERROR_BAD_REQUEST, publishedResponse.Error.Code)
186 assert.Equal(t, "Failed to decode bolt11 invoice: bolt11 too short", publishedResponse.Error.Message)
187 }
188
189 func TestHandlePayInvoiceEvent_ExpiredInvoice(t *testing.T) {
190 ctx := context.TODO()
191 svc, err := tests.CreateTestService(t)
192 require.NoError(t, err)
193 defer svc.Remove()
194
195 app, _, err := tests.CreateApp(svc)
196 assert.NoError(t, err)
197
198 appPermission := &db.AppPermission{
199 AppId: app.ID,
200 App: *app,
201 Scope: constants.PAY_INVOICE_SCOPE,
202 }
203 err = svc.DB.Create(appPermission).Error
204 assert.NoError(t, err)
205
206 nip47Request := &models.Request{}
207 err = json.Unmarshal([]byte(nip47PayJsonExpiredInvoice), nip47Request)
208 assert.NoError(t, err)
209
210 dbRequestEvent := &db.RequestEvent{}
211 err = svc.DB.Create(&dbRequestEvent).Error
212 assert.NoError(t, err)
213
214 var publishedResponse *models.Response
215
216 publishResponse := func(response *models.Response, tags nostr.Tags) {
217 publishedResponse = response
218 }
219
220 NewTestNip47Controller(svc).
221 HandlePayInvoiceEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse, nostr.Tags{})
222
223 assert.Nil(t, publishedResponse.Result)
224 assert.Equal(t, constants.ERROR_INTERNAL, publishedResponse.Error.Code)
225 assert.Equal(t, "this invoice has expired", publishedResponse.Error.Message)
226 }
227