@lightsparkdev/core 1.0.9 → 1.0.11

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.
@@ -7,26 +7,53 @@ declare function createSha256Hash(data: SourceData): Promise<Uint8Array>;
7
7
  declare function createSha256Hash(data: SourceData, asHex: true): Promise<string>;
8
8
 
9
9
  declare const defaultCurrencyCode = "USD";
10
- /** This enum identifies the unit of currency associated with a CurrencyAmount. **/
10
+ /**
11
+ * This enum identifies the unit of currency associated with a CurrencyAmount.
12
+ * *
13
+ */
11
14
  declare enum CurrencyUnit {
12
15
  /**
13
- * This is an enum value that represents values that could be added in the future.
14
- * Clients should support unknown values as more of them could be added without notice.
16
+ * This is an enum value that represents values that could be added in the
17
+ * future. Clients should support unknown values as more of them could be
18
+ * added without notice.
15
19
  */
16
20
  FUTURE_VALUE = "FUTURE_VALUE",
17
- /** Bitcoin is the cryptocurrency native to the Bitcoin network. It is used as the native medium for value transfer for the Lightning Network. **/
21
+ /**
22
+ * Bitcoin is the cryptocurrency native to the Bitcoin network.
23
+ * It is used as the native medium for value transfer for the Lightning
24
+ * Network. *
25
+ */
18
26
  BITCOIN = "BITCOIN",
19
- /** 0.00000001 (10e-8) Bitcoin or one hundred millionth of a Bitcoin. This is the unit most commonly used in Lightning transactions. **/
27
+ /**
28
+ * 0.00000001 (10e-8) Bitcoin or one hundred millionth of a Bitcoin.
29
+ * This is the unit most commonly used in Lightning transactions.
30
+ * *
31
+ */
20
32
  SATOSHI = "SATOSHI",
21
- /** 0.001 Satoshi, or 10e-11 Bitcoin. We recommend using the Satoshi unit instead when possible. **/
33
+ /**
34
+ * 0.001 Satoshi, or 10e-11 Bitcoin. We recommend using the Satoshi unit
35
+ * instead when possible. *
36
+ */
22
37
  MILLISATOSHI = "MILLISATOSHI",
23
38
  /** United States Dollar. **/
24
39
  USD = "USD",
25
- /** 0.000000001 (10e-9) Bitcoin or a billionth of a Bitcoin. We recommend using the Satoshi unit instead when possible. **/
40
+ /**
41
+ * 0.000000001 (10e-9) Bitcoin or a billionth of a Bitcoin.
42
+ * We recommend using the Satoshi unit instead when possible.
43
+ * *
44
+ */
26
45
  NANOBITCOIN = "NANOBITCOIN",
27
- /** 0.000001 (10e-6) Bitcoin or a millionth of a Bitcoin. We recommend using the Satoshi unit instead when possible. **/
46
+ /**
47
+ * 0.000001 (10e-6) Bitcoin or a millionth of a Bitcoin.
48
+ * We recommend using the Satoshi unit instead when possible.
49
+ * *
50
+ */
28
51
  MICROBITCOIN = "MICROBITCOIN",
29
- /** 0.001 (10e-3) Bitcoin or a thousandth of a Bitcoin. We recommend using the Satoshi unit instead when possible. **/
52
+ /**
53
+ * 0.001 (10e-3) Bitcoin or a thousandth of a Bitcoin.
54
+ * We recommend using the Satoshi unit instead when possible.
55
+ * *
56
+ */
30
57
  MILLIBITCOIN = "MILLIBITCOIN"
31
58
  }
32
59
  /** This object represents the value and unit for an amount of currency. **/
@@ -38,13 +65,15 @@ type CurrencyAmountType = {
38
65
  /** The unit of user's preferred currency. **/
39
66
  preferredCurrencyUnit: CurrencyUnit;
40
67
  /**
41
- * The rounded numeric value for this CurrencyAmount in the very base level of user's preferred
42
- * currency. For example, for USD, the value will be in cents.
68
+ * The rounded numeric value for this CurrencyAmount in the very base level
69
+ * of user's preferred currency. For example, for USD, the value will be in
70
+ * cents.
43
71
  **/
44
72
  preferredCurrencyValueRounded: number;
45
73
  /**
46
- * The approximate float value for this CurrencyAmount in the very base level of user's preferred
47
- * currency. For example, for USD, the value will be in cents.
74
+ * The approximate float value for this CurrencyAmount in the very base level
75
+ * of user's preferred currency. For example, for USD, the value will be in
76
+ * cents.
48
77
  **/
49
78
  preferredCurrencyValueApprox: number;
50
79
  };
@@ -192,13 +221,14 @@ declare function linearInterpolate(value: number, fromRangeStart: number, fromRa
192
221
  declare function round(num: number, decimalPlaces?: number): number;
193
222
  declare function isNumber(value: unknown): value is number;
194
223
 
195
- declare function pollUntil<D extends () => Promise<unknown>, T>(asyncFn: D, getValue: (data: Awaited<ReturnType<D>>, response: {
224
+ type GetValueResult<T> = {
196
225
  stopPolling: boolean;
197
226
  value: null | T;
198
- }) => {
227
+ };
228
+ declare function pollUntil<D extends () => Promise<unknown>, T>(asyncFn: D, getValue: (data: Awaited<ReturnType<D>>, response: {
199
229
  stopPolling: boolean;
200
230
  value: null | T;
201
- }, maxPolls?: number, pollIntervalMs?: number, ignoreErrors?: boolean | ((e: unknown) => boolean), getMaxPollsError?: (maxPolls: number) => Error): Promise<T>;
231
+ }) => GetValueResult<T>, maxPolls?: number, pollIntervalMs?: number, ignoreErrors?: boolean | ((e: unknown) => boolean), getMaxPollsError?: (maxPolls: number) => Error): Promise<T>;
202
232
 
203
233
  declare function sleep(ms: number): Promise<unknown>;
204
234
 
@@ -215,5 +245,8 @@ declare const isType: <T extends string>(typename: T) => <N extends {
215
245
  }>(node: N | null | undefined) => node is Extract<N, {
216
246
  __typename: T;
217
247
  }>;
248
+ type DeepPartial<T> = T extends object ? {
249
+ [P in keyof T]?: DeepPartial<T[P]>;
250
+ } : T;
218
251
 
219
- export { ById, CurrencyAmountArg, CurrencyAmountObj, CurrencyAmountType, CurrencyCodes, CurrencyLocales, CurrencyMap, CurrencyUnit, ExpandRecursively, Maybe, OmitTypename, abbrCurrencyUnit, b64decode, b64encode, bytesToHex, clamp, convertCurrencyAmount, convertCurrencyAmountValue, countryCodesToCurrencyCodes, createSha256Hash, defaultCurrencyCode, formatCurrencyStr, getCurrentLocale, getErrorMsg, hexToBytes, isBrowser, isCurrencyAmount, isCurrencyAmountObj, isCurrencyMap, isError, isErrorMsg, isErrorWithMessage, isNode, isNumber, isTest, isType, linearInterpolate, localeToCurrencyCode, localeToCurrencySymbol, mapCurrencyAmount, pollUntil, round, separateCurrencyStrParts, sleep, urlsafe_b64decode };
252
+ export { ById, CurrencyAmountArg, CurrencyAmountObj, CurrencyAmountType, CurrencyCodes, CurrencyLocales, CurrencyMap, CurrencyUnit, DeepPartial, ExpandRecursively, Maybe, OmitTypename, abbrCurrencyUnit, b64decode, b64encode, bytesToHex, clamp, convertCurrencyAmount, convertCurrencyAmountValue, countryCodesToCurrencyCodes, createSha256Hash, defaultCurrencyCode, formatCurrencyStr, getCurrentLocale, getErrorMsg, hexToBytes, isBrowser, isCurrencyAmount, isCurrencyAmountObj, isCurrencyMap, isError, isErrorMsg, isErrorWithMessage, isNode, isNumber, isTest, isType, linearInterpolate, localeToCurrencyCode, localeToCurrencySymbol, mapCurrencyAmount, pollUntil, round, separateCurrencyStrParts, sleep, urlsafe_b64decode };
@@ -34,7 +34,7 @@ import {
34
34
  separateCurrencyStrParts,
35
35
  sleep,
36
36
  urlsafe_b64decode
37
- } from "../chunk-UU6SHVGX.js";
37
+ } from "../chunk-F3XHLUGC.js";
38
38
  export {
39
39
  CurrencyUnit,
40
40
  abbrCurrencyUnit,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightsparkdev/core",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "Lightspark JS SDK",
5
5
  "author": "Lightspark Inc.",
6
6
  "keywords": [
@@ -61,7 +61,7 @@
61
61
  ],
62
62
  "scripts": {
63
63
  "build": "yarn tsc && tsup",
64
- "build:watch": "yarn build --watch",
64
+ "build:watch": "yarn build --watch --clean=false",
65
65
  "clean": "rm -rf .turbo && rm -rf dist",
66
66
  "dev": "yarn build -- --watch",
67
67
  "format:fix": "prettier src --write",
@@ -96,11 +96,11 @@
96
96
  "eslint": "^8.3.0",
97
97
  "eslint-watch": "^8.0.0",
98
98
  "jest": "^29.6.2",
99
- "prettier": "3.0.2",
100
- "prettier-plugin-organize-imports": "^3.2.2",
99
+ "prettier": "3.0.3",
100
+ "prettier-plugin-organize-imports": "^3.2.4",
101
101
  "ts-jest": "^29.1.1",
102
102
  "tsc-absolute": "^1.0.1",
103
- "tsup": "^6.7.0",
104
- "typescript": "^4.9.5"
103
+ "tsup": "^7.2.0",
104
+ "typescript": "^5.0.0"
105
105
  }
106
106
  }
package/src/Logger.ts CHANGED
@@ -9,7 +9,7 @@ export class Logger {
9
9
 
10
10
  constructor(loggerContext: string, getLoggingEnabled?: GetLoggingEnabled) {
11
11
  this.context = loggerContext;
12
- this.updateLoggingEnabled(getLoggingEnabled);
12
+ void this.updateLoggingEnabled(getLoggingEnabled);
13
13
  }
14
14
 
15
15
  async updateLoggingEnabled(getLoggingEnabled: GetLoggingEnabled) {
@@ -4,14 +4,13 @@ import type AuthProvider from "./AuthProvider.js";
4
4
  import { type Headers, type WsConnectionParams } from "./AuthProvider.js";
5
5
 
6
6
  export default class StubAuthProvider implements AuthProvider {
7
- async addAuthHeaders(headers: Headers) {
8
- return headers;
7
+ addAuthHeaders(headers: Headers) {
8
+ return Promise.resolve(headers);
9
9
  }
10
- async isAuthorized(): Promise<boolean> {
11
- return false;
10
+ isAuthorized(): Promise<boolean> {
11
+ return Promise.resolve(false);
12
12
  }
13
-
14
- async addWsConnectionParams(params: WsConnectionParams) {
15
- return params;
13
+ addWsConnectionParams(params: WsConnectionParams) {
14
+ return Promise.resolve(params);
16
15
  }
17
16
  }
@@ -117,6 +117,8 @@ const deriveKey = async (
117
117
  return [key, iv];
118
118
  };
119
119
 
120
+ type Header = { v: number; i: number; lsv?: number };
121
+
120
122
  const decrypt = async (
121
123
  header_json: string,
122
124
  ciphertext: string,
@@ -124,7 +126,7 @@ const decrypt = async (
124
126
  ): Promise<ArrayBuffer> => {
125
127
  let decoded = b64decode(ciphertext);
126
128
 
127
- let header;
129
+ let header: Header;
128
130
  if (header_json === "AES_256_CBC_PBKDF2_5000_SHA256") {
129
131
  header = {
130
132
  v: 0,
@@ -133,13 +135,13 @@ const decrypt = async (
133
135
  // Strip "Salted__" prefix
134
136
  decoded = decoded.slice(8);
135
137
  } else {
136
- header = JSON.parse(header_json);
138
+ header = JSON.parse(header_json) as Header;
137
139
  }
138
140
 
139
141
  if (header.v < 0 || header.v > 4) {
140
142
  throw new LightsparkException(
141
143
  "DecryptionError",
142
- "Unknown version ".concat(header.v),
144
+ `Unknown version ${header.v}`,
143
145
  );
144
146
  }
145
147
 
@@ -152,8 +154,7 @@ const decrypt = async (
152
154
  const salt = decoded.slice(decoded.length - 8, decoded.length);
153
155
  const nonce = decoded.slice(0, 12);
154
156
  const cipherText = decoded.slice(12, decoded.length - 8);
155
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
156
- const [key, _iv] = await deriveKey(
157
+ const [key /* , _iv */] = await deriveKey(
157
158
  password,
158
159
  salt,
159
160
  header.i,
@@ -244,7 +245,7 @@ const sign = async (
244
245
  name: "RSA-PSS",
245
246
  saltLength: 32,
246
247
  },
247
- keyOrAlias as CryptoKey,
248
+ keyOrAlias,
248
249
  data,
249
250
  );
250
251
  };
@@ -1,8 +1,8 @@
1
1
  // Copyright ©, 2023-present, Lightspark Group, Inc. - All Rights Reserved
2
2
 
3
- export * from "./crypto.js";
4
3
  export * from "./KeyOrAlias.js";
5
4
  export { default as LightsparkSigningException } from "./LightsparkSigningException.js";
6
5
  export { default as NodeKeyCache } from "./NodeKeyCache.js";
7
6
  export * from "./SigningKey.js";
7
+ export * from "./crypto.js";
8
8
  export * from "./types.js";
@@ -0,0 +1,21 @@
1
+ import { describe, expect, test } from "@jest/globals";
2
+ import { DefaultCrypto, b64encode } from "../../index.js";
3
+
4
+ describe("Crypto tests", () => {
5
+ test("should generate a key", async () => {
6
+ const { privateKey, publicKey } =
7
+ await DefaultCrypto.generateSigningKeyPair();
8
+
9
+ const serializedKeypair = {
10
+ privateKey: b64encode(
11
+ await DefaultCrypto.serializeSigningKey(privateKey, "pkcs8"),
12
+ ),
13
+ publicKey: b64encode(
14
+ await DefaultCrypto.serializeSigningKey(publicKey, "spki"),
15
+ ),
16
+ };
17
+
18
+ expect(serializedKeypair.privateKey).not.toBeNull();
19
+ expect(serializedKeypair.publicKey).not.toBeNull();
20
+ }, 60_000);
21
+ });
package/src/index.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  // Copyright ©, 2023-present, Lightspark Group, Inc. - All Rights Reserved
2
2
 
3
- export * from "./auth/index.js";
4
- export * from "./constants/index.js";
5
- export * from "./crypto/index.js";
6
3
  export { default as LightsparkException } from "./LightsparkException.js";
7
4
  export { Logger } from "./Logger.js";
8
- export * from "./requester/index.js";
9
5
  export {
10
- apiDomainForEnvironment,
11
6
  default as ServerEnvironment,
7
+ apiDomainForEnvironment,
12
8
  } from "./ServerEnvironment.js";
9
+ export * from "./auth/index.js";
10
+ export * from "./constants/index.js";
11
+ export * from "./crypto/index.js";
12
+ export * from "./requester/index.js";
13
13
  export * from "./utils/index.js";
@@ -7,7 +7,10 @@ type Query<T> = {
7
7
  /** The variables that will be passed to the query. **/
8
8
  variables?: { [key: string]: unknown };
9
9
 
10
- /** The function that will be called to construct the object from the response. **/
10
+ /**
11
+ * The function that will be called to construct the object from the
12
+ * response. *
13
+ */
11
14
  constructObject: (rawData: any) => T; // eslint-disable-line @typescript-eslint/no-explicit-any -- LIG-3400
12
15
 
13
16
  /** The id of the node that will be used to sign the query. **/
@@ -26,6 +26,14 @@ export const LIGHTSPARK_BETA_HEADER_VALUE =
26
26
  "z2h0BBYxTA83cjW7fi8QwWtBPCzkQKiemcuhKY08LOo";
27
27
  dayjs.extend(utc);
28
28
 
29
+ type BodyData = {
30
+ query: string;
31
+ variables: { [key: string]: unknown };
32
+ operationName: string;
33
+ nonce?: number;
34
+ expires_at?: string;
35
+ };
36
+
29
37
  class Requester {
30
38
  private readonly wsClient: WsClient;
31
39
  constructor(
@@ -55,6 +63,7 @@ class Requester {
55
63
  }
56
64
 
57
65
  public async executeQuery<T>(query: Query<T>): Promise<T | null> {
66
+ /* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- LIG-3400 */
58
67
  const data = await this.makeRawRequest(
59
68
  query.queryPayload,
60
69
  query.variables || {},
@@ -89,7 +98,7 @@ class Requester {
89
98
  }
90
99
  }
91
100
  const operation = operationMatch[2];
92
- const bodyData = {
101
+ const bodyData: BodyData = {
93
102
  query: queryPayload,
94
103
  variables,
95
104
  operationName: operation,
@@ -111,7 +120,7 @@ class Requester {
111
120
  signingNodeId: string | undefined = undefined,
112
121
  skipAuth: boolean = false,
113
122
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any -- LIG-3400 */
114
- ): Promise<any | null> {
123
+ ): Promise<any> {
115
124
  const operationNameRegex = /^\s*(query|mutation|subscription)\s+(\w+)/i;
116
125
  const operationMatch = queryPayload.match(operationNameRegex);
117
126
  if (!operationMatch || operationMatch.length < 3) {
@@ -131,7 +140,7 @@ class Requester {
131
140
  }
132
141
  }
133
142
  const operation = operationMatch[2];
134
- let bodyData = {
143
+ let bodyData: BodyData = {
135
144
  query: queryPayload,
136
145
  variables,
137
146
  operationName: operation,
@@ -166,6 +175,7 @@ class Requester {
166
175
 
167
176
  logger.info(`Requester.makeRawRequest`, {
168
177
  url,
178
+ operationName: operation,
169
179
  variables,
170
180
  });
171
181
  const response = await fetch(url, {
@@ -179,7 +189,10 @@ class Requester {
179
189
  `Request ${operation} failed. ${response.statusText}`,
180
190
  );
181
191
  }
182
- const responseJson = await response.json();
192
+ const responseJson = (await response.json()) as {
193
+ data: unknown;
194
+ errors: unknown;
195
+ };
183
196
  const data = responseJson.data;
184
197
  if (!data) {
185
198
  throw new LightsparkException(
@@ -201,11 +214,11 @@ class Requester {
201
214
  }
202
215
 
203
216
  private async addSigningDataIfNeeded(
204
- queryPayload: { query: string; variables: unknown; operationName: string },
217
+ queryPayload: BodyData,
205
218
  headers: { [key: string]: string },
206
219
  signingNodeId: string | undefined,
207
220
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any -- LIG-3400 */
208
- ): Promise<any> {
221
+ ): Promise<BodyData> {
209
222
  if (!signingNodeId) {
210
223
  return queryPayload;
211
224
  }
@@ -225,7 +238,7 @@ class Requester {
225
238
  expires_at: expiration,
226
239
  };
227
240
 
228
- const key = await this.nodeKeyCache.getKey(signingNodeId);
241
+ const key = this.nodeKeyCache.getKey(signingNodeId);
229
242
  if (!key) {
230
243
  throw new LightsparkSigningException(
231
244
  "Missing node of encrypted_signing_private_key",
@@ -7,26 +7,53 @@ import { isNumber, round } from "./numbers.js";
7
7
 
8
8
  export const defaultCurrencyCode = "USD";
9
9
 
10
- /** This enum identifies the unit of currency associated with a CurrencyAmount. **/
10
+ /**
11
+ * This enum identifies the unit of currency associated with a CurrencyAmount.
12
+ * *
13
+ */
11
14
  export enum CurrencyUnit {
12
15
  /**
13
- * This is an enum value that represents values that could be added in the future.
14
- * Clients should support unknown values as more of them could be added without notice.
16
+ * This is an enum value that represents values that could be added in the
17
+ * future. Clients should support unknown values as more of them could be
18
+ * added without notice.
15
19
  */
16
20
  FUTURE_VALUE = "FUTURE_VALUE",
17
- /** Bitcoin is the cryptocurrency native to the Bitcoin network. It is used as the native medium for value transfer for the Lightning Network. **/
21
+ /**
22
+ * Bitcoin is the cryptocurrency native to the Bitcoin network.
23
+ * It is used as the native medium for value transfer for the Lightning
24
+ * Network. *
25
+ */
18
26
  BITCOIN = "BITCOIN",
19
- /** 0.00000001 (10e-8) Bitcoin or one hundred millionth of a Bitcoin. This is the unit most commonly used in Lightning transactions. **/
27
+ /**
28
+ * 0.00000001 (10e-8) Bitcoin or one hundred millionth of a Bitcoin.
29
+ * This is the unit most commonly used in Lightning transactions.
30
+ * *
31
+ */
20
32
  SATOSHI = "SATOSHI",
21
- /** 0.001 Satoshi, or 10e-11 Bitcoin. We recommend using the Satoshi unit instead when possible. **/
33
+ /**
34
+ * 0.001 Satoshi, or 10e-11 Bitcoin. We recommend using the Satoshi unit
35
+ * instead when possible. *
36
+ */
22
37
  MILLISATOSHI = "MILLISATOSHI",
23
38
  /** United States Dollar. **/
24
39
  USD = "USD",
25
- /** 0.000000001 (10e-9) Bitcoin or a billionth of a Bitcoin. We recommend using the Satoshi unit instead when possible. **/
40
+ /**
41
+ * 0.000000001 (10e-9) Bitcoin or a billionth of a Bitcoin.
42
+ * We recommend using the Satoshi unit instead when possible.
43
+ * *
44
+ */
26
45
  NANOBITCOIN = "NANOBITCOIN",
27
- /** 0.000001 (10e-6) Bitcoin or a millionth of a Bitcoin. We recommend using the Satoshi unit instead when possible. **/
46
+ /**
47
+ * 0.000001 (10e-6) Bitcoin or a millionth of a Bitcoin.
48
+ * We recommend using the Satoshi unit instead when possible.
49
+ * *
50
+ */
28
51
  MICROBITCOIN = "MICROBITCOIN",
29
- /** 0.001 (10e-3) Bitcoin or a thousandth of a Bitcoin. We recommend using the Satoshi unit instead when possible. **/
52
+ /**
53
+ * 0.001 (10e-3) Bitcoin or a thousandth of a Bitcoin.
54
+ * We recommend using the Satoshi unit instead when possible.
55
+ * *
56
+ */
30
57
  MILLIBITCOIN = "MILLIBITCOIN",
31
58
  }
32
59
 
@@ -39,13 +66,15 @@ export type CurrencyAmountType = {
39
66
  /** The unit of user's preferred currency. **/
40
67
  preferredCurrencyUnit: CurrencyUnit;
41
68
  /**
42
- * The rounded numeric value for this CurrencyAmount in the very base level of user's preferred
43
- * currency. For example, for USD, the value will be in cents.
69
+ * The rounded numeric value for this CurrencyAmount in the very base level
70
+ * of user's preferred currency. For example, for USD, the value will be in
71
+ * cents.
44
72
  **/
45
73
  preferredCurrencyValueRounded: number;
46
74
  /**
47
- * The approximate float value for this CurrencyAmount in the very base level of user's preferred
48
- * currency. For example, for USD, the value will be in cents.
75
+ * The approximate float value for this CurrencyAmount in the very base level
76
+ * of user's preferred currency. For example, for USD, the value will be in
77
+ * cents.
49
78
  **/
50
79
  preferredCurrencyValueApprox: number;
51
80
  };
@@ -211,8 +240,12 @@ export type CurrencyMap = {
211
240
  };
212
241
 
213
242
  export type CurrencyAmountObj = {
214
- /* Technically the generated graphql schema has value as `any` but it's always a number.
215
- We are intentionally widening the type here to allow for more forgiving input: */
243
+ /*
244
+ * Technically the generated graphql schema has value as `any` but it's
245
+ * always a number.
246
+ * We are intentionally widening the type here to allow for more forgiving
247
+ * input:
248
+ */
216
249
  value?: number | string | null;
217
250
  /* assume satoshi if not provided */
218
251
  unit?: CurrencyUnit;
@@ -402,7 +435,10 @@ export function formatCurrencyStr(
402
435
  let { value: num } = currencyAmount;
403
436
  const { unit } = currencyAmount;
404
437
 
405
- /* Currencies should always be represented in the smallest unit, e.g. cents for USD: */
438
+ /**
439
+ * Currencies should always be represented in the smallest unit, e.g.
440
+ * cents for USD:
441
+ */
406
442
  if (unit === CurrencyUnit.USD) {
407
443
  num = num / 100;
408
444
  }
@@ -415,7 +451,8 @@ export function formatCurrencyStr(
415
451
  : maxFractionDigits;
416
452
  }
417
453
 
418
- // Symbol handled by toLocaleString for USD. These rely on the LightsparkIcons font
454
+ // Symbol handled by toLocaleString for USD.
455
+ // These rely on the LightsparkIcons font
419
456
  const symbol = !showBtcSymbol
420
457
  ? ""
421
458
  : unit === CurrencyUnit.BITCOIN
@@ -472,7 +509,8 @@ export function localeToCurrencySymbol(locale: string) {
472
509
  maximumFractionDigits: 0,
473
510
  }).format(0);
474
511
 
475
- // Remove numeric and non-breaking space characters to extract the currency symbol
512
+ // Remove numeric and non-breaking space characters to extract the currency
513
+ // symbol
476
514
  const { symbol } = separateCurrencyStrParts(formatted);
477
515
  return symbol;
478
516
  }
@@ -1,5 +1,7 @@
1
1
  /* From https://github.com/tadeegan/locale-currency. For now only USD conversion from
2
- BTC is supported by sparkcore, strip additional currency codes from the bundle: */
2
+ * BTC is supported by sparkcore, strip additional currency codes from the
3
+ * bundle:
4
+ */
3
5
  export const countryCodesToCurrencyCodes = {
4
6
  AD: "EUR",
5
7
  // AE: "AED",
@@ -5,50 +5,51 @@ function getDefaultMaxPollsError() {
5
5
  return new Error("pollUntil: Max polls reached");
6
6
  }
7
7
 
8
- export function pollUntil<D extends () => Promise<unknown>, T>(
8
+ type GetValueResult<T> = {
9
+ stopPolling: boolean;
10
+ value: null | T;
11
+ };
12
+
13
+ export async function pollUntil<D extends () => Promise<unknown>, T>(
9
14
  asyncFn: D,
10
15
  getValue: (
11
16
  data: Awaited<ReturnType<D>>,
12
17
  response: { stopPolling: boolean; value: null | T },
13
- ) => {
14
- stopPolling: boolean;
15
- value: null | T;
16
- },
18
+ ) => GetValueResult<T>,
17
19
  maxPolls = 60,
18
20
  pollIntervalMs = 500,
19
21
  ignoreErrors: boolean | ((e: unknown) => boolean) = false,
20
22
  getMaxPollsError: (maxPolls: number) => Error = getDefaultMaxPollsError,
21
23
  ): Promise<T> {
22
- return new Promise((resolve, reject) => {
23
- let polls = 0;
24
- let stopPolling = false;
25
- (async function () {
26
- while (!stopPolling) {
27
- polls += 1;
28
- if (polls > maxPolls) {
29
- stopPolling = true;
30
- const maxPollsError = getMaxPollsError(maxPolls);
31
- reject(maxPollsError);
32
- break;
33
- }
34
- try {
35
- const asyncResult = await asyncFn();
36
- const result = getValue(asyncResult as Awaited<ReturnType<D>>, {
37
- stopPolling: false,
38
- value: null,
39
- });
40
- if (result.stopPolling) {
41
- stopPolling = true;
42
- resolve(result.value as T);
43
- }
44
- } catch (e) {
45
- if (!ignoreErrors || (isFunction(ignoreErrors) && !ignoreErrors(e))) {
46
- stopPolling = true;
47
- reject(e);
48
- }
49
- }
50
- await sleep(pollIntervalMs);
24
+ let polls = 0;
25
+ let stopPolling = false;
26
+ let result: GetValueResult<T> = {
27
+ stopPolling: false,
28
+ value: null,
29
+ };
30
+ while (!stopPolling) {
31
+ polls += 1;
32
+ if (polls > maxPolls) {
33
+ stopPolling = true;
34
+ const maxPollsError = getMaxPollsError(maxPolls);
35
+ throw maxPollsError;
36
+ }
37
+ try {
38
+ const asyncResult = await asyncFn();
39
+ result = getValue(asyncResult as Awaited<ReturnType<D>>, {
40
+ stopPolling: false,
41
+ value: null,
42
+ });
43
+ if (result.stopPolling) {
44
+ stopPolling = true;
45
+ }
46
+ } catch (e) {
47
+ if (!ignoreErrors || (isFunction(ignoreErrors) && !ignoreErrors(e))) {
48
+ stopPolling = true;
49
+ throw e;
51
50
  }
52
- })();
53
- });
51
+ }
52
+ await sleep(pollIntervalMs);
53
+ }
54
+ return result.value as T;
54
55
  }
@@ -4,7 +4,7 @@ export type Maybe<T> = T | null | undefined;
4
4
 
5
5
  export type ExpandRecursively<T> = T extends object
6
6
  ? T extends infer O
7
- ? { [K in keyof O]: ExpandRecursively<O[K]> } // eslint-disable-line @typescript-eslint/no-unused-vars
7
+ ? { [K in keyof O]: ExpandRecursively<O[K]> }
8
8
  : never
9
9
  : T;
10
10
 
@@ -21,3 +21,9 @@ export const isType =
21
21
  ): node is Extract<N, { __typename: T }> => {
22
22
  return node?.__typename === typename;
23
23
  };
24
+
25
+ export type DeepPartial<T> = T extends object
26
+ ? {
27
+ [P in keyof T]?: DeepPartial<T[P]>;
28
+ }
29
+ : T;