@swapkit/helpers 1.0.0-rc.4 → 1.0.0-rc.41
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/dist/index.cjs +1 -1
- package/dist/index.d.ts +50 -25
- package/dist/index.es.js +842 -454
- package/package.json +12 -9
- package/src/helpers/asset.ts +46 -15
- package/src/helpers/liquidity.ts +12 -10
- package/src/helpers/others.ts +0 -48
- package/src/helpers/request.ts +15 -0
- package/src/index.ts +1 -0
- package/src/modules/__tests__/assetValue.test.ts +90 -12
- package/src/modules/__tests__/swapKitNumber.test.ts +174 -48
- package/src/modules/assetValue.ts +71 -54
- package/src/modules/bigIntArithmetics.ts +189 -108
- package/src/modules/swapKitError.ts +1 -1
- package/src/modules/swapKitNumber.ts +8 -1
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { BaseDecimal } from '@swapkit/types';
|
|
2
|
+
|
|
1
3
|
import type { SwapKitNumber } from './swapKitNumber.ts';
|
|
2
4
|
|
|
3
5
|
type NumberPrimitivesType = {
|
|
@@ -5,10 +7,11 @@ type NumberPrimitivesType = {
|
|
|
5
7
|
number: number;
|
|
6
8
|
string: string;
|
|
7
9
|
};
|
|
8
|
-
type NumberPrimitives = bigint | number | string;
|
|
10
|
+
export type NumberPrimitives = bigint | number | string;
|
|
9
11
|
type InitialisationValueType = NumberPrimitives | BigIntArithmetics | SwapKitNumber;
|
|
10
12
|
|
|
11
13
|
type SKBigIntParams = InitialisationValueType | { decimal?: number; value: number | string };
|
|
14
|
+
type AllowedNumberTypes = 'bigint' | 'number' | 'string';
|
|
12
15
|
|
|
13
16
|
const DEFAULT_DECIMAL = 8;
|
|
14
17
|
const toMultiplier = (decimal: number) => 10n ** BigInt(decimal);
|
|
@@ -69,38 +72,30 @@ export class BigIntArithmetics {
|
|
|
69
72
|
from,
|
|
70
73
|
to,
|
|
71
74
|
}: {
|
|
72
|
-
value:
|
|
75
|
+
value: InstanceType<typeof SwapKitNumber>;
|
|
73
76
|
from: number;
|
|
74
77
|
to: number;
|
|
75
78
|
}) {
|
|
76
|
-
return
|
|
77
|
-
(
|
|
79
|
+
return this.fromBigInt(
|
|
80
|
+
(value.getBaseValue('bigint') * toMultiplier(to)) / toMultiplier(from),
|
|
78
81
|
to,
|
|
79
82
|
);
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
constructor(params: SKBigIntParams) {
|
|
83
86
|
const value = getStringValue(params);
|
|
84
|
-
|
|
87
|
+
const isComplex = typeof params === 'object';
|
|
88
|
+
this.decimal = isComplex ? params.decimal : undefined;
|
|
85
89
|
|
|
86
90
|
// use the multiplier to keep track of decimal point - defaults to 8 if lower than 8
|
|
87
|
-
this.decimalMultiplier =
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
this.decimalMultiplier =
|
|
92
|
+
isComplex && 'decimalMultiplier' in params
|
|
93
|
+
? params.decimalMultiplier
|
|
94
|
+
: toMultiplier(Math.max(getFloatDecimals(toSafeValue(value)), this.decimal || 0));
|
|
90
95
|
this.#setValue(value);
|
|
91
96
|
}
|
|
92
97
|
|
|
93
|
-
|
|
94
|
-
return this.getBaseValue('string') as string;
|
|
95
|
-
}
|
|
96
|
-
get baseValueNumber() {
|
|
97
|
-
return this.getBaseValue('number') as number;
|
|
98
|
-
}
|
|
99
|
-
get baseValueBigInt() {
|
|
100
|
-
return this.getBaseValue('bigint') as bigint;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
set(value: SKBigIntParams) {
|
|
98
|
+
set(value: SKBigIntParams): this {
|
|
104
99
|
// @ts-expect-error False positive
|
|
105
100
|
return new this.constructor({ decimal: this.decimal, value, identifier: this.toString() });
|
|
106
101
|
}
|
|
@@ -117,22 +112,23 @@ export class BigIntArithmetics {
|
|
|
117
112
|
return this.#arithmetics('div', ...args);
|
|
118
113
|
}
|
|
119
114
|
gt(value: InitialisationValueType) {
|
|
120
|
-
return this
|
|
115
|
+
return this.#comparison('gt', value);
|
|
121
116
|
}
|
|
122
117
|
gte(value: InitialisationValueType) {
|
|
123
|
-
return this
|
|
118
|
+
return this.#comparison('gte', value);
|
|
124
119
|
}
|
|
125
120
|
lt(value: InitialisationValueType) {
|
|
126
|
-
return this
|
|
121
|
+
return this.#comparison('lt', value);
|
|
127
122
|
}
|
|
128
123
|
lte(value: InitialisationValueType) {
|
|
129
|
-
return this
|
|
124
|
+
return this.#comparison('lte', value);
|
|
130
125
|
}
|
|
131
126
|
eqValue(value: InitialisationValueType) {
|
|
132
|
-
return this
|
|
127
|
+
return this.#comparison('eqValue', value);
|
|
133
128
|
}
|
|
134
129
|
|
|
135
|
-
|
|
130
|
+
// @ts-expect-error False positive
|
|
131
|
+
getValue<T extends AllowedNumberTypes>(type: T): NumberPrimitivesType[T] {
|
|
136
132
|
const value = this.formatBigIntToSafeValue(
|
|
137
133
|
this.bigIntValue,
|
|
138
134
|
this.decimal || decimalFromMultiplier(this.decimalMultiplier),
|
|
@@ -140,38 +136,125 @@ export class BigIntArithmetics {
|
|
|
140
136
|
|
|
141
137
|
switch (type) {
|
|
142
138
|
case 'number':
|
|
143
|
-
|
|
144
|
-
return Number(value);
|
|
139
|
+
return Number(value) as NumberPrimitivesType[T];
|
|
145
140
|
case 'string':
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return this.bigIntValue;
|
|
141
|
+
return value as NumberPrimitivesType[T];
|
|
142
|
+
case 'bigint':
|
|
143
|
+
return ((this.bigIntValue * 10n ** BigInt(this.decimal || 8n)) /
|
|
144
|
+
this.decimalMultiplier) as NumberPrimitivesType[T];
|
|
151
145
|
}
|
|
152
146
|
}
|
|
153
147
|
|
|
154
|
-
|
|
155
|
-
|
|
148
|
+
// @ts-expect-error
|
|
149
|
+
getBaseValue<T extends AllowedNumberTypes>(type: T): NumberPrimitivesType[T] {
|
|
150
|
+
const divisor = this.decimalMultiplier / toMultiplier(this.decimal || BaseDecimal.THOR);
|
|
156
151
|
const baseValue = this.bigIntValue / divisor;
|
|
157
152
|
|
|
158
153
|
switch (type) {
|
|
159
154
|
case 'number':
|
|
160
|
-
|
|
161
|
-
return Number(baseValue);
|
|
155
|
+
return Number(baseValue) as NumberPrimitivesType[T];
|
|
162
156
|
case 'string':
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
// @ts-expect-error False positive
|
|
167
|
-
return this.bigIntValue;
|
|
157
|
+
return baseValue.toString() as NumberPrimitivesType[T];
|
|
158
|
+
case 'bigint':
|
|
159
|
+
return baseValue as NumberPrimitivesType[T];
|
|
168
160
|
}
|
|
169
161
|
}
|
|
170
162
|
|
|
171
163
|
getBigIntValue(value: InitialisationValueType, decimal?: number) {
|
|
172
164
|
if (!decimal && typeof value === 'object') return value.bigIntValue;
|
|
173
165
|
|
|
174
|
-
|
|
166
|
+
const stringValue = getStringValue(value);
|
|
167
|
+
const safeValue = toSafeValue(stringValue);
|
|
168
|
+
|
|
169
|
+
if (safeValue === '0' || safeValue === 'undefined') return 0n;
|
|
170
|
+
return this.#toBigInt(safeValue, decimal);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
toSignificant(significantDigits: number = 6) {
|
|
174
|
+
const [int, dec] = this.getValue('string').split('.');
|
|
175
|
+
const integer = int || '';
|
|
176
|
+
const decimal = dec || '';
|
|
177
|
+
const valueLength = parseInt(integer) ? integer.length + decimal.length : decimal.length;
|
|
178
|
+
|
|
179
|
+
if (valueLength <= significantDigits) {
|
|
180
|
+
return this.getValue('string');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (integer.length >= significantDigits) {
|
|
184
|
+
return integer.slice(0, significantDigits).padEnd(integer.length, '0');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (parseInt(integer)) {
|
|
188
|
+
return `${integer}.${decimal.slice(0, significantDigits - integer.length)}`.padEnd(
|
|
189
|
+
significantDigits - integer.length,
|
|
190
|
+
'0',
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const trimmedDecimal = parseInt(decimal);
|
|
195
|
+
const slicedDecimal = `${trimmedDecimal}`.slice(0, significantDigits);
|
|
196
|
+
|
|
197
|
+
return `0.${slicedDecimal.padStart(
|
|
198
|
+
decimal.length - `${trimmedDecimal}`.length + slicedDecimal.length,
|
|
199
|
+
'0',
|
|
200
|
+
)}`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
toFixed(fixedDigits: number = 6) {
|
|
204
|
+
const [int, dec] = this.getValue('string').split('.');
|
|
205
|
+
const integer = int || '';
|
|
206
|
+
const decimal = dec || '';
|
|
207
|
+
|
|
208
|
+
if (parseInt(integer)) {
|
|
209
|
+
return `${integer}.${decimal.slice(0, fixedDigits)}`.padEnd(fixedDigits, '0');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const trimmedDecimal = parseInt(decimal);
|
|
213
|
+
const slicedDecimal = `${trimmedDecimal}`.slice(0, fixedDigits);
|
|
214
|
+
|
|
215
|
+
return `0.${slicedDecimal.padStart(
|
|
216
|
+
decimal.length - `${trimmedDecimal}`.length + slicedDecimal.length,
|
|
217
|
+
'0',
|
|
218
|
+
)}`;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
toAbbreviation(digits = 2) {
|
|
222
|
+
const value = this.getValue('number');
|
|
223
|
+
const abbreviations = ['', 'K', 'M', 'B', 'T', 'Q', 'Qi', 'S'];
|
|
224
|
+
const tier = Math.floor(Math.log10(Math.abs(value)) / 3);
|
|
225
|
+
const suffix = abbreviations[tier];
|
|
226
|
+
|
|
227
|
+
if (!suffix) return this.getValue('string');
|
|
228
|
+
|
|
229
|
+
const scale = 10 ** (tier * 3);
|
|
230
|
+
const scaled = value / scale;
|
|
231
|
+
|
|
232
|
+
return `${scaled.toFixed(digits)}${suffix}`;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
toCurrency(
|
|
236
|
+
currency = '$',
|
|
237
|
+
{
|
|
238
|
+
currencyPosition = 'start',
|
|
239
|
+
decimal = 2,
|
|
240
|
+
decimalSeparator = '.',
|
|
241
|
+
thousandSeparator = ',',
|
|
242
|
+
} = {},
|
|
243
|
+
) {
|
|
244
|
+
const value = this.getValue('number');
|
|
245
|
+
const [int, dec = ''] = value.toFixed(6).split('.');
|
|
246
|
+
const integer = int.replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator);
|
|
247
|
+
|
|
248
|
+
const parsedValue =
|
|
249
|
+
!int && !dec
|
|
250
|
+
? '0.00'
|
|
251
|
+
: int === '0'
|
|
252
|
+
? `${parseFloat(`0.${dec}`)}`.replace('.', decimalSeparator)
|
|
253
|
+
: `${integer}${parseInt(dec) ? `${decimalSeparator}${dec.slice(0, decimal)}` : ''}`;
|
|
254
|
+
|
|
255
|
+
return `${currencyPosition === 'start' ? currency : ''}${parsedValue}${
|
|
256
|
+
currencyPosition === 'end' ? currency : ''
|
|
257
|
+
}`;
|
|
175
258
|
}
|
|
176
259
|
|
|
177
260
|
formatBigIntToSafeValue(value: bigint, decimal?: number) {
|
|
@@ -207,43 +290,14 @@ export class BigIntArithmetics {
|
|
|
207
290
|
)}.${decimalString}`.replace(/\.?0*$/, '');
|
|
208
291
|
}
|
|
209
292
|
|
|
210
|
-
toSignificant(significantDigits: number = 6) {
|
|
211
|
-
const [int, dec] = this.getValue('string').split('.');
|
|
212
|
-
const integer = int || '';
|
|
213
|
-
const decimal = dec || '';
|
|
214
|
-
const valueLength = parseInt(integer) ? integer.length + decimal.length : decimal.length;
|
|
215
|
-
|
|
216
|
-
if (valueLength <= significantDigits) {
|
|
217
|
-
return this.getValue('string');
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (integer.length >= significantDigits) {
|
|
221
|
-
return integer.slice(0, significantDigits).padEnd(integer.length, '0');
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
if (parseInt(integer)) {
|
|
225
|
-
return `${integer}.${decimal.slice(0, significantDigits - integer.length)}`.padEnd(
|
|
226
|
-
valueLength - significantDigits,
|
|
227
|
-
'0',
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const trimmedDecimal = parseInt(decimal);
|
|
232
|
-
const slicedDecimal = `${trimmedDecimal}`.slice(0, significantDigits);
|
|
233
|
-
|
|
234
|
-
return `0.${slicedDecimal.padStart(
|
|
235
|
-
decimal.length - `${trimmedDecimal}`.length + slicedDecimal.length,
|
|
236
|
-
'0',
|
|
237
|
-
)}`;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
293
|
#arithmetics(method: 'add' | 'sub' | 'mul' | 'div', ...args: InitialisationValueType[]): this {
|
|
241
294
|
const precisionDecimal = this.#retrievePrecisionDecimal(this, ...args);
|
|
242
|
-
const
|
|
295
|
+
const decimal = Math.max(precisionDecimal, decimalFromMultiplier(this.decimalMultiplier));
|
|
296
|
+
const precisionDecimalMultiplier = toMultiplier(decimal);
|
|
243
297
|
|
|
244
298
|
const result = args.reduce(
|
|
245
299
|
(acc: bigint, arg) => {
|
|
246
|
-
const value = this.getBigIntValue(arg,
|
|
300
|
+
const value = this.getBigIntValue(arg, decimal);
|
|
247
301
|
|
|
248
302
|
switch (method) {
|
|
249
303
|
case 'add':
|
|
@@ -273,65 +327,92 @@ export class BigIntArithmetics {
|
|
|
273
327
|
);
|
|
274
328
|
|
|
275
329
|
const value = formatBigIntToSafeValue({
|
|
276
|
-
bigIntDecimal:
|
|
277
|
-
decimal
|
|
330
|
+
bigIntDecimal: decimal,
|
|
331
|
+
decimal,
|
|
278
332
|
value: result,
|
|
279
333
|
});
|
|
280
334
|
|
|
281
335
|
// @ts-expect-error False positive
|
|
282
|
-
return new this.constructor({
|
|
336
|
+
return new this.constructor({
|
|
337
|
+
decimalMultiplier: toMultiplier(decimal),
|
|
338
|
+
decimal: this.decimal,
|
|
339
|
+
value,
|
|
340
|
+
identifier: this.toString(),
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
#comparison(method: 'gt' | 'gte' | 'lt' | 'lte' | 'eqValue', ...args: InitialisationValueType[]) {
|
|
345
|
+
const decimal = this.#retrievePrecisionDecimal(this, ...args);
|
|
346
|
+
const value = this.getBigIntValue(args[0], decimal);
|
|
347
|
+
const compareToValue = this.getBigIntValue(this, decimal);
|
|
348
|
+
|
|
349
|
+
switch (method) {
|
|
350
|
+
case 'gt':
|
|
351
|
+
return compareToValue > value;
|
|
352
|
+
case 'gte':
|
|
353
|
+
return compareToValue >= value;
|
|
354
|
+
case 'lt':
|
|
355
|
+
return compareToValue < value;
|
|
356
|
+
case 'lte':
|
|
357
|
+
return compareToValue <= value;
|
|
358
|
+
case 'eqValue':
|
|
359
|
+
return compareToValue === value;
|
|
360
|
+
}
|
|
283
361
|
}
|
|
284
362
|
|
|
285
363
|
#setValue(value: InitialisationValueType) {
|
|
286
|
-
const safeValue =
|
|
364
|
+
const safeValue = toSafeValue(value) || '0';
|
|
287
365
|
this.bigIntValue = this.#toBigInt(safeValue);
|
|
288
366
|
}
|
|
289
367
|
|
|
290
368
|
#retrievePrecisionDecimal(...args: InitialisationValueType[]) {
|
|
291
369
|
const decimals = args
|
|
292
|
-
.map((arg) =>
|
|
293
|
-
typeof arg === 'object'
|
|
370
|
+
.map((arg) => {
|
|
371
|
+
const isObject = typeof arg === 'object';
|
|
372
|
+
const value = isObject
|
|
294
373
|
? arg.decimal || decimalFromMultiplier(arg.decimalMultiplier)
|
|
295
|
-
:
|
|
296
|
-
|
|
374
|
+
: getFloatDecimals(toSafeValue(arg));
|
|
375
|
+
|
|
376
|
+
return value;
|
|
377
|
+
})
|
|
297
378
|
.filter(Boolean) as number[];
|
|
379
|
+
|
|
298
380
|
return Math.max(...decimals, DEFAULT_DECIMAL);
|
|
299
381
|
}
|
|
300
382
|
|
|
301
383
|
#toBigInt(value: string, decimal?: number) {
|
|
302
384
|
const multiplier = decimal ? toMultiplier(decimal) : this.decimalMultiplier;
|
|
303
385
|
const padDecimal = decimalFromMultiplier(multiplier);
|
|
304
|
-
const [integerPart, decimalPart = ''] = value.split('.');
|
|
386
|
+
const [integerPart = '', decimalPart = ''] = value.split('.');
|
|
305
387
|
|
|
306
388
|
return BigInt(`${integerPart}${decimalPart.padEnd(padDecimal, '0')}`);
|
|
307
389
|
}
|
|
390
|
+
}
|
|
308
391
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
useGrouping: false,
|
|
314
|
-
maximumFractionDigits: 20,
|
|
315
|
-
})
|
|
316
|
-
: getStringValue(value);
|
|
317
|
-
|
|
318
|
-
const splitValue = `${parsedValue}`.replaceAll(',', '.').split('.');
|
|
319
|
-
|
|
320
|
-
return splitValue.length > 1
|
|
321
|
-
? `${splitValue.slice(0, -1).join('')}.${splitValue.at(-1)}`
|
|
322
|
-
: splitValue[0];
|
|
323
|
-
}
|
|
392
|
+
const numberFormatter = Intl.NumberFormat('fullwide', {
|
|
393
|
+
useGrouping: false,
|
|
394
|
+
maximumFractionDigits: 20,
|
|
395
|
+
});
|
|
324
396
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
397
|
+
function toSafeValue(value: InitialisationValueType) {
|
|
398
|
+
const parsedValue =
|
|
399
|
+
typeof value === 'number' ? numberFormatter.format(value) : getStringValue(value);
|
|
400
|
+
const splitValue = `${parsedValue}`.replaceAll(',', '.').split('.');
|
|
401
|
+
|
|
402
|
+
return splitValue.length > 1
|
|
403
|
+
? `${splitValue.slice(0, -1).join('')}.${splitValue.at(-1)}`
|
|
404
|
+
: splitValue[0];
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function getFloatDecimals(value: string) {
|
|
408
|
+
const decimals = value.split('.')[1]?.length || 0;
|
|
409
|
+
return Math.max(decimals, DEFAULT_DECIMAL);
|
|
329
410
|
}
|
|
330
411
|
|
|
331
|
-
function getStringValue(
|
|
332
|
-
return typeof
|
|
333
|
-
? 'getValue' in
|
|
334
|
-
?
|
|
335
|
-
:
|
|
336
|
-
:
|
|
412
|
+
function getStringValue(param: SKBigIntParams) {
|
|
413
|
+
return typeof param === 'object'
|
|
414
|
+
? 'getValue' in param
|
|
415
|
+
? param.getValue('string')
|
|
416
|
+
: param.value
|
|
417
|
+
: param;
|
|
337
418
|
}
|
|
@@ -62,7 +62,7 @@ export type Keys = keyof typeof errorMessages;
|
|
|
62
62
|
|
|
63
63
|
export class SwapKitError extends Error {
|
|
64
64
|
constructor(errorKey: Keys, sourceError?: any) {
|
|
65
|
-
console.error(sourceError);
|
|
65
|
+
console.error(sourceError, { stack: sourceError?.stack, message: sourceError?.message });
|
|
66
66
|
|
|
67
67
|
super(errorKey, { cause: { code: errorMessages[errorKey], message: errorKey } });
|
|
68
68
|
Object.setPrototypeOf(this, SwapKitError.prototype);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BigIntArithmetics } from './bigIntArithmetics.ts';
|
|
1
|
+
import { BigIntArithmetics, formatBigIntToSafeValue } from './bigIntArithmetics.ts';
|
|
2
2
|
|
|
3
3
|
export type SwapKitValueType = BigIntArithmetics | string | number;
|
|
4
4
|
|
|
@@ -6,4 +6,11 @@ export class SwapKitNumber extends BigIntArithmetics {
|
|
|
6
6
|
eq(value: SwapKitValueType) {
|
|
7
7
|
return this.eqValue(value);
|
|
8
8
|
}
|
|
9
|
+
|
|
10
|
+
static fromBigInt(value: bigint, decimal?: number) {
|
|
11
|
+
return new SwapKitNumber({
|
|
12
|
+
decimal,
|
|
13
|
+
value: formatBigIntToSafeValue({ value, bigIntDecimal: decimal, decimal }),
|
|
14
|
+
});
|
|
15
|
+
}
|
|
9
16
|
}
|