@swapkit/helpers 4.5.7 → 4.5.9

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.
@@ -75,7 +75,7 @@ describe("BigIntArithmetics", () => {
75
75
  expect(num.toFixed(6)).toBe("0.000001");
76
76
  });
77
77
 
78
- test("handles negative numbers", () => {
78
+ test("handles negative numbers with toFixed", () => {
79
79
  const num = new BigIntArithmetics(-123.456);
80
80
  expect(num.toFixed(2)).toBe("-123.46");
81
81
  expect(num.toFixed(4)).toBe("-123.4560");
@@ -230,7 +230,7 @@ describe("BigIntArithmetics", () => {
230
230
  });
231
231
 
232
232
  describe("toAbbreviation edge cases", () => {
233
- test("handles negative numbers", () => {
233
+ test("handles negative numbers with abbreviation", () => {
234
234
  const num = new BigIntArithmetics(-1234567);
235
235
  expect(num.toAbbreviation()).toBe("-1.23M");
236
236
  });
@@ -260,37 +260,64 @@ describe("BigIntArithmetics", () => {
260
260
  });
261
261
 
262
262
  describe("toCurrency edge cases", () => {
263
- test("handles different currency symbols", () => {
263
+ test("currency symbols €, £, ¥", () => {
264
264
  const num = new BigIntArithmetics(1234.56);
265
- expect(num.toCurrency("€")).toContain("€");
266
- expect(num.toCurrency("£")).toContain("£");
267
- expect(num.toCurrency("¥")).toContain("¥");
265
+ expect(num.toCurrency("€")).toBe("€1,234.56");
266
+ expect(num.toCurrency("£")).toBe("£1,234.56");
267
+ expect(num.toCurrency("¥")).toBe("¥1,234.56");
268
268
  });
269
269
 
270
- test("handles currency position", () => {
270
+ test("currency position start and end", () => {
271
271
  const num = new BigIntArithmetics(1234.56);
272
- expect(num.toCurrency("€", { currencyPosition: "start" })).toMatch(/^€/);
273
- expect(num.toCurrency("€", { currencyPosition: "end" })).toMatch(/€$/);
272
+ expect(num.toCurrency("€", { currencyPosition: "start" })).toBe("€1,234.56");
273
+ expect(num.toCurrency("€", { currencyPosition: "end" })).toBe("1,234.56€");
274
274
  });
275
275
 
276
- test("handles custom separators", () => {
276
+ test("european format with custom separators", () => {
277
277
  const num = new BigIntArithmetics(1234567.89);
278
- const result = num.toCurrency("$", { decimalSeparator: ",", thousandSeparator: " " });
279
- expect(result).toContain(" ");
280
- expect(result).toContain(",");
278
+ expect(num.toCurrency("", { currencyPosition: "end", decimalSeparator: ",", thousandSeparator: "." })).toBe(
279
+ "1.234.567,89€",
280
+ );
281
281
  });
282
282
 
283
- test("handles zero with currency", () => {
284
- const num = new BigIntArithmetics(0);
285
- expect(num.toCurrency()).toContain("$");
286
- expect(num.toCurrency()).toContain("0");
283
+ test("small values < 1 rounds to decimal with trailing zeros removed without floating-point artifacts", () => {
284
+ expect(new BigIntArithmetics(0.015072).toCurrency("")).toBe("0.02");
285
+ expect(new BigIntArithmetics(0.333145).toCurrency("")).toBe("0.33");
286
+ expect(new BigIntArithmetics(0.000005).toCurrency("")).toBe("0");
287
+ expect(new BigIntArithmetics(0.00000548).toCurrency("", { decimal: 6 })).toBe("0.000005");
288
+ expect(new BigIntArithmetics(0.00003801).toCurrency("", { decimal: 6 })).toBe("0.000038");
289
+ });
290
+
291
+ test("small values strip trailing zeros", () => {
292
+ expect(new BigIntArithmetics(0.12).toCurrency("")).toBe("0.12");
293
+ expect(new BigIntArithmetics(0.1).toCurrency("")).toBe("0.1");
294
+ expect(new BigIntArithmetics(0.10000001).toCurrency("")).toBe("0.1");
295
+ });
296
+
297
+ test("negative small values", () => {
298
+ expect(new BigIntArithmetics(-0.015072).toCurrency("")).toBe("-0.02");
299
+ expect(new BigIntArithmetics(-0.00000001).toCurrency("", { decimal: 8 })).toBe("-0.00000001");
300
+ expect(new BigIntArithmetics(-0.00003801).toCurrency("", { decimal: 6 })).toBe("-0.000038");
301
+ expect(new BigIntArithmetics(-0.00000548).toCurrency("")).toBe("0");
302
+ });
303
+
304
+ test("values >= 1 round to decimal param", () => {
305
+ expect(new BigIntArithmetics(5.12).toCurrency("", { decimal: 2 })).toBe("5.12");
306
+ expect(new BigIntArithmetics(80.865327).toCurrency("", { decimal: 2 })).toBe("80.87");
307
+ expect(new BigIntArithmetics(33.432207).toCurrency("", { decimal: 2 })).toBe("33.43");
308
+ expect(new BigIntArithmetics(999.999).toCurrency("$")).toBe("$1,000");
309
+ expect(new BigIntArithmetics(0.0000000000000000000000000000001).toCurrency("", { decimal: 8 })).toBe("0");
310
+ });
311
+
312
+ test("zero value", () => {
313
+ expect(new BigIntArithmetics(0).toCurrency("$")).toBe("$0");
314
+ expect(new BigIntArithmetics(0).toCurrency("")).toBe("0");
287
315
  });
288
316
 
289
- test("handles custom decimal places", () => {
290
- const num = new BigIntArithmetics(1234.56789);
291
- const result = num.toCurrency("$", { decimal: 4 });
292
- expect(result).toContain("$");
293
- expect(result).toContain("1");
317
+ test("custom decimal separator for small values", () => {
318
+ expect(
319
+ new BigIntArithmetics(0.015072).toCurrency("", { currencyPosition: "end", decimal: 6, decimalSeparator: "," }),
320
+ ).toBe("0,015072€");
294
321
  });
295
322
  });
296
323
 
@@ -0,0 +1,125 @@
1
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2
+
3
+ import { FeeOption } from "../../types";
4
+ import {
5
+ applyFeeMultiplier,
6
+ applyFeeMultiplierToBigInt,
7
+ DEFAULT_FEE_MULTIPLIERS,
8
+ getFeeMultiplier,
9
+ getFeeMultiplierAsBigInt,
10
+ } from "../feeMultiplier";
11
+ import { SKConfig } from "../swapKitConfig";
12
+
13
+ describe("feeMultiplier", () => {
14
+ beforeEach(() => {
15
+ SKConfig.reinitialize();
16
+ });
17
+
18
+ afterEach(() => {
19
+ SKConfig.reinitialize();
20
+ });
21
+
22
+ describe("getFeeMultiplier", () => {
23
+ test("returns 1.0 for Average, 1.5 for Fast, 2.0 for Fastest", () => {
24
+ expect(getFeeMultiplier(FeeOption.Average)).toBe(1.0);
25
+ expect(getFeeMultiplier(FeeOption.Fast)).toBe(1.5);
26
+ expect(getFeeMultiplier(FeeOption.Fastest)).toBe(2.0);
27
+ });
28
+
29
+ test("defaults to Average when no option provided", () => {
30
+ expect(getFeeMultiplier()).toBe(1.0);
31
+ });
32
+
33
+ test("uses custom multipliers from SKConfig when set", () => {
34
+ SKConfig.set({ feeMultipliers: { [FeeOption.Average]: 1.2, [FeeOption.Fast]: 1.8, [FeeOption.Fastest]: 2.5 } });
35
+
36
+ expect(getFeeMultiplier(FeeOption.Average)).toBe(1.2);
37
+ expect(getFeeMultiplier(FeeOption.Fast)).toBe(1.8);
38
+ expect(getFeeMultiplier(FeeOption.Fastest)).toBe(2.5);
39
+ });
40
+ });
41
+
42
+ describe("getFeeMultiplierAsBigInt", () => {
43
+ test("converts multipliers to numerator/denominator for precise bigint math", () => {
44
+ expect(getFeeMultiplierAsBigInt(FeeOption.Average)).toEqual({ denominator: 10n, numerator: 10n });
45
+ expect(getFeeMultiplierAsBigInt(FeeOption.Fast)).toEqual({ denominator: 10n, numerator: 15n });
46
+ expect(getFeeMultiplierAsBigInt(FeeOption.Fastest)).toEqual({ denominator: 10n, numerator: 20n });
47
+ });
48
+
49
+ test("defaults to Average for bigint multiplier", () => {
50
+ expect(getFeeMultiplierAsBigInt()).toEqual({ denominator: 10n, numerator: 10n });
51
+ });
52
+ });
53
+
54
+ describe("applyFeeMultiplierToBigInt", () => {
55
+ test("applies multiplier to bigint values", () => {
56
+ expect(applyFeeMultiplierToBigInt(100n, FeeOption.Average)).toBe(100n);
57
+ expect(applyFeeMultiplierToBigInt(100n, FeeOption.Fast)).toBe(150n);
58
+ expect(applyFeeMultiplierToBigInt(100n, FeeOption.Fastest)).toBe(200n);
59
+ });
60
+
61
+ test("handles large values without overflow", () => {
62
+ expect(applyFeeMultiplierToBigInt(1000000000000000000n, FeeOption.Fastest)).toBe(2000000000000000000n);
63
+ });
64
+
65
+ test("defaults to Average for applyFeeMultiplierToBigInt", () => {
66
+ expect(applyFeeMultiplierToBigInt(100n)).toBe(100n);
67
+ });
68
+ });
69
+
70
+ describe("applyFeeMultiplier", () => {
71
+ test("applies multiplier to number values", () => {
72
+ expect(applyFeeMultiplier(100, FeeOption.Average)).toBe(100);
73
+ expect(applyFeeMultiplier(100, FeeOption.Fast)).toBe(150);
74
+ expect(applyFeeMultiplier(100, FeeOption.Fastest)).toBe(200);
75
+ });
76
+
77
+ test("floors result when floor=true", () => {
78
+ expect(applyFeeMultiplier(33, FeeOption.Fast, true)).toBe(49);
79
+ expect(applyFeeMultiplier(10.5, FeeOption.Fastest, true)).toBe(21);
80
+ });
81
+
82
+ test("preserves decimals when floor=false", () => {
83
+ expect(applyFeeMultiplier(33, FeeOption.Fast, false)).toBe(49.5);
84
+ });
85
+
86
+ test("defaults to Average for applyFeeMultiplier", () => {
87
+ expect(applyFeeMultiplier(100)).toBe(100);
88
+ });
89
+ });
90
+
91
+ describe("DEFAULT_FEE_MULTIPLIERS", () => {
92
+ test("exports correct default values", () => {
93
+ expect(DEFAULT_FEE_MULTIPLIERS[FeeOption.Average]).toBe(1.0);
94
+ expect(DEFAULT_FEE_MULTIPLIERS[FeeOption.Fast]).toBe(1.5);
95
+ expect(DEFAULT_FEE_MULTIPLIERS[FeeOption.Fastest]).toBe(2.0);
96
+ });
97
+ });
98
+
99
+ describe("edge cases", () => {
100
+ test("applies multiplier to zero value", () => {
101
+ expect(applyFeeMultiplierToBigInt(0n, FeeOption.Fastest)).toBe(0n);
102
+ expect(applyFeeMultiplier(0, FeeOption.Fastest)).toBe(0);
103
+ });
104
+
105
+ test("handles negative numbers", () => {
106
+ expect(applyFeeMultiplier(-100, FeeOption.Fast)).toBe(-150);
107
+ expect(applyFeeMultiplier(-100, FeeOption.Fastest)).toBe(-200);
108
+ });
109
+
110
+ test("handles negative bigint values", () => {
111
+ expect(applyFeeMultiplierToBigInt(-100n, FeeOption.Fast)).toBe(-150n);
112
+ expect(applyFeeMultiplierToBigInt(-100n, FeeOption.Fastest)).toBe(-200n);
113
+ });
114
+
115
+ test("handles decimal values with multiplier", () => {
116
+ expect(applyFeeMultiplier(0.5, FeeOption.Fastest)).toBe(1);
117
+ expect(applyFeeMultiplier(0.333, FeeOption.Fast)).toBeCloseTo(0.4995, 4);
118
+ });
119
+
120
+ test("handles very small bigint values", () => {
121
+ expect(applyFeeMultiplierToBigInt(1n, FeeOption.Fast)).toBe(1n); // 1 * 15 / 10 = 1 (integer division)
122
+ expect(applyFeeMultiplierToBigInt(5n, FeeOption.Fast)).toBe(7n); // 5 * 15 / 10 = 7
123
+ });
124
+ });
125
+ });
@@ -139,106 +139,6 @@ describe("SwapKitNumber", () => {
139
139
  });
140
140
  });
141
141
 
142
- describe("toSignificant", () => {
143
- describe("normal cases", () => {
144
- test("returns first significant number of digits", () => {
145
- const usdLikeNumber = new SwapKitNumber(1234.5678);
146
- expect(usdLikeNumber.toSignificant(2)).toBe("1200");
147
- expect(usdLikeNumber.toSignificant(3)).toBe("1230");
148
- expect(usdLikeNumber.toSignificant(4)).toBe("1234");
149
- expect(usdLikeNumber.toSignificant(5)).toBe("1234.5");
150
- expect(usdLikeNumber.toSignificant(6)).toBe("1234.56");
151
- expect(usdLikeNumber.toSignificant(7)).toBe("1234.567");
152
- expect(usdLikeNumber.toSignificant(8)).toBe("1234.5678");
153
-
154
- const btcLikeNumber = new SwapKitNumber(0.00005678);
155
- expect(btcLikeNumber.toSignificant(2)).toBe("0.000056");
156
- expect(btcLikeNumber.toSignificant(3)).toBe("0.0000567");
157
- expect(btcLikeNumber.toSignificant(4)).toBe("0.00005678");
158
- expect(btcLikeNumber.toSignificant(5)).toBe("0.00005678");
159
- expect(btcLikeNumber.toSignificant(8)).toBe("0.00005678");
160
- });
161
- });
162
-
163
- describe("custom decimals", () => {
164
- test("returns first significant number of digits", () => {
165
- const usdLikeNumber = new SwapKitNumber({ decimal: 2, value: 1234.5678 });
166
- expect(usdLikeNumber.toSignificant(2)).toBe("1200");
167
- expect(usdLikeNumber.toSignificant(3)).toBe("1230");
168
- expect(usdLikeNumber.toSignificant(4)).toBe("1234");
169
- expect(usdLikeNumber.toSignificant(5)).toBe("1234.5");
170
- expect(usdLikeNumber.toSignificant(6)).toBe("1234.57");
171
- expect(usdLikeNumber.toSignificant(7)).toBe("1234.57");
172
- expect(usdLikeNumber.toSignificant(8)).toBe("1234.57");
173
-
174
- const ethLikeNumber = new SwapKitNumber({ decimal: 18, value: 0.00005678 });
175
- expect(ethLikeNumber.toSignificant(2)).toBe("0.000056");
176
- expect(ethLikeNumber.toSignificant(3)).toBe("0.0000567");
177
- expect(ethLikeNumber.toSignificant(4)).toBe("0.00005678");
178
- expect(ethLikeNumber.toSignificant(5)).toBe("0.00005678");
179
- expect(ethLikeNumber.toSignificant(8)).toBe("0.00005678");
180
- expect(ethLikeNumber.toSignificant(18)).toBe("0.00005678");
181
- });
182
- });
183
- });
184
-
185
- describe("toAbbreviation", () => {
186
- test("returns abbreviation with up to 3 integer digits", () => {
187
- const skNumber = new SwapKitNumber(1234.5678);
188
- expect(skNumber.toAbbreviation()).toBe("1.23K");
189
-
190
- const skNumber2 = new SwapKitNumber(1234567.5678);
191
- expect(skNumber2.toAbbreviation()).toBe("1.23M");
192
-
193
- const skNumber3 = new SwapKitNumber(1234567890.5678);
194
- expect(skNumber3.toAbbreviation()).toBe("1.23B");
195
-
196
- const skNumber4 = new SwapKitNumber("1234567890123.5678");
197
- expect(skNumber4.toAbbreviation()).toBe("1.23T");
198
-
199
- const skNumber5 = new SwapKitNumber("1234567890123456.5678");
200
- expect(skNumber5.toAbbreviation()).toBe("1.23Q");
201
-
202
- const skNumber6 = new SwapKitNumber("1234567890123456789.5678");
203
- expect(skNumber6.toAbbreviation()).toBe("1.23Qi");
204
-
205
- const skNumber7 = new SwapKitNumber("1234567890123456789012.5678");
206
- expect(skNumber7.toAbbreviation()).toBe("1.23S");
207
-
208
- const skNumber8 = new SwapKitNumber(1234.5678);
209
- expect(skNumber8.toAbbreviation(0)).toBe("1K");
210
-
211
- const skNumber9 = new SwapKitNumber(1234.5678);
212
- expect(skNumber9.toAbbreviation(1)).toBe("1.2K");
213
-
214
- const skNumber10 = new SwapKitNumber(123456.78);
215
- expect(skNumber10.toAbbreviation()).toBe("123.46K");
216
- });
217
- });
218
-
219
- describe("toCurrency", () => {
220
- test("returns abbreviation with up to 3 integer digits", () => {
221
- const skNumber = new SwapKitNumber(1234.5678);
222
- expect(skNumber.toCurrency()).toBe("$1,234.57");
223
- expect(skNumber.toCurrency("€", { currencyPosition: "end", decimalSeparator: ",", thousandSeparator: " " })).toBe(
224
- "1 234,57€",
225
- );
226
-
227
- const skNumber2 = new SwapKitNumber(0.5678);
228
- expect(skNumber2.toCurrency()).toBe("$0.5678");
229
- expect(skNumber2.toCurrency("€", { currencyPosition: "end", decimalSeparator: "," })).toBe("0,5678€");
230
-
231
- const skNumber3 = new SwapKitNumber(0.00005678);
232
- expect(skNumber3.toCurrency()).toBe("$0.00005678");
233
- expect(
234
- skNumber3.toCurrency("€", { currencyPosition: "end", decimalSeparator: ",", thousandSeparator: " " }),
235
- ).toBe("0,00005678€");
236
-
237
- const skNumber4 = new SwapKitNumber(12345);
238
- expect(skNumber4.toCurrency()).toBe("$12,345");
239
- });
240
- });
241
-
242
142
  describe("add", () => {
243
143
  test("adds same type numbers correctly", () => {
244
144
  const skNumber1 = new SwapKitNumber(10);
@@ -183,7 +183,8 @@ export class BigIntArithmetics {
183
183
  const valueStr = this.getValue("string");
184
184
  const isNegative = valueStr.startsWith("-");
185
185
  const [int = "0", dec = ""] = (isNegative ? valueStr.slice(1) : valueStr).split(".");
186
- const sign = isNegative ? "-" : "";
186
+ const valueRoundsToZero = int === "0" && Number.parseInt(dec.slice(0, fixedDigits), 10) === 0;
187
+ const sign = isNegative && !valueRoundsToZero ? "-" : "";
187
188
 
188
189
  if (fixedDigits === 0) {
189
190
  if (int === "0" && !dec) return "0";
@@ -219,29 +220,27 @@ export class BigIntArithmetics {
219
220
 
220
221
  toCurrency(
221
222
  currency = "$",
222
- { currencyPosition = "start", decimal = 2, decimalSeparator = ".", thousandSeparator = "," } = {},
223
+ {
224
+ currencyPosition = "start",
225
+ decimal = 2,
226
+ decimalSeparator = ".",
227
+ thousandSeparator = ",",
228
+ trimTrailingZeros = true,
229
+ } = {},
223
230
  ) {
224
- const valueStr = this.getValue("string");
225
- const [int = "0", dec = ""] = valueStr.split(".");
226
-
227
- if (int === "0" && dec) {
228
- const formatted = `${Number.parseFloat(`0.${dec}`)}`.replace(".", decimalSeparator);
229
- return match(currencyPosition)
230
- .with("start", () => `${currency}${formatted}`)
231
- .with("end", () => `${formatted}${currency}`)
232
- .otherwise(() => `${currency}${formatted}`);
233
- }
231
+ const fixedValue = this.toFixed(decimal);
232
+ const isCurrencyAtEnd = currencyPosition === "end";
233
+ const [int = "0", dec = ""] = fixedValue.split(".");
234
+
235
+ const formattedInt = int.replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator);
236
+ const hasDecimals = dec && Number.parseInt(dec, 10) > 0;
237
+ const formattedValue = hasDecimals ? `${formattedInt}${decimalSeparator}${dec}` : formattedInt;
234
238
 
235
- const roundedStr = this.toFixed(decimal);
236
- const [roundedInt = "0", roundedDec = ""] = roundedStr.split(".");
237
- const formattedInt = roundedInt.replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator);
238
- const hasDecimals = roundedDec && Number.parseInt(roundedDec, 10) > 0;
239
- const value = hasDecimals ? `${formattedInt}${decimalSeparator}${roundedDec}` : formattedInt;
239
+ // Prevent regex from taking too long for large values
240
+ const canTrimTrailingZeros = formattedValue.length < 100 && trimTrailingZeros && hasDecimals;
241
+ const value = canTrimTrailingZeros ? formattedValue.replace(/\.?0*$/, "") : formattedValue;
240
242
 
241
- return match(currencyPosition)
242
- .with("start", () => `${currency}${value}`)
243
- .with("end", () => `${value}${currency}`)
244
- .otherwise(() => `${currency}${value}`);
243
+ return isCurrencyAtEnd ? `${value}${currency}` : `${currency}${value}`;
245
244
  }
246
245
 
247
246
  formatBigIntToSafeValue(value: bigint, decimal?: number) {
@@ -1,16 +1,142 @@
1
1
  import { describe, expect, test } from "bun:test";
2
+ import { Chain } from "@swapkit/types";
2
3
 
3
4
  import type { DerivationPathArray } from "../../types";
4
- import { derivationPathToString } from "../derivationPath";
5
+ import {
6
+ DerivationPath,
7
+ derivationPathToString,
8
+ getDerivationPathFor,
9
+ getWalletFormatFor,
10
+ updateDerivationPath,
11
+ } from "../derivationPath";
5
12
 
6
13
  describe("derivationPathToString", () => {
7
- test("should return the correct string for a full path", () => {
8
- const path = [1, 2, 3, 4, 5] as DerivationPathArray;
9
- expect(derivationPathToString(path)).toEqual("m/1'/2'/3'/4/5");
14
+ test("full 5-element path", () => {
15
+ expect(derivationPathToString([44, 60, 0, 0, 0] as DerivationPathArray)).toBe("m/44'/60'/0'/0/0");
16
+ expect(derivationPathToString([84, 0, 0, 0, 5] as DerivationPathArray)).toBe("m/84'/0'/0'/0/5");
10
17
  });
11
18
 
12
- test("should return the correct string for a short path", () => {
13
- const path = [1, 2, 3, 4] as DerivationPathArray;
14
- expect(derivationPathToString(path)).toEqual("m/1'/2'/3'/4");
19
+ test("4-element path without index", () => {
20
+ expect(derivationPathToString([44, 60, 0, 0] as DerivationPathArray)).toBe("m/44'/60'/0'/0");
21
+ expect(derivationPathToString([49, 2, 0, 1] as DerivationPathArray)).toBe("m/49'/2'/0'/1");
22
+ });
23
+
24
+ test("3-element account path", () => {
25
+ expect(derivationPathToString([44, 60, 0] as unknown as DerivationPathArray)).toBe("m/44'/60'/0'");
26
+ expect(derivationPathToString([44, 501, 5] as unknown as DerivationPathArray)).toBe("m/44'/501'/5'");
27
+ });
28
+ });
29
+
30
+ describe("updateDerivationPath", () => {
31
+ const basePath: DerivationPathArray = [44, 60, 0, 0, 0];
32
+
33
+ test("updates index (last element)", () => {
34
+ expect(updateDerivationPath(basePath, { index: 5 })).toEqual([44, 60, 0, 0, 5]);
35
+ expect(updateDerivationPath(basePath, { index: 100 })).toEqual([44, 60, 0, 0, 100]);
36
+ });
37
+
38
+ test("updates change (4th element)", () => {
39
+ expect(updateDerivationPath(basePath, { change: 1 })).toEqual([44, 60, 0, 1, 0]);
40
+ expect(updateDerivationPath([84, 0, 2, 0, 3], { change: 1 })).toEqual([84, 0, 2, 1, 3]);
41
+ });
42
+
43
+ test("updates account (3rd element)", () => {
44
+ expect(updateDerivationPath(basePath, { account: 5 })).toEqual([44, 60, 5, 0, 0]);
45
+ expect(updateDerivationPath([84, 0, 0, 1, 10], { account: 3 })).toEqual([84, 0, 3, 1, 10]);
46
+ });
47
+
48
+ test("returns unchanged path for empty params", () => {
49
+ expect(updateDerivationPath(basePath, {} as any)).toEqual(basePath);
50
+ });
51
+ });
52
+
53
+ describe("getDerivationPathFor", () => {
54
+ describe("EVM chains", () => {
55
+ test("Ethereum default path", () => {
56
+ expect(getDerivationPathFor({ chain: Chain.Ethereum, index: 0 })).toEqual([44, 60, 0, 0, 0]);
57
+ expect(getDerivationPathFor({ chain: Chain.Ethereum, index: 5 })).toEqual([44, 60, 0, 0, 5]);
58
+ });
59
+
60
+ test("Ethereum legacy type", () => {
61
+ expect(getDerivationPathFor({ chain: Chain.Ethereum, index: 3, type: "legacy" })).toEqual([44, 60, 0, 3]);
62
+ });
63
+
64
+ test("Ethereum account type", () => {
65
+ expect(getDerivationPathFor({ chain: Chain.Ethereum, index: 2, type: "account" })).toEqual([44, 60, 0, 2]);
66
+ });
67
+
68
+ test("Ethereum ledgerLive type", () => {
69
+ expect(getDerivationPathFor({ chain: Chain.Ethereum, index: 0, type: "ledgerLive" })).toEqual([44, 60, 0, 0, 0]);
70
+ expect(getDerivationPathFor({ addressIndex: 1, chain: Chain.Ethereum, index: 2, type: "ledgerLive" })).toEqual([
71
+ 44, 60, 2, 0, 1,
72
+ ]);
73
+ });
74
+
75
+ test("other EVM chains use same derivation", () => {
76
+ expect(getDerivationPathFor({ chain: Chain.BinanceSmartChain, index: 0 })).toEqual([44, 60, 0, 0, 0]);
77
+ expect(getDerivationPathFor({ chain: Chain.Avalanche, index: 0 })).toEqual([44, 60, 0, 0, 0]);
78
+ expect(getDerivationPathFor({ chain: Chain.Arbitrum, index: 0 })).toEqual([44, 60, 0, 0, 0]);
79
+ });
80
+ });
81
+
82
+ describe("Solana", () => {
83
+ test("default path", () => {
84
+ const result = getDerivationPathFor({ chain: Chain.Solana, index: 0 });
85
+ expect(result[1]).toBe(501);
86
+ });
87
+
88
+ test("account type", () => {
89
+ expect(getDerivationPathFor({ chain: Chain.Solana, index: 3, type: "account" })).toEqual([44, 501, 0, 3]);
90
+ });
91
+ });
92
+
93
+ describe("UTXO chains", () => {
94
+ test("Bitcoin nativeSegwitMiddleAccount", () => {
95
+ expect(getDerivationPathFor({ chain: Chain.Bitcoin, index: 0, type: "nativeSegwitMiddleAccount" })).toEqual([
96
+ 84, 0, 0, 0, 0,
97
+ ]);
98
+ expect(
99
+ getDerivationPathFor({ addressIndex: 5, chain: Chain.Bitcoin, index: 2, type: "nativeSegwitMiddleAccount" }),
100
+ ).toEqual([84, 0, 2, 0, 5]);
101
+ });
102
+
103
+ test("Bitcoin segwit", () => {
104
+ expect(getDerivationPathFor({ chain: Chain.Bitcoin, index: 3, type: "segwit" })).toEqual([49, 0, 0, 0, 3]);
105
+ });
106
+
107
+ test("Bitcoin legacy", () => {
108
+ expect(getDerivationPathFor({ chain: Chain.Bitcoin, index: 0, type: "legacy" })).toEqual([44, 0, 0, 0, 0]);
109
+ expect(getDerivationPathFor({ chain: Chain.Bitcoin, index: 5, type: "legacy" })).toEqual([44, 0, 0, 0, 5]);
110
+ });
111
+
112
+ test("Litecoin uses chainId 2", () => {
113
+ expect(getDerivationPathFor({ chain: Chain.Litecoin, index: 0, type: "legacy" })).toEqual([44, 2, 0, 0, 0]);
114
+ expect(getDerivationPathFor({ chain: Chain.Litecoin, index: 0, type: "segwit" })).toEqual([49, 2, 0, 0, 0]);
115
+ });
116
+ });
117
+ });
118
+
119
+ describe("getWalletFormatFor", () => {
120
+ test("returns legacy for purpose 44", () => {
121
+ expect(getWalletFormatFor("m/44'/0'/0'/0/0")).toBe("legacy");
122
+ expect(getWalletFormatFor("m/44'/60'/0'/0/0")).toBe("legacy");
123
+ });
124
+
125
+ test("returns p2sh for purpose 49", () => {
126
+ expect(getWalletFormatFor("m/49'/0'/0'/0/0")).toBe("p2sh");
127
+ expect(getWalletFormatFor("m/49'/2'/0'/0/0")).toBe("p2sh");
128
+ });
129
+
130
+ test("returns bech32 for purpose 84 and others", () => {
131
+ expect(getWalletFormatFor("m/84'/0'/0'/0/0")).toBe("bech32");
132
+ expect(getWalletFormatFor("m/86'/0'/0'/0/0")).toBe("bech32");
133
+ });
134
+ });
135
+
136
+ describe("DerivationPath export", () => {
137
+ test("exports string paths for common chains", () => {
138
+ expect(typeof DerivationPath[Chain.Ethereum]).toBe("string");
139
+ expect(typeof DerivationPath[Chain.Bitcoin]).toBe("string");
140
+ expect(DerivationPath[Chain.Ethereum]).toMatch(/^m\/\d+'\/\d+'\/\d+'/);
15
141
  });
16
142
  });