@@ -2,6 +2,178 @@ import { expect } from 'vitest'
22import { keyPair } from '../test/crypto'
33import { walletTest } from '../test/fixtures'
44
5+ const LNURL_TEST_ADDRESS = import . meta. env . LNURL_TEST_ADDRESS
6+ const LNURL_TEST_AMOUNT_MSATS = Number ( import . meta. env . LNURL_TEST_AMOUNT_MSATS )
7+ const lnurlWalletTest = LNURL_TEST_ADDRESS ? walletTest : walletTest . skip
8+
9+ const parseLnurlPayResponse = ( response : unknown ) => {
10+ expect ( response ) . toBeDefined ( )
11+ expect ( response ) . toMatchObject ( {
12+ callback : expect . any ( String ) ,
13+ maxSendable : expect . any ( Number ) ,
14+ metadata : expect . any ( String ) ,
15+ minSendable : expect . any ( Number ) ,
16+ tag : expect . any ( String ) ,
17+ } )
18+ return response as {
19+ callback : string
20+ maxSendable : number
21+ metadata : string
22+ minSendable : number
23+ tag : string
24+ }
25+ }
26+
27+ const parsePayLightningAddressResponse = ( response : unknown ) => {
28+ expect ( response ) . toBeDefined ( )
29+ expect ( response ) . toMatchObject ( {
30+ contract_id : expect . any ( String ) ,
31+ fee : expect . any ( Number ) ,
32+ payment_type : expect . any ( Object ) ,
33+ } )
34+ return response as {
35+ contract_id : string
36+ fee : number
37+ payment_type : {
38+ lightning ?: string
39+ internal ?: string
40+ }
41+ }
42+ }
43+
44+ walletTest (
45+ 'verifyLightningAddress should throw on invalid lightning address' ,
46+ async ( { wallet } ) => {
47+ expect ( wallet ) . toBeDefined ( )
48+ expect ( wallet . isOpen ( ) ) . toBe ( true )
49+
50+ const counterBefore = wallet . testing . getRequestCounter ( )
51+ try {
52+ await wallet . lightning . verifyLightningAddress ( 'not-a-lightning-address' )
53+ expect . unreachable ( 'Should throw error' )
54+ } catch ( error ) {
55+ expect ( error ) . toBeDefined ( )
56+ }
57+
58+ expect ( wallet . testing . getRequestCounter ( ) ) . toBe ( counterBefore + 1 )
59+ } ,
60+ )
61+
62+ walletTest (
63+ 'payLightningAddress should throw on invalid lightning address' ,
64+ async ( { wallet } ) => {
65+ expect ( wallet ) . toBeDefined ( )
66+ expect ( wallet . isOpen ( ) ) . toBe ( true )
67+
68+ const counterBefore = wallet . testing . getRequestCounter ( )
69+ try {
70+ await wallet . lightning . payLightningAddress ( 'not-a-lightning-address' , 1000 )
71+ expect . unreachable ( 'Should throw error' )
72+ } catch ( error ) {
73+ expect ( error ) . toBeDefined ( )
74+ }
75+
76+ expect ( wallet . testing . getRequestCounter ( ) ) . toBe ( counterBefore + 1 )
77+ } ,
78+ )
79+
80+ lnurlWalletTest (
81+ 'verifyLightningAddress should return lnurl metadata for configured address' ,
82+ async ( { wallet } ) => {
83+ expect ( wallet ) . toBeDefined ( )
84+ expect ( wallet . isOpen ( ) ) . toBe ( true )
85+
86+ const counterBefore = wallet . testing . getRequestCounter ( )
87+ const response = await wallet . lightning . verifyLightningAddress (
88+ LNURL_TEST_ADDRESS ,
89+ )
90+ const lnurl = parseLnurlPayResponse ( response )
91+ expect ( lnurl . tag ) . toBe ( 'payRequest' )
92+ expect ( lnurl . callback . length ) . toBeGreaterThan ( 0 )
93+ expect ( lnurl . minSendable ) . toBeLessThanOrEqual ( lnurl . maxSendable )
94+ expect ( wallet . testing . getRequestCounter ( ) ) . toBe ( counterBefore + 1 )
95+ } ,
96+ )
97+
98+ lnurlWalletTest (
99+ 'payLightningAddress should pay configured lnurl address' ,
100+ { timeout : 20_000 } ,
101+ async ( { fundedWallet } ) => {
102+ expect ( fundedWallet ) . toBeDefined ( )
103+ expect ( fundedWallet . isOpen ( ) ) . toBe ( true )
104+
105+ const verifyResponse = await fundedWallet . lightning . verifyLightningAddress (
106+ LNURL_TEST_ADDRESS ,
107+ )
108+ const lnurl = parseLnurlPayResponse ( verifyResponse )
109+ const amountMsats = Math . min (
110+ Math . max ( LNURL_TEST_AMOUNT_MSATS || 1000 , lnurl . minSendable ) ,
111+ lnurl . maxSendable ,
112+ )
113+
114+ const initialBalance = await fundedWallet . balance . getBalance ( )
115+ const payment = parsePayLightningAddressResponse (
116+ await fundedWallet . lightning . payLightningAddress (
117+ LNURL_TEST_ADDRESS ,
118+ amountMsats ,
119+ ) ,
120+ )
121+
122+ if ( payment . payment_type . lightning ) {
123+ const waitResult = await fundedWallet . lightning . waitForPay (
124+ payment . payment_type . lightning ,
125+ )
126+ expect ( waitResult . success ) . toBe ( true )
127+ }
128+
129+ const finalBalance = await fundedWallet . balance . getBalance ( )
130+ expect ( finalBalance ) . toBeLessThan ( initialBalance )
131+ } ,
132+ )
133+
134+ lnurlWalletTest (
135+ 'payLightningAddress should throw when amount is below lnurl minimum' ,
136+ async ( { wallet } ) => {
137+ expect ( wallet ) . toBeDefined ( )
138+ expect ( wallet . isOpen ( ) ) . toBe ( true )
139+
140+ const verifyResponse = await wallet . lightning . verifyLightningAddress (
141+ LNURL_TEST_ADDRESS ,
142+ )
143+ const lnurl = parseLnurlPayResponse ( verifyResponse )
144+ const invalidAmount = lnurl . minSendable - 1
145+ expect ( invalidAmount ) . toBeGreaterThanOrEqual ( 0 )
146+
147+ try {
148+ await wallet . lightning . payLightningAddress ( LNURL_TEST_ADDRESS , invalidAmount )
149+ expect . unreachable ( 'Should throw error' )
150+ } catch ( error ) {
151+ expect ( error ) . toBeDefined ( )
152+ }
153+ } ,
154+ )
155+
156+ lnurlWalletTest (
157+ 'payLightningAddress should throw when amount is above lnurl maximum' ,
158+ async ( { wallet } ) => {
159+ expect ( wallet ) . toBeDefined ( )
160+ expect ( wallet . isOpen ( ) ) . toBe ( true )
161+
162+ const verifyResponse = await wallet . lightning . verifyLightningAddress (
163+ LNURL_TEST_ADDRESS ,
164+ )
165+ const lnurl = parseLnurlPayResponse ( verifyResponse )
166+ const invalidAmount = lnurl . maxSendable + 1
167+
168+ try {
169+ await wallet . lightning . payLightningAddress ( LNURL_TEST_ADDRESS , invalidAmount )
170+ expect . unreachable ( 'Should throw error' )
171+ } catch ( error ) {
172+ expect ( error ) . toBeDefined ( )
173+ }
174+ } ,
175+ )
176+
5177walletTest (
6178 'createInvoice should create a bolt11 invoice' ,
7179 async ( { wallet } ) => {
0 commit comments