@ledgerhq/coin-framework 0.3.5 → 0.3.6-next.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/.eslintrc.js +8 -46
- package/CHANGELOG.md +13 -0
- package/package.json +9 -18
- package/src/account/accountId.ts +20 -30
- package/src/account/accountName.ts +1 -4
- package/src/account/balanceHistoryCache.ts +18 -37
- package/src/account/groupOperations.ts +4 -6
- package/src/account/helpers.test.ts +6 -26
- package/src/account/helpers.ts +33 -66
- package/src/account/ordering.ts +10 -18
- package/src/account/pending.ts +6 -15
- package/src/account/serialization.ts +8 -19
- package/src/account/support.ts +8 -18
- package/src/account.test.ts +25 -40
- package/src/bot/specs.ts +24 -43
- package/src/bot/types.ts +1 -1
- package/src/bridge/getAddressWrapper.ts +5 -13
- package/src/bridge/jsHelpers.ts +215 -259
- package/src/cache.ts +4 -4
- package/src/currencies/BigNumberToLocaleString.test.ts +25 -33
- package/src/currencies/BigNumberToLocaleString.ts +3 -8
- package/src/currencies/CurrencyURIScheme.ts +1 -3
- package/src/currencies/chopCurrencyUnitDecimals.ts +1 -4
- package/src/currencies/formatCurrencyUnit.ts +11 -21
- package/src/currencies/index.ts +1 -4
- package/src/currencies/localeUtility.ts +2 -4
- package/src/currencies/parseCurrencyUnit.ts +1 -4
- package/src/currencies/sanitizeValueString.ts +1 -1
- package/src/currencies/support.ts +3 -9
- package/src/derivation.test.ts +1 -4
- package/src/derivation.ts +45 -95
- package/src/errors.test.ts +1 -1
- package/src/errors.ts +2 -6
- package/src/mocks/account.ts +27 -80
- package/src/mocks/fixtures/nfts.test.ts +2 -6
- package/src/mocks/fixtures/nfts.ts +12 -38
- package/src/mocks/helpers.ts +2 -8
- package/src/nft/nftId.ts +2 -2
- package/src/operation.test.ts +6 -31
- package/src/operation.ts +12 -26
- package/src/transaction/common.ts +9 -22
|
@@ -9,12 +9,8 @@ test("basic toLocaleString usage", () => {
|
|
|
9
9
|
expect(toLocaleString(new BigNumber(123.01))).toBe("123.01");
|
|
10
10
|
expect(toLocaleString(new BigNumber(123.012))).toBe("123.012");
|
|
11
11
|
expect(toLocaleString(new BigNumber(1123))).toBe("1,123");
|
|
12
|
-
expect(toLocaleString(new BigNumber("9999999999999999"))).toBe(
|
|
13
|
-
|
|
14
|
-
);
|
|
15
|
-
expect(toLocaleString(new BigNumber("9999999999999.99"))).toBe(
|
|
16
|
-
"9,999,999,999,999.99"
|
|
17
|
-
);
|
|
12
|
+
expect(toLocaleString(new BigNumber("9999999999999999"))).toBe("9,999,999,999,999,999");
|
|
13
|
+
expect(toLocaleString(new BigNumber("9999999999999.99"))).toBe("9,999,999,999,999.99");
|
|
18
14
|
});
|
|
19
15
|
test("toLocaleString to default maximumFractionDigits to 3", () => {
|
|
20
16
|
expect(toLocaleString(new BigNumber(4.44444))).toBe("4.444");
|
|
@@ -36,62 +32,62 @@ test("toLocaleString minimumFractionDigits", () => {
|
|
|
36
32
|
expect(
|
|
37
33
|
toLocaleString(new BigNumber(0), "en", {
|
|
38
34
|
minimumFractionDigits: 1,
|
|
39
|
-
})
|
|
35
|
+
}),
|
|
40
36
|
).toBe("0.0");
|
|
41
37
|
expect(
|
|
42
38
|
toLocaleString(new BigNumber(8), "en", {
|
|
43
39
|
minimumFractionDigits: 1,
|
|
44
|
-
})
|
|
40
|
+
}),
|
|
45
41
|
).toBe("8.0");
|
|
46
42
|
expect(
|
|
47
43
|
toLocaleString(new BigNumber(123), "en", {
|
|
48
44
|
minimumFractionDigits: 1,
|
|
49
|
-
})
|
|
45
|
+
}),
|
|
50
46
|
).toBe("123.0");
|
|
51
47
|
expect(
|
|
52
48
|
toLocaleString(new BigNumber(0.001), "en", {
|
|
53
49
|
minimumFractionDigits: 1,
|
|
54
|
-
})
|
|
50
|
+
}),
|
|
55
51
|
).toBe("0.001");
|
|
56
52
|
expect(
|
|
57
53
|
toLocaleString(new BigNumber(9.5), "en", {
|
|
58
54
|
minimumFractionDigits: 1,
|
|
59
|
-
})
|
|
55
|
+
}),
|
|
60
56
|
).toBe("9.5");
|
|
61
57
|
expect(
|
|
62
58
|
toLocaleString(new BigNumber(9.6), "en", {
|
|
63
59
|
minimumFractionDigits: 2,
|
|
64
|
-
})
|
|
60
|
+
}),
|
|
65
61
|
).toBe("9.60");
|
|
66
62
|
expect(
|
|
67
63
|
toLocaleString(new BigNumber(13.1), "en", {
|
|
68
64
|
minimumFractionDigits: 3,
|
|
69
|
-
})
|
|
65
|
+
}),
|
|
70
66
|
).toBe("13.100");
|
|
71
67
|
expect(
|
|
72
68
|
toLocaleString(new BigNumber(123.01), "en", {
|
|
73
69
|
minimumFractionDigits: 5,
|
|
74
|
-
})
|
|
70
|
+
}),
|
|
75
71
|
).toBe("123.01000");
|
|
76
72
|
expect(
|
|
77
73
|
toLocaleString(new BigNumber(123.012), "en", {
|
|
78
74
|
minimumFractionDigits: 10,
|
|
79
|
-
})
|
|
75
|
+
}),
|
|
80
76
|
).toBe("123.0120000000");
|
|
81
77
|
expect(
|
|
82
78
|
toLocaleString(new BigNumber(1123), "en", {
|
|
83
79
|
minimumFractionDigits: 1,
|
|
84
|
-
})
|
|
80
|
+
}),
|
|
85
81
|
).toBe("1,123.0");
|
|
86
82
|
expect(
|
|
87
83
|
toLocaleString(new BigNumber("9999999999999999"), "en", {
|
|
88
84
|
minimumFractionDigits: 1,
|
|
89
|
-
})
|
|
85
|
+
}),
|
|
90
86
|
).toBe("9,999,999,999,999,999.0");
|
|
91
87
|
expect(
|
|
92
88
|
toLocaleString(new BigNumber("9999999999999.999"), "en", {
|
|
93
89
|
minimumFractionDigits: 5,
|
|
94
|
-
})
|
|
90
|
+
}),
|
|
95
91
|
).toBe("9,999,999,999,999.99900");
|
|
96
92
|
});
|
|
97
93
|
test("toLocaleString minimumFractionDigits and maximumFractionDigits", () => {
|
|
@@ -99,57 +95,53 @@ test("toLocaleString minimumFractionDigits and maximumFractionDigits", () => {
|
|
|
99
95
|
toLocaleString(new BigNumber(1), "en", {
|
|
100
96
|
minimumFractionDigits: 1,
|
|
101
97
|
maximumFractionDigits: 5,
|
|
102
|
-
})
|
|
98
|
+
}),
|
|
103
99
|
).toBe("1.0");
|
|
104
100
|
expect(
|
|
105
101
|
toLocaleString(new BigNumber(1.003), "en", {
|
|
106
102
|
minimumFractionDigits: 1,
|
|
107
103
|
maximumFractionDigits: 5,
|
|
108
|
-
})
|
|
104
|
+
}),
|
|
109
105
|
).toBe("1.003");
|
|
110
106
|
expect(
|
|
111
107
|
toLocaleString(new BigNumber(1.000003), "en", {
|
|
112
108
|
minimumFractionDigits: 1,
|
|
113
109
|
maximumFractionDigits: 5,
|
|
114
|
-
})
|
|
110
|
+
}),
|
|
115
111
|
).toBe("1.0");
|
|
116
112
|
expect(
|
|
117
113
|
toLocaleString(new BigNumber(1.333333333333), "en", {
|
|
118
114
|
minimumFractionDigits: 1,
|
|
119
115
|
maximumFractionDigits: 5,
|
|
120
|
-
})
|
|
116
|
+
}),
|
|
121
117
|
).toBe("1.33333");
|
|
122
118
|
expect(
|
|
123
119
|
toLocaleString(new BigNumber(0), "en", {
|
|
124
120
|
minimumFractionDigits: 1,
|
|
125
121
|
maximumFractionDigits: 5,
|
|
126
|
-
})
|
|
122
|
+
}),
|
|
127
123
|
).toBe("0.0");
|
|
128
124
|
expect(
|
|
129
125
|
toLocaleString(new BigNumber(0.003), "en", {
|
|
130
126
|
minimumFractionDigits: 1,
|
|
131
127
|
maximumFractionDigits: 5,
|
|
132
|
-
})
|
|
128
|
+
}),
|
|
133
129
|
).toBe("0.003");
|
|
134
130
|
expect(
|
|
135
131
|
toLocaleString(new BigNumber(0.000003), "en", {
|
|
136
132
|
minimumFractionDigits: 1,
|
|
137
133
|
maximumFractionDigits: 5,
|
|
138
|
-
})
|
|
134
|
+
}),
|
|
139
135
|
).toBe("0.0");
|
|
140
136
|
expect(
|
|
141
137
|
toLocaleString(new BigNumber(9.7), "en", {
|
|
142
138
|
minimumFractionDigits: 1,
|
|
143
139
|
maximumFractionDigits: 1,
|
|
144
|
-
})
|
|
140
|
+
}),
|
|
145
141
|
).toBe("9.7");
|
|
146
142
|
expect(
|
|
147
|
-
toLocaleString(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
{
|
|
151
|
-
maximumFractionDigits: 20,
|
|
152
|
-
}
|
|
153
|
-
)
|
|
143
|
+
toLocaleString(new BigNumber("4.4444444444444444444411111111111111"), "en", {
|
|
144
|
+
maximumFractionDigits: 20,
|
|
145
|
+
}),
|
|
154
146
|
).toBe("4.44444444444444444444");
|
|
155
147
|
});
|
|
@@ -28,14 +28,12 @@ const getFormatForLocale = (locale: string) => {
|
|
|
28
28
|
export const toLocaleString = (
|
|
29
29
|
n: BigNumber,
|
|
30
30
|
localeInput?: string,
|
|
31
|
-
options: Partial<SupportedOptions> = {}
|
|
31
|
+
options: Partial<SupportedOptions> = {},
|
|
32
32
|
): string => {
|
|
33
33
|
let locale = localeInput;
|
|
34
34
|
if (!locale) locale = "en";
|
|
35
35
|
const minimumFractionDigits: number =
|
|
36
|
-
"minimumFractionDigits" in options
|
|
37
|
-
? (options.minimumFractionDigits as number)
|
|
38
|
-
: 0;
|
|
36
|
+
"minimumFractionDigits" in options ? (options.minimumFractionDigits as number) : 0;
|
|
39
37
|
const maximumFractionDigits: number =
|
|
40
38
|
"maximumFractionDigits" in options
|
|
41
39
|
? (options.maximumFractionDigits as number)
|
|
@@ -54,10 +52,7 @@ export const toLocaleString = (
|
|
|
54
52
|
const maxDecimals = bn.toFormat(maximumFractionDigits, BigNumber.ROUND_FLOOR);
|
|
55
53
|
|
|
56
54
|
if (maximumFractionDigits !== minimumFractionDigits) {
|
|
57
|
-
const minDecimals = bn.toFormat(
|
|
58
|
-
minimumFractionDigits,
|
|
59
|
-
BigNumber.ROUND_FLOOR
|
|
60
|
-
);
|
|
55
|
+
const minDecimals = bn.toFormat(minimumFractionDigits, BigNumber.ROUND_FLOOR);
|
|
61
56
|
let i = maxDecimals.length;
|
|
62
57
|
|
|
63
58
|
// cleanup useless '0's from the right until the minimumFractionDigits
|
|
@@ -46,9 +46,7 @@ export function decodeURIScheme(str: string): Data {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
const [, , scheme, address, , queryStr] = m;
|
|
49
|
-
const query: Record<string, any> = queryStr
|
|
50
|
-
? querystring.parse(queryStr)
|
|
51
|
-
: {};
|
|
49
|
+
const query: Record<string, any> = queryStr ? querystring.parse(queryStr) : {};
|
|
52
50
|
const currency = findCryptoCurrencyByScheme(scheme);
|
|
53
51
|
|
|
54
52
|
if (!currency) {
|
|
@@ -7,10 +7,7 @@
|
|
|
7
7
|
import type { Unit } from "@ledgerhq/types-cryptoassets";
|
|
8
8
|
|
|
9
9
|
// - useGrouping: true
|
|
10
|
-
export const chopCurrencyUnitDecimals = (
|
|
11
|
-
unit: Unit,
|
|
12
|
-
valueString: string
|
|
13
|
-
): string => {
|
|
10
|
+
export const chopCurrencyUnitDecimals = (unit: Unit, valueString: string): string => {
|
|
14
11
|
let str = "";
|
|
15
12
|
let decimals = -1;
|
|
16
13
|
|
|
@@ -53,7 +53,7 @@ type FormatFragmentTypes = "value" | "sign" | "code" | "separator";
|
|
|
53
53
|
export function formatCurrencyUnitFragment(
|
|
54
54
|
unit: Unit,
|
|
55
55
|
value: BigNumber,
|
|
56
|
-
_options?: formatCurrencyUnitOptions
|
|
56
|
+
_options?: formatCurrencyUnitOptions,
|
|
57
57
|
): FormatFragment[] {
|
|
58
58
|
if (!BigNumber.isBigNumber(value)) {
|
|
59
59
|
console.warn("formatCurrencyUnit called with value=", value);
|
|
@@ -70,10 +70,7 @@ export function formatCurrencyUnitFragment(
|
|
|
70
70
|
return [];
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
const options: Record<
|
|
74
|
-
string,
|
|
75
|
-
formatCurrencyUnitOptions[keyof formatCurrencyUnitOptions]
|
|
76
|
-
> = {};
|
|
73
|
+
const options: Record<string, formatCurrencyUnitOptions[keyof formatCurrencyUnitOptions]> = {};
|
|
77
74
|
|
|
78
75
|
if (_options) {
|
|
79
76
|
let k: keyof formatCurrencyUnitOptions;
|
|
@@ -109,20 +106,14 @@ export function formatCurrencyUnitFragment(
|
|
|
109
106
|
Math.max(
|
|
110
107
|
0, // dynamic max number of digits based on the value itself. to only show significant part
|
|
111
108
|
Math.min(
|
|
112
|
-
dynamicSignificantDigits -
|
|
113
|
-
Math.ceil(Math.log10(floatValueAbs.toNumber())),
|
|
109
|
+
dynamicSignificantDigits - Math.ceil(Math.log10(floatValueAbs.toNumber())),
|
|
114
110
|
magnitude + subMagnitude,
|
|
115
|
-
staticSignificantDigits
|
|
116
|
-
)
|
|
117
|
-
)
|
|
111
|
+
staticSignificantDigits,
|
|
112
|
+
),
|
|
113
|
+
),
|
|
118
114
|
);
|
|
119
115
|
const fragValueByKind = {
|
|
120
|
-
sign:
|
|
121
|
-
alwaysShowSign || floatValue.isNegative()
|
|
122
|
-
? floatValue.isNegative()
|
|
123
|
-
? "-"
|
|
124
|
-
: "+"
|
|
125
|
-
: null,
|
|
116
|
+
sign: alwaysShowSign || floatValue.isNegative() ? (floatValue.isNegative() ? "-" : "+") : null,
|
|
126
117
|
code: showCode ? code : null,
|
|
127
118
|
value: discreet
|
|
128
119
|
? "***"
|
|
@@ -136,7 +127,7 @@ export function formatCurrencyUnitFragment(
|
|
|
136
127
|
const frags: FormatFragment[] = [];
|
|
137
128
|
let nonSepIndex = -1;
|
|
138
129
|
let sepConsumed = true;
|
|
139
|
-
(unit.prefixCode ? prefixFormat : suffixFormat).forEach(
|
|
130
|
+
(unit.prefixCode ? prefixFormat : suffixFormat).forEach(kind => {
|
|
140
131
|
const v = fragValueByKind[kind];
|
|
141
132
|
if (!v) return;
|
|
142
133
|
const isSep = kind === "separator";
|
|
@@ -156,12 +147,11 @@ export function formatCurrencyUnitFragment(
|
|
|
156
147
|
export function formatCurrencyUnit(
|
|
157
148
|
unit: Unit,
|
|
158
149
|
value: BigNumber,
|
|
159
|
-
options?: formatCurrencyUnitOptions
|
|
150
|
+
options?: formatCurrencyUnitOptions,
|
|
160
151
|
): string {
|
|
161
152
|
const joinFragmentsSeparator =
|
|
162
|
-
(options && options.joinFragmentsSeparator) ||
|
|
163
|
-
defaultFormatOptions.joinFragmentsSeparator;
|
|
153
|
+
(options && options.joinFragmentsSeparator) || defaultFormatOptions.joinFragmentsSeparator;
|
|
164
154
|
return formatCurrencyUnitFragment(unit, value, options)
|
|
165
|
-
.map(
|
|
155
|
+
.map(f => f.value)
|
|
166
156
|
.join(joinFragmentsSeparator);
|
|
167
157
|
}
|
package/src/currencies/index.ts
CHANGED
|
@@ -27,10 +27,7 @@ import {
|
|
|
27
27
|
export * from "./support";
|
|
28
28
|
import { parseCurrencyUnit } from "./parseCurrencyUnit";
|
|
29
29
|
import { chopCurrencyUnitDecimals } from "./chopCurrencyUnitDecimals";
|
|
30
|
-
import {
|
|
31
|
-
formatCurrencyUnit,
|
|
32
|
-
formatCurrencyUnitFragment,
|
|
33
|
-
} from "./formatCurrencyUnit";
|
|
30
|
+
import { formatCurrencyUnit, formatCurrencyUnitFragment } from "./formatCurrencyUnit";
|
|
34
31
|
import { formatShort } from "./formatShort";
|
|
35
32
|
import { valueFromUnit } from "./valueFromUnit";
|
|
36
33
|
import type { Currency } from "@ledgerhq/types-cryptoassets";
|
|
@@ -25,10 +25,8 @@ export type GetSeparators = (locale: string) => {
|
|
|
25
25
|
decimal: string | null | undefined;
|
|
26
26
|
thousands: string | null | undefined;
|
|
27
27
|
};
|
|
28
|
-
export const getSeparators: GetSeparators = memoize(
|
|
29
|
-
const res = localeNotAvailable
|
|
30
|
-
? getFallback(locale)[1]
|
|
31
|
-
: (10000.2).toLocaleString(locale);
|
|
28
|
+
export const getSeparators: GetSeparators = memoize(locale => {
|
|
29
|
+
const res = localeNotAvailable ? getFallback(locale)[1] : (10000.2).toLocaleString(locale);
|
|
32
30
|
let decimal;
|
|
33
31
|
let thousands;
|
|
34
32
|
|
|
@@ -5,10 +5,7 @@ import { BigNumber } from "bignumber.js";
|
|
|
5
5
|
// make sure you have at least following options set on the formatter:
|
|
6
6
|
// - useGrouping: true
|
|
7
7
|
// - showCode: false
|
|
8
|
-
export const parseCurrencyUnit = (
|
|
9
|
-
unit: Unit,
|
|
10
|
-
valueString: string
|
|
11
|
-
): BigNumber => {
|
|
8
|
+
export const parseCurrencyUnit = (unit: Unit, valueString: string): BigNumber => {
|
|
12
9
|
const str = valueString.replace(/,/g, ".");
|
|
13
10
|
const value = new BigNumber(str);
|
|
14
11
|
if (value.isNaN()) return new BigNumber(0);
|
|
@@ -3,11 +3,7 @@ import {
|
|
|
3
3
|
getCryptoCurrencyById,
|
|
4
4
|
hasCryptoCurrencyId,
|
|
5
5
|
} from "@ledgerhq/cryptoassets";
|
|
6
|
-
import {
|
|
7
|
-
CryptoCurrency,
|
|
8
|
-
CryptoCurrencyId,
|
|
9
|
-
FiatCurrency,
|
|
10
|
-
} from "@ledgerhq/types-cryptoassets";
|
|
6
|
+
import { CryptoCurrency, CryptoCurrencyId, FiatCurrency } from "@ledgerhq/types-cryptoassets";
|
|
11
7
|
import { getEnv } from "@ledgerhq/live-env";
|
|
12
8
|
|
|
13
9
|
// set by user side effect to precise which currencies are considered supported (typically by live)
|
|
@@ -81,16 +77,14 @@ export function listSupportedFiats(): FiatCurrency[] {
|
|
|
81
77
|
|
|
82
78
|
export function setSupportedCurrencies(ids: CryptoCurrencyId[]) {
|
|
83
79
|
userSupportedCurrencies = Array.from(new Set(ids)) // Make sure to remove duplicates
|
|
84
|
-
.map(
|
|
80
|
+
.map(id => getCryptoCurrencyById(id));
|
|
85
81
|
}
|
|
86
82
|
|
|
87
83
|
function getExperimentalSupports() {
|
|
88
84
|
return getEnv("EXPERIMENTAL_CURRENCIES")
|
|
89
85
|
.split(",")
|
|
90
86
|
.filter(
|
|
91
|
-
(id: string) =>
|
|
92
|
-
hasCryptoCurrencyId(id) &&
|
|
93
|
-
!userSupportedCurrencies.find((c) => c.id === id)
|
|
87
|
+
(id: string) => hasCryptoCurrencyId(id) && !userSupportedCurrencies.find(c => c.id === id),
|
|
94
88
|
)
|
|
95
89
|
.map(getCryptoCurrencyById);
|
|
96
90
|
}
|
package/src/derivation.test.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { getCryptoCurrencyById } from "./currencies";
|
|
2
|
-
import {
|
|
3
|
-
getPreferredNewAccountScheme,
|
|
4
|
-
getDefaultPreferredNewAccountScheme,
|
|
5
|
-
} from "./derivation";
|
|
2
|
+
import { getPreferredNewAccountScheme, getDefaultPreferredNewAccountScheme } from "./derivation";
|
|
6
3
|
describe("derivation", () => {
|
|
7
4
|
test("getPreferredNewAccountScheme should return a list of schemes for a given currency", () => {
|
|
8
5
|
const testData = [
|
package/src/derivation.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import invariant from "invariant";
|
|
2
2
|
import { Observable, defer, of, range, empty } from "rxjs";
|
|
3
|
-
import {
|
|
4
|
-
catchError,
|
|
5
|
-
switchMap,
|
|
6
|
-
concatMap,
|
|
7
|
-
takeWhile,
|
|
8
|
-
map,
|
|
9
|
-
} from "rxjs/operators";
|
|
3
|
+
import { catchError, switchMap, concatMap, takeWhile, map } from "rxjs/operators";
|
|
10
4
|
import { log } from "@ledgerhq/logs";
|
|
11
5
|
import { TransportStatusError, UserRefusedAddress } from "@ledgerhq/errors";
|
|
12
6
|
import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
@@ -227,55 +221,32 @@ const legacyDerivationsPerFamily: Record<string, DerivationMode[]> = {
|
|
|
227
221
|
};
|
|
228
222
|
|
|
229
223
|
export const asDerivationMode = (derivationMode: string): DerivationMode => {
|
|
230
|
-
invariant(
|
|
231
|
-
derivationMode in modes,
|
|
232
|
-
"not a derivationMode. Got: '%s'",
|
|
233
|
-
derivationMode
|
|
234
|
-
);
|
|
224
|
+
invariant(derivationMode in modes, "not a derivationMode. Got: '%s'", derivationMode);
|
|
235
225
|
return derivationMode as DerivationMode;
|
|
236
226
|
};
|
|
237
|
-
export const getAllDerivationModes = (): DerivationMode[] =>
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
): number =>
|
|
242
|
-
(modes[derivationMode] as { mandatoryEmptyAccountSkip: number })
|
|
243
|
-
.mandatoryEmptyAccountSkip || 0;
|
|
244
|
-
export const isInvalidDerivationMode = (
|
|
245
|
-
derivationMode: DerivationMode
|
|
246
|
-
): boolean =>
|
|
227
|
+
export const getAllDerivationModes = (): DerivationMode[] => Object.keys(modes) as DerivationMode[];
|
|
228
|
+
export const getMandatoryEmptyAccountSkip = (derivationMode: DerivationMode): number =>
|
|
229
|
+
(modes[derivationMode] as { mandatoryEmptyAccountSkip: number }).mandatoryEmptyAccountSkip || 0;
|
|
230
|
+
export const isInvalidDerivationMode = (derivationMode: DerivationMode): boolean =>
|
|
247
231
|
(modes[derivationMode] as { isInvalid: boolean }).isInvalid || false;
|
|
248
|
-
export const isSegwitDerivationMode = (
|
|
249
|
-
derivationMode: DerivationMode
|
|
250
|
-
): boolean =>
|
|
232
|
+
export const isSegwitDerivationMode = (derivationMode: DerivationMode): boolean =>
|
|
251
233
|
(modes[derivationMode] as { isSegwit: boolean }).isSegwit || false;
|
|
252
|
-
export const isNativeSegwitDerivationMode = (
|
|
253
|
-
derivationMode:
|
|
254
|
-
): boolean =>
|
|
255
|
-
(modes[derivationMode] as { isNativeSegwit: boolean }).isNativeSegwit ||
|
|
256
|
-
false;
|
|
257
|
-
export const isTaprootDerivationMode = (
|
|
258
|
-
derivationMode: DerivationMode
|
|
259
|
-
): boolean =>
|
|
234
|
+
export const isNativeSegwitDerivationMode = (derivationMode: DerivationMode): boolean =>
|
|
235
|
+
(modes[derivationMode] as { isNativeSegwit: boolean }).isNativeSegwit || false;
|
|
236
|
+
export const isTaprootDerivationMode = (derivationMode: DerivationMode): boolean =>
|
|
260
237
|
(modes[derivationMode] as { isTaproot: boolean }).isTaproot || false;
|
|
261
238
|
|
|
262
|
-
export const isUnsplitDerivationMode = (
|
|
263
|
-
derivationMode: DerivationMode
|
|
264
|
-
): boolean =>
|
|
239
|
+
export const isUnsplitDerivationMode = (derivationMode: DerivationMode): boolean =>
|
|
265
240
|
(modes[derivationMode] as { isUnsplit: boolean }).isUnsplit || false;
|
|
266
|
-
export const isIterableDerivationMode = (
|
|
267
|
-
derivationMode: DerivationMode
|
|
268
|
-
): boolean =>
|
|
241
|
+
export const isIterableDerivationMode = (derivationMode: DerivationMode): boolean =>
|
|
269
242
|
!(modes[derivationMode] as { isNonIterable: boolean }).isNonIterable;
|
|
270
|
-
export const getDerivationModeStartsAt = (
|
|
271
|
-
derivationMode:
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
derivationMode: DerivationMode
|
|
275
|
-
): number => (modes[derivationMode] as { purpose: number }).purpose || 44;
|
|
243
|
+
export const getDerivationModeStartsAt = (derivationMode: DerivationMode): number =>
|
|
244
|
+
(modes[derivationMode] as { startsAt: number }).startsAt || 0;
|
|
245
|
+
export const getPurposeDerivationMode = (derivationMode: DerivationMode): number =>
|
|
246
|
+
(modes[derivationMode] as { purpose: number }).purpose || 44;
|
|
276
247
|
export const getTagDerivationMode = (
|
|
277
248
|
currency: CryptoCurrency,
|
|
278
|
-
derivationMode: DerivationMode
|
|
249
|
+
derivationMode: DerivationMode,
|
|
279
250
|
): string | null | undefined => {
|
|
280
251
|
const mode = modes[derivationMode] as { tag: any; isInvalid: any };
|
|
281
252
|
|
|
@@ -293,14 +264,11 @@ export const getTagDerivationMode = (
|
|
|
293
264
|
|
|
294
265
|
return null;
|
|
295
266
|
};
|
|
296
|
-
export const getAddressFormatDerivationMode = (
|
|
297
|
-
derivationMode:
|
|
298
|
-
): string =>
|
|
299
|
-
(modes[derivationMode] as { addressFormat: string }).addressFormat ||
|
|
300
|
-
"legacy";
|
|
267
|
+
export const getAddressFormatDerivationMode = (derivationMode: DerivationMode): string =>
|
|
268
|
+
(modes[derivationMode] as { addressFormat: string }).addressFormat || "legacy";
|
|
301
269
|
export const derivationModeSupportsIndex = (
|
|
302
270
|
derivationMode: DerivationMode,
|
|
303
|
-
index: number
|
|
271
|
+
index: number,
|
|
304
272
|
): boolean => {
|
|
305
273
|
const mode = modes[derivationMode];
|
|
306
274
|
if ((mode as { skipFirst: boolean }).skipFirst && index === 0) return false;
|
|
@@ -326,8 +294,7 @@ export const getDerivationScheme = ({
|
|
|
326
294
|
overridesCoinType: string;
|
|
327
295
|
};
|
|
328
296
|
if (overridesDerivation) return overridesDerivation;
|
|
329
|
-
const splitFrom =
|
|
330
|
-
isUnsplitDerivationMode(derivationMode) && currency.forkedFrom;
|
|
297
|
+
const splitFrom = isUnsplitDerivationMode(derivationMode) && currency.forkedFrom;
|
|
331
298
|
const coinType = splitFrom
|
|
332
299
|
? getCryptoCurrencyById(splitFrom).coinType
|
|
333
300
|
: typeof overridesCoinType === "number"
|
|
@@ -350,7 +317,7 @@ export const runDerivationScheme = (
|
|
|
350
317
|
account?: number | string;
|
|
351
318
|
node?: number | string;
|
|
352
319
|
address?: number | string;
|
|
353
|
-
} = {}
|
|
320
|
+
} = {},
|
|
354
321
|
) =>
|
|
355
322
|
derivationScheme
|
|
356
323
|
.replace("<coin_type>", String(coinType))
|
|
@@ -365,7 +332,7 @@ export const runAccountDerivationScheme = (
|
|
|
365
332
|
},
|
|
366
333
|
opts: {
|
|
367
334
|
account?: number | string;
|
|
368
|
-
} = {}
|
|
335
|
+
} = {},
|
|
369
336
|
) =>
|
|
370
337
|
runDerivationScheme(scheme, currency, {
|
|
371
338
|
...opts,
|
|
@@ -401,15 +368,11 @@ const seedIdentifierPath: Record<string, SeedPathFn> = {
|
|
|
401
368
|
};
|
|
402
369
|
export const getSeedIdentifierDerivation = (
|
|
403
370
|
currency: CryptoCurrency,
|
|
404
|
-
derivationMode: DerivationMode
|
|
371
|
+
derivationMode: DerivationMode,
|
|
405
372
|
): string => {
|
|
406
|
-
const unsplitFork = isUnsplitDerivationMode(derivationMode)
|
|
407
|
-
? currency.forkedFrom
|
|
408
|
-
: null;
|
|
373
|
+
const unsplitFork = isUnsplitDerivationMode(derivationMode) ? currency.forkedFrom : null;
|
|
409
374
|
const purpose = getPurposeDerivationMode(derivationMode);
|
|
410
|
-
const { coinType } = unsplitFork
|
|
411
|
-
? getCryptoCurrencyById(unsplitFork)
|
|
412
|
-
: currency;
|
|
375
|
+
const { coinType } = unsplitFork ? getCryptoCurrencyById(unsplitFork) : currency;
|
|
413
376
|
const f = seedIdentifierPath[currency.id] || seedIdentifierPath._;
|
|
414
377
|
return f({
|
|
415
378
|
purpose,
|
|
@@ -417,9 +380,7 @@ export const getSeedIdentifierDerivation = (
|
|
|
417
380
|
});
|
|
418
381
|
};
|
|
419
382
|
// return an array of ways to derivate, by convention the latest is the standard one.
|
|
420
|
-
export const getDerivationModesForCurrency = (
|
|
421
|
-
currency: CryptoCurrency
|
|
422
|
-
): DerivationMode[] => {
|
|
383
|
+
export const getDerivationModesForCurrency = (currency: CryptoCurrency): DerivationMode[] => {
|
|
423
384
|
let all: DerivationMode[] = [];
|
|
424
385
|
if (currency.family in legacyDerivationsPerFamily) {
|
|
425
386
|
all = all.concat(legacyDerivationsPerFamily[currency.family]);
|
|
@@ -465,32 +426,25 @@ export const getDerivationModesForCurrency = (
|
|
|
465
426
|
}
|
|
466
427
|
|
|
467
428
|
if (!getEnv("SCAN_FOR_INVALID_PATHS")) {
|
|
468
|
-
return all.filter(
|
|
429
|
+
return all.filter(a => !isInvalidDerivationMode(a));
|
|
469
430
|
}
|
|
470
431
|
|
|
471
432
|
return all;
|
|
472
433
|
};
|
|
473
|
-
const preferredList: DerivationMode[] = [
|
|
474
|
-
"native_segwit",
|
|
475
|
-
"taproot",
|
|
476
|
-
"segwit",
|
|
477
|
-
"",
|
|
478
|
-
];
|
|
434
|
+
const preferredList: DerivationMode[] = ["native_segwit", "taproot", "segwit", ""];
|
|
479
435
|
// null => no settings
|
|
480
436
|
// [ .. ]
|
|
481
437
|
export const getPreferredNewAccountScheme = (
|
|
482
|
-
currency: CryptoCurrency
|
|
438
|
+
currency: CryptoCurrency,
|
|
483
439
|
): DerivationMode[] | null | undefined => {
|
|
484
440
|
if (currency.family !== "bitcoin") return null;
|
|
485
441
|
const derivationsModes = getDerivationModesForCurrency(currency);
|
|
486
|
-
const list = preferredList.filter((p)
|
|
487
|
-
derivationsModes.includes(p as DerivationMode)
|
|
488
|
-
);
|
|
442
|
+
const list = preferredList.filter(p => derivationsModes.includes(p as DerivationMode));
|
|
489
443
|
if (list.length === 1) return null;
|
|
490
444
|
return list as DerivationMode[];
|
|
491
445
|
};
|
|
492
446
|
export const getDefaultPreferredNewAccountScheme = (
|
|
493
|
-
currency: CryptoCurrency
|
|
447
|
+
currency: CryptoCurrency,
|
|
494
448
|
): DerivationMode | null | undefined => {
|
|
495
449
|
const list = getPreferredNewAccountScheme(currency);
|
|
496
450
|
return list && list[0];
|
|
@@ -527,23 +481,19 @@ export function walletDerivation<R>({
|
|
|
527
481
|
path,
|
|
528
482
|
derivationMode,
|
|
529
483
|
}).pipe(
|
|
530
|
-
catchError(
|
|
531
|
-
if (
|
|
532
|
-
e instanceof TransportStatusError ||
|
|
533
|
-
e instanceof UserRefusedAddress
|
|
534
|
-
) {
|
|
484
|
+
catchError(e => {
|
|
485
|
+
if (e instanceof TransportStatusError || e instanceof UserRefusedAddress) {
|
|
535
486
|
log("scanAccounts", "ignore derivationMode=" + derivationMode);
|
|
536
487
|
}
|
|
537
488
|
|
|
538
489
|
return empty();
|
|
539
|
-
})
|
|
540
|
-
)
|
|
490
|
+
}),
|
|
491
|
+
),
|
|
541
492
|
).pipe(
|
|
542
|
-
switchMap(
|
|
493
|
+
switchMap(parentDerivation => {
|
|
543
494
|
const seedIdentifier = parentDerivation.publicKey;
|
|
544
495
|
const emptyCount = 0;
|
|
545
|
-
const mandatoryEmptyAccountSkip =
|
|
546
|
-
getMandatoryEmptyAccountSkip(derivationMode);
|
|
496
|
+
const mandatoryEmptyAccountSkip = getMandatoryEmptyAccountSkip(derivationMode);
|
|
547
497
|
const derivationScheme = getDerivationScheme({
|
|
548
498
|
derivationMode,
|
|
549
499
|
currency,
|
|
@@ -552,7 +502,7 @@ export function walletDerivation<R>({
|
|
|
552
502
|
const startsAt = getDerivationModeStartsAt(derivationMode);
|
|
553
503
|
return range(startsAt, stopAt - startsAt).pipe(
|
|
554
504
|
// derivate addresses/xpubs
|
|
555
|
-
concatMap(
|
|
505
|
+
concatMap(index => {
|
|
556
506
|
if (!derivationModeSupportsIndex(derivationMode, index)) {
|
|
557
507
|
return empty();
|
|
558
508
|
}
|
|
@@ -569,11 +519,11 @@ export function walletDerivation<R>({
|
|
|
569
519
|
path,
|
|
570
520
|
derivationMode,
|
|
571
521
|
}).pipe(
|
|
572
|
-
map(
|
|
522
|
+
map(accountDerivation => ({
|
|
573
523
|
parentDerivation,
|
|
574
524
|
accountDerivation,
|
|
575
525
|
index,
|
|
576
|
-
}))
|
|
526
|
+
})),
|
|
577
527
|
);
|
|
578
528
|
}), // do action with these derivations (e.g. synchronize)
|
|
579
529
|
concatMap(({ parentDerivation, accountDerivation, index }) =>
|
|
@@ -584,12 +534,12 @@ export function walletDerivation<R>({
|
|
|
584
534
|
derivationMode,
|
|
585
535
|
shouldSkipEmpty: emptyCount < mandatoryEmptyAccountSkip,
|
|
586
536
|
seedIdentifier,
|
|
587
|
-
})
|
|
537
|
+
}),
|
|
588
538
|
), // take until the list is complete (based on criteria defined by stepAddress)
|
|
589
539
|
// $FlowFixMe
|
|
590
|
-
takeWhile(
|
|
591
|
-
concatMap(({ result }) => (result ? of(result) : empty()))
|
|
540
|
+
takeWhile(r => !r.complete, true), // emit just the results
|
|
541
|
+
concatMap(({ result }) => (result ? of(result) : empty())),
|
|
592
542
|
);
|
|
593
|
-
})
|
|
543
|
+
}),
|
|
594
544
|
);
|
|
595
545
|
}
|
package/src/errors.test.ts
CHANGED
package/src/errors.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { createCustomErrorClass } from "@ledgerhq/errors";
|
|
2
2
|
|
|
3
|
-
export const FreshAddressIndexInvalid = createCustomErrorClass(
|
|
4
|
-
"FreshAddressIndexInvalid"
|
|
5
|
-
);
|
|
3
|
+
export const FreshAddressIndexInvalid = createCustomErrorClass("FreshAddressIndexInvalid");
|
|
6
4
|
|
|
7
|
-
export const UnsupportedDerivation = createCustomErrorClass(
|
|
8
|
-
"UnsupportedDerivation"
|
|
9
|
-
);
|
|
5
|
+
export const UnsupportedDerivation = createCustomErrorClass("UnsupportedDerivation");
|