@onekeyfe/hd-core 1.1.4-alpha.2 → 1.1.5

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 (62) hide show
  1. package/dist/api/BaseMethod.d.ts +2 -0
  2. package/dist/api/BaseMethod.d.ts.map +1 -1
  3. package/dist/api/allnetwork/AllNetworkGetAddress.d.ts +4 -28
  4. package/dist/api/allnetwork/AllNetworkGetAddress.d.ts.map +1 -1
  5. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts +47 -0
  6. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -0
  7. package/dist/api/allnetwork/AllNetworkGetAddressByLoop.d.ts +8 -0
  8. package/dist/api/allnetwork/AllNetworkGetAddressByLoop.d.ts.map +1 -0
  9. package/dist/api/btc/BTCGetPublicKey.d.ts.map +1 -1
  10. package/dist/api/cosmos/CosmosGetPublicKey.d.ts +1 -1
  11. package/dist/api/cosmos/CosmosGetPublicKey.d.ts.map +1 -1
  12. package/dist/api/device/DeviceUnlock.d.ts +0 -2
  13. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  14. package/dist/api/evm/EVMGetPublicKey.d.ts +1 -0
  15. package/dist/api/evm/EVMGetPublicKey.d.ts.map +1 -1
  16. package/dist/api/index.d.ts +1 -0
  17. package/dist/api/index.d.ts.map +1 -1
  18. package/dist/core/RequestQueue.d.ts +4 -0
  19. package/dist/core/RequestQueue.d.ts.map +1 -1
  20. package/dist/core/index.d.ts +3 -2
  21. package/dist/core/index.d.ts.map +1 -1
  22. package/dist/device/Device.d.ts +4 -1
  23. package/dist/device/Device.d.ts.map +1 -1
  24. package/dist/device/DeviceCommands.d.ts +4 -4
  25. package/dist/events/call.d.ts +9 -0
  26. package/dist/events/call.d.ts.map +1 -1
  27. package/dist/events/core.d.ts +2 -2
  28. package/dist/events/core.d.ts.map +1 -1
  29. package/dist/events/iframe.d.ts +11 -1
  30. package/dist/events/iframe.d.ts.map +1 -1
  31. package/dist/index.d.ts +43 -13
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +406 -150
  34. package/dist/inject.d.ts +3 -0
  35. package/dist/inject.d.ts.map +1 -1
  36. package/dist/types/api/allNetworkGetAddress.d.ts +12 -3
  37. package/dist/types/api/allNetworkGetAddress.d.ts.map +1 -1
  38. package/dist/types/api/evmGetPublicKey.d.ts +1 -0
  39. package/dist/types/api/evmGetPublicKey.d.ts.map +1 -1
  40. package/dist/types/api/index.d.ts +2 -1
  41. package/dist/types/api/index.d.ts.map +1 -1
  42. package/package.json +4 -4
  43. package/src/api/BaseMethod.ts +3 -0
  44. package/src/api/allnetwork/AllNetworkGetAddress.ts +19 -408
  45. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +480 -0
  46. package/src/api/allnetwork/AllNetworkGetAddressByLoop.ts +161 -0
  47. package/src/api/btc/BTCGetPublicKey.ts +13 -0
  48. package/src/api/cosmos/CosmosGetPublicKey.ts +1 -1
  49. package/src/api/device/DeviceUnlock.ts +1 -48
  50. package/src/api/evm/EVMGetPublicKey.ts +9 -3
  51. package/src/api/index.ts +1 -0
  52. package/src/core/RequestQueue.ts +26 -0
  53. package/src/core/index.ts +42 -24
  54. package/src/device/Device.ts +66 -0
  55. package/src/events/call.ts +10 -0
  56. package/src/events/core.ts +7 -1
  57. package/src/events/iframe.ts +12 -1
  58. package/src/index.ts +2 -1
  59. package/src/inject.ts +47 -0
  60. package/src/types/api/allNetworkGetAddress.ts +17 -3
  61. package/src/types/api/evmGetPublicKey.ts +1 -0
  62. package/src/types/api/index.ts +2 -1
@@ -1,59 +1,12 @@
1
1
  import { LockDevice } from '@onekeyfe/hd-transport';
2
- import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
3
- import semver from 'semver';
4
2
  import { BaseMethod } from '../BaseMethod';
5
- import { toHardened } from '../helpers/pathUtils';
6
- import { DeviceFirmwareRange } from '../../types';
7
- import { getDeviceFirmwareVersion, getMethodVersionRange } from '../../utils';
8
3
 
9
4
  export default class DeviceUnlock extends BaseMethod<LockDevice> {
10
5
  init() {
11
6
  this.useDevicePassphraseState = false;
12
7
  }
13
8
 
14
- supportUnlockVersionRange(): DeviceFirmwareRange {
15
- return {
16
- pro: {
17
- min: '4.15.0',
18
- },
19
- };
20
- }
21
-
22
9
  async run() {
23
- const firmwareVersion = getDeviceFirmwareVersion(this.device.features)?.join('.');
24
- const versionRange = getMethodVersionRange(
25
- this.device.features,
26
- type => this.supportUnlockVersionRange()[type]
27
- );
28
-
29
- if (versionRange && semver.gte(firmwareVersion, versionRange.min)) {
30
- const res = await this.device.commands.typedCall('UnLockDevice', 'UnLockDeviceResponse');
31
- if (this.device.features) {
32
- this.device.features.unlocked = res.message.unlocked == null ? null : res.message.unlocked;
33
- this.device.features.unlocked_attach_pin =
34
- res.message.unlocked_attach_pin == null ? undefined : res.message.unlocked_attach_pin;
35
- this.device.features.passphrase_protection =
36
- res.message.passphrase_protection == null ? null : res.message.passphrase_protection;
37
-
38
- return Promise.resolve(this.device.features);
39
- }
40
-
41
- const featuresRes = await this.device.commands.typedCall('GetFeatures', 'Features');
42
- return Promise.resolve(featuresRes.message);
43
- }
44
-
45
- const { type } = await this.device.commands.typedCall('GetAddress', 'Address', {
46
- address_n: [toHardened(44), toHardened(1), toHardened(0), 0, 0],
47
- coin_name: 'Testnet',
48
- script_type: 'SPENDADDRESS',
49
- show_display: false,
50
- });
51
-
52
- // @ts-expect-error
53
- if (type === 'CallMethodError') {
54
- throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Get the passphrase state error');
55
- }
56
- const res = await this.device.commands.typedCall('GetFeatures', 'Features');
57
- return Promise.resolve(res.message);
10
+ return this.device.unlockDevice();
58
11
  }
59
12
  }
@@ -13,6 +13,8 @@ import { batchGetPublickeys } from '../helpers/batchGetPublickeys';
13
13
  export default class EVMGetPublicKey extends BaseMethod<EthereumGetPublicKeyOneKey[]> {
14
14
  hasBundle = false;
15
15
 
16
+ confirmShowOnOneKey = false;
17
+
16
18
  useBatch = false;
17
19
 
18
20
  init() {
@@ -20,9 +22,13 @@ export default class EVMGetPublicKey extends BaseMethod<EthereumGetPublicKeyOneK
20
22
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
21
23
 
22
24
  this.hasBundle = !!this.payload?.bundle;
23
- this.useBatch = this.payload?.bundle?.every(
24
- (item: EVMGetPublicKeyParams) => item.showOnOneKey !== true
25
+
26
+ this.confirmShowOnOneKey = this.payload?.bundle?.some(
27
+ (item: EVMGetPublicKeyParams) => !!item.showOnOneKey
25
28
  );
29
+
30
+ this.useBatch = !this.confirmShowOnOneKey && this.hasBundle && this.payload.useBatch;
31
+
26
32
  const payload = this.hasBundle ? this.payload : { bundle: [this.payload] };
27
33
 
28
34
  // check payload
@@ -66,7 +72,7 @@ export default class EVMGetPublicKey extends BaseMethod<EthereumGetPublicKeyOneK
66
72
  async run() {
67
73
  const responses: EVMPublicKey[] = [];
68
74
 
69
- if (this.useBatch && this.hasBundle && supportBatchPublicKey(this.device?.features)) {
75
+ if (this.useBatch && supportBatchPublicKey(this.device?.features)) {
70
76
  try {
71
77
  const res = await batchGetPublickeys(this.device, this.params, 'secp256k1', 60, {
72
78
  includeNode: false,
package/src/api/index.ts CHANGED
@@ -41,6 +41,7 @@ export { default as promptWebDeviceAccess } from './PromptWebDeviceAccess';
41
41
  export { default as cipherKeyValue } from './CipherKeyValue';
42
42
 
43
43
  export { default as allNetworkGetAddress } from './allnetwork/AllNetworkGetAddress';
44
+ export { default as allNetworkGetAddressByLoop } from './allnetwork/AllNetworkGetAddressByLoop';
44
45
 
45
46
  export { default as btcGetAddress } from './btc/BTCGetAddress';
46
47
  export { default as btcGetPublicKey } from './btc/BTCGetPublicKey';
@@ -13,6 +13,8 @@ export type RequestTask = {
13
13
  export default class RequestQueue {
14
14
  private requestQueue = new Map<number, RequestTask>();
15
15
 
16
+ private pendingCallbackTasks = new Map<string, Deferred<void>>();
17
+
16
18
  // 生成唯一请求ID
17
19
  public generateRequestId = (method?: BaseMethod) => {
18
20
  if (method && method.responseID != null) {
@@ -104,4 +106,28 @@ export default class RequestQueue {
104
106
  public releaseTask(requestId: number) {
105
107
  this.requestQueue.delete(requestId);
106
108
  }
109
+
110
+ public registerPendingCallbackTask(connectId: string, callbackPromise: Deferred<void>) {
111
+ this.pendingCallbackTasks.set(connectId, callbackPromise);
112
+
113
+ callbackPromise.promise.finally(() => {
114
+ Log.debug(`Callback task completed for connectId: ${connectId}`);
115
+ this.pendingCallbackTasks.delete(connectId);
116
+ });
117
+ }
118
+
119
+ public async waitForPendingCallbackTasks(connectId: string): Promise<void> {
120
+ const pendingTask = this.pendingCallbackTasks.get(connectId);
121
+ if (pendingTask) {
122
+ Log.debug(`Waiting for pending callback task to complete for connectId: ${connectId}`);
123
+ await pendingTask.promise;
124
+ }
125
+ }
126
+
127
+ public cancelCallbackTasks(connectId: string) {
128
+ const pendingTask = this.pendingCallbackTasks.get(connectId);
129
+ if (pendingTask) {
130
+ pendingTask.resolve();
131
+ }
132
+ }
107
133
  }
package/src/core/index.ts CHANGED
@@ -58,7 +58,7 @@ import { getSynchronize } from '../utils/getSynchronize';
58
58
 
59
59
  const Log = getLogger(LoggerNames.Core);
60
60
 
61
- type CoreContext = ReturnType<Core['getCoreContext']>;
61
+ export type CoreContext = ReturnType<Core['getCoreContext']>;
62
62
 
63
63
  function hasDeriveCardano(method: BaseMethod): boolean {
64
64
  if (
@@ -201,6 +201,11 @@ const onCallDevice = async (
201
201
  DevicePool.clearDeviceCache(method.payload.connectId);
202
202
  }
203
203
 
204
+ // wait for previous callback tasks to complete (ensure device does not call concurrently)
205
+ if (method.connectId) {
206
+ await context.waitForCallbackTasks(method.connectId);
207
+ }
208
+
204
209
  await waitForPendingPromise(getPrePendingCallPromise, setPrePendingCallPromise);
205
210
 
206
211
  const task = requestQueue.createTask(method);
@@ -231,6 +236,7 @@ const onCallDevice = async (
231
236
 
232
237
  Log.debug('Call API - setDevice: ', device.mainId);
233
238
  method.setDevice?.(device);
239
+ method.context = context;
234
240
 
235
241
  device.on(DEVICE.PIN, onDevicePinHandler);
236
242
  device.on(DEVICE.BUTTON, onDeviceButtonHandler);
@@ -246,6 +252,10 @@ const onCallDevice = async (
246
252
  );
247
253
 
248
254
  try {
255
+ if (method.connectId) {
256
+ await context.waitForCallbackTasks(method.connectId);
257
+ }
258
+
249
259
  await waitForPendingPromise(getPrePendingCallPromise, setPrePendingCallPromise);
250
260
 
251
261
  const inner = async (): Promise<void> => {
@@ -288,28 +298,19 @@ const onCallDevice = async (
288
298
  };
289
299
 
290
300
  // Provide more specific error message based on which version check failed
291
- if (newVersionStatus === 'required' && bleVersionStatus === 'required') {
292
- throw createNewFirmwareForceUpdateHardwareError(
293
- method.connectId,
294
- method.deviceId,
295
- 'both',
296
- currentVersions
297
- );
298
- } else if (newVersionStatus === 'required') {
299
- throw createNewFirmwareForceUpdateHardwareError(
300
- method.connectId,
301
- method.deviceId,
302
- 'firmware',
303
- currentVersions
304
- );
305
- } else {
306
- throw createNewFirmwareForceUpdateHardwareError(
307
- method.connectId,
308
- method.deviceId,
309
- 'ble',
310
- currentVersions
311
- );
301
+ const requiredUpdates: ('firmware' | 'ble')[] = [];
302
+ if (newVersionStatus === 'required') {
303
+ requiredUpdates.push('firmware');
304
+ }
305
+ if (bleVersionStatus === 'required') {
306
+ requiredUpdates.push('ble');
312
307
  }
308
+ throw createNewFirmwareForceUpdateHardwareError(
309
+ method.connectId,
310
+ method.deviceId,
311
+ requiredUpdates,
312
+ currentVersions
313
+ );
313
314
  }
314
315
 
315
316
  if (versionRange) {
@@ -735,6 +736,7 @@ const ensureConnected = async (
735
736
  HardwareErrorCode.BleWriteCharacteristicError,
736
737
  HardwareErrorCode.BleAlreadyConnected,
737
738
  HardwareErrorCode.FirmwareUpdateLimitOneDevice,
739
+ HardwareErrorCode.SelectDevice,
738
740
  HardwareErrorCode.DeviceDetectInBootloaderMode,
739
741
  HardwareErrorCode.BleCharacteristicNotifyChangeFailure,
740
742
  HardwareErrorCode.WebDeviceNotFoundOrNeedsPermission,
@@ -777,6 +779,10 @@ export const cancel = (context: CoreContext, connectId?: string) => {
777
779
  // }
778
780
  // setPrePendingCallPromise(device?.interruptionFromUser());
779
781
  // requestQueue.abortRequestsByConnectId(connectId);
782
+
783
+ // cancel callback tasks
784
+ requestQueue.cancelCallbackTasks(connectId);
785
+
780
786
  const requestIds = requestQueue.getRequestTasksId();
781
787
  Log.debug(
782
788
  `Cancel Api connect requestQueues: length:${requestIds.length} requestIds:${requestIds.join(
@@ -910,7 +916,7 @@ const onDevicePinHandler = async (...[device, type, callback]: DeviceEvents['pin
910
916
  callback(null, uiResp.payload);
911
917
  };
912
918
 
913
- const onDeviceButtonHandler = (...[device, request]: [...DeviceEvents['button']]) => {
919
+ export const onDeviceButtonHandler = (...[device, request]: [...DeviceEvents['button']]) => {
914
920
  postMessage(createDeviceMessage(DEVICE.BUTTON, { ...request, device: device.toMessageObject() }));
915
921
 
916
922
  if (request.code === 'ButtonRequest_PinEntry' || request.code === 'ButtonRequest_AttachPin') {
@@ -1014,7 +1020,7 @@ const removeUiPromise = (promise: Deferred<any>) => {
1014
1020
  export default class Core extends EventEmitter {
1015
1021
  private requestQueue = new RequestQueue();
1016
1022
 
1017
- // 上一个请求的 promise 完成,后续需要清理的工作,需要在下一次请求前完成
1023
+ // background task
1018
1024
  private prePendingCallPromise: Promise<void> | undefined;
1019
1025
 
1020
1026
  private methodSynchronize = getSynchronize();
@@ -1027,6 +1033,13 @@ export default class Core extends EventEmitter {
1027
1033
  setPrePendingCallPromise: (promise: Promise<void> | undefined) => {
1028
1034
  this.prePendingCallPromise = promise;
1029
1035
  },
1036
+ // callback 任务管理
1037
+ registerCallbackTask: (connectId: string, callbackPromise: Deferred<any>) => {
1038
+ this.requestQueue.registerPendingCallbackTask(connectId, callbackPromise);
1039
+ },
1040
+ waitForCallbackTasks: (connectId: string) =>
1041
+ this.requestQueue.waitForPendingCallbackTasks(connectId),
1042
+ cancelCallbackTasks: (connectId: string) => this.requestQueue.cancelCallbackTasks(connectId),
1030
1043
  };
1031
1044
  }
1032
1045
 
@@ -1077,6 +1090,11 @@ export default class Core extends EventEmitter {
1077
1090
  cancel(this.getCoreContext(), message.payload.connectId);
1078
1091
  break;
1079
1092
  }
1093
+ case IFRAME.CALLBACK: {
1094
+ Log.log('callback message: ', message);
1095
+ postMessage(message);
1096
+ break;
1097
+ }
1080
1098
  default:
1081
1099
  break;
1082
1100
  }
@@ -1,4 +1,5 @@
1
1
  import EventEmitter from 'events';
2
+ import semver from 'semver';
2
3
  import { OneKeyDeviceInfo as DeviceDescriptor } from '@onekeyfe/hd-transport';
3
4
  import {
4
5
  createDeferred,
@@ -16,6 +17,7 @@ import {
16
17
  getDeviceType,
17
18
  getDeviceUUID,
18
19
  getLogger,
20
+ getMethodVersionRange,
19
21
  LoggerNames,
20
22
  } from '../utils';
21
23
  import {
@@ -28,6 +30,7 @@ import type DeviceConnector from './DeviceConnector';
28
30
  import { DeviceCommands, PassphrasePromptResponse } from './DeviceCommands';
29
31
 
30
32
  import {
33
+ type DeviceFirmwareRange,
31
34
  EOneKeyDeviceMode,
32
35
  type Device as DeviceTyped,
33
36
  type Features,
@@ -43,6 +46,7 @@ import {
43
46
  import { PROTO } from '../constants';
44
47
  import { DataManager } from '../data-manager';
45
48
  import TransportManager from '../data-manager/TransportManager';
49
+ import { toHardened } from '../api/helpers/pathUtils';
46
50
 
47
51
  export type InitOptions = {
48
52
  initSession?: boolean;
@@ -151,6 +155,8 @@ export class Device extends EventEmitter {
151
155
 
152
156
  passphraseState: string | undefined = undefined;
153
157
 
158
+ pendingCallbackPromise?: Deferred<void>;
159
+
154
160
  constructor(descriptor: DeviceDescriptor) {
155
161
  super();
156
162
  this.originalDescriptor = descriptor;
@@ -264,6 +270,18 @@ export class Device extends EventEmitter {
264
270
  (this.isUsedHere() && !this.keepSession && this.mainId) ||
265
271
  (this.mainId && DataManager.isBleConnect(env))
266
272
  ) {
273
+ // wait for callback tasks to complete before releasing device
274
+ if (this.pendingCallbackPromise) {
275
+ try {
276
+ Log.debug(
277
+ 'Waiting for callback tasks to complete before releasing device (in release method)'
278
+ );
279
+ await this.pendingCallbackPromise.promise;
280
+ } catch (error) {
281
+ Log.error('Error waiting for callback tasks in release method:', error);
282
+ }
283
+ }
284
+
267
285
  if (this.commands) {
268
286
  this.commands.dispose(false);
269
287
  if (this.commands.callPromise) {
@@ -732,6 +750,54 @@ export class Device extends EventEmitter {
732
750
  return res.message;
733
751
  }
734
752
 
753
+ supportUnlockVersionRange(): DeviceFirmwareRange {
754
+ return {
755
+ pro: {
756
+ min: '4.15.0',
757
+ },
758
+ };
759
+ }
760
+
761
+ async unlockDevice() {
762
+ const firmwareVersion = getDeviceFirmwareVersion(this.features)?.join('.');
763
+ const versionRange = getMethodVersionRange(
764
+ this.features,
765
+ type => this.supportUnlockVersionRange()[type]
766
+ );
767
+
768
+ if (versionRange && semver.gte(firmwareVersion, versionRange.min)) {
769
+ const res = await this.commands.typedCall('UnLockDevice', 'UnLockDeviceResponse');
770
+ if (this.features) {
771
+ this.features.unlocked = res.message.unlocked == null ? null : res.message.unlocked;
772
+ this.features.unlocked_attach_pin =
773
+ res.message.unlocked_attach_pin == null ? undefined : res.message.unlocked_attach_pin;
774
+ this.features.passphrase_protection =
775
+ res.message.passphrase_protection == null ? null : res.message.passphrase_protection;
776
+
777
+ return Promise.resolve(this.features);
778
+ }
779
+
780
+ const featuresRes = await this.commands.typedCall('GetFeatures', 'Features');
781
+ this._updateFeatures(featuresRes.message);
782
+ return Promise.resolve(featuresRes.message);
783
+ }
784
+
785
+ const { type } = await this.commands.typedCall('GetAddress', 'Address', {
786
+ address_n: [toHardened(44), toHardened(1), toHardened(0), 0, 0],
787
+ coin_name: 'Testnet',
788
+ script_type: 'SPENDADDRESS',
789
+ show_display: false,
790
+ });
791
+
792
+ // @ts-expect-error
793
+ if (type === 'CallMethodError') {
794
+ throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'unlock device error');
795
+ }
796
+ const res = await this.commands.typedCall('GetFeatures', 'Features');
797
+ this._updateFeatures(res.message);
798
+ return Promise.resolve(res.message);
799
+ }
800
+
735
801
  async checkPassphraseStateSafety(
736
802
  passphraseState?: string,
737
803
  useEmptyPassphrase?: boolean,
@@ -58,6 +58,16 @@ export interface IFrameSwitchTransportMessage {
58
58
  payload: { env: ConnectSettings['env'] };
59
59
  }
60
60
 
61
+ export interface IFrameCallbackMessage {
62
+ event: typeof IFRAME.CALLBACK;
63
+ type: typeof IFRAME.CALLBACK;
64
+ payload: {
65
+ callbackId: string;
66
+ data?: any;
67
+ error?: any;
68
+ };
69
+ }
70
+
61
71
  export const RESPONSE_EVENT = 'RESPONSE_EVENT';
62
72
 
63
73
  export interface MethodResponseMessage {
@@ -1,6 +1,11 @@
1
1
  import { HardwareError } from '@onekeyfe/hd-shared';
2
2
  import { Unsuccessful } from '../types/params';
3
- import { IFrameCallMessage, IFrameCancelMessage, IFrameSwitchTransportMessage } from './call';
3
+ import {
4
+ IFrameCallMessage,
5
+ IFrameCancelMessage,
6
+ IFrameSwitchTransportMessage,
7
+ IFrameCallbackMessage,
8
+ } from './call';
4
9
  import { DeviceEventMessage } from './device';
5
10
  import { IFrameEventMessage } from './iframe';
6
11
  import { UiEventMessage } from './ui-request';
@@ -18,6 +23,7 @@ export type CoreMessage = {
18
23
  | IFrameCallMessage
19
24
  | IFrameCancelMessage
20
25
  | IFrameSwitchTransportMessage
26
+ | IFrameCallbackMessage
21
27
  | UiResponseMessage
22
28
  | UiEventMessage
23
29
  | DeviceEventMessage
@@ -8,6 +8,7 @@ export const IFRAME = {
8
8
  CALL: 'iframe-call',
9
9
  CANCEL: 'iframe-cancel',
10
10
  SWITCH_TRANSPORT: 'iframe-switch-transport',
11
+ CALLBACK: 'iframe-callback',
11
12
  } as const;
12
13
 
13
14
  export interface IFrameInit {
@@ -29,7 +30,17 @@ export interface IFrameSwitchTransport {
29
30
  };
30
31
  }
31
32
 
32
- export type IFrameEvent = IFrameInit | IFrameBridge | IFrameSwitchTransport;
33
+ export interface IFrameCallback {
34
+ type: typeof IFRAME.CALLBACK;
35
+ payload: {
36
+ callbackId: string;
37
+ data?: any;
38
+ error?: any;
39
+ finished?: boolean;
40
+ };
41
+ }
42
+
43
+ export type IFrameEvent = IFrameInit | IFrameBridge | IFrameSwitchTransport | IFrameCallback;
33
44
  export type IFrameEventMessage = IFrameEvent & { event: typeof UI_EVENT };
34
45
 
35
46
  export const createIFrameMessage: MessageFactoryFn<typeof UI_EVENT, IFrameEvent> = (
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { inject, InjectApi } from './inject';
1
+ import { inject, InjectApi, executeCallback, cleanupCallback } from './inject';
2
2
  import { lowLevelInject, LowLevelInjectApi, LowLevelCoreApi } from './lowLevelInject';
3
3
  import { topLevelInject } from './topLevelInject';
4
4
  import { CoreApi } from './types/api';
@@ -14,6 +14,7 @@ export * from './data-manager';
14
14
  export * from './events';
15
15
  export * from './types';
16
16
  export { whitelist, whitelistExtension } from './data/config';
17
+ export { executeCallback, cleanupCallback };
17
18
 
18
19
  const HardwareSdk = ({
19
20
  init,
package/src/inject.ts CHANGED
@@ -1,6 +1,31 @@
1
1
  import { EventEmitter } from 'events';
2
2
  import { CallMethod } from './events';
3
3
  import { CoreApi } from './types/api';
4
+ import type { AllNetworkAddress } from './types/api/allNetworkGetAddress';
5
+
6
+ type CallbackFunction = (data?: any, error?: { message: string; code?: number }) => void;
7
+
8
+ const callbackManager = new Map<string, CallbackFunction>();
9
+
10
+ const generateCallbackId = () =>
11
+ `callback_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
12
+
13
+ const registerCallback = (id: string, callback: CallbackFunction) => {
14
+ callbackManager.set(id, callback);
15
+ };
16
+
17
+ const executeCallback = (id: string, ...args: any[]) => {
18
+ const callback = callbackManager.get(id);
19
+ if (callback) {
20
+ callback(...args);
21
+ }
22
+ };
23
+
24
+ const cleanupCallback = (id: string) => {
25
+ callbackManager.delete(id);
26
+ };
27
+
28
+ export { executeCallback, cleanupCallback };
4
29
 
5
30
  export interface InjectApi {
6
31
  call: CallMethod;
@@ -147,6 +172,28 @@ export const createCoreApi = (
147
172
 
148
173
  allNetworkGetAddress: (connectId, deviceId, params) =>
149
174
  call({ ...params, connectId, deviceId, method: 'allNetworkGetAddress' }),
175
+ allNetworkGetAddressByLoop: (connectId, deviceId, params) => {
176
+ const { onLoopItemResponse, onAllItemsResponse, ...restParams } = params;
177
+
178
+ const callbackId = generateCallbackId();
179
+ registerCallback(callbackId, onLoopItemResponse);
180
+
181
+ const callbackIdFinish = generateCallbackId();
182
+ registerCallback(callbackIdFinish, (data?: AllNetworkAddress[]) => {
183
+ onAllItemsResponse?.(data);
184
+ cleanupCallback(callbackIdFinish);
185
+ cleanupCallback(callbackId);
186
+ });
187
+
188
+ return call({
189
+ ...restParams,
190
+ connectId,
191
+ deviceId,
192
+ method: 'allNetworkGetAddressByLoop',
193
+ callbackId,
194
+ callbackIdFinish,
195
+ });
196
+ },
150
197
 
151
198
  evmGetAddress: (connectId, deviceId, params) =>
152
199
  call({ ...params, connectId, deviceId, method: 'evmGetAddress' }),
@@ -1,4 +1,4 @@
1
- import type { CommonParams, Response } from '../params';
1
+ import type { CommonParams, Response, Unsuccessful } from '../params';
2
2
  import type { CardanoAddressParameters } from './cardano';
3
3
 
4
4
  export type INetwork =
@@ -91,10 +91,10 @@ type AllNetworkAddressPayload =
91
91
  xpubSegwit: string;
92
92
  };
93
93
 
94
- export type AllNetworkAddress = CommonResponseParams & {
94
+ export type AllNetworkAddress = AllNetworkAddressParams & {
95
95
  success: boolean;
96
96
  payload?:
97
- | AllNetworkAddressPayload
97
+ | (AllNetworkAddressPayload & { rootFingerprint: number })
98
98
  | {
99
99
  error: string;
100
100
  code: number;
@@ -108,8 +108,22 @@ export type AllNetworkGetAddressParams = {
108
108
  bundle: AllNetworkAddressParams[];
109
109
  };
110
110
 
111
+ export type AllNetworkGetAddressParamsByLoop = AllNetworkGetAddressParams & {
112
+ callbackId?: string;
113
+ callbackIdFinish?: string;
114
+ onLoopItemResponse: (data?: AllNetworkAddress) => void;
115
+ onAllItemsResponse: (data?: AllNetworkAddress[], error?: Unsuccessful) => void;
116
+ };
117
+
111
118
  export declare function allNetworkGetAddress(
112
119
  connectId: string,
113
120
  deviceId: string,
114
121
  params: CommonParams & AllNetworkGetAddressParams
115
122
  ): Response<AllNetworkAddress[]>;
123
+
124
+ export declare function allNetworkGetAddressByLoop(
125
+ connectId: string,
126
+ deviceId: string,
127
+ params: CommonParams & AllNetworkGetAddressParamsByLoop
128
+ // only return empty array
129
+ ): Response<AllNetworkAddress[]>;
@@ -14,6 +14,7 @@ export type EVMGetPublicKeyParams = {
14
14
  path: string | number[];
15
15
  showOnOneKey?: boolean;
16
16
  chainId?: number;
17
+ useBatch?: boolean;
17
18
  };
18
19
 
19
20
  export declare function evmGetPublicKey(
@@ -43,7 +43,7 @@ import { setU2FCounter } from './setU2FCounter';
43
43
 
44
44
  import { cipherKeyValue } from './cipherKeyValue';
45
45
 
46
- import { allNetworkGetAddress } from './allNetworkGetAddress';
46
+ import { allNetworkGetAddress, allNetworkGetAddressByLoop } from './allNetworkGetAddress';
47
47
 
48
48
  import { evmGetAddress } from './evmGetAddress';
49
49
  import { evmGetPublicKey } from './evmGetPublicKey';
@@ -230,6 +230,7 @@ export type CoreApi = {
230
230
  * All network function
231
231
  */
232
232
  allNetworkGetAddress: typeof allNetworkGetAddress;
233
+ allNetworkGetAddressByLoop: typeof allNetworkGetAddressByLoop;
233
234
 
234
235
  /**
235
236
  * EVM function