@lightsparkdev/core 1.0.21 → 1.1.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/CHANGELOG.md +13 -0
- package/dist/{chunk-Y3FWNVYS.js → chunk-XRYQNSG7.js} +157 -131
- package/dist/{index-9e41ffe5.d.ts → index-4698c2db.d.ts} +39 -75
- package/dist/index.cjs +189 -145
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +34 -16
- package/dist/utils/index.cjs +158 -132
- package/dist/utils/index.d.cts +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +3 -3
- package/package.json +1 -1
- package/src/requester/Requester.ts +35 -14
- package/src/utils/currency.ts +96 -114
- package/src/utils/types.ts +6 -0
|
@@ -137,7 +137,7 @@ class Requester {
|
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
const operation = operationMatch[2];
|
|
140
|
-
|
|
140
|
+
const payload: BodyData = {
|
|
141
141
|
query: queryPayload,
|
|
142
142
|
variables,
|
|
143
143
|
operationName: operation,
|
|
@@ -149,16 +149,22 @@ class Requester {
|
|
|
149
149
|
"Content-Type": "application/json",
|
|
150
150
|
"X-Lightspark-SDK": sdkUserAgent,
|
|
151
151
|
"User-Agent": browserUserAgent || sdkUserAgent,
|
|
152
|
+
"X-GraphQL-Operation": operation,
|
|
152
153
|
};
|
|
153
|
-
const headers = skipAuth
|
|
154
|
+
const headers: { [key: string]: string } = skipAuth
|
|
154
155
|
? baseHeaders
|
|
155
156
|
: await this.authProvider.addAuthHeaders(baseHeaders);
|
|
156
|
-
bodyData = await this.addSigningDataIfNeeded(
|
|
157
|
-
|
|
157
|
+
let bodyData = await this.addSigningDataIfNeeded(
|
|
158
|
+
payload,
|
|
158
159
|
headers,
|
|
159
160
|
signingNodeId,
|
|
160
161
|
);
|
|
161
162
|
|
|
163
|
+
if (bodyData.length > 1024 && typeof CompressionStream != "undefined") {
|
|
164
|
+
bodyData = await compress(bodyData);
|
|
165
|
+
headers["Content-Encoding"] = "deflate";
|
|
166
|
+
}
|
|
167
|
+
|
|
162
168
|
let urlWithProtocol = this.baseUrl;
|
|
163
169
|
if (
|
|
164
170
|
!urlWithProtocol.startsWith("https://") &&
|
|
@@ -177,7 +183,7 @@ class Requester {
|
|
|
177
183
|
const response = await fetch(url, {
|
|
178
184
|
method: "POST",
|
|
179
185
|
headers: headers,
|
|
180
|
-
body:
|
|
186
|
+
body: bodyData,
|
|
181
187
|
});
|
|
182
188
|
if (!response.ok) {
|
|
183
189
|
throw new LightsparkException(
|
|
@@ -214,9 +220,16 @@ class Requester {
|
|
|
214
220
|
headers: { [key: string]: string },
|
|
215
221
|
signingNodeId: string | undefined,
|
|
216
222
|
/* eslint-disable-next-line @typescript-eslint/no-explicit-any -- LIG-3400 */
|
|
217
|
-
): Promise<
|
|
223
|
+
): Promise<Uint8Array> {
|
|
224
|
+
let TextEncoderImpl;
|
|
225
|
+
if (typeof TextEncoder === "undefined") {
|
|
226
|
+
TextEncoderImpl = (await import("text-encoding")).TextEncoder;
|
|
227
|
+
} else {
|
|
228
|
+
TextEncoderImpl = TextEncoder;
|
|
229
|
+
}
|
|
230
|
+
|
|
218
231
|
if (!signingNodeId) {
|
|
219
|
-
return queryPayload;
|
|
232
|
+
return new TextEncoderImpl().encode(JSON.stringify(queryPayload));
|
|
220
233
|
}
|
|
221
234
|
|
|
222
235
|
const query = queryPayload.query;
|
|
@@ -241,12 +254,6 @@ class Requester {
|
|
|
241
254
|
);
|
|
242
255
|
}
|
|
243
256
|
|
|
244
|
-
let TextEncoderImpl;
|
|
245
|
-
if (typeof TextEncoder === "undefined") {
|
|
246
|
-
TextEncoderImpl = (await import("text-encoding")).TextEncoder;
|
|
247
|
-
} else {
|
|
248
|
-
TextEncoderImpl = TextEncoder;
|
|
249
|
-
}
|
|
250
257
|
const encodedPayload = new TextEncoderImpl().encode(
|
|
251
258
|
JSON.stringify(payload),
|
|
252
259
|
);
|
|
@@ -258,8 +265,22 @@ class Requester {
|
|
|
258
265
|
v: "1",
|
|
259
266
|
signature: encodedSignedPayload,
|
|
260
267
|
});
|
|
261
|
-
return
|
|
268
|
+
return encodedPayload;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
async function compress(data: Uint8Array): Promise<Uint8Array> {
|
|
273
|
+
const stream = new Blob([data]).stream();
|
|
274
|
+
const compressedStream = stream.pipeThrough(new CompressionStream("deflate"));
|
|
275
|
+
const reader = compressedStream.getReader();
|
|
276
|
+
const chunks = [];
|
|
277
|
+
let done, value;
|
|
278
|
+
while (!done) {
|
|
279
|
+
({ done, value } = await reader.read()); // eslint-disable-line @typescript-eslint/no-unsafe-assignment
|
|
280
|
+
chunks.push(value);
|
|
262
281
|
}
|
|
282
|
+
const blob = new Blob(chunks);
|
|
283
|
+
return new Uint8Array(await blob.arrayBuffer());
|
|
263
284
|
}
|
|
264
285
|
|
|
265
286
|
export default Requester;
|
package/src/utils/currency.ts
CHANGED
|
@@ -7,75 +7,35 @@ import { isNumber, round } from "./numbers.js";
|
|
|
7
7
|
|
|
8
8
|
export const defaultCurrencyCode = "USD";
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
* instead when possible. *
|
|
36
|
-
*/
|
|
37
|
-
MILLISATOSHI = "MILLISATOSHI",
|
|
38
|
-
/** United States Dollar. **/
|
|
39
|
-
USD = "USD",
|
|
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
|
-
*/
|
|
45
|
-
NANOBITCOIN = "NANOBITCOIN",
|
|
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
|
-
*/
|
|
51
|
-
MICROBITCOIN = "MICROBITCOIN",
|
|
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
|
-
*/
|
|
57
|
-
MILLIBITCOIN = "MILLIBITCOIN",
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/** This object represents the value and unit for an amount of currency. **/
|
|
61
|
-
export type CurrencyAmountType = {
|
|
62
|
-
/** The original numeric value for this CurrencyAmount. **/
|
|
10
|
+
/* This const identifies the unit of currency associated with a CurrencyAmount as created by the SDK
|
|
11
|
+
* writer and used in JS SDKs. The schema version uses camel case for the keys so we convert
|
|
12
|
+
* arguments of that type to this format for use in the functions below. */
|
|
13
|
+
export const CurrencyUnit = {
|
|
14
|
+
FUTURE_VALUE: "FUTURE_VALUE",
|
|
15
|
+
BITCOIN: "BITCOIN",
|
|
16
|
+
SATOSHI: "SATOSHI",
|
|
17
|
+
MILLISATOSHI: "MILLISATOSHI",
|
|
18
|
+
USD: "USD",
|
|
19
|
+
NANOBITCOIN: "NANOBITCOIN",
|
|
20
|
+
MICROBITCOIN: "MICROBITCOIN",
|
|
21
|
+
MILLIBITCOIN: "MILLIBITCOIN",
|
|
22
|
+
|
|
23
|
+
Bitcoin: "BITCOIN",
|
|
24
|
+
Microbitcoin: "MICROBITCOIN",
|
|
25
|
+
Millibitcoin: "MILLIBITCOIN",
|
|
26
|
+
Millisatoshi: "MILLISATOSHI",
|
|
27
|
+
Nanobitcoin: "NANOBITCOIN",
|
|
28
|
+
Satoshi: "SATOSHI",
|
|
29
|
+
Usd: "USD",
|
|
30
|
+
} as const;
|
|
31
|
+
|
|
32
|
+
export type CurrencyUnitType = (typeof CurrencyUnit)[keyof typeof CurrencyUnit];
|
|
33
|
+
|
|
34
|
+
export type SDKCurrencyAmountType = {
|
|
63
35
|
originalValue: number;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
/** The unit of user's preferred currency. **/
|
|
67
|
-
preferredCurrencyUnit: CurrencyUnit;
|
|
68
|
-
/**
|
|
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.
|
|
72
|
-
**/
|
|
36
|
+
originalUnit: CurrencyUnitType;
|
|
37
|
+
preferredCurrencyUnit: CurrencyUnitType;
|
|
73
38
|
preferredCurrencyValueRounded: number;
|
|
74
|
-
/**
|
|
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.
|
|
78
|
-
**/
|
|
79
39
|
preferredCurrencyValueApprox: number;
|
|
80
40
|
};
|
|
81
41
|
|
|
@@ -163,8 +123,8 @@ const CONVERSION_MAP = {
|
|
|
163
123
|
};
|
|
164
124
|
|
|
165
125
|
export function convertCurrencyAmountValue(
|
|
166
|
-
fromUnit:
|
|
167
|
-
toUnit:
|
|
126
|
+
fromUnit: CurrencyUnitType,
|
|
127
|
+
toUnit: CurrencyUnitType,
|
|
168
128
|
amount: number,
|
|
169
129
|
centsPerBtc = 1,
|
|
170
130
|
): number {
|
|
@@ -191,9 +151,9 @@ export function convertCurrencyAmountValue(
|
|
|
191
151
|
}
|
|
192
152
|
|
|
193
153
|
export const convertCurrencyAmount = (
|
|
194
|
-
from:
|
|
195
|
-
toUnit:
|
|
196
|
-
):
|
|
154
|
+
from: SDKCurrencyAmountType,
|
|
155
|
+
toUnit: CurrencyUnitType,
|
|
156
|
+
): SDKCurrencyAmountType => {
|
|
197
157
|
const value = convertCurrencyAmountValue(
|
|
198
158
|
from.originalUnit,
|
|
199
159
|
toUnit,
|
|
@@ -240,21 +200,17 @@ export type CurrencyMap = {
|
|
|
240
200
|
};
|
|
241
201
|
|
|
242
202
|
export type CurrencyAmountObj = {
|
|
243
|
-
/*
|
|
244
|
-
*
|
|
245
|
-
* always a number.
|
|
246
|
-
* We are intentionally widening the type here to allow for more forgiving
|
|
247
|
-
* input:
|
|
248
|
-
*/
|
|
203
|
+
/* Technically the generated graphql schema has value as `any` but it's always a number.
|
|
204
|
+
* We are intentionally widening the type here to allow for more forgiving input: */
|
|
249
205
|
value?: number | string | null;
|
|
250
206
|
/* assume satoshi if not provided */
|
|
251
|
-
unit?:
|
|
252
|
-
__typename?: "CurrencyAmount";
|
|
207
|
+
unit?: CurrencyUnitType;
|
|
208
|
+
__typename?: "CurrencyAmount" | undefined;
|
|
253
209
|
};
|
|
254
210
|
|
|
255
211
|
export type CurrencyAmountArg =
|
|
256
212
|
| CurrencyAmountObj
|
|
257
|
-
|
|
|
213
|
+
| SDKCurrencyAmountType
|
|
258
214
|
| undefined
|
|
259
215
|
| null;
|
|
260
216
|
|
|
@@ -264,10 +220,13 @@ export function isCurrencyAmountObj(arg: unknown): arg is CurrencyAmountObj {
|
|
|
264
220
|
);
|
|
265
221
|
}
|
|
266
222
|
|
|
267
|
-
export function
|
|
223
|
+
export function isSDKCurrencyAmount(
|
|
224
|
+
arg: unknown,
|
|
225
|
+
): arg is SDKCurrencyAmountType {
|
|
268
226
|
return (
|
|
269
227
|
typeof arg === "object" &&
|
|
270
228
|
arg !== null &&
|
|
229
|
+
/* We can expect all SDK CurrencyAmount types to always have these exact properties: */
|
|
271
230
|
"originalValue" in arg &&
|
|
272
231
|
"originalUnit" in arg &&
|
|
273
232
|
"preferredCurrencyUnit" in arg &&
|
|
@@ -275,7 +234,6 @@ export function isCurrencyAmount(arg: unknown): arg is CurrencyAmountType {
|
|
|
275
234
|
"preferredCurrencyValueApprox" in arg
|
|
276
235
|
);
|
|
277
236
|
}
|
|
278
|
-
|
|
279
237
|
function asNumber(value: string | number | null | undefined) {
|
|
280
238
|
if (typeof value === "string") {
|
|
281
239
|
return Number(value);
|
|
@@ -287,12 +245,12 @@ function getCurrencyAmount(currencyAmountArg: CurrencyAmountArg) {
|
|
|
287
245
|
let value = 0;
|
|
288
246
|
let unit = undefined;
|
|
289
247
|
|
|
290
|
-
if (
|
|
291
|
-
value = asNumber(currencyAmountArg.value);
|
|
292
|
-
unit = currencyAmountArg.unit;
|
|
293
|
-
} else if (isCurrencyAmount(currencyAmountArg)) {
|
|
248
|
+
if (isSDKCurrencyAmount(currencyAmountArg)) {
|
|
294
249
|
value = currencyAmountArg.originalValue;
|
|
295
250
|
unit = currencyAmountArg.originalUnit;
|
|
251
|
+
} else if (isCurrencyAmountObj(currencyAmountArg)) {
|
|
252
|
+
value = asNumber(currencyAmountArg.value);
|
|
253
|
+
unit = currencyAmountArg.unit;
|
|
296
254
|
}
|
|
297
255
|
|
|
298
256
|
return {
|
|
@@ -410,7 +368,7 @@ export const isCurrencyMap = (
|
|
|
410
368
|
typeof currencyMap.type === "string" &&
|
|
411
369
|
currencyMap.type === "CurrencyMap";
|
|
412
370
|
|
|
413
|
-
export const abbrCurrencyUnit = (unit:
|
|
371
|
+
export const abbrCurrencyUnit = (unit: CurrencyUnitType) => {
|
|
414
372
|
switch (unit) {
|
|
415
373
|
case CurrencyUnit.BITCOIN:
|
|
416
374
|
return "BTC";
|
|
@@ -424,35 +382,54 @@ export const abbrCurrencyUnit = (unit: CurrencyUnit) => {
|
|
|
424
382
|
return "Unsupported CurrencyUnit";
|
|
425
383
|
};
|
|
426
384
|
|
|
385
|
+
const defaultOptions = {
|
|
386
|
+
/* undefined indicates to use default precision for unit defined below */
|
|
387
|
+
precision: undefined,
|
|
388
|
+
compact: false,
|
|
389
|
+
showBtcSymbol: false,
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
type FormatCurrencyStrOptions = {
|
|
393
|
+
/* undefined indicates to use default precision for unit defined below */
|
|
394
|
+
precision?: number | "full" | undefined;
|
|
395
|
+
compact?: boolean | undefined;
|
|
396
|
+
showBtcSymbol?: boolean | undefined;
|
|
397
|
+
};
|
|
398
|
+
|
|
427
399
|
export function formatCurrencyStr(
|
|
428
400
|
amount: CurrencyAmountArg,
|
|
429
|
-
|
|
430
|
-
compact?: boolean,
|
|
431
|
-
showBtcSymbol = false,
|
|
432
|
-
options: Intl.NumberFormatOptions = {},
|
|
401
|
+
options?: FormatCurrencyStrOptions,
|
|
433
402
|
) {
|
|
403
|
+
const { precision, compact, showBtcSymbol } = {
|
|
404
|
+
...defaultOptions,
|
|
405
|
+
...options,
|
|
406
|
+
};
|
|
407
|
+
|
|
434
408
|
const currencyAmount = getCurrencyAmount(amount);
|
|
435
409
|
let { value: num } = currencyAmount;
|
|
436
410
|
const { unit } = currencyAmount;
|
|
437
411
|
|
|
438
|
-
|
|
439
|
-
* Currencies should always be represented in the smallest unit, e.g.
|
|
440
|
-
* cents for USD:
|
|
441
|
-
*/
|
|
412
|
+
/* Currencies should always be represented in the smallest unit, e.g. cents for USD: */
|
|
442
413
|
if (unit === CurrencyUnit.USD) {
|
|
443
414
|
num = num / 100;
|
|
444
415
|
}
|
|
445
416
|
|
|
446
|
-
function getDefaultMaxFractionDigits(
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
417
|
+
function getDefaultMaxFractionDigits(
|
|
418
|
+
defaultDigits: number,
|
|
419
|
+
fullPrecisionDigits: number,
|
|
420
|
+
) {
|
|
421
|
+
let digits = defaultDigits;
|
|
422
|
+
if (precision === "full") {
|
|
423
|
+
digits = fullPrecisionDigits;
|
|
424
|
+
} else if (typeof precision === "number") {
|
|
425
|
+
digits = precision;
|
|
426
|
+
} else if (compact) {
|
|
427
|
+
digits = 1;
|
|
428
|
+
}
|
|
429
|
+
return digits;
|
|
452
430
|
}
|
|
453
431
|
|
|
454
|
-
|
|
455
|
-
// These rely on the LightsparkIcons font
|
|
432
|
+
/* Symbol handled by toLocaleString for USD. These rely on the LightsparkIcons font: */
|
|
456
433
|
const symbol = !showBtcSymbol
|
|
457
434
|
? ""
|
|
458
435
|
: unit === CurrencyUnit.BITCOIN
|
|
@@ -465,35 +442,41 @@ export function formatCurrencyStr(
|
|
|
465
442
|
|
|
466
443
|
switch (unit) {
|
|
467
444
|
case CurrencyUnit.BITCOIN:
|
|
445
|
+
/* In most cases product prefers 4 precision digtis for BTC. In a few places
|
|
446
|
+
full precision (8 digits) are preferred, e.g. for a transaction details page: */
|
|
468
447
|
return `${symbol}${num.toLocaleString(currentLocale, {
|
|
469
448
|
notation: compact ? ("compact" as const) : undefined,
|
|
470
|
-
maximumFractionDigits: getDefaultMaxFractionDigits(4),
|
|
471
|
-
...options,
|
|
449
|
+
maximumFractionDigits: getDefaultMaxFractionDigits(4, 8),
|
|
472
450
|
})}`;
|
|
473
|
-
case CurrencyUnit.MILLISATOSHI:
|
|
474
451
|
case CurrencyUnit.SATOSHI:
|
|
452
|
+
/* In most cases product prefers hiding sub sat precision (msats). In a few
|
|
453
|
+
places full precision (3 digits) are preferred, e.g. for Lightning fees
|
|
454
|
+
paid on a transaction details page: */
|
|
455
|
+
return `${symbol}${num.toLocaleString(currentLocale, {
|
|
456
|
+
notation: compact ? ("compact" as const) : undefined,
|
|
457
|
+
maximumFractionDigits: getDefaultMaxFractionDigits(0, 3),
|
|
458
|
+
})}`;
|
|
459
|
+
case CurrencyUnit.MILLISATOSHI:
|
|
475
460
|
case CurrencyUnit.MICROBITCOIN:
|
|
476
461
|
case CurrencyUnit.MILLIBITCOIN:
|
|
477
462
|
case CurrencyUnit.NANOBITCOIN:
|
|
478
463
|
default:
|
|
479
464
|
return `${symbol}${num.toLocaleString(currentLocale, {
|
|
480
465
|
notation: compact ? ("compact" as const) : undefined,
|
|
481
|
-
maximumFractionDigits: getDefaultMaxFractionDigits(0),
|
|
482
|
-
...options,
|
|
466
|
+
maximumFractionDigits: getDefaultMaxFractionDigits(0, 0),
|
|
483
467
|
})}`;
|
|
484
468
|
case CurrencyUnit.USD:
|
|
485
469
|
return num.toLocaleString(currentLocale, {
|
|
486
470
|
style: "currency",
|
|
487
471
|
currency: defaultCurrencyCode,
|
|
488
472
|
notation: compact ? ("compact" as const) : undefined,
|
|
489
|
-
maximumFractionDigits: getDefaultMaxFractionDigits(2),
|
|
490
|
-
...options,
|
|
473
|
+
maximumFractionDigits: getDefaultMaxFractionDigits(2, 2),
|
|
491
474
|
});
|
|
492
475
|
}
|
|
493
476
|
}
|
|
494
477
|
|
|
495
478
|
export function separateCurrencyStrParts(currencyStr: string) {
|
|
496
|
-
|
|
479
|
+
/* split the currency string into the symbol and the amount */
|
|
497
480
|
const symbol = currencyStr.replace(/[0-9\s\u00a0.,]/g, "");
|
|
498
481
|
const amount = currencyStr.replace(/[^\d.,-]/g, "");
|
|
499
482
|
return { symbol, amount };
|
|
@@ -509,8 +492,7 @@ export function localeToCurrencySymbol(locale: string) {
|
|
|
509
492
|
maximumFractionDigits: 0,
|
|
510
493
|
}).format(0);
|
|
511
494
|
|
|
512
|
-
|
|
513
|
-
// symbol
|
|
495
|
+
/* Remove numeric and non-breaking space characters to extract the currency symbol */
|
|
514
496
|
const { symbol } = separateCurrencyStrParts(formatted);
|
|
515
497
|
return symbol;
|
|
516
498
|
}
|
package/src/utils/types.ts
CHANGED
|
@@ -39,3 +39,9 @@ export function notNullUndefined<TValue>(
|
|
|
39
39
|
): value is TValue {
|
|
40
40
|
return value !== null && value !== undefined;
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
/* Make specific properties on object optional: */
|
|
44
|
+
export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
45
|
+
|
|
46
|
+
/* Opposite of Partial - make all keys required with NonNullable values */
|
|
47
|
+
export type Complete<T> = { [P in keyof T]-?: NonNullable<T[P]> };
|