@onekeyfe/hd-core 1.1.19-alpha.0 → 1.1.19-alpha.2

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 (52) hide show
  1. package/dist/api/BaseMethod.d.ts +5 -0
  2. package/dist/api/BaseMethod.d.ts.map +1 -1
  3. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  4. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  5. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  6. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  7. package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
  8. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +4 -4
  9. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  10. package/dist/api/firmware/bootloaderHelper.d.ts +1 -1
  11. package/dist/api/firmware/bootloaderHelper.d.ts.map +1 -1
  12. package/dist/api/firmware/updateBootloader.d.ts +1 -1
  13. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  14. package/dist/api/firmware/uploadFirmware.d.ts +5 -5
  15. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  16. package/dist/core/index.d.ts +6 -3
  17. package/dist/core/index.d.ts.map +1 -1
  18. package/dist/device/Device.d.ts +5 -2
  19. package/dist/device/Device.d.ts.map +1 -1
  20. package/dist/device/DeviceCommands.d.ts +8 -6
  21. package/dist/device/DeviceCommands.d.ts.map +1 -1
  22. package/dist/index.d.ts +51 -6
  23. package/dist/index.js +404 -76
  24. package/dist/types/device.d.ts +3 -0
  25. package/dist/types/device.d.ts.map +1 -1
  26. package/dist/utils/index.d.ts +1 -0
  27. package/dist/utils/index.d.ts.map +1 -1
  28. package/dist/utils/logger.d.ts +1 -1
  29. package/dist/utils/logger.d.ts.map +1 -1
  30. package/dist/utils/patch.d.ts +1 -1
  31. package/dist/utils/patch.d.ts.map +1 -1
  32. package/dist/utils/tracing.d.ts +34 -0
  33. package/dist/utils/tracing.d.ts.map +1 -0
  34. package/package.json +4 -4
  35. package/src/api/BaseMethod.ts +38 -1
  36. package/src/api/FirmwareUpdate.ts +2 -1
  37. package/src/api/FirmwareUpdateV2.ts +2 -1
  38. package/src/api/FirmwareUpdateV3.ts +2 -0
  39. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +46 -15
  40. package/src/api/evm/EVMSignTypedData.ts +8 -2
  41. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +16 -18
  42. package/src/api/firmware/bootloaderHelper.ts +3 -1
  43. package/src/api/firmware/updateBootloader.ts +6 -3
  44. package/src/api/firmware/uploadFirmware.ts +87 -21
  45. package/src/core/index.ts +135 -27
  46. package/src/data/messages/messages.json +11 -1
  47. package/src/device/Device.ts +24 -3
  48. package/src/device/DeviceCommands.ts +55 -13
  49. package/src/types/device.ts +5 -0
  50. package/src/utils/index.ts +1 -0
  51. package/src/utils/logger.ts +3 -2
  52. package/src/utils/tracing.ts +238 -0
package/src/core/index.ts CHANGED
@@ -1,62 +1,75 @@
1
1
  import semver from 'semver';
2
2
  import EventEmitter from 'events';
3
- import { Features, LowlevelTransportSharedPlugin, OneKeyDeviceInfo } from '@onekeyfe/hd-transport';
4
3
  import {
5
- createDeferred,
6
- Deferred,
7
4
  ERRORS,
8
5
  HardwareError,
9
6
  HardwareErrorCode,
7
+ createDefectiveFirmwareError,
8
+ createDeferred,
10
9
  createDeprecatedHardwareError,
11
10
  createNeedUpgradeFirmwareHardwareError,
12
11
  createNewFirmwareForceUpdateHardwareError,
13
12
  createNewFirmwareUnReleaseHardwareError,
14
- createDefectiveFirmwareError,
15
13
  } from '@onekeyfe/hd-shared';
14
+
16
15
  import {
17
- getDeviceFirmwareVersion,
18
- getDeviceBLEFirmwareVersion,
16
+ LoggerNames,
19
17
  enableLog,
18
+ getDeviceBLEFirmwareVersion,
19
+ getDeviceFirmwareVersion,
20
+ getFirmwareType,
20
21
  getLogger,
21
- LoggerNames,
22
+ getMethodVersionRange,
22
23
  setLoggerPostMessage,
23
24
  wait,
24
- getMethodVersionRange,
25
- getFirmwareType,
26
25
  } from '../utils';
27
26
  import {
28
27
  findDefectiveBatchDevice,
29
28
  getDefectiveDeviceInfo,
30
29
  } from '../utils/findDefectiveBatchDevice';
31
30
  import { supportNewPassphrase } from '../utils/deviceFeaturesUtils';
32
- import { Device, DeviceEvents, InitOptions, RunOptions } from '../device/Device';
31
+ import {
32
+ cleanupSdkInstance,
33
+ completeRequestContext,
34
+ createRequestContext,
35
+ createSdkTracingContext,
36
+ formatRequestContext,
37
+ getActiveRequestsByDeviceInstance,
38
+ updateRequestContext,
39
+ } from '../utils/tracing';
40
+ import { Device } from '../device/Device';
33
41
  import { DeviceList } from '../device/DeviceList';
34
42
  import { DevicePool } from '../device/DevicePool';
35
43
  import { findMethod } from '../api/utils';
36
44
  import { DataManager } from '../data-manager';
37
-
38
45
  import { UI_REQUEST as UI_REQUEST_CONST } from '../constants/ui-request';
39
46
  import {
40
47
  CORE_EVENT,
41
- CoreMessage,
42
- createDeviceMessage,
43
- createResponseMessage,
44
- createUiMessage,
45
48
  DEVICE,
46
49
  IFRAME,
47
- IFrameCallMessage,
48
50
  UI_REQUEST,
49
51
  UI_RESPONSE,
50
- UiPromise,
51
- UiPromiseResponse,
52
+ createDeviceMessage,
53
+ createResponseMessage,
54
+ createUiMessage,
52
55
  } from '../events';
53
- import type { BaseMethod } from '../api/BaseMethod';
54
- import type { ConnectSettings, KnownDevice } from '../types';
55
56
  import TransportManager from '../data-manager/TransportManager';
56
57
  import DeviceConnector from '../device/DeviceConnector';
57
58
  import RequestQueue from './RequestQueue';
58
59
  import { getSynchronize } from '../utils/getSynchronize';
59
60
 
61
+ import type { ConnectSettings, KnownDevice } from '../types';
62
+ import type { CoreMessage, IFrameCallMessage, UiPromise, UiPromiseResponse } from '../events';
63
+ import type { DeviceEvents, InitOptions, RunOptions } from '../device/Device';
64
+ import type { SdkTracingContext } from '../utils/tracing';
65
+ import type { Deferred } from '@onekeyfe/hd-shared';
66
+ import type {
67
+ Features,
68
+ LowlevelTransportSharedPlugin,
69
+ OneKeyDeviceInfo,
70
+ } from '@onekeyfe/hd-transport';
71
+ import type { BaseMethod } from '../api/BaseMethod';
72
+
60
73
  const Log = getLogger(LoggerNames.Core);
61
74
 
62
75
  export type CoreContext = ReturnType<Core['getCoreContext']>;
@@ -97,6 +110,30 @@ let preConnectCache: {
97
110
  passphraseState: undefined,
98
111
  };
99
112
 
113
+ const toError = (error: unknown): Error | undefined => {
114
+ if (error instanceof Error) return error;
115
+ if (error == null) return undefined;
116
+ if (typeof error === 'string') return new Error(error);
117
+ try {
118
+ return new Error(JSON.stringify(error));
119
+ } catch {
120
+ return new Error(String(error));
121
+ }
122
+ };
123
+
124
+ const updateMethodRequestContext = (method: BaseMethod, updates: any) => {
125
+ if (method.requestContext) {
126
+ updateRequestContext(method.requestContext.responseID, updates);
127
+ }
128
+ };
129
+
130
+ const completeMethodRequestContext = (method: BaseMethod, error?: unknown) => {
131
+ if (!method.requestContext) {
132
+ return;
133
+ }
134
+ completeRequestContext(method.requestContext.responseID, toError(error));
135
+ };
136
+
100
137
  export const callAPI = async (context: CoreContext, message: CoreMessage) => {
101
138
  if (!message.id || !message.payload || message.type !== IFRAME.CALL) {
102
139
  return Promise.reject(ERRORS.TypedError('on call: message.id or message.payload is missing'));
@@ -108,6 +145,15 @@ export const callAPI = async (context: CoreContext, message: CoreMessage) => {
108
145
  method = findMethod(message as IFrameCallMessage);
109
146
  method.connector = _connector;
110
147
  method.postMessage = postMessage;
148
+ method.setContext?.(context);
149
+
150
+ method.requestContext = createRequestContext(method.responseID, method.name, {
151
+ sdkInstanceId: context.sdkInstanceId,
152
+ connectId: method.connectId,
153
+ });
154
+
155
+ Log.debug(`[${context.sdkInstanceId}] callAPI: ${formatRequestContext(method.requestContext)}`);
156
+
111
157
  method.init();
112
158
  } catch (error) {
113
159
  return Promise.reject(error);
@@ -116,10 +162,13 @@ export const callAPI = async (context: CoreContext, message: CoreMessage) => {
116
162
  DevicePool.emitter.on(DEVICE.CONNECT, onDeviceConnectHandler);
117
163
 
118
164
  if (!method.useDevice) {
165
+ updateMethodRequestContext(method, { status: 'running' });
119
166
  try {
120
167
  const response = await method.run();
168
+ completeMethodRequestContext(method);
121
169
  return createResponseMessage(method.responseID, true, response);
122
170
  } catch (error) {
171
+ completeMethodRequestContext(method, error);
123
172
  return createResponseMessage(method.responseID, false, { error });
124
173
  }
125
174
  }
@@ -191,6 +240,8 @@ const onCallDevice = async (
191
240
 
192
241
  const { requestQueue, getPrePendingCallPromise, setPrePendingCallPromise } = context;
193
242
 
243
+ updateMethodRequestContext(method, { status: 'running' });
244
+
194
245
  const connectStateChange = preConnectCache.passphraseState !== method.payload.passphraseState;
195
246
 
196
247
  preConnectCache = {
@@ -225,6 +276,8 @@ const onCallDevice = async (
225
276
  } catch (e) {
226
277
  console.log('ensureConnected error: ', e);
227
278
 
279
+ completeMethodRequestContext(method, e);
280
+
228
281
  if (e.name === 'AbortError' || e.message === 'Request aborted') {
229
282
  requestQueue.releaseTask(method.responseID);
230
283
  return createResponseMessage(method.responseID, false, {
@@ -239,6 +292,19 @@ const onCallDevice = async (
239
292
  method.setDevice?.(device);
240
293
  method.context = context;
241
294
 
295
+ updateMethodRequestContext(method, {
296
+ deviceInstanceId: device.instanceId,
297
+ commandsInstanceId: device.commands?.instanceId,
298
+ });
299
+
300
+ const activeRequests = getActiveRequestsByDeviceInstance(device.instanceId);
301
+ if (activeRequests.length > 0) {
302
+ Log.warn(
303
+ `[${method.instanceId}] Device ${device.instanceId} has ${activeRequests.length} active requests:`,
304
+ activeRequests.map(formatRequestContext)
305
+ );
306
+ }
307
+
242
308
  device.on(DEVICE.PIN, onDevicePinHandler);
243
309
  device.on(DEVICE.BUTTON, onDeviceButtonHandler);
244
310
  device.on(
@@ -452,10 +518,12 @@ const onCallDevice = async (
452
518
  Log.debug('Call API - Inner Method Run: ');
453
519
  messageResponse = createResponseMessage(method.responseID, true, response);
454
520
  requestQueue.resolveRequest(method.responseID, messageResponse);
521
+ completeMethodRequestContext(method);
455
522
  } catch (error) {
456
- Log.debug('Call API - Inner Method Run Error: ', error);
523
+ Log.debug(`Call API - Inner Method Run Error`, error);
457
524
  messageResponse = createResponseMessage(method.responseID, false, { error });
458
525
  requestQueue.resolveRequest(method.responseID, messageResponse);
526
+ completeMethodRequestContext(method, error);
459
527
  }
460
528
  };
461
529
  Log.debug('Call API - Device Run: ', device.mainId);
@@ -471,6 +539,7 @@ const onCallDevice = async (
471
539
  return await task.callPromise.promise;
472
540
  } catch (e) {
473
541
  Log.debug('Device Run Error: ', e);
542
+ completeMethodRequestContext(method, e);
474
543
  return createResponseMessage(method.responseID, false, { error: e });
475
544
  }
476
545
  } catch (error) {
@@ -480,6 +549,7 @@ const onCallDevice = async (
480
549
  ERRORS.TypedError(HardwareErrorCode.CallMethodError, error.message)
481
550
  );
482
551
  Log.debug('Call API - Run Error: ', error);
552
+ completeMethodRequestContext(method, error);
483
553
  } finally {
484
554
  const response = messageResponse;
485
555
 
@@ -507,7 +577,21 @@ const onCallDevice = async (
507
577
 
508
578
  cleanup();
509
579
 
510
- removeDeviceListener(device);
580
+ if (device) {
581
+ const stillActive = getActiveRequestsByDeviceInstance(device.instanceId);
582
+ if (stillActive.length > 1) {
583
+ Log.warn(
584
+ `[${method.instanceId}] Removing listeners while ${stillActive.length} requests are active!`,
585
+ {
586
+ deviceInstanceId: device.instanceId,
587
+ activeRequests: stillActive.map(formatRequestContext),
588
+ pinListeners: device.listenerCount(DEVICE.PIN),
589
+ }
590
+ );
591
+ } else {
592
+ removeDeviceListener(device);
593
+ }
594
+ }
511
595
  }
512
596
  };
513
597
 
@@ -587,7 +671,10 @@ function initDeviceForBle(method: BaseMethod) {
587
671
  if (deviceCacheMap.has(method.connectId)) {
588
672
  device = deviceCacheMap.get(method.connectId) as Device;
589
673
  } else {
590
- device = Device.fromDescriptor({ id: method.connectId } as OneKeyDeviceInfo);
674
+ device = Device.fromDescriptor(
675
+ { id: method.connectId } as OneKeyDeviceInfo,
676
+ method.sdkInstanceId
677
+ );
591
678
  deviceCacheMap.set(method.connectId, device);
592
679
  }
593
680
  device.deviceConnector = _connector;
@@ -642,7 +729,7 @@ const ensureConnected = async (
642
729
  if (timer) {
643
730
  clearTimeout(timer);
644
731
  }
645
- reject(ERRORS.TypedError(HardwareErrorCode.ActionCancelled));
732
+ reject(ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled));
646
733
  return true;
647
734
  }
648
735
  return false;
@@ -806,7 +893,7 @@ export const cancel = (context: CoreContext, connectId?: string) => {
806
893
  }
807
894
  requestQueue.rejectRequest(
808
895
  requestId,
809
- ERRORS.TypedError(HardwareErrorCode.ActionCancelled)
896
+ ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)
810
897
  );
811
898
  }
812
899
  }
@@ -831,7 +918,7 @@ export const cancel = (context: CoreContext, connectId?: string) => {
831
918
 
832
919
  requestQueue.rejectRequest(
833
920
  requestId,
834
- ERRORS.TypedError(HardwareErrorCode.ActionCancelled)
921
+ ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)
835
922
  );
836
923
  }
837
924
  }
@@ -844,7 +931,10 @@ export const cancel = (context: CoreContext, connectId?: string) => {
844
931
  });
845
932
 
846
933
  requestQueue.getRequestTasksId().forEach(requestId => {
847
- requestQueue.rejectRequest(requestId, ERRORS.TypedError(HardwareErrorCode.ActionCancelled));
934
+ requestQueue.rejectRequest(
935
+ requestId,
936
+ ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)
937
+ );
848
938
  });
849
939
  }
850
940
  }
@@ -1005,6 +1095,9 @@ const onSelectDeviceInBootloaderForWebDeviceHandler = async (
1005
1095
  * @memberof Core
1006
1096
  */
1007
1097
  const postMessage = (message: CoreMessage) => {
1098
+ if (!_core) {
1099
+ return;
1100
+ }
1008
1101
  _core.emit(CORE_EVENT, message);
1009
1102
  };
1010
1103
 
@@ -1023,6 +1116,10 @@ const removeUiPromise = (promise: Deferred<any>) => {
1023
1116
  };
1024
1117
 
1025
1118
  export default class Core extends EventEmitter {
1119
+ private tracingContext: SdkTracingContext;
1120
+
1121
+ public readonly sdkInstanceId: string;
1122
+
1026
1123
  private requestQueue = new RequestQueue();
1027
1124
 
1028
1125
  // background task
@@ -1030,8 +1127,17 @@ export default class Core extends EventEmitter {
1030
1127
 
1031
1128
  private methodSynchronize = getSynchronize();
1032
1129
 
1130
+ constructor() {
1131
+ super();
1132
+ this.tracingContext = createSdkTracingContext();
1133
+ this.sdkInstanceId = this.tracingContext.sdkInstanceId;
1134
+ Log.debug(`[Core] Created SDK instance: ${this.sdkInstanceId}`);
1135
+ }
1136
+
1033
1137
  private getCoreContext() {
1034
1138
  return {
1139
+ sdkInstanceId: this.sdkInstanceId,
1140
+ tracingContext: this.tracingContext,
1035
1141
  requestQueue: this.requestQueue,
1036
1142
  methodSynchronize: this.methodSynchronize,
1037
1143
  getPrePendingCallPromise: () => this.prePendingCallPromise,
@@ -1109,6 +1215,8 @@ export default class Core extends EventEmitter {
1109
1215
  dispose() {
1110
1216
  _deviceList = undefined;
1111
1217
  _connector = undefined;
1218
+ Log.debug(`[Core] Disposing SDK instance: ${this.sdkInstanceId}`);
1219
+ cleanupSdkInstance(this.sdkInstanceId);
1112
1220
  }
1113
1221
  }
1114
1222
 
@@ -1997,6 +1997,15 @@
1997
1997
  }
1998
1998
  }
1999
1999
  },
2000
+ "UpgradeFileHeader": {
2001
+ "fields": {
2002
+ "data": {
2003
+ "rule": "required",
2004
+ "type": "bytes",
2005
+ "id": 1
2006
+ }
2007
+ }
2008
+ },
2000
2009
  "CardanoDerivationType": {
2001
2010
  "values": {
2002
2011
  "LEDGER": 0,
@@ -12397,7 +12406,8 @@
12397
12406
  "MessageType_GetPassphraseState": 10028,
12398
12407
  "MessageType_PassphraseState": 10029,
12399
12408
  "MessageType_UnLockDevice": 10030,
12400
- "MessageType_UnLockDeviceResponse": 10031
12409
+ "MessageType_UnLockDeviceResponse": 10031,
12410
+ "MessageType_UpgradeFileHeader": 10050
12401
12411
  }
12402
12412
  },
12403
12413
  "google": {
@@ -24,6 +24,7 @@ import {
24
24
  fixFeaturesFirmwareVersion,
25
25
  getPassphraseStateWithRefreshDeviceInfo,
26
26
  } from '../utils/deviceFeaturesUtils';
27
+ import { generateInstanceId } from '../utils/tracing';
27
28
 
28
29
  import type DeviceConnector from './DeviceConnector';
29
30
  // eslint-disable-next-line import/no-cycle
@@ -99,6 +100,15 @@ export class Device extends EventEmitter {
99
100
  */
100
101
  originalDescriptor: DeviceDescriptor;
101
102
 
103
+ sdkInstanceId?: string;
104
+
105
+ /**
106
+ * 设备实例唯一标识
107
+ */
108
+ instanceId: string;
109
+
110
+ createdAt: number;
111
+
102
112
  /**
103
113
  * 设备主 ID
104
114
  * 蓝牙连接时是设备的 UUID
@@ -158,14 +168,22 @@ export class Device extends EventEmitter {
158
168
 
159
169
  pendingCallbackPromise?: Deferred<void>;
160
170
 
161
- constructor(descriptor: DeviceDescriptor) {
171
+ constructor(descriptor: DeviceDescriptor, sdkInstanceId?: string) {
162
172
  super();
163
173
  this.originalDescriptor = descriptor;
174
+ this.sdkInstanceId = sdkInstanceId;
175
+ this.instanceId = generateInstanceId('Device', this.sdkInstanceId);
176
+ this.createdAt = Date.now();
177
+ Log.debug(
178
+ `[Device] Created: ${this.instanceId}${
179
+ this.sdkInstanceId ? ` for SDK: ${this.sdkInstanceId}` : ''
180
+ }`
181
+ );
164
182
  }
165
183
 
166
- static fromDescriptor(originalDescriptor: DeviceDescriptor) {
184
+ static fromDescriptor(originalDescriptor: DeviceDescriptor, sdkInstanceId?: string) {
167
185
  const descriptor = { ...originalDescriptor };
168
- return new Device(descriptor);
186
+ return new Device(descriptor, sdkInstanceId);
169
187
  }
170
188
 
171
189
  // simplified object to pass via postMessage
@@ -183,6 +201,9 @@ export class Device extends EventEmitter {
183
201
  connectId: DataManager.isBleConnect(env) ? this.mainId || null : getDeviceUUID(this.features),
184
202
  /** Hardware ID, will not change at any time */
185
203
  uuid: getDeviceUUID(this.features),
204
+ sdkInstanceId: this.sdkInstanceId,
205
+ instanceId: this.instanceId,
206
+ createdAt: this.createdAt,
186
207
  deviceType,
187
208
  /** ID for current seeds, will clear after replace a new seed at device */
188
209
  deviceId: this.features.device_id || null,
@@ -1,11 +1,18 @@
1
- import type { Transport, Messages, FailureType } from '@onekeyfe/hd-transport';
2
1
  import { ERRORS, HardwareError, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
+
3
3
  import TransportManager from '../data-manager/TransportManager';
4
4
  import DataManager from '../data-manager/DataManager';
5
- import { patchFeatures, getLogger, LoggerNames, getDeviceType } from '../utils';
6
- import type { Device } from './Device';
5
+ import { LoggerNames, getDeviceType, getLogger, patchFeatures } from '../utils';
7
6
  import { DEVICE, type PassphraseRequestPayload } from '../events';
8
7
  import { DeviceModelToTypes } from '../types';
8
+ import {
9
+ formatRequestContext,
10
+ generateInstanceId,
11
+ getActiveRequestsByDeviceInstance,
12
+ } from '../utils/tracing';
13
+
14
+ import type { Device } from './Device';
15
+ import type { FailureType, Messages, Transport } from '@onekeyfe/hd-transport';
9
16
 
10
17
  export type PassphrasePromptResponse = {
11
18
  passphrase?: string;
@@ -114,12 +121,17 @@ export const cancelDeviceWithInitialize = (device: Device) => {
114
121
  };
115
122
 
116
123
  const Log = getLogger(LoggerNames.DeviceCommands);
124
+ const LogCore = getLogger(LoggerNames.Core);
117
125
 
118
126
  /**
119
127
  * The life cycle begins with the acquisition of the device and ends with the disposal device commands
120
128
  * acquire device -> create DeviceCommands -> release device -> dispose DeviceCommands
121
129
  */
122
130
  export class DeviceCommands {
131
+ instanceId: string;
132
+
133
+ currentResponseID?: number;
134
+
123
135
  device: Device;
124
136
 
125
137
  transport: Transport;
@@ -135,6 +147,9 @@ export class DeviceCommands {
135
147
  this.mainId = mainId;
136
148
  this.transport = TransportManager.getTransport();
137
149
  this.disposed = false;
150
+ this.instanceId = generateInstanceId('DeviceCommands', device.sdkInstanceId);
151
+
152
+ Log.debug(`[DeviceCommands] Created: ${this.instanceId}, device: ${this.device.instanceId}`);
138
153
  }
139
154
 
140
155
  async dispose(_cancelRequest: boolean) {
@@ -217,10 +232,14 @@ export class DeviceCommands {
217
232
  const promise = this.transport.call(this.mainId, type, msg) as any;
218
233
  this.callPromise = promise;
219
234
  const res = await promise;
220
- Log.debug('[DeviceCommands] [call] Received', res.type);
235
+ if (res.type === 'Failure') {
236
+ LogCore.debug('[DeviceCommands] [call] Received', res.type, res.message);
237
+ } else {
238
+ LogCore.debug('[DeviceCommands] [call] Received', res.type);
239
+ }
221
240
  return res;
222
241
  } catch (error) {
223
- Log.debug('[DeviceCommands] [call] Received error', error);
242
+ LogCore.debug('[DeviceCommands] [call] Received error', error);
224
243
  if (error.errorCode === HardwareErrorCode.BleDeviceBondError) {
225
244
  return {
226
245
  type: 'BleDeviceBondError',
@@ -400,14 +419,16 @@ export class DeviceCommands {
400
419
  message?.includes('verify failed')
401
420
  ) {
402
421
  error = ERRORS.TypedError(HardwareErrorCode.FirmwareVerificationFailed, message);
422
+ } else if (message?.includes('Firmware downgrade not allowed')) {
423
+ // Check firmware check failed
424
+ error = ERRORS.TypedError(HardwareErrorCode.FirmwareDowngradeNotAllowed, message);
403
425
  }
404
426
  }
405
427
 
406
428
  if (code === 'Failure_UnexpectedMessage') {
407
429
  if (callType === 'PassphraseAck') {
408
430
  error = ERRORS.TypedError(HardwareErrorCode.UnexpectPassphrase);
409
- }
410
- if (message === 'Not in Signing mode') {
431
+ } else if (message === 'Not in Signing mode') {
411
432
  error = ERRORS.TypedError(HardwareErrorCode.NotInSigningMode);
412
433
  }
413
434
  }
@@ -500,7 +521,7 @@ export class DeviceCommands {
500
521
  cancelDeviceInPrompt(this.device, false)
501
522
  .then(onCancel => {
502
523
  const error = ERRORS.TypedError(
503
- HardwareErrorCode.ActionCancelled,
524
+ HardwareErrorCode.CallQueueActionCancelled,
504
525
  `${DEVICE.PIN} canceled`
505
526
  );
506
527
  // onCancel not void
@@ -515,7 +536,15 @@ export class DeviceCommands {
515
536
  reject(error);
516
537
  });
517
538
 
518
- if (this.device.listenerCount(DEVICE.PIN) > 0) {
539
+ const listenerCount = this.device.listenerCount(DEVICE.PIN);
540
+
541
+ Log.debug(`[${this.instanceId}] _promptPin called`, {
542
+ responseID: this.currentResponseID,
543
+ deviceInstanceId: this.device.instanceId,
544
+ listenerCount,
545
+ });
546
+
547
+ if (listenerCount > 0) {
519
548
  this.device.setCancelableAction(cancelAndReject);
520
549
  this.device.emit(DEVICE.PIN, this.device, type, (err, pin) => {
521
550
  this.device.clearCancelableAction();
@@ -526,11 +555,22 @@ export class DeviceCommands {
526
555
  }
527
556
  });
528
557
  } else {
529
- console.warn('[DeviceCommands] [call] PIN callback not configured, cancelling request');
558
+ const activeRequests = getActiveRequestsByDeviceInstance(this.device.instanceId);
559
+ const errorInfo = {
560
+ commandsInstanceId: this.instanceId,
561
+ deviceInstanceId: this.device.instanceId,
562
+ currentResponseID: this.currentResponseID,
563
+ listenerCount,
564
+ activeRequests: activeRequests.map(formatRequestContext),
565
+ };
566
+
567
+ LogCore.error('[DeviceCommands] [call] PIN callback not configured, cancelling request', {
568
+ ...errorInfo,
569
+ });
530
570
  reject(
531
571
  ERRORS.TypedError(
532
572
  HardwareErrorCode.RuntimeError,
533
- '_promptPin: PIN callback not configured'
573
+ `_promptPin: PIN callback not configured: ${JSON.stringify(errorInfo)}`
534
574
  )
535
575
  );
536
576
  }
@@ -543,7 +583,7 @@ export class DeviceCommands {
543
583
  cancelDeviceInPrompt(this.device, false)
544
584
  .then(onCancel => {
545
585
  const error = ERRORS.TypedError(
546
- HardwareErrorCode.ActionCancelled,
586
+ HardwareErrorCode.CallQueueActionCancelled,
547
587
  `${DEVICE.PASSPHRASE} canceled`
548
588
  );
549
589
  // onCancel not void
@@ -574,7 +614,9 @@ export class DeviceCommands {
574
614
  }
575
615
  );
576
616
  } else {
577
- Log.error('[DeviceCommands] [call] Passphrase callback not configured, cancelling request');
617
+ LogCore.error(
618
+ '[DeviceCommands] [call] Passphrase callback not configured, cancelling request'
619
+ );
578
620
  reject(
579
621
  ERRORS.TypedError(
580
622
  HardwareErrorCode.RuntimeError,
@@ -35,6 +35,11 @@ export type KnownDevice = {
35
35
  unavailableCapabilities: UnavailableCapabilities;
36
36
  bleFirmwareVersion: IVersionArray | null;
37
37
  firmwareVersion: IVersionArray | null;
38
+
39
+ // debug sdk
40
+ instanceId?: string;
41
+ sdkInstanceId?: string;
42
+ createdAt?: number;
38
43
  };
39
44
 
40
45
  export type SearchDevice = {
@@ -2,6 +2,7 @@ export { getLogger, enableLog, LoggerNames, getLog, setLoggerPostMessage } from
2
2
  export * from './assets';
3
3
  export * from './versionUtils';
4
4
  export * from './patch';
5
+ export * from './tracing';
5
6
  // Device utils
6
7
  export {
7
8
  getDeviceTypeByBleName,
@@ -1,5 +1,6 @@
1
- import { CoreMessage } from '../events';
2
- import { createLogMessage, LOG } from '../events/log';
1
+ import { LOG, createLogMessage } from '../events/log';
2
+
3
+ import type { CoreMessage } from '../events';
3
4
 
4
5
  type LogMessage = {
5
6
  level: string;