@ledgerhq/revault-sdk 0.25.0 → 0.25.1
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/lib/bake.cjs +1214 -1359
- package/lib/bake.cjs.map +1 -1
- package/lib/bake.d.cts +564 -562
- package/lib/bake.d.ts +564 -562
- package/lib/bake.js +1204 -1359
- package/lib/bake.js.map +1 -1
- package/lib/chunk-CKQMccvm.cjs +28 -0
- package/lib/crypto-BDBF_rfw.cjs +268 -0
- package/lib/crypto-BDBF_rfw.cjs.map +1 -0
- package/lib/crypto-CPCBrCSZ.js +245 -0
- package/lib/crypto-CPCBrCSZ.js.map +1 -0
- package/lib/crypto.cjs +5 -11
- package/lib/crypto.d.cts +10 -7
- package/lib/crypto.d.ts +10 -7
- package/lib/crypto.js +2 -11
- package/lib/device-0lcfYGHr.cjs +793 -0
- package/lib/device-0lcfYGHr.cjs.map +1 -0
- package/lib/device-B8Fww8_6.js +719 -0
- package/lib/device-B8Fww8_6.js.map +1 -0
- package/lib/device.cjs +6 -13
- package/lib/device.d.cts +2 -50
- package/lib/device.d.ts +2 -50
- package/lib/device.js +2 -13
- package/lib/engine.cjs +835 -886
- package/lib/engine.cjs.map +1 -1
- package/lib/engine.d.cts +3 -25
- package/lib/engine.d.ts +3 -25
- package/lib/engine.js +828 -885
- package/lib/engine.js.map +1 -1
- package/lib/index--fscLDTT.d.ts +237 -0
- package/lib/index-BE7oUpCb.d.cts +237 -0
- package/lib/index-C4Xjiv0k.d.cts +23 -0
- package/lib/index-CVjhPoZh.d.ts +23 -0
- package/lib/index.cjs +0 -1
- package/lib/index.d.cts +10 -5
- package/lib/index.d.ts +10 -5
- package/lib/index.js +1 -1
- package/lib/logger-Cme0iL1f.d.cts +10 -0
- package/lib/logger-DWLViq7U.d.ts +10 -0
- package/lib/onboarding.cjs +179 -181
- package/lib/onboarding.cjs.map +1 -1
- package/lib/onboarding.d.cts +1751 -1722
- package/lib/onboarding.d.ts +1751 -1722
- package/lib/onboarding.js +175 -181
- package/lib/onboarding.js.map +1 -1
- package/lib/trpc-CWGPr8Ox.d.ts +20 -0
- package/lib/trpc-C_dUOB1u.d.cts +20 -0
- package/lib/types-4CfR5--z.d.ts +203 -0
- package/lib/types-Byf9V35t.d.cts +203 -0
- package/lib/types-CQROu0nu.d.cts +6 -0
- package/lib/types-_QeBv1U4.d.ts +6 -0
- package/lib/types.cjs +0 -1
- package/lib/types.d.cts +3 -4
- package/lib/types.d.ts +3 -4
- package/lib/types.js +1 -1
- package/lib/utils-BGbdjOP9.js +61 -0
- package/lib/utils-BGbdjOP9.js.map +1 -0
- package/lib/utils-DbSFXp4c.cjs +86 -0
- package/lib/utils-DbSFXp4c.cjs.map +1 -0
- package/package.json +6 -6
- package/lib/chunk-2WGM7EWA.cjs +0 -282
- package/lib/chunk-2WGM7EWA.cjs.map +0 -1
- package/lib/chunk-AXI72NFY.js +0 -50
- package/lib/chunk-AXI72NFY.js.map +0 -1
- package/lib/chunk-DRMYBKL3.cjs +0 -820
- package/lib/chunk-DRMYBKL3.cjs.map +0 -1
- package/lib/chunk-KV5FO7N5.js +0 -282
- package/lib/chunk-KV5FO7N5.js.map +0 -1
- package/lib/chunk-LH4QQXUH.cjs +0 -50
- package/lib/chunk-LH4QQXUH.cjs.map +0 -1
- package/lib/chunk-PFZIW6UP.js +0 -820
- package/lib/chunk-PFZIW6UP.js.map +0 -1
- package/lib/crypto.cjs.map +0 -1
- package/lib/crypto.js.map +0 -1
- package/lib/device.cjs.map +0 -1
- package/lib/device.js.map +0 -1
- package/lib/index.cjs.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/logger-C-TPbnjv.d.cts +0 -9
- package/lib/logger-C-TPbnjv.d.ts +0 -9
- package/lib/types-C-ngtI5m.d.ts +0 -202
- package/lib/types-CpGEbAxh.d.cts +0 -19
- package/lib/types-CpGEbAxh.d.ts +0 -19
- package/lib/types-CryvY9pW.d.cts +0 -202
- package/lib/types-DJfbanPz.d.cts +0 -167
- package/lib/types-DJfbanPz.d.ts +0 -167
- package/lib/types.cjs.map +0 -1
- package/lib/types.js.map +0 -1
|
@@ -0,0 +1,719 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import axiosRetry from "axios-retry";
|
|
3
|
+
import { v4 } from "uuid";
|
|
4
|
+
import { Observable, throwError, timer } from "rxjs";
|
|
5
|
+
import { catchError, mergeMap, retryWhen } from "rxjs/operators";
|
|
6
|
+
//#region src/device/constants.ts
|
|
7
|
+
const PATHS = {
|
|
8
|
+
U2F: "5655636'/5583430'",
|
|
9
|
+
CONFIDENTIALITY: "5655636'/4410950'",
|
|
10
|
+
KEY_MATERIAL: "5655636'/4932953'",
|
|
11
|
+
VALIDATION: "5655636'/5652812'"
|
|
12
|
+
};
|
|
13
|
+
const SCRIPT_IDS = {
|
|
14
|
+
INIT_SESSION: 3,
|
|
15
|
+
ACCOUNT_MANAGER_SESSION: 2
|
|
16
|
+
};
|
|
17
|
+
const STR_ROLES = {
|
|
18
|
+
OPERATOR: "00",
|
|
19
|
+
ADMIN: "01",
|
|
20
|
+
SHARED_OWNER: "02"
|
|
21
|
+
};
|
|
22
|
+
const APPID_VAULT_ADMINISTRATOR = "ad5be1a1fe011ce7f53ae081a22ae000a42021f3f94106a3bac9f76e8230e4b9";
|
|
23
|
+
const all61xxStatus = [];
|
|
24
|
+
for (let i = 24832; i <= 25087; i++) all61xxStatus.push(i);
|
|
25
|
+
const PAGINATED_STATUS = all61xxStatus;
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/device/api-device.ts
|
|
28
|
+
function createApiDevice(options, logger) {
|
|
29
|
+
const { genSeed } = options;
|
|
30
|
+
const sessionId = v4();
|
|
31
|
+
const deviceApi = axios.create({ baseURL: options.deviceApiUrl });
|
|
32
|
+
axiosRetry(deviceApi, {
|
|
33
|
+
retryDelay: axiosRetry.linearDelay(1e3),
|
|
34
|
+
retries: 3,
|
|
35
|
+
retryCondition: () => true,
|
|
36
|
+
onRetry: (retryCount, err) => {
|
|
37
|
+
const formattedErr = `${err.code ?? `UNKNOWN`} on ${err.config?.method?.toUpperCase() ?? "UNKNOWN_METHOD"} ${err.config?.url ?? "UNKNOWN_URL"}`;
|
|
38
|
+
logger.warning(`Retrying request to device-api (attempt ${retryCount}) - Cause: ${formattedErr}`);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
/* v8 ignore start -- @preserve */
|
|
42
|
+
deviceApi.interceptors.request.use((config) => {
|
|
43
|
+
logger.debug(`[device-api] ${config.method?.toUpperCase()} ${config.url}${config.data ? ` ${JSON.stringify(config.data)}` : ""}`);
|
|
44
|
+
if (["post", "put"].includes(config.method)) {
|
|
45
|
+
const isStringMode = typeof config.data === "string";
|
|
46
|
+
const enhancedData = {
|
|
47
|
+
sessionID: sessionId,
|
|
48
|
+
psd_model: "02",
|
|
49
|
+
version: 3,
|
|
50
|
+
...isStringMode ? JSON.parse(config.data) : config.data
|
|
51
|
+
};
|
|
52
|
+
config.data = isStringMode ? JSON.stringify(enhancedData) : enhancedData;
|
|
53
|
+
}
|
|
54
|
+
return config;
|
|
55
|
+
}, (error) => Promise.reject(error));
|
|
56
|
+
/* v8 ignore stop */
|
|
57
|
+
return { with: (index) => {
|
|
58
|
+
const __seed = genSeed({
|
|
59
|
+
salt: options.salt,
|
|
60
|
+
index
|
|
61
|
+
});
|
|
62
|
+
const getSeed = async () => {
|
|
63
|
+
if (typeof __seed === "string") return Promise.resolve(__seed);
|
|
64
|
+
return __seed;
|
|
65
|
+
};
|
|
66
|
+
const authenticate = async ({ challenge, workspaceName }) => {
|
|
67
|
+
const role = challenge.role;
|
|
68
|
+
if (role === "READ_ONLY_API_KEY") throw new Error("Invalid role for authenticate: READ_ONLY_API_KEY");
|
|
69
|
+
const { data } = await deviceApi.post("/authenticate", {
|
|
70
|
+
seed: await getSeed(),
|
|
71
|
+
challenge: Buffer.from(challenge.challenge, "base64").toString("hex"),
|
|
72
|
+
application: APPID_VAULT_ADMINISTRATOR,
|
|
73
|
+
key_handle: challenge.keyHandle,
|
|
74
|
+
name: challenge.name,
|
|
75
|
+
role: STR_ROLES[role],
|
|
76
|
+
type: "02",
|
|
77
|
+
workspaceName
|
|
78
|
+
});
|
|
79
|
+
return data;
|
|
80
|
+
};
|
|
81
|
+
const finalizePairingHandshake = async (params) => {
|
|
82
|
+
const { handshake, partitionId } = params;
|
|
83
|
+
const payload = {
|
|
84
|
+
seed: await getSeed(),
|
|
85
|
+
handshake,
|
|
86
|
+
ciphertext: partitionId
|
|
87
|
+
};
|
|
88
|
+
return (await deviceApi.post("/finalize-pairing-handshake", payload)).data;
|
|
89
|
+
};
|
|
90
|
+
const generateSeedFragment = async () => {
|
|
91
|
+
const payload = {
|
|
92
|
+
seed: await getSeed(),
|
|
93
|
+
path: PATHS.KEY_MATERIAL,
|
|
94
|
+
goal: 0
|
|
95
|
+
};
|
|
96
|
+
const { data } = await deviceApi.post("/generate-key-component", payload);
|
|
97
|
+
return data;
|
|
98
|
+
};
|
|
99
|
+
const generateWrappingKeyFragment = async () => {
|
|
100
|
+
const payload = {
|
|
101
|
+
seed: await getSeed(),
|
|
102
|
+
goal: 1,
|
|
103
|
+
path: PATHS.KEY_MATERIAL
|
|
104
|
+
};
|
|
105
|
+
const res = await deviceApi.post("/generate-key-fragments", payload);
|
|
106
|
+
return Buffer.from(res.data, "hex").toString("base64");
|
|
107
|
+
};
|
|
108
|
+
const getAttestation = async () => {
|
|
109
|
+
const { data: attestationStr } = await deviceApi.post("/get-attestation", { seed: await getSeed() });
|
|
110
|
+
const attestationBuffer = Buffer.from(attestationStr, "hex");
|
|
111
|
+
const certLen = attestationBuffer.readInt8(98);
|
|
112
|
+
return {
|
|
113
|
+
attestation: {
|
|
114
|
+
codeHash: attestationBuffer.slice(0, 32).toString("base64"),
|
|
115
|
+
attestationPub: attestationBuffer.slice(32, 97).toString("base64"),
|
|
116
|
+
certificate: attestationBuffer.slice(97, 99 + certLen).toString("base64")
|
|
117
|
+
},
|
|
118
|
+
buffer: attestationBuffer
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
const getConfidentialityKey = async () => {
|
|
122
|
+
const res = await deviceApi.post("/get-confidentiality-key", { seed: await getSeed() });
|
|
123
|
+
return {
|
|
124
|
+
confidentialityKeyCurve25519: res.data.confidentiality_key_curve25519,
|
|
125
|
+
confidentialityKeySignature: res.data.confidentiality_key_signature
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
const getConfidentialityPubKey = async () => {
|
|
129
|
+
return getPublicKey({ path: PATHS.CONFIDENTIALITY });
|
|
130
|
+
};
|
|
131
|
+
const getDeviceUserId = async () => {
|
|
132
|
+
return (await deviceApi.post("/blue-device-id", { seed: await getSeed() })).data.blue_device_id.toUpperCase();
|
|
133
|
+
};
|
|
134
|
+
const getU2FPubKey = async () => {
|
|
135
|
+
return getPublicKey({ path: PATHS.U2F });
|
|
136
|
+
};
|
|
137
|
+
const getValidationPubKey = async () => {
|
|
138
|
+
return getPublicKey({ path: PATHS.VALIDATION });
|
|
139
|
+
};
|
|
140
|
+
const hasPairing = async () => {
|
|
141
|
+
return (await deviceApi.post("/get-partition-ids", { seed: await getSeed() })).data.length > 0;
|
|
142
|
+
};
|
|
143
|
+
const initPairingHandshake = async () => {
|
|
144
|
+
const { data } = await deviceApi.post("/initiate-pairing-handshake", { seed: await getSeed() });
|
|
145
|
+
return {
|
|
146
|
+
pubKey: data.pubKey,
|
|
147
|
+
signature: Buffer.from(data.attestation, "hex").toString("base64")
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
const openSession = async (params) => {
|
|
151
|
+
const { secureChannel } = params;
|
|
152
|
+
const signature = Buffer.from(secureChannel.certificate.signature, "base64");
|
|
153
|
+
const attestationPubKey = Buffer.from(secureChannel.certificate.attestationPub, "base64");
|
|
154
|
+
const attestationCertificate = Buffer.from(secureChannel.certificate.certificate, "base64");
|
|
155
|
+
const attestation = Buffer.concat([
|
|
156
|
+
Buffer.from([signature.length]),
|
|
157
|
+
signature,
|
|
158
|
+
attestationPubKey,
|
|
159
|
+
Buffer.from([attestationCertificate.length]),
|
|
160
|
+
attestationCertificate
|
|
161
|
+
]);
|
|
162
|
+
const payload = {
|
|
163
|
+
seed: await getSeed(),
|
|
164
|
+
path: PATHS.CONFIDENTIALITY,
|
|
165
|
+
pubKey: secureChannel.pubKey,
|
|
166
|
+
attestation: attestation.toString("hex"),
|
|
167
|
+
scriptId: SCRIPT_IDS.INIT_SESSION
|
|
168
|
+
};
|
|
169
|
+
const { data: deviceResponse } = await deviceApi.post("/open-session", payload);
|
|
170
|
+
if (deviceResponse !== "9000") throw new Error(`device-api device failed with code: ${deviceResponse}`);
|
|
171
|
+
};
|
|
172
|
+
const register = async (params) => {
|
|
173
|
+
const { challenge, u2fRegisterData, name, role } = params;
|
|
174
|
+
const payload = {
|
|
175
|
+
seed: await getSeed(),
|
|
176
|
+
challenge,
|
|
177
|
+
name,
|
|
178
|
+
role: STR_ROLES[role],
|
|
179
|
+
hsm_data: u2fRegisterData,
|
|
180
|
+
type: "02",
|
|
181
|
+
application: APPID_VAULT_ADMINISTRATOR
|
|
182
|
+
};
|
|
183
|
+
const { data } = await deviceApi.post("/register", payload);
|
|
184
|
+
const response = Buffer.from(data, "hex");
|
|
185
|
+
let i = 0;
|
|
186
|
+
const rfu = response.slice(i, i + 1)[0];
|
|
187
|
+
i += 1;
|
|
188
|
+
const pubKey = response.slice(i, i + 65).toString("hex");
|
|
189
|
+
i += 65;
|
|
190
|
+
const keyHandleLength = response.slice(i, i + 1)[0];
|
|
191
|
+
i++;
|
|
192
|
+
const keyHandle = response.slice(i, i + keyHandleLength);
|
|
193
|
+
i += keyHandleLength;
|
|
194
|
+
return {
|
|
195
|
+
u2fRegister: response.slice(0, response.length - 2),
|
|
196
|
+
keyHandle,
|
|
197
|
+
rfu,
|
|
198
|
+
pubKey
|
|
199
|
+
};
|
|
200
|
+
};
|
|
201
|
+
const registerData = async (params) => {
|
|
202
|
+
const { challenge } = params;
|
|
203
|
+
const payload = {
|
|
204
|
+
seed: await getSeed(),
|
|
205
|
+
challenge
|
|
206
|
+
};
|
|
207
|
+
return (await deviceApi.post("/u2f-register-data", payload)).data;
|
|
208
|
+
};
|
|
209
|
+
const setPairing = async ({ pairing }) => {
|
|
210
|
+
const payload = {
|
|
211
|
+
seed: await getSeed(),
|
|
212
|
+
blob: pairing.blob,
|
|
213
|
+
pairing: {
|
|
214
|
+
bootstrap_enabled: pairing.pairing.bootstrapEnabled,
|
|
215
|
+
partition_key: pairing.pairing.partitionKey,
|
|
216
|
+
workspace_name: pairing.pairing.workspaceName
|
|
217
|
+
},
|
|
218
|
+
partition_key_attestation: {
|
|
219
|
+
code_hash: pairing.partitionKeyAttestation.codeHash,
|
|
220
|
+
attestation_pub: pairing.partitionKeyAttestation.attestationPub,
|
|
221
|
+
certificate: pairing.partitionKeyAttestation.certificate,
|
|
222
|
+
signature: pairing.partitionKeyAttestation.signature
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
await deviceApi.post("/set-partition-key", payload);
|
|
226
|
+
};
|
|
227
|
+
const startKKPatternAsResponder = async (params) => {
|
|
228
|
+
const payload = {
|
|
229
|
+
seed: await getSeed(),
|
|
230
|
+
script_id: SCRIPT_IDS.ACCOUNT_MANAGER_SESSION,
|
|
231
|
+
handshake: params.handshake,
|
|
232
|
+
handshake_attestation: "",
|
|
233
|
+
partition_id: params.partitionId
|
|
234
|
+
};
|
|
235
|
+
const { data } = await deviceApi.post("/start-kk-pattern-as-responder", payload);
|
|
236
|
+
const buffer = Buffer.from(data, "hex");
|
|
237
|
+
const dataLength = buffer.readInt8(0);
|
|
238
|
+
return {
|
|
239
|
+
handshake: buffer.slice(1, dataLength + 1).toString("base64"),
|
|
240
|
+
signature: buffer.slice(dataLength + 1).toString("base64")
|
|
241
|
+
};
|
|
242
|
+
};
|
|
243
|
+
const startKPatternAsResponder = async (params) => {
|
|
244
|
+
const { handshake, partitionId } = params;
|
|
245
|
+
const payload = {
|
|
246
|
+
seed: await getSeed(),
|
|
247
|
+
script_id: SCRIPT_IDS.ACCOUNT_MANAGER_SESSION,
|
|
248
|
+
handshake,
|
|
249
|
+
handshake_attestation: "",
|
|
250
|
+
partition_id: partitionId
|
|
251
|
+
};
|
|
252
|
+
const { data: deviceResponse } = await deviceApi.post("/start-k-pattern-as-responder", payload);
|
|
253
|
+
if (deviceResponse !== "9000") throw new Error(`device-api device failed with code: ${deviceResponse}`);
|
|
254
|
+
};
|
|
255
|
+
const getPublicKey = async (params) => {
|
|
256
|
+
const { path } = params;
|
|
257
|
+
const payload = {
|
|
258
|
+
seed: await getSeed(),
|
|
259
|
+
secp256k1: true,
|
|
260
|
+
path
|
|
261
|
+
};
|
|
262
|
+
const res = await deviceApi.post("/get-public-key", payload);
|
|
263
|
+
return {
|
|
264
|
+
pubKey: res.data.pubKey,
|
|
265
|
+
signature: Buffer.from(res.data.attestation, "hex").toString("base64")
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
const validateVaultOperation = async (params) => {
|
|
269
|
+
const { actions } = params;
|
|
270
|
+
const payload = {
|
|
271
|
+
seed: await getSeed(),
|
|
272
|
+
path: PATHS.VALIDATION,
|
|
273
|
+
actions
|
|
274
|
+
};
|
|
275
|
+
const { data: signature } = await deviceApi.post("/validate-op", payload);
|
|
276
|
+
return signature;
|
|
277
|
+
};
|
|
278
|
+
const sendAPDU = (_apdu) => {
|
|
279
|
+
logger.info("Can't send arbitrary APDU to software device");
|
|
280
|
+
return Promise.resolve("9000");
|
|
281
|
+
};
|
|
282
|
+
const getVersion = async () => {
|
|
283
|
+
return "1.2.3";
|
|
284
|
+
};
|
|
285
|
+
const poll = async () => {
|
|
286
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
287
|
+
return { isAppOpened: true };
|
|
288
|
+
};
|
|
289
|
+
const pollApp = async () => {
|
|
290
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
291
|
+
return "9000";
|
|
292
|
+
};
|
|
293
|
+
return {
|
|
294
|
+
authenticate,
|
|
295
|
+
finalizePairingHandshake,
|
|
296
|
+
generateSeedFragment,
|
|
297
|
+
generateWrappingKeyFragment,
|
|
298
|
+
getAttestation,
|
|
299
|
+
getConfidentialityKey,
|
|
300
|
+
getConfidentialityPubKey,
|
|
301
|
+
getDeviceUserId,
|
|
302
|
+
getU2FPubKey,
|
|
303
|
+
getValidationPubKey,
|
|
304
|
+
hasPairing,
|
|
305
|
+
initPairingHandshake,
|
|
306
|
+
openSession,
|
|
307
|
+
register,
|
|
308
|
+
registerData,
|
|
309
|
+
setPairing,
|
|
310
|
+
startKKPatternAsResponder,
|
|
311
|
+
startKPatternAsResponder,
|
|
312
|
+
validateVaultOperation,
|
|
313
|
+
getVersion,
|
|
314
|
+
sendAPDU,
|
|
315
|
+
poll,
|
|
316
|
+
pollApp
|
|
317
|
+
};
|
|
318
|
+
} };
|
|
319
|
+
}
|
|
320
|
+
//#endregion
|
|
321
|
+
//#region ../../node_modules/.pnpm/@ledgerhq+errors@6.32.0/node_modules/@ledgerhq/errors/lib-es/helpers.js
|
|
322
|
+
const errorClasses = {};
|
|
323
|
+
const deserializers = {};
|
|
324
|
+
const addCustomErrorDeserializer = (name, deserializer) => {
|
|
325
|
+
deserializers[name] = deserializer;
|
|
326
|
+
};
|
|
327
|
+
const createCustomErrorClass = (name) => {
|
|
328
|
+
class CustomErrorClass extends Error {
|
|
329
|
+
cause;
|
|
330
|
+
constructor(message, fields, options) {
|
|
331
|
+
super(message || name, options);
|
|
332
|
+
Object.setPrototypeOf(this, CustomErrorClass.prototype);
|
|
333
|
+
this.name = name;
|
|
334
|
+
if (fields) for (const k in fields) this[k] = fields[k];
|
|
335
|
+
if (options && isObject(options) && "cause" in options && !this.cause) {
|
|
336
|
+
const cause = options.cause;
|
|
337
|
+
this.cause = cause;
|
|
338
|
+
if ("stack" in cause) this.stack = this.stack + "\nCAUSE: " + cause.stack;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
errorClasses[name] = CustomErrorClass;
|
|
343
|
+
return CustomErrorClass;
|
|
344
|
+
};
|
|
345
|
+
function isObject(value) {
|
|
346
|
+
return typeof value === "object";
|
|
347
|
+
}
|
|
348
|
+
createCustomErrorClass("AccountNameRequired");
|
|
349
|
+
createCustomErrorClass("AccountNotSupported");
|
|
350
|
+
createCustomErrorClass("AccountAwaitingSendPendingOperations");
|
|
351
|
+
createCustomErrorClass("AmountRequired");
|
|
352
|
+
const BluetoothRequired = createCustomErrorClass("BluetoothRequired");
|
|
353
|
+
createCustomErrorClass("BtcUnmatchedApp");
|
|
354
|
+
const CantOpenDevice = createCustomErrorClass("CantOpenDevice");
|
|
355
|
+
createCustomErrorClass("CashAddrNotSupported");
|
|
356
|
+
createCustomErrorClass("ClaimRewardsFeesWarning");
|
|
357
|
+
createCustomErrorClass("CurrencyNotSupported");
|
|
358
|
+
createCustomErrorClass("DeviceAppVerifyNotSupported");
|
|
359
|
+
createCustomErrorClass("DeviceGenuineSocketEarlyClose");
|
|
360
|
+
createCustomErrorClass("DeviceNotGenuine");
|
|
361
|
+
createCustomErrorClass("DeviceOnDashboardExpected");
|
|
362
|
+
createCustomErrorClass("DeviceOnDashboardUnexpected");
|
|
363
|
+
createCustomErrorClass("DeviceInOSUExpected");
|
|
364
|
+
const DeviceHalted = createCustomErrorClass("DeviceHalted");
|
|
365
|
+
createCustomErrorClass("DeviceNameInvalid");
|
|
366
|
+
createCustomErrorClass("DeviceSocketFail");
|
|
367
|
+
createCustomErrorClass("DeviceSocketNoBulkStatus");
|
|
368
|
+
createCustomErrorClass("DeviceSocketNoBulkStatus");
|
|
369
|
+
createCustomErrorClass("UnresponsiveDeviceError");
|
|
370
|
+
const DisconnectedDevice = createCustomErrorClass("DisconnectedDevice");
|
|
371
|
+
createCustomErrorClass("DisconnectedDeviceDuringOperation");
|
|
372
|
+
createCustomErrorClass("DeviceExtractOnboardingStateError");
|
|
373
|
+
createCustomErrorClass("DeviceOnboardingStatePollingError");
|
|
374
|
+
createCustomErrorClass("EnpointConfig");
|
|
375
|
+
createCustomErrorClass("EthAppPleaseEnableContractData");
|
|
376
|
+
createCustomErrorClass("SolAppPleaseEnableContractData");
|
|
377
|
+
createCustomErrorClass("CeloAppPleaseEnableContractData");
|
|
378
|
+
createCustomErrorClass("FeeEstimationFailed");
|
|
379
|
+
createCustomErrorClass("FirmwareNotRecognized");
|
|
380
|
+
createCustomErrorClass("HardResetFail");
|
|
381
|
+
createCustomErrorClass("InvalidXRPTag");
|
|
382
|
+
createCustomErrorClass("InvalidAddress");
|
|
383
|
+
createCustomErrorClass("InvalidTransactionError");
|
|
384
|
+
createCustomErrorClass("InvalidNonce");
|
|
385
|
+
createCustomErrorClass("InvalidAddressBecauseDestinationIsAlsoSource");
|
|
386
|
+
createCustomErrorClass("LatestMCUInstalledError");
|
|
387
|
+
createCustomErrorClass("LatestFirmwareVersionRequired");
|
|
388
|
+
createCustomErrorClass("UnsupportedFeatureError");
|
|
389
|
+
createCustomErrorClass("NanoSNotSupported");
|
|
390
|
+
createCustomErrorClass("UnknownMCU");
|
|
391
|
+
createCustomErrorClass("LedgerAPIError");
|
|
392
|
+
createCustomErrorClass("LedgerAPIErrorWithMessage");
|
|
393
|
+
createCustomErrorClass("LedgerAPINotAvailable");
|
|
394
|
+
createCustomErrorClass("ManagerAppAlreadyInstalled");
|
|
395
|
+
createCustomErrorClass("ManagerAppRelyOnBTC");
|
|
396
|
+
createCustomErrorClass("ManagerAppDepInstallRequired");
|
|
397
|
+
createCustomErrorClass("ManagerAppDepUninstallRequired");
|
|
398
|
+
createCustomErrorClass("ManagerDeviceLocked");
|
|
399
|
+
createCustomErrorClass("ManagerFirmwareNotEnoughSpace");
|
|
400
|
+
createCustomErrorClass("ManagerNotEnoughSpace");
|
|
401
|
+
createCustomErrorClass("ManagerUninstallBTCDep");
|
|
402
|
+
createCustomErrorClass("NetworkDown");
|
|
403
|
+
createCustomErrorClass("NetworkError");
|
|
404
|
+
createCustomErrorClass("NoAddressesFound");
|
|
405
|
+
createCustomErrorClass("NotEnoughBalance");
|
|
406
|
+
createCustomErrorClass("NotEnoughBalanceFees");
|
|
407
|
+
createCustomErrorClass("NotEnoughBalanceSwap");
|
|
408
|
+
createCustomErrorClass("NotEnoughBalanceToDelegate");
|
|
409
|
+
createCustomErrorClass("UnstakeNotEnoughStakedBalanceLeft");
|
|
410
|
+
createCustomErrorClass("RestakeNotEnoughStakedBalanceLeft");
|
|
411
|
+
createCustomErrorClass("NotEnoughToRestake");
|
|
412
|
+
createCustomErrorClass("NotEnoughToUnstake");
|
|
413
|
+
createCustomErrorClass("NotEnoughBalanceInParentAccount");
|
|
414
|
+
createCustomErrorClass("NotEnoughSpendableBalance");
|
|
415
|
+
createCustomErrorClass("NotEnoughBalanceBecauseDestinationNotCreated");
|
|
416
|
+
createCustomErrorClass("NotEnoughToStake");
|
|
417
|
+
createCustomErrorClass("NoAccessToCamera");
|
|
418
|
+
createCustomErrorClass("NotEnoughGas");
|
|
419
|
+
createCustomErrorClass("NotEnoughGasSwap");
|
|
420
|
+
createCustomErrorClass("TronEmptyAccount");
|
|
421
|
+
createCustomErrorClass("MaybeKeepTronAccountAlive");
|
|
422
|
+
createCustomErrorClass("NotSupportedLegacyAddress");
|
|
423
|
+
createCustomErrorClass("GasLessThanEstimate");
|
|
424
|
+
createCustomErrorClass("PriorityFeeTooLow");
|
|
425
|
+
createCustomErrorClass("PriorityFeeTooHigh");
|
|
426
|
+
createCustomErrorClass("PriorityFeeHigherThanMaxFee");
|
|
427
|
+
createCustomErrorClass("MaxFeeTooLow");
|
|
428
|
+
createCustomErrorClass("PasswordsDontMatch");
|
|
429
|
+
createCustomErrorClass("PasswordIncorrect");
|
|
430
|
+
createCustomErrorClass("RecommendSubAccountsToEmpty");
|
|
431
|
+
createCustomErrorClass("RecommendUndelegation");
|
|
432
|
+
createCustomErrorClass("TimeoutTagged");
|
|
433
|
+
createCustomErrorClass("UnexpectedBootloader");
|
|
434
|
+
createCustomErrorClass("MCUNotGenuineToDashboard");
|
|
435
|
+
createCustomErrorClass("RecipientRequired");
|
|
436
|
+
createCustomErrorClass("UnavailableTezosOriginatedAccountReceive");
|
|
437
|
+
createCustomErrorClass("UnavailableTezosOriginatedAccountSend");
|
|
438
|
+
createCustomErrorClass("UpdateFetchFileFail");
|
|
439
|
+
createCustomErrorClass("UpdateIncorrectHash");
|
|
440
|
+
createCustomErrorClass("UpdateIncorrectSig");
|
|
441
|
+
createCustomErrorClass("UpdateYourApp");
|
|
442
|
+
createCustomErrorClass("UserRefusedDeviceNameChange");
|
|
443
|
+
createCustomErrorClass("UserRefusedAddress");
|
|
444
|
+
createCustomErrorClass("UserRefusedFirmwareUpdate");
|
|
445
|
+
createCustomErrorClass("UserRefusedAllowManager");
|
|
446
|
+
createCustomErrorClass("UserRefusedOnDevice");
|
|
447
|
+
createCustomErrorClass("PinNotSet");
|
|
448
|
+
createCustomErrorClass("ExpertModeRequired");
|
|
449
|
+
createCustomErrorClass("TransportOpenUserCancelled");
|
|
450
|
+
const TransportInterfaceNotAvailable = createCustomErrorClass("TransportInterfaceNotAvailable");
|
|
451
|
+
createCustomErrorClass("TransportRaceCondition");
|
|
452
|
+
const TransportWebUSBGestureRequired = createCustomErrorClass("TransportWebUSBGestureRequired");
|
|
453
|
+
createCustomErrorClass("TransactionHasBeenValidatedError");
|
|
454
|
+
createCustomErrorClass("TransportExchangeTimeoutError");
|
|
455
|
+
createCustomErrorClass("DeviceShouldStayInApp");
|
|
456
|
+
createCustomErrorClass("WebsocketConnectionError");
|
|
457
|
+
createCustomErrorClass("WebsocketConnectionFailed");
|
|
458
|
+
createCustomErrorClass("WrongDeviceForAccount");
|
|
459
|
+
createCustomErrorClass("WrongDeviceForAccountPayout");
|
|
460
|
+
createCustomErrorClass("MissingSwapPayloadParamaters");
|
|
461
|
+
createCustomErrorClass("WrongDeviceForAccountRefund");
|
|
462
|
+
createCustomErrorClass("WrongAppForCurrency");
|
|
463
|
+
createCustomErrorClass("ETHAddressNonEIP");
|
|
464
|
+
createCustomErrorClass("CantScanQRCode");
|
|
465
|
+
createCustomErrorClass("FeeNotLoaded");
|
|
466
|
+
createCustomErrorClass("FeeNotLoadedSwap");
|
|
467
|
+
createCustomErrorClass("FeeRequired");
|
|
468
|
+
createCustomErrorClass("FeeTooHigh");
|
|
469
|
+
createCustomErrorClass("PendingOperation");
|
|
470
|
+
createCustomErrorClass("SyncError");
|
|
471
|
+
createCustomErrorClass("PairingFailed");
|
|
472
|
+
createCustomErrorClass("PeerRemovedPairing");
|
|
473
|
+
createCustomErrorClass("GenuineCheckFailed");
|
|
474
|
+
createCustomErrorClass("LedgerAPI4xx");
|
|
475
|
+
createCustomErrorClass("LedgerAPI5xx");
|
|
476
|
+
const FirmwareOrAppUpdateRequired = createCustomErrorClass("FirmwareOrAppUpdateRequired");
|
|
477
|
+
createCustomErrorClass("ReplacementTransactionUnderpriced");
|
|
478
|
+
createCustomErrorClass("OpReturnSizeLimit");
|
|
479
|
+
createCustomErrorClass("DustLimit");
|
|
480
|
+
createCustomErrorClass("ConcordiumInsufficientFunds");
|
|
481
|
+
createCustomErrorClass("ConcordiumMemoTooLong");
|
|
482
|
+
createCustomErrorClass("ConcordiumPairingExpiredError");
|
|
483
|
+
createCustomErrorClass("ConcordiumSessionExpiredError");
|
|
484
|
+
createCustomErrorClass("LanguageNotFound");
|
|
485
|
+
createCustomErrorClass("NoDBPathGiven");
|
|
486
|
+
createCustomErrorClass("DBWrongPassword");
|
|
487
|
+
createCustomErrorClass("DBNotReset");
|
|
488
|
+
createCustomErrorClass("SequenceNumberError");
|
|
489
|
+
createCustomErrorClass("DisabledTransactionBroadcastError");
|
|
490
|
+
/**
|
|
491
|
+
* Type of a Transport error used to represent all equivalent errors coming from all possible implementation of Transport
|
|
492
|
+
*/
|
|
493
|
+
var HwTransportErrorType;
|
|
494
|
+
(function(HwTransportErrorType) {
|
|
495
|
+
HwTransportErrorType["Unknown"] = "Unknown";
|
|
496
|
+
HwTransportErrorType["LocationServicesDisabled"] = "LocationServicesDisabled";
|
|
497
|
+
HwTransportErrorType["LocationServicesUnauthorized"] = "LocationServicesUnauthorized";
|
|
498
|
+
HwTransportErrorType["BluetoothScanStartFailed"] = "BluetoothScanStartFailed";
|
|
499
|
+
})(HwTransportErrorType || (HwTransportErrorType = {}));
|
|
500
|
+
/**
|
|
501
|
+
* TransportError is used for any generic transport errors.
|
|
502
|
+
* e.g. Error thrown when data received by exchanges are incorrect or if exchanged failed to communicate with the device for various reason.
|
|
503
|
+
*/
|
|
504
|
+
var TransportError = class extends Error {
|
|
505
|
+
id;
|
|
506
|
+
constructor(message, id) {
|
|
507
|
+
const name = "TransportError";
|
|
508
|
+
super(message || name);
|
|
509
|
+
this.name = name;
|
|
510
|
+
this.message = message;
|
|
511
|
+
this.stack = new Error(message).stack;
|
|
512
|
+
this.id = id;
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
addCustomErrorDeserializer("TransportError", (e) => new TransportError(e.message, e.id));
|
|
516
|
+
const StatusCodes = {
|
|
517
|
+
ACCESS_CONDITION_NOT_FULFILLED: 38916,
|
|
518
|
+
ALGORITHM_NOT_SUPPORTED: 38020,
|
|
519
|
+
CLA_NOT_SUPPORTED: 28160,
|
|
520
|
+
CODE_BLOCKED: 38976,
|
|
521
|
+
CODE_NOT_INITIALIZED: 38914,
|
|
522
|
+
COMMAND_INCOMPATIBLE_FILE_STRUCTURE: 27009,
|
|
523
|
+
CONDITIONS_OF_USE_NOT_SATISFIED: 27013,
|
|
524
|
+
CONTRADICTION_INVALIDATION: 38928,
|
|
525
|
+
CONTRADICTION_SECRET_CODE_STATUS: 38920,
|
|
526
|
+
DEVICE_IN_RECOVERY_MODE: 26159,
|
|
527
|
+
CUSTOM_IMAGE_EMPTY: 26158,
|
|
528
|
+
FILE_ALREADY_EXISTS: 27273,
|
|
529
|
+
FILE_NOT_FOUND: 37892,
|
|
530
|
+
GP_AUTH_FAILED: 25344,
|
|
531
|
+
HALTED: 28586,
|
|
532
|
+
INCONSISTENT_FILE: 37896,
|
|
533
|
+
INCORRECT_DATA: 27264,
|
|
534
|
+
INCORRECT_LENGTH: 26368,
|
|
535
|
+
INCORRECT_P1_P2: 27392,
|
|
536
|
+
INS_NOT_SUPPORTED: 27904,
|
|
537
|
+
DEVICE_NOT_ONBOARDED: 27911,
|
|
538
|
+
DEVICE_NOT_ONBOARDED_2: 26129,
|
|
539
|
+
INVALID_KCV: 38021,
|
|
540
|
+
INVALID_OFFSET: 37890,
|
|
541
|
+
LICENSING: 28482,
|
|
542
|
+
LOCKED_DEVICE: 21781,
|
|
543
|
+
MAX_VALUE_REACHED: 38992,
|
|
544
|
+
MEMORY_PROBLEM: 37440,
|
|
545
|
+
MISSING_CRITICAL_PARAMETER: 26624,
|
|
546
|
+
NO_EF_SELECTED: 37888,
|
|
547
|
+
NOT_ENOUGH_MEMORY_SPACE: 27268,
|
|
548
|
+
OK: 36864,
|
|
549
|
+
PIN_REMAINING_ATTEMPTS: 25536,
|
|
550
|
+
REFERENCED_DATA_NOT_FOUND: 27272,
|
|
551
|
+
SECURITY_STATUS_NOT_SATISFIED: 27010,
|
|
552
|
+
TECHNICAL_PROBLEM: 28416,
|
|
553
|
+
UNKNOWN_APDU: 27906,
|
|
554
|
+
USER_REFUSED_ON_DEVICE: 21761,
|
|
555
|
+
NOT_ENOUGH_SPACE: 20738,
|
|
556
|
+
APP_NOT_FOUND_OR_INVALID_CONTEXT: 20771,
|
|
557
|
+
INVALID_APP_NAME_LENGTH: 26378,
|
|
558
|
+
GEN_AES_KEY_FAILED: 21529,
|
|
559
|
+
INTERNAL_CRYPTO_OPERATION_FAILED: 21530,
|
|
560
|
+
INTERNAL_COMPUTE_AES_CMAC_FAILED: 21531,
|
|
561
|
+
ENCRYPT_APP_STORAGE_FAILED: 21532,
|
|
562
|
+
INVALID_BACKUP_STATE: 26178,
|
|
563
|
+
PIN_NOT_SET: 21762,
|
|
564
|
+
INVALID_BACKUP_LENGTH: 26419,
|
|
565
|
+
INVALID_RESTORE_STATE: 26179,
|
|
566
|
+
INVALID_CHUNK_LENGTH: 26420,
|
|
567
|
+
INVALID_BACKUP_HEADER: 26698,
|
|
568
|
+
SW_BAD_STATE: 45063
|
|
569
|
+
};
|
|
570
|
+
function getAltStatusMessage(code) {
|
|
571
|
+
switch (code) {
|
|
572
|
+
case 26368: return "Incorrect length";
|
|
573
|
+
case 26624: return "Missing critical parameter";
|
|
574
|
+
case 27010: return "Security not satisfied (dongle locked or have invalid access rights)";
|
|
575
|
+
case 27013: return "Condition of use not satisfied (denied by the user?)";
|
|
576
|
+
case 27264: return "Invalid data received";
|
|
577
|
+
case 27392: return "Invalid parameter received";
|
|
578
|
+
case 21781: return "Locked device";
|
|
579
|
+
case 45063: return "Unexpected state on the device";
|
|
580
|
+
}
|
|
581
|
+
if (28416 <= code && code <= 28671) return "Internal error, please report";
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Error thrown when a device returned a non success status.
|
|
585
|
+
* the error.statusCode is one of the `StatusCodes` exported by this library.
|
|
586
|
+
*/
|
|
587
|
+
var TransportStatusError = class TransportStatusError extends Error {
|
|
588
|
+
statusCode;
|
|
589
|
+
statusText;
|
|
590
|
+
/**
|
|
591
|
+
* @param statusCode The error status code coming from a Transport implementation
|
|
592
|
+
* @param options containing:
|
|
593
|
+
* - canBeMappedToChildError: enable the mapping of TransportStatusError to an error extending/inheriting from it
|
|
594
|
+
* . Ex: LockedDeviceError. Default to true.
|
|
595
|
+
*/
|
|
596
|
+
constructor(statusCode, { canBeMappedToChildError = true } = {}) {
|
|
597
|
+
const statusText = Object.keys(StatusCodes).find((k) => StatusCodes[k] === statusCode) || "UNKNOWN_ERROR";
|
|
598
|
+
const message = `Ledger device: ${getAltStatusMessage(statusCode) || statusText} (0x${statusCode.toString(16)})`;
|
|
599
|
+
super(message);
|
|
600
|
+
this.name = "TransportStatusError";
|
|
601
|
+
this.statusCode = statusCode;
|
|
602
|
+
this.statusText = statusText;
|
|
603
|
+
Object.setPrototypeOf(this, TransportStatusError.prototype);
|
|
604
|
+
if (canBeMappedToChildError && statusCode === StatusCodes.LOCKED_DEVICE) return new LockedDeviceError(message);
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
var LockedDeviceError = class LockedDeviceError extends TransportStatusError {
|
|
608
|
+
constructor(message) {
|
|
609
|
+
super(StatusCodes.LOCKED_DEVICE, { canBeMappedToChildError: false });
|
|
610
|
+
if (message) this.message = message;
|
|
611
|
+
this.name = "LockedDeviceError";
|
|
612
|
+
Object.setPrototypeOf(this, LockedDeviceError.prototype);
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
addCustomErrorDeserializer("TransportStatusError", (e) => new TransportStatusError(e.statusCode));
|
|
616
|
+
//#endregion
|
|
617
|
+
//#region src/device/device-access.ts
|
|
618
|
+
const initialErrorRemapping = (error) => throwError(error && error instanceof TransportStatusError && error.statusCode === 28586 ? new DeviceHalted(error.message) : error instanceof TransportStatusError && error.statusCode === 27392 ? new FirmwareOrAppUpdateRequired(error.message) : error);
|
|
619
|
+
const never = new Promise(() => {});
|
|
620
|
+
const modules = [];
|
|
621
|
+
const registerTransportModule = (module) => {
|
|
622
|
+
modules.push(module);
|
|
623
|
+
};
|
|
624
|
+
const close = (transport, deviceId) => {
|
|
625
|
+
for (const m of modules) {
|
|
626
|
+
const p = m.close?.(transport, deviceId);
|
|
627
|
+
if (p) return p;
|
|
628
|
+
}
|
|
629
|
+
return transport.close();
|
|
630
|
+
};
|
|
631
|
+
const open = (deviceId) => {
|
|
632
|
+
for (const m of modules) {
|
|
633
|
+
const p = m.open(deviceId);
|
|
634
|
+
if (p) return p;
|
|
635
|
+
}
|
|
636
|
+
return Promise.reject(/* @__PURE__ */ new Error(`Can't find handler to open ${deviceId}`));
|
|
637
|
+
};
|
|
638
|
+
const transportFinally = (cleanup) => (observable) => Observable.create((o) => {
|
|
639
|
+
let done = false;
|
|
640
|
+
const finalize = () => {
|
|
641
|
+
if (done) return never;
|
|
642
|
+
done = true;
|
|
643
|
+
return cleanup();
|
|
644
|
+
};
|
|
645
|
+
const sub = observable.subscribe({
|
|
646
|
+
next: (e) => o.next(e),
|
|
647
|
+
complete: () => {
|
|
648
|
+
finalize().then(() => o.complete());
|
|
649
|
+
},
|
|
650
|
+
error: (e) => {
|
|
651
|
+
finalize().then(() => o.error(e));
|
|
652
|
+
}
|
|
653
|
+
});
|
|
654
|
+
return () => {
|
|
655
|
+
sub.unsubscribe();
|
|
656
|
+
finalize();
|
|
657
|
+
};
|
|
658
|
+
});
|
|
659
|
+
const accessHooks = [];
|
|
660
|
+
const deviceQueues = {};
|
|
661
|
+
const withDevice = (deviceId) => (job) => new Observable((o) => {
|
|
662
|
+
let unsubscribed;
|
|
663
|
+
let sub;
|
|
664
|
+
const deviceQueue = deviceQueues[deviceId] ?? Promise.resolve();
|
|
665
|
+
const finalize = (transport, cleanups) => close(transport, deviceId).catch(() => {}).then(() => {
|
|
666
|
+
cleanups.forEach((c) => c());
|
|
667
|
+
});
|
|
668
|
+
let finish;
|
|
669
|
+
deviceQueues[deviceId] = new Promise((resolve) => {
|
|
670
|
+
finish = resolve;
|
|
671
|
+
});
|
|
672
|
+
deviceQueue.then(() => open(deviceId)).then(async (transport) => {
|
|
673
|
+
if (unsubscribed) return finalize(transport, [finish]);
|
|
674
|
+
if (transport.requestConnectionPriority && typeof transport.requestConnectionPriority === "function") await transport.requestConnectionPriority("High");
|
|
675
|
+
return transport;
|
|
676
|
+
}).catch((e) => {
|
|
677
|
+
finish();
|
|
678
|
+
if (e instanceof BluetoothRequired) throw e;
|
|
679
|
+
if (e instanceof TransportWebUSBGestureRequired) throw e;
|
|
680
|
+
if (e instanceof TransportInterfaceNotAvailable) throw e;
|
|
681
|
+
throw new CantOpenDevice(e.message);
|
|
682
|
+
}).then((transport) => {
|
|
683
|
+
if (!transport) return;
|
|
684
|
+
if (unsubscribed) return finalize(transport, [finish]);
|
|
685
|
+
const cleanups = accessHooks.map((hook) => hook());
|
|
686
|
+
sub = job(transport).pipe(catchError(initialErrorRemapping), transportFinally(() => finalize(transport, [...cleanups, finish]))).subscribe(o);
|
|
687
|
+
}).catch((error) => o.error(error));
|
|
688
|
+
return () => {
|
|
689
|
+
unsubscribed = true;
|
|
690
|
+
if (sub) sub.unsubscribe();
|
|
691
|
+
};
|
|
692
|
+
});
|
|
693
|
+
const WITH_DEVICE_POLLING_DELAY = 500;
|
|
694
|
+
const retryWhileErrors = (acceptError) => (attempts) => attempts.pipe(mergeMap((error) => {
|
|
695
|
+
if (!acceptError(error)) return throwError(error);
|
|
696
|
+
return timer(WITH_DEVICE_POLLING_DELAY);
|
|
697
|
+
}));
|
|
698
|
+
const withDevicePolling = (deviceId) => (job, acceptError = () => false) => withDevice(deviceId)(job).pipe(retryWhen(retryWhileErrors(acceptError)));
|
|
699
|
+
//#endregion
|
|
700
|
+
//#region src/device/utils.ts
|
|
701
|
+
const isTransportStatusError = (error) => {
|
|
702
|
+
return error instanceof TransportStatusError || error instanceof Error && "statusCode" in error && error.message.startsWith("Ledger device:");
|
|
703
|
+
};
|
|
704
|
+
const CANCEL_STATUS_CODES = [
|
|
705
|
+
27013,
|
|
706
|
+
45068,
|
|
707
|
+
45069,
|
|
708
|
+
45072,
|
|
709
|
+
45074,
|
|
710
|
+
45075,
|
|
711
|
+
21761
|
|
712
|
+
];
|
|
713
|
+
const isDeviceCancelError = (error) => {
|
|
714
|
+
return isTransportStatusError(error) && CANCEL_STATUS_CODES.includes(error.statusCode);
|
|
715
|
+
};
|
|
716
|
+
//#endregion
|
|
717
|
+
export { DisconnectedDevice as a, APPID_VAULT_ADMINISTRATOR as c, SCRIPT_IDS as d, STR_ROLES as f, withDevicePolling as i, PAGINATED_STATUS as l, isTransportStatusError as n, LockedDeviceError as o, registerTransportModule as r, createApiDevice as s, isDeviceCancelError as t, PATHS as u };
|
|
718
|
+
|
|
719
|
+
//# sourceMappingURL=device-B8Fww8_6.js.map
|