@onekeyfe/hd-transport 1.2.0-alpha.2 → 1.2.0-alpha.4
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/README.md +1 -1
- package/__tests__/messages.test.js +8 -0
- package/__tests__/protocol-v2.test.js +137 -77
- package/dist/constants.d.ts +2 -2
- package/dist/index.d.ts +391 -323
- package/dist/index.js +77 -68
- package/dist/protocols/index.d.ts.map +1 -1
- package/dist/protocols/v2/session.d.ts +1 -1
- package/dist/protocols/v2/session.d.ts.map +1 -1
- package/dist/serialization/protobuf/messages.d.ts.map +1 -1
- package/dist/types/messages.d.ts +280 -222
- package/dist/types/messages.d.ts.map +1 -1
- package/messages-protocol-v2.json +1224 -1804
- package/package.json +2 -2
- package/scripts/protobuf-build.sh +51 -143
- package/src/constants.ts +2 -2
- package/src/protocols/index.ts +1 -0
- package/src/protocols/v2/session.ts +4 -5
- package/src/serialization/protobuf/messages.ts +6 -1
- package/src/types/messages.ts +351 -280
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ In order to be able to use new features of onekey-firmware you need to update pr
|
|
|
20
20
|
1. `yarn update-submodules` to update firmware submodule
|
|
21
21
|
1. `yarn update-protobuf` to generate new `./messages.json`, `./messages-protocol-v2.json` and `./src/types/messages.ts`
|
|
22
22
|
|
|
23
|
-
The same task can be run from the repository root with `yarn update-protobuf`. The Protocol V2 schema requires the `firmware-pro2` submodule checked out on branch `
|
|
23
|
+
The same task can be run from the repository root with `yarn update-protobuf`. The Protocol V2 schema requires the `firmware-pro2` submodule checked out on branch `dev`.
|
|
24
24
|
|
|
25
25
|
## Docs
|
|
26
26
|
|
|
@@ -70,6 +70,14 @@ describe('messages', () => {
|
|
|
70
70
|
expect(() => createMessageFromType(messages, 0)).not.toThrow();
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
+
test('createMessageFromType throws a readable error for unknown ids', () => {
|
|
74
|
+
const messages = parseConfigure(json);
|
|
75
|
+
|
|
76
|
+
expect(() => createMessageFromType(messages, 99999)).toThrow(
|
|
77
|
+
'MessageType id "99999" is not defined in protobuf schema'
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
73
81
|
test('createMessageFromName (wire_type case)', () => {
|
|
74
82
|
const messages = parseConfigure(json);
|
|
75
83
|
const name = 'TxAckInput';
|
|
@@ -15,6 +15,18 @@ const protocolV1Messages = parseConfigure({
|
|
|
15
15
|
},
|
|
16
16
|
},
|
|
17
17
|
},
|
|
18
|
+
Failure: {
|
|
19
|
+
fields: {
|
|
20
|
+
code: {
|
|
21
|
+
type: 'uint32',
|
|
22
|
+
id: 1,
|
|
23
|
+
},
|
|
24
|
+
message: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
id: 2,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
18
30
|
ButtonRequest: {
|
|
19
31
|
fields: {
|
|
20
32
|
code: {
|
|
@@ -32,6 +44,7 @@ const protocolV1Messages = parseConfigure({
|
|
|
32
44
|
MessageType: {
|
|
33
45
|
values: {
|
|
34
46
|
MessageType_Success: 2,
|
|
47
|
+
MessageType_Failure: 3,
|
|
35
48
|
MessageType_ButtonRequest: 26,
|
|
36
49
|
MessageType_OnekeyGetFeatures: 10025,
|
|
37
50
|
MessageType_OnekeyFeatures: 10026,
|
|
@@ -42,21 +55,22 @@ const protocolV1Messages = parseConfigure({
|
|
|
42
55
|
|
|
43
56
|
const protocolV2Messages = parseConfigure({
|
|
44
57
|
nested: {
|
|
45
|
-
|
|
58
|
+
ProtocolInfoRequest: {
|
|
46
59
|
fields: {},
|
|
47
60
|
},
|
|
48
|
-
|
|
61
|
+
ProtocolInfo: {
|
|
49
62
|
fields: {
|
|
50
|
-
|
|
63
|
+
version: {
|
|
51
64
|
type: 'uint32',
|
|
52
65
|
id: 1,
|
|
53
66
|
},
|
|
54
|
-
|
|
67
|
+
supported_messages: {
|
|
55
68
|
type: 'uint32',
|
|
56
69
|
id: 2,
|
|
70
|
+
rule: 'repeated',
|
|
57
71
|
},
|
|
58
|
-
|
|
59
|
-
type: '
|
|
72
|
+
protobuf_definition: {
|
|
73
|
+
type: 'string',
|
|
60
74
|
id: 3,
|
|
61
75
|
},
|
|
62
76
|
},
|
|
@@ -77,18 +91,53 @@ const protocolV2Messages = parseConfigure({
|
|
|
77
91
|
},
|
|
78
92
|
},
|
|
79
93
|
},
|
|
80
|
-
|
|
81
|
-
fields: {
|
|
94
|
+
DeviceFirmwareTarget: {
|
|
95
|
+
fields: {
|
|
96
|
+
target_id: {
|
|
97
|
+
type: 'uint32',
|
|
98
|
+
id: 1,
|
|
99
|
+
},
|
|
100
|
+
path: {
|
|
101
|
+
type: 'string',
|
|
102
|
+
id: 2,
|
|
103
|
+
},
|
|
104
|
+
},
|
|
82
105
|
},
|
|
83
|
-
|
|
106
|
+
DeviceFirmwareUpdateRequest: {
|
|
107
|
+
fields: {
|
|
108
|
+
targets: {
|
|
109
|
+
type: 'DeviceFirmwareTarget',
|
|
110
|
+
id: 1,
|
|
111
|
+
rule: 'repeated',
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
DeviceFirmwareUpdateRecord: {
|
|
84
116
|
fields: {
|
|
85
117
|
target_id: {
|
|
86
118
|
type: 'uint32',
|
|
87
119
|
id: 1,
|
|
88
120
|
},
|
|
89
|
-
|
|
121
|
+
status: {
|
|
90
122
|
type: 'uint32',
|
|
91
|
-
id:
|
|
123
|
+
id: 10,
|
|
124
|
+
},
|
|
125
|
+
payload_version: {
|
|
126
|
+
type: 'uint32',
|
|
127
|
+
id: 20,
|
|
128
|
+
},
|
|
129
|
+
path: {
|
|
130
|
+
type: 'string',
|
|
131
|
+
id: 30,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
DeviceFirmwareUpdateStatus: {
|
|
136
|
+
fields: {
|
|
137
|
+
records: {
|
|
138
|
+
type: 'DeviceFirmwareUpdateRecord',
|
|
139
|
+
id: 1,
|
|
140
|
+
rule: 'repeated',
|
|
92
141
|
},
|
|
93
142
|
},
|
|
94
143
|
},
|
|
@@ -117,13 +166,13 @@ const protocolV2Messages = parseConfigure({
|
|
|
117
166
|
},
|
|
118
167
|
MessageType: {
|
|
119
168
|
values: {
|
|
120
|
-
|
|
121
|
-
|
|
169
|
+
MessageType_ProtocolInfoRequest: 60200,
|
|
170
|
+
MessageType_ProtocolInfo: 60201,
|
|
122
171
|
MessageType_Ping: 60206,
|
|
123
172
|
MessageType_Success: 60207,
|
|
124
173
|
MessageType_FileWrite: 60805,
|
|
125
|
-
|
|
126
|
-
|
|
174
|
+
MessageType_DeviceFirmwareUpdateRequest: 61000,
|
|
175
|
+
MessageType_DeviceFirmwareUpdateStatus: 61002,
|
|
127
176
|
MessageType_PartialNested: 62000,
|
|
128
177
|
},
|
|
129
178
|
},
|
|
@@ -144,10 +193,10 @@ const rewriteSeq = (frame, seq) => {
|
|
|
144
193
|
|
|
145
194
|
describe('Protocol V2 framing and session', () => {
|
|
146
195
|
test('encodes and decodes Protocol V2 protobuf frames', () => {
|
|
147
|
-
const frame = ProtocolV2.encodeFrame(schemas, '
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
196
|
+
const frame = ProtocolV2.encodeFrame(schemas, 'ProtocolInfo', {
|
|
197
|
+
version: 1,
|
|
198
|
+
supported_messages: [60200, 60201],
|
|
199
|
+
protobuf_definition: 'proto',
|
|
151
200
|
});
|
|
152
201
|
|
|
153
202
|
const parsed = protocolV2.decodeFrame(frame);
|
|
@@ -155,15 +204,15 @@ describe('Protocol V2 framing and session', () => {
|
|
|
155
204
|
|
|
156
205
|
const decoded = ProtocolV2.decodeFrame(schemas, frame);
|
|
157
206
|
expect(decoded).toEqual({
|
|
158
|
-
type: '
|
|
159
|
-
messageName: '
|
|
207
|
+
type: 'ProtocolInfo',
|
|
208
|
+
messageName: 'ProtocolInfo',
|
|
160
209
|
messageTypeId: 60201,
|
|
161
210
|
pbPayload: parsed.pbPayload,
|
|
162
211
|
seq: parsed.seq,
|
|
163
212
|
message: {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
213
|
+
version: 1,
|
|
214
|
+
supported_messages: [60200, 60201],
|
|
215
|
+
protobuf_definition: 'proto',
|
|
167
216
|
},
|
|
168
217
|
});
|
|
169
218
|
});
|
|
@@ -201,10 +250,9 @@ describe('Protocol V2 framing and session', () => {
|
|
|
201
250
|
});
|
|
202
251
|
|
|
203
252
|
test('reassembles split Protocol V2 frames and rejects oversized frames', () => {
|
|
204
|
-
const frame = ProtocolV2.encodeFrame(schemas, '
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
patch_version: 0,
|
|
253
|
+
const frame = ProtocolV2.encodeFrame(schemas, 'ProtocolInfo', {
|
|
254
|
+
version: 1,
|
|
255
|
+
supported_messages: [],
|
|
208
256
|
});
|
|
209
257
|
const assembler = new ProtocolV2FrameAssembler();
|
|
210
258
|
|
|
@@ -216,15 +264,13 @@ describe('Protocol V2 framing and session', () => {
|
|
|
216
264
|
});
|
|
217
265
|
|
|
218
266
|
test('keeps bytes after the first complete frame for the next read', () => {
|
|
219
|
-
const first = ProtocolV2.encodeFrame(schemas, '
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
patch_version: 0,
|
|
267
|
+
const first = ProtocolV2.encodeFrame(schemas, 'ProtocolInfo', {
|
|
268
|
+
version: 1,
|
|
269
|
+
supported_messages: [],
|
|
223
270
|
});
|
|
224
|
-
const second = ProtocolV2.encodeFrame(schemas, '
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
patch_version: 0,
|
|
271
|
+
const second = ProtocolV2.encodeFrame(schemas, 'ProtocolInfo', {
|
|
272
|
+
version: 2,
|
|
273
|
+
supported_messages: [],
|
|
228
274
|
});
|
|
229
275
|
const assembler = new ProtocolV2FrameAssembler();
|
|
230
276
|
const combined = new Uint8Array(first.length + second.length);
|
|
@@ -237,10 +283,9 @@ describe('Protocol V2 framing and session', () => {
|
|
|
237
283
|
|
|
238
284
|
test('session writes one encoded frame and decodes the response frame', async () => {
|
|
239
285
|
const written = [];
|
|
240
|
-
const response = ProtocolV2.encodeFrame(schemas, '
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
patch_version: 1,
|
|
286
|
+
const response = ProtocolV2.encodeFrame(schemas, 'ProtocolInfo', {
|
|
287
|
+
version: 2,
|
|
288
|
+
supported_messages: [60206],
|
|
244
289
|
});
|
|
245
290
|
const session = new ProtocolV2Session({
|
|
246
291
|
schemas,
|
|
@@ -253,18 +298,18 @@ describe('Protocol V2 framing and session', () => {
|
|
|
253
298
|
Promise.resolve(rewriteSeq(response, protocolV2.decodeFrame(written[0]).seq)),
|
|
254
299
|
});
|
|
255
300
|
|
|
256
|
-
const result = await session.call('
|
|
301
|
+
const result = await session.call('ProtocolInfoRequest', {});
|
|
257
302
|
|
|
258
303
|
expect(written).toHaveLength(1);
|
|
259
304
|
expect(written[0][4]).toBe(1);
|
|
260
305
|
expect(written[0][5]).toBe(0);
|
|
261
306
|
expect(protocolV2.decodeFrame(written[0]).messageTypeId).toBe(60200);
|
|
262
307
|
expect(result).toEqual({
|
|
263
|
-
type: '
|
|
308
|
+
type: 'ProtocolInfo',
|
|
264
309
|
message: {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
310
|
+
version: 2,
|
|
311
|
+
supported_messages: [60206],
|
|
312
|
+
protobuf_definition: null,
|
|
268
313
|
},
|
|
269
314
|
});
|
|
270
315
|
});
|
|
@@ -294,10 +339,9 @@ describe('Protocol V2 framing and session', () => {
|
|
|
294
339
|
});
|
|
295
340
|
|
|
296
341
|
test('session accepts response frames with a device-owned seq', async () => {
|
|
297
|
-
const response = ProtocolV2.encodeFrame(schemas, '
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
patch_version: 1,
|
|
342
|
+
const response = ProtocolV2.encodeFrame(schemas, 'ProtocolInfo', {
|
|
343
|
+
version: 2,
|
|
344
|
+
supported_messages: [],
|
|
301
345
|
});
|
|
302
346
|
const logger = {
|
|
303
347
|
debug: jest.fn(),
|
|
@@ -310,12 +354,12 @@ describe('Protocol V2 framing and session', () => {
|
|
|
310
354
|
logger,
|
|
311
355
|
});
|
|
312
356
|
|
|
313
|
-
await expect(session.call('
|
|
314
|
-
type: '
|
|
357
|
+
await expect(session.call('ProtocolInfoRequest', {})).resolves.toEqual({
|
|
358
|
+
type: 'ProtocolInfo',
|
|
315
359
|
message: {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
360
|
+
version: 2,
|
|
361
|
+
supported_messages: [],
|
|
362
|
+
protobuf_definition: null,
|
|
319
363
|
},
|
|
320
364
|
});
|
|
321
365
|
expect(logger.debug).toHaveBeenCalledWith(expect.stringContaining('seq differs'));
|
|
@@ -399,10 +443,9 @@ describe('Protocol V2 framing and session', () => {
|
|
|
399
443
|
const stale = ProtocolV2.encodeFrame(schemas, 'Success', {
|
|
400
444
|
message: 'stale response',
|
|
401
445
|
});
|
|
402
|
-
const response = ProtocolV2.encodeFrame(schemas, '
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
patch_version: 1,
|
|
446
|
+
const response = ProtocolV2.encodeFrame(schemas, 'ProtocolInfo', {
|
|
447
|
+
version: 2,
|
|
448
|
+
supported_messages: [],
|
|
406
449
|
});
|
|
407
450
|
const logger = {
|
|
408
451
|
debug: jest.fn(),
|
|
@@ -417,13 +460,13 @@ describe('Protocol V2 framing and session', () => {
|
|
|
417
460
|
});
|
|
418
461
|
|
|
419
462
|
await expect(
|
|
420
|
-
session.call('
|
|
463
|
+
session.call('ProtocolInfoRequest', {}, { expectedTypes: ['ProtocolInfo'] })
|
|
421
464
|
).resolves.toEqual({
|
|
422
|
-
type: '
|
|
465
|
+
type: 'ProtocolInfo',
|
|
423
466
|
message: {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
467
|
+
version: 2,
|
|
468
|
+
supported_messages: [],
|
|
469
|
+
protobuf_definition: null,
|
|
427
470
|
},
|
|
428
471
|
});
|
|
429
472
|
|
|
@@ -433,9 +476,8 @@ describe('Protocol V2 framing and session', () => {
|
|
|
433
476
|
|
|
434
477
|
test('session consumes intermediate response frames before returning the final response', async () => {
|
|
435
478
|
const written = [];
|
|
436
|
-
const progress = ProtocolV2.encodeFrame(schemas, '
|
|
437
|
-
target_id:
|
|
438
|
-
progress: 42,
|
|
479
|
+
const progress = ProtocolV2.encodeFrame(schemas, 'DeviceFirmwareUpdateStatus', {
|
|
480
|
+
records: [{ target_id: 3, status: 1 }],
|
|
439
481
|
});
|
|
440
482
|
const success = ProtocolV2.encodeFrame(schemas, 'Success', {
|
|
441
483
|
message: 'ok',
|
|
@@ -459,20 +501,19 @@ describe('Protocol V2 framing and session', () => {
|
|
|
459
501
|
});
|
|
460
502
|
|
|
461
503
|
const result = await session.call(
|
|
462
|
-
'
|
|
463
|
-
{},
|
|
504
|
+
'DeviceFirmwareUpdateRequest',
|
|
505
|
+
{ targets: [{ target_id: 3, path: 'vol1:firmware.bin' }] },
|
|
464
506
|
{
|
|
465
|
-
intermediateTypes: ['
|
|
507
|
+
intermediateTypes: ['DeviceFirmwareUpdateStatus'],
|
|
466
508
|
onIntermediateResponse,
|
|
467
509
|
}
|
|
468
510
|
);
|
|
469
511
|
|
|
470
512
|
expect(readFrame).toHaveBeenCalledTimes(2);
|
|
471
513
|
expect(onIntermediateResponse).toHaveBeenCalledWith({
|
|
472
|
-
type: '
|
|
514
|
+
type: 'DeviceFirmwareUpdateStatus',
|
|
473
515
|
message: {
|
|
474
|
-
target_id:
|
|
475
|
-
progress: 42,
|
|
516
|
+
records: [{ target_id: 3, status: 1, payload_version: null, path: null }],
|
|
476
517
|
},
|
|
477
518
|
});
|
|
478
519
|
expect(result).toEqual({
|
|
@@ -562,7 +603,7 @@ describe('Protocol V2 framing and session', () => {
|
|
|
562
603
|
});
|
|
563
604
|
|
|
564
605
|
await expect(
|
|
565
|
-
session.call('
|
|
606
|
+
session.call('ProtocolInfoRequest', {}, { timeoutMs: 10, expectedTypes: ['ProtocolInfo'] })
|
|
566
607
|
).rejects.toThrow('Protocol V2 response timeout');
|
|
567
608
|
|
|
568
609
|
// Without cancellation the loop would skip this unexpected Success frame
|
|
@@ -687,10 +728,9 @@ describe('Protocol V2 framing and session', () => {
|
|
|
687
728
|
});
|
|
688
729
|
|
|
689
730
|
test('assembler drain returns every buffered complete frame', () => {
|
|
690
|
-
const first = ProtocolV2.encodeFrame(schemas, '
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
patch_version: 0,
|
|
731
|
+
const first = ProtocolV2.encodeFrame(schemas, 'ProtocolInfo', {
|
|
732
|
+
version: 1,
|
|
733
|
+
supported_messages: [],
|
|
694
734
|
});
|
|
695
735
|
const second = ProtocolV2.encodeFrame(schemas, 'Success', { message: 'ok' });
|
|
696
736
|
const third = ProtocolV2.encodeFrame(schemas, 'Success', { message: 'last' });
|
|
@@ -714,6 +754,26 @@ describe('Protocol V2 framing and session', () => {
|
|
|
714
754
|
expect(decoded.type).toBe('ButtonRequest');
|
|
715
755
|
});
|
|
716
756
|
|
|
757
|
+
test('decodes legacy V1 Failure as a Protocol V2 fallback', () => {
|
|
758
|
+
// Some device-side rejection paths still return legacy Failure(type=3)
|
|
759
|
+
// inside a Protocol V2 frame. It must surface as a device Failure, not as
|
|
760
|
+
// a protobuf catalog TypeError.
|
|
761
|
+
const frame = ProtocolV2.encodeFrame(
|
|
762
|
+
{ ...schemas, protocolV2: schemas.protocolV1 },
|
|
763
|
+
'Failure',
|
|
764
|
+
{
|
|
765
|
+
code: 1,
|
|
766
|
+
message: 'Action cancelled',
|
|
767
|
+
}
|
|
768
|
+
);
|
|
769
|
+
const decoded = ProtocolV2.decodeFrame(schemas, frame);
|
|
770
|
+
expect(decoded.type).toBe('Failure');
|
|
771
|
+
expect(decoded.message).toEqual({
|
|
772
|
+
code: 1,
|
|
773
|
+
message: 'Action cancelled',
|
|
774
|
+
});
|
|
775
|
+
});
|
|
776
|
+
|
|
717
777
|
test('does not fall back to legacy V1 messages outside the allowlist', () => {
|
|
718
778
|
// OnekeyFeatures exists only in the V1 schema and is not allowlisted.
|
|
719
779
|
const frame = protocolV2.encodeProtobufFrame(10026, new Uint8Array(0));
|
package/dist/constants.d.ts
CHANGED
|
@@ -5,9 +5,9 @@ export declare const PROTOCOL_V1_USB_PACKET_SIZE: number;
|
|
|
5
5
|
export declare const PROTOCOL_V1_MESSAGE_HEADER_SIZE: number;
|
|
6
6
|
export declare const PROTOCOL_V1_ENVELOPE_HEADER_SIZE: number;
|
|
7
7
|
export declare const PROTOCOL_V2_FRAME_MAX_BYTES = 4608;
|
|
8
|
-
export declare const PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE =
|
|
8
|
+
export declare const PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE = 4000;
|
|
9
9
|
export declare const PROTOCOL_V2_BLE_FILE_CHUNK_SIZE = 1800;
|
|
10
|
-
export declare const PROTOCOL_V2_FILE_CHUNK_SIZE =
|
|
10
|
+
export declare const PROTOCOL_V2_FILE_CHUNK_SIZE = 4000;
|
|
11
11
|
export declare const PROTOCOL_V2_CHANNEL_USB = 0;
|
|
12
12
|
export declare const PROTOCOL_V2_CHANNEL_BLE_UART = 1;
|
|
13
13
|
export declare const PROTOCOL_V2_CHANNEL_SOCKET = 2;
|