@onekeyfe/hwk-adapter-core 1.2.2-alpha.8 → 1.2.3-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-3M3GMF64.mjs +68 -0
- package/dist/chunk-3M3GMF64.mjs.map +1 -0
- package/dist/{chunk-67BP77GT.mjs → chunk-72KOSYTH.mjs} +145 -56
- package/dist/chunk-72KOSYTH.mjs.map +1 -0
- package/dist/chunk-7SFFS2NL.js +68 -0
- package/dist/chunk-7SFFS2NL.js.map +1 -0
- package/dist/{chunk-SK7ZF33J.js → chunk-IZEVYMJK.js} +145 -56
- package/dist/chunk-IZEVYMJK.js.map +1 -0
- package/dist/{chunk-U63HTLGJ.mjs → chunk-KCIK56B5.mjs} +31 -2
- package/dist/chunk-KCIK56B5.mjs.map +1 -0
- package/dist/{chunk-BAGEFFFY.js → chunk-RRCFH7X6.js} +32 -3
- package/dist/chunk-RRCFH7X6.js.map +1 -0
- package/dist/errors-ChA_YEZY.d.mts +296 -0
- package/dist/errors-ChA_YEZY.d.ts +296 -0
- package/dist/errors.d.mts +1 -205
- package/dist/errors.d.ts +1 -205
- package/dist/errors.js +8 -2
- package/dist/errors.js.map +1 -1
- package/dist/errors.mjs +9 -3
- package/dist/index.d.mts +530 -57
- package/dist/index.d.ts +530 -57
- package/dist/index.js +600 -58
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +591 -49
- package/dist/index.mjs.map +1 -1
- package/dist/{ui-events-Cb7haAeE.d.ts → ui-events-BXI9BBpx.d.mts} +19 -3
- package/dist/{ui-events-Cb7haAeE.d.mts → ui-events-BXI9BBpx.d.ts} +19 -3
- package/dist/ui-events.d.mts +1 -1
- package/dist/ui-events.d.ts +1 -1
- package/dist/ui-events.js +3 -2
- package/dist/ui-events.js.map +1 -1
- package/dist/ui-events.mjs +2 -1
- package/package.json +2 -2
- package/dist/chunk-67BP77GT.mjs.map +0 -1
- package/dist/chunk-BAGEFFFY.js.map +0 -1
- package/dist/chunk-SK7ZF33J.js.map +0 -1
- package/dist/chunk-U63HTLGJ.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
HardwareErrorCode,
|
|
3
|
-
ORPHAN_ELIGIBLE_ERROR_CODES,
|
|
4
|
-
createHwkError,
|
|
5
2
|
enrichErrorMessage
|
|
6
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3M3GMF64.mjs";
|
|
7
4
|
import {
|
|
8
5
|
UI_EVENT,
|
|
9
6
|
UI_REQUEST,
|
|
@@ -13,19 +10,40 @@ import {
|
|
|
13
10
|
UI_REQUEST_TIMEOUT_TAG,
|
|
14
11
|
UI_RESPONSE,
|
|
15
12
|
UiRequestRegistry
|
|
16
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-KCIK56B5.mjs";
|
|
14
|
+
import {
|
|
15
|
+
HardwareErrorCode,
|
|
16
|
+
ORPHAN_ELIGIBLE_ERROR_CODES,
|
|
17
|
+
createHwkError,
|
|
18
|
+
defaultOriginForCode,
|
|
19
|
+
defaultRecoveryForCode,
|
|
20
|
+
isHwkRecoveryHint,
|
|
21
|
+
operationMayHaveCompletedParams
|
|
22
|
+
} from "./chunk-72KOSYTH.mjs";
|
|
17
23
|
|
|
18
24
|
// src/types/response.ts
|
|
19
25
|
function success(payload) {
|
|
20
26
|
return { success: true, payload };
|
|
21
27
|
}
|
|
22
|
-
function failure(code, error, params) {
|
|
28
|
+
function failure(code, error, params, origin, recovery) {
|
|
23
29
|
return {
|
|
24
30
|
success: false,
|
|
25
|
-
payload: {
|
|
31
|
+
payload: {
|
|
32
|
+
error,
|
|
33
|
+
code,
|
|
34
|
+
...origin !== void 0 ? { origin } : {},
|
|
35
|
+
recovery: recovery ?? defaultRecoveryForCode(code),
|
|
36
|
+
...params ? { params } : {}
|
|
37
|
+
}
|
|
26
38
|
};
|
|
27
39
|
}
|
|
28
40
|
|
|
41
|
+
// src/types/device.ts
|
|
42
|
+
function resolveSearchTargetReusePolicy(device) {
|
|
43
|
+
if (device.capabilities?.persistentDeviceIdentity) return "reconnectable";
|
|
44
|
+
return "current-discovery";
|
|
45
|
+
}
|
|
46
|
+
|
|
29
47
|
// src/types/fingerprint.ts
|
|
30
48
|
import { sha256 } from "@noble/hashes/sha256";
|
|
31
49
|
import { bytesToHex, utf8ToBytes } from "@noble/hashes/utils";
|
|
@@ -35,11 +53,21 @@ var CHAIN_FINGERPRINT_PATHS = {
|
|
|
35
53
|
// Cointype 1 (testnet) is rejected by some Ledger BTC App configurations.
|
|
36
54
|
btc: "m/44'/0'/0'",
|
|
37
55
|
sol: "m/44'/501'/0'",
|
|
38
|
-
tron: "m/44'/195'/0'/0/0"
|
|
56
|
+
tron: "m/44'/195'/0'/0/0",
|
|
57
|
+
// Shielded UA (single Orchard receiver) derived from the transparent path.
|
|
58
|
+
zcash: "m/44'/133'/0'/0/0"
|
|
39
59
|
};
|
|
60
|
+
function parseBip32MasterFingerprint(value) {
|
|
61
|
+
if (typeof value !== "string") return void 0;
|
|
62
|
+
const normalized = value.trim().toLowerCase();
|
|
63
|
+
return /^[0-9a-f]{8}$/.test(normalized) ? normalized : void 0;
|
|
64
|
+
}
|
|
40
65
|
function deriveDeviceFingerprint(value) {
|
|
41
66
|
return bytesToHex(sha256(utf8ToBytes(value))).slice(0, 16);
|
|
42
67
|
}
|
|
68
|
+
function deriveWalletId(canonicalPublicMaterial) {
|
|
69
|
+
return bytesToHex(sha256(utf8ToBytes(`onekey-hwk-wallet-id:v1:${canonicalPublicMaterial}`)));
|
|
70
|
+
}
|
|
43
71
|
|
|
44
72
|
// src/events/device.ts
|
|
45
73
|
var DEVICE_EVENT = "DEVICE_EVENT";
|
|
@@ -48,6 +76,10 @@ var DEVICE = {
|
|
|
48
76
|
DISCONNECT: "device-disconnect",
|
|
49
77
|
CHANGED: "device-changed",
|
|
50
78
|
FEATURES: "features",
|
|
79
|
+
/** Trezor transport binding, emitted only after matching the expected firmware device_id. */
|
|
80
|
+
TREZOR_CONNECTION_VERIFIED: "device-trezor-connection-verified",
|
|
81
|
+
/** Ledger BLE address repair, emitted only after matching the stored chain fingerprint. */
|
|
82
|
+
LEDGER_CONNECTION_VERIFIED: "device-ledger-connection-verified",
|
|
51
83
|
/**
|
|
52
84
|
* Trezor-only. Emitted after a successful THP handshake that minted or
|
|
53
85
|
* refreshed pairing credentials. The host should persist `credentials`
|
|
@@ -66,7 +98,8 @@ var SDK = {
|
|
|
66
98
|
DEVICE_STUCK: "device-stuck",
|
|
67
99
|
DEVICE_UNRESPONSIVE: "device-unresponsive",
|
|
68
100
|
DEVICE_RECOVERED: "device-recovered",
|
|
69
|
-
DEVICE_INTERACTION: "device-interaction"
|
|
101
|
+
DEVICE_INTERACTION: "device-interaction",
|
|
102
|
+
INTERACTION_ENDED: "interaction-ended"
|
|
70
103
|
};
|
|
71
104
|
|
|
72
105
|
// src/utils/DeviceJobQueue.ts
|
|
@@ -175,6 +208,236 @@ var DeviceJobQueue = class {
|
|
|
175
208
|
}
|
|
176
209
|
};
|
|
177
210
|
|
|
211
|
+
// src/utils/hardwareRuntimeId.ts
|
|
212
|
+
import { bytesToHex as bytesToHex2, randomBytes } from "@noble/hashes/utils";
|
|
213
|
+
var HARDWARE_RUNTIME_ID_PREFIX = "hwk:runtime:v1";
|
|
214
|
+
var RANDOM_ID_BYTES = 16;
|
|
215
|
+
var RANDOM_ID_PATTERN = /^[0-9a-f]{32}$/;
|
|
216
|
+
var VENDORS = /* @__PURE__ */ new Set(["trezor", "ledger", "keystone"]);
|
|
217
|
+
var CONNECTION_TYPES = /* @__PURE__ */ new Set(["usb", "ble", "qr"]);
|
|
218
|
+
function createNonce() {
|
|
219
|
+
return bytesToHex2(randomBytes(RANDOM_ID_BYTES));
|
|
220
|
+
}
|
|
221
|
+
function createHardwareInteractionId(vendor) {
|
|
222
|
+
return `${HARDWARE_RUNTIME_ID_PREFIX}:interaction:${vendor}:${createNonce()}`;
|
|
223
|
+
}
|
|
224
|
+
function createHardwareSearchTargetId(params) {
|
|
225
|
+
return `${HARDWARE_RUNTIME_ID_PREFIX}:search-target:${params.vendor}:${params.connectionType}:${createNonce()}`;
|
|
226
|
+
}
|
|
227
|
+
function createHardwareConnectorSessionId(params) {
|
|
228
|
+
return `${HARDWARE_RUNTIME_ID_PREFIX}:connector-session:${params.vendor}:${params.connectionType}:${createNonce()}`;
|
|
229
|
+
}
|
|
230
|
+
function hasHardwareRuntimeIdPrefix(value) {
|
|
231
|
+
return typeof value === "string" && value.startsWith(`${HARDWARE_RUNTIME_ID_PREFIX}:`);
|
|
232
|
+
}
|
|
233
|
+
function parseHardwareRuntimeId(value) {
|
|
234
|
+
if (!hasHardwareRuntimeIdPrefix(value)) return void 0;
|
|
235
|
+
const parts = value.split(":");
|
|
236
|
+
const kind = parts[3];
|
|
237
|
+
const vendor = parts[4];
|
|
238
|
+
if (!VENDORS.has(vendor)) return void 0;
|
|
239
|
+
if (kind === "interaction" && parts.length === 6 && RANDOM_ID_PATTERN.test(parts[5])) {
|
|
240
|
+
return {
|
|
241
|
+
kind,
|
|
242
|
+
vendor,
|
|
243
|
+
nonce: parts[5]
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const connectionType = parts[5];
|
|
247
|
+
if ((kind === "search-target" || kind === "connector-session") && parts.length === 7 && CONNECTION_TYPES.has(connectionType) && RANDOM_ID_PATTERN.test(parts[6])) {
|
|
248
|
+
return {
|
|
249
|
+
kind,
|
|
250
|
+
vendor,
|
|
251
|
+
connectionType,
|
|
252
|
+
nonce: parts[6]
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
return void 0;
|
|
256
|
+
}
|
|
257
|
+
function isHardwareInteractionId(value) {
|
|
258
|
+
return parseHardwareRuntimeId(value)?.kind === "interaction";
|
|
259
|
+
}
|
|
260
|
+
function isHardwareSearchTargetId(value) {
|
|
261
|
+
return parseHardwareRuntimeId(value)?.kind === "search-target";
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/utils/InteractionRegistry.ts
|
|
265
|
+
var INTERACTION_DEFAULT_TTL_MS = 6e5;
|
|
266
|
+
var InteractionRegistry = class {
|
|
267
|
+
constructor(options) {
|
|
268
|
+
this._active = /* @__PURE__ */ new Map();
|
|
269
|
+
this._ended = /* @__PURE__ */ new Map();
|
|
270
|
+
this._vendor = options.vendor;
|
|
271
|
+
this._ttlMs = options.ttlMs ?? INTERACTION_DEFAULT_TTL_MS;
|
|
272
|
+
this._onEnded = options.onEnded;
|
|
273
|
+
}
|
|
274
|
+
create(params) {
|
|
275
|
+
const now = Date.now();
|
|
276
|
+
const interactionId = createHardwareInteractionId(this._vendor);
|
|
277
|
+
const interaction = {
|
|
278
|
+
interactionId,
|
|
279
|
+
searchTargetId: params.searchTargetId,
|
|
280
|
+
connectId: params.connectId,
|
|
281
|
+
device: params.device,
|
|
282
|
+
connectionKeys: Array.from(
|
|
283
|
+
new Set(
|
|
284
|
+
[params.searchTargetId, params.connectId, ...params.connectionKeys ?? []].filter(
|
|
285
|
+
Boolean
|
|
286
|
+
)
|
|
287
|
+
)
|
|
288
|
+
),
|
|
289
|
+
createdAt: now,
|
|
290
|
+
lastActiveAt: now
|
|
291
|
+
};
|
|
292
|
+
const timer = this._createTimer(interactionId);
|
|
293
|
+
this._active.set(interactionId, { ...interaction, timer, retainCount: 0 });
|
|
294
|
+
return interaction;
|
|
295
|
+
}
|
|
296
|
+
resolve(interactionId) {
|
|
297
|
+
const active = this._active.get(interactionId);
|
|
298
|
+
if (!active) {
|
|
299
|
+
const ended = this._ended.get(interactionId);
|
|
300
|
+
if (ended) {
|
|
301
|
+
throw createHwkError({
|
|
302
|
+
code: 10113 /* InteractionEnded */,
|
|
303
|
+
message: `Hardware interaction has ended (${ended.reason})`,
|
|
304
|
+
params: { interactionId, reason: ended.reason }
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
throw createHwkError({
|
|
308
|
+
code: 10112 /* InteractionNotFound */,
|
|
309
|
+
message: "Hardware interaction was not found",
|
|
310
|
+
params: { interactionId }
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
if (active.timer) clearTimeout(active.timer);
|
|
314
|
+
active.lastActiveAt = Date.now();
|
|
315
|
+
active.timer = active.retainCount === 0 ? this._createTimer(interactionId) : void 0;
|
|
316
|
+
return active;
|
|
317
|
+
}
|
|
318
|
+
/** Keep an interaction alive while one device job is actively using it. */
|
|
319
|
+
retain(interactionId) {
|
|
320
|
+
const active = this.resolve(interactionId);
|
|
321
|
+
if (active.timer) clearTimeout(active.timer);
|
|
322
|
+
active.timer = void 0;
|
|
323
|
+
active.retainCount += 1;
|
|
324
|
+
let released = false;
|
|
325
|
+
return () => {
|
|
326
|
+
if (released) return;
|
|
327
|
+
released = true;
|
|
328
|
+
const current = this._active.get(interactionId);
|
|
329
|
+
if (!current) return;
|
|
330
|
+
current.retainCount = Math.max(0, current.retainCount - 1);
|
|
331
|
+
current.lastActiveAt = Date.now();
|
|
332
|
+
if (current.retainCount === 0) {
|
|
333
|
+
current.timer = this._createTimer(interactionId);
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
/** Return active or tombstoned binding data without refreshing its TTL. */
|
|
338
|
+
find(interactionId) {
|
|
339
|
+
return this._active.get(interactionId) ?? this._ended.get(interactionId)?.interaction;
|
|
340
|
+
}
|
|
341
|
+
findActiveByConnectionKey(connectionKey) {
|
|
342
|
+
if (!connectionKey) return void 0;
|
|
343
|
+
return [...this._active.values()].find(
|
|
344
|
+
(interaction) => interaction.connectionKeys.includes(connectionKey)
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
/** Replace the live transport binding after the same target was reconnected. */
|
|
348
|
+
rebind(interactionId, params) {
|
|
349
|
+
const active = this._active.get(interactionId);
|
|
350
|
+
if (!active) {
|
|
351
|
+
this.resolve(interactionId);
|
|
352
|
+
throw new Error("Unreachable interaction rebind");
|
|
353
|
+
}
|
|
354
|
+
if (active.timer) clearTimeout(active.timer);
|
|
355
|
+
active.connectId = params.connectId;
|
|
356
|
+
active.device = params.device;
|
|
357
|
+
active.connectionKeys = Array.from(
|
|
358
|
+
new Set([params.connectId, ...params.connectionKeys ?? []].filter(Boolean))
|
|
359
|
+
);
|
|
360
|
+
active.lastActiveAt = Date.now();
|
|
361
|
+
active.timer = active.retainCount === 0 ? this._createTimer(interactionId) : void 0;
|
|
362
|
+
return active;
|
|
363
|
+
}
|
|
364
|
+
end(interactionId, reason) {
|
|
365
|
+
const active = this._active.get(interactionId);
|
|
366
|
+
if (!active) return void 0;
|
|
367
|
+
if (active.timer) clearTimeout(active.timer);
|
|
368
|
+
this._active.delete(interactionId);
|
|
369
|
+
this._rememberEnded(active, reason);
|
|
370
|
+
this._onEnded?.(active, reason);
|
|
371
|
+
return active;
|
|
372
|
+
}
|
|
373
|
+
endByConnectionKey(connectionKey, reason, exceptInteractionId) {
|
|
374
|
+
if (!connectionKey) return;
|
|
375
|
+
for (const interaction of [...this._active.values()]) {
|
|
376
|
+
if (interaction.interactionId === exceptInteractionId) continue;
|
|
377
|
+
if (interaction.connectionKeys.includes(connectionKey)) {
|
|
378
|
+
this.end(interaction.interactionId, reason);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
endAll(reason, exceptInteractionId) {
|
|
383
|
+
for (const interactionId of [...this._active.keys()]) {
|
|
384
|
+
if (interactionId === exceptInteractionId) continue;
|
|
385
|
+
this.end(interactionId, reason);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
_createTimer(interactionId) {
|
|
389
|
+
const timer = setTimeout(() => {
|
|
390
|
+
this.end(interactionId, "timeout");
|
|
391
|
+
}, this._ttlMs);
|
|
392
|
+
timer.unref?.();
|
|
393
|
+
return timer;
|
|
394
|
+
}
|
|
395
|
+
_rememberEnded(interaction, reason) {
|
|
396
|
+
this._ended.set(interaction.interactionId, { reason, interaction });
|
|
397
|
+
if (this._ended.size <= 100) return;
|
|
398
|
+
const oldest = this._ended.keys().next().value;
|
|
399
|
+
if (oldest) this._ended.delete(oldest);
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
// src/utils/hardwareOperationTarget.ts
|
|
404
|
+
function resolveHardwareOperationTarget(positionalTargetId, commonInteractionId, expectedVendor) {
|
|
405
|
+
const normalizedPositionalTargetId = positionalTargetId ?? void 0;
|
|
406
|
+
const normalizedCommonInteractionId = commonInteractionId || void 0;
|
|
407
|
+
const positionalInteractionId = isHardwareInteractionId(normalizedPositionalTargetId) ? normalizedPositionalTargetId : void 0;
|
|
408
|
+
const parsedPositionalTarget = parseHardwareRuntimeId(normalizedPositionalTargetId);
|
|
409
|
+
const parsedCommonInteraction = parseHardwareRuntimeId(normalizedCommonInteractionId);
|
|
410
|
+
if (normalizedPositionalTargetId && hasHardwareRuntimeIdPrefix(normalizedPositionalTargetId) && !parsedPositionalTarget) {
|
|
411
|
+
return failure(10002 /* InvalidParams */, "Invalid hardware operation target id");
|
|
412
|
+
}
|
|
413
|
+
if (parsedPositionalTarget?.kind === "connector-session") {
|
|
414
|
+
return failure(
|
|
415
|
+
10002 /* InvalidParams */,
|
|
416
|
+
"Hardware connector session id cannot be used as an operation target"
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
if (normalizedCommonInteractionId && parsedCommonInteraction?.kind !== "interaction") {
|
|
420
|
+
return failure(10002 /* InvalidParams */, "Invalid hardware interaction id");
|
|
421
|
+
}
|
|
422
|
+
if (expectedVendor && (parsedPositionalTarget && parsedPositionalTarget.vendor !== expectedVendor || parsedCommonInteraction && parsedCommonInteraction.vendor !== expectedVendor)) {
|
|
423
|
+
return failure(
|
|
424
|
+
10002 /* InvalidParams */,
|
|
425
|
+
`Hardware interaction does not belong to ${expectedVendor}`
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
if (positionalInteractionId && normalizedCommonInteractionId && positionalInteractionId !== normalizedCommonInteractionId) {
|
|
429
|
+
return failure(10002 /* InvalidParams */, "Conflicting hardware interaction ids", {
|
|
430
|
+
positionalInteractionId,
|
|
431
|
+
commonInteractionId: normalizedCommonInteractionId
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
const interactionId = normalizedCommonInteractionId ?? positionalInteractionId;
|
|
435
|
+
return success({
|
|
436
|
+
interactionId,
|
|
437
|
+
targetId: interactionId ?? normalizedPositionalTargetId
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
|
|
178
441
|
// src/types/connector.ts
|
|
179
442
|
var EConnectorInteraction = /* @__PURE__ */ ((EConnectorInteraction2) => {
|
|
180
443
|
EConnectorInteraction2["Searching"] = "searching";
|
|
@@ -190,7 +453,7 @@ function createBridgedConnector(vendor, connectionType, bridge) {
|
|
|
190
453
|
return {
|
|
191
454
|
connectionType,
|
|
192
455
|
searchDevices: (options) => bridge.searchDevices({ vendor, options }),
|
|
193
|
-
connect: (deviceId) => bridge.connect({ vendor, deviceId }),
|
|
456
|
+
connect: (deviceId, options) => bridge.connect({ vendor, deviceId, ...options ? { options } : {} }),
|
|
194
457
|
disconnect: (sessionId) => bridge.disconnect({ vendor, sessionId }),
|
|
195
458
|
call: (sessionId, method, callParams) => bridge.call({ vendor, sessionId, method, callParams }),
|
|
196
459
|
cancel: (sessionId) => bridge.cancel({ vendor, sessionId }),
|
|
@@ -331,10 +594,14 @@ function createCombinedConnector(connectors) {
|
|
|
331
594
|
});
|
|
332
595
|
}
|
|
333
596
|
const searchDevices = async (options = {}) => {
|
|
597
|
+
const selectedConnectors = connectors.map((child, index) => ({ child, index })).filter(
|
|
598
|
+
({ child }) => !options.transportType || child.connectionType === options.transportType
|
|
599
|
+
);
|
|
600
|
+
if (!selectedConnectors.length) return [];
|
|
334
601
|
const perConnector = [];
|
|
335
|
-
await new Promise((resolve) => {
|
|
602
|
+
await new Promise((resolve, reject) => {
|
|
336
603
|
let finished = false;
|
|
337
|
-
let remaining =
|
|
604
|
+
let remaining = selectedConnectors.length;
|
|
338
605
|
let settleTimer;
|
|
339
606
|
const finish = () => {
|
|
340
607
|
if (finished) return;
|
|
@@ -342,19 +609,20 @@ function createCombinedConnector(connectors) {
|
|
|
342
609
|
if (settleTimer) clearTimeout(settleTimer);
|
|
343
610
|
resolve();
|
|
344
611
|
};
|
|
345
|
-
|
|
346
|
-
void child.searchDevices().then(
|
|
612
|
+
selectedConnectors.forEach(({ child, index }) => {
|
|
613
|
+
void child.searchDevices(options.purpose ? { purpose: options.purpose } : void 0).then(
|
|
347
614
|
(devices) => devices.map((device) => ({
|
|
348
615
|
...device,
|
|
349
616
|
connectionType: device.connectionType ?? child.connectionType
|
|
350
617
|
}))
|
|
351
|
-
).catch(
|
|
352
|
-
()
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
618
|
+
).catch((error) => {
|
|
619
|
+
if (options.transportType) {
|
|
620
|
+
finished = true;
|
|
621
|
+
if (settleTimer) clearTimeout(settleTimer);
|
|
622
|
+
reject(error);
|
|
623
|
+
}
|
|
624
|
+
return [];
|
|
625
|
+
}).then((devices) => {
|
|
358
626
|
remaining -= 1;
|
|
359
627
|
if (!finished) {
|
|
360
628
|
perConnector.push({ index, devices });
|
|
@@ -371,7 +639,12 @@ function createCombinedConnector(connectors) {
|
|
|
371
639
|
});
|
|
372
640
|
});
|
|
373
641
|
perConnector.sort((a, b) => a.index - b.index);
|
|
374
|
-
deviceOwner.clear();
|
|
642
|
+
if (!options.transportType) deviceOwner.clear();
|
|
643
|
+
else {
|
|
644
|
+
for (const [id, owner] of deviceOwner) {
|
|
645
|
+
if (owner.connectionType === options.transportType) deviceOwner.delete(id);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
375
648
|
const merged = [];
|
|
376
649
|
perConnector.forEach(({ index, devices }) => {
|
|
377
650
|
for (const device of devices) {
|
|
@@ -381,11 +654,11 @@ function createCombinedConnector(connectors) {
|
|
|
381
654
|
});
|
|
382
655
|
return merged.sort((a, b) => rank(a) - rank(b));
|
|
383
656
|
};
|
|
384
|
-
const resolveOwner = async (deviceId) => {
|
|
385
|
-
if (deviceId && deviceOwner.has(deviceId)) {
|
|
657
|
+
const resolveOwner = async (deviceId, transportType) => {
|
|
658
|
+
if (deviceId && deviceOwner.has(deviceId) && (!transportType || deviceOwner.get(deviceId)?.connectionType === transportType)) {
|
|
386
659
|
return { owner: deviceOwner.get(deviceId), deviceId };
|
|
387
660
|
}
|
|
388
|
-
const devices = await searchDevices({ waitForAll: Boolean(deviceId) });
|
|
661
|
+
const devices = await searchDevices({ waitForAll: Boolean(deviceId), transportType });
|
|
389
662
|
if (deviceId) {
|
|
390
663
|
const owner = deviceOwner.get(deviceId);
|
|
391
664
|
if (!owner)
|
|
@@ -396,13 +669,14 @@ function createCombinedConnector(connectors) {
|
|
|
396
669
|
if (!first) throw combinedDeviceNotFoundError("Combined connector: no devices found");
|
|
397
670
|
return { owner: deviceOwner.get(first.connectId), deviceId: first.connectId };
|
|
398
671
|
};
|
|
399
|
-
const connectByExplicitId = async (deviceId) => {
|
|
672
|
+
const connectByExplicitId = async (deviceId, transportType) => {
|
|
400
673
|
const cachedOwner = deviceOwner.get(deviceId);
|
|
401
|
-
if (cachedOwner) {
|
|
674
|
+
if (cachedOwner && (!transportType || cachedOwner.connectionType === transportType)) {
|
|
402
675
|
return { session: await cachedOwner.connect(deviceId), owner: cachedOwner };
|
|
403
676
|
}
|
|
404
677
|
let lastError;
|
|
405
678
|
for (const child of connectors) {
|
|
679
|
+
if (transportType && child.connectionType !== transportType) continue;
|
|
406
680
|
try {
|
|
407
681
|
const session = await child.connect(deviceId);
|
|
408
682
|
deviceOwner.set(deviceId, child);
|
|
@@ -424,14 +698,15 @@ function createCombinedConnector(connectors) {
|
|
|
424
698
|
// Nominal value only — the per-device `connectionType` is authoritative
|
|
425
699
|
// for a fused connector.
|
|
426
700
|
connectionType: connectors[0].connectionType,
|
|
427
|
-
|
|
428
|
-
|
|
701
|
+
availableTransports: [...new Set(connectors.map((child) => child.connectionType))],
|
|
702
|
+
searchDevices: (options) => searchDevices(options),
|
|
703
|
+
connect: async (deviceId, options) => {
|
|
429
704
|
let owner;
|
|
430
705
|
let session;
|
|
431
706
|
if (deviceId) {
|
|
432
|
-
({ session, owner } = await connectByExplicitId(deviceId));
|
|
707
|
+
({ session, owner } = await connectByExplicitId(deviceId, options?.transportType));
|
|
433
708
|
} else {
|
|
434
|
-
const resolved = await resolveOwner();
|
|
709
|
+
const resolved = await resolveOwner(void 0, options?.transportType);
|
|
435
710
|
owner = resolved.owner;
|
|
436
711
|
session = await owner.connect(resolved.deviceId);
|
|
437
712
|
}
|
|
@@ -537,6 +812,130 @@ var TypedEventEmitter = class {
|
|
|
537
812
|
}
|
|
538
813
|
};
|
|
539
814
|
|
|
815
|
+
// src/utils/requestSaveDeviceBinding.ts
|
|
816
|
+
async function requestSaveDeviceBinding(emitter, registry, binding, signal) {
|
|
817
|
+
const type = UI_REQUEST.REQUEST_SAVE_DEVICE_BINDING;
|
|
818
|
+
if (!emitter.listenerCount(type)) return false;
|
|
819
|
+
if (signal?.aborted) throw signal.reason;
|
|
820
|
+
const requestId = registry.createRequestId();
|
|
821
|
+
const pending = registry.wait(type, { requestId });
|
|
822
|
+
void pending.catch(() => void 0);
|
|
823
|
+
const cancel = () => registry.cancel(type, requestId);
|
|
824
|
+
signal?.addEventListener("abort", cancel, { once: true });
|
|
825
|
+
try {
|
|
826
|
+
emitter.emit(type, { type, payload: { ...binding, requestId } });
|
|
827
|
+
const response = await pending;
|
|
828
|
+
if (signal?.aborted) throw signal.reason;
|
|
829
|
+
if (response?.saved !== true) {
|
|
830
|
+
throw createHwkError({
|
|
831
|
+
code: 1e4 /* UnknownError */,
|
|
832
|
+
message: "Verified device binding could not be saved"
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
emitter.emit(UI_REQUEST.DEVICE_BINDING_STATUS, {
|
|
836
|
+
type: UI_REQUEST.DEVICE_BINDING_STATUS,
|
|
837
|
+
payload: { selectionRequestId: binding.selectionRequestId, status: "saved" }
|
|
838
|
+
});
|
|
839
|
+
return true;
|
|
840
|
+
} catch (error) {
|
|
841
|
+
emitter.emit(UI_REQUEST.DEVICE_BINDING_STATUS, {
|
|
842
|
+
type: UI_REQUEST.DEVICE_BINDING_STATUS,
|
|
843
|
+
payload: {
|
|
844
|
+
selectionRequestId: binding.selectionRequestId,
|
|
845
|
+
status: signal?.aborted ? "cancelled" : "failed"
|
|
846
|
+
}
|
|
847
|
+
});
|
|
848
|
+
throw error;
|
|
849
|
+
} finally {
|
|
850
|
+
signal?.removeEventListener("abort", cancel);
|
|
851
|
+
registry.cancel(type, requestId);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// src/utils/requestBleDeviceSelection.ts
|
|
856
|
+
async function requestBleDeviceSelection({
|
|
857
|
+
emitter,
|
|
858
|
+
registry,
|
|
859
|
+
request,
|
|
860
|
+
scan,
|
|
861
|
+
signal,
|
|
862
|
+
pollIntervalMs = 1500
|
|
863
|
+
}) {
|
|
864
|
+
const type = UI_REQUEST.REQUEST_SELECT_DEVICE;
|
|
865
|
+
if (signal.aborted) throw signal.reason;
|
|
866
|
+
if (!emitter.listenerCount(type)) {
|
|
867
|
+
throw createHwkError({
|
|
868
|
+
code: 10100 /* DeviceNotFound */,
|
|
869
|
+
message: "Select a Bluetooth device before continuing"
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
const requestId = registry.createRequestId();
|
|
873
|
+
let { devices } = request;
|
|
874
|
+
let stopped = false;
|
|
875
|
+
let timer;
|
|
876
|
+
let wake;
|
|
877
|
+
const stop = () => {
|
|
878
|
+
stopped = true;
|
|
879
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
880
|
+
wake?.();
|
|
881
|
+
};
|
|
882
|
+
const waitForNextScan = () => new Promise((resolve) => {
|
|
883
|
+
wake = resolve;
|
|
884
|
+
timer = setTimeout(resolve, pollIntervalMs);
|
|
885
|
+
if (stopped) resolve();
|
|
886
|
+
});
|
|
887
|
+
const cancel = () => registry.cancel(type, requestId);
|
|
888
|
+
const reply = registry.wait(type, { requestId }).finally(stop);
|
|
889
|
+
void reply.catch(() => void 0);
|
|
890
|
+
const publish = () => emitter.emit(type, {
|
|
891
|
+
type,
|
|
892
|
+
payload: { ...request, devices, requestId, scanning: true }
|
|
893
|
+
});
|
|
894
|
+
signal.addEventListener("abort", cancel, { once: true });
|
|
895
|
+
let polling;
|
|
896
|
+
try {
|
|
897
|
+
publish();
|
|
898
|
+
polling = (async () => {
|
|
899
|
+
await Promise.resolve();
|
|
900
|
+
while (!stopped) {
|
|
901
|
+
const snapshot = await scan();
|
|
902
|
+
if (stopped || signal.aborted) return;
|
|
903
|
+
devices = snapshot;
|
|
904
|
+
publish();
|
|
905
|
+
if (stopped) return;
|
|
906
|
+
await waitForNextScan();
|
|
907
|
+
}
|
|
908
|
+
})();
|
|
909
|
+
const selected = await Promise.race([reply, polling.then(() => reply)]);
|
|
910
|
+
stop();
|
|
911
|
+
await polling;
|
|
912
|
+
if (signal.aborted) throw signal.reason;
|
|
913
|
+
const device = devices.find((candidate) => candidate.connectId === selected.sdkConnectId);
|
|
914
|
+
if (!device) {
|
|
915
|
+
throw createHwkError({
|
|
916
|
+
code: 10100 /* DeviceNotFound */,
|
|
917
|
+
message: "Selected Bluetooth device is no longer available"
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
emitter.emit(UI_REQUEST.DEVICE_BINDING_STATUS, {
|
|
921
|
+
type: UI_REQUEST.DEVICE_BINDING_STATUS,
|
|
922
|
+
payload: { selectionRequestId: requestId, status: "verifying" }
|
|
923
|
+
});
|
|
924
|
+
return { device, requestId };
|
|
925
|
+
} catch (error) {
|
|
926
|
+
emitter.emit(UI_REQUEST.DEVICE_BINDING_STATUS, {
|
|
927
|
+
type: UI_REQUEST.DEVICE_BINDING_STATUS,
|
|
928
|
+
payload: { selectionRequestId: requestId, status: signal.aborted ? "cancelled" : "failed" }
|
|
929
|
+
});
|
|
930
|
+
throw error;
|
|
931
|
+
} finally {
|
|
932
|
+
stop();
|
|
933
|
+
signal.removeEventListener("abort", cancel);
|
|
934
|
+
registry.cancel(type, requestId);
|
|
935
|
+
await polling?.catch(() => void 0);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
|
|
540
939
|
// src/utils/semver.ts
|
|
541
940
|
function compareSemver(a, b) {
|
|
542
941
|
const pa = a.split(".").map(Number);
|
|
@@ -564,14 +963,96 @@ function padHex64(hex) {
|
|
|
564
963
|
function hexToBytes(hex) {
|
|
565
964
|
return nobleHexToBytes(stripHex(hex));
|
|
566
965
|
}
|
|
567
|
-
function
|
|
966
|
+
function bytesToHex3(bytes) {
|
|
568
967
|
return nobleBytesToHex(bytes);
|
|
569
968
|
}
|
|
570
969
|
|
|
970
|
+
// src/utils/solanaOffchainMessage.ts
|
|
971
|
+
var SOLANA_OFFCHAIN_SIGNING_DOMAIN = Uint8Array.of(
|
|
972
|
+
255,
|
|
973
|
+
...Array.from("solana offchain", (character) => character.charCodeAt(0))
|
|
974
|
+
);
|
|
975
|
+
var SOLANA_PUBLIC_KEY_LENGTH = 32;
|
|
976
|
+
var MAX_SOLANA_OFFCHAIN_SIGNERS = 255;
|
|
977
|
+
function compareBytes(a, b) {
|
|
978
|
+
for (let index = 0; index < a.length; index += 1) {
|
|
979
|
+
const difference = (a[index] ?? 0) - (b[index] ?? 0);
|
|
980
|
+
if (difference !== 0) return difference;
|
|
981
|
+
}
|
|
982
|
+
return a.length - b.length;
|
|
983
|
+
}
|
|
984
|
+
function bytesEqual(a, b) {
|
|
985
|
+
return a.length === b.length && a.every((value, index) => value === b[index]);
|
|
986
|
+
}
|
|
987
|
+
function decodeUtf8Strict(bytes) {
|
|
988
|
+
let encoded = "";
|
|
989
|
+
for (const value of bytes) {
|
|
990
|
+
encoded += `%${value.toString(16).padStart(2, "0")}`;
|
|
991
|
+
}
|
|
992
|
+
return decodeURIComponent(encoded);
|
|
993
|
+
}
|
|
994
|
+
function prepareSolanaOffchainMessageV1({
|
|
995
|
+
message,
|
|
996
|
+
requiredSigners
|
|
997
|
+
}) {
|
|
998
|
+
if (message.length === 0) {
|
|
999
|
+
throw new Error("Solana off-chain message cannot be empty");
|
|
1000
|
+
}
|
|
1001
|
+
if (requiredSigners.length === 0 || requiredSigners.length > MAX_SOLANA_OFFCHAIN_SIGNERS) {
|
|
1002
|
+
throw new Error("Solana off-chain message requires between 1 and 255 signers");
|
|
1003
|
+
}
|
|
1004
|
+
let messageText;
|
|
1005
|
+
try {
|
|
1006
|
+
messageText = decodeUtf8Strict(message);
|
|
1007
|
+
} catch {
|
|
1008
|
+
throw new Error("Solana off-chain message must contain valid UTF-8");
|
|
1009
|
+
}
|
|
1010
|
+
const signerBytes = requiredSigners.map((signer, index) => {
|
|
1011
|
+
let bytes;
|
|
1012
|
+
try {
|
|
1013
|
+
bytes = hexToBytes(signer);
|
|
1014
|
+
} catch {
|
|
1015
|
+
throw new Error(`Solana off-chain signer ${index} must be a hex public key`);
|
|
1016
|
+
}
|
|
1017
|
+
if (bytes.length !== SOLANA_PUBLIC_KEY_LENGTH) {
|
|
1018
|
+
throw new Error(`Solana off-chain signer ${index} must be 32 bytes`);
|
|
1019
|
+
}
|
|
1020
|
+
return bytes;
|
|
1021
|
+
});
|
|
1022
|
+
signerBytes.sort(compareBytes);
|
|
1023
|
+
for (let index = 1; index < signerBytes.length; index += 1) {
|
|
1024
|
+
if (bytesEqual(signerBytes[index - 1], signerBytes[index])) {
|
|
1025
|
+
throw new Error("Solana off-chain signers must be unique");
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
const serializedMessage = new Uint8Array(
|
|
1029
|
+
SOLANA_OFFCHAIN_SIGNING_DOMAIN.length + 2 + signerBytes.length * SOLANA_PUBLIC_KEY_LENGTH + message.length
|
|
1030
|
+
);
|
|
1031
|
+
let offset = 0;
|
|
1032
|
+
serializedMessage.set(SOLANA_OFFCHAIN_SIGNING_DOMAIN, offset);
|
|
1033
|
+
offset += SOLANA_OFFCHAIN_SIGNING_DOMAIN.length;
|
|
1034
|
+
serializedMessage[offset] = 1;
|
|
1035
|
+
offset += 1;
|
|
1036
|
+
serializedMessage[offset] = signerBytes.length;
|
|
1037
|
+
offset += 1;
|
|
1038
|
+
for (const signer of signerBytes) {
|
|
1039
|
+
serializedMessage.set(signer, offset);
|
|
1040
|
+
offset += SOLANA_PUBLIC_KEY_LENGTH;
|
|
1041
|
+
}
|
|
1042
|
+
serializedMessage.set(message, offset);
|
|
1043
|
+
return {
|
|
1044
|
+
messageText,
|
|
1045
|
+
requiredSigners: signerBytes.map(bytesToHex3),
|
|
1046
|
+
serializedMessage
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
|
|
571
1050
|
// src/utils/deviceIdentity.ts
|
|
572
1051
|
var ONEKEY_BLE_SERVICE_UUID = "00000001-0000-1000-8000-00805f9b34fb";
|
|
573
1052
|
var TREZOR_BLE_SERVICE_UUID = "8c000001-a59b-4d58-a9ad-073df69fa1b1";
|
|
574
1053
|
var LEDGER_USB_VENDOR_ID = 11415;
|
|
1054
|
+
var KEYSTONE_USB_VENDOR_ID = 4617;
|
|
1055
|
+
var KEYSTONE_USB_PRODUCT_ID = 12289;
|
|
575
1056
|
var lower = (value) => value?.trim().toLowerCase() ?? "";
|
|
576
1057
|
var hasServiceUuid = (input, uuid) => {
|
|
577
1058
|
const expected = uuid.toLowerCase();
|
|
@@ -594,6 +1075,11 @@ function detectHardwareVendorFromDescriptor(input) {
|
|
|
594
1075
|
if (typeof input.vendor === "number" && input.vendor === LEDGER_USB_VENDOR_ID || input.vendorId === LEDGER_USB_VENDOR_ID || manufacturerName.includes("ledger")) {
|
|
595
1076
|
return "ledger";
|
|
596
1077
|
}
|
|
1078
|
+
const usbVendorId = typeof input.vendor === "number" ? input.vendor : input.vendorId;
|
|
1079
|
+
const usbProductId = typeof input.product === "number" ? input.product : input.productId;
|
|
1080
|
+
if (usbVendorId === KEYSTONE_USB_VENDOR_ID && usbProductId === KEYSTONE_USB_PRODUCT_ID || manufacturerName.includes("keystone")) {
|
|
1081
|
+
return "keystone";
|
|
1082
|
+
}
|
|
597
1083
|
return void 0;
|
|
598
1084
|
}
|
|
599
1085
|
function isKnownNonTargetHardwareVendor(input, targetVendor) {
|
|
@@ -617,28 +1103,62 @@ async function batchCall(params, callFn, onProgress) {
|
|
|
617
1103
|
|
|
618
1104
|
// src/utils/methodCatalog.ts
|
|
619
1105
|
var HARDWARE_METHOD_CATALOG = {
|
|
620
|
-
evmGetAddress: { chain: "evm", allNetwork: true },
|
|
621
|
-
evmSignTransaction: {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
1106
|
+
evmGetAddress: { chain: "evm", allNetwork: true, replayAfterTransportFailure: "safe" },
|
|
1107
|
+
evmSignTransaction: {
|
|
1108
|
+
chain: "evm",
|
|
1109
|
+
allNetwork: false,
|
|
1110
|
+
replayAfterTransportFailure: "unsafe"
|
|
1111
|
+
},
|
|
1112
|
+
evmSignMessage: { chain: "evm", allNetwork: false, replayAfterTransportFailure: "unsafe" },
|
|
1113
|
+
evmSignTypedData: { chain: "evm", allNetwork: false, replayAfterTransportFailure: "unsafe" },
|
|
1114
|
+
btcGetAddress: { chain: "btc", allNetwork: true, replayAfterTransportFailure: "safe" },
|
|
1115
|
+
btcGetPublicKey: { chain: "btc", allNetwork: true, replayAfterTransportFailure: "safe" },
|
|
1116
|
+
btcSignTransaction: {
|
|
1117
|
+
chain: "btc",
|
|
1118
|
+
allNetwork: false,
|
|
1119
|
+
replayAfterTransportFailure: "unsafe"
|
|
1120
|
+
},
|
|
1121
|
+
btcSignPsbt: { chain: "btc", allNetwork: false, replayAfterTransportFailure: "unsafe" },
|
|
1122
|
+
btcSignMessage: { chain: "btc", allNetwork: false, replayAfterTransportFailure: "unsafe" },
|
|
1123
|
+
btcGetMasterFingerprint: {
|
|
1124
|
+
chain: "btc",
|
|
1125
|
+
allNetwork: false,
|
|
1126
|
+
replayAfterTransportFailure: "safe"
|
|
1127
|
+
},
|
|
1128
|
+
solGetAddress: { chain: "sol", allNetwork: true, replayAfterTransportFailure: "safe" },
|
|
1129
|
+
solSignTransaction: {
|
|
1130
|
+
chain: "sol",
|
|
1131
|
+
allNetwork: false,
|
|
1132
|
+
replayAfterTransportFailure: "unsafe"
|
|
1133
|
+
},
|
|
1134
|
+
solSignMessage: { chain: "sol", allNetwork: false, replayAfterTransportFailure: "unsafe" },
|
|
1135
|
+
tronGetAddress: { chain: "tron", allNetwork: true, replayAfterTransportFailure: "safe" },
|
|
1136
|
+
tronSignTransaction: {
|
|
1137
|
+
chain: "tron",
|
|
1138
|
+
allNetwork: false,
|
|
1139
|
+
replayAfterTransportFailure: "unsafe"
|
|
1140
|
+
},
|
|
1141
|
+
tronSignMessage: { chain: "tron", allNetwork: false, replayAfterTransportFailure: "unsafe" },
|
|
1142
|
+
zcashGetFullViewingKey: {
|
|
1143
|
+
chain: "zcash",
|
|
1144
|
+
allNetwork: false,
|
|
1145
|
+
replayAfterTransportFailure: "safe"
|
|
1146
|
+
},
|
|
1147
|
+
zcashGetShieldedAddress: {
|
|
1148
|
+
chain: "zcash",
|
|
1149
|
+
allNetwork: false,
|
|
1150
|
+
replayAfterTransportFailure: "safe"
|
|
1151
|
+
}
|
|
636
1152
|
};
|
|
637
1153
|
var ALL_NETWORK_METHOD_NAMES = Object.entries(HARDWARE_METHOD_CATALOG).filter(([, metadata]) => metadata.allNetwork).map(([method]) => method);
|
|
638
1154
|
var ALL_NETWORK_METHOD_SET = new Set(ALL_NETWORK_METHOD_NAMES);
|
|
639
1155
|
function getHardwareMethodMetadata(method) {
|
|
640
1156
|
return HARDWARE_METHOD_CATALOG[method];
|
|
641
1157
|
}
|
|
1158
|
+
var SAFE_NON_CHAIN_METHODS = /* @__PURE__ */ new Set(["getFeatures", "authenticateDevice"]);
|
|
1159
|
+
function canReplayHardwareMethodAfterTransportFailure(method) {
|
|
1160
|
+
return getHardwareMethodMetadata(method)?.replayAfterTransportFailure === "safe" || SAFE_NON_CHAIN_METHODS.has(method);
|
|
1161
|
+
}
|
|
642
1162
|
function isAllNetworkMethodName(method) {
|
|
643
1163
|
return ALL_NETWORK_METHOD_SET.has(method);
|
|
644
1164
|
}
|
|
@@ -731,7 +1251,10 @@ export {
|
|
|
731
1251
|
DeviceJobQueue,
|
|
732
1252
|
EConnectorInteraction,
|
|
733
1253
|
HARDWARE_METHOD_CATALOG,
|
|
1254
|
+
HARDWARE_RUNTIME_ID_PREFIX,
|
|
734
1255
|
HardwareErrorCode,
|
|
1256
|
+
INTERACTION_DEFAULT_TTL_MS,
|
|
1257
|
+
InteractionRegistry,
|
|
735
1258
|
ORPHAN_ELIGIBLE_ERROR_CODES,
|
|
736
1259
|
SDK,
|
|
737
1260
|
TypedEventEmitter,
|
|
@@ -745,23 +1268,42 @@ export {
|
|
|
745
1268
|
UiRequestRegistry,
|
|
746
1269
|
batchCall,
|
|
747
1270
|
buildUnsupportedMethodResponse,
|
|
748
|
-
|
|
1271
|
+
bytesToHex3 as bytesToHex,
|
|
1272
|
+
canReplayHardwareMethodAfterTransportFailure,
|
|
749
1273
|
compareSemver,
|
|
750
1274
|
createBridgedConnector,
|
|
751
1275
|
createCombinedConnector,
|
|
1276
|
+
createHardwareConnectorSessionId,
|
|
1277
|
+
createHardwareInteractionId,
|
|
1278
|
+
createHardwareSearchTargetId,
|
|
752
1279
|
createHwkError,
|
|
1280
|
+
defaultOriginForCode,
|
|
1281
|
+
defaultRecoveryForCode,
|
|
753
1282
|
deriveDeviceFingerprint,
|
|
1283
|
+
deriveWalletId,
|
|
754
1284
|
detectHardwareVendorFromDescriptor,
|
|
755
1285
|
enrichErrorMessage,
|
|
756
1286
|
ensure0x,
|
|
757
1287
|
failure,
|
|
758
1288
|
getAllNetworkMethodChain,
|
|
759
1289
|
getHardwareMethodMetadata,
|
|
1290
|
+
hasHardwareRuntimeIdPrefix,
|
|
760
1291
|
hexToBytes,
|
|
761
1292
|
isAllNetworkMethodName,
|
|
1293
|
+
isHardwareInteractionId,
|
|
1294
|
+
isHardwareSearchTargetId,
|
|
1295
|
+
isHwkRecoveryHint,
|
|
762
1296
|
isKnownNonTargetHardwareVendor,
|
|
1297
|
+
operationMayHaveCompletedParams,
|
|
763
1298
|
padHex64,
|
|
1299
|
+
parseBip32MasterFingerprint,
|
|
1300
|
+
parseHardwareRuntimeId,
|
|
1301
|
+
prepareSolanaOffchainMessageV1,
|
|
764
1302
|
rehydrateConnectorError,
|
|
1303
|
+
requestBleDeviceSelection,
|
|
1304
|
+
requestSaveDeviceBinding,
|
|
1305
|
+
resolveHardwareOperationTarget,
|
|
1306
|
+
resolveSearchTargetReusePolicy,
|
|
765
1307
|
runAllNetworkGetAddress,
|
|
766
1308
|
serializeConnectorError,
|
|
767
1309
|
stripHex,
|