@atomiqlabs/sdk 8.8.3 → 8.9.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 (130) hide show
  1. package/api/index.d.ts +1 -0
  2. package/api/index.js +3 -0
  3. package/dist/ApiList.d.ts +37 -0
  4. package/dist/ApiList.js +30 -0
  5. package/dist/api/ApiEndpoints.d.ts +393 -0
  6. package/dist/api/ApiEndpoints.js +2 -0
  7. package/dist/api/ApiParser.d.ts +10 -0
  8. package/dist/api/ApiParser.js +134 -0
  9. package/dist/api/ApiTypes.d.ts +157 -0
  10. package/dist/api/ApiTypes.js +75 -0
  11. package/dist/api/SerializedAction.d.ts +40 -0
  12. package/dist/api/SerializedAction.js +59 -0
  13. package/dist/api/SwapperApi.d.ts +50 -0
  14. package/dist/api/SwapperApi.js +431 -0
  15. package/dist/api/index.d.ts +5 -0
  16. package/dist/api/index.js +24 -0
  17. package/dist/events/UnifiedSwapEventListener.d.ts +4 -3
  18. package/dist/events/UnifiedSwapEventListener.js +8 -2
  19. package/dist/http/HttpUtils.d.ts +4 -2
  20. package/dist/http/HttpUtils.js +10 -4
  21. package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +2 -1
  22. package/dist/http/paramcoders/client/StreamingFetchPromise.js +3 -2
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +1 -0
  25. package/dist/intermediaries/IntermediaryDiscovery.d.ts +7 -2
  26. package/dist/intermediaries/IntermediaryDiscovery.js +4 -4
  27. package/dist/intermediaries/apis/IntermediaryAPI.d.ts +171 -14
  28. package/dist/intermediaries/apis/IntermediaryAPI.js +174 -28
  29. package/dist/intermediaries/auth/SignedKeyBasedAuth.d.ts +14 -0
  30. package/dist/intermediaries/auth/SignedKeyBasedAuth.js +68 -0
  31. package/dist/storage/IUnifiedStorage.d.ts +45 -3
  32. package/dist/storage/UnifiedSwapStorage.d.ts +8 -2
  33. package/dist/storage/UnifiedSwapStorage.js +46 -8
  34. package/dist/swapper/Swapper.d.ts +36 -3
  35. package/dist/swapper/Swapper.js +54 -18
  36. package/dist/swapper/SwapperUtils.d.ts +18 -2
  37. package/dist/swapper/SwapperUtils.js +39 -1
  38. package/dist/swaps/ISwap.d.ts +70 -9
  39. package/dist/swaps/ISwap.js +28 -6
  40. package/dist/swaps/ISwapWrapper.d.ts +11 -1
  41. package/dist/swaps/ISwapWrapper.js +23 -3
  42. package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +1 -1
  43. package/dist/swaps/escrow_swaps/IEscrowSwap.js +4 -2
  44. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +2 -1
  45. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +2 -2
  46. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +3 -1
  47. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +3 -2
  48. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +47 -31
  49. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +201 -67
  50. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +3 -1
  51. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +6 -6
  52. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +82 -15
  53. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +304 -98
  54. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +3 -1
  55. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +6 -6
  56. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +75 -42
  57. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +424 -87
  58. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +3 -1
  59. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +7 -7
  60. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +54 -11
  61. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +214 -41
  62. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +2 -1
  63. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +7 -8
  64. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +3 -1
  65. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +5 -5
  66. package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +76 -19
  67. package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +290 -51
  68. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +3 -1
  69. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +5 -5
  70. package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +53 -12
  71. package/dist/swaps/trusted/ln/LnForGasSwap.js +163 -49
  72. package/dist/swaps/trusted/ln/LnForGasWrapper.js +1 -2
  73. package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +14 -13
  74. package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +30 -47
  75. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +3 -1
  76. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +4 -4
  77. package/dist/types/SwapExecutionAction.d.ts +141 -34
  78. package/dist/types/SwapExecutionAction.js +104 -0
  79. package/dist/types/SwapExecutionStep.d.ts +144 -0
  80. package/dist/types/SwapExecutionStep.js +87 -0
  81. package/dist/types/TokenAmount.d.ts +6 -0
  82. package/dist/types/TokenAmount.js +26 -1
  83. package/dist/utils/BitcoinUtils.d.ts +2 -0
  84. package/dist/utils/BitcoinUtils.js +34 -1
  85. package/dist/utils/Utils.d.ts +3 -1
  86. package/dist/utils/Utils.js +7 -1
  87. package/package.json +7 -4
  88. package/src/api/ApiEndpoints.ts +427 -0
  89. package/src/api/ApiParser.ts +138 -0
  90. package/src/api/ApiTypes.ts +229 -0
  91. package/src/api/SerializedAction.ts +97 -0
  92. package/src/api/SwapperApi.ts +545 -0
  93. package/src/api/index.ts +5 -0
  94. package/src/events/UnifiedSwapEventListener.ts +11 -3
  95. package/src/http/HttpUtils.ts +10 -4
  96. package/src/http/paramcoders/client/StreamingFetchPromise.ts +4 -2
  97. package/src/index.ts +1 -0
  98. package/src/intermediaries/IntermediaryDiscovery.ts +9 -2
  99. package/src/intermediaries/apis/IntermediaryAPI.ts +314 -30
  100. package/src/intermediaries/auth/SignedKeyBasedAuth.ts +69 -0
  101. package/src/storage/IUnifiedStorage.ts +45 -4
  102. package/src/storage/UnifiedSwapStorage.ts +42 -8
  103. package/src/swapper/Swapper.ts +87 -18
  104. package/src/swapper/SwapperUtils.ts +42 -2
  105. package/src/swaps/ISwap.ts +88 -16
  106. package/src/swaps/ISwapWrapper.ts +28 -3
  107. package/src/swaps/escrow_swaps/IEscrowSwap.ts +5 -3
  108. package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +3 -1
  109. package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +4 -1
  110. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +264 -67
  111. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +6 -4
  112. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +390 -89
  113. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +6 -4
  114. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +548 -94
  115. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +7 -5
  116. package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +276 -45
  117. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +7 -6
  118. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +5 -3
  119. package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +393 -57
  120. package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +5 -3
  121. package/src/swaps/trusted/ln/LnForGasSwap.ts +211 -47
  122. package/src/swaps/trusted/ln/LnForGasWrapper.ts +1 -2
  123. package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +32 -51
  124. package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +5 -3
  125. package/src/types/SwapExecutionAction.ts +266 -43
  126. package/src/types/SwapExecutionStep.ts +224 -0
  127. package/src/types/TokenAmount.ts +36 -2
  128. package/src/utils/BitcoinUtils.ts +32 -0
  129. package/src/utils/Utils.ts +10 -1
  130. package/src/intermediaries/apis/TrustedIntermediaryAPI.ts +0 -258
@@ -192,8 +192,14 @@ export class IntermediaryDiscovery extends EventEmitter {
192
192
  */
193
193
  private overrideNodeUrls?: string[];
194
194
 
195
+ /**
196
+ * @private
197
+ */
198
+ private lpApi: IntermediaryAPI;
199
+
195
200
  constructor(
196
201
  swapContracts: {[chainIdentifier: string]: {[contractVersion: string]: {swapContract: SwapContract, spvVaultContract: SpvVaultContract}}},
202
+ lpApi: IntermediaryAPI,
197
203
  registryUrl: string = REGISTRY_URL,
198
204
  nodeUrls?: string[],
199
205
  httpRequestTimeout?: number,
@@ -205,6 +211,7 @@ export class IntermediaryDiscovery extends EventEmitter {
205
211
  this.overrideNodeUrls = nodeUrls;
206
212
  this.httpRequestTimeout = httpRequestTimeout;
207
213
  this.maxWaitForOthersTimeout = maxWaitForOthersTimeout;
214
+ this.lpApi = lpApi;
208
215
  }
209
216
 
210
217
  /**
@@ -242,7 +249,7 @@ export class IntermediaryDiscovery extends EventEmitter {
242
249
  info: InfoHandlerResponseEnvelope
243
250
  }> {
244
251
  const response = await tryWithRetries(
245
- () => IntermediaryAPI.getIntermediaryInfo(url, this.httpRequestTimeout, abortSignal),
252
+ () => this.lpApi.getIntermediaryInfo(url, this.httpRequestTimeout, abortSignal),
246
253
  {maxRetries: 3, delay: 100, exponential: true},
247
254
  undefined,
248
255
  abortSignal,
@@ -489,7 +496,7 @@ export class IntermediaryDiscovery extends EventEmitter {
489
496
  /**
490
497
  * Returns swap candidates for a specific swap type & token address
491
498
  *
492
- * @remark Also filters the LPs based on supported swap versions
499
+ * @remarks Also filters the LPs based on supported swap versions
493
500
  *
494
501
  * @param chainIdentifier Chain identifier of the smart chain
495
502
  * @param swapType Swap protocol type
@@ -1,10 +1,10 @@
1
1
  import {RequestError} from "../../errors/RequestError";
2
2
  import {
3
- FieldTypeEnum,
4
- RequestSchemaResult,
3
+ FieldTypeEnum, RequestSchema,
4
+ RequestSchemaResult, RequestSchemaResultPromise,
5
5
  verifySchema
6
6
  } from "../../http/paramcoders/SchemaVerifier";
7
- import {streamingFetchPromise} from "../../http/paramcoders/client/StreamingFetchPromise";
7
+ import {RequestBody, streamingFetchPromise} from "../../http/paramcoders/client/StreamingFetchPromise";
8
8
  import {extendAbortController, randomBytes} from "../../utils/Utils";
9
9
  import {httpGet, httpPost} from "../../http/HttpUtils";
10
10
  import {tryWithRetries} from "../../utils/RetryUtils";
@@ -329,8 +329,148 @@ export type SpvFromBTCInit = {
329
329
  psbtHex: string
330
330
  }
331
331
 
332
+ /////////////////////////
333
+ ///// Trusted from BTCLN
334
+
335
+ export enum TrustedInvoiceStatusResponseCodes {
336
+ EXPIRED=10001,
337
+ PAID=10000,
338
+ AWAIT_PAYMENT=10010,
339
+ PENDING=10011,
340
+ TX_SENT=10012
341
+ }
342
+
343
+ export type TrustedInvoiceStatusResponse = {
344
+ code: TrustedInvoiceStatusResponseCodes.TX_SENT | TrustedInvoiceStatusResponseCodes.PAID,
345
+ msg: string,
346
+ data: {
347
+ txId: string
348
+ }
349
+ } | {
350
+ code: Exclude<TrustedInvoiceStatusResponseCodes, TrustedInvoiceStatusResponseCodes.TX_SENT | TrustedInvoiceStatusResponseCodes.PAID>,
351
+ msg: string
352
+ };
353
+
354
+ export type TrustedFromBTCLNInit = {
355
+ address: string,
356
+ amount: bigint,
357
+ token: string
358
+ };
359
+
360
+ const TrustedFromBTCLNResponseSchema = {
361
+ pr: FieldTypeEnum.String,
362
+ swapFee: FieldTypeEnum.BigInt,
363
+ swapFeeSats: FieldTypeEnum.BigInt,
364
+ total: FieldTypeEnum.BigInt
365
+ } as const;
366
+
367
+ export type TrustedFromBTCLNResponseType = RequestSchemaResult<typeof TrustedFromBTCLNResponseSchema>;
368
+
369
+ /////////////////////////
370
+ ///// Trusted from BTC
371
+
372
+ export enum TrustedAddressStatusResponseCodes {
373
+ EXPIRED=10001,
374
+ PAID=10000,
375
+ AWAIT_PAYMENT=10010,
376
+ AWAIT_CONFIRMATION=10011,
377
+ PENDING=10013,
378
+ TX_SENT=10012,
379
+ REFUNDED=10014,
380
+ DOUBLE_SPENT=10015,
381
+ REFUNDABLE=10016
382
+ }
383
+
384
+ export type TrustedAddressStatusResponse = {
385
+ code: TrustedAddressStatusResponseCodes.TX_SENT | TrustedAddressStatusResponseCodes.PAID,
386
+ msg: string,
387
+ data: {
388
+ adjustedAmount: string,
389
+ adjustedTotal: string,
390
+ adjustedFee?: string,
391
+ adjustedFeeSats?: string,
392
+ txId: string,
393
+ scTxId: string
394
+ }
395
+ } | {
396
+ code: TrustedAddressStatusResponseCodes.AWAIT_CONFIRMATION | TrustedAddressStatusResponseCodes.PENDING,
397
+ msg: string,
398
+ data: {
399
+ adjustedAmount: string,
400
+ adjustedTotal: string,
401
+ adjustedFee?: string,
402
+ adjustedFeeSats?: string,
403
+ txId: string
404
+ }
405
+ } | {
406
+ code: TrustedAddressStatusResponseCodes.REFUNDABLE,
407
+ msg: string,
408
+ data: {
409
+ adjustedAmount: string
410
+ }
411
+ } | {
412
+ code: TrustedAddressStatusResponseCodes.REFUNDED | TrustedAddressStatusResponseCodes.DOUBLE_SPENT,
413
+ msg: string,
414
+ data: {
415
+ txId: string
416
+ }
417
+ } | {
418
+ code: TrustedAddressStatusResponseCodes.AWAIT_PAYMENT | TrustedAddressStatusResponseCodes.EXPIRED,
419
+ msg: string
420
+ };
421
+
422
+ export type TrustedFromBTCInit = {
423
+ address: string,
424
+ amount: bigint,
425
+ token: string,
426
+ refundAddress?: string
427
+ };
428
+
429
+ const TrustedFromBTCResponseSchema = {
430
+ paymentHash: FieldTypeEnum.String,
431
+ sequence: FieldTypeEnum.BigInt,
432
+ btcAddress: FieldTypeEnum.String,
433
+ amountSats: FieldTypeEnum.BigInt,
434
+ swapFeeSats: FieldTypeEnum.BigInt,
435
+ swapFee: FieldTypeEnum.BigInt,
436
+ total: FieldTypeEnum.BigInt,
437
+ intermediaryKey: FieldTypeEnum.String,
438
+ recommendedFee: FieldTypeEnum.Number,
439
+ expiresAt: FieldTypeEnum.Number
440
+ } as const;
441
+
442
+ export type TrustedFromBTCResponseType = RequestSchemaResult<typeof TrustedFromBTCResponseSchema>;
443
+
332
444
  export class IntermediaryAPI {
333
445
 
446
+ requestHeaders?: (type: "GET" | "POST", url: string, body?: any) => Record<string, string>;
447
+
448
+ constructor(requestHeaders?: (type: "GET" | "POST", url: string, body?: any) => Record<string, string>) {
449
+ this.requestHeaders = requestHeaders;
450
+ }
451
+
452
+ httpGet<T>(url: string, timeout?: number, abortSignal?: AbortSignal, allowNon200: boolean = false): Promise<T> {
453
+ const headers = this.requestHeaders==null ? {} : this.requestHeaders("GET", url);
454
+ return httpGet(url, timeout, abortSignal, allowNon200, headers);
455
+ }
456
+
457
+ httpPost<T>(url: string, body: any, timeout?: number, abortSignal?: AbortSignal): Promise<T> {
458
+ const headers = this.requestHeaders==null ? {} : this.requestHeaders("POST", url, body);
459
+ return httpPost(url, body, timeout, abortSignal, headers);
460
+ }
461
+
462
+ streamingFetchPromise<T extends RequestSchema>(
463
+ url: string,
464
+ body: RequestBody,
465
+ schema: T,
466
+ timeout?: number,
467
+ signal?: AbortSignal,
468
+ streamRequest?: boolean
469
+ ): Promise<RequestSchemaResultPromise<T>> {
470
+ const headers = this.requestHeaders==null ? {} : this.requestHeaders("POST", url);
471
+ return streamingFetchPromise(url, body, schema, timeout, signal, streamRequest, headers);
472
+ }
473
+
334
474
  /**
335
475
  * Returns the information about a specific intermediary
336
476
  *
@@ -341,7 +481,7 @@ export class IntermediaryAPI {
341
481
  * @throws {RequestError} If non-200 http response code is returned
342
482
  * @throws {Error} If the supplied nonce doesn't match the response
343
483
  */
344
- static async getIntermediaryInfo(
484
+ async getIntermediaryInfo(
345
485
  baseUrl: string,
346
486
  timeout?: number,
347
487
  abortSignal?: AbortSignal
@@ -353,8 +493,8 @@ export class IntermediaryAPI {
353
493
  //We don't know whether the node supports only POST or also has GET info support enabled
354
494
  // here we try both, and abort when the first one returns (which should be GET)
355
495
  const response = await Promise.any([
356
- httpGet<InfoHandlerResponse>(baseUrl+"/info?nonce="+nonce, timeout, abortController.signal),
357
- httpPost<InfoHandlerResponse>(baseUrl+"/info", {
496
+ this.httpGet<InfoHandlerResponse>(baseUrl+"/info?nonce="+nonce, timeout, abortController.signal),
497
+ this.httpPost<InfoHandlerResponse>(baseUrl+"/info", {
358
498
  nonce,
359
499
  }, timeout, abortController.signal)
360
500
  ]);
@@ -377,14 +517,14 @@ export class IntermediaryAPI {
377
517
  *
378
518
  * @throws {RequestError} If non-200 http response code is returned
379
519
  */
380
- static async getRefundAuthorization(
520
+ async getRefundAuthorization(
381
521
  url: string,
382
522
  paymentHash: string,
383
523
  sequence: bigint,
384
524
  timeout?: number,
385
525
  abortSignal?: AbortSignal
386
526
  ): Promise<RefundAuthorizationResponse> {
387
- return tryWithRetries(() => httpGet<RefundAuthorizationResponse>(
527
+ return tryWithRetries(() => this.httpGet<RefundAuthorizationResponse>(
388
528
  url + "/getRefundAuthorization"+
389
529
  "?paymentHash=" + encodeURIComponent(paymentHash) +
390
530
  "&sequence=" + encodeURIComponent(sequence.toString(10)),
@@ -403,13 +543,13 @@ export class IntermediaryAPI {
403
543
  *
404
544
  * @throws {RequestError} If non-200 http response code is returned
405
545
  */
406
- static async getPaymentAuthorization(
546
+ async getPaymentAuthorization(
407
547
  url: string,
408
548
  paymentHash: string,
409
549
  timeout?: number,
410
550
  abortSignal?: AbortSignal
411
551
  ): Promise<PaymentAuthorizationResponse> {
412
- return tryWithRetries(() => httpGet<PaymentAuthorizationResponse>(
552
+ return tryWithRetries(() => this.httpGet<PaymentAuthorizationResponse>(
413
553
  url+"/getInvoicePaymentAuth"+
414
554
  "?paymentHash="+encodeURIComponent(paymentHash),
415
555
  timeout,
@@ -427,13 +567,13 @@ export class IntermediaryAPI {
427
567
  *
428
568
  * @throws {RequestError} If non-200 http response code is returned
429
569
  */
430
- static async getInvoiceStatus(
570
+ async getInvoiceStatus(
431
571
  url: string,
432
572
  paymentHash: string,
433
573
  timeout?: number,
434
574
  abortSignal?: AbortSignal
435
575
  ): Promise<InvoiceStatusResponse> {
436
- return tryWithRetries(() => httpGet<InvoiceStatusResponse>(
576
+ return tryWithRetries(() => this.httpGet<InvoiceStatusResponse>(
437
577
  url+"/getInvoiceStatus"+
438
578
  "?paymentHash="+encodeURIComponent(paymentHash),
439
579
  timeout,
@@ -453,7 +593,7 @@ export class IntermediaryAPI {
453
593
  *
454
594
  * @throws {RequestError} If non-200 http response code is returned
455
595
  */
456
- static initToBTC(
596
+ initToBTC(
457
597
  chainIdentifier: string,
458
598
  baseUrl: string,
459
599
  init: ToBTCInit,
@@ -464,7 +604,7 @@ export class IntermediaryAPI {
464
604
  signDataPrefetch: Promise<any>,
465
605
  response: Promise<ToBTCResponseType>
466
606
  } {
467
- const responseBodyPromise = streamingFetchPromise(baseUrl+"/tobtc/payInvoice?chain="+encodeURIComponent(chainIdentifier), {
607
+ const responseBodyPromise = this.streamingFetchPromise(baseUrl+"/tobtc/payInvoice?chain="+encodeURIComponent(chainIdentifier), {
468
608
  ...init.additionalParams,
469
609
  address: init.btcAddress,
470
610
  amount: init.amount.toString(10),
@@ -512,7 +652,7 @@ export class IntermediaryAPI {
512
652
  *
513
653
  * @throws {RequestError} If non-200 http response code is returned
514
654
  */
515
- static initFromBTC(
655
+ initFromBTC(
516
656
  chainIdentifier: string,
517
657
  baseUrl: string,
518
658
  depositToken: string,
@@ -524,7 +664,7 @@ export class IntermediaryAPI {
524
664
  signDataPrefetch: Promise<any>,
525
665
  response: Promise<FromBTCResponseType>
526
666
  } {
527
- const responseBodyPromise = streamingFetchPromise(
667
+ const responseBodyPromise = this.streamingFetchPromise(
528
668
  baseUrl+"/frombtc/getAddress?chain="+encodeURIComponent(chainIdentifier)+"&depositToken="+encodeURIComponent(depositToken),
529
669
  {
530
670
  ...init.additionalParams,
@@ -585,7 +725,7 @@ export class IntermediaryAPI {
585
725
  *
586
726
  * @throws {RequestError} If non-200 http response code is returned
587
727
  */
588
- static initFromBTCLN(
728
+ initFromBTCLN(
589
729
  chainIdentifier: string,
590
730
  baseUrl: string,
591
731
  depositToken: string,
@@ -597,7 +737,7 @@ export class IntermediaryAPI {
597
737
  lnPublicKey: Promise<string | null>,
598
738
  response: Promise<FromBTCLNResponseType>
599
739
  } {
600
- const responseBodyPromise = streamingFetchPromise(
740
+ const responseBodyPromise = this.streamingFetchPromise(
601
741
  baseUrl+"/frombtcln/createInvoice?chain="+encodeURIComponent(chainIdentifier)+"&depositToken="+encodeURIComponent(depositToken),
602
742
  {
603
743
  ...init.additionalParams,
@@ -648,7 +788,7 @@ export class IntermediaryAPI {
648
788
  *
649
789
  * @throws {RequestError} If non-200 http response code is returned
650
790
  */
651
- static initFromBTCLNAuto(
791
+ initFromBTCLNAuto(
652
792
  chainIdentifier: string,
653
793
  baseUrl: string,
654
794
  init: FromBTCLNAutoInit,
@@ -659,7 +799,7 @@ export class IntermediaryAPI {
659
799
  lnPublicKey: Promise<string | null>,
660
800
  response: Promise<FromBTCLNAutoResponseType>
661
801
  } {
662
- const responseBodyPromise = streamingFetchPromise(
802
+ const responseBodyPromise = this.streamingFetchPromise(
663
803
  baseUrl+"/frombtcln_auto/createInvoice?chain="+encodeURIComponent(chainIdentifier),
664
804
  {
665
805
  ...init.additionalParams,
@@ -712,7 +852,7 @@ export class IntermediaryAPI {
712
852
  *
713
853
  * @throws {RequestError} If non-200 http response code is returned
714
854
  */
715
- static initToBTCLN(
855
+ initToBTCLN(
716
856
  chainIdentifier: string,
717
857
  baseUrl: string,
718
858
  init: ToBTCLNInit,
@@ -723,7 +863,7 @@ export class IntermediaryAPI {
723
863
  signDataPrefetch: Promise<any>,
724
864
  response: Promise<ToBTCLNResponseType>
725
865
  } {
726
- const responseBodyPromise = streamingFetchPromise(baseUrl+"/tobtcln/payInvoice?chain="+encodeURIComponent(chainIdentifier), {
866
+ const responseBodyPromise = this.streamingFetchPromise(baseUrl+"/tobtcln/payInvoice?chain="+encodeURIComponent(chainIdentifier), {
727
867
  exactIn: false,
728
868
  ...init.additionalParams,
729
869
  pr: init.pr,
@@ -768,14 +908,14 @@ export class IntermediaryAPI {
768
908
  *
769
909
  * @throws {RequestError} If non-200 http response code is returned
770
910
  */
771
- static async initToBTCLNExactIn(
911
+ async initToBTCLNExactIn(
772
912
  baseUrl: string,
773
913
  init: ToBTCLNInitExactIn,
774
914
  timeout?: number,
775
915
  abortSignal?: AbortSignal,
776
916
  streamRequest?: boolean
777
917
  ): Promise<ToBTCLNResponseType> {
778
- const responseBody = await streamingFetchPromise(baseUrl+"/tobtcln/payInvoiceExactIn", {
918
+ const responseBody = await this.streamingFetchPromise(baseUrl+"/tobtcln/payInvoiceExactIn", {
779
919
  ...init.additionalParams,
780
920
  pr: init.pr,
781
921
  reqId: init.reqId,
@@ -810,7 +950,7 @@ export class IntermediaryAPI {
810
950
  *
811
951
  * @throws {RequestError} If non-200 http response code is returned
812
952
  */
813
- static prepareToBTCLNExactIn(
953
+ prepareToBTCLNExactIn(
814
954
  chainIdentifier: string,
815
955
  baseUrl: string,
816
956
  init: ToBTCLNPrepareExactIn,
@@ -821,7 +961,7 @@ export class IntermediaryAPI {
821
961
  signDataPrefetch: Promise<any>,
822
962
  response: Promise<ToBTCLNPrepareExactInResponseType>
823
963
  } {
824
- const responseBodyPromise = streamingFetchPromise(baseUrl+"/tobtcln/payInvoice?chain="+encodeURIComponent(chainIdentifier), {
964
+ const responseBodyPromise = this.streamingFetchPromise(baseUrl+"/tobtcln/payInvoice?chain="+encodeURIComponent(chainIdentifier), {
825
965
  exactIn: true,
826
966
  ...init.additionalParams,
827
967
  pr: init.pr,
@@ -866,7 +1006,7 @@ export class IntermediaryAPI {
866
1006
  *
867
1007
  * @throws {RequestError} If non-200 http response code is returned
868
1008
  */
869
- static prepareSpvFromBTC(
1009
+ prepareSpvFromBTC(
870
1010
  chainIdentifier: string,
871
1011
  baseUrl: string,
872
1012
  init: SpvFromBTCPrepare,
@@ -884,7 +1024,7 @@ export class IntermediaryAPI {
884
1024
  const amount = await init.amount;
885
1025
  return amount.toString(10);
886
1026
  })();
887
- const responseBodyPromise = streamingFetchPromise(baseUrl+"/frombtc_spv/getQuote?chain="+encodeURIComponent(chainIdentifier), {
1027
+ const responseBodyPromise = this.streamingFetchPromise(baseUrl+"/frombtc_spv/getQuote?chain="+encodeURIComponent(chainIdentifier), {
888
1028
  exactOut: init.exactOut,
889
1029
  ...init.additionalParams,
890
1030
  address: init.address,
@@ -929,7 +1069,7 @@ export class IntermediaryAPI {
929
1069
  *
930
1070
  * @throws {RequestError} If non-200 http response code is returned
931
1071
  */
932
- static initSpvFromBTC(
1072
+ initSpvFromBTC(
933
1073
  chainIdentifier: string,
934
1074
  url: string,
935
1075
  init: SpvFromBTCInit,
@@ -937,7 +1077,7 @@ export class IntermediaryAPI {
937
1077
  abortSignal?: AbortSignal,
938
1078
  streamRequest?: boolean
939
1079
  ): Promise<SpvFromBTCInitResponseType> {
940
- const responseBodyPromise = streamingFetchPromise(url+"/postQuote?chain="+encodeURIComponent(chainIdentifier), {
1080
+ const responseBodyPromise = this.streamingFetchPromise(url+"/postQuote?chain="+encodeURIComponent(chainIdentifier), {
941
1081
  quoteId: init.quoteId,
942
1082
  psbtHex: init.psbtHex
943
1083
  }, {
@@ -960,4 +1100,148 @@ export class IntermediaryAPI {
960
1100
  });
961
1101
  }
962
1102
 
1103
+
1104
+ /**
1105
+ * Fetches the invoice status from the intermediary node
1106
+ *
1107
+ * @param url Url of the trusted intermediary
1108
+ * @param paymentHash Payment hash of the lightning invoice
1109
+ * @param timeout Timeout in milliseconds
1110
+ * @param abortSignal
1111
+ * @throws {RequestError} if non-200 http response is returned
1112
+ */
1113
+ async getTrustedInvoiceStatus(
1114
+ url: string,
1115
+ paymentHash: string,
1116
+ timeout?: number,
1117
+ abortSignal?: AbortSignal
1118
+ ): Promise<TrustedInvoiceStatusResponse> {
1119
+ return tryWithRetries(() => this.httpGet<TrustedInvoiceStatusResponse>(
1120
+ url+"/getInvoiceStatus?paymentHash="+encodeURIComponent(paymentHash),
1121
+ timeout, abortSignal
1122
+ ), undefined, RequestError, abortSignal);
1123
+ }
1124
+
1125
+ /**
1126
+ * Initiate a trusted swap from BTCLN to SC native currency, retries!
1127
+ *
1128
+ * @param chainIdentifier
1129
+ * @param baseUrl Base url of the trusted swap intermediary
1130
+ * @param init Initialization parameters
1131
+ * @param timeout Timeout in milliseconds for the request
1132
+ * @param abortSignal
1133
+ * @throws {RequestError} If the response is non-200
1134
+ */
1135
+ async initTrustedFromBTCLN(
1136
+ chainIdentifier: string,
1137
+ baseUrl: string,
1138
+ init: TrustedFromBTCLNInit,
1139
+ timeout?: number,
1140
+ abortSignal?: AbortSignal
1141
+ ): Promise<TrustedFromBTCLNResponseType> {
1142
+ const resp = await tryWithRetries(
1143
+ () => this.httpGet<{code: number, msg: string, data?: any}>(
1144
+ baseUrl+"/lnforgas/createInvoice" +
1145
+ "?address="+encodeURIComponent(init.address) +
1146
+ "&amount="+encodeURIComponent(init.amount.toString(10))+
1147
+ "&chain="+encodeURIComponent(chainIdentifier)+
1148
+ "&token="+encodeURIComponent(init.token),
1149
+ timeout,
1150
+ abortSignal
1151
+ ), undefined, RequestError, abortSignal
1152
+ );
1153
+
1154
+ if(resp.code!==10000) throw RequestError.parse(JSON.stringify(resp), 400);
1155
+ const res = verifySchema(resp.data, TrustedFromBTCLNResponseSchema);
1156
+ if(res==null) throw new Error("Invalid response returned from LP");
1157
+ return res;
1158
+ }
1159
+
1160
+ /**
1161
+ * Fetches the address status from the intermediary node
1162
+ *
1163
+ * @param url Url of the trusted intermediary
1164
+ * @param paymentHash Payment hash of the swap
1165
+ * @param sequence Sequence number of the swap
1166
+ * @param timeout Timeout in milliseconds
1167
+ * @param abortSignal
1168
+ * @throws {RequestError} if non-200 http response is returned
1169
+ */
1170
+ async getTrustedAddressStatus(
1171
+ url: string,
1172
+ paymentHash: string,
1173
+ sequence: bigint,
1174
+ timeout?: number,
1175
+ abortSignal?: AbortSignal
1176
+ ): Promise<TrustedAddressStatusResponse> {
1177
+ return tryWithRetries(() => this.httpGet<TrustedAddressStatusResponse>(
1178
+ url+"/getAddressStatus?paymentHash="+encodeURIComponent(paymentHash)+"&sequence="+encodeURIComponent(sequence.toString(10)),
1179
+ timeout, abortSignal
1180
+ ), undefined, RequestError, abortSignal);
1181
+ }
1182
+
1183
+ /**
1184
+ * Sets the refund address for an on-chain gas swap
1185
+ *
1186
+ * @param url Url of the trusted intermediary
1187
+ * @param paymentHash Payment hash of the swap
1188
+ * @param sequence Sequence number of the swap
1189
+ * @param refundAddress Refund address to set for the swap
1190
+ * @param timeout Timeout in milliseconds
1191
+ * @param abortSignal
1192
+ * @throws {RequestError} if non-200 http response is returned
1193
+ */
1194
+ async setTrustedRefundAddress(
1195
+ url: string,
1196
+ paymentHash: string,
1197
+ sequence: bigint,
1198
+ refundAddress: string,
1199
+ timeout?: number,
1200
+ abortSignal?: AbortSignal
1201
+ ): Promise<void> {
1202
+ return tryWithRetries(() => this.httpGet<void>(
1203
+ url+"/setRefundAddress" +
1204
+ "?paymentHash="+encodeURIComponent(paymentHash)+
1205
+ "&sequence="+encodeURIComponent(sequence.toString(10))+
1206
+ "&refundAddress="+encodeURIComponent(refundAddress),
1207
+ timeout, abortSignal
1208
+ ), undefined, RequestError, abortSignal);
1209
+ }
1210
+
1211
+ /**
1212
+ * Initiate a trusted swap from BTC to SC native currency, retries!
1213
+ *
1214
+ * @param chainIdentifier
1215
+ * @param baseUrl Base url of the trusted swap intermediary
1216
+ * @param init Initialization parameters
1217
+ * @param timeout Timeout in milliseconds for the request
1218
+ * @param abortSignal
1219
+ * @throws {RequestError} If the response is non-200
1220
+ */
1221
+ async initTrustedFromBTC(
1222
+ chainIdentifier: string,
1223
+ baseUrl: string,
1224
+ init: TrustedFromBTCInit,
1225
+ timeout?: number,
1226
+ abortSignal?: AbortSignal
1227
+ ): Promise<TrustedFromBTCResponseType> {
1228
+ const resp = await tryWithRetries(
1229
+ () => this.httpGet<{code: number, msg: string, data?: any}>(
1230
+ baseUrl+"/frombtc_trusted/getAddress?chain="+encodeURIComponent(chainIdentifier)+
1231
+ "&address="+encodeURIComponent(init.address)+
1232
+ "&amount="+encodeURIComponent(init.amount.toString(10))+
1233
+ (init.refundAddress==null ? "" : "&refundAddress="+encodeURIComponent(init.refundAddress))+
1234
+ "&exactIn=true"+
1235
+ "&token="+encodeURIComponent(init.token),
1236
+ timeout,
1237
+ abortSignal
1238
+ ), undefined, RequestError, abortSignal
1239
+ );
1240
+
1241
+ if(resp.code!==10000) throw RequestError.parse(JSON.stringify(resp), 400);
1242
+ const res = verifySchema(resp.data, TrustedFromBTCResponseSchema);
1243
+ if(res==null) throw new Error("Invalid response returned from LP");
1244
+ return res;
1245
+ }
1246
+
963
1247
  }
@@ -0,0 +1,69 @@
1
+ import {secp256k1, schnorr} from "@noble/curves/secp256k1";
2
+ import {randomBytes} from "../../utils/Utils";
3
+
4
+
5
+ function parsePrivateKey(value: string, name: string) {
6
+ if(!/^[0-9a-fA-F]{64}$/.test(value)) throw new Error(`${name} must be a 32-byte hex private key`);
7
+ const bytes = Buffer.from(value, "hex");
8
+ if(!secp256k1.utils.isValidPrivateKey(bytes)) throw new Error(`${name} is not a valid secp256k1 private key`);
9
+ return bytes;
10
+ }
11
+
12
+ function parsePublicKey(value: string, name: string) {
13
+ if(!/^[0-9a-fA-F]{64}$/.test(value)) throw new Error(`${name} must be an X-only 32-byte hex public key`);
14
+ if(!secp256k1.utils.isValidPublicKey(Buffer.from("02"+value, "hex"), true)) throw new Error(`${name} is not a valid X-only 32-byte secp256k1 public key`);
15
+ return Buffer.from(value, "hex");
16
+ }
17
+
18
+ function parseSignature(value: string, name: string) {
19
+ if(!/^[0-9a-fA-F]{128}$/.test(value)) throw new Error(`${name} must be a valid 64-byte hex schnorr signature`);
20
+ return Buffer.from(value, "hex");
21
+ }
22
+
23
+ const CERTIFICATE_LENGTH = 64+128+64;
24
+
25
+ /**
26
+ * Adds a `x-atomiq-auth` header with the following binary format, that is hex-encoded:
27
+ * - 4 bytes - timestamp (timestamp when the request was sent)
28
+ * - 32 bytes - random bytes (entropy, to be signed)
29
+ *
30
+ * - 32 bytes - key of the signing authority
31
+ * - 64 bytes - schnorr signature signing the request signing key by the signing authority
32
+ *
33
+ * - 32 bytes - request signing key (signed by the signing authority)
34
+ * - 64 bytes - schnorr signature of the timestamp and random bytes
35
+ *
36
+ * Uses secp256k1 curve and schnorr signatures
37
+ */
38
+ export function getSignedKeyBasedAuthHandler(certificate: string, privateKey: string): (type: "GET" | "POST", url: string, body?: any) => Record<string, string> {
39
+ const _privateKey = parsePrivateKey(privateKey, "Private key");
40
+
41
+ if(certificate.length!==CERTIFICATE_LENGTH) throw new Error(`Certificate has invalid length, expected ${CERTIFICATE_LENGTH}!`);
42
+
43
+ const authorityPublicKey = parsePublicKey(certificate.substring(0, 64), "Certificate: Authority Public key");
44
+ const authoritySignature = parseSignature(certificate.substring(64, 64+128), "Certificate: Authority Signature");
45
+ const signingPublicKey = parsePublicKey(certificate.substring(64+128), "Certificate: Signing Public key");
46
+
47
+ if(!schnorr.verify(authoritySignature, signingPublicKey, authorityPublicKey)) throw new Error("Invalid certificate, authority signature is not valid!");
48
+ if(!signingPublicKey.equals(schnorr.getPublicKey(privateKey))) throw new Error("Passed private key doesn't match the certificate!");
49
+
50
+ const _certificate = Buffer.from(certificate, "hex");
51
+
52
+ return () => {
53
+ const timestamp = Math.floor(Date.now()/1000);
54
+ const timestampBuffer = Buffer.alloc(4);
55
+ timestampBuffer.writeUInt32BE(timestamp);
56
+ const requestUid = randomBytes(32);
57
+
58
+ const toSign = Buffer.concat([timestampBuffer, requestUid]);
59
+ const signature = schnorr.sign(toSign, _privateKey);
60
+
61
+ return {
62
+ "x-atomiq-auth": Buffer.concat([
63
+ toSign,
64
+ _certificate,
65
+ signature
66
+ ]).toString("hex")
67
+ }
68
+ };
69
+ }