@lightsparkdev/lightspark-sdk 0.4.10 → 1.0.0

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 (125) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +1 -1
  3. package/dist/{chunk-NXUFC5J7.js → chunk-LZC5C5NI.js} +2908 -635
  4. package/dist/{index-3ffe9e7b.d.ts → index-09d4ac20.d.ts} +373 -62
  5. package/dist/index.cjs +3395 -842
  6. package/dist/index.d.ts +2 -2
  7. package/dist/index.js +390 -94
  8. package/dist/objects/index.cjs +2735 -553
  9. package/dist/objects/index.d.ts +1 -1
  10. package/dist/objects/index.js +17 -5
  11. package/package.json +12 -9
  12. package/src/NodeKeyLoaderCache.ts +87 -0
  13. package/src/SigningKeyLoader.ts +177 -0
  14. package/src/auth/AccountTokenAuthProvider.ts +4 -4
  15. package/src/client.ts +209 -118
  16. package/src/graphql/CreateInvoice.ts +3 -2
  17. package/src/graphql/CreateLnurlInvoice.ts +2 -0
  18. package/src/graphql/CreateUmaInvoice.ts +23 -0
  19. package/src/graphql/MultiNodeDashboard.ts +0 -3
  20. package/src/graphql/PayUmaInvoice.ts +29 -0
  21. package/src/graphql/RecoverNodeSigningKey.ts +1 -1
  22. package/src/graphql/SingleNodeDashboard.ts +0 -1
  23. package/src/lightspark_crypto/lightspark_crypto.d.ts +157 -0
  24. package/src/lightspark_crypto/lightspark_crypto.js +1010 -0
  25. package/src/lightspark_crypto/lightspark_crypto_bg.wasm +0 -0
  26. package/src/lightspark_crypto/lightspark_crypto_bg.wasm.d.ts +120 -0
  27. package/src/lightspark_crypto/package.json +11 -0
  28. package/src/objects/Account.ts +437 -120
  29. package/src/objects/AccountToApiTokensConnection.ts +3 -3
  30. package/src/objects/AccountToChannelsConnection.ts +4 -4
  31. package/src/objects/AccountToNodesConnection.ts +2 -15
  32. package/src/objects/AccountToPaymentRequestsConnection.ts +3 -3
  33. package/src/objects/AccountToTransactionsConnection.ts +6 -6
  34. package/src/objects/AccountToWalletsConnection.ts +2 -2
  35. package/src/objects/Balances.ts +2 -2
  36. package/src/objects/Channel.ts +4 -4
  37. package/src/objects/ChannelClosingTransaction.ts +2 -2
  38. package/src/objects/ChannelOpeningTransaction.ts +2 -2
  39. package/src/objects/ChannelToTransactionsConnection.ts +4 -4
  40. package/src/objects/{CryptoSanctionsScreeningProvider.ts → ComplianceProvider.ts} +3 -3
  41. package/src/objects/Connection.ts +25 -31
  42. package/src/objects/CreateApiTokenInput.ts +1 -1
  43. package/src/objects/CreateApiTokenOutput.ts +1 -1
  44. package/src/objects/CreateInvoiceInput.ts +0 -6
  45. package/src/objects/CreateLnurlInvoiceInput.ts +1 -7
  46. package/src/objects/CreateNodeWalletAddressInput.ts +1 -1
  47. package/src/objects/CreateNodeWalletAddressOutput.ts +1 -1
  48. package/src/objects/CreateTestModeInvoiceInput.ts +1 -1
  49. package/src/objects/CreateTestModeInvoiceOutput.ts +1 -1
  50. package/src/objects/CreateTestModePaymentInput.ts +1 -1
  51. package/src/objects/CreateTestModePaymentoutput.ts +14 -2
  52. package/src/objects/CreateUmaInvoiceInput.ts +24 -0
  53. package/src/objects/DeclineToSignMessagesInput.ts +16 -0
  54. package/src/objects/DeclineToSignMessagesOutput.ts +28 -0
  55. package/src/objects/DeleteApiTokenOutput.ts +1 -1
  56. package/src/objects/Entity.ts +401 -66
  57. package/src/objects/GraphNode.ts +3 -3
  58. package/src/objects/IdAndSignature.ts +16 -0
  59. package/src/objects/IncomingPayment.ts +21 -8
  60. package/src/objects/IncomingPaymentAttempt.ts +2 -2
  61. package/src/objects/IncomingPaymentToAttemptsConnection.ts +3 -3
  62. package/src/objects/Invoice.ts +118 -21
  63. package/src/objects/InvoiceData.ts +118 -21
  64. package/src/objects/LightningFeeEstimateForInvoiceInput.ts +1 -1
  65. package/src/objects/LightningFeeEstimateForNodeInput.ts +1 -1
  66. package/src/objects/LightningFeeEstimateOutput.ts +2 -2
  67. package/src/objects/LightningTransaction.ts +155 -31
  68. package/src/objects/LightsparkNode.ts +272 -112
  69. package/src/objects/LightsparkNodeOwner.ts +8 -4
  70. package/src/objects/LightsparkNodeToChannelsConnection.ts +3 -3
  71. package/src/objects/LightsparkNodeWithOSK.ts +389 -0
  72. package/src/objects/LightsparkNodeWithRemoteSigning.ts +384 -0
  73. package/src/objects/Node.ts +213 -60
  74. package/src/objects/NodeToAddressesConnection.ts +2 -2
  75. package/src/objects/OnChainTransaction.ts +2 -2
  76. package/src/objects/OutgoingPayment.ts +139 -24
  77. package/src/objects/OutgoingPaymentAttempt.ts +5 -5
  78. package/src/objects/OutgoingPaymentAttemptToHopsConnection.ts +3 -3
  79. package/src/objects/OutgoingPaymentToAttemptsConnection.ts +3 -3
  80. package/src/objects/OutgoingPaymentsForInvoiceQueryInput.ts +25 -0
  81. package/src/objects/OutgoingPaymentsForInvoiceQueryOutput.ts +28 -0
  82. package/src/objects/PayUmaInvoiceInput.ts +25 -0
  83. package/src/objects/{LightsparkNodePurpose.ts → PaymentDirection.ts} +5 -7
  84. package/src/objects/PaymentRequest.ts +119 -22
  85. package/src/objects/PaymentRequestData.ts +119 -22
  86. package/src/objects/PostTransactionData.ts +39 -0
  87. package/src/objects/RegisterPaymentInput.ts +31 -0
  88. package/src/objects/RegisterPaymentOutput.ts +23 -0
  89. package/src/objects/ReleaseChannelPerCommitmentSecretInput.ts +23 -0
  90. package/src/objects/ReleaseChannelPerCommitmentSecretOutput.ts +23 -0
  91. package/src/objects/ReleasePaymentPreimageInput.ts +20 -0
  92. package/src/objects/ReleasePaymentPreimageOutput.ts +23 -0
  93. package/src/objects/RemoteSigningSubEventType.ts +26 -0
  94. package/src/objects/RequestWithdrawalInput.ts +1 -1
  95. package/src/objects/RequestWithdrawalOutput.ts +1 -1
  96. package/src/objects/RoutingTransaction.ts +1 -1
  97. package/src/objects/ScreenNodeInput.ts +20 -0
  98. package/src/objects/ScreenNodeOutput.ts +22 -0
  99. package/src/objects/SetInvoicePaymentHashInput.ts +24 -0
  100. package/src/objects/SetInvoicePaymentHashOutput.ts +23 -0
  101. package/src/objects/SignInvoiceInput.ts +19 -0
  102. package/src/objects/SignInvoiceOutput.ts +21 -0
  103. package/src/objects/SignMessagesInput.ts +18 -0
  104. package/src/objects/SignMessagesOutput.ts +26 -0
  105. package/src/objects/Signable.ts +58 -0
  106. package/src/objects/SignablePayload.ts +93 -0
  107. package/src/objects/SignablePayloadStatus.ts +17 -0
  108. package/src/objects/SingleNodeDashboard.ts +0 -2
  109. package/src/objects/Transaction.ts +153 -29
  110. package/src/objects/TransactionFailures.ts +1 -1
  111. package/src/objects/UpdateChannelPerCommitmentPointInput.ts +25 -0
  112. package/src/objects/UpdateChannelPerCommitmentPointOutput.ts +23 -0
  113. package/src/objects/UpdateNodeSharedSecretInput.ts +18 -0
  114. package/src/objects/UpdateNodeSharedSecretOutput.ts +23 -0
  115. package/src/objects/Wallet.ts +271 -51
  116. package/src/objects/WalletToPaymentRequestsConnection.ts +3 -3
  117. package/src/objects/WalletToTransactionsConnection.ts +3 -3
  118. package/src/objects/WithdrawalRequest.ts +6 -6
  119. package/src/objects/WithdrawalRequestToChannelClosingTransactionsConnection.ts +2 -2
  120. package/src/objects/WithdrawalRequestToChannelOpeningTransactionsConnection.ts +2 -2
  121. package/src/objects/index.ts +37 -4
  122. package/src/{__tests__ → tests}/webhooks.test.ts +1 -1
  123. package/src/webhooks.ts +1 -1
  124. package/src/objects/ScreenBitcoinAddressesInput.ts +0 -23
  125. package/src/objects/ScreenBitcoinAddressesOutput.ts +0 -25
package/src/client.ts CHANGED
@@ -9,16 +9,16 @@ import type {
9
9
  KeyOrAliasType,
10
10
  Maybe,
11
11
  Query,
12
+ SigningKey,
12
13
  } from "@lightsparkdev/core";
13
14
  import {
14
- b64encode,
15
15
  DefaultCrypto,
16
- KeyOrAlias,
17
16
  LightsparkAuthException,
18
17
  LightsparkException,
19
18
  LightsparkSigningException,
20
19
  NodeKeyCache,
21
20
  Requester,
21
+ SigningKeyType,
22
22
  StubAuthProvider,
23
23
  } from "@lightsparkdev/core";
24
24
  import { createHash } from "crypto";
@@ -30,6 +30,7 @@ import { CreateLnurlInvoice } from "./graphql/CreateLnurlInvoice.js";
30
30
  import { CreateNodeWalletAddress } from "./graphql/CreateNodeWalletAddress.js";
31
31
  import { CreateTestModeInvoice } from "./graphql/CreateTestModeInvoice.js";
32
32
  import { CreateTestModePayment } from "./graphql/CreateTestModePayment.js";
33
+ import { CreateUmaInvoice } from "./graphql/CreateUmaInvoice.js";
33
34
  import { DecodeInvoice } from "./graphql/DecodeInvoice.js";
34
35
  import { DeleteApiToken } from "./graphql/DeleteApiToken.js";
35
36
  import { FundNode } from "./graphql/FundNode.js";
@@ -38,12 +39,13 @@ import { LightningFeeEstimateForNode } from "./graphql/LightningFeeEstimateForNo
38
39
  import type { AccountDashboard } from "./graphql/MultiNodeDashboard.js";
39
40
  import { MultiNodeDashboard } from "./graphql/MultiNodeDashboard.js";
40
41
  import { PayInvoice } from "./graphql/PayInvoice.js";
41
- import { RecoverNodeSigningKey } from "./graphql/RecoverNodeSigningKey.js";
42
+ import { PayUmaInvoice } from "./graphql/PayUmaInvoice.js";
42
43
  import { RequestWithdrawal } from "./graphql/RequestWithdrawal.js";
43
44
  import { SendPayment } from "./graphql/SendPayment.js";
44
45
  import { SingleNodeDashboard as SingleNodeDashboardQuery } from "./graphql/SingleNodeDashboard.js";
45
46
  import { TransactionsForNode } from "./graphql/TransactionsForNode.js";
46
47
  import { TransactionSubscription } from "./graphql/TransactionSubscription.js";
48
+ import NodeKeyLoaderCache from "./NodeKeyLoaderCache.js";
47
49
  import Account from "./objects/Account.js";
48
50
  import { ApiTokenFromJson } from "./objects/ApiToken.js";
49
51
  import BitcoinNetwork from "./objects/BitcoinNetwork.js";
@@ -68,6 +70,7 @@ import { TransactionUpdateFromJson } from "./objects/TransactionUpdate.js";
68
70
  import type WithdrawalMode from "./objects/WithdrawalMode.js";
69
71
  import type WithdrawalRequest from "./objects/WithdrawalRequest.js";
70
72
  import { WithdrawalRequestFromJson } from "./objects/WithdrawalRequest.js";
73
+ import { type SigningKeyLoaderArgs } from "./SigningKeyLoader.js";
71
74
 
72
75
  const sdkVersion = packageJson.version;
73
76
 
@@ -97,6 +100,9 @@ const sdkVersion = packageJson.version;
97
100
  class LightsparkClient {
98
101
  private requester: Requester;
99
102
  private readonly nodeKeyCache: NodeKeyCache;
103
+ private readonly nodeKeyLoaderCache: NodeKeyLoaderCache;
104
+ private readonly LIGHTSPARK_SDK_ENDPOINT =
105
+ process.env.LIGHTSPARK_SDK_ENDPOINT || "graphql/server/2023-09-13";
100
106
 
101
107
  /**
102
108
  * Constructs a new LightsparkClient.
@@ -110,21 +116,54 @@ class LightsparkClient {
110
116
  constructor(
111
117
  private authProvider: AuthProvider = new StubAuthProvider(),
112
118
  private readonly serverUrl: string = "api.lightspark.com",
113
- private readonly cryptoImpl: CryptoInterface = DefaultCrypto
119
+ private readonly cryptoImpl: CryptoInterface = DefaultCrypto,
114
120
  ) {
115
121
  this.nodeKeyCache = new NodeKeyCache(this.cryptoImpl);
122
+ this.nodeKeyLoaderCache = new NodeKeyLoaderCache(
123
+ this.nodeKeyCache,
124
+ this.cryptoImpl,
125
+ );
116
126
  this.requester = new Requester(
117
127
  this.nodeKeyCache,
118
- LIGHTSPARK_SDK_ENDPOINT,
128
+ this.LIGHTSPARK_SDK_ENDPOINT,
119
129
  `js-lightspark-sdk/${sdkVersion}`,
120
130
  authProvider,
121
131
  serverUrl,
122
- this.cryptoImpl
132
+ this.cryptoImpl,
123
133
  );
124
134
 
125
135
  autoBind(this);
126
136
  }
127
137
 
138
+ /**
139
+ * Sets the key loader for a node. This unlocks client operations that require a private key.
140
+ * Passing in [NodeIdAndPasswordSigningKeyLoaderArgs] loads the RSA key for an OSK node.
141
+ * Passing in [MasterSeedSigningKeyLoaderArgs] loads the Secp256k1 key for a remote signing node.
142
+ *
143
+ * @param nodeId The ID of the node the key is for
144
+ * @param loader The loader for the key
145
+ */
146
+ public async loadNodeSigningKey(
147
+ nodeId: string,
148
+ loaderArgs: SigningKeyLoaderArgs,
149
+ ) {
150
+ this.nodeKeyLoaderCache.setLoader(nodeId, loaderArgs, this.requester);
151
+ const key = await this.getNodeSigningKey(nodeId);
152
+ return !!key;
153
+ }
154
+
155
+ /**
156
+ * Gets the signing key for a node. Must have previously called [loadNodeSigningKey].
157
+ *
158
+ * @param nodeId The ID of the node the key is for
159
+ * @returns The signing key for the node
160
+ */
161
+ public async getNodeSigningKey(
162
+ nodeId: string,
163
+ ): Promise<SigningKey | undefined> {
164
+ return await this.nodeKeyLoaderCache.getKeyWithLoader(nodeId);
165
+ }
166
+
128
167
  /**
129
168
  * Sets the auth provider for the client. This is useful for switching between auth providers if you are using
130
169
  * multiple accounts or waiting for the user to log in.
@@ -134,11 +173,11 @@ class LightsparkClient {
134
173
  public async setAuthProvider(authProvider: AuthProvider) {
135
174
  this.requester = new Requester(
136
175
  this.nodeKeyCache,
137
- LIGHTSPARK_SDK_ENDPOINT,
176
+ this.LIGHTSPARK_SDK_ENDPOINT,
138
177
  `js-lightspark-sdk/${sdkVersion}`,
139
178
  authProvider,
140
179
  this.serverUrl,
141
- this.cryptoImpl
180
+ this.cryptoImpl,
142
181
  );
143
182
  this.authProvider = authProvider;
144
183
  }
@@ -155,7 +194,7 @@ class LightsparkClient {
155
194
  */
156
195
  public async getCurrentAccount(): Promise<Maybe<Account>> {
157
196
  return await this.requester.executeQuery<Account>(
158
- Account.getAccountQuery()
197
+ Account.getAccountQuery(),
159
198
  );
160
199
  }
161
200
 
@@ -172,7 +211,7 @@ class LightsparkClient {
172
211
  nodeId: string,
173
212
  numTransactions: number = 20,
174
213
  bitcoinNetwork: BitcoinNetwork = BitcoinNetwork.MAINNET,
175
- afterDate: Maybe<string> = undefined
214
+ afterDate: Maybe<string> = undefined,
176
215
  ): Promise<Transaction[]> {
177
216
  const response = await this.requester.makeRawRequest(TransactionsForNode, {
178
217
  nodeId,
@@ -182,7 +221,7 @@ class LightsparkClient {
182
221
  });
183
222
  return (
184
223
  response.current_account?.recent_transactions.entities.map(
185
- (transaction) => TransactionFromJson(transaction)
224
+ (transaction) => TransactionFromJson(transaction),
186
225
  ) ?? []
187
226
  );
188
227
  }
@@ -194,19 +233,19 @@ class LightsparkClient {
194
233
  * @returns A zen-observable that emits transaction updates for the given node IDs.
195
234
  */
196
235
  public listenToTransactions(
197
- nodeIds: string[]
236
+ nodeIds: string[],
198
237
  ): Observable<TransactionUpdate | undefined> {
199
238
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
200
239
  const response = this.requester.subscribe<{ transactions: any }>(
201
240
  TransactionSubscription,
202
241
  {
203
242
  nodeIds,
204
- }
243
+ },
205
244
  );
206
245
  return response.map(
207
246
  (response) =>
208
247
  response?.data?.transactions &&
209
- TransactionUpdateFromJson(response.data.transactions)
248
+ TransactionUpdateFromJson(response.data.transactions),
210
249
  );
211
250
  }
212
251
 
@@ -221,7 +260,7 @@ class LightsparkClient {
221
260
  */
222
261
  public async getAccountDashboard(
223
262
  nodeIds: string[] | undefined = undefined,
224
- bitcoinNetwork: BitcoinNetwork = BitcoinNetwork.MAINNET
263
+ bitcoinNetwork: BitcoinNetwork = BitcoinNetwork.MAINNET,
225
264
  ): Promise<AccountDashboard> {
226
265
  const response = await this.requester.makeRawRequest(MultiNodeDashboard, {
227
266
  nodeIds: nodeIds,
@@ -240,7 +279,7 @@ class LightsparkClient {
240
279
  1. You are requesting MAINNET nodes, but you have no MAINNET nodes yet. In this case, request BitcoinNetwork.REGTEST instead.
241
280
  2. You are specifying specific node IDs, but those IDs don't exist or are not on the bitcoid network you requested.
242
281
  3. The api token or authentication mechanism you are using is not authorized to access the nodes you requested. If you're using
243
- an API token, make sure it has the correct permissions for the desired network (only test tokens have access to REGTEST nodes).`
282
+ an API token, make sure it has the correct permissions for the desired network (only test tokens have access to REGTEST nodes).`,
244
283
  );
245
284
  }
246
285
  const account = response.current_account;
@@ -251,7 +290,6 @@ class LightsparkClient {
251
290
  return {
252
291
  color: node.color,
253
292
  displayName: node.display_name,
254
- purpose: node.purpose,
255
293
  id: node.id,
256
294
  publicKey: node.public_key,
257
295
  status: node.status,
@@ -281,17 +319,17 @@ class LightsparkClient {
281
319
  requiredReserve:
282
320
  account.blockchain_balance.required_reserve &&
283
321
  CurrencyAmountFromJson(
284
- account.blockchain_balance.required_reserve
322
+ account.blockchain_balance.required_reserve,
285
323
  ),
286
324
  availableBalance:
287
325
  account.blockchain_balance.available_balance &&
288
326
  CurrencyAmountFromJson(
289
- account.blockchain_balance.available_balance
327
+ account.blockchain_balance.available_balance,
290
328
  ),
291
329
  unconfirmedBalance:
292
330
  account.blockchain_balance.unconfirmed_balance &&
293
331
  CurrencyAmountFromJson(
294
- account.blockchain_balance.unconfirmed_balance
332
+ account.blockchain_balance.unconfirmed_balance,
295
333
  ),
296
334
  }
297
335
  : null,
@@ -316,7 +354,7 @@ class LightsparkClient {
316
354
  public async getSingleNodeDashboard(
317
355
  nodeId: string,
318
356
  bitcoinNetwork: BitcoinNetwork = BitcoinNetwork.MAINNET,
319
- transactionsAfterDate: Maybe<string> = undefined
357
+ transactionsAfterDate: Maybe<string> = undefined,
320
358
  ): Promise<SingleNodeDashboard> {
321
359
  const response = await this.requester.makeRawRequest(
322
360
  SingleNodeDashboardQuery,
@@ -325,7 +363,7 @@ class LightsparkClient {
325
363
  network: bitcoinNetwork,
326
364
  numTransactions: 20,
327
365
  transactionsAfterDate,
328
- }
366
+ },
329
367
  );
330
368
  if (!response.current_account) {
331
369
  throw new LightsparkAuthException("No current account");
@@ -338,7 +376,7 @@ class LightsparkClient {
338
376
  ) {
339
377
  throw new LightsparkException(
340
378
  "InvalidOrMissingNode",
341
- "No nodes found for node dashboard"
379
+ "No nodes found for node dashboard",
342
380
  );
343
381
  }
344
382
  const node = account.dashboard_overview_nodes.entities[0];
@@ -354,7 +392,6 @@ class LightsparkClient {
354
392
  return {
355
393
  color: node.color,
356
394
  displayName: account.name,
357
- purpose: node.purpose,
358
395
  id: node.id,
359
396
  publicKey: node.public_key,
360
397
  status: node.status,
@@ -365,16 +402,16 @@ class LightsparkClient {
365
402
  remoteBalance: currencyAmountOrUndefined(node.remote_balance),
366
403
  blockchainBalance: node.blockchain_balance && {
367
404
  availableBalance: currencyAmountOrUndefined(
368
- node.blockchain_balance.available_balance
405
+ node.blockchain_balance.available_balance,
369
406
  ),
370
407
  confirmedBalance: currencyAmountOrUndefined(
371
- node.blockchain_balance.confirmed_balance
408
+ node.blockchain_balance.confirmed_balance,
372
409
  ),
373
410
  unconfirmedBalance: currencyAmountOrUndefined(
374
- node.blockchain_balance.unconfirmed_balance
411
+ node.blockchain_balance.unconfirmed_balance,
375
412
  ),
376
413
  totalBalance: currencyAmountOrUndefined(
377
- node.blockchain_balance.total_balance
414
+ node.blockchain_balance.total_balance,
378
415
  ),
379
416
  },
380
417
  recentTransactions:
@@ -395,20 +432,29 @@ class LightsparkClient {
395
432
  * @param type The type of invoice to create. Defaults to a normal payment invoice, but you can pass InvoiceType.AMP
396
433
  * to create an [AMP invoice](https://docs.lightning.engineering/lightning-network-tools/lnd/amp), which can be
397
434
  * paid multiple times.
435
+ * @param expirySecs The number of seconds until the invoice expires. Defaults to 86400 (1 day).
398
436
  * @returns An encoded payment request for the invoice, or undefined if the invoice could not be created.
399
437
  */
400
438
  public async createInvoice(
401
439
  nodeId: string,
402
440
  amountMsats: number,
403
441
  memo: string,
404
- type: InvoiceType | undefined = undefined
442
+ type: InvoiceType | undefined = undefined,
443
+ expirySecs: number | undefined = undefined,
405
444
  ): Promise<string | undefined> {
406
- const response = await this.requester.makeRawRequest(CreateInvoice, {
445
+ const variables = {
407
446
  node_id: nodeId,
408
447
  amount_msats: amountMsats,
409
448
  memo,
410
449
  type,
411
- });
450
+ };
451
+ if (expirySecs !== undefined) {
452
+ variables["expiry_secs"] = expirySecs;
453
+ }
454
+ const response = await this.requester.makeRawRequest(
455
+ CreateInvoice,
456
+ variables,
457
+ );
412
458
  return response.create_invoice?.invoice.data?.encoded_payment_request;
413
459
  }
414
460
 
@@ -424,18 +470,27 @@ class LightsparkClient {
424
470
  * @param metadata The LNURL metadata payload field in the initial payreq response. This wil be hashed and present in the
425
471
  * h-tag (SHA256 purpose of payment) of the resulting Bolt 11 invoice. See
426
472
  * [this spec](https://github.com/lnurl/luds/blob/luds/06.md#pay-to-static-qrnfclink) for details.
473
+ * @param expirySecs The number of seconds until the invoice expires. Defaults to 86400 (1 day).
427
474
  * @returns An Invoice object representing the generated invoice.
428
475
  */
429
476
  public async createLnurlInvoice(
430
477
  nodeId: string,
431
478
  amountMsats: number,
432
- metadata: string
479
+ metadata: string,
480
+ expirySecs: number | undefined = undefined,
433
481
  ): Promise<Invoice | undefined> {
434
- const response = await this.requester.makeRawRequest(CreateLnurlInvoice, {
482
+ const variables = {
435
483
  node_id: nodeId,
436
484
  amount_msats: amountMsats,
437
485
  metadata_hash: createHash("sha256").update(metadata).digest("hex"),
438
- });
486
+ };
487
+ if (expirySecs !== undefined) {
488
+ variables["expiry_secs"] = expirySecs;
489
+ }
490
+ const response = await this.requester.makeRawRequest(
491
+ CreateLnurlInvoice,
492
+ variables,
493
+ );
439
494
  const invoiceJson = response.create_lnurl_invoice?.invoice;
440
495
  if (!invoiceJson) {
441
496
  return undefined;
@@ -443,6 +498,43 @@ class LightsparkClient {
443
498
  return InvoiceFromJson(invoiceJson);
444
499
  }
445
500
 
501
+ /**
502
+ * Creates a new invoice for the UMA protocol. The metadata is hashed and included in the invoice.
503
+ * This API generates a Lightning Invoice (follows the Bolt 11 specification) to request a payment
504
+ * from another Lightning Node. This should only be used for generating invoices for UMA, with `createInvoice`
505
+ * preferred in the general case.
506
+ *
507
+ * @param nodeId The node ID for which to create an invoice.
508
+ * @param amountMsats The amount of the invoice in msats. You can create a zero-amount invoice to accept any payment amount.
509
+ * @param metadata The LNURL metadata payload field in the initial payreq response. This wil be hashed and present in the
510
+ * h-tag (SHA256 purpose of payment) of the resulting Bolt 11 invoice. See
511
+ * [this spec](https://github.com/lnurl/luds/blob/luds/06.md#pay-to-static-qrnfclink) for details.
512
+ * @param expirySecs The number of seconds until the invoice expires. Defaults to 3600 (1 hour).
513
+ * @returns An Invoice object representing the generated invoice.
514
+ */
515
+ public async createUmaInvoice(
516
+ nodeId: string,
517
+ amountMsats: number,
518
+ metadata: string,
519
+ expirySecs: number | undefined = undefined,
520
+ ): Promise<Invoice | undefined> {
521
+ const variables = {
522
+ node_id: nodeId,
523
+ amount_msats: amountMsats,
524
+ metadata_hash: createHash("sha256").update(metadata).digest("hex"),
525
+ expiry_secs: expirySecs !== undefined ? expirySecs : 3600,
526
+ };
527
+ const response = await this.requester.makeRawRequest(
528
+ CreateUmaInvoice,
529
+ variables,
530
+ );
531
+ const invoiceJson = response.create_uma_invoice?.invoice;
532
+ if (!invoiceJson) {
533
+ return undefined;
534
+ }
535
+ return InvoiceFromJson(invoiceJson);
536
+ }
537
+
446
538
  /**
447
539
  * Decodes an encoded lightning invoice string.
448
540
  *
@@ -463,13 +555,13 @@ class LightsparkClient {
463
555
  * @returns A fee estimate for the given bitcoin network including a minimum fee rate, and a max-speed fee rate.
464
556
  */
465
557
  public async getBitcoinFeeEstimate(
466
- bitcoinNetwork: BitcoinNetwork = BitcoinNetwork.MAINNET
558
+ bitcoinNetwork: BitcoinNetwork = BitcoinNetwork.MAINNET,
467
559
  ): Promise<FeeEstimate> {
468
560
  const response = await this.requester.makeRawRequest(
469
561
  BitcoinFeeEstimateQuery,
470
562
  {
471
563
  bitcoin_network: bitcoinNetwork,
472
- }
564
+ },
473
565
  );
474
566
  return FeeEstimateFromJson(response.bitcoin_fee_estimate);
475
567
  }
@@ -486,7 +578,7 @@ class LightsparkClient {
486
578
  public async getLightningFeeEstimateForInvoice(
487
579
  nodeId: string,
488
580
  encodedPaymentRequest: string,
489
- amountMsats: number | undefined = undefined
581
+ amountMsats: number | undefined = undefined,
490
582
  ): Promise<CurrencyAmount> {
491
583
  const response = await this.requester.makeRawRequest(
492
584
  LightningFeeEstimateForInvoice,
@@ -494,11 +586,11 @@ class LightsparkClient {
494
586
  node_id: nodeId,
495
587
  encoded_payment_request: encodedPaymentRequest,
496
588
  amount_msats: amountMsats,
497
- }
589
+ },
498
590
  );
499
591
  return CurrencyAmountFromJson(
500
592
  response.lightning_fee_estimate_for_invoice
501
- .lightning_fee_estimate_output_fee_estimate
593
+ .lightning_fee_estimate_output_fee_estimate,
502
594
  );
503
595
  }
504
596
 
@@ -513,7 +605,7 @@ class LightsparkClient {
513
605
  public async getLightningFeeEstimateForNode(
514
606
  nodeId: string,
515
607
  destinationNodePublicKey: string,
516
- amountMsats: number
608
+ amountMsats: number,
517
609
  ): Promise<CurrencyAmount> {
518
610
  const response = await this.requester.makeRawRequest(
519
611
  LightningFeeEstimateForNode,
@@ -521,69 +613,12 @@ class LightsparkClient {
521
613
  node_id: nodeId,
522
614
  destination_node_public_key: destinationNodePublicKey,
523
615
  amount_msats: amountMsats,
524
- }
616
+ },
525
617
  );
526
618
  return CurrencyAmountFromJson(
527
619
  response.lightning_fee_estimate_for_node
528
- .lightning_fee_estimate_output_fee_estimate
529
- );
530
- }
531
-
532
- /**
533
- * Unlock the given node for sensitive operations like sending payments.
534
- *
535
- * @param nodeId The ID of the node to unlock.
536
- * @param password The node password assigned at node creation.
537
- * @returns True if the node was unlocked successfully, false otherwise.
538
- */
539
- public async unlockNode(nodeId: string, password: string): Promise<boolean> {
540
- const encryptedKey = await this.recoverNodeSigningKey(nodeId);
541
- if (!encryptedKey) {
542
- console.warn("No encrypted key found for node " + nodeId);
543
- return false;
544
- }
545
-
546
- const signingPrivateKey =
547
- await this.cryptoImpl.decryptSecretWithNodePassword(
548
- encryptedKey.cipher,
549
- encryptedKey.encrypted_value,
550
- password
551
- );
552
-
553
- if (!signingPrivateKey) {
554
- throw new LightsparkSigningException(
555
- "Unable to decrypt signing key with provided password. Please try again."
556
- );
557
- }
558
-
559
- let signingPrivateKeyPEM = "";
560
- if (new Uint8Array(signingPrivateKey)[0] === 48) {
561
- // Support DER format - https://github.com/lightsparkdev/webdev/pull/1982
562
- signingPrivateKeyPEM = b64encode(signingPrivateKey);
563
- } else {
564
- const dec = new TextDecoder();
565
- signingPrivateKeyPEM = dec.decode(signingPrivateKey);
566
- }
567
-
568
- await this.nodeKeyCache.loadKey(
569
- nodeId,
570
- KeyOrAlias.key(signingPrivateKeyPEM)
620
+ .lightning_fee_estimate_output_fee_estimate,
571
621
  );
572
- return true;
573
- }
574
-
575
- private async recoverNodeSigningKey(
576
- nodeId: string
577
- ): Promise<Maybe<{ encrypted_value: string; cipher: string }>> {
578
- const response = await this.requester.makeRawRequest(
579
- RecoverNodeSigningKey,
580
- { nodeId }
581
- );
582
- const nodeEntity = response.entity;
583
- if (nodeEntity?.__typename === "LightsparkNode") {
584
- return nodeEntity.encrypted_signing_private_key;
585
- }
586
- return null;
587
622
  }
588
623
 
589
624
  /**
@@ -594,9 +629,13 @@ class LightsparkClient {
594
629
  */
595
630
  public async loadNodeKey(
596
631
  nodeId: string,
597
- signingPrivateKeyOrAlias: KeyOrAliasType
632
+ signingPrivateKeyOrAlias: KeyOrAliasType,
598
633
  ) {
599
- await this.nodeKeyCache.loadKey(nodeId, signingPrivateKeyOrAlias);
634
+ await this.nodeKeyCache.loadKey(
635
+ nodeId,
636
+ signingPrivateKeyOrAlias,
637
+ SigningKeyType.RSASigningKey,
638
+ );
600
639
  }
601
640
 
602
641
  /**
@@ -620,7 +659,7 @@ class LightsparkClient {
620
659
  encodedInvoice: string,
621
660
  maximumFeesMsats: number,
622
661
  timeoutSecs: number = 60,
623
- amountMsats: number | undefined = undefined
662
+ amountMsats: number | undefined = undefined,
624
663
  ): Promise<OutgoingPayment | undefined> {
625
664
  if (!this.nodeKeyCache.hasKey(payerNodeId)) {
626
665
  throw new LightsparkSigningException("Paying node is not unlocked");
@@ -637,12 +676,13 @@ class LightsparkClient {
637
676
  const response = await this.requester.makeRawRequest(
638
677
  PayInvoice,
639
678
  variables,
640
- payerNodeId
679
+ payerNodeId,
641
680
  );
642
681
  if (response.pay_invoice?.payment.outgoing_payment_failure_message) {
643
682
  throw new LightsparkException(
644
683
  "PaymentError",
645
- response.pay_invoice?.payment.outgoing_payment_failure_message.rich_text_text
684
+ response.pay_invoice?.payment.outgoing_payment_failure_message
685
+ .rich_text_text,
646
686
  );
647
687
  }
648
688
  return (
@@ -651,6 +691,58 @@ class LightsparkClient {
651
691
  );
652
692
  }
653
693
 
694
+ /**
695
+ * sends an UMA payment to a node on the Lightning Network, based on the invoice
696
+ * (as defined by the BOLT11 specification) that you provide.
697
+ * This should only be used for paying UMA invoices, with `payInvoice` preferred in the general case.
698
+ *
699
+ * @param payerNodeId The ID of the node that will pay the invoice.
700
+ * @param encodedInvoice The encoded invoice to pay.
701
+ * @param maximumFeesMsats Maximum fees (in msats) to pay for the payment. This parameter is required.
702
+ * As guidance, a maximum fee of 16 basis points should make almost all transactions succeed. For example,
703
+ * for a transaction between 10k sats and 100k sats, this would mean a fee limit of 16 to 160 sats.
704
+ * @param timeoutSecs A timeout for the payment in seconds. Defaults to 60 seconds.
705
+ * @param amountMsats The amount to pay in msats for a zero-amount invoice. Defaults to the full amount of the
706
+ * invoice. NOTE: This parameter can only be passed for a zero-amount invoice. Otherwise, the call will fail.
707
+ * @returns An `OutgoingPayment` object if the payment was successful, or undefined if the payment failed.
708
+ */
709
+ public async payUmaInvoice(
710
+ payerNodeId: string,
711
+ encodedInvoice: string,
712
+ maximumFeesMsats: number,
713
+ timeoutSecs: number = 60,
714
+ amountMsats: number | undefined = undefined,
715
+ ): Promise<OutgoingPayment | undefined> {
716
+ if (!this.nodeKeyCache.hasKey(payerNodeId)) {
717
+ throw new LightsparkSigningException("Paying node is not unlocked");
718
+ }
719
+ const variables: Record<string, string | number> = {
720
+ node_id: payerNodeId,
721
+ encoded_invoice: encodedInvoice,
722
+ timeout_secs: timeoutSecs,
723
+ maximum_fees_msats: maximumFeesMsats,
724
+ };
725
+ if (amountMsats !== undefined) {
726
+ variables.amount_msats = amountMsats;
727
+ }
728
+ const response = await this.requester.makeRawRequest(
729
+ PayUmaInvoice,
730
+ variables,
731
+ payerNodeId,
732
+ );
733
+ if (response.pay_invoice?.payment.outgoing_payment_failure_message) {
734
+ throw new LightsparkException(
735
+ "PaymentError",
736
+ response.pay_invoice?.payment.outgoing_payment_failure_message
737
+ .rich_text_text,
738
+ );
739
+ }
740
+ return (
741
+ response.pay_uma_invoice &&
742
+ OutgoingPaymentFromJson(response.pay_invoice.payment)
743
+ );
744
+ }
745
+
654
746
  /**
655
747
  * Sends a payment directly to a node on the Lightning Network through the public key of the node without an invoice.
656
748
  *
@@ -668,7 +760,7 @@ class LightsparkClient {
668
760
  destinationPublicKey: string,
669
761
  timeoutSecs: number = 60,
670
762
  amountMsats: number,
671
- maximumFeesMsats: number
763
+ maximumFeesMsats: number,
672
764
  ): Promise<OutgoingPayment | undefined> {
673
765
  if (!this.nodeKeyCache.hasKey(payerNodeId)) {
674
766
  throw new LightsparkSigningException("Paying node is not unlocked");
@@ -682,12 +774,13 @@ class LightsparkClient {
682
774
  amount_msats: amountMsats,
683
775
  maximum_fees_msats: maximumFeesMsats,
684
776
  },
685
- payerNodeId
777
+ payerNodeId,
686
778
  );
687
779
  if (response.send_payment?.payment.outgoing_payment_failure_message) {
688
780
  throw new LightsparkException(
689
781
  "PaymentError",
690
- response.send_payment?.payment.outgoing_payment_failure_message.rich_text_text
782
+ response.send_payment?.payment.outgoing_payment_failure_message
783
+ .rich_text_text,
691
784
  );
692
785
  }
693
786
  return (
@@ -705,7 +798,7 @@ class LightsparkClient {
705
798
  public async createNodeWalletAddress(nodeId: string): Promise<string> {
706
799
  const response = await this.requester.makeRawRequest(
707
800
  CreateNodeWalletAddress,
708
- { node_id: nodeId }
801
+ { node_id: nodeId },
709
802
  );
710
803
  return response.create_node_wallet_address.wallet_address;
711
804
  }
@@ -727,7 +820,7 @@ class LightsparkClient {
727
820
  nodeId: string,
728
821
  amountSats: number,
729
822
  bitcoinAddress: string,
730
- mode: WithdrawalMode
823
+ mode: WithdrawalMode,
731
824
  ): Promise<WithdrawalRequest> {
732
825
  const response = await this.requester.makeRawRequest(
733
826
  RequestWithdrawal,
@@ -737,7 +830,7 @@ class LightsparkClient {
737
830
  bitcoin_address: bitcoinAddress,
738
831
  withdrawal_mode: mode,
739
832
  },
740
- nodeId
833
+ nodeId,
741
834
  );
742
835
  return WithdrawalRequestFromJson(response.request_withdrawal.request);
743
836
  }
@@ -753,7 +846,7 @@ class LightsparkClient {
753
846
  */
754
847
  public async fundNode(
755
848
  nodeId: string,
756
- amountSats: number | undefined = undefined
849
+ amountSats: number | undefined = undefined,
757
850
  ): Promise<CurrencyAmount> {
758
851
  const response = await this.requester.makeRawRequest(FundNode, {
759
852
  node_id: nodeId,
@@ -775,7 +868,7 @@ class LightsparkClient {
775
868
  public async createApiToken(
776
869
  name: string,
777
870
  transact: boolean = true,
778
- testMode: boolean = true
871
+ testMode: boolean = true,
779
872
  ): Promise<CreateApiTokenOutput> {
780
873
  let permissions: Permission[];
781
874
  if (transact && testMode) {
@@ -820,7 +913,7 @@ class LightsparkClient {
820
913
  localNodeId: string,
821
914
  amountMsats: number,
822
915
  memo: string | undefined = undefined,
823
- invoiceType: InvoiceType = InvoiceType.STANDARD
916
+ invoiceType: InvoiceType = InvoiceType.STANDARD,
824
917
  ): Promise<string | null> {
825
918
  return await this.executeRawQuery({
826
919
  queryPayload: CreateTestModeInvoice,
@@ -840,7 +933,7 @@ class LightsparkClient {
840
933
  if (!encodedPaymentRequest) {
841
934
  throw new LightsparkException(
842
935
  "CreateTestModeInvoiceError",
843
- "Unable to create test mode invoice"
936
+ "Unable to create test mode invoice",
844
937
  );
845
938
  }
846
939
  return encodedPaymentRequest;
@@ -860,7 +953,7 @@ class LightsparkClient {
860
953
  public async createTestModePayment(
861
954
  localNodeId: string,
862
955
  encodedInvoice: string,
863
- amountMsats: number | undefined = undefined
956
+ amountMsats: number | undefined = undefined,
864
957
  ): Promise<OutgoingPayment | null> {
865
958
  return await this.executeRawQuery({
866
959
  queryPayload: CreateTestModePayment,
@@ -875,7 +968,7 @@ class LightsparkClient {
875
968
  } | null;
876
969
  }) => {
877
970
  return OutgoingPaymentFromJson(
878
- responseJson.create_test_mode_payment?.payment
971
+ responseJson.create_test_mode_payment?.payment,
879
972
  );
880
973
  },
881
974
  });
@@ -895,6 +988,4 @@ class LightsparkClient {
895
988
  }
896
989
  }
897
990
 
898
- const LIGHTSPARK_SDK_ENDPOINT = "graphql/server/2023-04-04";
899
-
900
991
  export default LightsparkClient;