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