@lodestar/utils 1.16.0-dev.5064fab473 → 1.16.0-dev.53f8f99c64

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/lib/format.d.ts CHANGED
@@ -14,4 +14,16 @@ export declare function prettyBytesShort(root: Uint8Array | string): string;
14
14
  * values on explorers like beaconcha.in while improving readability of logs
15
15
  */
16
16
  export declare function truncBytes(root: Uint8Array | string): string;
17
+ /**
18
+ * Format a bigint value as a decimal string
19
+ */
20
+ export declare function formatBigDecimal(numerator: bigint, denominator: bigint, maxDecimalFactor: bigint): string;
21
+ /**
22
+ * Format wei as ETH, with up to 5 decimals and append ' ETH'
23
+ */
24
+ export declare function prettyWeiToEth(wei: bigint): string;
25
+ /**
26
+ * Format milliseconds to time format HH:MM:SS.ms
27
+ */
28
+ export declare function prettyMsToTime(timeMs: number): string;
17
29
  //# sourceMappingURL=format.d.ts.map
package/lib/format.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { toHexString } from "./bytes.js";
2
+ import { ETH_TO_WEI } from "./ethConversion.js";
2
3
  /**
3
4
  * Format bytes as `0x1234…1234`
4
5
  * 4 bytes can represent 4294967296 values, so the chance of collision is low
@@ -24,4 +25,29 @@ export function truncBytes(root) {
24
25
  const str = typeof root === "string" ? root : toHexString(root);
25
26
  return str.slice(0, 14);
26
27
  }
28
+ /**
29
+ * Format a bigint value as a decimal string
30
+ */
31
+ export function formatBigDecimal(numerator, denominator, maxDecimalFactor) {
32
+ const full = numerator / denominator;
33
+ const fraction = ((numerator - full * denominator) * maxDecimalFactor) / denominator;
34
+ // zeros to be added post decimal are number of zeros in maxDecimalFactor - number of digits in fraction
35
+ const zerosPostDecimal = String(maxDecimalFactor).length - 1 - String(fraction).length;
36
+ return `${full}.${"0".repeat(zerosPostDecimal)}${fraction}`;
37
+ }
38
+ // display upto 5 decimal places
39
+ const MAX_DECIMAL_FACTOR = BigInt("100000");
40
+ /**
41
+ * Format wei as ETH, with up to 5 decimals and append ' ETH'
42
+ */
43
+ export function prettyWeiToEth(wei) {
44
+ return `${formatBigDecimal(wei, ETH_TO_WEI, MAX_DECIMAL_FACTOR)} ETH`;
45
+ }
46
+ /**
47
+ * Format milliseconds to time format HH:MM:SS.ms
48
+ */
49
+ export function prettyMsToTime(timeMs) {
50
+ const date = new Date(0, 0, 0, 0, 0, 0, timeMs);
51
+ return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}.${date.getMilliseconds()}`;
52
+ }
27
53
  //# sourceMappingURL=format.js.map
package/lib/format.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,YAAY,CAAC;AAEvC;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAyB;IACnD,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAChE,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAyB;IACxD,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAChE,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAyB;IAClD,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAChE,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,YAAY,CAAC;AACvC,OAAO,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AAE9C;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAyB;IACnD,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAChE,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAyB;IACxD,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAChE,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAyB;IAClD,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAChE,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAiB,EAAE,WAAmB,EAAE,gBAAwB;IAC/F,MAAM,IAAI,GAAG,SAAS,GAAG,WAAW,CAAC;IACrC,MAAM,QAAQ,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI,GAAG,WAAW,CAAC,GAAG,gBAAgB,CAAC,GAAG,WAAW,CAAC;IAErF,wGAAwG;IACxG,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;IACvF,OAAO,GAAG,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,GAAG,QAAQ,EAAE,CAAC;AAC9D,CAAC;AAED,gCAAgC;AAChC,MAAM,kBAAkB,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;AAE5C;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,GAAG,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,kBAAkB,CAAC,MAAM,CAAC;AACxE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IAChD,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,UAAU,EAAE,IAAI,IAAI,CAAC,UAAU,EAAE,IAAI,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;AAClG,CAAC"}
package/lib/metrics.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { NonEmptyArray } from "./types.js";
1
2
  export type NoLabels = Record<string, never>;
2
3
  export type LabelsGeneric = Record<string, string | number>;
3
4
  export type LabelKeys<Labels extends LabelsGeneric> = Extract<keyof Labels, string>;
@@ -30,7 +31,7 @@ export type GaugeConfig<Labels extends LabelsGeneric> = {
30
31
  } & (NoLabels extends Labels ? {
31
32
  labelNames?: never;
32
33
  } : {
33
- labelNames: [LabelKeys<Labels>, ...LabelKeys<Labels>[]];
34
+ labelNames: NonEmptyArray<LabelKeys<Labels>>;
34
35
  });
35
36
  export type HistogramConfig<Labels extends LabelsGeneric> = GaugeConfig<Labels> & {
36
37
  buckets?: number[];
package/lib/promise.d.ts CHANGED
@@ -1,26 +1,45 @@
1
+ import { ArrayToTuple, NonEmptyArray } from "./types.js";
1
2
  /**
2
3
  * While promise t is not finished, call function `fn` per `interval`
3
4
  */
4
5
  export declare function callFnWhenAwait<T>(p: Promise<NonNullable<T>>, fn: () => void, interval: number): Promise<NonNullable<T>>;
5
- export declare enum RaceEvent {
6
- /** all reject/resolve before cutoff */
7
- precutoff = "precutoff-return",
8
- /** cutoff reached as some were pending till cutoff **/
9
- cutoff = "cutoff-reached",
10
- /** atleast one resolved till cutoff so no race required */
11
- resolvedatcutoff = "resolved-at-cutoff",
12
- /** if none reject/resolve before cutoff but one resolves or all reject before timeout */
13
- pretimeout = "pretimeout-return",
14
- /** timeout reached as none resolved and some were pending till timeout*/
15
- timeout = "timeout-reached",
16
- /** promise resolved */
17
- resolved = "resolved",
18
- /** promise rejected */
19
- rejected = "rejected"
20
- }
6
+ export type PromiseResult<T> = {
7
+ promise: Promise<T>;
8
+ } & ({
9
+ status: "pending";
10
+ } | {
11
+ status: "fulfilled";
12
+ value: T;
13
+ durationMs: number;
14
+ } | {
15
+ status: "rejected";
16
+ reason: Error;
17
+ durationMs: number;
18
+ });
19
+ export type PromiseFulfilledResult<T> = PromiseResult<T> & {
20
+ status: "fulfilled";
21
+ };
22
+ export type PromiseRejectedResult<T> = PromiseResult<T> & {
23
+ status: "rejected";
24
+ };
21
25
  /**
22
- * Wait for promises to resolve till cutoff and then race them beyond the cutoff with an overall timeout
23
- * @return resolved values or rejections or still pending errors corresponding to input promises
26
+ * Wrap a promise to an object to track the status and value of the promise
24
27
  */
25
- export declare function racePromisesWithCutoff<T>(promises: Promise<T>[], cutoffMs: number, timeoutMs: number, eventCb: (event: RaceEvent, delayMs: number, index?: number) => void): Promise<(Error | T)[]>;
28
+ export declare function wrapPromise<T>(promise: PromiseLike<T>): PromiseResult<T>;
29
+ type ReturnPromiseWithTuple<Tuple extends NonEmptyArray<PromiseLike<unknown>>> = {
30
+ [Index in keyof ArrayToTuple<Tuple>]: PromiseResult<Awaited<Tuple[Index]>>;
31
+ };
32
+ /**
33
+ * Two phased approach for resolving promises:
34
+ * - first wait `resolveTimeoutMs` or until all promises settle
35
+ * - then wait `raceTimeoutMs - resolveTimeoutMs` or until at least a single promise resolves
36
+ *
37
+ * Returns a list of promise results, see `PromiseResult`
38
+ */
39
+ export declare function resolveOrRacePromises<T extends NonEmptyArray<PromiseLike<unknown>>>(promises: T, { resolveTimeoutMs, raceTimeoutMs, signal, }: {
40
+ resolveTimeoutMs: number;
41
+ raceTimeoutMs: number;
42
+ signal?: AbortSignal;
43
+ }): Promise<ReturnPromiseWithTuple<T>> | never;
44
+ export {};
26
45
  //# sourceMappingURL=promise.d.ts.map
package/lib/promise.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { ErrorAborted, TimeoutError } from "./errors.js";
1
2
  import { sleep } from "./sleep.js";
2
3
  /**
3
4
  * While promise t is not finished, call function `fn` per `interval`
@@ -19,100 +20,78 @@ export async function callFnWhenAwait(p, fn, interval) {
19
20
  }
20
21
  return t;
21
22
  }
22
- var PromiseStatus;
23
- (function (PromiseStatus) {
24
- PromiseStatus[PromiseStatus["resolved"] = 0] = "resolved";
25
- PromiseStatus[PromiseStatus["rejected"] = 1] = "rejected";
26
- PromiseStatus[PromiseStatus["pending"] = 2] = "pending";
27
- })(PromiseStatus || (PromiseStatus = {}));
28
- function mapStatusesToResponses(promisesStates) {
29
- return promisesStates.map((pmStatus) => {
30
- switch (pmStatus.status) {
31
- case PromiseStatus.resolved:
32
- return pmStatus.value;
33
- case PromiseStatus.rejected:
34
- return pmStatus.value;
35
- case PromiseStatus.pending:
36
- return Error("pending");
37
- }
38
- });
23
+ /**
24
+ * Wrap a promise to an object to track the status and value of the promise
25
+ */
26
+ export function wrapPromise(promise) {
27
+ const startedAt = Date.now();
28
+ const result = {
29
+ promise: promise.then((value) => {
30
+ result.status = "fulfilled";
31
+ result.value = value;
32
+ result.durationMs = Date.now() - startedAt;
33
+ return value;
34
+ }, (reason) => {
35
+ result.status = "rejected";
36
+ result.reason = reason;
37
+ result.durationMs = Date.now() - startedAt;
38
+ throw reason;
39
+ }),
40
+ status: "pending",
41
+ };
42
+ return result;
39
43
  }
40
- export var RaceEvent;
41
- (function (RaceEvent) {
42
- /** all reject/resolve before cutoff */
43
- RaceEvent["precutoff"] = "precutoff-return";
44
- /** cutoff reached as some were pending till cutoff **/
45
- RaceEvent["cutoff"] = "cutoff-reached";
46
- /** atleast one resolved till cutoff so no race required */
47
- RaceEvent["resolvedatcutoff"] = "resolved-at-cutoff";
48
- /** if none reject/resolve before cutoff but one resolves or all reject before timeout */
49
- RaceEvent["pretimeout"] = "pretimeout-return";
50
- /** timeout reached as none resolved and some were pending till timeout*/
51
- RaceEvent["timeout"] = "timeout-reached";
52
- // events for the promises for better tracking
53
- /** promise resolved */
54
- RaceEvent["resolved"] = "resolved";
55
- /** promise rejected */
56
- RaceEvent["rejected"] = "rejected";
57
- })(RaceEvent || (RaceEvent = {}));
58
44
  /**
59
- * Wait for promises to resolve till cutoff and then race them beyond the cutoff with an overall timeout
60
- * @return resolved values or rejections or still pending errors corresponding to input promises
45
+ * Two phased approach for resolving promises:
46
+ * - first wait `resolveTimeoutMs` or until all promises settle
47
+ * - then wait `raceTimeoutMs - resolveTimeoutMs` or until at least a single promise resolves
48
+ *
49
+ * Returns a list of promise results, see `PromiseResult`
61
50
  */
62
- export async function racePromisesWithCutoff(promises, cutoffMs, timeoutMs, eventCb) {
63
- // start the cutoff and timeout timers
64
- let cutoffObserved = false;
65
- const cutoffPromise = sleep(cutoffMs).then(() => {
66
- cutoffObserved = true;
67
- });
68
- let timeoutObserved = false;
69
- const timeoutPromise = sleep(timeoutMs).then(() => {
70
- timeoutObserved = true;
71
- });
72
- const startTime = Date.now();
73
- // Track promises status and resolved values/rejected errors
74
- // Even if the promises reject with the following decoration promises will not throw
75
- const promisesStates = [];
76
- promises.forEach((promise, index) => {
77
- promisesStates[index] = { status: PromiseStatus.pending, value: null };
78
- promise
79
- .then((value) => {
80
- eventCb(RaceEvent.resolved, Date.now() - startTime, index);
81
- promisesStates[index] = { status: PromiseStatus.resolved, value };
82
- })
83
- .catch((e) => {
84
- eventCb(RaceEvent.rejected, Date.now() - startTime, index);
85
- promisesStates[index] = { status: PromiseStatus.rejected, value: e };
86
- });
87
- });
88
- // Wait till cutoff time unless all original promises resolve/reject early
89
- await Promise.allSettled(promises.map((promise) => Promise.race([promise, cutoffPromise])));
90
- if (cutoffObserved) {
91
- // If any is resolved, then just simply return as we are post cutoff
92
- const anyResolved = promisesStates.reduce((acc, pmState) => acc || pmState.status === PromiseStatus.resolved, false);
93
- if (anyResolved) {
94
- eventCb(RaceEvent.resolvedatcutoff, Date.now() - startTime);
95
- return mapStatusesToResponses(promisesStates);
51
+ export async function resolveOrRacePromises(promises, { resolveTimeoutMs, raceTimeoutMs, signal, }) {
52
+ if (raceTimeoutMs <= resolveTimeoutMs) {
53
+ throw new Error("Race time must be greater than resolve time");
54
+ }
55
+ const resolveTimeoutError = new TimeoutError(`Given promises can't be resolved within resolveTimeoutMs=${resolveTimeoutMs}`);
56
+ const raceTimeoutError = new TimeoutError(`Not a any single promise be resolved in given raceTimeoutMs=${raceTimeoutMs}`);
57
+ const promiseResults = promises.map((p) => wrapPromise(p));
58
+ // We intentionally want an array of promises here
59
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
60
+ promises = promiseResults.map((p) => p.promise);
61
+ try {
62
+ await Promise.race([
63
+ Promise.allSettled(promises),
64
+ sleep(resolveTimeoutMs, signal).then(() => {
65
+ throw resolveTimeoutError;
66
+ }),
67
+ ]);
68
+ return promiseResults;
69
+ }
70
+ catch (err) {
71
+ if (err instanceof ErrorAborted) {
72
+ return promiseResults;
96
73
  }
97
- else {
98
- eventCb(RaceEvent.cutoff, Date.now() - startTime);
74
+ if (err !== resolveTimeoutError) {
75
+ throw err;
99
76
  }
100
77
  }
101
- else {
102
- eventCb(RaceEvent.precutoff, Date.now() - startTime);
103
- return mapStatusesToResponses(promisesStates);
104
- }
105
- // Post deadline resolve with any of the promise or all rejected before timeout
106
- await Promise.any(promises.map((promise) => Promise.race([promise, timeoutPromise]))).catch(
107
- // just ignore if all reject as we will returned mapped rejections
108
- // eslint-disable-next-line @typescript-eslint/no-empty-function
109
- (_e) => { });
110
- if (timeoutObserved) {
111
- eventCb(RaceEvent.timeout, Date.now() - startTime);
78
+ try {
79
+ await Promise.race([
80
+ Promise.any(promises),
81
+ sleep(raceTimeoutMs - resolveTimeoutMs, signal).then(() => {
82
+ throw raceTimeoutError;
83
+ }),
84
+ ]);
85
+ return promiseResults;
112
86
  }
113
- else {
114
- eventCb(RaceEvent.pretimeout, Date.now() - startTime);
87
+ catch (err) {
88
+ if (err instanceof ErrorAborted) {
89
+ return promiseResults;
90
+ }
91
+ if (err !== raceTimeoutError && !(err instanceof AggregateError)) {
92
+ throw err;
93
+ }
115
94
  }
116
- return mapStatusesToResponses(promisesStates);
95
+ return promiseResults;
117
96
  }
118
97
  //# sourceMappingURL=promise.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"promise.js","sourceRoot":"","sources":["../src/promise.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"promise.js","sourceRoot":"","sources":["../src/promise.ts"],"names":[],"mappings":"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"}
package/lib/retry.d.ts CHANGED
@@ -4,11 +4,17 @@ export type RetryOptions = {
4
4
  */
5
5
  retries?: number;
6
6
  /**
7
- * An optional Function that is invoked after the provided callback throws
8
- * It expects a boolean to know if it should retry or not
9
- * Useful to make retrying conditional on the type of error thrown
7
+ * An optional Function that is invoked after the provided callback throws.
8
+ * It expects a boolean to know if it should retry or not.
9
+ * Useful to make retrying conditional on the type of error thrown.
10
10
  */
11
11
  shouldRetry?: (lastError: Error) => boolean;
12
+ /**
13
+ * An optional Function that is invoked right before a retry is performed.
14
+ * It's passed the Error that triggered it and a number identifying the attempt.
15
+ * Useful to track number of retries and errors in logs or metrics.
16
+ */
17
+ onRetry?: (lastError: Error, attempt: number) => unknown;
12
18
  /**
13
19
  * Milliseconds to wait before retrying again
14
20
  */
package/lib/retry.js CHANGED
@@ -7,15 +7,25 @@ import { sleep } from "./sleep.js";
7
7
  */
8
8
  export async function retry(fn, opts) {
9
9
  const maxRetries = opts?.retries ?? 5;
10
+ // Number of retries + the initial attempt
11
+ const maxAttempts = maxRetries + 1;
10
12
  const shouldRetry = opts?.shouldRetry;
13
+ const onRetry = opts?.onRetry;
11
14
  let lastError = Error("RetryError");
12
- for (let i = 1; i <= maxRetries; i++) {
15
+ for (let i = 1; i <= maxAttempts; i++) {
13
16
  try {
17
+ // If not the first attempt, invoke right before retrying
18
+ if (i > 1)
19
+ onRetry?.(lastError, i);
14
20
  return await fn(i);
15
21
  }
16
22
  catch (e) {
17
23
  lastError = e;
18
- if (shouldRetry && !shouldRetry(lastError)) {
24
+ if (i === maxAttempts) {
25
+ // Reached maximum number of attempts, there's no need to check if we should retry
26
+ break;
27
+ }
28
+ else if (shouldRetry && !shouldRetry(lastError)) {
19
29
  break;
20
30
  }
21
31
  else if (opts?.retryDelay !== undefined) {
package/lib/retry.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAoBjC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAI,EAAuC,EAAE,IAAmB;IACzF,MAAM,UAAU,GAAG,IAAI,EAAE,OAAO,IAAI,CAAC,CAAC;IACtC,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,CAAC;IAEtC,IAAI,SAAS,GAAU,KAAK,CAAC,YAAY,CAAC,CAAC;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC,EAAE,EAAE;QACpC,IAAI;YACF,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;SACpB;QAAC,OAAO,CAAC,EAAE;YACV,SAAS,GAAG,CAAU,CAAC;YACvB,IAAI,WAAW,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE;gBAC1C,MAAM;aACP;iBAAM,IAAI,IAAI,EAAE,UAAU,KAAK,SAAS,EAAE;gBACzC,MAAM,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;aAC7C;SACF;KACF;IACD,MAAM,SAAS,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AA0BjC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAI,EAAuC,EAAE,IAAmB;IACzF,MAAM,UAAU,GAAG,IAAI,EAAE,OAAO,IAAI,CAAC,CAAC;IACtC,0CAA0C;IAC1C,MAAM,WAAW,GAAG,UAAU,GAAG,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,CAAC;IAE9B,IAAI,SAAS,GAAU,KAAK,CAAC,YAAY,CAAC,CAAC;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC,EAAE,EAAE;QACrC,IAAI;YACF,yDAAyD;YACzD,IAAI,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;YAEnC,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;SACpB;QAAC,OAAO,CAAC,EAAE;YACV,SAAS,GAAG,CAAU,CAAC;YAEvB,IAAI,CAAC,KAAK,WAAW,EAAE;gBACrB,kFAAkF;gBAClF,MAAM;aACP;iBAAM,IAAI,WAAW,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE;gBACjD,MAAM;aACP;iBAAM,IAAI,IAAI,EAAE,UAAU,KAAK,SAAS,EAAE;gBACzC,MAAM,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;aAC7C;SACF;KACF;IACD,MAAM,SAAS,CAAC;AAClB,CAAC"}
package/lib/sleep.js CHANGED
@@ -10,7 +10,6 @@ export async function sleep(ms, signal) {
10
10
  return new Promise((resolve, reject) => {
11
11
  if (signal && signal.aborted)
12
12
  return reject(new ErrorAborted());
13
- // eslint-disable-next-line @typescript-eslint/no-empty-function
14
13
  let onDone = () => { };
15
14
  const timeout = setTimeout(() => {
16
15
  onDone();
package/lib/sleep.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sleep.js","sourceRoot":"","sources":["../src/sleep.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAEzC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,EAAU,EAAE,MAAoB;IAC1D,IAAI,EAAE,GAAG,CAAC,EAAE;QACV,OAAO;KACR;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC;QAEhE,gEAAgE;QAChE,IAAI,MAAM,GAAe,GAAG,EAAE,GAAE,CAAC,CAAC;QAElC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,MAAM,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC;QAC7B,CAAC,CAAC;QACF,IAAI,MAAM;YAAE,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAEtD,MAAM,GAAG,GAAG,EAAE;YACZ,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,IAAI,MAAM;gBAAE,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3D,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"sleep.js","sourceRoot":"","sources":["../src/sleep.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAEzC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,EAAU,EAAE,MAAoB;IAC1D,IAAI,EAAE,GAAG,CAAC,EAAE;QACV,OAAO;KACR;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC;QAEhE,IAAI,MAAM,GAAe,GAAG,EAAE,GAAE,CAAC,CAAC;QAElC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,MAAM,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC;QAC7B,CAAC,CAAC;QACF,IAAI,MAAM;YAAE,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAEtD,MAAM,GAAG,GAAG,EAAE;YACZ,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,IAAI,MAAM;gBAAE,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3D,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
package/lib/types.d.ts CHANGED
@@ -7,4 +7,13 @@ export type RecursivePartial<T> = {
7
7
  };
8
8
  /** Type safe wrapper for Number constructor that takes 'any' */
9
9
  export declare function bnToNum(bn: bigint): number;
10
+ export type NonEmptyArray<T> = [T, ...T[]];
11
+ /**
12
+ * ArrayToTuple converts an `Array<T>` to `[T, ...T]`
13
+ *
14
+ * eg: `[1, 2, 3]` from type `number[]` to `[number, number, number]`
15
+ */
16
+ export type ArrayToTuple<Tuple extends NonEmptyArray<unknown>> = {
17
+ [Index in keyof Tuple]: Tuple[Index];
18
+ };
10
19
  //# sourceMappingURL=types.d.ts.map
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "bugs": {
12
12
  "url": "https://github.com/ChainSafe/lodestar/issues"
13
13
  },
14
- "version": "1.16.0-dev.5064fab473",
14
+ "version": "1.16.0-dev.53f8f99c64",
15
15
  "type": "module",
16
16
  "exports": "./lib/index.js",
17
17
  "files": [
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "types": "lib/index.d.ts",
41
41
  "dependencies": {
42
- "@chainsafe/as-sha256": "^0.3.1",
42
+ "@chainsafe/as-sha256": "^0.4.1",
43
43
  "any-signal": "3.0.1",
44
44
  "bigint-buffer": "^1.1.5",
45
45
  "case": "^1.6.3",
@@ -58,5 +58,5 @@
58
58
  "beacon",
59
59
  "blockchain"
60
60
  ],
61
- "gitHead": "6d5a6d4fd1714586ee4acda1b2aaaf7d65bdc039"
61
+ "gitHead": "2536a9754d55fac8d093d83e8ee9c8428bfddf4d"
62
62
  }