@@ -7,14 +7,19 @@ import { L402BudgetExceededError } from "../src/errors.js";
77// ── Mock LnBot SDK ──
88
99function createMockLn ( ) {
10+ const l402 = {
11+ createChallenge : vi . fn ( ) ,
12+ verify : vi . fn ( ) ,
13+ pay : vi . fn ( ) ,
14+ } ;
1015 return {
11- l402 : {
12- createChallenge : vi . fn ( ) ,
13- verify : vi . fn ( ) ,
14- pay : vi . fn ( ) ,
15- } ,
16+ wallet : vi . fn ( ) . mockReturnValue ( { l402 } ) ,
17+ _l402 : l402 ,
1618 } as unknown as LnBot & {
17- l402 : {
19+ wallet : ReturnType < typeof vi . fn > ;
20+ _l402 : {
21+ createChallenge : ReturnType < typeof vi . fn > ;
22+ verify : ReturnType < typeof vi . fn > ;
1823 pay : ReturnType < typeof vi . fn > ;
1924 } ;
2025 } ;
@@ -52,12 +57,12 @@ describe("L402 client", () => {
5257 jsonResponse ( 200 , { data : "free" } ) ,
5358 ) ;
5459
55- const c = client ( ln ) ;
60+ const c = client ( ln , { walletId : "wal_test" } ) ;
5661 const res = await c . fetch ( URL_PREMIUM ) ;
5762
5863 expect ( res . status ) . toBe ( 200 ) ;
5964 expect ( await res . json ( ) ) . toEqual ( { data : "free" } ) ;
60- expect ( ln . l402 . pay ) . not . toHaveBeenCalled ( ) ;
65+ expect ( ln . _l402 . pay ) . not . toHaveBeenCalled ( ) ;
6166 } ) ;
6267
6368 it ( "pays 402 challenge and retries with authorization" , async ( ) => {
@@ -74,7 +79,7 @@ describe("L402 client", () => {
7479
7580 globalThis . fetch = mockFetch ;
7681
77- ln . l402 . pay . mockResolvedValue ( {
82+ ln . _l402 . pay . mockResolvedValue ( {
7883 authorization : "L402 mac123:preimage_hex" ,
7984 paymentHash : "hash123" ,
8085 preimage : "preimage_hex" ,
@@ -84,12 +89,12 @@ describe("L402 client", () => {
8489 status : "settled" ,
8590 } ) ;
8691
87- const c = client ( ln ) ;
92+ const c = client ( ln , { walletId : "wal_test" } ) ;
8893 const res = await c . fetch ( URL_PREMIUM ) ;
8994
9095 expect ( res . status ) . toBe ( 200 ) ;
9196 expect ( await res . json ( ) ) . toEqual ( { data : "premium" } ) ;
92- expect ( ln . l402 . pay ) . toHaveBeenCalledWith ( { wwwAuthenticate : wwwAuth } ) ;
97+ expect ( ln . _l402 . pay ) . toHaveBeenCalledWith ( { wwwAuthenticate : wwwAuth } ) ;
9398
9499 // Verify retry had Authorization header
95100 const retryCall = mockFetch . mock . calls [ 1 ] ;
@@ -111,7 +116,7 @@ describe("L402 client", () => {
111116
112117 globalThis . fetch = mockFetch ;
113118
114- ln . l402 . pay . mockResolvedValue ( {
119+ ln . _l402 . pay . mockResolvedValue ( {
115120 authorization : "L402 mac:pre" ,
116121 paymentHash : "hash" ,
117122 preimage : "pre" ,
@@ -121,15 +126,15 @@ describe("L402 client", () => {
121126 status : "settled" ,
122127 } ) ;
123128
124- const c = client ( ln ) ;
129+ const c = client ( ln , { walletId : "wal_test" } ) ;
125130
126131 // First fetch — pays
127132 await c . fetch ( URL_PREMIUM ) ;
128- expect ( ln . l402 . pay ) . toHaveBeenCalledTimes ( 1 ) ;
133+ expect ( ln . _l402 . pay ) . toHaveBeenCalledTimes ( 1 ) ;
129134
130135 // Second fetch — uses cache, no new payment
131136 const res2 = await c . fetch ( URL_PREMIUM ) ;
132- expect ( ln . l402 . pay ) . toHaveBeenCalledTimes ( 1 ) ; // Still 1
137+ expect ( ln . _l402 . pay ) . toHaveBeenCalledTimes ( 1 ) ; // Still 1
133138 expect ( res2 . status ) . toBe ( 200 ) ;
134139
135140 // Cached token was sent
@@ -160,7 +165,7 @@ describe("L402 client", () => {
160165
161166 globalThis . fetch = mockFetch ;
162167
163- ln . l402 . pay . mockResolvedValue ( {
168+ ln . _l402 . pay . mockResolvedValue ( {
164169 authorization : "L402 mac:pre" ,
165170 paymentHash : "hash" ,
166171 preimage : "pre" ,
@@ -170,15 +175,15 @@ describe("L402 client", () => {
170175 status : "settled" ,
171176 } ) ;
172177
173- const c = client ( ln ) ;
178+ const c = client ( ln , { walletId : "wal_test" } ) ;
174179
175180 // First fetch — pays
176181 await c . fetch ( URL_PREMIUM ) ;
177- expect ( ln . l402 . pay ) . toHaveBeenCalledTimes ( 1 ) ;
182+ expect ( ln . _l402 . pay ) . toHaveBeenCalledTimes ( 1 ) ;
178183
179184 // Second fetch — cached token rejected, re-pays
180185 const res2 = await c . fetch ( URL_PREMIUM ) ;
181- expect ( ln . l402 . pay ) . toHaveBeenCalledTimes ( 2 ) ;
186+ expect ( ln . _l402 . pay ) . toHaveBeenCalledTimes ( 2 ) ;
182187 expect ( res2 . status ) . toBe ( 200 ) ;
183188 } ) ;
184189
@@ -190,11 +195,11 @@ describe("L402 client", () => {
190195 ) ,
191196 ) ;
192197
193- const c = client ( ln , { maxPrice : 100 } ) ;
198+ const c = client ( ln , { walletId : "wal_test" , maxPrice : 100 } ) ;
194199
195200 await expect ( c . fetch ( URL_PREMIUM ) ) . rejects . toThrow ( L402BudgetExceededError ) ;
196201 await expect ( c . fetch ( URL_PREMIUM ) ) . rejects . toThrow ( "exceeds maxPrice" ) ;
197- expect ( ln . l402 . pay ) . not . toHaveBeenCalled ( ) ;
202+ expect ( ln . _l402 . pay ) . not . toHaveBeenCalled ( ) ;
198203 } ) ;
199204
200205 it ( "throws L402BudgetExceededError when budget is exhausted" , async ( ) => {
@@ -211,7 +216,7 @@ describe("L402 client", () => {
211216 return Promise . resolve ( jsonResponse ( 200 , { data : "ok" } ) ) ;
212217 } ) ;
213218
214- ln . l402 . pay . mockResolvedValue ( {
219+ ln . _l402 . pay . mockResolvedValue ( {
215220 authorization : "L402 mac:pre" ,
216221 paymentHash : "hash" ,
217222 preimage : "pre" ,
@@ -222,6 +227,7 @@ describe("L402 client", () => {
222227 } ) ;
223228
224229 const c = client ( ln , {
230+ walletId : "wal_test" ,
225231 budgetSats : 100 ,
226232 budgetPeriod : "day" ,
227233 store : "none" , // Disable cache so each request pays
@@ -239,7 +245,7 @@ describe("L402 client", () => {
239245 jsonResponse ( 402 , { error : "pay up" } ) ,
240246 ) ;
241247
242- const c = client ( ln ) ;
248+ const c = client ( ln , { walletId : "wal_test" } ) ;
243249
244250 await expect ( c . fetch ( URL_PREMIUM ) ) . rejects . toThrow (
245251 "402 response missing WWW-Authenticate header" ,
@@ -252,7 +258,7 @@ describe("L402 client", () => {
252258 jsonResponse ( 402 , { price : 10 } , { "www-authenticate" : wwwAuth } ) ,
253259 ) ;
254260
255- ln . l402 . pay . mockResolvedValue ( {
261+ ln . _l402 . pay . mockResolvedValue ( {
256262 authorization : null ,
257263 paymentHash : "hash" ,
258264 preimage : null ,
@@ -262,7 +268,7 @@ describe("L402 client", () => {
262268 status : "failed" ,
263269 } ) ;
264270
265- const c = client ( ln ) ;
271+ const c = client ( ln , { walletId : "wal_test" } ) ;
266272
267273 await expect ( c . fetch ( URL_PREMIUM ) ) . rejects . toThrow ( L402PaymentFailedError ) ;
268274 } ) ;
@@ -272,7 +278,7 @@ describe("L402 client", () => {
272278 jsonResponse ( 200 , { result : 42 } ) ,
273279 ) ;
274280
275- const c = client ( ln ) ;
281+ const c = client ( ln , { walletId : "wal_test" } ) ;
276282 const data = await c . get ( URL_PREMIUM ) ;
277283
278284 expect ( data ) . toEqual ( { result : 42 } ) ;
@@ -283,7 +289,7 @@ describe("L402 client", () => {
283289 jsonResponse ( 200 , { created : true } ) ,
284290 ) ;
285291
286- const c = client ( ln ) ;
292+ const c = client ( ln , { walletId : "wal_test" } ) ;
287293 const data = await c . post ( URL_PREMIUM , {
288294 body : JSON . stringify ( { query : "test" } ) ,
289295 } ) ;
@@ -298,7 +304,7 @@ describe("L402 client", () => {
298304 jsonResponse ( 200 , { updated : true } ) ,
299305 ) ;
300306
301- const c = client ( ln ) ;
307+ const c = client ( ln , { walletId : "wal_test" } ) ;
302308 const data = await c . put ( URL_PREMIUM , {
303309 body : JSON . stringify ( { name : "new" } ) ,
304310 } ) ;
@@ -313,7 +319,7 @@ describe("L402 client", () => {
313319 jsonResponse ( 200 , { patched : true } ) ,
314320 ) ;
315321
316- const c = client ( ln ) ;
322+ const c = client ( ln , { walletId : "wal_test" } ) ;
317323 const data = await c . patch ( URL_PREMIUM , {
318324 body : JSON . stringify ( { field : "value" } ) ,
319325 } ) ;
@@ -328,7 +334,7 @@ describe("L402 client", () => {
328334 jsonResponse ( 200 , { deleted : true } ) ,
329335 ) ;
330336
331- const c = client ( ln ) ;
337+ const c = client ( ln , { walletId : "wal_test" } ) ;
332338 const data = await c . delete ( URL_PREMIUM ) ;
333339
334340 expect ( data ) . toEqual ( { deleted : true } ) ;
@@ -346,7 +352,7 @@ describe("L402 client", () => {
346352 jsonResponse ( 402 , { price : 10 } , { "www-authenticate" : wwwAuth } ) ,
347353 ) ;
348354
349- ln . l402 . pay . mockResolvedValue ( {
355+ ln . _l402 . pay . mockResolvedValue ( {
350356 authorization : "L402 mac:pre" ,
351357 paymentHash : "hash" ,
352358 preimage : "pre" ,
@@ -356,7 +362,7 @@ describe("L402 client", () => {
356362 status : "settled" ,
357363 } ) ;
358364
359- const c = client ( ln ) ;
365+ const c = client ( ln , { walletId : "wal_test" } ) ;
360366
361367 await expect ( c . fetch ( URL_PREMIUM ) ) . rejects . toSatisfy ( ( err : unknown ) => {
362368 expect ( err ) . toBeInstanceOf ( L402PaymentFailedError ) ;
@@ -365,7 +371,7 @@ describe("L402 client", () => {
365371 ) ;
366372 return true ;
367373 } ) ;
368- expect ( ln . l402 . pay ) . toHaveBeenCalledTimes ( 1 ) ;
374+ expect ( ln . _l402 . pay ) . toHaveBeenCalledTimes ( 1 ) ;
369375 } ) ;
370376
371377 it ( "defaults maxPrice to 1000 sats" , async ( ) => {
@@ -376,7 +382,7 @@ describe("L402 client", () => {
376382 ) ,
377383 ) ;
378384
379- const c = client ( ln ) ; // No maxPrice specified
385+ const c = client ( ln , { walletId : "wal_test" } ) ; // No maxPrice specified
380386
381387 await expect ( c . fetch ( URL_PREMIUM ) ) . rejects . toThrow ( "exceeds maxPrice 1000" ) ;
382388 } ) ;
0 commit comments