@atomiqlabs/base 13.0.4 → 13.1.3

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.
@@ -0,0 +1,23 @@
1
+ /**
2
+ * A type defining total capacity of a given lightning network node
3
+ *
4
+ * @category Bitcoin
5
+ */
6
+ export type LNNodeLiquidity = {
7
+ publicKey: string;
8
+ capacity: bigint;
9
+ numChannels: number;
10
+ };
11
+ /**
12
+ * An interface for Lightning API, provides view of the public lightning network data like channel graph
13
+ *
14
+ * @category Bitcoin
15
+ */
16
+ export interface LightningNetworkApi {
17
+ /**
18
+ * Returns the lightning network's node liquidity as identified by an identity public key
19
+ *
20
+ * @param pubkey
21
+ */
22
+ getLNNodeLiquidity(pubkey: string): Promise<LNNodeLiquidity | null>;
23
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -226,4 +226,10 @@ export interface BitcoinRpc<T extends BtcBlock> {
226
226
  fee: number;
227
227
  feeRate: number;
228
228
  }>;
229
+ /**
230
+ * Parses a bitcoin address from the passed output script in hexadecimal format
231
+ *
232
+ * @param outputScriptHex
233
+ */
234
+ outputScriptToAddress?(outputScriptHex: string): Promise<string>;
229
235
  }
@@ -0,0 +1,112 @@
1
+ /// <reference types="node" />
2
+ import { Buffer } from "buffer";
3
+ import { BitcoinRpc, BtcTx } from "./BitcoinRpc";
4
+ import { BtcBlock } from "../../btcrelay/types/BtcBlock";
5
+ /**
6
+ * A type defining a bitcoin transaction with its blockheight and optional input addresses populated
7
+ *
8
+ * @category Bitcoin
9
+ */
10
+ export type BtcTxWithBlockheight = BtcTx & {
11
+ blockheight?: number;
12
+ inputAddresses?: string[];
13
+ };
14
+ /**
15
+ * A type defining a single UTXO belonging to an address
16
+ *
17
+ * @category Bitcoin
18
+ */
19
+ export type BtcAddressUtxo = {
20
+ txid: string;
21
+ vout: number;
22
+ confirmed: boolean;
23
+ block_height: number;
24
+ block_hash: string;
25
+ block_time: number;
26
+ value: bigint;
27
+ };
28
+ /**
29
+ * An extended interface for Bitcoin, that allows querying balances and UTXOs of any address + other utilities
30
+ *
31
+ * @category Bitcoin
32
+ */
33
+ export interface BitcoinRpcWithAddressIndex<T extends BtcBlock> extends BitcoinRpc<T> {
34
+ /**
35
+ * Returns the current fee rate required for submitted bitcoin transactions in sats/vB
36
+ */
37
+ getFeeRate(): Promise<number>;
38
+ /**
39
+ * Returns confirmed & unconfirmed balances for a given wallet address
40
+ *
41
+ * @param address
42
+ */
43
+ getAddressBalances(address: string): Promise<{
44
+ confirmedBalance: bigint;
45
+ unconfirmedBalance: bigint;
46
+ }>;
47
+ /**
48
+ * Returns UTXOs owned by the given wallet address
49
+ * @param address
50
+ */
51
+ getAddressUTXOs(address: string): Promise<BtcAddressUtxo[]>;
52
+ /**
53
+ * Returns CPFP (children-pay-for-parent) data for a given transaction, or null if transaction is not found
54
+ * or already confirmed
55
+ *
56
+ * @param txId
57
+ */
58
+ getCPFPData(txId: string): Promise<{
59
+ effectiveFeePerVsize: number;
60
+ adjustedVsize: number;
61
+ } | null>;
62
+ /**
63
+ * @inheritDoc
64
+ */
65
+ getTransaction(txId: string): Promise<BtcTxWithBlockheight | null>;
66
+ /**
67
+ * Awaits till the given transaction gets confirmed
68
+ *
69
+ * @param txId Transaction ID to monitor
70
+ * @param requiredConfirmations Required number of confirmations
71
+ * @param stateUpdateCbk Optional update callback called with the current status of the bitcoin transaction
72
+ * @param abortSignal
73
+ * @param intervalSeconds How often to poll
74
+ */
75
+ waitForTransaction(txId: string, requiredConfirmations: number, stateUpdateCbk?: (btcTx?: BtcTxWithBlockheight, txEtaMS?: number) => void, abortSignal?: AbortSignal, intervalSeconds?: number): Promise<BtcTxWithBlockheight>;
76
+ /**
77
+ * Returns an estimate after which time the tx will confirm with the required amount of confirmations,
78
+ * confirmationDelay of -1 means the transaction won't confirm in the near future
79
+ *
80
+ * @param tx
81
+ * @param requiredConfirmations
82
+ *
83
+ * @returns estimated confirmation delay, -1 if the transaction won't confirm in the near future, null if the
84
+ * transaction was replaced or was confirmed in the meantime
85
+ */
86
+ getConfirmationDelay(tx: BtcTx, requiredConfirmations: number): Promise<number | null>;
87
+ /**
88
+ * Checks if an address received the transaction with the required txoHash, returns info about that
89
+ * specific transaction if found, or null if not found
90
+ *
91
+ * @param address Address that should receive the transaction
92
+ * @param txoHash Required output txoHash
93
+ */
94
+ checkAddressTxos(address: string, txoHash: Buffer): Promise<{
95
+ tx: Omit<BtcTxWithBlockheight, "hex" | "raw">;
96
+ vout: number;
97
+ } | null>;
98
+ /**
99
+ * Waits till the address receives a transaction containing a specific txoHash
100
+ *
101
+ * @param address Address that should receive the transaction
102
+ * @param txoHash Required output txoHash
103
+ * @param requiredConfirmations Required confirmations of the transaction
104
+ * @param stateUpdateCbk Callback for transaction state updates
105
+ * @param abortSignal Abort signal
106
+ * @param intervalSeconds How often to check new transaction
107
+ */
108
+ waitForAddressTxo(address: string, txoHash: Buffer, requiredConfirmations: number, stateUpdateCbk: (btcTx?: Omit<BtcTxWithBlockheight, "hex" | "raw">, vout?: number, txEtaMS?: number) => void, abortSignal?: AbortSignal, intervalSeconds?: number): Promise<{
109
+ tx: Omit<BtcTxWithBlockheight, "hex" | "raw">;
110
+ vout: number;
111
+ }>;
112
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export * from "./btcrelay/BtcRelay";
2
2
  export * from "./btc/rpc/BitcoinRpc";
3
+ export * from "./btc/rpc/BitcoinRpcWithAddressIndex";
4
+ export * from "./btc/lightning/LightningNetworkApi";
3
5
  export * from "./btcrelay/synchronizer/RelaySynchronizer";
4
6
  export * from "./btcrelay/types/BtcBlock";
5
7
  export * from "./btcrelay/types/BtcHeader";
@@ -12,6 +14,7 @@ export * from "./events/types/swap/RefundEvent";
12
14
  export * from "./events/types/swap/SwapEvent";
13
15
  export * from "./lockable/Lockable";
14
16
  export * from "./storage/IStorageManager";
17
+ export * from "./storage/VoidStorageManager";
15
18
  export * from "./storage/StorageObject";
16
19
  export * from "./swaps/SwapContract";
17
20
  export * from "./swaps/SwapData";
@@ -24,6 +27,9 @@ export * from "./errors/TransactionRevertedError";
24
27
  export * from "./chains/ChainType";
25
28
  export * from "./chains/ChainData";
26
29
  export * from "./utils/BigIntBufferUtils";
30
+ export * from "./utils/Logger";
31
+ export * from "./utils/RetryUtils";
32
+ export * from "./utils/TimeoutUtils";
27
33
  export * from "./btc/BitcoinNetwork";
28
34
  export * from "./chains/ChainInterface";
29
35
  export * from "./spv_swap/SpvVaultContract";
package/dist/index.js CHANGED
@@ -16,6 +16,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./btcrelay/BtcRelay"), exports);
18
18
  __exportStar(require("./btc/rpc/BitcoinRpc"), exports);
19
+ __exportStar(require("./btc/rpc/BitcoinRpcWithAddressIndex"), exports);
20
+ __exportStar(require("./btc/lightning/LightningNetworkApi"), exports);
19
21
  __exportStar(require("./btcrelay/synchronizer/RelaySynchronizer"), exports);
20
22
  __exportStar(require("./btcrelay/types/BtcBlock"), exports);
21
23
  __exportStar(require("./btcrelay/types/BtcHeader"), exports);
@@ -28,6 +30,7 @@ __exportStar(require("./events/types/swap/RefundEvent"), exports);
28
30
  __exportStar(require("./events/types/swap/SwapEvent"), exports);
29
31
  __exportStar(require("./lockable/Lockable"), exports);
30
32
  __exportStar(require("./storage/IStorageManager"), exports);
33
+ __exportStar(require("./storage/VoidStorageManager"), exports);
31
34
  __exportStar(require("./storage/StorageObject"), exports);
32
35
  __exportStar(require("./swaps/SwapContract"), exports);
33
36
  __exportStar(require("./swaps/SwapData"), exports);
@@ -40,6 +43,9 @@ __exportStar(require("./errors/TransactionRevertedError"), exports);
40
43
  __exportStar(require("./chains/ChainType"), exports);
41
44
  __exportStar(require("./chains/ChainData"), exports);
42
45
  __exportStar(require("./utils/BigIntBufferUtils"), exports);
46
+ __exportStar(require("./utils/Logger"), exports);
47
+ __exportStar(require("./utils/RetryUtils"), exports);
48
+ __exportStar(require("./utils/TimeoutUtils"), exports);
43
49
  __exportStar(require("./btc/BitcoinNetwork"), exports);
44
50
  __exportStar(require("./chains/ChainInterface"), exports);
45
51
  __exportStar(require("./spv_swap/SpvVaultContract"), exports);
@@ -0,0 +1,33 @@
1
+ import { IStorageManager } from "./IStorageManager";
2
+ /**
3
+ * A dummy storage manager that doesn't store anything, and should be only used as a placeholder
4
+ *
5
+ * @category Storage
6
+ * @internal
7
+ */
8
+ export declare class VoidStorageManager implements IStorageManager<any> {
9
+ /**
10
+ * @inheritDoc
11
+ */
12
+ data: {
13
+ [p: string]: any;
14
+ };
15
+ /**
16
+ * @inheritDoc
17
+ */
18
+ init(): Promise<void>;
19
+ /**
20
+ * @inheritDoc
21
+ */
22
+ loadData(type: {
23
+ new (data: any): any;
24
+ }): Promise<any[]>;
25
+ /**
26
+ * @inheritDoc
27
+ */
28
+ removeData(hash: string): Promise<void>;
29
+ /**
30
+ * @inheritDoc
31
+ */
32
+ saveData(hash: string, object: any): Promise<void>;
33
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VoidStorageManager = void 0;
4
+ /**
5
+ * A dummy storage manager that doesn't store anything, and should be only used as a placeholder
6
+ *
7
+ * @category Storage
8
+ * @internal
9
+ */
10
+ class VoidStorageManager {
11
+ constructor() {
12
+ /**
13
+ * @inheritDoc
14
+ */
15
+ this.data = {};
16
+ }
17
+ /**
18
+ * @inheritDoc
19
+ */
20
+ init() {
21
+ return Promise.resolve();
22
+ }
23
+ /**
24
+ * @inheritDoc
25
+ */
26
+ loadData(type) {
27
+ return Promise.resolve([]);
28
+ }
29
+ /**
30
+ * @inheritDoc
31
+ */
32
+ removeData(hash) {
33
+ return Promise.resolve();
34
+ }
35
+ /**
36
+ * @inheritDoc
37
+ */
38
+ saveData(hash, object) {
39
+ return Promise.resolve();
40
+ }
41
+ }
42
+ exports.VoidStorageManager = VoidStorageManager;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Type of the logger
3
+ *
4
+ * @internal
5
+ */
6
+ export type LoggerType = {
7
+ debug: (msg: string, ...args: any[]) => void;
8
+ info: (msg: string, ...args: any[]) => void;
9
+ warn: (msg: string, ...args: any[]) => void;
10
+ error: (msg: string, ...args: any[]) => void;
11
+ };
12
+ /**
13
+ * Getter function to create a logger instance
14
+ *
15
+ * @internal
16
+ */
17
+ export declare function getLogger(prefix: string): LoggerType;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLogger = void 0;
4
+ /**
5
+ * Getter function to create a logger instance
6
+ *
7
+ * @internal
8
+ */
9
+ function getLogger(prefix) {
10
+ return {
11
+ debug: (msg, ...args) => global.atomiqLogLevel >= 3 && console.debug(prefix + msg, ...args),
12
+ info: (msg, ...args) => global.atomiqLogLevel >= 2 && console.info(prefix + msg, ...args),
13
+ warn: (msg, ...args) => (global.atomiqLogLevel == null || global.atomiqLogLevel >= 1) && console.warn(prefix + msg, ...args),
14
+ error: (msg, ...args) => (global.atomiqLogLevel == null || global.atomiqLogLevel >= 0) && console.error(prefix + msg, ...args)
15
+ };
16
+ }
17
+ exports.getLogger = getLogger;
@@ -0,0 +1,23 @@
1
+ type Constructor<T = any> = new (...args: any[]) => T;
2
+ /**
3
+ * Runs the passed function multiple times if it fails
4
+ *
5
+ * @param func A callback for executing the action
6
+ * @param func.retryCount Count of the current retry, starting from 0 for original request and increasing
7
+ * @param retryPolicy Retry policy
8
+ * @param retryPolicy.maxRetries How many retries to attempt in total
9
+ * @param retryPolicy.delay How long should the delay be
10
+ * @param retryPolicy.exponential Whether to use exponentially increasing delays
11
+ * @param errorAllowed A callback for determining whether a given error is allowed, and we should therefore not retry
12
+ * @param abortSignal
13
+ *
14
+ * @returns Result of the action executing callback
15
+ *
16
+ * @internal
17
+ */
18
+ export declare function tryWithRetries<T>(func: (retryCount: number) => Promise<T>, retryPolicy?: {
19
+ maxRetries?: number;
20
+ delay?: number;
21
+ exponential?: boolean;
22
+ }, errorAllowed?: ((e: any) => boolean) | Constructor<Error> | Constructor<Error>[], abortSignal?: AbortSignal): Promise<T>;
23
+ export {};
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tryWithRetries = void 0;
4
+ const Logger_1 = require("./Logger");
5
+ const TimeoutUtils_1 = require("./TimeoutUtils");
6
+ const logger = (0, Logger_1.getLogger)("RetryUtils: ");
7
+ function isConstructor(fn) {
8
+ return (typeof fn === 'function' &&
9
+ fn.prototype != null &&
10
+ fn.prototype.constructor === fn);
11
+ }
12
+ function isConstructorArray(fnArr) {
13
+ return Array.isArray(fnArr) && fnArr.every(isConstructor);
14
+ }
15
+ /**
16
+ * Checks whether the passed error is allowed to pass through
17
+ *
18
+ * @param e Error in question
19
+ * @param errorAllowed Allowed errors as defined as a callback function, specific error type, or an array of error types
20
+ */
21
+ function checkError(e, errorAllowed) {
22
+ if (isConstructorArray(errorAllowed))
23
+ return errorAllowed.find(error => e instanceof error) != null;
24
+ if (isConstructor(errorAllowed))
25
+ return e instanceof errorAllowed;
26
+ return errorAllowed(e);
27
+ }
28
+ /**
29
+ * Runs the passed function multiple times if it fails
30
+ *
31
+ * @param func A callback for executing the action
32
+ * @param func.retryCount Count of the current retry, starting from 0 for original request and increasing
33
+ * @param retryPolicy Retry policy
34
+ * @param retryPolicy.maxRetries How many retries to attempt in total
35
+ * @param retryPolicy.delay How long should the delay be
36
+ * @param retryPolicy.exponential Whether to use exponentially increasing delays
37
+ * @param errorAllowed A callback for determining whether a given error is allowed, and we should therefore not retry
38
+ * @param abortSignal
39
+ *
40
+ * @returns Result of the action executing callback
41
+ *
42
+ * @internal
43
+ */
44
+ async function tryWithRetries(func, retryPolicy, errorAllowed, abortSignal) {
45
+ retryPolicy = retryPolicy || {};
46
+ retryPolicy.maxRetries = retryPolicy.maxRetries || 5;
47
+ retryPolicy.delay = retryPolicy.delay || 500;
48
+ retryPolicy.exponential = retryPolicy.exponential == null ? true : retryPolicy.exponential;
49
+ let err = null;
50
+ for (let i = 0; i < retryPolicy.maxRetries; i++) {
51
+ try {
52
+ return await func(i);
53
+ }
54
+ catch (e) {
55
+ if (errorAllowed != null && checkError(e, errorAllowed))
56
+ throw e;
57
+ err = e;
58
+ logger.warn("tryWithRetries(): Error on try number: " + i, e);
59
+ }
60
+ if (abortSignal != null && abortSignal.aborted)
61
+ throw (abortSignal.reason || new Error("Aborted"));
62
+ if (i !== retryPolicy.maxRetries - 1) {
63
+ await (0, TimeoutUtils_1.timeoutPromise)(retryPolicy.exponential ? retryPolicy.delay * Math.pow(2, i) : retryPolicy.delay, abortSignal);
64
+ }
65
+ }
66
+ throw err;
67
+ }
68
+ exports.tryWithRetries = tryWithRetries;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Returns a promise that resolves after given amount seconds
3
+ *
4
+ * @param timeout how many milliseconds to wait for
5
+ * @param abortSignal
6
+ *
7
+ * @internal
8
+ */
9
+ export declare function timeoutPromise(timeout: number, abortSignal?: AbortSignal): Promise<void>;
10
+ /**
11
+ * Returns an abort signal that aborts after a specified timeout in milliseconds
12
+ *
13
+ * @param timeout Milliseconds to wait
14
+ * @param abortReason Abort with this abort reason
15
+ * @param abortSignal Abort signal to extend
16
+ *
17
+ * @internal
18
+ */
19
+ export declare function timeoutSignal(timeout: number, abortReason?: any, abortSignal?: AbortSignal): AbortSignal;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.timeoutSignal = exports.timeoutPromise = void 0;
4
+ /**
5
+ * Returns a promise that resolves after given amount seconds
6
+ *
7
+ * @param timeout how many milliseconds to wait for
8
+ * @param abortSignal
9
+ *
10
+ * @internal
11
+ */
12
+ function timeoutPromise(timeout, abortSignal) {
13
+ return new Promise((resolve, reject) => {
14
+ if (abortSignal != null && abortSignal.aborted) {
15
+ reject(abortSignal.reason);
16
+ return;
17
+ }
18
+ let abortSignalListener;
19
+ let timeoutHandle = setTimeout(() => {
20
+ if (abortSignalListener != null && abortSignal != null)
21
+ abortSignal.removeEventListener("abort", abortSignalListener);
22
+ resolve();
23
+ }, timeout);
24
+ if (abortSignal != null) {
25
+ abortSignal.addEventListener("abort", abortSignalListener = () => {
26
+ if (timeoutHandle != null)
27
+ clearTimeout(timeoutHandle);
28
+ timeoutHandle = null;
29
+ reject(abortSignal.reason);
30
+ });
31
+ }
32
+ });
33
+ }
34
+ exports.timeoutPromise = timeoutPromise;
35
+ /**
36
+ * Returns an abort signal that aborts after a specified timeout in milliseconds
37
+ *
38
+ * @param timeout Milliseconds to wait
39
+ * @param abortReason Abort with this abort reason
40
+ * @param abortSignal Abort signal to extend
41
+ *
42
+ * @internal
43
+ */
44
+ function timeoutSignal(timeout, abortReason, abortSignal) {
45
+ if (timeout == null)
46
+ throw new Error("Timeout seconds cannot be null!");
47
+ const abortController = new AbortController();
48
+ const timeoutHandle = setTimeout(() => abortController.abort(abortReason || new Error("Timed out")), timeout);
49
+ if (abortSignal != null) {
50
+ abortSignal.addEventListener("abort", () => {
51
+ clearTimeout(timeoutHandle);
52
+ abortController.abort(abortSignal.reason);
53
+ });
54
+ }
55
+ return abortController.signal;
56
+ }
57
+ exports.timeoutSignal = timeoutSignal;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atomiqlabs/base",
3
- "version": "13.0.4",
3
+ "version": "13.1.3",
4
4
  "description": "Base classes and interfaces for atomiq protocol",
5
5
  "main": "./dist/index.js",
6
6
  "types:": "./dist/index.d.ts",
@@ -0,0 +1,27 @@
1
+
2
+ /**
3
+ * A type defining total capacity of a given lightning network node
4
+ *
5
+ * @category Bitcoin
6
+ */
7
+ export type LNNodeLiquidity = {
8
+ publicKey: string,
9
+ capacity: bigint,
10
+ numChannels: number
11
+ };
12
+
13
+ /**
14
+ * An interface for Lightning API, provides view of the public lightning network data like channel graph
15
+ *
16
+ * @category Bitcoin
17
+ */
18
+ export interface LightningNetworkApi {
19
+
20
+ /**
21
+ * Returns the lightning network's node liquidity as identified by an identity public key
22
+ *
23
+ * @param pubkey
24
+ */
25
+ getLNNodeLiquidity(pubkey: string): Promise<LNNodeLiquidity | null>
26
+
27
+ }
@@ -242,4 +242,11 @@ export interface BitcoinRpc<T extends BtcBlock> {
242
242
  */
243
243
  getEffectiveFeeRate(btcTx: BtcTx): Promise<{vsize: number, fee: number, feeRate: number}>;
244
244
 
245
+ /**
246
+ * Parses a bitcoin address from the passed output script in hexadecimal format
247
+ *
248
+ * @param outputScriptHex
249
+ */
250
+ outputScriptToAddress?(outputScriptHex: string): Promise<string>;
251
+
245
252
  }
@@ -0,0 +1,138 @@
1
+ import {Buffer} from "buffer";
2
+ import {BitcoinRpc, BtcTx} from "./BitcoinRpc";
3
+ import {BtcBlock} from "../../btcrelay/types/BtcBlock";
4
+
5
+
6
+ /**
7
+ * A type defining a bitcoin transaction with its blockheight and optional input addresses populated
8
+ *
9
+ * @category Bitcoin
10
+ */
11
+ export type BtcTxWithBlockheight = BtcTx & {
12
+ blockheight?: number,
13
+ inputAddresses?: string[]
14
+ };
15
+
16
+ /**
17
+ * A type defining a single UTXO belonging to an address
18
+ *
19
+ * @category Bitcoin
20
+ */
21
+ export type BtcAddressUtxo = {
22
+ txid: string,
23
+ vout: number,
24
+ confirmed: boolean,
25
+ block_height: number,
26
+ block_hash: string,
27
+ block_time: number
28
+ value: bigint
29
+ };
30
+
31
+ /**
32
+ * An extended interface for Bitcoin, that allows querying balances and UTXOs of any address + other utilities
33
+ *
34
+ * @category Bitcoin
35
+ */
36
+ export interface BitcoinRpcWithAddressIndex<T extends BtcBlock> extends BitcoinRpc<T> {
37
+
38
+ /**
39
+ * Returns the current fee rate required for submitted bitcoin transactions in sats/vB
40
+ */
41
+ getFeeRate(): Promise<number>;
42
+
43
+ /**
44
+ * Returns confirmed & unconfirmed balances for a given wallet address
45
+ *
46
+ * @param address
47
+ */
48
+ getAddressBalances(address: string): Promise<{
49
+ confirmedBalance: bigint,
50
+ unconfirmedBalance: bigint
51
+ }>;
52
+
53
+ /**
54
+ * Returns UTXOs owned by the given wallet address
55
+ * @param address
56
+ */
57
+ getAddressUTXOs(address: string): Promise<BtcAddressUtxo[]>;
58
+
59
+ /**
60
+ * Returns CPFP (children-pay-for-parent) data for a given transaction, or null if transaction is not found
61
+ * or already confirmed
62
+ *
63
+ * @param txId
64
+ */
65
+ getCPFPData(txId: string): Promise<{
66
+ effectiveFeePerVsize: number,
67
+ adjustedVsize: number
68
+ } | null>;
69
+
70
+ /**
71
+ * @inheritDoc
72
+ */
73
+ getTransaction(txId: string): Promise<BtcTxWithBlockheight | null>;
74
+
75
+ /**
76
+ * Awaits till the given transaction gets confirmed
77
+ *
78
+ * @param txId Transaction ID to monitor
79
+ * @param requiredConfirmations Required number of confirmations
80
+ * @param stateUpdateCbk Optional update callback called with the current status of the bitcoin transaction
81
+ * @param abortSignal
82
+ * @param intervalSeconds How often to poll
83
+ */
84
+ waitForTransaction(
85
+ txId: string,
86
+ requiredConfirmations: number,
87
+ stateUpdateCbk?: (btcTx?: BtcTxWithBlockheight, txEtaMS?: number) => void,
88
+ abortSignal?: AbortSignal,
89
+ intervalSeconds?: number
90
+ ): Promise<BtcTxWithBlockheight>;
91
+
92
+ /**
93
+ * Returns an estimate after which time the tx will confirm with the required amount of confirmations,
94
+ * confirmationDelay of -1 means the transaction won't confirm in the near future
95
+ *
96
+ * @param tx
97
+ * @param requiredConfirmations
98
+ *
99
+ * @returns estimated confirmation delay, -1 if the transaction won't confirm in the near future, null if the
100
+ * transaction was replaced or was confirmed in the meantime
101
+ */
102
+ getConfirmationDelay(tx: BtcTx, requiredConfirmations: number): Promise<number | null>
103
+
104
+ /**
105
+ * Checks if an address received the transaction with the required txoHash, returns info about that
106
+ * specific transaction if found, or null if not found
107
+ *
108
+ * @param address Address that should receive the transaction
109
+ * @param txoHash Required output txoHash
110
+ */
111
+ checkAddressTxos(address: string, txoHash: Buffer): Promise<{
112
+ tx: Omit<BtcTxWithBlockheight, "hex" | "raw">,
113
+ vout: number
114
+ } | null>;
115
+
116
+ /**
117
+ * Waits till the address receives a transaction containing a specific txoHash
118
+ *
119
+ * @param address Address that should receive the transaction
120
+ * @param txoHash Required output txoHash
121
+ * @param requiredConfirmations Required confirmations of the transaction
122
+ * @param stateUpdateCbk Callback for transaction state updates
123
+ * @param abortSignal Abort signal
124
+ * @param intervalSeconds How often to check new transaction
125
+ */
126
+ waitForAddressTxo(
127
+ address: string,
128
+ txoHash: Buffer,
129
+ requiredConfirmations: number,
130
+ stateUpdateCbk: (btcTx?: Omit<BtcTxWithBlockheight, "hex" | "raw">, vout?: number, txEtaMS?: number) => void,
131
+ abortSignal?: AbortSignal,
132
+ intervalSeconds?: number
133
+ ): Promise<{
134
+ tx: Omit<BtcTxWithBlockheight, "hex" | "raw">,
135
+ vout: number
136
+ }>;
137
+
138
+ }
package/src/index.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export * from "./btcrelay/BtcRelay";
2
2
  export * from "./btc/rpc/BitcoinRpc";
3
+ export * from "./btc/rpc/BitcoinRpcWithAddressIndex";
4
+ export * from "./btc/lightning/LightningNetworkApi";
3
5
  export * from "./btcrelay/synchronizer/RelaySynchronizer";
4
6
  export * from "./btcrelay/types/BtcBlock";
5
7
  export * from "./btcrelay/types/BtcHeader";
@@ -12,6 +14,7 @@ export * from "./events/types/swap/RefundEvent";
12
14
  export * from "./events/types/swap/SwapEvent";
13
15
  export * from "./lockable/Lockable";
14
16
  export * from "./storage/IStorageManager";
17
+ export * from "./storage/VoidStorageManager";
15
18
  export * from "./storage/StorageObject";
16
19
  export * from "./swaps/SwapContract";
17
20
  export * from "./swaps/SwapData";
@@ -27,6 +30,9 @@ export * from "./chains/ChainType";
27
30
  export * from "./chains/ChainData";
28
31
 
29
32
  export * from "./utils/BigIntBufferUtils";
33
+ export * from "./utils/Logger";
34
+ export * from "./utils/RetryUtils";
35
+ export * from "./utils/TimeoutUtils";
30
36
 
31
37
  export * from "./btc/BitcoinNetwork";
32
38
 
@@ -0,0 +1,42 @@
1
+ import {IStorageManager} from "./IStorageManager";
2
+
3
+ /**
4
+ * A dummy storage manager that doesn't store anything, and should be only used as a placeholder
5
+ *
6
+ * @category Storage
7
+ * @internal
8
+ */
9
+ export class VoidStorageManager implements IStorageManager<any> {
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ data: { [p: string]: any } = {};
14
+
15
+ /**
16
+ * @inheritDoc
17
+ */
18
+ init(): Promise<void> {
19
+ return Promise.resolve();
20
+ }
21
+
22
+ /**
23
+ * @inheritDoc
24
+ */
25
+ loadData(type: { new(data: any): any }): Promise<any[]> {
26
+ return Promise.resolve([]);
27
+ }
28
+
29
+ /**
30
+ * @inheritDoc
31
+ */
32
+ removeData(hash: string): Promise<void> {
33
+ return Promise.resolve();
34
+ }
35
+
36
+ /**
37
+ * @inheritDoc
38
+ */
39
+ saveData(hash: string, object: any): Promise<void> {
40
+ return Promise.resolve();
41
+ }
42
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Type of the logger
3
+ *
4
+ * @internal
5
+ */
6
+ export type LoggerType = {
7
+ debug: (msg: string, ...args: any[]) => void,
8
+ info: (msg: string, ...args: any[]) => void,
9
+ warn: (msg: string, ...args: any[]) => void,
10
+ error: (msg: string, ...args: any[]) => void
11
+ };
12
+
13
+ /**
14
+ * Getter function to create a logger instance
15
+ *
16
+ * @internal
17
+ */
18
+ export function getLogger(prefix: string): LoggerType {
19
+ return {
20
+ debug: (msg, ...args) => (global as any).atomiqLogLevel >= 3 && console.debug(prefix + msg, ...args),
21
+ info: (msg, ...args) => (global as any).atomiqLogLevel >= 2 && console.info(prefix + msg, ...args),
22
+ warn: (msg, ...args) => ((global as any).atomiqLogLevel == null || (global as any).atomiqLogLevel >= 1) && console.warn(prefix + msg, ...args),
23
+ error: (msg, ...args) => ((global as any).atomiqLogLevel == null || (global as any).atomiqLogLevel >= 0) && console.error(prefix + msg, ...args)
24
+ };
25
+ }
@@ -0,0 +1,73 @@
1
+ import {getLogger} from "./Logger";
2
+ import {timeoutPromise} from "./TimeoutUtils";
3
+
4
+ const logger = getLogger("RetryUtils: ");
5
+
6
+ type Constructor<T = any> = new (...args: any[]) => T;
7
+
8
+ function isConstructor(fn: any): fn is Constructor {
9
+ return (
10
+ typeof fn === 'function' &&
11
+ fn.prototype != null &&
12
+ fn.prototype.constructor === fn
13
+ );
14
+ }
15
+
16
+ function isConstructorArray(fnArr: any): fnArr is Constructor[] {
17
+ return Array.isArray(fnArr) && fnArr.every(isConstructor);
18
+ }
19
+
20
+ /**
21
+ * Checks whether the passed error is allowed to pass through
22
+ *
23
+ * @param e Error in question
24
+ * @param errorAllowed Allowed errors as defined as a callback function, specific error type, or an array of error types
25
+ */
26
+ function checkError(e: any, errorAllowed: ((e: any) => boolean) | Constructor<Error> | Constructor<Error>[]) {
27
+ if (isConstructorArray(errorAllowed)) return errorAllowed.find(error => e instanceof error) != null;
28
+ if (isConstructor(errorAllowed)) return e instanceof errorAllowed;
29
+ return errorAllowed(e);
30
+ }
31
+
32
+ /**
33
+ * Runs the passed function multiple times if it fails
34
+ *
35
+ * @param func A callback for executing the action
36
+ * @param func.retryCount Count of the current retry, starting from 0 for original request and increasing
37
+ * @param retryPolicy Retry policy
38
+ * @param retryPolicy.maxRetries How many retries to attempt in total
39
+ * @param retryPolicy.delay How long should the delay be
40
+ * @param retryPolicy.exponential Whether to use exponentially increasing delays
41
+ * @param errorAllowed A callback for determining whether a given error is allowed, and we should therefore not retry
42
+ * @param abortSignal
43
+ *
44
+ * @returns Result of the action executing callback
45
+ *
46
+ * @internal
47
+ */
48
+ export async function tryWithRetries<T>(func: (retryCount: number) => Promise<T>, retryPolicy?: {
49
+ maxRetries?: number, delay?: number, exponential?: boolean
50
+ }, errorAllowed?: ((e: any) => boolean) | Constructor<Error> | Constructor<Error>[], abortSignal?: AbortSignal): Promise<T> {
51
+ retryPolicy = retryPolicy || {};
52
+ retryPolicy.maxRetries = retryPolicy.maxRetries || 5;
53
+ retryPolicy.delay = retryPolicy.delay || 500;
54
+ retryPolicy.exponential = retryPolicy.exponential == null ? true : retryPolicy.exponential;
55
+
56
+ let err = null;
57
+
58
+ for (let i = 0; i < retryPolicy.maxRetries; i++) {
59
+ try {
60
+ return await func(i);
61
+ } catch (e) {
62
+ if (errorAllowed != null && checkError(e, errorAllowed)) throw e;
63
+ err = e;
64
+ logger.warn("tryWithRetries(): Error on try number: " + i, e);
65
+ }
66
+ if (abortSignal != null && abortSignal.aborted) throw (abortSignal.reason || new Error("Aborted"));
67
+ if (i !== retryPolicy.maxRetries - 1) {
68
+ await timeoutPromise(retryPolicy.exponential ? retryPolicy.delay * Math.pow(2, i) : retryPolicy.delay, abortSignal);
69
+ }
70
+ }
71
+
72
+ throw err;
73
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Returns a promise that resolves after given amount seconds
3
+ *
4
+ * @param timeout how many milliseconds to wait for
5
+ * @param abortSignal
6
+ *
7
+ * @internal
8
+ */
9
+ export function timeoutPromise(timeout: number, abortSignal?: AbortSignal): Promise<void> {
10
+ return new Promise<void>((resolve, reject) => {
11
+ if (abortSignal != null && abortSignal.aborted) {
12
+ reject(abortSignal.reason);
13
+ return;
14
+ }
15
+
16
+ let abortSignalListener: () => void;
17
+ let timeoutHandle: any | null = setTimeout(() => {
18
+ if (abortSignalListener != null && abortSignal != null) abortSignal.removeEventListener("abort", abortSignalListener);
19
+ resolve();
20
+ }, timeout);
21
+
22
+ if (abortSignal != null) {
23
+ abortSignal.addEventListener("abort", abortSignalListener = () => {
24
+ if (timeoutHandle != null) clearTimeout(timeoutHandle);
25
+ timeoutHandle = null;
26
+ reject(abortSignal.reason);
27
+ });
28
+ }
29
+ });
30
+ }
31
+
32
+ /**
33
+ * Returns an abort signal that aborts after a specified timeout in milliseconds
34
+ *
35
+ * @param timeout Milliseconds to wait
36
+ * @param abortReason Abort with this abort reason
37
+ * @param abortSignal Abort signal to extend
38
+ *
39
+ * @internal
40
+ */
41
+ export function timeoutSignal(timeout: number, abortReason?: any, abortSignal?: AbortSignal): AbortSignal {
42
+ if (timeout == null) throw new Error("Timeout seconds cannot be null!");
43
+ const abortController = new AbortController();
44
+ const timeoutHandle = setTimeout(() => abortController.abort(abortReason || new Error("Timed out")), timeout);
45
+ if (abortSignal != null) {
46
+ abortSignal.addEventListener("abort", () => {
47
+ clearTimeout(timeoutHandle);
48
+ abortController.abort(abortSignal.reason);
49
+ });
50
+ }
51
+ return abortController.signal;
52
+ }