@atomiqlabs/sdk 8.7.7 → 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 (152) 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/bitcoin/coinselect2/accumulative.d.ts +1 -0
  18. package/dist/bitcoin/coinselect2/accumulative.js +1 -1
  19. package/dist/bitcoin/coinselect2/blackjack.d.ts +1 -0
  20. package/dist/bitcoin/coinselect2/blackjack.js +1 -1
  21. package/dist/bitcoin/coinselect2/index.d.ts +3 -2
  22. package/dist/bitcoin/coinselect2/index.js +2 -2
  23. package/dist/bitcoin/coinselect2/utils.d.ts +7 -2
  24. package/dist/bitcoin/coinselect2/utils.js +45 -10
  25. package/dist/bitcoin/wallet/BitcoinWallet.d.ts +8 -25
  26. package/dist/bitcoin/wallet/BitcoinWallet.js +31 -18
  27. package/dist/bitcoin/wallet/IBitcoinWallet.d.ts +40 -2
  28. package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +7 -2
  29. package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +10 -4
  30. package/dist/events/UnifiedSwapEventListener.d.ts +4 -3
  31. package/dist/events/UnifiedSwapEventListener.js +8 -2
  32. package/dist/http/HttpUtils.d.ts +4 -2
  33. package/dist/http/HttpUtils.js +10 -4
  34. package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +2 -1
  35. package/dist/http/paramcoders/client/StreamingFetchPromise.js +3 -2
  36. package/dist/index.d.ts +1 -0
  37. package/dist/index.js +1 -0
  38. package/dist/intermediaries/IntermediaryDiscovery.d.ts +7 -2
  39. package/dist/intermediaries/IntermediaryDiscovery.js +4 -4
  40. package/dist/intermediaries/apis/IntermediaryAPI.d.ts +182 -15
  41. package/dist/intermediaries/apis/IntermediaryAPI.js +192 -31
  42. package/dist/intermediaries/auth/SignedKeyBasedAuth.d.ts +14 -0
  43. package/dist/intermediaries/auth/SignedKeyBasedAuth.js +68 -0
  44. package/dist/storage/IUnifiedStorage.d.ts +45 -3
  45. package/dist/storage/UnifiedSwapStorage.d.ts +8 -2
  46. package/dist/storage/UnifiedSwapStorage.js +46 -8
  47. package/dist/swapper/Swapper.d.ts +77 -4
  48. package/dist/swapper/Swapper.js +117 -25
  49. package/dist/swapper/SwapperUtils.d.ts +18 -2
  50. package/dist/swapper/SwapperUtils.js +39 -1
  51. package/dist/swaps/ISwap.d.ts +70 -9
  52. package/dist/swaps/ISwap.js +28 -6
  53. package/dist/swaps/ISwapWrapper.d.ts +11 -1
  54. package/dist/swaps/ISwapWrapper.js +23 -3
  55. package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +1 -1
  56. package/dist/swaps/escrow_swaps/IEscrowSwap.js +4 -2
  57. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +2 -1
  58. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +2 -2
  59. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +3 -1
  60. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +3 -2
  61. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +47 -31
  62. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +201 -67
  63. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +3 -1
  64. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +6 -6
  65. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +82 -15
  66. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +304 -98
  67. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +3 -1
  68. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +6 -6
  69. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +75 -42
  70. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +424 -87
  71. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +3 -1
  72. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +7 -7
  73. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +54 -11
  74. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +214 -41
  75. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +2 -1
  76. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +7 -8
  77. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +3 -1
  78. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +5 -5
  79. package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +85 -22
  80. package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +299 -56
  81. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +41 -7
  82. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +183 -58
  83. package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +53 -12
  84. package/dist/swaps/trusted/ln/LnForGasSwap.js +163 -49
  85. package/dist/swaps/trusted/ln/LnForGasWrapper.js +1 -2
  86. package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +14 -13
  87. package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +30 -47
  88. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +3 -1
  89. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +4 -4
  90. package/dist/types/SwapExecutionAction.d.ts +141 -34
  91. package/dist/types/SwapExecutionAction.js +104 -0
  92. package/dist/types/SwapExecutionStep.d.ts +144 -0
  93. package/dist/types/SwapExecutionStep.js +87 -0
  94. package/dist/types/TokenAmount.d.ts +6 -0
  95. package/dist/types/TokenAmount.js +26 -1
  96. package/dist/utils/BitcoinUtils.d.ts +4 -0
  97. package/dist/utils/BitcoinUtils.js +73 -1
  98. package/dist/utils/BitcoinWalletUtils.d.ts +2 -2
  99. package/dist/utils/Utils.d.ts +3 -1
  100. package/dist/utils/Utils.js +7 -1
  101. package/package.json +7 -4
  102. package/src/api/ApiEndpoints.ts +427 -0
  103. package/src/api/ApiParser.ts +138 -0
  104. package/src/api/ApiTypes.ts +229 -0
  105. package/src/api/SerializedAction.ts +97 -0
  106. package/src/api/SwapperApi.ts +545 -0
  107. package/src/api/index.ts +5 -0
  108. package/src/bitcoin/coinselect2/accumulative.ts +2 -1
  109. package/src/bitcoin/coinselect2/blackjack.ts +2 -1
  110. package/src/bitcoin/coinselect2/index.ts +5 -4
  111. package/src/bitcoin/coinselect2/utils.ts +55 -14
  112. package/src/bitcoin/wallet/BitcoinWallet.ts +69 -57
  113. package/src/bitcoin/wallet/IBitcoinWallet.ts +44 -3
  114. package/src/bitcoin/wallet/SingleAddressBitcoinWallet.ts +12 -4
  115. package/src/events/UnifiedSwapEventListener.ts +11 -3
  116. package/src/http/HttpUtils.ts +10 -4
  117. package/src/http/paramcoders/client/StreamingFetchPromise.ts +4 -2
  118. package/src/index.ts +1 -0
  119. package/src/intermediaries/IntermediaryDiscovery.ts +9 -2
  120. package/src/intermediaries/apis/IntermediaryAPI.ts +335 -35
  121. package/src/intermediaries/auth/SignedKeyBasedAuth.ts +69 -0
  122. package/src/storage/IUnifiedStorage.ts +45 -4
  123. package/src/storage/UnifiedSwapStorage.ts +42 -8
  124. package/src/swapper/Swapper.ts +165 -24
  125. package/src/swapper/SwapperUtils.ts +42 -2
  126. package/src/swaps/ISwap.ts +88 -16
  127. package/src/swaps/ISwapWrapper.ts +28 -3
  128. package/src/swaps/escrow_swaps/IEscrowSwap.ts +5 -3
  129. package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +3 -1
  130. package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +4 -1
  131. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +264 -67
  132. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +6 -4
  133. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +390 -89
  134. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +6 -4
  135. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +548 -94
  136. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +7 -5
  137. package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +276 -45
  138. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +7 -6
  139. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +5 -3
  140. package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +413 -64
  141. package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +239 -61
  142. package/src/swaps/trusted/ln/LnForGasSwap.ts +211 -47
  143. package/src/swaps/trusted/ln/LnForGasWrapper.ts +1 -2
  144. package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +32 -51
  145. package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +5 -3
  146. package/src/types/SwapExecutionAction.ts +266 -43
  147. package/src/types/SwapExecutionStep.ts +224 -0
  148. package/src/types/TokenAmount.ts +36 -2
  149. package/src/utils/BitcoinUtils.ts +73 -0
  150. package/src/utils/BitcoinWalletUtils.ts +2 -2
  151. package/src/utils/Utils.ts +10 -1
  152. package/src/intermediaries/apis/TrustedIntermediaryAPI.ts +0 -258
@@ -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";
@@ -298,20 +298,24 @@ const SpvFromBTCPrepareResponseSchema = {
298
298
 
299
299
  callerFeeShare: FieldTypeEnum.BigInt,
300
300
  frontingFeeShare: FieldTypeEnum.BigInt,
301
- executionFeeShare: FieldTypeEnum.BigInt
301
+ executionFeeShare: FieldTypeEnum.BigInt,
302
+
303
+ usedUtxoInputCalculation: FieldTypeEnum.BooleanOptional
302
304
  } as const;
303
305
 
304
306
  export type SpvFromBTCPrepareResponseType = RequestSchemaResult<typeof SpvFromBTCPrepareResponseSchema>;
305
307
 
306
308
  export type SpvFromBTCPrepare = SwapInit & {
307
309
  address: string,
308
- amount: bigint,
310
+ amount: Promise<bigint>,
309
311
  gasAmount: bigint,
310
312
  gasToken: string,
311
313
  exactOut: boolean,
312
314
  callerFeeRate: Promise<bigint>,
313
315
  frontingFeeRate: bigint,
314
- stickyAddress?: boolean
316
+ stickyAddress?: boolean,
317
+ amountUtxos?: Promise<{ value: number, vSize: number, cpfp?: { effectiveVSize: number, effectiveFeeRate: number }}[] | undefined>,
318
+ amountFeeRate?: Promise<number | undefined>
315
319
  }
316
320
 
317
321
  const SpvFromBTCInitResponseSchema = {
@@ -325,8 +329,148 @@ export type SpvFromBTCInit = {
325
329
  psbtHex: string
326
330
  }
327
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
+
328
444
  export class IntermediaryAPI {
329
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
+
330
474
  /**
331
475
  * Returns the information about a specific intermediary
332
476
  *
@@ -337,7 +481,7 @@ export class IntermediaryAPI {
337
481
  * @throws {RequestError} If non-200 http response code is returned
338
482
  * @throws {Error} If the supplied nonce doesn't match the response
339
483
  */
340
- static async getIntermediaryInfo(
484
+ async getIntermediaryInfo(
341
485
  baseUrl: string,
342
486
  timeout?: number,
343
487
  abortSignal?: AbortSignal
@@ -349,8 +493,8 @@ export class IntermediaryAPI {
349
493
  //We don't know whether the node supports only POST or also has GET info support enabled
350
494
  // here we try both, and abort when the first one returns (which should be GET)
351
495
  const response = await Promise.any([
352
- httpGet<InfoHandlerResponse>(baseUrl+"/info?nonce="+nonce, timeout, abortController.signal),
353
- httpPost<InfoHandlerResponse>(baseUrl+"/info", {
496
+ this.httpGet<InfoHandlerResponse>(baseUrl+"/info?nonce="+nonce, timeout, abortController.signal),
497
+ this.httpPost<InfoHandlerResponse>(baseUrl+"/info", {
354
498
  nonce,
355
499
  }, timeout, abortController.signal)
356
500
  ]);
@@ -373,14 +517,14 @@ export class IntermediaryAPI {
373
517
  *
374
518
  * @throws {RequestError} If non-200 http response code is returned
375
519
  */
376
- static async getRefundAuthorization(
520
+ async getRefundAuthorization(
377
521
  url: string,
378
522
  paymentHash: string,
379
523
  sequence: bigint,
380
524
  timeout?: number,
381
525
  abortSignal?: AbortSignal
382
526
  ): Promise<RefundAuthorizationResponse> {
383
- return tryWithRetries(() => httpGet<RefundAuthorizationResponse>(
527
+ return tryWithRetries(() => this.httpGet<RefundAuthorizationResponse>(
384
528
  url + "/getRefundAuthorization"+
385
529
  "?paymentHash=" + encodeURIComponent(paymentHash) +
386
530
  "&sequence=" + encodeURIComponent(sequence.toString(10)),
@@ -399,13 +543,13 @@ export class IntermediaryAPI {
399
543
  *
400
544
  * @throws {RequestError} If non-200 http response code is returned
401
545
  */
402
- static async getPaymentAuthorization(
546
+ async getPaymentAuthorization(
403
547
  url: string,
404
548
  paymentHash: string,
405
549
  timeout?: number,
406
550
  abortSignal?: AbortSignal
407
551
  ): Promise<PaymentAuthorizationResponse> {
408
- return tryWithRetries(() => httpGet<PaymentAuthorizationResponse>(
552
+ return tryWithRetries(() => this.httpGet<PaymentAuthorizationResponse>(
409
553
  url+"/getInvoicePaymentAuth"+
410
554
  "?paymentHash="+encodeURIComponent(paymentHash),
411
555
  timeout,
@@ -423,13 +567,13 @@ export class IntermediaryAPI {
423
567
  *
424
568
  * @throws {RequestError} If non-200 http response code is returned
425
569
  */
426
- static async getInvoiceStatus(
570
+ async getInvoiceStatus(
427
571
  url: string,
428
572
  paymentHash: string,
429
573
  timeout?: number,
430
574
  abortSignal?: AbortSignal
431
575
  ): Promise<InvoiceStatusResponse> {
432
- return tryWithRetries(() => httpGet<InvoiceStatusResponse>(
576
+ return tryWithRetries(() => this.httpGet<InvoiceStatusResponse>(
433
577
  url+"/getInvoiceStatus"+
434
578
  "?paymentHash="+encodeURIComponent(paymentHash),
435
579
  timeout,
@@ -449,7 +593,7 @@ export class IntermediaryAPI {
449
593
  *
450
594
  * @throws {RequestError} If non-200 http response code is returned
451
595
  */
452
- static initToBTC(
596
+ initToBTC(
453
597
  chainIdentifier: string,
454
598
  baseUrl: string,
455
599
  init: ToBTCInit,
@@ -460,7 +604,7 @@ export class IntermediaryAPI {
460
604
  signDataPrefetch: Promise<any>,
461
605
  response: Promise<ToBTCResponseType>
462
606
  } {
463
- const responseBodyPromise = streamingFetchPromise(baseUrl+"/tobtc/payInvoice?chain="+encodeURIComponent(chainIdentifier), {
607
+ const responseBodyPromise = this.streamingFetchPromise(baseUrl+"/tobtc/payInvoice?chain="+encodeURIComponent(chainIdentifier), {
464
608
  ...init.additionalParams,
465
609
  address: init.btcAddress,
466
610
  amount: init.amount.toString(10),
@@ -508,7 +652,7 @@ export class IntermediaryAPI {
508
652
  *
509
653
  * @throws {RequestError} If non-200 http response code is returned
510
654
  */
511
- static initFromBTC(
655
+ initFromBTC(
512
656
  chainIdentifier: string,
513
657
  baseUrl: string,
514
658
  depositToken: string,
@@ -520,7 +664,7 @@ export class IntermediaryAPI {
520
664
  signDataPrefetch: Promise<any>,
521
665
  response: Promise<FromBTCResponseType>
522
666
  } {
523
- const responseBodyPromise = streamingFetchPromise(
667
+ const responseBodyPromise = this.streamingFetchPromise(
524
668
  baseUrl+"/frombtc/getAddress?chain="+encodeURIComponent(chainIdentifier)+"&depositToken="+encodeURIComponent(depositToken),
525
669
  {
526
670
  ...init.additionalParams,
@@ -581,7 +725,7 @@ export class IntermediaryAPI {
581
725
  *
582
726
  * @throws {RequestError} If non-200 http response code is returned
583
727
  */
584
- static initFromBTCLN(
728
+ initFromBTCLN(
585
729
  chainIdentifier: string,
586
730
  baseUrl: string,
587
731
  depositToken: string,
@@ -593,7 +737,7 @@ export class IntermediaryAPI {
593
737
  lnPublicKey: Promise<string | null>,
594
738
  response: Promise<FromBTCLNResponseType>
595
739
  } {
596
- const responseBodyPromise = streamingFetchPromise(
740
+ const responseBodyPromise = this.streamingFetchPromise(
597
741
  baseUrl+"/frombtcln/createInvoice?chain="+encodeURIComponent(chainIdentifier)+"&depositToken="+encodeURIComponent(depositToken),
598
742
  {
599
743
  ...init.additionalParams,
@@ -644,7 +788,7 @@ export class IntermediaryAPI {
644
788
  *
645
789
  * @throws {RequestError} If non-200 http response code is returned
646
790
  */
647
- static initFromBTCLNAuto(
791
+ initFromBTCLNAuto(
648
792
  chainIdentifier: string,
649
793
  baseUrl: string,
650
794
  init: FromBTCLNAutoInit,
@@ -655,7 +799,7 @@ export class IntermediaryAPI {
655
799
  lnPublicKey: Promise<string | null>,
656
800
  response: Promise<FromBTCLNAutoResponseType>
657
801
  } {
658
- const responseBodyPromise = streamingFetchPromise(
802
+ const responseBodyPromise = this.streamingFetchPromise(
659
803
  baseUrl+"/frombtcln_auto/createInvoice?chain="+encodeURIComponent(chainIdentifier),
660
804
  {
661
805
  ...init.additionalParams,
@@ -708,7 +852,7 @@ export class IntermediaryAPI {
708
852
  *
709
853
  * @throws {RequestError} If non-200 http response code is returned
710
854
  */
711
- static initToBTCLN(
855
+ initToBTCLN(
712
856
  chainIdentifier: string,
713
857
  baseUrl: string,
714
858
  init: ToBTCLNInit,
@@ -719,7 +863,7 @@ export class IntermediaryAPI {
719
863
  signDataPrefetch: Promise<any>,
720
864
  response: Promise<ToBTCLNResponseType>
721
865
  } {
722
- const responseBodyPromise = streamingFetchPromise(baseUrl+"/tobtcln/payInvoice?chain="+encodeURIComponent(chainIdentifier), {
866
+ const responseBodyPromise = this.streamingFetchPromise(baseUrl+"/tobtcln/payInvoice?chain="+encodeURIComponent(chainIdentifier), {
723
867
  exactIn: false,
724
868
  ...init.additionalParams,
725
869
  pr: init.pr,
@@ -764,14 +908,14 @@ export class IntermediaryAPI {
764
908
  *
765
909
  * @throws {RequestError} If non-200 http response code is returned
766
910
  */
767
- static async initToBTCLNExactIn(
911
+ async initToBTCLNExactIn(
768
912
  baseUrl: string,
769
913
  init: ToBTCLNInitExactIn,
770
914
  timeout?: number,
771
915
  abortSignal?: AbortSignal,
772
916
  streamRequest?: boolean
773
917
  ): Promise<ToBTCLNResponseType> {
774
- const responseBody = await streamingFetchPromise(baseUrl+"/tobtcln/payInvoiceExactIn", {
918
+ const responseBody = await this.streamingFetchPromise(baseUrl+"/tobtcln/payInvoiceExactIn", {
775
919
  ...init.additionalParams,
776
920
  pr: init.pr,
777
921
  reqId: init.reqId,
@@ -806,7 +950,7 @@ export class IntermediaryAPI {
806
950
  *
807
951
  * @throws {RequestError} If non-200 http response code is returned
808
952
  */
809
- static prepareToBTCLNExactIn(
953
+ prepareToBTCLNExactIn(
810
954
  chainIdentifier: string,
811
955
  baseUrl: string,
812
956
  init: ToBTCLNPrepareExactIn,
@@ -817,7 +961,7 @@ export class IntermediaryAPI {
817
961
  signDataPrefetch: Promise<any>,
818
962
  response: Promise<ToBTCLNPrepareExactInResponseType>
819
963
  } {
820
- const responseBodyPromise = streamingFetchPromise(baseUrl+"/tobtcln/payInvoice?chain="+encodeURIComponent(chainIdentifier), {
964
+ const responseBodyPromise = this.streamingFetchPromise(baseUrl+"/tobtcln/payInvoice?chain="+encodeURIComponent(chainIdentifier), {
821
965
  exactIn: true,
822
966
  ...init.additionalParams,
823
967
  pr: init.pr,
@@ -862,7 +1006,7 @@ export class IntermediaryAPI {
862
1006
  *
863
1007
  * @throws {RequestError} If non-200 http response code is returned
864
1008
  */
865
- static prepareSpvFromBTC(
1009
+ prepareSpvFromBTC(
866
1010
  chainIdentifier: string,
867
1011
  baseUrl: string,
868
1012
  init: SpvFromBTCPrepare,
@@ -870,17 +1014,29 @@ export class IntermediaryAPI {
870
1014
  abortSignal?: AbortSignal,
871
1015
  streamRequest?: boolean
872
1016
  ): Promise<SpvFromBTCPrepareResponseType> {
873
- const responseBodyPromise = streamingFetchPromise(baseUrl+"/frombtc_spv/getQuote?chain="+encodeURIComponent(chainIdentifier), {
1017
+ //We need to make sure we only send the amount parameter after the amountUtxos and amountFeeRate resolve
1018
+ // this is needed, because in the LP code to maintain backwards compatibility the amountUtxos and amountFeeRate
1019
+ // params are checked immediately after the amount param (and other params) are received, if amount were sent
1020
+ // first without the amountUtxos or amountFeeRate populated these fields would've been skipped altogether
1021
+ const amountPromise = (async () => {
1022
+ if(init.amountUtxos!=null) await init.amountUtxos;
1023
+ if(init.amountFeeRate!=null) await init.amountFeeRate;
1024
+ const amount = await init.amount;
1025
+ return amount.toString(10);
1026
+ })();
1027
+ const responseBodyPromise = this.streamingFetchPromise(baseUrl+"/frombtc_spv/getQuote?chain="+encodeURIComponent(chainIdentifier), {
874
1028
  exactOut: init.exactOut,
875
1029
  ...init.additionalParams,
876
1030
  address: init.address,
877
- amount: init.amount.toString(10),
1031
+ amount: amountPromise,
878
1032
  token: init.token,
879
1033
  gasAmount: init.gasAmount.toString(10),
880
1034
  gasToken: init.gasToken,
881
1035
  frontingFeeRate: init.frontingFeeRate.toString(10),
882
1036
  callerFeeRate: init.callerFeeRate.then(val => val.toString(10)),
883
- stickyAddress: init.stickyAddress
1037
+ stickyAddress: init.stickyAddress,
1038
+ amountUtxos: init.amountUtxos,
1039
+ amountFeeRate: init.amountFeeRate
884
1040
  }, {
885
1041
  code: FieldTypeEnum.Number,
886
1042
  msg: FieldTypeEnum.String,
@@ -913,7 +1069,7 @@ export class IntermediaryAPI {
913
1069
  *
914
1070
  * @throws {RequestError} If non-200 http response code is returned
915
1071
  */
916
- static initSpvFromBTC(
1072
+ initSpvFromBTC(
917
1073
  chainIdentifier: string,
918
1074
  url: string,
919
1075
  init: SpvFromBTCInit,
@@ -921,7 +1077,7 @@ export class IntermediaryAPI {
921
1077
  abortSignal?: AbortSignal,
922
1078
  streamRequest?: boolean
923
1079
  ): Promise<SpvFromBTCInitResponseType> {
924
- const responseBodyPromise = streamingFetchPromise(url+"/postQuote?chain="+encodeURIComponent(chainIdentifier), {
1080
+ const responseBodyPromise = this.streamingFetchPromise(url+"/postQuote?chain="+encodeURIComponent(chainIdentifier), {
925
1081
  quoteId: init.quoteId,
926
1082
  psbtHex: init.psbtHex
927
1083
  }, {
@@ -944,4 +1100,148 @@ export class IntermediaryAPI {
944
1100
  });
945
1101
  }
946
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
+
947
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
+ }