@swapkit/helpers 1.0.0-rc.6 → 1.0.0-rc.61

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