@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.
Files changed (42) hide show
  1. package/lib/bake.cjs +12 -3
  2. package/lib/bake.cjs.map +1 -1
  3. package/lib/bake.d.cts +8 -1
  4. package/lib/bake.d.ts +8 -1
  5. package/lib/bake.js +11 -2
  6. package/lib/bake.js.map +1 -1
  7. package/lib/{chunk-B5EUR3HT.cjs → chunk-2HKHCIKX.cjs} +75 -59
  8. package/lib/chunk-2HKHCIKX.cjs.map +1 -0
  9. package/lib/{chunk-7WN7G7BY.js → chunk-42CFPNWC.js} +78 -62
  10. package/lib/chunk-42CFPNWC.js.map +1 -0
  11. package/lib/{chunk-QVDZOA4O.js → chunk-73OX5XDM.js} +21 -12
  12. package/lib/chunk-73OX5XDM.js.map +1 -0
  13. package/lib/{chunk-CKNBRCHA.cjs → chunk-P53CFOI6.cjs} +22 -13
  14. package/lib/chunk-P53CFOI6.cjs.map +1 -0
  15. package/lib/crypto.cjs +4 -2
  16. package/lib/crypto.cjs.map +1 -1
  17. package/lib/crypto.d.cts +2 -1
  18. package/lib/crypto.d.ts +2 -1
  19. package/lib/crypto.js +5 -3
  20. package/lib/device.cjs +2 -2
  21. package/lib/device.d.cts +5 -5
  22. package/lib/device.d.ts +5 -5
  23. package/lib/device.js +1 -1
  24. package/lib/engine.cjs +46 -35
  25. package/lib/engine.cjs.map +1 -1
  26. package/lib/engine.d.cts +2 -2
  27. package/lib/engine.d.ts +2 -2
  28. package/lib/engine.js +28 -17
  29. package/lib/engine.js.map +1 -1
  30. package/lib/onboarding.cjs +20 -7
  31. package/lib/onboarding.cjs.map +1 -1
  32. package/lib/onboarding.d.cts +1 -1
  33. package/lib/onboarding.d.ts +1 -1
  34. package/lib/onboarding.js +19 -6
  35. package/lib/onboarding.js.map +1 -1
  36. package/lib/{types-Cp-L-rsW.d.ts → types-Dkr4g0qP.d.ts} +1 -1
  37. package/lib/{types-DEyShR5S.d.cts → types-pUN38HdE.d.cts} +1 -1
  38. package/package.json +12 -11
  39. package/lib/chunk-7WN7G7BY.js.map +0 -1
  40. package/lib/chunk-B5EUR3HT.cjs.map +0 -1
  41. package/lib/chunk-CKNBRCHA.cjs.map +0 -1
  42. 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
- /* v8 ignore start */
41
- retryCondition: () => true,
42
- onRetry: (retryCount, err) => {
43
- 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"))}`;
44
- logger.warning(
45
- `Retrying request to device-api (attempt ${retryCount}) - Cause: ${formattedErr}`
46
- );
47
- }
48
- /* v8 ignore stop */
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 seed = genSeed({ salt: options.salt, index });
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", { seed });
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", { seed });
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 += 1)[0];
206
- const pubKey = response.slice(i, i += 65).toString("hex");
207
- const keyHandleLength = response.slice(i, ++i)[0];
208
- const keyHandle = response.slice(i, i += keyHandleLength);
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.isTransportStatusError = isTransportStatusError; exports.isDeviceCancelError = isDeviceCancelError; exports.registerTransportModule = registerTransportModule; exports.withDevicePolling = withDevicePolling;
500
- //# sourceMappingURL=chunk-B5EUR3HT.cjs.map
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":"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","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
- /* v8 ignore start */
41
- retryCondition: () => true,
42
- onRetry: (retryCount, err) => {
43
- const formattedErr = `${err.code ?? `UNKNOWN`} on ${err.config?.method?.toUpperCase() ?? "UNKNOWN_METHOD"} ${err.config?.url ?? "UNKNOWN_URL"}`;
44
- logger.warning(
45
- `Retrying request to device-api (attempt ${retryCount}) - Cause: ${formattedErr}`
46
- );
47
- }
48
- /* v8 ignore stop */
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 seed = genSeed({ salt: options.salt, index });
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", { seed });
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", { seed });
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 += 1)[0];
206
- const pubKey = response.slice(i, i += 65).toString("hex");
207
- const keyHandleLength = response.slice(i, ++i)[0];
208
- const keyHandle = response.slice(i, i += keyHandleLength);
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 as TransportStatusError2,
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 TransportStatusError2 && error.statusCode === 28586 ? new DeviceHalted(error.message) : error instanceof TransportStatusError2 && error.statusCode === 27392 ? new FirmwareOrAppUpdateRequired(error.message) : error
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
- //# sourceMappingURL=chunk-7WN7G7BY.js.map
515
+ /* v8 ignore next -- @preserve */
516
+ //# sourceMappingURL=chunk-42CFPNWC.js.map