@onekeyfe/hd-core 1.1.19-alpha.0 → 1.1.19-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.
Files changed (36) 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/FirmwareUpdateV3.d.ts.map +1 -1
  4. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  5. package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
  6. package/dist/api/firmware/uploadFirmware.d.ts +4 -4
  7. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  8. package/dist/core/index.d.ts +3 -0
  9. package/dist/core/index.d.ts.map +1 -1
  10. package/dist/device/Device.d.ts +5 -2
  11. package/dist/device/Device.d.ts.map +1 -1
  12. package/dist/device/DeviceCommands.d.ts +6 -4
  13. package/dist/device/DeviceCommands.d.ts.map +1 -1
  14. package/dist/index.d.ts +51 -6
  15. package/dist/index.js +348 -63
  16. package/dist/types/device.d.ts +3 -0
  17. package/dist/types/device.d.ts.map +1 -1
  18. package/dist/utils/index.d.ts +1 -0
  19. package/dist/utils/index.d.ts.map +1 -1
  20. package/dist/utils/patch.d.ts +1 -1
  21. package/dist/utils/patch.d.ts.map +1 -1
  22. package/dist/utils/tracing.d.ts +34 -0
  23. package/dist/utils/tracing.d.ts.map +1 -0
  24. package/package.json +4 -4
  25. package/src/api/BaseMethod.ts +38 -1
  26. package/src/api/FirmwareUpdateV3.ts +2 -0
  27. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +46 -15
  28. package/src/api/evm/EVMSignTypedData.ts +8 -2
  29. package/src/api/firmware/uploadFirmware.ts +51 -15
  30. package/src/core/index.ts +108 -7
  31. package/src/data/messages/messages.json +11 -1
  32. package/src/device/Device.ts +24 -3
  33. package/src/device/DeviceCommands.ts +42 -8
  34. package/src/types/device.ts +5 -0
  35. package/src/utils/index.ts +1 -0
  36. package/src/utils/tracing.ts +251 -0
@@ -2,29 +2,27 @@ import semver from 'semver';
2
2
  import { blake2s } from '@noble/hashes/blake2s';
3
3
  import JSZip from 'jszip';
4
4
  import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
5
- import { Success } from '@onekeyfe/hd-transport';
5
+
6
6
  import {
7
- wait,
7
+ LoggerNames,
8
8
  getDeviceBootloaderVersion,
9
9
  getDeviceType,
10
- LoggerNames,
11
10
  getLogger,
11
+ wait,
12
12
  } from '../../utils';
13
- import {
14
- DEVICE,
15
- CoreMessage,
16
- createUiMessage,
17
- UI_REQUEST,
18
- IFirmwareUpdateProgressType,
19
- } from '../../events';
20
- import { PROTO } from '../../constants';
21
- import type { Device } from '../../device/Device';
22
- import type { TypedCall, TypedResponseMessage } from '../../device/DeviceCommands';
23
- import { DeviceModelToTypes, KnownDevice } from '../../types';
13
+ import { DEVICE, UI_REQUEST, createUiMessage } from '../../events';
14
+ import { DeviceModelToTypes } from '../../types';
24
15
  import { bytesToHex } from '../helpers/hexUtils';
25
16
  import { DataManager } from '../../data-manager';
26
17
  import { DevicePool } from '../../device/DevicePool';
27
18
 
19
+ import type { KnownDevice } from '../../types';
20
+ import type { TypedCall, TypedResponseMessage } from '../../device/DeviceCommands';
21
+ import type { PROTO } from '../../constants';
22
+ import type { CoreMessage, IFirmwareUpdateProgressType } from '../../events';
23
+ import type { Success } from '@onekeyfe/hd-transport';
24
+ import type { Device } from '../../device/Device';
25
+
28
26
  const NEW_BOOT_UPRATE_FIRMWARE_VERSION = '2.4.5';
29
27
  const SESSION_ERROR = 'session not found';
30
28
  const FIRMWARE_UPDATE_CONFIRM = 'Firmware install confirmed';
@@ -111,7 +109,45 @@ export const uploadFirmware = async (
111
109
  if (DeviceModelToTypes.model_mini.includes(deviceType)) {
112
110
  postConfirmationMessage(device);
113
111
  postProgressTip(device, 'ConfirmOnDevice', postMessage);
114
- const eraseCommand = updateType === 'firmware' ? 'FirmwareErase' : 'FirmwareErase_ex';
112
+ const isFirmware = updateType === 'firmware';
113
+
114
+ const deviceBootloaderVersion = getDeviceBootloaderVersion(device.features).join('.');
115
+ const supportUpgradeFileHeader = semver.gt(deviceBootloaderVersion, '2.1.0');
116
+
117
+ Log.debug(
118
+ 'supportUpgradeFileHeader:',
119
+ supportUpgradeFileHeader,
120
+ 'deviceBootloaderVersion:',
121
+ deviceBootloaderVersion
122
+ );
123
+ if (isFirmware && supportUpgradeFileHeader) {
124
+ // Extract and validate firmware header (first 1KB)
125
+ const HEADER_SIZE = 1024;
126
+ if (payload.byteLength < HEADER_SIZE) {
127
+ throw ERRORS.TypedError(
128
+ HardwareErrorCode.RuntimeError,
129
+ `firmware payload too small: ${payload.byteLength} bytes, expected at least ${HEADER_SIZE} bytes`
130
+ );
131
+ }
132
+
133
+ Log.debug('Uploading firmware header:', { size: HEADER_SIZE, totalSize: payload.byteLength });
134
+ postProgressTip(device, 'UploadingFirmwareHeader', postMessage);
135
+
136
+ const header = new Uint8Array(payload.slice(0, HEADER_SIZE));
137
+ const headerRes = (await typedCall('UpgradeFileHeader', 'Success', {
138
+ data: bytesToHex(header),
139
+ })) as TypedResponseMessage<'Success'>;
140
+
141
+ const isUnexpectedMessage = headerRes.message?.message?.includes('Failure_UnexpectedMessage');
142
+ if (headerRes.type !== 'Success' && !isUnexpectedMessage) {
143
+ Log.error('Firmware header upload failed:', headerRes);
144
+ throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'failed to upload firmware header');
145
+ }
146
+
147
+ Log.debug('Firmware header uploaded successfully, isUnexpectedMessage:', isUnexpectedMessage);
148
+ }
149
+
150
+ const eraseCommand = isFirmware ? 'FirmwareErase' : 'FirmwareErase_ex';
115
151
  const eraseRes = await typedCall(eraseCommand as unknown as any, 'Success', {});
116
152
  if (eraseRes.type !== 'Success') {
117
153
  throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'erase firmware error');
package/src/core/index.ts CHANGED
@@ -29,6 +29,16 @@ import {
29
29
  getDefectiveDeviceInfo,
30
30
  } from '../utils/findDefectiveBatchDevice';
31
31
  import { supportNewPassphrase } from '../utils/deviceFeaturesUtils';
32
+ import {
33
+ completeRequestContext,
34
+ createRequestContext,
35
+ createSdkTracingContext,
36
+ formatRequestContext,
37
+ getActiveRequestsByDeviceInstance,
38
+ SdkTracingContext,
39
+ updateRequestContext,
40
+ cleanupSdkInstance,
41
+ } from '../utils/tracing';
32
42
  import { Device, DeviceEvents, InitOptions, RunOptions } from '../device/Device';
33
43
  import { DeviceList } from '../device/DeviceList';
34
44
  import { DevicePool } from '../device/DevicePool';
@@ -97,6 +107,30 @@ let preConnectCache: {
97
107
  passphraseState: undefined,
98
108
  };
99
109
 
110
+ const toError = (error: unknown): Error | undefined => {
111
+ if (error instanceof Error) return error;
112
+ if (error == null) return undefined;
113
+ if (typeof error === 'string') return new Error(error);
114
+ try {
115
+ return new Error(JSON.stringify(error));
116
+ } catch {
117
+ return new Error(String(error));
118
+ }
119
+ };
120
+
121
+ const updateMethodRequestContext = (method: BaseMethod, updates: any) => {
122
+ if (method.requestContext) {
123
+ updateRequestContext(method.requestContext.responseID, updates);
124
+ }
125
+ };
126
+
127
+ const completeMethodRequestContext = (method: BaseMethod, error?: unknown) => {
128
+ if (!method.requestContext) {
129
+ return;
130
+ }
131
+ completeRequestContext(method.requestContext.responseID, toError(error));
132
+ };
133
+
100
134
  export const callAPI = async (context: CoreContext, message: CoreMessage) => {
101
135
  if (!message.id || !message.payload || message.type !== IFRAME.CALL) {
102
136
  return Promise.reject(ERRORS.TypedError('on call: message.id or message.payload is missing'));
@@ -108,6 +142,15 @@ export const callAPI = async (context: CoreContext, message: CoreMessage) => {
108
142
  method = findMethod(message as IFrameCallMessage);
109
143
  method.connector = _connector;
110
144
  method.postMessage = postMessage;
145
+ method.setContext?.(context);
146
+
147
+ method.requestContext = createRequestContext(method.responseID, method.name, {
148
+ sdkInstanceId: context.sdkInstanceId,
149
+ connectId: method.connectId,
150
+ });
151
+
152
+ Log.debug(`[${context.sdkInstanceId}] callAPI: ${formatRequestContext(method.requestContext)}`);
153
+
111
154
  method.init();
112
155
  } catch (error) {
113
156
  return Promise.reject(error);
@@ -116,10 +159,13 @@ export const callAPI = async (context: CoreContext, message: CoreMessage) => {
116
159
  DevicePool.emitter.on(DEVICE.CONNECT, onDeviceConnectHandler);
117
160
 
118
161
  if (!method.useDevice) {
162
+ updateMethodRequestContext(method, { status: 'running' });
119
163
  try {
120
164
  const response = await method.run();
165
+ completeMethodRequestContext(method);
121
166
  return createResponseMessage(method.responseID, true, response);
122
167
  } catch (error) {
168
+ completeMethodRequestContext(method, error);
123
169
  return createResponseMessage(method.responseID, false, { error });
124
170
  }
125
171
  }
@@ -191,6 +237,8 @@ const onCallDevice = async (
191
237
 
192
238
  const { requestQueue, getPrePendingCallPromise, setPrePendingCallPromise } = context;
193
239
 
240
+ updateMethodRequestContext(method, { status: 'running' });
241
+
194
242
  const connectStateChange = preConnectCache.passphraseState !== method.payload.passphraseState;
195
243
 
196
244
  preConnectCache = {
@@ -225,6 +273,8 @@ const onCallDevice = async (
225
273
  } catch (e) {
226
274
  console.log('ensureConnected error: ', e);
227
275
 
276
+ completeMethodRequestContext(method, e);
277
+
228
278
  if (e.name === 'AbortError' || e.message === 'Request aborted') {
229
279
  requestQueue.releaseTask(method.responseID);
230
280
  return createResponseMessage(method.responseID, false, {
@@ -239,6 +289,19 @@ const onCallDevice = async (
239
289
  method.setDevice?.(device);
240
290
  method.context = context;
241
291
 
292
+ updateMethodRequestContext(method, {
293
+ deviceInstanceId: device.instanceId,
294
+ commandsInstanceId: device.commands?.instanceId,
295
+ });
296
+
297
+ const activeRequests = getActiveRequestsByDeviceInstance(device.instanceId);
298
+ if (activeRequests.length > 0) {
299
+ Log.warn(
300
+ `[${method.instanceId}] Device ${device.instanceId} has ${activeRequests.length} active requests:`,
301
+ activeRequests.map(formatRequestContext)
302
+ );
303
+ }
304
+
242
305
  device.on(DEVICE.PIN, onDevicePinHandler);
243
306
  device.on(DEVICE.BUTTON, onDeviceButtonHandler);
244
307
  device.on(
@@ -452,10 +515,12 @@ const onCallDevice = async (
452
515
  Log.debug('Call API - Inner Method Run: ');
453
516
  messageResponse = createResponseMessage(method.responseID, true, response);
454
517
  requestQueue.resolveRequest(method.responseID, messageResponse);
518
+ completeMethodRequestContext(method);
455
519
  } catch (error) {
456
- Log.debug('Call API - Inner Method Run Error: ', error);
520
+ Log.debug(`Call API - Inner Method Run Error`, error);
457
521
  messageResponse = createResponseMessage(method.responseID, false, { error });
458
522
  requestQueue.resolveRequest(method.responseID, messageResponse);
523
+ completeMethodRequestContext(method, error);
459
524
  }
460
525
  };
461
526
  Log.debug('Call API - Device Run: ', device.mainId);
@@ -471,6 +536,7 @@ const onCallDevice = async (
471
536
  return await task.callPromise.promise;
472
537
  } catch (e) {
473
538
  Log.debug('Device Run Error: ', e);
539
+ completeMethodRequestContext(method, e);
474
540
  return createResponseMessage(method.responseID, false, { error: e });
475
541
  }
476
542
  } catch (error) {
@@ -480,6 +546,7 @@ const onCallDevice = async (
480
546
  ERRORS.TypedError(HardwareErrorCode.CallMethodError, error.message)
481
547
  );
482
548
  Log.debug('Call API - Run Error: ', error);
549
+ completeMethodRequestContext(method, error);
483
550
  } finally {
484
551
  const response = messageResponse;
485
552
 
@@ -507,7 +574,20 @@ const onCallDevice = async (
507
574
 
508
575
  cleanup();
509
576
 
510
- removeDeviceListener(device);
577
+ if (device) {
578
+ const stillActive = getActiveRequestsByDeviceInstance(device.instanceId);
579
+ if (stillActive.length > 1) {
580
+ Log.warn(
581
+ `[${method.instanceId}] Removing listeners while ${stillActive.length} requests are active!`,
582
+ {
583
+ deviceInstanceId: device.instanceId,
584
+ activeRequests: stillActive.map(formatRequestContext),
585
+ pinListeners: device.listenerCount(DEVICE.PIN),
586
+ }
587
+ );
588
+ }
589
+ removeDeviceListener(device);
590
+ }
511
591
  }
512
592
  };
513
593
 
@@ -587,7 +667,10 @@ function initDeviceForBle(method: BaseMethod) {
587
667
  if (deviceCacheMap.has(method.connectId)) {
588
668
  device = deviceCacheMap.get(method.connectId) as Device;
589
669
  } else {
590
- device = Device.fromDescriptor({ id: method.connectId } as OneKeyDeviceInfo);
670
+ device = Device.fromDescriptor(
671
+ { id: method.connectId } as OneKeyDeviceInfo,
672
+ method.sdkInstanceId
673
+ );
591
674
  deviceCacheMap.set(method.connectId, device);
592
675
  }
593
676
  device.deviceConnector = _connector;
@@ -642,7 +725,7 @@ const ensureConnected = async (
642
725
  if (timer) {
643
726
  clearTimeout(timer);
644
727
  }
645
- reject(ERRORS.TypedError(HardwareErrorCode.ActionCancelled));
728
+ reject(ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled));
646
729
  return true;
647
730
  }
648
731
  return false;
@@ -806,7 +889,7 @@ export const cancel = (context: CoreContext, connectId?: string) => {
806
889
  }
807
890
  requestQueue.rejectRequest(
808
891
  requestId,
809
- ERRORS.TypedError(HardwareErrorCode.ActionCancelled)
892
+ ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)
810
893
  );
811
894
  }
812
895
  }
@@ -831,7 +914,7 @@ export const cancel = (context: CoreContext, connectId?: string) => {
831
914
 
832
915
  requestQueue.rejectRequest(
833
916
  requestId,
834
- ERRORS.TypedError(HardwareErrorCode.ActionCancelled)
917
+ ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)
835
918
  );
836
919
  }
837
920
  }
@@ -844,7 +927,10 @@ export const cancel = (context: CoreContext, connectId?: string) => {
844
927
  });
845
928
 
846
929
  requestQueue.getRequestTasksId().forEach(requestId => {
847
- requestQueue.rejectRequest(requestId, ERRORS.TypedError(HardwareErrorCode.ActionCancelled));
930
+ requestQueue.rejectRequest(
931
+ requestId,
932
+ ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)
933
+ );
848
934
  });
849
935
  }
850
936
  }
@@ -1023,6 +1109,10 @@ const removeUiPromise = (promise: Deferred<any>) => {
1023
1109
  };
1024
1110
 
1025
1111
  export default class Core extends EventEmitter {
1112
+ private tracingContext: SdkTracingContext;
1113
+
1114
+ public readonly sdkInstanceId: string;
1115
+
1026
1116
  private requestQueue = new RequestQueue();
1027
1117
 
1028
1118
  // background task
@@ -1030,8 +1120,17 @@ export default class Core extends EventEmitter {
1030
1120
 
1031
1121
  private methodSynchronize = getSynchronize();
1032
1122
 
1123
+ constructor() {
1124
+ super();
1125
+ this.tracingContext = createSdkTracingContext();
1126
+ this.sdkInstanceId = this.tracingContext.sdkInstanceId;
1127
+ Log.debug(`[Core] Created SDK instance: ${this.sdkInstanceId}`);
1128
+ }
1129
+
1033
1130
  private getCoreContext() {
1034
1131
  return {
1132
+ sdkInstanceId: this.sdkInstanceId,
1133
+ tracingContext: this.tracingContext,
1035
1134
  requestQueue: this.requestQueue,
1036
1135
  methodSynchronize: this.methodSynchronize,
1037
1136
  getPrePendingCallPromise: () => this.prePendingCallPromise,
@@ -1109,6 +1208,8 @@ export default class Core extends EventEmitter {
1109
1208
  dispose() {
1110
1209
  _deviceList = undefined;
1111
1210
  _connector = undefined;
1211
+ Log.debug(`[Core] Disposing SDK instance: ${this.sdkInstanceId}`);
1212
+ cleanupSdkInstance(this.sdkInstanceId);
1112
1213
  }
1113
1214
  }
1114
1215
 
@@ -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,
@@ -6,6 +6,11 @@ import { patchFeatures, getLogger, LoggerNames, getDeviceType } from '../utils';
6
6
  import type { Device } from './Device';
7
7
  import { DEVICE, type PassphraseRequestPayload } from '../events';
8
8
  import { DeviceModelToTypes } from '../types';
9
+ import {
10
+ formatRequestContext,
11
+ generateInstanceId,
12
+ getActiveRequestsByDeviceInstance,
13
+ } from '../utils/tracing';
9
14
 
10
15
  export type PassphrasePromptResponse = {
11
16
  passphrase?: string;
@@ -114,12 +119,17 @@ export const cancelDeviceWithInitialize = (device: Device) => {
114
119
  };
115
120
 
116
121
  const Log = getLogger(LoggerNames.DeviceCommands);
122
+ const LogCore = getLogger(LoggerNames.Core);
117
123
 
118
124
  /**
119
125
  * The life cycle begins with the acquisition of the device and ends with the disposal device commands
120
126
  * acquire device -> create DeviceCommands -> release device -> dispose DeviceCommands
121
127
  */
122
128
  export class DeviceCommands {
129
+ instanceId: string;
130
+
131
+ currentResponseID?: number;
132
+
123
133
  device: Device;
124
134
 
125
135
  transport: Transport;
@@ -135,6 +145,9 @@ export class DeviceCommands {
135
145
  this.mainId = mainId;
136
146
  this.transport = TransportManager.getTransport();
137
147
  this.disposed = false;
148
+ this.instanceId = generateInstanceId('DeviceCommands', device.sdkInstanceId);
149
+
150
+ Log.debug(`[DeviceCommands] Created: ${this.instanceId}, device: ${this.device.instanceId}`);
138
151
  }
139
152
 
140
153
  async dispose(_cancelRequest: boolean) {
@@ -217,10 +230,10 @@ export class DeviceCommands {
217
230
  const promise = this.transport.call(this.mainId, type, msg) as any;
218
231
  this.callPromise = promise;
219
232
  const res = await promise;
220
- Log.debug('[DeviceCommands] [call] Received', res.type);
233
+ LogCore.debug('[DeviceCommands] [call] Received', res.type);
221
234
  return res;
222
235
  } catch (error) {
223
- Log.debug('[DeviceCommands] [call] Received error', error);
236
+ LogCore.debug('[DeviceCommands] [call] Received error', error);
224
237
  if (error.errorCode === HardwareErrorCode.BleDeviceBondError) {
225
238
  return {
226
239
  type: 'BleDeviceBondError',
@@ -500,7 +513,7 @@ export class DeviceCommands {
500
513
  cancelDeviceInPrompt(this.device, false)
501
514
  .then(onCancel => {
502
515
  const error = ERRORS.TypedError(
503
- HardwareErrorCode.ActionCancelled,
516
+ HardwareErrorCode.CallQueueActionCancelled,
504
517
  `${DEVICE.PIN} canceled`
505
518
  );
506
519
  // onCancel not void
@@ -515,7 +528,15 @@ export class DeviceCommands {
515
528
  reject(error);
516
529
  });
517
530
 
518
- if (this.device.listenerCount(DEVICE.PIN) > 0) {
531
+ const listenerCount = this.device.listenerCount(DEVICE.PIN);
532
+
533
+ Log.debug(`[${this.instanceId}] _promptPin called`, {
534
+ responseID: this.currentResponseID,
535
+ deviceInstanceId: this.device.instanceId,
536
+ listenerCount,
537
+ });
538
+
539
+ if (listenerCount > 0) {
519
540
  this.device.setCancelableAction(cancelAndReject);
520
541
  this.device.emit(DEVICE.PIN, this.device, type, (err, pin) => {
521
542
  this.device.clearCancelableAction();
@@ -526,11 +547,22 @@ export class DeviceCommands {
526
547
  }
527
548
  });
528
549
  } else {
529
- console.warn('[DeviceCommands] [call] PIN callback not configured, cancelling request');
550
+ const activeRequests = getActiveRequestsByDeviceInstance(this.device.instanceId);
551
+ const errorInfo = {
552
+ commandsInstanceId: this.instanceId,
553
+ deviceInstanceId: this.device.instanceId,
554
+ currentResponseID: this.currentResponseID,
555
+ listenerCount,
556
+ activeRequests: activeRequests.map(formatRequestContext),
557
+ };
558
+
559
+ LogCore.error('[DeviceCommands] [call] PIN callback not configured, cancelling request', {
560
+ ...errorInfo,
561
+ });
530
562
  reject(
531
563
  ERRORS.TypedError(
532
564
  HardwareErrorCode.RuntimeError,
533
- '_promptPin: PIN callback not configured'
565
+ `_promptPin: PIN callback not configured: ${JSON.stringify(errorInfo)}`
534
566
  )
535
567
  );
536
568
  }
@@ -543,7 +575,7 @@ export class DeviceCommands {
543
575
  cancelDeviceInPrompt(this.device, false)
544
576
  .then(onCancel => {
545
577
  const error = ERRORS.TypedError(
546
- HardwareErrorCode.ActionCancelled,
578
+ HardwareErrorCode.CallQueueActionCancelled,
547
579
  `${DEVICE.PASSPHRASE} canceled`
548
580
  );
549
581
  // onCancel not void
@@ -574,7 +606,9 @@ export class DeviceCommands {
574
606
  }
575
607
  );
576
608
  } else {
577
- Log.error('[DeviceCommands] [call] Passphrase callback not configured, cancelling request');
609
+ LogCore.error(
610
+ '[DeviceCommands] [call] Passphrase callback not configured, cancelling request'
611
+ );
578
612
  reject(
579
613
  ERRORS.TypedError(
580
614
  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,