@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.
- package/api/index.d.ts +1 -0
- package/api/index.js +3 -0
- package/dist/ApiList.d.ts +37 -0
- package/dist/ApiList.js +30 -0
- package/dist/api/ApiEndpoints.d.ts +393 -0
- package/dist/api/ApiEndpoints.js +2 -0
- package/dist/api/ApiParser.d.ts +10 -0
- package/dist/api/ApiParser.js +134 -0
- package/dist/api/ApiTypes.d.ts +157 -0
- package/dist/api/ApiTypes.js +75 -0
- package/dist/api/SerializedAction.d.ts +40 -0
- package/dist/api/SerializedAction.js +59 -0
- package/dist/api/SwapperApi.d.ts +50 -0
- package/dist/api/SwapperApi.js +431 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.js +24 -0
- package/dist/bitcoin/coinselect2/accumulative.d.ts +1 -0
- package/dist/bitcoin/coinselect2/accumulative.js +1 -1
- package/dist/bitcoin/coinselect2/blackjack.d.ts +1 -0
- package/dist/bitcoin/coinselect2/blackjack.js +1 -1
- package/dist/bitcoin/coinselect2/index.d.ts +3 -2
- package/dist/bitcoin/coinselect2/index.js +2 -2
- package/dist/bitcoin/coinselect2/utils.d.ts +7 -2
- package/dist/bitcoin/coinselect2/utils.js +45 -10
- package/dist/bitcoin/wallet/BitcoinWallet.d.ts +8 -25
- package/dist/bitcoin/wallet/BitcoinWallet.js +31 -18
- package/dist/bitcoin/wallet/IBitcoinWallet.d.ts +40 -2
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +7 -2
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +10 -4
- package/dist/events/UnifiedSwapEventListener.d.ts +4 -3
- package/dist/events/UnifiedSwapEventListener.js +8 -2
- package/dist/http/HttpUtils.d.ts +4 -2
- package/dist/http/HttpUtils.js +10 -4
- package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +2 -1
- package/dist/http/paramcoders/client/StreamingFetchPromise.js +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/intermediaries/IntermediaryDiscovery.d.ts +7 -2
- package/dist/intermediaries/IntermediaryDiscovery.js +4 -4
- package/dist/intermediaries/apis/IntermediaryAPI.d.ts +182 -15
- package/dist/intermediaries/apis/IntermediaryAPI.js +192 -31
- package/dist/intermediaries/auth/SignedKeyBasedAuth.d.ts +14 -0
- package/dist/intermediaries/auth/SignedKeyBasedAuth.js +68 -0
- package/dist/storage/IUnifiedStorage.d.ts +45 -3
- package/dist/storage/UnifiedSwapStorage.d.ts +8 -2
- package/dist/storage/UnifiedSwapStorage.js +46 -8
- package/dist/swapper/Swapper.d.ts +77 -4
- package/dist/swapper/Swapper.js +117 -25
- package/dist/swapper/SwapperUtils.d.ts +18 -2
- package/dist/swapper/SwapperUtils.js +39 -1
- package/dist/swaps/ISwap.d.ts +70 -9
- package/dist/swaps/ISwap.js +28 -6
- package/dist/swaps/ISwapWrapper.d.ts +11 -1
- package/dist/swaps/ISwapWrapper.js +23 -3
- package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +1 -1
- package/dist/swaps/escrow_swaps/IEscrowSwap.js +4 -2
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +2 -1
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +2 -2
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +3 -2
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +47 -31
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +201 -67
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +6 -6
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +82 -15
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +304 -98
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +6 -6
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +75 -42
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +424 -87
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +7 -7
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +54 -11
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +214 -41
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +2 -1
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +7 -8
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +5 -5
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +85 -22
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +299 -56
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +41 -7
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +183 -58
- package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +53 -12
- package/dist/swaps/trusted/ln/LnForGasSwap.js +163 -49
- package/dist/swaps/trusted/ln/LnForGasWrapper.js +1 -2
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +14 -13
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +30 -47
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +3 -1
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +4 -4
- package/dist/types/SwapExecutionAction.d.ts +141 -34
- package/dist/types/SwapExecutionAction.js +104 -0
- package/dist/types/SwapExecutionStep.d.ts +144 -0
- package/dist/types/SwapExecutionStep.js +87 -0
- package/dist/types/TokenAmount.d.ts +6 -0
- package/dist/types/TokenAmount.js +26 -1
- package/dist/utils/BitcoinUtils.d.ts +4 -0
- package/dist/utils/BitcoinUtils.js +73 -1
- package/dist/utils/BitcoinWalletUtils.d.ts +2 -2
- package/dist/utils/Utils.d.ts +3 -1
- package/dist/utils/Utils.js +7 -1
- package/package.json +7 -4
- package/src/api/ApiEndpoints.ts +427 -0
- package/src/api/ApiParser.ts +138 -0
- package/src/api/ApiTypes.ts +229 -0
- package/src/api/SerializedAction.ts +97 -0
- package/src/api/SwapperApi.ts +545 -0
- package/src/api/index.ts +5 -0
- package/src/bitcoin/coinselect2/accumulative.ts +2 -1
- package/src/bitcoin/coinselect2/blackjack.ts +2 -1
- package/src/bitcoin/coinselect2/index.ts +5 -4
- package/src/bitcoin/coinselect2/utils.ts +55 -14
- package/src/bitcoin/wallet/BitcoinWallet.ts +69 -57
- package/src/bitcoin/wallet/IBitcoinWallet.ts +44 -3
- package/src/bitcoin/wallet/SingleAddressBitcoinWallet.ts +12 -4
- package/src/events/UnifiedSwapEventListener.ts +11 -3
- package/src/http/HttpUtils.ts +10 -4
- package/src/http/paramcoders/client/StreamingFetchPromise.ts +4 -2
- package/src/index.ts +1 -0
- package/src/intermediaries/IntermediaryDiscovery.ts +9 -2
- package/src/intermediaries/apis/IntermediaryAPI.ts +335 -35
- package/src/intermediaries/auth/SignedKeyBasedAuth.ts +69 -0
- package/src/storage/IUnifiedStorage.ts +45 -4
- package/src/storage/UnifiedSwapStorage.ts +42 -8
- package/src/swapper/Swapper.ts +165 -24
- package/src/swapper/SwapperUtils.ts +42 -2
- package/src/swaps/ISwap.ts +88 -16
- package/src/swaps/ISwapWrapper.ts +28 -3
- package/src/swaps/escrow_swaps/IEscrowSwap.ts +5 -3
- package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +3 -1
- package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +4 -1
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +264 -67
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +6 -4
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +390 -89
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +6 -4
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +548 -94
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +7 -5
- package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +276 -45
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +7 -6
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +5 -3
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +413 -64
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +239 -61
- package/src/swaps/trusted/ln/LnForGasSwap.ts +211 -47
- package/src/swaps/trusted/ln/LnForGasWrapper.ts +1 -2
- package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +32 -51
- package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +5 -3
- package/src/types/SwapExecutionAction.ts +266 -43
- package/src/types/SwapExecutionStep.ts +224 -0
- package/src/types/TokenAmount.ts +36 -2
- package/src/utils/BitcoinUtils.ts +73 -0
- package/src/utils/BitcoinWalletUtils.ts +2 -2
- package/src/utils/Utils.ts +10 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
+
}
|