@lightsparkdev/lightspark-sdk 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/{chunk-5RDIWPBE.js → chunk-D32EWIPX.js} +3 -1
  3. package/dist/env.cjs +3 -1
  4. package/dist/env.d.cts +17 -0
  5. package/dist/env.js +2 -2
  6. package/dist/{index-f040db9f.d.ts → index-5acc6526.d.ts} +717 -14
  7. package/dist/index.cjs +29 -19
  8. package/dist/index.d.cts +41 -0
  9. package/dist/index.d.ts +3 -3
  10. package/dist/index.js +26 -21
  11. package/dist/objects/index.d.cts +4 -0
  12. package/dist/objects/index.d.ts +1 -1
  13. package/dist/objects/index.js +1 -1
  14. package/dist/{text-encoding-MDIPJAHL.js → text-encoding-26SMKBAQ.js} +3 -1
  15. package/package.json +4 -4
  16. package/src/auth/AccountTokenAuthProvider.ts +15 -11
  17. package/src/client.ts +7 -6
  18. package/src/helpers.ts +3 -1
  19. package/src/objects/Account.ts +8 -0
  20. package/src/objects/AccountToChannelsConnection.ts +5 -0
  21. package/src/objects/Channel.ts +31 -0
  22. package/src/objects/GraphNode.ts +28 -0
  23. package/src/objects/IncomingPayment.ts +17 -0
  24. package/src/objects/LightsparkNodeWithOSK.ts +61 -0
  25. package/src/objects/LightsparkNodeWithRemoteSigning.ts +60 -0
  26. package/src/objects/OutgoingPayment.ts +19 -0
  27. package/src/objects/OutgoingPaymentAttempt.ts +26 -0
  28. package/src/objects/Wallet.ts +12 -0
  29. package/src/objects/WithdrawalRequest.ts +17 -0
  30. package/src/tests/integration/constants.ts +13 -0
  31. package/src/tests/integration/general-regtest.test.ts +652 -0
  32. package/src/tests/serialization.test.ts +5 -2
  33. package/src/webhooks.ts +1 -1
  34. package/src/tests/integration/client.test.ts +0 -207
  35. /package/dist/{chunk-NIMBE7W3.js → chunk-BMTV3EA2.js} +0 -0
@@ -0,0 +1,652 @@
1
+ /**
2
+ * To run test properly:
3
+ * 1. Create LIGHTSPARK_API_TOKEN_CLIENT_ID and LIGHTSPARK_API_TOKEN_CLIENT_SECRET in https://app.lightspark.com/api-config
4
+ * 2. lightspark-wallet init-env
5
+ * 3. yarn workspace @lightsparkdev/wallet-sdk test
6
+ */
7
+
8
+ import { describe, expect, test } from "@jest/globals";
9
+ import { mapCurrencyAmount, pollUntil, round } from "@lightsparkdev/core";
10
+ import dayjs from "dayjs";
11
+ import LightsparkClient from "../../client.js";
12
+ import { getCredentialsFromEnvOrThrow } from "../../env.js";
13
+ import { DecodeInvoice } from "../../graphql/DecodeInvoice.js";
14
+ import {
15
+ AccountTokenAuthProvider,
16
+ BitcoinNetwork,
17
+ InvoiceType,
18
+ OutgoingPayment,
19
+ PaymentRequestStatus,
20
+ TransactionStatus,
21
+ type AccountToNodesConnection,
22
+ } from "../../index.js";
23
+ import { logger } from "../../logger.js";
24
+ import {
25
+ DAY_IN_MS,
26
+ ENCODED_REGTEST_REQUEST_FOR_TESTS,
27
+ INVOICE_EXPIRY,
28
+ LONG_TEST_TIMEOUT,
29
+ MAX_FEE,
30
+ PAGINATION_STEP,
31
+ PAY_AMOUNT,
32
+ REGTEST_SIGNING_KEY_PASSWORD,
33
+ TESTS_TIMEOUT,
34
+ TRANSACTION_WAIT_TIME,
35
+ } from "./constants.js";
36
+
37
+ const unauthorizedLightsparkClient = new LightsparkClient();
38
+
39
+ const { apiTokenClientId, apiTokenClientSecret, baseUrl } =
40
+ getCredentialsFromEnvOrThrow();
41
+
42
+ let lightsparkClient: LightsparkClient;
43
+ let paymentInvoice: string | undefined;
44
+ let regtestNodeId: string | undefined;
45
+ let invoicePayment: OutgoingPayment | undefined;
46
+
47
+ const pollIntervalMs = 750;
48
+ const pollTimeoutSecs = 20;
49
+ const pollMaxTimeouts = (pollTimeoutSecs * 1000) / pollIntervalMs;
50
+ const pollIgnoreErrors = false;
51
+
52
+ let nodesConnection: AccountToNodesConnection | undefined;
53
+
54
+ const testModeInvoices: Record<string, string | null> = {
55
+ withMemo: null,
56
+ withoutMemo: null,
57
+ };
58
+
59
+ const createTestModePayment = async () => {
60
+ const regtestNodeId = getRegtestNodeId();
61
+ const testInvoice = await lightsparkClient.createInvoice(
62
+ regtestNodeId,
63
+ PAY_AMOUNT,
64
+ "hi there!",
65
+ );
66
+
67
+ if (!testInvoice) {
68
+ throw new TypeError("Test invoice wasn't created");
69
+ }
70
+
71
+ const payment = await lightsparkClient.createTestModePayment(
72
+ regtestNodeId,
73
+ testInvoice,
74
+ );
75
+ if (!payment) {
76
+ throw new TypeError("Test mode payment wasn't created");
77
+ }
78
+ return payment;
79
+ };
80
+
81
+ const initSuiteName = "initialization";
82
+ const p0SuiteName = "p0";
83
+ const p1SuiteName = "p1";
84
+ const p2SuiteName = "p2";
85
+ function log(msg: string, ...args: unknown[]) {
86
+ logger.info(
87
+ `${expect
88
+ .getState()
89
+ .currentTestName?.replace(
90
+ new RegExp(`^(${initSuiteName}|p[0-2])\\s`, "g"),
91
+ "",
92
+ )}: ${msg}`,
93
+ ...args,
94
+ );
95
+ }
96
+
97
+ function getRegtestNodeId() {
98
+ expect(regtestNodeId).toBeDefined();
99
+ if (!regtestNodeId) {
100
+ throw new TypeError("No regtest nodes in account");
101
+ }
102
+ return regtestNodeId;
103
+ }
104
+
105
+ async function getAccount() {
106
+ const account = await lightsparkClient.getCurrentAccount();
107
+ if (!account) {
108
+ throw new TypeError("No account");
109
+ }
110
+ return account;
111
+ }
112
+
113
+ async function getRegtestNode() {
114
+ const account = await getAccount();
115
+ const regtestNodeId = getRegtestNodeId();
116
+ const nodesConnection = await account.getNodes(
117
+ lightsparkClient,
118
+ 1,
119
+ [BitcoinNetwork.REGTEST],
120
+ [regtestNodeId],
121
+ );
122
+ const regtestNode = nodesConnection.entities[0];
123
+ if (!regtestNode) {
124
+ throw new TypeError(`No regtest node found for account ${account.id}`);
125
+ }
126
+ return regtestNode;
127
+ }
128
+
129
+ describe(initSuiteName, () => {
130
+ test("should get env vars and construct the client successfully", () => {
131
+ const accountAuthProvider = new AccountTokenAuthProvider(
132
+ apiTokenClientId,
133
+ apiTokenClientSecret,
134
+ );
135
+ lightsparkClient = new LightsparkClient(accountAuthProvider, baseUrl);
136
+ expect(lightsparkClient).toBeDefined();
137
+ });
138
+
139
+ test(
140
+ "Should successfully get the current account regtest node and set it as the default for current test suite",
141
+ async () => {
142
+ const account = await getAccount();
143
+ nodesConnection = await account.getNodes(lightsparkClient, 1, [
144
+ BitcoinNetwork.REGTEST,
145
+ ]);
146
+
147
+ if (!nodesConnection?.entities) {
148
+ throw new TypeError("No connections in account");
149
+ }
150
+
151
+ const [regtestNode] = nodesConnection?.entities;
152
+ regtestNodeId = regtestNode?.id;
153
+ log("regtestNodeId", regtestNode?.id);
154
+
155
+ await lightsparkClient.loadNodeSigningKey(getRegtestNodeId(), {
156
+ password: REGTEST_SIGNING_KEY_PASSWORD,
157
+ });
158
+
159
+ expect(regtestNode).toBeDefined();
160
+ },
161
+ TESTS_TIMEOUT,
162
+ );
163
+ });
164
+
165
+ describe(p0SuiteName, () => {
166
+ test("Should create a normal payment invoice", async () => {
167
+ paymentInvoice = await lightsparkClient.createInvoice(
168
+ getRegtestNodeId(),
169
+ PAY_AMOUNT,
170
+ "hi there!",
171
+ );
172
+ expect(paymentInvoice).toBeDefined();
173
+ });
174
+
175
+ test("Should create a AMP type invoice", async () => {
176
+ const AmpPaymentInvoice = await lightsparkClient.createInvoice(
177
+ getRegtestNodeId(),
178
+ PAY_AMOUNT,
179
+ "hi there!",
180
+ InvoiceType.AMP,
181
+ );
182
+ expect(AmpPaymentInvoice).toBeDefined();
183
+ });
184
+
185
+ test("Should create a invoice with custom expiration", async () => {
186
+ const AmpPaymentInvoiceWithExpiration =
187
+ await lightsparkClient.createInvoice(
188
+ getRegtestNodeId(),
189
+ PAY_AMOUNT,
190
+ "hi there!",
191
+ InvoiceType.STANDARD,
192
+ INVOICE_EXPIRY,
193
+ );
194
+ expect(AmpPaymentInvoiceWithExpiration).toBeDefined();
195
+ });
196
+
197
+ test("Should create an invoice that allows the payer to specify any amount", async () => {
198
+ const AnyPaymentAmountInvoice = await lightsparkClient.createInvoice(
199
+ getRegtestNodeId(),
200
+ 0,
201
+ "hi there!",
202
+ InvoiceType.STANDARD,
203
+ INVOICE_EXPIRY,
204
+ );
205
+ expect(AnyPaymentAmountInvoice).toBeDefined();
206
+ });
207
+
208
+ test("should throw an error on create an unauthorized invoice", async () => {
209
+ await expect(
210
+ unauthorizedLightsparkClient.createInvoice(
211
+ getRegtestNodeId(),
212
+ 0,
213
+ "hi there!",
214
+ ),
215
+ ).rejects.toThrowError();
216
+ });
217
+
218
+ const satsToFund = 40_000;
219
+ test("Should deposit funds to node with a defined amount of sats", async () => {
220
+ let regtestNode = await getRegtestNode();
221
+
222
+ const initialOwnedBalance = mapCurrencyAmount(
223
+ regtestNode?.balances?.ownedBalance,
224
+ );
225
+ const initialSendBalance = mapCurrencyAmount(
226
+ regtestNode?.balances?.availableToSendBalance,
227
+ );
228
+ log("initialOwnedBalance.sats", initialOwnedBalance.sats);
229
+ log("initialSendBalance.sats", initialSendBalance.sats);
230
+
231
+ const nodeId = getRegtestNodeId();
232
+
233
+ const targetBalanceSats = 40_000_000;
234
+ /* Backend will error on fund_node if total balance is greater than 100,000,000 sats, so we should
235
+ adjust to a target balance less than that: */
236
+ if (initialOwnedBalance.sats > targetBalanceSats) {
237
+ const invoiceAmount = initialOwnedBalance.sats - targetBalanceSats;
238
+ log("adjusting balance: invoiceAmount sats", invoiceAmount);
239
+
240
+ await lightsparkClient.loadNodeSigningKey(getRegtestNodeId(), {
241
+ password: REGTEST_SIGNING_KEY_PASSWORD,
242
+ });
243
+
244
+ const invoice = await lightsparkClient.createTestModeInvoice(
245
+ nodeId,
246
+ round((initialOwnedBalance.sats - targetBalanceSats) * 1000), // convert to msats
247
+ );
248
+
249
+ if (!invoice) {
250
+ throw new Error("Unable to create invoice for balance adjustment");
251
+ }
252
+
253
+ const feeRate = 0.0016;
254
+ const payment = await lightsparkClient.payInvoice(
255
+ nodeId,
256
+ invoice,
257
+ round(invoiceAmount * feeRate),
258
+ );
259
+
260
+ if (!payment) {
261
+ throw new Error("Payment undefined for balance adjustment");
262
+ }
263
+
264
+ const completePayment = await lightsparkClient.waitForTransactionComplete(
265
+ payment.id,
266
+ pollTimeoutSecs,
267
+ );
268
+ log("adjusting balance: completePayment", completePayment);
269
+
270
+ if (completePayment.status !== TransactionStatus.SUCCESS) {
271
+ log("adjusting balance: completePayment failed", completePayment);
272
+ throw new Error("Balance adjustment payment failed");
273
+ }
274
+ }
275
+
276
+ log(`Funding node ${nodeId} with ${satsToFund} sats`);
277
+ await lightsparkClient.fundNode(nodeId, satsToFund);
278
+
279
+ regtestNode = await pollUntil(
280
+ () => {
281
+ return getRegtestNode();
282
+ },
283
+ (current, response) => {
284
+ if (
285
+ current &&
286
+ !mapCurrencyAmount(
287
+ current.balances?.availableToSendBalance,
288
+ ).isEqualTo(initialSendBalance)
289
+ ) {
290
+ return {
291
+ stopPolling: true,
292
+ value: current,
293
+ };
294
+ }
295
+ return response;
296
+ },
297
+ pollIntervalMs,
298
+ pollMaxTimeouts,
299
+ pollIgnoreErrors,
300
+ () => new Error("Timeout waiting for payment to be received"),
301
+ );
302
+
303
+ const balances = regtestNode?.balances;
304
+ if (!balances) {
305
+ throw new Error("No balances property on node");
306
+ }
307
+ log(
308
+ "regtestNode.balances.availableToSend sats",
309
+ mapCurrencyAmount(balances.availableToSendBalance).sats,
310
+ );
311
+ log(
312
+ "regtestNode.balances.ownedBalance sats",
313
+ mapCurrencyAmount(balances.ownedBalance).sats,
314
+ );
315
+ log(
316
+ "regtestNode.balances.withdrawableBalance sats",
317
+ mapCurrencyAmount(balances.availableToWithdrawBalance).sats,
318
+ );
319
+
320
+ expect(
321
+ mapCurrencyAmount(regtestNode.balances?.availableToSendBalance).isEqualTo(
322
+ initialOwnedBalance,
323
+ ),
324
+ ).toBe(false);
325
+ }, 120_000);
326
+
327
+ test("Should pay an invoice", async () => {
328
+ const node = await getRegtestNode();
329
+ log(
330
+ "node.balances.availableToSendBalance",
331
+ node.balances?.availableToSendBalance,
332
+ );
333
+
334
+ const testInvoice = await lightsparkClient.createTestModeInvoice(
335
+ getRegtestNodeId(),
336
+ PAY_AMOUNT,
337
+ "hi there!",
338
+ );
339
+
340
+ if (!testInvoice) {
341
+ throw new TypeError("Test invoice doesn't created");
342
+ }
343
+
344
+ invoicePayment = await lightsparkClient.payInvoice(
345
+ getRegtestNodeId(),
346
+ testInvoice,
347
+ MAX_FEE,
348
+ TESTS_TIMEOUT,
349
+ );
350
+ expect(invoicePayment).toBeDefined();
351
+ });
352
+
353
+ // TODO: THIS ACTION CAN BE CREATED ONLY IN MAINNET
354
+ // test('Should deposit funds to node with a defined amount of sats', async () => {
355
+ // const fundingResult = await lightsparkClient.requestWithdrawal(getRegtestNodeId(), PAY_AMOUNT, '', WithdrawalMode.WALLET_THEN_CHANNELS)
356
+ // const transaction = await lightsparkClient.waitForTransactionComplete(fundingResult.id, TRANSACTION_WAIT_TIME)
357
+ // expect(transaction.status).toBe(TransactionStatus.SUCCESS)
358
+ // }, TRANSACTION_WAIT_TIME)
359
+
360
+ test(
361
+ "Should open just-in-time channel from inbound payment",
362
+ async () => {
363
+ const payment = await createTestModePayment();
364
+ const { status } = await lightsparkClient.waitForTransactionComplete(
365
+ payment.id,
366
+ TRANSACTION_WAIT_TIME,
367
+ );
368
+ expect(status).toBe(TransactionStatus.SUCCESS);
369
+ },
370
+ TESTS_TIMEOUT,
371
+ );
372
+ });
373
+
374
+ describe(p1SuiteName, () => {
375
+ test(
376
+ "should fetch the current account",
377
+ async () => {
378
+ const wallet = await lightsparkClient.getCurrentAccount();
379
+ expect(wallet?.id).toBeDefined();
380
+ },
381
+ TESTS_TIMEOUT,
382
+ );
383
+
384
+ test(
385
+ "should fetch the current account from unauthorized client",
386
+ async () => {
387
+ await expect(
388
+ unauthorizedLightsparkClient.getCurrentAccount(),
389
+ ).rejects.toThrowError();
390
+ },
391
+ TESTS_TIMEOUT,
392
+ );
393
+
394
+ test(
395
+ "should listen current payment requests",
396
+ async () => {
397
+ for (let i = 0; i < PAGINATION_STEP; i++) {
398
+ await createTestModePayment();
399
+ }
400
+ const requests = await lightsparkClient.getRecentPaymentRequests(
401
+ getRegtestNodeId(),
402
+ PAGINATION_STEP,
403
+ BitcoinNetwork.REGTEST,
404
+ );
405
+ expect(requests.length).toBe(PAGINATION_STEP);
406
+ },
407
+ LONG_TEST_TIMEOUT,
408
+ );
409
+
410
+ test(
411
+ "should listen current payment requests after some date",
412
+ async () => {
413
+ const requestsAfterDate = dayjs(Date.now() - DAY_IN_MS).format();
414
+ const requests = await lightsparkClient.getRecentPaymentRequests(
415
+ getRegtestNodeId(),
416
+ PAGINATION_STEP,
417
+ BitcoinNetwork.REGTEST,
418
+ requestsAfterDate,
419
+ );
420
+ expect(requests.length).toBe(PAGINATION_STEP);
421
+ },
422
+ TESTS_TIMEOUT,
423
+ );
424
+
425
+ test(
426
+ "should listen current payment requests from unauthorized client",
427
+ async () => {
428
+ await expect(
429
+ unauthorizedLightsparkClient.getRecentPaymentRequests(
430
+ getRegtestNodeId(),
431
+ PAGINATION_STEP,
432
+ BitcoinNetwork.REGTEST,
433
+ ),
434
+ ).rejects.toThrowError();
435
+ },
436
+ TESTS_TIMEOUT,
437
+ );
438
+
439
+ test(
440
+ "should list recent transactions",
441
+ async () => {
442
+ const transactions = await lightsparkClient.getRecentTransactions(
443
+ getRegtestNodeId(),
444
+ undefined,
445
+ BitcoinNetwork.REGTEST,
446
+ );
447
+ expect(transactions.length > 0).toBe(true);
448
+ },
449
+ TESTS_TIMEOUT,
450
+ );
451
+
452
+ test("should fetch an invoices payment by IDs", () => {
453
+ if (!invoicePayment?.id) throw new TypeError("invoicePayment is null");
454
+
455
+ const payment = OutgoingPayment.getOutgoingPaymentQuery(invoicePayment?.id);
456
+
457
+ expect(payment.queryPayload).not.toBeNull();
458
+ });
459
+
460
+ test(
461
+ "should decode an invoice",
462
+ async () => {
463
+ const decodedInvoice = await lightsparkClient.decodeInvoice(
464
+ ENCODED_REGTEST_REQUEST_FOR_TESTS,
465
+ );
466
+
467
+ expect(decodedInvoice).not.toBeNull();
468
+ expect(decodedInvoice?.memo).toBe("hi there!");
469
+ expect(decodedInvoice?.paymentHash).toBe(
470
+ "7806a0f8acd5385f9dd13d0aaa14922a7349afc5ba5d4b2bbbaaab5abd7f93ca",
471
+ );
472
+ },
473
+ TESTS_TIMEOUT,
474
+ );
475
+
476
+ test(
477
+ "should create STANDARD a test mode invoice",
478
+ async () => {
479
+ testModeInvoices.withMemo = await lightsparkClient.createTestModeInvoice(
480
+ getRegtestNodeId(),
481
+ PAY_AMOUNT,
482
+ "hi there!",
483
+ );
484
+ expect(testModeInvoices.withMemo).not.toBeNull();
485
+ },
486
+ TESTS_TIMEOUT,
487
+ );
488
+
489
+ test(
490
+ "should create an AMP a test mode invoice",
491
+ async () => {
492
+ const testInvoice = await lightsparkClient.createTestModeInvoice(
493
+ getRegtestNodeId(),
494
+ 0,
495
+ "",
496
+ InvoiceType.AMP,
497
+ );
498
+ expect(testInvoice).not.toBeNull();
499
+ },
500
+ TESTS_TIMEOUT,
501
+ );
502
+
503
+ test(
504
+ "should create a clear memo test mode invoice",
505
+ async () => {
506
+ testModeInvoices.withoutMemo =
507
+ await lightsparkClient.createTestModeInvoice(getRegtestNodeId(), 0);
508
+ expect(testModeInvoices.withoutMemo).not.toBeNull();
509
+ },
510
+ TESTS_TIMEOUT,
511
+ );
512
+
513
+ test(
514
+ "should pay a test mode invoice",
515
+ async () => {
516
+ if (!testModeInvoices.withoutMemo) {
517
+ throw new TypeError("Test mode invoice wasn't created");
518
+ }
519
+
520
+ const invoicePayment = await lightsparkClient.payInvoice(
521
+ getRegtestNodeId(),
522
+ testModeInvoices.withoutMemo,
523
+ MAX_FEE,
524
+ TESTS_TIMEOUT,
525
+ PAY_AMOUNT,
526
+ );
527
+ expect(invoicePayment).toBeDefined();
528
+ },
529
+ TESTS_TIMEOUT,
530
+ );
531
+
532
+ test(
533
+ "should create a test mode payment",
534
+ async () => {
535
+ const regtestNodeId = getRegtestNodeId();
536
+
537
+ const invoiceForTestPayment = await lightsparkClient.createInvoice(
538
+ regtestNodeId,
539
+ PAY_AMOUNT,
540
+ "hi there!",
541
+ );
542
+
543
+ if (!invoiceForTestPayment) {
544
+ throw new TypeError("Invoice for test payment wasn't created");
545
+ }
546
+
547
+ const payment = await lightsparkClient.createTestModePayment(
548
+ regtestNodeId,
549
+ invoiceForTestPayment,
550
+ );
551
+
552
+ if (!payment) {
553
+ throw new TypeError("Test mode payment wasn't created");
554
+ }
555
+
556
+ const transaction = await lightsparkClient.waitForTransactionComplete(
557
+ payment.id,
558
+ TRANSACTION_WAIT_TIME,
559
+ );
560
+
561
+ expect(transaction?.status).toBe(TransactionStatus.SUCCESS);
562
+ },
563
+ TESTS_TIMEOUT,
564
+ );
565
+
566
+ test(
567
+ "should successfully create an uma invoice",
568
+ async () => {
569
+ const nodeId = getRegtestNodeId();
570
+
571
+ const metadata = JSON.stringify([
572
+ ["text/plain", "Pay to vasp2.com user $bob"],
573
+ ["text/identifier", "$bob@vasp2.com"],
574
+ ]);
575
+
576
+ const umaInvoice = await lightsparkClient.createUmaInvoice(
577
+ nodeId,
578
+ 1000,
579
+ metadata,
580
+ );
581
+ expect(umaInvoice?.status).toEqual(PaymentRequestStatus.OPEN);
582
+ },
583
+ TESTS_TIMEOUT,
584
+ );
585
+ });
586
+
587
+ describe(p2SuiteName, () => {
588
+ test(
589
+ "should get a bitcoin fee estimate",
590
+ async () => {
591
+ const fee = await lightsparkClient.getBitcoinFeeEstimate();
592
+ expect(fee).not.toBeNull();
593
+ },
594
+ TESTS_TIMEOUT,
595
+ );
596
+
597
+ // FIXME: THIS ACTION WORKS ONLY IN MAINNET
598
+ // test('should send a keysend payment', async () => {
599
+ // const payment = await lightsparkClient.sendPayment(
600
+ // getRegtestNodeId(),
601
+ // '018afbd7e2fd4f890000ac5e051e3488',
602
+ // TESTS_TIMEOUT,
603
+ // PAY_AMOUNT,
604
+ // MAX_FEE
605
+ // )
606
+ // expect(payment?.status).not.toBe(TransactionStatus.FAILED)
607
+ // })
608
+
609
+ test(
610
+ "should execute a raw graphql query",
611
+ async () => {
612
+ type DecodeInvoiceQueryResult = {
613
+ decoded_payment_request: {
614
+ __typename: "InvoiceData";
615
+ invoice_data_payment_hash: string;
616
+ invoice_data_amount: {
617
+ currency_amount_original_value: number;
618
+ };
619
+ invoice_data_memo: string;
620
+ };
621
+ };
622
+
623
+ const result = await lightsparkClient.executeRawQuery<
624
+ DecodeInvoiceQueryResult["decoded_payment_request"]
625
+ >({
626
+ queryPayload: DecodeInvoice,
627
+ variables: {
628
+ encoded_payment_request: ENCODED_REGTEST_REQUEST_FOR_TESTS,
629
+ },
630
+ constructObject: (data) =>
631
+ (data as DecodeInvoiceQueryResult)?.decoded_payment_request,
632
+ });
633
+
634
+ expect({
635
+ invoice_data_payment_hash: result?.invoice_data_payment_hash,
636
+ invoice_data_amount: {
637
+ currency_amount_original_value:
638
+ result?.invoice_data_amount.currency_amount_original_value,
639
+ },
640
+ invoice_data_memo: result?.invoice_data_memo,
641
+ }).toEqual({
642
+ invoice_data_payment_hash:
643
+ "7806a0f8acd5385f9dd13d0aaa14922a7349afc5ba5d4b2bbbaaab5abd7f93ca",
644
+ invoice_data_amount: {
645
+ currency_amount_original_value: 0,
646
+ },
647
+ invoice_data_memo: "hi there!",
648
+ });
649
+ },
650
+ TESTS_TIMEOUT,
651
+ );
652
+ });
@@ -4,10 +4,13 @@ import {
4
4
  } from "../objects/InvoiceData.js";
5
5
 
6
6
  describe("Serialization", () => {
7
- test("should serialize and deserialize InvoiceData to the same object", async () => {
7
+ test("should serialize and deserialize InvoiceData to the same object", () => {
8
8
  const serialized = `{"__typename": "InvoiceData", "invoice_data_encoded_payment_request":"lnbcrt34170n1pj5vdn4pp56jhw0672v566u4rvl333v8hwwuvavvu9gx4a2mqag4pkrvm0hwkqhp5xaz278y6cejcvpqnndl4wfq3slgthjduwlfksg778aevn23v2pdscqzpgxqyz5vqsp5ee5jezfvjqvvz7hfwta3ekk8hs6dq36szkgp40qh7twa8upquxlq9qyyssqjg2slc95falxf2t67y0wu2w43qwfcvfflwl8tn4ppqw9tumwqxk36qkfct9p2w8c3yy2ld7c6nacy4ssv2gl6qyqfpmhl4jmarnjf8cpvjlxek","invoice_data_bitcoin_network":"REGTEST","invoice_data_payment_hash":"d4aee7ebca6535ae546cfc63161eee7719d6338541abd56c1d454361b36fbbac","invoice_data_amount":{"currency_amount_original_value":3417,"currency_amount_original_unit":"SATOSHI","currency_amount_preferred_currency_unit":"USD","currency_amount_preferred_currency_value_rounded":118,"currency_amount_preferred_currency_value_approx":118.89352818371607},"invoice_data_created_at":"2023-11-04T12:17:57Z","invoice_data_expires_at":"2023-11-05T12:17:57Z","invoice_data_memo":null,"invoice_data_destination":{"graph_node_id":"GraphNode:0189a572-6dba-cf00-0000-ac0908d34ea6","graph_node_created_at":"2023-07-30T06:18:07.162759Z","graph_node_updated_at":"2023-11-04T12:01:04.015414Z","graph_node_alias":"ls_test_vSViIQitob_SE","graph_node_bitcoin_network":"REGTEST","graph_node_color":"#3399ff","graph_node_conductivity":null,"graph_node_display_name":"ls_test_vSViIQitob_SE","graph_node_public_key":"02253935a5703a6f0429081e08d2defce0faa15f4d75305302284751d53a4e0608", "__typename":"GraphNode"}}`;
9
9
  const deserialized = InvoiceDataFromJson(JSON.parse(serialized));
10
- const reserialized = InvoiceDataToJson(deserialized);
10
+ const reserialized = InvoiceDataToJson(deserialized) as Record<
11
+ string,
12
+ unknown
13
+ >;
11
14
  expect(reserialized).toEqual(JSON.parse(serialized));
12
15
 
13
16
  const deserializedAgain = InvoiceDataFromJson(reserialized);
package/src/webhooks.ts CHANGED
@@ -78,7 +78,7 @@ export class RemoteSigningWebhookHandler {
78
78
  this.validator,
79
79
  );
80
80
  const variables = JSON.parse(response.variables);
81
- this.client.executeRawQuery({
81
+ return this.client.executeRawQuery({
82
82
  queryPayload: response.query,
83
83
  variables,
84
84
  constructObject: (rawData: unknown) => rawData,