@onekeyfe/hd-transport 1.2.0-alpha.13 → 1.2.0-alpha.131

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 (59) hide show
  1. package/__tests__/messages.test.js +144 -4
  2. package/__tests__/protocol-v2-ble-frame-writer.test.js +119 -0
  3. package/__tests__/protocol-v2-link-manager.test.js +176 -9
  4. package/__tests__/protocol-v2-usb-transport-base.test.js +36 -2
  5. package/__tests__/protocol-v2.test.js +540 -108
  6. package/__tests__/transport-log.test.js +79 -0
  7. package/dist/constants.d.ts +3 -1
  8. package/dist/constants.d.ts.map +1 -1
  9. package/dist/index.d.ts +645 -217
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +679 -153
  12. package/dist/protocols/index.d.ts +17 -1
  13. package/dist/protocols/index.d.ts.map +1 -1
  14. package/dist/protocols/v2/ble-frame-writer.d.ts +15 -0
  15. package/dist/protocols/v2/ble-frame-writer.d.ts.map +1 -0
  16. package/dist/protocols/v2/decode.d.ts +11 -0
  17. package/dist/protocols/v2/decode.d.ts.map +1 -1
  18. package/dist/protocols/v2/errors.d.ts +16 -0
  19. package/dist/protocols/v2/errors.d.ts.map +1 -0
  20. package/dist/protocols/v2/frame-assembler.d.ts.map +1 -1
  21. package/dist/protocols/v2/index.d.ts +2 -0
  22. package/dist/protocols/v2/index.d.ts.map +1 -1
  23. package/dist/protocols/v2/link-manager.d.ts +5 -0
  24. package/dist/protocols/v2/link-manager.d.ts.map +1 -1
  25. package/dist/protocols/v2/session.d.ts +14 -4
  26. package/dist/protocols/v2/session.d.ts.map +1 -1
  27. package/dist/protocols/v2/usb-transport-base.d.ts +2 -0
  28. package/dist/protocols/v2/usb-transport-base.d.ts.map +1 -1
  29. package/dist/serialization/protobuf/decode.d.ts.map +1 -1
  30. package/dist/serialization/protobuf/encode.d.ts.map +1 -1
  31. package/dist/types/messages.d.ts +301 -156
  32. package/dist/types/messages.d.ts.map +1 -1
  33. package/dist/types/transport.d.ts +21 -3
  34. package/dist/types/transport.d.ts.map +1 -1
  35. package/dist/utils/transportLog.d.ts +9 -0
  36. package/dist/utils/transportLog.d.ts.map +1 -0
  37. package/messages-protocol-v2.json +523 -449
  38. package/package.json +2 -2
  39. package/scripts/protobuf-build.sh +112 -32
  40. package/scripts/protobuf-patches/index.js +1 -0
  41. package/scripts/protobuf-types.js +10 -1
  42. package/src/constants.ts +30 -16
  43. package/src/index.ts +5 -1
  44. package/src/protocols/index.ts +114 -3
  45. package/src/protocols/v2/ble-frame-writer.ts +77 -0
  46. package/src/protocols/v2/crc8.ts +1 -1
  47. package/src/protocols/v2/decode.ts +49 -12
  48. package/src/protocols/v2/encode.ts +1 -1
  49. package/src/protocols/v2/errors.ts +54 -0
  50. package/src/protocols/v2/frame-assembler.ts +6 -4
  51. package/src/protocols/v2/index.ts +2 -0
  52. package/src/protocols/v2/link-manager.ts +65 -5
  53. package/src/protocols/v2/session.ts +224 -80
  54. package/src/protocols/v2/usb-transport-base.ts +42 -10
  55. package/src/serialization/protobuf/decode.ts +4 -1
  56. package/src/serialization/protobuf/encode.ts +5 -1
  57. package/src/types/messages.ts +375 -198
  58. package/src/types/transport.ts +30 -3
  59. package/src/utils/transportLog.ts +102 -0
@@ -1,5 +1,15 @@
1
1
  import type EventEmitter from 'events';
2
2
 
3
+ export const TRANSPORT_EVENT = {
4
+ DEVICE_DISCONNECT: 'transport-device-disconnect',
5
+ } as const;
6
+
7
+ export type TransportDeviceDisconnectEvent = {
8
+ id: string;
9
+ connectId: string;
10
+ name: string | null;
11
+ };
12
+
3
13
  export type ProtocolType = 'V1' | 'V2';
4
14
 
5
15
  export type OneKeyDeviceCommType =
@@ -43,15 +53,27 @@ export type AcquireInput = {
43
53
  uuid?: string;
44
54
  forceCleanRunPromise?: boolean;
45
55
  expectedProtocol?: ProtocolType;
56
+ protocolHint?: ProtocolType;
46
57
  };
47
58
 
48
59
  export type MessageFromOneKey = { type: string; message: Record<string, any> };
49
60
 
61
+ export type TransportWriteMetrics = {
62
+ elapsedMs: number;
63
+ frameBytes: number;
64
+ };
65
+
50
66
  export type TransportCallOptions = {
51
67
  timeoutMs?: number;
52
68
  expectedTypes?: string[];
53
69
  intermediateTypes?: string[];
54
70
  onIntermediateResponse?: (response: MessageFromOneKey) => void;
71
+ /** Called after the complete request frame has been submitted to the transport. */
72
+ onWriteCompleted?: (metrics: TransportWriteMetrics) => void;
73
+ /** Resolve after the complete request frame is written without waiting for a response. */
74
+ returnAfterWrite?: boolean;
75
+ /** Prefer acknowledged BLE characteristic writes for this call when supported. */
76
+ writeWithResponse?: boolean;
55
77
  };
56
78
 
57
79
  type ITransportInitFn = (
@@ -64,7 +86,12 @@ export type Transport = {
64
86
  enumerate(): Promise<Array<OneKeyDeviceInfo>>;
65
87
  listen(old?: Array<OneKeyDeviceInfo>): Promise<Array<OneKeyDeviceInfo>>;
66
88
  acquire(input: AcquireInput): Promise<string>;
67
- release(session: string, onclose: boolean): Promise<void>;
89
+ /**
90
+ * `keepSession` tells a transport that the caller intends to keep using this
91
+ * device across calls (firmware update, batched signing). Transports that
92
+ * hold the link open may use it to pick a longer idle window; the rest ignore it.
93
+ */
94
+ release(session: string, onclose: boolean, keepSession?: boolean): Promise<void>;
68
95
  configure(signedData: JSON | string): Promise<void>;
69
96
  configureProtocolV2?: (signedData: JSON | string) => Promise<void> | void;
70
97
  call(
@@ -92,7 +119,7 @@ export type Transport = {
92
119
 
93
120
  // resolves when the transport can be used; rejects when it cannot
94
121
  init: ITransportInitFn;
95
- stop(): void;
122
+ stop(): void | Promise<void>;
96
123
 
97
124
  configured: boolean;
98
125
  version: string;
@@ -105,7 +132,7 @@ export type Transport = {
105
132
  export type LowLevelDevice = OneKeyDeviceInfoBase & { id: string; name: string };
106
133
  export type LowlevelTransportSharedPlugin = {
107
134
  enumerate: () => Promise<LowLevelDevice[]>;
108
- send: (uuid: string, data: string) => Promise<void>;
135
+ send: (uuid: string, data: string, options?: { withoutResponse?: boolean }) => Promise<void>;
109
136
  receive: (uuid?: string) => Promise<string>;
110
137
  connect: (uuid: string) => Promise<void>;
111
138
  disconnect: (uuid: string) => Promise<void>;
@@ -0,0 +1,102 @@
1
+ import type { ProtocolType } from '../types';
2
+
3
+ const REDACTED = '[REDACTED]';
4
+
5
+ const SENSITIVE_LOG_KEYS = new Set([
6
+ 'accesstoken',
7
+ 'address',
8
+ 'apikey',
9
+ 'connectid',
10
+ 'devicestate',
11
+ 'deviceid',
12
+ 'entropy',
13
+ 'expectedpassphrasestate',
14
+ 'mnemonic',
15
+ 'passphrase',
16
+ 'passphrasestate',
17
+ 'password',
18
+ 'pin',
19
+ 'privatekey',
20
+ 'publickey',
21
+ 'seed',
22
+ 'serialnumber',
23
+ 'session',
24
+ 'sessionid',
25
+ 'signature',
26
+ 'token',
27
+ 'uuid',
28
+ 'walletsessionid',
29
+ 'xprv',
30
+ 'xpub',
31
+ ]);
32
+
33
+ const normalizeLogKey = (key: string) => key.replace(/[_-]/g, '').toLowerCase();
34
+
35
+ const isSensitiveLogKey = (key: string) => {
36
+ const normalizedKey = normalizeLogKey(key);
37
+ return (
38
+ SENSITIVE_LOG_KEYS.has(normalizedKey) ||
39
+ normalizedKey.endsWith('address') ||
40
+ normalizedKey.endsWith('privatekey') ||
41
+ normalizedKey.endsWith('publickey') ||
42
+ normalizedKey.endsWith('signature')
43
+ );
44
+ };
45
+
46
+ const isSigningMessage = (messageName?: string) =>
47
+ Boolean(messageName && /(?:sign|txack|transaction)/i.test(messageName));
48
+
49
+ const redactLogValue = (value: unknown, seen: WeakSet<object>): unknown => {
50
+ if (ArrayBuffer.isView(value)) {
51
+ return `[BINARY:${value.byteLength}]`;
52
+ }
53
+ if (value instanceof ArrayBuffer) {
54
+ return `[BINARY:${value.byteLength}]`;
55
+ }
56
+ if (Array.isArray(value)) {
57
+ return value.map(item => redactLogValue(item, seen));
58
+ }
59
+ if (!value || typeof value !== 'object') {
60
+ return value;
61
+ }
62
+ if (seen.has(value)) {
63
+ return '[CIRCULAR]';
64
+ }
65
+
66
+ seen.add(value);
67
+ const redacted = Object.fromEntries(
68
+ Object.entries(value as Record<string, unknown>).map(([key, item]) => [
69
+ key,
70
+ isSensitiveLogKey(key) && item !== null && item !== undefined
71
+ ? REDACTED
72
+ : redactLogValue(item, seen),
73
+ ])
74
+ );
75
+ seen.delete(value);
76
+ return redacted;
77
+ };
78
+
79
+ export function getSafeTransportLogPayload(value: unknown, messageName?: string): unknown {
80
+ if (isSigningMessage(messageName)) {
81
+ return REDACTED;
82
+ }
83
+ return redactLogValue(value, new WeakSet());
84
+ }
85
+
86
+ export function createTransportCallLog(
87
+ name: string,
88
+ protocol: ProtocolType,
89
+ data: Record<string, unknown>
90
+ ) {
91
+ return {
92
+ name,
93
+ protocol,
94
+ request: getSafeTransportLogPayload(data, name),
95
+ };
96
+ }
97
+
98
+ const HIGH_VOLUME_CALLS = new Set(['FileWrite', 'FilesystemFileWrite', 'EmmcFileWrite']);
99
+
100
+ export function shouldSuppressHighVolumeCallLog(name: string) {
101
+ return HIGH_VOLUME_CALLS.has(name);
102
+ }