@ledgerhq/revault-sdk 0.21.5 → 0.21.7
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 +12 -3
- package/lib/bake.cjs.map +1 -1
- package/lib/bake.d.cts +8 -1
- package/lib/bake.d.ts +8 -1
- package/lib/bake.js +11 -2
- package/lib/bake.js.map +1 -1
- package/lib/{chunk-B5EUR3HT.cjs → chunk-2HKHCIKX.cjs} +75 -59
- package/lib/chunk-2HKHCIKX.cjs.map +1 -0
- package/lib/{chunk-7WN7G7BY.js → chunk-42CFPNWC.js} +78 -62
- package/lib/chunk-42CFPNWC.js.map +1 -0
- package/lib/{chunk-QVDZOA4O.js → chunk-73OX5XDM.js} +21 -12
- package/lib/chunk-73OX5XDM.js.map +1 -0
- package/lib/{chunk-CKNBRCHA.cjs → chunk-P53CFOI6.cjs} +22 -13
- package/lib/chunk-P53CFOI6.cjs.map +1 -0
- package/lib/crypto.cjs +4 -2
- package/lib/crypto.cjs.map +1 -1
- package/lib/crypto.d.cts +2 -1
- package/lib/crypto.d.ts +2 -1
- package/lib/crypto.js +5 -3
- package/lib/device.cjs +2 -2
- package/lib/device.d.cts +5 -5
- package/lib/device.d.ts +5 -5
- package/lib/device.js +1 -1
- package/lib/engine.cjs +46 -35
- package/lib/engine.cjs.map +1 -1
- package/lib/engine.d.cts +2 -2
- package/lib/engine.d.ts +2 -2
- package/lib/engine.js +28 -17
- package/lib/engine.js.map +1 -1
- package/lib/onboarding.cjs +20 -7
- package/lib/onboarding.cjs.map +1 -1
- package/lib/onboarding.d.cts +1 -1
- package/lib/onboarding.d.ts +1 -1
- package/lib/onboarding.js +19 -6
- package/lib/onboarding.js.map +1 -1
- package/lib/{types-Cp-L-rsW.d.ts → types-Dkr4g0qP.d.ts} +1 -1
- package/lib/{types-DEyShR5S.d.cts → types-pUN38HdE.d.cts} +1 -1
- package/package.json +12 -11
- package/lib/chunk-7WN7G7BY.js.map +0 -1
- package/lib/chunk-B5EUR3HT.cjs.map +0 -1
- package/lib/chunk-CKNBRCHA.cjs.map +0 -1
- package/lib/chunk-QVDZOA4O.js.map +0 -1
|
@@ -37,15 +37,19 @@ function createApiDevice(options, logger) {
|
|
|
37
37
|
_axiosretry2.default.call(void 0, deviceApi, {
|
|
38
38
|
retryDelay: _axiosretry2.default.linearDelay(1e3),
|
|
39
39
|
retries: 3,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
retryCondition: (
|
|
41
|
+
/* v8 ignore next -- @preserve */
|
|
42
|
+
() => true
|
|
43
|
+
),
|
|
44
|
+
onRetry: (
|
|
45
|
+
/* v8 ignore next -- @preserve */
|
|
46
|
+
(retryCount, err) => {
|
|
47
|
+
const formattedErr = `${_nullishCoalesce(err.code, () => ( `UNKNOWN`))} on ${_nullishCoalesce(_optionalChain([err, 'access', _ => _.config, 'optionalAccess', _2 => _2.method, 'optionalAccess', _3 => _3.toUpperCase, 'call', _4 => _4()]), () => ( "UNKNOWN_METHOD"))} ${_nullishCoalesce(_optionalChain([err, 'access', _5 => _5.config, 'optionalAccess', _6 => _6.url]), () => ( "UNKNOWN_URL"))}`;
|
|
48
|
+
logger.warning(
|
|
49
|
+
`Retrying request to device-api (attempt ${retryCount}) - Cause: ${formattedErr}`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
)
|
|
49
53
|
});
|
|
50
54
|
deviceApi.interceptors.request.use(
|
|
51
55
|
(config) => {
|
|
@@ -68,12 +72,15 @@ function createApiDevice(options, logger) {
|
|
|
68
72
|
}
|
|
69
73
|
return config;
|
|
70
74
|
},
|
|
71
|
-
/* v8 ignore stop */
|
|
72
75
|
(error) => Promise.reject(error)
|
|
73
76
|
);
|
|
74
77
|
return {
|
|
75
78
|
with: (index) => {
|
|
76
|
-
const
|
|
79
|
+
const __seed = genSeed({ salt: options.salt, index });
|
|
80
|
+
const getSeed = async () => {
|
|
81
|
+
if (typeof __seed === "string") return Promise.resolve(__seed);
|
|
82
|
+
return __seed;
|
|
83
|
+
};
|
|
77
84
|
const authenticate = async ({
|
|
78
85
|
challenge,
|
|
79
86
|
workspaceName
|
|
@@ -82,7 +89,7 @@ function createApiDevice(options, logger) {
|
|
|
82
89
|
if (role === "READ_ONLY_API_KEY")
|
|
83
90
|
throw new Error("Invalid role for authenticate: READ_ONLY_API_KEY");
|
|
84
91
|
const { data } = await deviceApi.post("/authenticate", {
|
|
85
|
-
seed,
|
|
92
|
+
seed: await getSeed(),
|
|
86
93
|
challenge: Buffer.from(challenge.challenge, "base64").toString("hex"),
|
|
87
94
|
application: APPID_VAULT_ADMINISTRATOR,
|
|
88
95
|
key_handle: challenge.keyHandle,
|
|
@@ -96,13 +103,13 @@ function createApiDevice(options, logger) {
|
|
|
96
103
|
};
|
|
97
104
|
const finalizePairingHandshake = async (params) => {
|
|
98
105
|
const { handshake, partitionId } = params;
|
|
99
|
-
const payload = { seed, handshake, ciphertext: partitionId };
|
|
106
|
+
const payload = { seed: await getSeed(), handshake, ciphertext: partitionId };
|
|
100
107
|
const res = await deviceApi.post("/finalize-pairing-handshake", payload);
|
|
101
108
|
return res.data;
|
|
102
109
|
};
|
|
103
110
|
const generateSeedFragment = async () => {
|
|
104
111
|
const payload = {
|
|
105
|
-
seed,
|
|
112
|
+
seed: await getSeed(),
|
|
106
113
|
path: PATHS.KEY_MATERIAL,
|
|
107
114
|
goal: 0
|
|
108
115
|
// seed fragment
|
|
@@ -112,12 +119,14 @@ function createApiDevice(options, logger) {
|
|
|
112
119
|
};
|
|
113
120
|
const generateWrappingKeyFragment = async () => {
|
|
114
121
|
const goal = 1;
|
|
115
|
-
const payload = { seed, goal, path: PATHS.KEY_MATERIAL };
|
|
122
|
+
const payload = { seed: await getSeed(), goal, path: PATHS.KEY_MATERIAL };
|
|
116
123
|
const res = await deviceApi.post("/generate-key-fragments", payload);
|
|
117
124
|
return Buffer.from(res.data, "hex").toString("base64");
|
|
118
125
|
};
|
|
119
126
|
const getAttestation = async () => {
|
|
120
|
-
const { data: attestationStr } = await deviceApi.post("/get-attestation", {
|
|
127
|
+
const { data: attestationStr } = await deviceApi.post("/get-attestation", {
|
|
128
|
+
seed: await getSeed()
|
|
129
|
+
});
|
|
121
130
|
const attestationBuffer = Buffer.from(attestationStr, "hex");
|
|
122
131
|
const certLen = attestationBuffer.readInt8(32 + 65 + 1);
|
|
123
132
|
return {
|
|
@@ -130,7 +139,7 @@ function createApiDevice(options, logger) {
|
|
|
130
139
|
};
|
|
131
140
|
};
|
|
132
141
|
const getConfidentialityKey = async () => {
|
|
133
|
-
const res = await deviceApi.post("/get-confidentiality-key", { seed });
|
|
142
|
+
const res = await deviceApi.post("/get-confidentiality-key", { seed: await getSeed() });
|
|
134
143
|
return {
|
|
135
144
|
confidentialityKeyCurve25519: res.data.confidentiality_key_curve25519,
|
|
136
145
|
confidentialityKeySignature: res.data.confidentiality_key_signature
|
|
@@ -140,7 +149,9 @@ function createApiDevice(options, logger) {
|
|
|
140
149
|
return getPublicKey({ path: PATHS.CONFIDENTIALITY });
|
|
141
150
|
};
|
|
142
151
|
const getDeviceUserId = async () => {
|
|
143
|
-
const res = await deviceApi.post("/blue-device-id", {
|
|
152
|
+
const res = await deviceApi.post("/blue-device-id", {
|
|
153
|
+
seed: await getSeed()
|
|
154
|
+
});
|
|
144
155
|
return res.data.blue_device_id.toUpperCase();
|
|
145
156
|
};
|
|
146
157
|
const getU2FPubKey = async () => {
|
|
@@ -150,13 +161,13 @@ function createApiDevice(options, logger) {
|
|
|
150
161
|
return getPublicKey({ path: PATHS.VALIDATION });
|
|
151
162
|
};
|
|
152
163
|
const hasPairing = async () => {
|
|
153
|
-
const res = await deviceApi.post("/get-partition-ids", { seed });
|
|
164
|
+
const res = await deviceApi.post("/get-partition-ids", { seed: await getSeed() });
|
|
154
165
|
return res.data.length > 0;
|
|
155
166
|
};
|
|
156
167
|
const initPairingHandshake = async () => {
|
|
157
168
|
const { data } = await deviceApi.post(
|
|
158
169
|
"/initiate-pairing-handshake",
|
|
159
|
-
{ seed }
|
|
170
|
+
{ seed: await getSeed() }
|
|
160
171
|
);
|
|
161
172
|
return {
|
|
162
173
|
pubKey: data.pubKey,
|
|
@@ -176,7 +187,7 @@ function createApiDevice(options, logger) {
|
|
|
176
187
|
attestationCertificate
|
|
177
188
|
]);
|
|
178
189
|
const payload = {
|
|
179
|
-
seed,
|
|
190
|
+
seed: await getSeed(),
|
|
180
191
|
path: PATHS.CONFIDENTIALITY,
|
|
181
192
|
pubKey: secureChannel.pubKey,
|
|
182
193
|
attestation: attestation.toString("hex"),
|
|
@@ -190,7 +201,7 @@ function createApiDevice(options, logger) {
|
|
|
190
201
|
const register = async (params) => {
|
|
191
202
|
const { challenge, u2fRegisterData, name, role } = params;
|
|
192
203
|
const payload = {
|
|
193
|
-
seed,
|
|
204
|
+
seed: await getSeed(),
|
|
194
205
|
challenge,
|
|
195
206
|
name,
|
|
196
207
|
role: STR_ROLES[role],
|
|
@@ -202,10 +213,14 @@ function createApiDevice(options, logger) {
|
|
|
202
213
|
const { data } = await deviceApi.post("/register", payload);
|
|
203
214
|
const response = Buffer.from(data, "hex");
|
|
204
215
|
let i = 0;
|
|
205
|
-
const rfu = response.slice(i, i
|
|
206
|
-
|
|
207
|
-
const
|
|
208
|
-
|
|
216
|
+
const rfu = response.slice(i, i + 1)[0];
|
|
217
|
+
i += 1;
|
|
218
|
+
const pubKey = response.slice(i, i + 65).toString("hex");
|
|
219
|
+
i += 65;
|
|
220
|
+
const keyHandleLength = response.slice(i, i + 1)[0];
|
|
221
|
+
i++;
|
|
222
|
+
const keyHandle = response.slice(i, i + keyHandleLength);
|
|
223
|
+
i += keyHandleLength;
|
|
209
224
|
return {
|
|
210
225
|
u2fRegister: response.slice(0, response.length - 2),
|
|
211
226
|
keyHandle,
|
|
@@ -215,13 +230,13 @@ function createApiDevice(options, logger) {
|
|
|
215
230
|
};
|
|
216
231
|
const registerData = async (params) => {
|
|
217
232
|
const { challenge } = params;
|
|
218
|
-
const payload = { seed, challenge };
|
|
233
|
+
const payload = { seed: await getSeed(), challenge };
|
|
219
234
|
const res = await deviceApi.post("/u2f-register-data", payload);
|
|
220
235
|
return res.data;
|
|
221
236
|
};
|
|
222
237
|
const setPairing = async ({ pairing }) => {
|
|
223
238
|
const payload = {
|
|
224
|
-
seed,
|
|
239
|
+
seed: await getSeed(),
|
|
225
240
|
blob: pairing.blob,
|
|
226
241
|
pairing: {
|
|
227
242
|
bootstrap_enabled: pairing.pairing.bootstrapEnabled,
|
|
@@ -239,7 +254,7 @@ function createApiDevice(options, logger) {
|
|
|
239
254
|
};
|
|
240
255
|
const startKKPatternAsResponder = async (params) => {
|
|
241
256
|
const payload = {
|
|
242
|
-
seed,
|
|
257
|
+
seed: await getSeed(),
|
|
243
258
|
script_id: SCRIPT_IDS.ACCOUNT_MANAGER_SESSION,
|
|
244
259
|
handshake: params.handshake,
|
|
245
260
|
// for device-api it's normal to have empty string as handshake_attestation
|
|
@@ -257,7 +272,7 @@ function createApiDevice(options, logger) {
|
|
|
257
272
|
const startKPatternAsResponder = async (params) => {
|
|
258
273
|
const { handshake, partitionId } = params;
|
|
259
274
|
const payload = {
|
|
260
|
-
seed,
|
|
275
|
+
seed: await getSeed(),
|
|
261
276
|
script_id: SCRIPT_IDS.ACCOUNT_MANAGER_SESSION,
|
|
262
277
|
handshake,
|
|
263
278
|
// for device-api it's normal to have empty string as handshake_attestation
|
|
@@ -274,7 +289,7 @@ function createApiDevice(options, logger) {
|
|
|
274
289
|
};
|
|
275
290
|
const getPublicKey = async (params) => {
|
|
276
291
|
const { path } = params;
|
|
277
|
-
const payload = { seed, secp256k1: true, path };
|
|
292
|
+
const payload = { seed: await getSeed(), secp256k1: true, path };
|
|
278
293
|
const res = await deviceApi.post("/get-public-key", payload);
|
|
279
294
|
return {
|
|
280
295
|
pubKey: res.data.pubKey,
|
|
@@ -284,7 +299,7 @@ function createApiDevice(options, logger) {
|
|
|
284
299
|
const validateVaultOperation = async (params) => {
|
|
285
300
|
const { actions } = params;
|
|
286
301
|
const payload = {
|
|
287
|
-
seed,
|
|
302
|
+
seed: await getSeed(),
|
|
288
303
|
path: PATHS.VALIDATION,
|
|
289
304
|
actions
|
|
290
305
|
};
|
|
@@ -335,30 +350,6 @@ function createApiDevice(options, logger) {
|
|
|
335
350
|
};
|
|
336
351
|
}
|
|
337
352
|
|
|
338
|
-
// src/device/utils.ts
|
|
339
|
-
var _errors = require('@ledgerhq/errors');
|
|
340
|
-
var isTransportStatusError = (error) => {
|
|
341
|
-
return error instanceof _errors.TransportStatusError || error instanceof Error && "statusCode" in error && error.message.startsWith("Ledger device:");
|
|
342
|
-
};
|
|
343
|
-
var CANCEL_STATUS_CODES = [
|
|
344
|
-
27013,
|
|
345
|
-
// cancel on Ledger Blue
|
|
346
|
-
// STAX
|
|
347
|
-
45068,
|
|
348
|
-
// cancel collect wk fragment
|
|
349
|
-
45069,
|
|
350
|
-
// cancel user registration
|
|
351
|
-
45072,
|
|
352
|
-
// cancel review
|
|
353
|
-
45074,
|
|
354
|
-
// cancel master seed generation
|
|
355
|
-
45075
|
|
356
|
-
// cancel login
|
|
357
|
-
];
|
|
358
|
-
var isDeviceCancelError = (error) => {
|
|
359
|
-
return isTransportStatusError(error) && CANCEL_STATUS_CODES.includes(error.statusCode);
|
|
360
|
-
};
|
|
361
|
-
|
|
362
353
|
// src/device/device-access.ts
|
|
363
354
|
|
|
364
355
|
|
|
@@ -368,7 +359,7 @@ var isDeviceCancelError = (error) => {
|
|
|
368
359
|
|
|
369
360
|
|
|
370
361
|
|
|
371
|
-
|
|
362
|
+
var _errors = require('@ledgerhq/errors');
|
|
372
363
|
var _rxjs = require('rxjs');
|
|
373
364
|
var _operators = require('rxjs/operators');
|
|
374
365
|
var initialErrorRemapping = (error) => _rxjs.throwError.call(void 0,
|
|
@@ -482,6 +473,30 @@ var retryWhileErrors = (acceptError) => (
|
|
|
482
473
|
);
|
|
483
474
|
var withDevicePolling = (deviceId) => (job, acceptError = () => false) => withDevice(deviceId)(job).pipe(_operators.retryWhen.call(void 0, retryWhileErrors(acceptError)));
|
|
484
475
|
|
|
476
|
+
// src/device/utils.ts
|
|
477
|
+
|
|
478
|
+
var isTransportStatusError = (error) => {
|
|
479
|
+
return error instanceof _errors.TransportStatusError || error instanceof Error && "statusCode" in error && error.message.startsWith("Ledger device:");
|
|
480
|
+
};
|
|
481
|
+
var CANCEL_STATUS_CODES = [
|
|
482
|
+
27013,
|
|
483
|
+
// cancel on Ledger Blue
|
|
484
|
+
// STAX
|
|
485
|
+
45068,
|
|
486
|
+
// cancel collect wk fragment
|
|
487
|
+
45069,
|
|
488
|
+
// cancel user registration
|
|
489
|
+
45072,
|
|
490
|
+
// cancel review
|
|
491
|
+
45074,
|
|
492
|
+
// cancel master seed generation
|
|
493
|
+
45075
|
|
494
|
+
// cancel login
|
|
495
|
+
];
|
|
496
|
+
var isDeviceCancelError = (error) => {
|
|
497
|
+
return isTransportStatusError(error) && CANCEL_STATUS_CODES.includes(error.statusCode);
|
|
498
|
+
};
|
|
499
|
+
|
|
485
500
|
|
|
486
501
|
|
|
487
502
|
|
|
@@ -496,5 +511,6 @@ var withDevicePolling = (deviceId) => (job, acceptError = () => false) => withDe
|
|
|
496
511
|
|
|
497
512
|
|
|
498
513
|
|
|
499
|
-
exports.PATHS = PATHS; exports.STATUS_LENGTH = STATUS_LENGTH; exports.SCRIPT_IDS = SCRIPT_IDS; exports.STR_ROLES = STR_ROLES; exports.APPID_VAULT_ADMINISTRATOR = APPID_VAULT_ADMINISTRATOR; exports.PAGINATED_STATUS = PAGINATED_STATUS; exports.STREAMING_RESPONSE = STREAMING_RESPONSE; exports.STREAMING_NEXT_ACTION = STREAMING_NEXT_ACTION; exports.createApiDevice = createApiDevice; exports.
|
|
500
|
-
|
|
514
|
+
exports.PATHS = PATHS; exports.STATUS_LENGTH = STATUS_LENGTH; exports.SCRIPT_IDS = SCRIPT_IDS; exports.STR_ROLES = STR_ROLES; exports.APPID_VAULT_ADMINISTRATOR = APPID_VAULT_ADMINISTRATOR; exports.PAGINATED_STATUS = PAGINATED_STATUS; exports.STREAMING_RESPONSE = STREAMING_RESPONSE; exports.STREAMING_NEXT_ACTION = STREAMING_NEXT_ACTION; exports.createApiDevice = createApiDevice; exports.registerTransportModule = registerTransportModule; exports.withDevicePolling = withDevicePolling; exports.isTransportStatusError = isTransportStatusError; exports.isDeviceCancelError = isDeviceCancelError;
|
|
515
|
+
/* v8 ignore next -- @preserve */
|
|
516
|
+
//# sourceMappingURL=chunk-2HKHCIKX.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/_work/revault/revault/packages/sdk/lib/chunk-2HKHCIKX.cjs","../src/device/api-device.ts","../src/device/constants.ts","../src/device/device-access.ts","../src/device/utils.ts"],"names":["TransportStatusError"],"mappings":"AAAA;ACMA,4EAAkB;AAClB,iGAAuB;AACvB,4BAA6B;ADJ7B;AACA;AELO,IAAM,MAAA,EAAQ;AAAA,EACnB,GAAA,EAAK,mBAAA;AAAA,EACL,eAAA,EAAiB,mBAAA;AAAA,EACjB,YAAA,EAAc,mBAAA;AAAA,EACd,UAAA,EAAY;AACd,CAAA;AAEO,IAAM,cAAA,EAAgB,CAAA;AAEtB,IAAM,WAAA,EAAa;AAAA,EACxB,YAAA,EAAc,CAAA;AAAA,EACd,uBAAA,EAAyB;AAC3B,CAAA;AAEO,IAAM,UAAA,EAAmE;AAAA,EAC9E,QAAA,EAAU,IAAA;AAAA,EACV,KAAA,EAAO,IAAA;AAAA,EACP,YAAA,EAAc;AAChB,CAAA;AAEO,IAAM,0BAAA,EACX,kEAAA;AAEF,IAAM,cAAA,EAAgB,CAAC,CAAA;AACvB,IAAA,CAAA,IAAS,EAAA,EAAI,KAAA,EAAQ,EAAA,GAAK,KAAA,EAAQ,CAAA,EAAA,EAAK;AACrC,EAAA,aAAA,CAAc,IAAA,CAAK,CAAC,CAAA;AACtB;AAEO,IAAM,iBAAA,EAAmB,aAAA;AACzB,IAAM,mBAAA,EAAqB,CAAA;AAC3B,IAAM,sBAAA,EAAwB,CAAA;AFArC;AACA;ACQO,SAAS,eAAA,CAAgB,OAAA,EAAkB,MAAA,EAA2B;AAC3E,EAAA,MAAM,EAAE,QAAQ,EAAA,EAAI,OAAA;AACpB,EAAA,MAAM,UAAA,EAAY,sBAAA,CAAO;AACzB,EAAA,MAAM,UAAA,EAAY,eAAA,CAAM,MAAA,CAAO,EAAE,OAAA,EAAS,OAAA,CAAQ,aAAa,CAAC,CAAA;AAEhE,EAAA,kCAAA,SAAW,EAAW;AAAA,IACpB,UAAA,EAAY,oBAAA,CAAW,WAAA,CAAY,GAAI,CAAA;AAAA,IACvC,OAAA,EAAS,CAAA;AAAA,IACT,cAAA,EAAA;AAAA;AAAA,MAAkD,CAAA,EAAA,GAAM;AAAA,IAAA,CAAA;AAAA,IACxD,OAAA,EAAA;AAAA;AAAA,MAEE,CAAC,UAAA,EAAY,GAAA,EAAA,GAAQ;AACnB,QAAA,MAAM,aAAA,EAAe,CAAA,mBAAA;AACd,QAAA;AACL,UAAA;AACF,QAAA;AACF,MAAA;AAAA,IAAA;AACH,EAAA;AAGsB,EAAA;AACT,IAAA;AACH,MAAA;AACW,QAAA;AAClB,MAAA;AACoB,MAAA;AAGG,QAAA;AACP,QAAA;AAIO,QAAA;AACR,UAAA;AAAA;AACA,UAAA;AAAA;AACF,UAAA;AAAA;AACN,UAAA;AACL,QAAA;AACc,QAAA;AAChB,MAAA;AACO,MAAA;AACT,IAAA;AACiC,IAAA;AACnC,EAAA;AAEO,EAAA;AAC4B,IAAA;AACR,MAAA;AAEP,MAAA;AACQ,QAAA;AACf,QAAA;AACT,MAAA;AAEqB,MAAA;AACnB,QAAA;AACA,QAAA;AAIqB,MAAA;AACR,QAAA;AACA,QAAA;AACK,UAAA;AACD,QAAA;AACK,UAAA;AACF,UAAA;AACL,UAAA;AACD,UAAA;AACI,UAAA;AACI,UAAA;AACd,UAAA;AAAA;AACN,UAAA;AACD,QAAA;AACM,QAAA;AACT,MAAA;AAEM,MAAA;AAIe,QAAA;AACD,QAAA;AACA,QAAA;AACP,QAAA;AACb,MAAA;AAEM,MAAA;AACY,QAAA;AACM,UAAA;AACR,UAAA;AACN,UAAA;AAAA;AACR,QAAA;AACiB,QAAA;AACV,QAAA;AACT,MAAA;AAEM,MAAA;AACS,QAAA;AACK,QAAA;AACA,QAAA;AACC,QAAA;AACrB,MAAA;AAEuB,MAAA;AAQP,QAAA;AACQ,UAAA;AACrB,QAAA;AACK,QAAA;AACU,QAAA;AACT,QAAA;AACQ,UAAA;AACD,YAAA;AACM,YAAA;AACH,YAAA;AACf,UAAA;AACQ,UAAA;AACV,QAAA;AACF,MAAA;AAEM,MAAA;AAIc,QAAA;AAIX,QAAA;AACL,UAAA;AACA,UAAA;AACF,QAAA;AACF,MAAA;AAEM,MAAA;AACkB,QAAA;AACxB,MAAA;AAEwB,MAAA;AACJ,QAAA;AACI,UAAA;AACrB,QAAA;AACe,QAAA;AAClB,MAAA;AAEqB,MAAA;AACG,QAAA;AACxB,MAAA;AAEM,MAAA;AACkB,QAAA;AACxB,MAAA;AAEmB,MAAA;AACC,QAAA;AACF,QAAA;AAClB,MAAA;AAEM,MAAA;AACa,QAAA;AACf,UAAA;AACc,UAAA;AAChB,QAAA;AACO,QAAA;AACQ,UAAA;AACK,UAAA;AACpB,QAAA;AACF,MAAA;AAEoB,MAAA;AAGI,QAAA;AACJ,QAAA;AACZ,QAAA;AACA,QAAA;AACc,QAAA;AACL,UAAA;AACb,UAAA;AACA,UAAA;AACa,UAAA;AACb,UAAA;AACD,QAAA;AACe,QAAA;AACM,UAAA;AACR,UAAA;AACJ,UAAA;AACK,UAAA;AACH,UAAA;AACZ,QAAA;AACc,QAAA;AACV,QAAA;AACc,UAAA;AAClB,QAAA;AACF,MAAA;AAEwB,MAAA;AAWH,QAAA;AACH,QAAA;AACM,UAAA;AACpB,UAAA;AACA,UAAA;AACoB,UAAA;AACV,UAAA;AACJ,UAAA;AAAA;AACO,UAAA;AACf,QAAA;AACiB,QAAA;AACA,QAAA;AACT,QAAA;AACa,QAAA;AAChB,QAAA;AACU,QAAA;AACV,QAAA;AACC,QAAA;AACN,QAAA;AACkB,QAAA;AACb,QAAA;AACE,QAAA;AACQ,UAAA;AACb,UAAA;AACA,UAAA;AACA,UAAA;AACF,QAAA;AACF,MAAA;AAEqB,MAAA;AACG,QAAA;AACJ,QAAA;AACA,QAAA;AACP,QAAA;AACb,MAAA;AAEmB,MAAA;AACD,QAAA;AACM,UAAA;AACN,UAAA;AACL,UAAA;AACP,YAAA;AACe,YAAA;AACC,YAAA;AAClB,UAAA;AACA,UAAA;AACa,YAAA;AACM,YAAA;AACJ,YAAA;AACF,YAAA;AACb,UAAA;AACF,QAAA;AACqB,QAAA;AACvB,MAAA;AAEM,MAAA;AAKY,QAAA;AACM,UAAA;AACT,UAAA;AACO,UAAA;AAAA;AAElB,UAAA;AACc,UAAA;AAChB,QAAA;AACiB,QAAA;AACK,QAAA;AACH,QAAA;AACZ,QAAA;AACa,UAAA;AACA,UAAA;AACpB,QAAA;AACF,MAAA;AAEM,MAAA;AAKe,QAAA;AACH,QAAA;AACM,UAAA;AACT,UAAA;AACX,UAAA;AAAA;AAEA,UAAA;AACc,UAAA;AAChB,QAAA;AACc,QAAA;AACZ,UAAA;AACA,UAAA;AACF,QAAA;AACI,QAAA;AACc,UAAA;AAClB,QAAA;AACF,MAAA;AAEqB,MAAA;AAGF,QAAA;AAEC,QAAA;AACA,QAAA;AACX,QAAA;AACY,UAAA;AACC,UAAA;AACpB,QAAA;AACF,MAAA;AAEM,MAAA;AACgB,QAAA;AACJ,QAAA;AACM,UAAA;AACR,UAAA;AACZ,UAAA;AACF,QAAA;AACc,QAAA;AACP,QAAA;AACT,MAAA;AAEkB,MAAA;AACJ,QAAA;AACG,QAAA;AACjB,MAAA;AAEmB,MAAA;AACV,QAAA;AACT,MAAA;AAEa,MAAA;AACQ,QAAA;AACG,QAAA;AACxB,MAAA;AAEgB,MAAA;AACK,QAAA;AACZ,QAAA;AACT,MAAA;AAEO,MAAA;AACL,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACF,EAAA;AACF;ADzE8B;AACA;AGtV9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACK;AAEc;AACA;AAEU;AAED,EAAA;AAK5B;AAG8B;AAAE;AAyBE;AAEG;AAClB,EAAA;AACrB;AAE4C;AACjB,EAAA;AACH,IAAA;AACN,IAAA;AAChB,EAAA;AAEuB,EAAA;AACzB;AAE8D;AACnC,EAAA;AACE,IAAA;AACX,IAAA;AAChB,EAAA;AAC0B,EAAA;AAC5B;AAGG;AACG;AAEuB,EAAA;AACZ,IAAA;AAGiB,IAAA;AACT,MAAA;AACV,MAAA;AACQ,MAAA;AACjB,IAAA;AAEuB,IAAA;AACA,MAAA;AACL,MAAA;AACO,QAAA;AACvB,MAAA;AACc,MAAA;AACS,QAAA;AACvB,MAAA;AACD,IAAA;AACY,IAAA;AACK,MAAA;AACF,MAAA;AAChB,IAAA;AACD,EAAA;AAAA;AAI8B;AAEb;AAGnB;AAIO,EAAA;AAEA,EAAA;AAEgB,EAAA;AAGF,EAAA;AAIF,EAAA;AAEgB,IAAA;AAC3B,EAAA;AAID,EAAA;AAGqB,EAAA;AACd,IAAA;AACV,EAAA;AAGkB,EAAA;AAIG,IAAA;AAGA,MAAA;AAClB,IAAA;AAGY,IAAA;AAGM,MAAA;AAClB,IAAA;AAEO,IAAA;AAGK,EAAA;AAEL,IAAA;AACU,IAAA;AACA,IAAA;AACA,IAAA;AACQ,IAAA;AAGN,EAAA;AACH,IAAA;AAGE,IAAA;AAGA,MAAA;AAClB,IAAA;AAEiB,IAAA;AAEd,IAAA;AACY,MAAA;AAAqB;AAEhC,MAAA;AAAiB,QAAA;AAAA;AAEK,UAAA;AAAqB,QAAA;AAC3C,MAAA;AAEU,IAAA;AAGU,EAAA;AACf,EAAA;AACI,IAAA;AAEU,IAAA;AAC3B,EAAA;AACD;AAEC;AAGH;AAAA;AAGU,EAAA;AACa,IAAA;AACI,MAAA;AACF,QAAA;AACpB,MAAA;AAEa,MAAA;AACd,IAAA;AACH,EAAA;AAAA;AAGD;AH0P2B;AACA;AI3drB;AAE8B;AAElBA,EAAAA;AAGrB;AAE4B;AAC1B,EAAA;AAAA;AAAA;AAGA,EAAA;AAAA;AACA,EAAA;AAAA;AACA,EAAA;AAAA;AACA,EAAA;AAAA;AACA,EAAA;AAAA;AACF;AAEoC;AAC3B,EAAA;AACT;AJ4d8B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/_work/revault/revault/packages/sdk/lib/chunk-2HKHCIKX.cjs","sourcesContent":[null,"import type {\n HsmCertificate,\n PsdAuthChallengeResponse,\n PsdPairingData,\n PubKey,\n} from \"@ledgerhq/revault-api\";\nimport axios from \"axios\";\nimport axiosRetry from \"axios-retry\";\nimport { v4 as uuidv4 } from \"uuid\";\n\nimport type { Logger } from \"@/logger\";\n\nimport { APPID_VAULT_ADMINISTRATOR, PATHS, SCRIPT_IDS, STR_ROLES } from \"./constants\";\nimport type { Device } from \"./types\";\n\ntype Options = {\n /**\n * device-api URL\n */\n deviceApiUrl: string;\n\n /**\n * salt used by device-api\n */\n salt: string;\n\n /**\n * seed generation function used for device-api device spawn\n */\n genSeed: (p: { salt: string; index: number }) => string | Promise<string>;\n};\n\nexport type ApiDevice = {\n /**\n * bind a device to the given device index\n */\n with: (index: number) => Device;\n};\n\nexport function createApiDevice(options: Options, logger: Logger): ApiDevice {\n const { genSeed } = options;\n const sessionId = uuidv4();\n const deviceApi = axios.create({ baseURL: options.deviceApiUrl });\n\n axiosRetry(deviceApi, {\n retryDelay: axiosRetry.linearDelay(1000),\n retries: 3,\n retryCondition: /* v8 ignore next -- @preserve */ () => true,\n onRetry:\n /* v8 ignore next -- @preserve */\n (retryCount, err) => {\n const formattedErr = `${err.code ?? `UNKNOWN`} on ${err.config?.method?.toUpperCase() ?? \"UNKNOWN_METHOD\"} ${err.config?.url ?? \"UNKNOWN_URL\"}`;\n logger.warning(\n `Retrying request to device-api (attempt ${retryCount}) - Cause: ${formattedErr}`,\n );\n },\n });\n\n /* v8 ignore next -- @preserve */\n deviceApi.interceptors.request.use(\n (config) => {\n logger.debug(\n `[device-api] ${config.method?.toUpperCase()} ${config.url}${config.data ? ` ${JSON.stringify(config.data)}` : \"\"}`,\n );\n if ([\"post\", \"put\"].includes(config.method!)) {\n // when interceptor is called in combination with axios-retry, config.data can be a string or an object\n // and we should return either a string or an object compatible with the original type\n const isStringMode = typeof config.data === \"string\";\n const data = (isStringMode ? JSON.parse(config.data) : config.data) as Record<\n string,\n unknown\n >;\n const enhancedData = {\n sessionID: sessionId, // Used to ensure dedicated session if someones else uses same seed\n psd_model: \"02\", // Stax\n version: 3, // Used to properly enable noise channel\n ...data,\n };\n config.data = isStringMode ? JSON.stringify(enhancedData) : enhancedData;\n }\n return config;\n },\n (error: Error) => Promise.reject(error),\n );\n\n return {\n with: (index: number): Device => {\n const __seed = genSeed({ salt: options.salt, index });\n\n const getSeed = async (): Promise<string> => {\n if (typeof __seed === \"string\") return Promise.resolve(__seed);\n return __seed;\n };\n\n const authenticate = async ({\n challenge,\n workspaceName,\n }: {\n challenge: PsdAuthChallengeResponse;\n workspaceName: string;\n }): Promise<string> => {\n const role = challenge.role;\n if (role === \"READ_ONLY_API_KEY\")\n throw new Error(\"Invalid role for authenticate: READ_ONLY_API_KEY\");\n const { data } = await deviceApi.post<string>(\"/authenticate\", {\n seed: await getSeed(),\n challenge: Buffer.from(challenge.challenge, \"base64\").toString(\"hex\"),\n application: APPID_VAULT_ADMINISTRATOR,\n key_handle: challenge.keyHandle,\n name: challenge.name,\n role: STR_ROLES[role],\n type: \"02\", // Stax\n workspaceName,\n });\n return data;\n };\n\n const finalizePairingHandshake = async (params: {\n handshake: string;\n partitionId: string;\n }): Promise<string> => {\n const { handshake, partitionId } = params;\n const payload = { seed: await getSeed(), handshake, ciphertext: partitionId };\n const res = await deviceApi.post<string>(\"/finalize-pairing-handshake\", payload);\n return res.data;\n };\n\n const generateSeedFragment = async (): Promise<string> => {\n const payload = {\n seed: await getSeed(),\n path: PATHS.KEY_MATERIAL,\n goal: 0, // seed fragment\n };\n const { data } = await deviceApi.post<string>(\"/generate-key-component\", payload);\n return data;\n };\n\n const generateWrappingKeyFragment = async (): Promise<string> => {\n const goal = 1; // means Wrapping Key\n const payload = { seed: await getSeed(), goal, path: PATHS.KEY_MATERIAL };\n const res = await deviceApi.post<string>(\"/generate-key-fragments\", payload);\n return Buffer.from(res.data, \"hex\").toString(\"base64\");\n };\n\n const getAttestation = async (): Promise<{\n attestation: {\n codeHash: string;\n attestationPub: string;\n certificate: string;\n };\n buffer: Buffer;\n }> => {\n const { data: attestationStr } = await deviceApi.post<string>(\"/get-attestation\", {\n seed: await getSeed(),\n });\n const attestationBuffer = Buffer.from(attestationStr, \"hex\");\n const certLen = attestationBuffer.readInt8(32 + 65 + 1);\n return {\n attestation: {\n codeHash: attestationBuffer.slice(0, 32).toString(\"base64\"),\n attestationPub: attestationBuffer.slice(32, 32 + 65).toString(\"base64\"),\n certificate: attestationBuffer.slice(32 + 65, 32 + 65 + 2 + certLen).toString(\"base64\"),\n },\n buffer: attestationBuffer,\n };\n };\n\n const getConfidentialityKey = async (): Promise<{\n confidentialityKeyCurve25519: string;\n confidentialityKeySignature: string;\n }> => {\n const res = await deviceApi.post<{\n confidentiality_key_curve25519: string;\n confidentiality_key_signature: string;\n }>(\"/get-confidentiality-key\", { seed: await getSeed() });\n return {\n confidentialityKeyCurve25519: res.data.confidentiality_key_curve25519,\n confidentialityKeySignature: res.data.confidentiality_key_signature,\n };\n };\n\n const getConfidentialityPubKey = async (): Promise<{ pubKey: string; signature: string }> => {\n return getPublicKey({ path: PATHS.CONFIDENTIALITY });\n };\n\n const getDeviceUserId = async (): Promise<string> => {\n const res = await deviceApi.post<{ blue_device_id: string }>(\"/blue-device-id\", {\n seed: await getSeed(),\n });\n return res.data.blue_device_id.toUpperCase();\n };\n\n const getU2FPubKey = async (): Promise<{ pubKey: string; signature: string }> => {\n return getPublicKey({ path: PATHS.U2F });\n };\n\n const getValidationPubKey = async (): Promise<{ pubKey: string; signature: string }> => {\n return getPublicKey({ path: PATHS.VALIDATION });\n };\n\n const hasPairing = async (): Promise<boolean> => {\n const res = await deviceApi.post<string[]>(\"/get-partition-ids\", { seed: await getSeed() });\n return res.data.length > 0;\n };\n\n const initPairingHandshake = async (): Promise<{ pubKey: string; signature: string }> => {\n const { data } = await deviceApi.post<{ attestation: string; pubKey: string }>(\n \"/initiate-pairing-handshake\",\n { seed: await getSeed() },\n );\n return {\n pubKey: data.pubKey,\n signature: Buffer.from(data.attestation, \"hex\").toString(\"base64\"),\n };\n };\n\n const openSession = async (params: {\n secureChannel: { pubKey: PubKey; certificate: HsmCertificate };\n }): Promise<void> => {\n const { secureChannel } = params;\n const signature = Buffer.from(secureChannel.certificate.signature, \"base64\");\n const attestationPubKey = Buffer.from(secureChannel.certificate.attestationPub, \"base64\");\n const attestationCertificate = Buffer.from(secureChannel.certificate.certificate, \"base64\");\n const attestation = Buffer.concat([\n Buffer.from([signature.length]),\n signature,\n attestationPubKey,\n Buffer.from([attestationCertificate.length]),\n attestationCertificate,\n ]);\n const payload = {\n seed: await getSeed(),\n path: PATHS.CONFIDENTIALITY,\n pubKey: secureChannel.pubKey,\n attestation: attestation.toString(\"hex\"),\n scriptId: SCRIPT_IDS.INIT_SESSION,\n };\n const { data: deviceResponse } = await deviceApi.post<string>(\"/open-session\", payload);\n if (deviceResponse !== \"9000\") {\n throw new Error(`device-api device failed with code: ${deviceResponse}`);\n }\n };\n\n const register = async (params: {\n challenge: string;\n u2fRegisterData: string;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n }): Promise<{\n u2fRegister: Buffer;\n keyHandle: Buffer;\n rfu: number;\n pubKey: string;\n }> => {\n const { challenge, u2fRegisterData, name, role } = params;\n const payload = {\n seed: await getSeed(),\n challenge,\n name,\n role: STR_ROLES[role],\n hsm_data: u2fRegisterData,\n type: \"02\", // Stax\n application: APPID_VAULT_ADMINISTRATOR,\n };\n const { data } = await deviceApi.post<string>(\"/register\", payload);\n const response = Buffer.from(data, \"hex\");\n let i = 0;\n const rfu = response.slice(i, i + 1)[0]!;\n i += 1;\n const pubKey = response.slice(i, i + 65).toString(\"hex\");\n i += 65;\n const keyHandleLength = response.slice(i, i + 1)[0]!;\n i++;\n const keyHandle = response.slice(i, i + keyHandleLength);\n i += keyHandleLength;\n return {\n u2fRegister: response.slice(0, response.length - 2),\n keyHandle,\n rfu,\n pubKey,\n };\n };\n\n const registerData = async (params: { challenge: string }): Promise<string> => {\n const { challenge } = params;\n const payload = { seed: await getSeed(), challenge };\n const res = await deviceApi.post<string>(\"/u2f-register-data\", payload);\n return res.data;\n };\n\n const setPairing = async ({ pairing }: { pairing: PsdPairingData }): Promise<void> => {\n const payload = {\n seed: await getSeed(),\n blob: pairing.blob,\n pairing: {\n bootstrap_enabled: pairing.pairing.bootstrapEnabled,\n partition_key: pairing.pairing.partitionKey,\n workspace_name: pairing.pairing.workspaceName,\n },\n partition_key_attestation: {\n code_hash: pairing.partitionKeyAttestation.codeHash,\n attestation_pub: pairing.partitionKeyAttestation.attestationPub,\n certificate: pairing.partitionKeyAttestation.certificate,\n signature: pairing.partitionKeyAttestation.signature,\n },\n };\n await deviceApi.post(\"/set-partition-key\", payload);\n };\n\n const startKKPatternAsResponder = async (params: {\n handshake: string;\n handshakeAttestation: HsmCertificate;\n partitionId: string;\n }): Promise<{ handshake: string; signature: string }> => {\n const payload = {\n seed: await getSeed(),\n script_id: SCRIPT_IDS.ACCOUNT_MANAGER_SESSION,\n handshake: params.handshake,\n // for device-api it's normal to have empty string as handshake_attestation\n handshake_attestation: \"\",\n partition_id: params.partitionId,\n };\n const { data } = await deviceApi.post<string>(\"/start-kk-pattern-as-responder\", payload);\n const buffer = Buffer.from(data, \"hex\");\n const dataLength = buffer.readInt8(0);\n return {\n handshake: buffer.slice(1, dataLength + 1).toString(\"base64\"),\n signature: buffer.slice(dataLength + 1).toString(\"base64\"),\n };\n };\n\n const startKPatternAsResponder = async (params: {\n handshake: string;\n handshakeAttestation: HsmCertificate;\n partitionId: string;\n }): Promise<void> => {\n const { handshake, partitionId } = params;\n const payload = {\n seed: await getSeed(),\n script_id: SCRIPT_IDS.ACCOUNT_MANAGER_SESSION,\n handshake,\n // for device-api it's normal to have empty string as handshake_attestation\n handshake_attestation: \"\",\n partition_id: partitionId,\n };\n const { data: deviceResponse } = await deviceApi.post<string>(\n \"/start-k-pattern-as-responder\",\n payload,\n );\n if (deviceResponse !== \"9000\") {\n throw new Error(`device-api device failed with code: ${deviceResponse}`);\n }\n };\n\n const getPublicKey = async (params: {\n path: string;\n }): Promise<{ pubKey: string; signature: string }> => {\n const { path } = params;\n type DeviceApiGetPubKeyResponse = { attestation: string; pubKey: string };\n const payload = { seed: await getSeed(), secp256k1: true, path };\n const res = await deviceApi.post<DeviceApiGetPubKeyResponse>(\"/get-public-key\", payload);\n return {\n pubKey: res.data.pubKey,\n signature: Buffer.from(res.data.attestation, \"hex\").toString(\"base64\"),\n };\n };\n\n const validateVaultOperation = async (params: { actions: string[] }): Promise<string> => {\n const { actions } = params;\n const payload = {\n seed: await getSeed(),\n path: PATHS.VALIDATION,\n actions,\n };\n const { data: signature } = await deviceApi.post<string>(\"/validate-op\", payload);\n return signature;\n };\n\n const sendAPDU = (_apdu: string): Promise<string> => {\n logger.info(\"Can't send arbitrary APDU to software device\");\n return Promise.resolve(\"9000\");\n };\n\n const getVersion = async (): Promise<string> => {\n return \"1.2.3\";\n };\n\n const poll = async (): Promise<{ isAppOpened: boolean }> => {\n await new Promise((r) => setTimeout(r, 1e3));\n return { isAppOpened: true };\n };\n\n const pollApp = async (): Promise<string> => {\n await new Promise((r) => setTimeout(r, 1e3));\n return \"9000\";\n };\n\n return {\n authenticate,\n finalizePairingHandshake,\n generateSeedFragment,\n generateWrappingKeyFragment,\n getAttestation,\n getConfidentialityKey,\n getConfidentialityPubKey,\n getDeviceUserId,\n getU2FPubKey,\n getValidationPubKey,\n hasPairing,\n initPairingHandshake,\n openSession,\n register,\n registerData,\n setPairing,\n startKKPatternAsResponder,\n startKPatternAsResponder,\n validateVaultOperation,\n getVersion,\n sendAPDU,\n poll,\n pollApp,\n };\n },\n };\n}\n","export const PATHS = {\n U2F: \"5655636'/5583430'\",\n CONFIDENTIALITY: \"5655636'/4410950'\",\n KEY_MATERIAL: \"5655636'/4932953'\",\n VALIDATION: \"5655636'/5652812'\",\n} as const;\n\nexport const STATUS_LENGTH = 2;\n\nexport const SCRIPT_IDS = {\n INIT_SESSION: 3,\n ACCOUNT_MANAGER_SESSION: 2,\n} as const;\n\nexport const STR_ROLES: Record<\"OPERATOR\" | \"ADMIN\" | \"SHARED_OWNER\", string> = {\n OPERATOR: \"00\",\n ADMIN: \"01\",\n SHARED_OWNER: \"02\",\n} as const;\n\nexport const APPID_VAULT_ADMINISTRATOR =\n \"ad5be1a1fe011ce7f53ae081a22ae000a42021f3f94106a3bac9f76e8230e4b9\";\n\nconst all61xxStatus = [];\nfor (let i = 0x6100; i <= 0x61ff; i++) {\n all61xxStatus.push(i);\n}\n\nexport const PAGINATED_STATUS = all61xxStatus;\nexport const STREAMING_RESPONSE = 0x02;\nexport const STREAMING_NEXT_ACTION = 0x01;\n","// biome-ignore-all lint: outside copy-paste, not worth fixing\n// ------------------------------------------------------------------------------------------------\n// ------------------------------------------------------------------------------------------------\n// THIS IS SOME HORRIBLE CODE IMPORTED JUST\n// FOR THE SAKE OF NOT IMPORTING UGLY, WICKED, AND\n// BROKEN @ledgerhq/live-* LIBRARIES\n//\n// IT'S MEANT TO BE CONSIDERED AS A BLACK BOX\n// ------------------------------------------------------------------------------------------------\n// ------------------------------------------------------------------------------------------------\nimport {\n BluetoothRequired,\n CantOpenDevice,\n DeviceHalted,\n FirmwareOrAppUpdateRequired,\n TransportInterfaceNotAvailable,\n TransportStatusError,\n TransportWebUSBGestureRequired,\n} from \"@ledgerhq/errors\";\nimport type Transport from \"@ledgerhq/hw-transport\";\nimport { Observable, throwError, timer } from \"rxjs\";\nimport { catchError, mergeMap, retryWhen } from \"rxjs/operators\";\n\nconst initialErrorRemapping = (error: Error): Observable<never> =>\n throwError(\n error && error instanceof TransportStatusError && error.statusCode === 0x6faa\n ? new DeviceHalted(error.message)\n : error instanceof TransportStatusError && error.statusCode === 0x6b00\n ? new FirmwareOrAppUpdateRequired(error.message)\n : error,\n );\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nconst never = new Promise(() => {});\n\ntype Discovery = Observable<{\n type: \"add\" | \"remove\";\n id: string;\n name: string;\n}>;\n\nexport type TransportModule = {\n // unique transport name that identify the transport module\n id: string;\n // open a device by an id, this id must be unique across all modules\n // you can typically prefix it with `something|` that identify it globally\n // returns falsy if the transport module can't handle this id\n // here, open means we want to START doing something with the transport\n open: (id: string) => Promise<Transport> | null | undefined;\n // here, close means we want to STOP doing something with the transport\n close?: (transport: Transport, id: string) => Promise<void> | null | undefined;\n // disconnect/interrupt a device connection globally\n // returns falsy if the transport module can't handle this id\n disconnect: (id: string) => Promise<void> | null | undefined;\n // optional observable that allows to discover a transport\n discovery?: Discovery;\n};\n\nconst modules: TransportModule[] = [];\n\nexport const registerTransportModule = (module: TransportModule): void => {\n modules.push(module);\n};\n\nexport const close = (transport: Transport, deviceId: string): Promise<void> => {\n for (const m of modules) {\n const p = m.close?.(transport, deviceId);\n if (p) return p;\n }\n // fallback on an actual close\n return transport.close();\n};\n\nexport const open = (deviceId: string): Promise<Transport> => {\n for (const m of modules) {\n const p = m.open(deviceId);\n if (p) return p;\n }\n return Promise.reject(new Error(`Can't find handler to open ${deviceId}`));\n};\n\nconst transportFinally =\n (cleanup: () => Promise<void>) =>\n <T>(observable: Observable<T>): Observable<T> =>\n // @ts-expect-error typescript not checking against the instanceof\n Observable.create((o) => {\n let done = false;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const finalize = (): any => {\n if (done) return never;\n done = true;\n return cleanup();\n };\n\n const sub = observable.subscribe({\n next: (e) => o.next(e),\n complete: () => {\n void finalize().then(() => o.complete());\n },\n error: (e) => {\n void finalize().then(() => o.error(e));\n },\n });\n return () => {\n sub.unsubscribe();\n void finalize();\n };\n });\n\ntype AccessHook = () => () => void;\n\nconst accessHooks: AccessHook[] = [];\n\nconst deviceQueues = {};\n\nexport const withDevice =\n (deviceId: string) =>\n <T>(job: (t: Transport) => Observable<T>): Observable<T> =>\n new Observable((o) => {\n // @ts-expect-error typescript not checking against the instanceof\n let unsubscribed;\n // @ts-expect-error typescript not checking against the instanceof\n let sub;\n // @ts-expect-error typescript not checking against the instanceof\n const deviceQueue = deviceQueues[deviceId] ?? Promise.resolve();\n\n // @ts-expect-error typescript not checking against the instanceof\n const finalize = (transport, cleanups): Promise<void> =>\n close(transport, deviceId)\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n .catch(() => {})\n .then(() => {\n // @ts-expect-error typescript not checking against the instanceof\n cleanups.forEach((c) => c());\n });\n\n // when we'll finish all the current job, we'll call finish\n // @ts-expect-error typescript not checking against the instanceof\n let finish;\n // this new promise is the next exec queue\n // @ts-expect-error typescript not checking against the instanceof\n deviceQueues[deviceId] = new Promise((resolve) => {\n finish = resolve;\n });\n // for any new job, we'll now wait the exec queue to be available\n deviceQueue\n .then(() => open(deviceId)) // open the transport\n // @ts-expect-error typescript not checking against the instanceof\n .then(async (transport) => {\n // @ts-expect-error typescript not checking against the instanceof\n if (unsubscribed) {\n // it was unsubscribed prematurely\n // @ts-expect-error typescript not checking against the instanceof\n return finalize(transport, [finish]);\n }\n\n if (\n transport.requestConnectionPriority &&\n typeof transport.requestConnectionPriority === \"function\"\n ) {\n await transport.requestConnectionPriority(\"High\");\n }\n\n return transport;\n })\n // @ts-expect-error typescript not checking against the instanceof\n .catch((e) => {\n // @ts-expect-error typescript not checking against the instanceof\n finish();\n if (e instanceof BluetoothRequired) throw e;\n if (e instanceof TransportWebUSBGestureRequired) throw e;\n if (e instanceof TransportInterfaceNotAvailable) throw e;\n throw new CantOpenDevice(e.message);\n })\n // @ts-expect-error typescript not checking against the instanceof\n .then((transport) => {\n if (!transport) return;\n\n // @ts-expect-error typescript not checking against the instanceof\n if (unsubscribed) {\n // it was unsubscribed prematurely\n // @ts-expect-error typescript not checking against the instanceof\n return finalize(transport, [finish]);\n }\n\n const cleanups = accessHooks.map((hook) => hook());\n sub = job(transport) // $FlowFixMe\n .pipe(\n catchError(initialErrorRemapping),\n // $FlowFixMe\n transportFinally(() =>\n // @ts-expect-error typescript not checking against the instanceof\n finalize(transport, [...cleanups, finish]),\n ),\n )\n .subscribe(o);\n })\n // @ts-expect-error typescript not checking against the instanceof\n .catch((error) => o.error(error));\n return () => {\n unsubscribed = true;\n // @ts-expect-error typescript not checking against the instanceof\n if (sub) sub.unsubscribe();\n };\n });\n\nconst WITH_DEVICE_POLLING_DELAY = 500;\n\nexport const retryWhileErrors =\n (acceptError: (arg0: Error) => boolean) =>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (attempts: Observable<any>): Observable<any> =>\n attempts.pipe(\n mergeMap((error) => {\n if (!acceptError(error)) {\n return throwError(error);\n }\n\n return timer(WITH_DEVICE_POLLING_DELAY);\n }),\n );\n\nexport const withDevicePolling =\n (deviceId: string) =>\n <T>(\n job: (arg0: Transport) => Observable<T>,\n acceptError: (arg0: Error) => boolean = () => false,\n ): Observable<T> =>\n withDevice(deviceId)(job).pipe(retryWhen(retryWhileErrors(acceptError)));\n","import { TransportStatusError } from \"@ledgerhq/errors\";\n\nexport const isTransportStatusError = (error: unknown): error is TransportStatusError => {\n return (\n error instanceof TransportStatusError ||\n (error instanceof Error && \"statusCode\" in error && error.message.startsWith(\"Ledger device:\"))\n );\n};\n\nconst CANCEL_STATUS_CODES = [\n 0x6985, // cancel on Ledger Blue\n\n // STAX\n 0xb00c, // cancel collect wk fragment\n 0xb00d, // cancel user registration\n 0xb010, // cancel review\n 0xb012, // cancel master seed generation\n 0xb013, // cancel login\n];\n\nexport const isDeviceCancelError = (error: Error): boolean => {\n return isTransportStatusError(error) && CANCEL_STATUS_CODES.includes(error.statusCode);\n};\n"]}
|
|
@@ -37,15 +37,19 @@ function createApiDevice(options, logger) {
|
|
|
37
37
|
axiosRetry(deviceApi, {
|
|
38
38
|
retryDelay: axiosRetry.linearDelay(1e3),
|
|
39
39
|
retries: 3,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
retryCondition: (
|
|
41
|
+
/* v8 ignore next -- @preserve */
|
|
42
|
+
() => true
|
|
43
|
+
),
|
|
44
|
+
onRetry: (
|
|
45
|
+
/* v8 ignore next -- @preserve */
|
|
46
|
+
(retryCount, err) => {
|
|
47
|
+
const formattedErr = `${err.code ?? `UNKNOWN`} on ${err.config?.method?.toUpperCase() ?? "UNKNOWN_METHOD"} ${err.config?.url ?? "UNKNOWN_URL"}`;
|
|
48
|
+
logger.warning(
|
|
49
|
+
`Retrying request to device-api (attempt ${retryCount}) - Cause: ${formattedErr}`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
)
|
|
49
53
|
});
|
|
50
54
|
deviceApi.interceptors.request.use(
|
|
51
55
|
(config) => {
|
|
@@ -68,12 +72,15 @@ function createApiDevice(options, logger) {
|
|
|
68
72
|
}
|
|
69
73
|
return config;
|
|
70
74
|
},
|
|
71
|
-
/* v8 ignore stop */
|
|
72
75
|
(error) => Promise.reject(error)
|
|
73
76
|
);
|
|
74
77
|
return {
|
|
75
78
|
with: (index) => {
|
|
76
|
-
const
|
|
79
|
+
const __seed = genSeed({ salt: options.salt, index });
|
|
80
|
+
const getSeed = async () => {
|
|
81
|
+
if (typeof __seed === "string") return Promise.resolve(__seed);
|
|
82
|
+
return __seed;
|
|
83
|
+
};
|
|
77
84
|
const authenticate = async ({
|
|
78
85
|
challenge,
|
|
79
86
|
workspaceName
|
|
@@ -82,7 +89,7 @@ function createApiDevice(options, logger) {
|
|
|
82
89
|
if (role === "READ_ONLY_API_KEY")
|
|
83
90
|
throw new Error("Invalid role for authenticate: READ_ONLY_API_KEY");
|
|
84
91
|
const { data } = await deviceApi.post("/authenticate", {
|
|
85
|
-
seed,
|
|
92
|
+
seed: await getSeed(),
|
|
86
93
|
challenge: Buffer.from(challenge.challenge, "base64").toString("hex"),
|
|
87
94
|
application: APPID_VAULT_ADMINISTRATOR,
|
|
88
95
|
key_handle: challenge.keyHandle,
|
|
@@ -96,13 +103,13 @@ function createApiDevice(options, logger) {
|
|
|
96
103
|
};
|
|
97
104
|
const finalizePairingHandshake = async (params) => {
|
|
98
105
|
const { handshake, partitionId } = params;
|
|
99
|
-
const payload = { seed, handshake, ciphertext: partitionId };
|
|
106
|
+
const payload = { seed: await getSeed(), handshake, ciphertext: partitionId };
|
|
100
107
|
const res = await deviceApi.post("/finalize-pairing-handshake", payload);
|
|
101
108
|
return res.data;
|
|
102
109
|
};
|
|
103
110
|
const generateSeedFragment = async () => {
|
|
104
111
|
const payload = {
|
|
105
|
-
seed,
|
|
112
|
+
seed: await getSeed(),
|
|
106
113
|
path: PATHS.KEY_MATERIAL,
|
|
107
114
|
goal: 0
|
|
108
115
|
// seed fragment
|
|
@@ -112,12 +119,14 @@ function createApiDevice(options, logger) {
|
|
|
112
119
|
};
|
|
113
120
|
const generateWrappingKeyFragment = async () => {
|
|
114
121
|
const goal = 1;
|
|
115
|
-
const payload = { seed, goal, path: PATHS.KEY_MATERIAL };
|
|
122
|
+
const payload = { seed: await getSeed(), goal, path: PATHS.KEY_MATERIAL };
|
|
116
123
|
const res = await deviceApi.post("/generate-key-fragments", payload);
|
|
117
124
|
return Buffer.from(res.data, "hex").toString("base64");
|
|
118
125
|
};
|
|
119
126
|
const getAttestation = async () => {
|
|
120
|
-
const { data: attestationStr } = await deviceApi.post("/get-attestation", {
|
|
127
|
+
const { data: attestationStr } = await deviceApi.post("/get-attestation", {
|
|
128
|
+
seed: await getSeed()
|
|
129
|
+
});
|
|
121
130
|
const attestationBuffer = Buffer.from(attestationStr, "hex");
|
|
122
131
|
const certLen = attestationBuffer.readInt8(32 + 65 + 1);
|
|
123
132
|
return {
|
|
@@ -130,7 +139,7 @@ function createApiDevice(options, logger) {
|
|
|
130
139
|
};
|
|
131
140
|
};
|
|
132
141
|
const getConfidentialityKey = async () => {
|
|
133
|
-
const res = await deviceApi.post("/get-confidentiality-key", { seed });
|
|
142
|
+
const res = await deviceApi.post("/get-confidentiality-key", { seed: await getSeed() });
|
|
134
143
|
return {
|
|
135
144
|
confidentialityKeyCurve25519: res.data.confidentiality_key_curve25519,
|
|
136
145
|
confidentialityKeySignature: res.data.confidentiality_key_signature
|
|
@@ -140,7 +149,9 @@ function createApiDevice(options, logger) {
|
|
|
140
149
|
return getPublicKey({ path: PATHS.CONFIDENTIALITY });
|
|
141
150
|
};
|
|
142
151
|
const getDeviceUserId = async () => {
|
|
143
|
-
const res = await deviceApi.post("/blue-device-id", {
|
|
152
|
+
const res = await deviceApi.post("/blue-device-id", {
|
|
153
|
+
seed: await getSeed()
|
|
154
|
+
});
|
|
144
155
|
return res.data.blue_device_id.toUpperCase();
|
|
145
156
|
};
|
|
146
157
|
const getU2FPubKey = async () => {
|
|
@@ -150,13 +161,13 @@ function createApiDevice(options, logger) {
|
|
|
150
161
|
return getPublicKey({ path: PATHS.VALIDATION });
|
|
151
162
|
};
|
|
152
163
|
const hasPairing = async () => {
|
|
153
|
-
const res = await deviceApi.post("/get-partition-ids", { seed });
|
|
164
|
+
const res = await deviceApi.post("/get-partition-ids", { seed: await getSeed() });
|
|
154
165
|
return res.data.length > 0;
|
|
155
166
|
};
|
|
156
167
|
const initPairingHandshake = async () => {
|
|
157
168
|
const { data } = await deviceApi.post(
|
|
158
169
|
"/initiate-pairing-handshake",
|
|
159
|
-
{ seed }
|
|
170
|
+
{ seed: await getSeed() }
|
|
160
171
|
);
|
|
161
172
|
return {
|
|
162
173
|
pubKey: data.pubKey,
|
|
@@ -176,7 +187,7 @@ function createApiDevice(options, logger) {
|
|
|
176
187
|
attestationCertificate
|
|
177
188
|
]);
|
|
178
189
|
const payload = {
|
|
179
|
-
seed,
|
|
190
|
+
seed: await getSeed(),
|
|
180
191
|
path: PATHS.CONFIDENTIALITY,
|
|
181
192
|
pubKey: secureChannel.pubKey,
|
|
182
193
|
attestation: attestation.toString("hex"),
|
|
@@ -190,7 +201,7 @@ function createApiDevice(options, logger) {
|
|
|
190
201
|
const register = async (params) => {
|
|
191
202
|
const { challenge, u2fRegisterData, name, role } = params;
|
|
192
203
|
const payload = {
|
|
193
|
-
seed,
|
|
204
|
+
seed: await getSeed(),
|
|
194
205
|
challenge,
|
|
195
206
|
name,
|
|
196
207
|
role: STR_ROLES[role],
|
|
@@ -202,10 +213,14 @@ function createApiDevice(options, logger) {
|
|
|
202
213
|
const { data } = await deviceApi.post("/register", payload);
|
|
203
214
|
const response = Buffer.from(data, "hex");
|
|
204
215
|
let i = 0;
|
|
205
|
-
const rfu = response.slice(i, i
|
|
206
|
-
|
|
207
|
-
const
|
|
208
|
-
|
|
216
|
+
const rfu = response.slice(i, i + 1)[0];
|
|
217
|
+
i += 1;
|
|
218
|
+
const pubKey = response.slice(i, i + 65).toString("hex");
|
|
219
|
+
i += 65;
|
|
220
|
+
const keyHandleLength = response.slice(i, i + 1)[0];
|
|
221
|
+
i++;
|
|
222
|
+
const keyHandle = response.slice(i, i + keyHandleLength);
|
|
223
|
+
i += keyHandleLength;
|
|
209
224
|
return {
|
|
210
225
|
u2fRegister: response.slice(0, response.length - 2),
|
|
211
226
|
keyHandle,
|
|
@@ -215,13 +230,13 @@ function createApiDevice(options, logger) {
|
|
|
215
230
|
};
|
|
216
231
|
const registerData = async (params) => {
|
|
217
232
|
const { challenge } = params;
|
|
218
|
-
const payload = { seed, challenge };
|
|
233
|
+
const payload = { seed: await getSeed(), challenge };
|
|
219
234
|
const res = await deviceApi.post("/u2f-register-data", payload);
|
|
220
235
|
return res.data;
|
|
221
236
|
};
|
|
222
237
|
const setPairing = async ({ pairing }) => {
|
|
223
238
|
const payload = {
|
|
224
|
-
seed,
|
|
239
|
+
seed: await getSeed(),
|
|
225
240
|
blob: pairing.blob,
|
|
226
241
|
pairing: {
|
|
227
242
|
bootstrap_enabled: pairing.pairing.bootstrapEnabled,
|
|
@@ -239,7 +254,7 @@ function createApiDevice(options, logger) {
|
|
|
239
254
|
};
|
|
240
255
|
const startKKPatternAsResponder = async (params) => {
|
|
241
256
|
const payload = {
|
|
242
|
-
seed,
|
|
257
|
+
seed: await getSeed(),
|
|
243
258
|
script_id: SCRIPT_IDS.ACCOUNT_MANAGER_SESSION,
|
|
244
259
|
handshake: params.handshake,
|
|
245
260
|
// for device-api it's normal to have empty string as handshake_attestation
|
|
@@ -257,7 +272,7 @@ function createApiDevice(options, logger) {
|
|
|
257
272
|
const startKPatternAsResponder = async (params) => {
|
|
258
273
|
const { handshake, partitionId } = params;
|
|
259
274
|
const payload = {
|
|
260
|
-
seed,
|
|
275
|
+
seed: await getSeed(),
|
|
261
276
|
script_id: SCRIPT_IDS.ACCOUNT_MANAGER_SESSION,
|
|
262
277
|
handshake,
|
|
263
278
|
// for device-api it's normal to have empty string as handshake_attestation
|
|
@@ -274,7 +289,7 @@ function createApiDevice(options, logger) {
|
|
|
274
289
|
};
|
|
275
290
|
const getPublicKey = async (params) => {
|
|
276
291
|
const { path } = params;
|
|
277
|
-
const payload = { seed, secp256k1: true, path };
|
|
292
|
+
const payload = { seed: await getSeed(), secp256k1: true, path };
|
|
278
293
|
const res = await deviceApi.post("/get-public-key", payload);
|
|
279
294
|
return {
|
|
280
295
|
pubKey: res.data.pubKey,
|
|
@@ -284,7 +299,7 @@ function createApiDevice(options, logger) {
|
|
|
284
299
|
const validateVaultOperation = async (params) => {
|
|
285
300
|
const { actions } = params;
|
|
286
301
|
const payload = {
|
|
287
|
-
seed,
|
|
302
|
+
seed: await getSeed(),
|
|
288
303
|
path: PATHS.VALIDATION,
|
|
289
304
|
actions
|
|
290
305
|
};
|
|
@@ -335,30 +350,6 @@ function createApiDevice(options, logger) {
|
|
|
335
350
|
};
|
|
336
351
|
}
|
|
337
352
|
|
|
338
|
-
// src/device/utils.ts
|
|
339
|
-
import { TransportStatusError } from "@ledgerhq/errors";
|
|
340
|
-
var isTransportStatusError = (error) => {
|
|
341
|
-
return error instanceof TransportStatusError || error instanceof Error && "statusCode" in error && error.message.startsWith("Ledger device:");
|
|
342
|
-
};
|
|
343
|
-
var CANCEL_STATUS_CODES = [
|
|
344
|
-
27013,
|
|
345
|
-
// cancel on Ledger Blue
|
|
346
|
-
// STAX
|
|
347
|
-
45068,
|
|
348
|
-
// cancel collect wk fragment
|
|
349
|
-
45069,
|
|
350
|
-
// cancel user registration
|
|
351
|
-
45072,
|
|
352
|
-
// cancel review
|
|
353
|
-
45074,
|
|
354
|
-
// cancel master seed generation
|
|
355
|
-
45075
|
|
356
|
-
// cancel login
|
|
357
|
-
];
|
|
358
|
-
var isDeviceCancelError = (error) => {
|
|
359
|
-
return isTransportStatusError(error) && CANCEL_STATUS_CODES.includes(error.statusCode);
|
|
360
|
-
};
|
|
361
|
-
|
|
362
353
|
// src/device/device-access.ts
|
|
363
354
|
import {
|
|
364
355
|
BluetoothRequired,
|
|
@@ -366,13 +357,13 @@ import {
|
|
|
366
357
|
DeviceHalted,
|
|
367
358
|
FirmwareOrAppUpdateRequired,
|
|
368
359
|
TransportInterfaceNotAvailable,
|
|
369
|
-
TransportStatusError
|
|
360
|
+
TransportStatusError,
|
|
370
361
|
TransportWebUSBGestureRequired
|
|
371
362
|
} from "@ledgerhq/errors";
|
|
372
363
|
import { Observable, throwError, timer } from "rxjs";
|
|
373
364
|
import { catchError, mergeMap, retryWhen } from "rxjs/operators";
|
|
374
365
|
var initialErrorRemapping = (error) => throwError(
|
|
375
|
-
error && error instanceof
|
|
366
|
+
error && error instanceof TransportStatusError && error.statusCode === 28586 ? new DeviceHalted(error.message) : error instanceof TransportStatusError && error.statusCode === 27392 ? new FirmwareOrAppUpdateRequired(error.message) : error
|
|
376
367
|
);
|
|
377
368
|
var never = new Promise(() => {
|
|
378
369
|
});
|
|
@@ -482,6 +473,30 @@ var retryWhileErrors = (acceptError) => (
|
|
|
482
473
|
);
|
|
483
474
|
var withDevicePolling = (deviceId) => (job, acceptError = () => false) => withDevice(deviceId)(job).pipe(retryWhen(retryWhileErrors(acceptError)));
|
|
484
475
|
|
|
476
|
+
// src/device/utils.ts
|
|
477
|
+
import { TransportStatusError as TransportStatusError2 } from "@ledgerhq/errors";
|
|
478
|
+
var isTransportStatusError = (error) => {
|
|
479
|
+
return error instanceof TransportStatusError2 || error instanceof Error && "statusCode" in error && error.message.startsWith("Ledger device:");
|
|
480
|
+
};
|
|
481
|
+
var CANCEL_STATUS_CODES = [
|
|
482
|
+
27013,
|
|
483
|
+
// cancel on Ledger Blue
|
|
484
|
+
// STAX
|
|
485
|
+
45068,
|
|
486
|
+
// cancel collect wk fragment
|
|
487
|
+
45069,
|
|
488
|
+
// cancel user registration
|
|
489
|
+
45072,
|
|
490
|
+
// cancel review
|
|
491
|
+
45074,
|
|
492
|
+
// cancel master seed generation
|
|
493
|
+
45075
|
|
494
|
+
// cancel login
|
|
495
|
+
];
|
|
496
|
+
var isDeviceCancelError = (error) => {
|
|
497
|
+
return isTransportStatusError(error) && CANCEL_STATUS_CODES.includes(error.statusCode);
|
|
498
|
+
};
|
|
499
|
+
|
|
485
500
|
export {
|
|
486
501
|
PATHS,
|
|
487
502
|
STATUS_LENGTH,
|
|
@@ -492,9 +507,10 @@ export {
|
|
|
492
507
|
STREAMING_RESPONSE,
|
|
493
508
|
STREAMING_NEXT_ACTION,
|
|
494
509
|
createApiDevice,
|
|
495
|
-
isTransportStatusError,
|
|
496
|
-
isDeviceCancelError,
|
|
497
510
|
registerTransportModule,
|
|
498
|
-
withDevicePolling
|
|
511
|
+
withDevicePolling,
|
|
512
|
+
isTransportStatusError,
|
|
513
|
+
isDeviceCancelError
|
|
499
514
|
};
|
|
500
|
-
|
|
515
|
+
/* v8 ignore next -- @preserve */
|
|
516
|
+
//# sourceMappingURL=chunk-42CFPNWC.js.map
|