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

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.
@@ -5,14 +5,10 @@ set -euxo pipefail
5
5
  echo $#
6
6
 
7
7
  PARENT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
8
- PACKAGE_ROOT="$PARENT_PATH/.."
9
8
 
10
9
  SRC="../../submodules/firmware/common/protob"
11
10
  DIST="."
12
11
  LANG="typescript"
13
- # Absolute paths — resolved relative to this script's directory
14
- REPO_ROOT="$PARENT_PATH/../../.."
15
- CORE_MESSAGES_DIR="$REPO_ROOT/packages/core/src/data/messages"
16
12
 
17
13
  if [[ $# -ne 0 && $# -ne 3 ]]
18
14
  then
@@ -33,238 +29,30 @@ if [[ "$LANG" != "typescript" && "$LANG" != "flow" ]];
33
29
  exit 1
34
30
  fi
35
31
 
36
- if [[ "$SRC" = /* ]]; then
37
- SRC_PATH="$SRC"
38
- else
39
- SRC_PATH="$PACKAGE_ROOT/$SRC"
40
- fi
41
-
42
- if [[ "$DIST" = /* ]]; then
43
- DIST_PATH="$DIST"
44
- else
45
- DIST_PATH="$PACKAGE_ROOT/$DIST"
46
- fi
47
-
48
- # Remove temp proto files on any exit, including failure paths
49
- trap 'rm -f "$DIST_PATH/messages-tmp.proto" "$PARENT_PATH/messages-protocol-v2-tmp.proto"' EXIT
50
-
51
-
52
- # ============================================================
53
- # BUILD Pro1 messages.json (requires firmware submodule)
54
- # ============================================================
55
- # Combines all messages*.proto files from firmware submodule into
56
- # messages.json, then copies to core package.
57
- if [ -d "$SRC_PATH" ] && ls "$SRC_PATH"/messages*.proto 1>/dev/null 2>&1; then
58
- echo "=== Building Pro1 (legacy) protobuf messages ==="
59
- TMP_PROTO="$DIST_PATH/messages-tmp.proto"
60
- echo 'syntax = "proto2";' > "$TMP_PROTO"
61
- echo 'import "google/protobuf/descriptor.proto";' >> "$TMP_PROTO"
62
- echo "Build proto file from $SRC_PATH"
63
- grep -hv -e '^import ' -e '^syntax' -e '^package' -e 'option java_' "$SRC_PATH"/messages*.proto \
64
- | sed 's/ hw\.trezor\.messages\.common\./ /' \
65
- | sed 's/ common\./ /' \
66
- | sed 's/ ethereum_definitions\./ /' \
67
- | sed 's/ management\./ /' \
68
- | sed 's/^option /\/\/ option /' \
69
- | grep -v ' reserved '>> "$TMP_PROTO"
70
-
71
- npx pbjs -t json -p "$DIST_PATH" -o "$DIST_PATH/messages.json" --keep-case "$TMP_PROTO"
72
- rm "$TMP_PROTO"
73
32
 
74
- # Copy to core package
75
- cp "$DIST_PATH/messages.json" "$CORE_MESSAGES_DIR/messages.json"
76
- echo "Pro1 messages.json copied to core"
33
+ # BUILD combined messages.proto file from protobuf files
34
+ # this code was copied from ./submodules/firmware/protob Makekile
35
+ # clear protobuf syntax and remove unknown values to be able to work with proto2js
36
+ echo 'syntax = "proto2";' > $DIST/messages.proto
37
+ echo 'import "google/protobuf/descriptor.proto";' >> $DIST/messages.proto
38
+ echo "Build proto file from $SRC"
39
+ grep -hv -e '^import ' -e '^syntax' -e '^package' -e 'option java_' $SRC/messages*.proto \
40
+ | sed 's/ hw\.trezor\.messages\.common\./ /' \
41
+ | sed 's/ common\./ /' \
42
+ | sed 's/ ethereum_definitions\./ /' \
43
+ | sed 's/ management\./ /' \
44
+ | sed 's/^option /\/\/ option /' \
45
+ | grep -v ' reserved '>> $DIST/messages.proto
77
46
 
78
- yarn --cwd "$PACKAGE_ROOT" prettier --write "$DIST_PATH/messages.json"
79
- yarn --cwd "$PACKAGE_ROOT" prettier --write "$CORE_MESSAGES_DIR/messages.json"
80
- # Type generation (protobuf-types.js) runs once at the end of the Protocol V2
81
- # section below, after both schemas are available.
82
- else
83
- # Intentional asymmetry with the Protocol V2 section below: the legacy firmware
84
- # submodule is optional (the committed messages.json stays in use when it is
85
- # absent), while firmware-pro2 is the only source of the Protocol V2 schema,
86
- # so its absence is a hard error (exit 1).
87
- echo "⚠️ firmware submodule not found at $SRC_PATH"
88
- echo " Skipping Pro1 protobuf build. To enable:"
89
- echo " git submodule update --init submodules/firmware"
90
- fi
47
+ # BUILD messages.json from message.proto
48
+ npx pbjs -t json -p $DIST -o $DIST/messages.json --keep-case messages.proto
49
+ rm $DIST/messages.proto
91
50
 
51
+ echo "generating type definitions for: $LANG"
92
52
 
93
- # ============================================================
94
- # BUILD Protocol V2 messages-protocol-v2.json
95
- # ============================================================
96
- # Source of truth: submodules/firmware-pro2/sys/protobuf/onekey_protocol/.
97
- # Protocol V2 keeps chain/app protocols under legacy/ and system protocols under latest/.
98
- # The SDK flattens them into one protobuf schema for transport runtime, but it must keep
99
- # firmware message names and enum values intact. SDK-facing aliases belong in core/API code,
100
- # not in the protobuf schema.
101
- # ============================================================
102
53
  cd "$PARENT_PATH"
103
54
 
104
- SRC_PRO2_LEGACY="$REPO_ROOT/submodules/firmware-pro2/sys/protobuf/onekey_protocol/legacy"
105
- SRC_PRO2_LATEST="$REPO_ROOT/submodules/firmware-pro2/sys/protobuf/onekey_protocol/latest"
106
-
107
- if [ -d "$SRC_PRO2_LATEST" ] && ls "$SRC_PRO2_LATEST"/messages*.proto 1>/dev/null 2>&1; then
108
- echo "=== Building Protocol V2 messages from firmware-pro2 legacy + latest protobuf schema ==="
109
- TMP_PROTO="$PARENT_PATH/messages-protocol-v2-tmp.proto"
110
-
111
- {
112
- echo 'syntax = "proto2";'
113
- echo 'import "google/protobuf/descriptor.proto";'
114
- echo ''
115
-
116
- # Pro2 firmware keeps chain/app protocols under legacy/, and Protocol V2
117
- # device/filesystem/firmware protocols under latest/. Build one flat
118
- # schema so Protocol V2 framing can also encode legacy public-chain calls.
119
- grep -hv \
120
- -e '^import ' -e '^syntax' -e '^package' -e 'option java_' \
121
- "$SRC_PRO2_LEGACY"/messages*.proto \
122
- | sed 's/ hw\.onekey\.messages\.[a-zA-Z_]*\./ /g' \
123
- | sed 's/ crypto\./ /g' \
124
- | sed 's/ ethereum_definitions\./ /g' \
125
- | sed 's/ management\./ /g' \
126
- | sed 's/^option /\/\/ option /' \
127
- | grep -v ' reserved '
128
-
129
- echo ''
130
- echo '// --- Protocol V2 system messages ---'
131
- grep -hv \
132
- -e '^import ' -e '^syntax' -e '^package' -e 'option java_' \
133
- -e '^option ' \
134
- "$SRC_PRO2_LATEST"/messages*.proto \
135
- | grep -v ' reserved '
136
-
137
- } > "$TMP_PROTO"
138
-
139
- node - "$TMP_PROTO" <<'NODE'
140
- const fs = require('fs');
55
+ node ./protobuf-types.js $LANG
141
56
 
142
- const protoPath = process.argv[2];
143
- let proto = fs.readFileSync(protoPath, 'utf8');
144
-
145
- const removeTopLevelMessage = (source, name) => {
146
- const pattern = new RegExp(`(^|\\n)message\\s+${name}\\s*\\{`, 'm');
147
- const match = pattern.exec(source);
148
- if (!match) return source;
149
-
150
- const start = match.index + (match[1] ? match[1].length : 0);
151
- let index = start;
152
- let depth = 0;
153
- while (index < source.length) {
154
- const char = source[index];
155
- if (char === '{') {
156
- depth += 1;
157
- } else if (char === '}') {
158
- depth -= 1;
159
- if (depth === 0) {
160
- index += 1;
161
- while (index < source.length && /\s/.test(source[index])) index += 1;
162
- return `${source.slice(0, start)}${source.slice(index)}`;
163
- }
164
- }
165
- index += 1;
166
- }
167
- throw new Error(`Unterminated message block: ${name}`);
168
- };
169
-
170
- [
171
- 'Initialize',
172
- 'GetFeatures',
173
- 'OnekeyGetFeatures',
174
- 'Features',
175
- ].forEach(name => {
176
- proto = removeTopLevelMessage(proto, name);
177
- });
178
-
179
- fs.writeFileSync(protoPath, proto);
180
-
181
- const messageNames = new Set(
182
- Array.from(proto.matchAll(/^\s*message\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{/gm)).map(
183
- match => match[1]
184
- )
185
- );
186
- const messageTypeNames = new Set(
187
- Array.from(proto.matchAll(/^\s*MessageType_([A-Za-z_][A-Za-z0-9_]*)\s*=/gm)).map(
188
- match => match[1]
189
- )
190
- );
191
- const requiredMessages = [
192
- 'DeviceFactoryInfoSet',
193
- 'DeviceFactoryInfoGet',
194
- 'DeviceFactoryInfo',
195
- 'ProtocolInfoRequest',
196
- 'ProtocolInfo',
197
- 'Ping',
198
- 'Success',
199
- 'Failure',
200
- 'DeviceReboot',
201
- 'DeviceInfoGet',
202
- 'DeviceInfo',
203
- 'DeviceStatusGet',
204
- 'DeviceStatus',
205
- 'DevGetOnboardingStatus',
206
- 'DevOnboardingStatus',
207
- 'DeviceSessionGet',
208
- 'DeviceSession',
209
- 'DeviceSessionAskPin',
210
- 'DeviceSessionPinResult',
211
- 'DeviceFirmwareUpdateRequest',
212
- 'DeviceFirmwareUpdateStatusGet',
213
- 'DeviceFirmwareUpdateStatus',
214
- 'FilesystemPermissionFix',
215
- 'FilesystemPathInfo',
216
- 'FilesystemPathInfoQuery',
217
- 'FilesystemFile',
218
- 'FilesystemFileRead',
219
- 'FilesystemFileWrite',
220
- 'FilesystemFileDelete',
221
- 'FilesystemDir',
222
- 'FilesystemDirList',
223
- 'FilesystemDirMake',
224
- 'FilesystemDirRemove',
225
- 'FilesystemFormat',
226
- 'PortfolioUpdate',
227
- ];
228
- const missingMessages = requiredMessages.filter(name => !messageNames.has(name));
229
- const missingMessageTypes = requiredMessages.filter(name => !messageTypeNames.has(name));
230
-
231
- if (missingMessages.length > 0 || missingMessageTypes.length > 0) {
232
- throw new Error(
233
- `Protocol V2 schema missing required entries: messages=[${missingMessages.join(
234
- ', '
235
- )}], messageTypes=[${missingMessageTypes.join(
236
- ', '
237
- )}]. Make sure submodules/firmware-pro2 is checked out on branch dev ` +
238
- '(origin/dev), which contains the latest Protocol V2 Device*/Filesystem* messages.'
239
- );
240
- }
241
-
242
- NODE
243
-
244
- npx pbjs -t json \
245
- -p "$PARENT_PATH" \
246
- -o "$PARENT_PATH/../messages-protocol-v2.json" \
247
- --keep-case \
248
- "$(basename "$TMP_PROTO")"
249
-
250
- rm -f "$TMP_PROTO"
251
-
252
- cp "$PARENT_PATH/../messages-protocol-v2.json" "$CORE_MESSAGES_DIR/messages-protocol-v2.json"
253
- echo "Protocol V2 messages-protocol-v2.json generated from firmware-pro2 legacy + latest schema and copied to core"
254
-
255
- yarn --cwd "$PACKAGE_ROOT" prettier --write "$PARENT_PATH/../messages-protocol-v2.json"
256
- yarn --cwd "$PACKAGE_ROOT" prettier --write "$CORE_MESSAGES_DIR/messages-protocol-v2.json"
257
-
258
- echo "generating type definitions for: $LANG"
259
- node ./protobuf-types.js $LANG
260
- yarn --cwd "$PACKAGE_ROOT" prettier --write "$PACKAGE_ROOT/src/types/messages.ts"
261
- echo "=== Protocol V2 messages build complete ==="
262
- else
263
- # Unlike the optional Pro1 (legacy) section above, the firmware-pro2 submodule is
264
- # the only source of the Protocol V2 schema, so a missing checkout is a hard error.
265
- echo "firmware-pro2 latest protobuf schema not found at $SRC_PRO2_LATEST"
266
- echo "The Protocol V2 schema requires firmware-pro2 on branch dev."
267
- echo "Run: git submodule update --init submodules/firmware-pro2"
268
- echo "Then: git -C submodules/firmware-pro2 fetch origin dev && git -C submodules/firmware-pro2 checkout origin/dev"
269
- exit 1
270
- fi
57
+ yarn prettier --write messages.json
58
+ yarn prettier --write **/messages.ts
@@ -19,6 +19,10 @@ const optionalJsonFiles = ['../messages-protocol-v2.json'];
19
19
  const OPTIONAL_DUPLICATE_TYPE_ALIASES = {
20
20
  DeviceInfo: 'ProtocolV2DeviceInfo',
21
21
  };
22
+ const OPTIONAL_NESTED_TYPE_ALIASES = [
23
+ { parent: 'Failure', name: 'FailureType', alias: 'ProtocolV2FailureType' },
24
+ { parent: 'Features', name: 'Capability', alias: 'ProtocolV2Capability' },
25
+ ];
22
26
  const messageTypeAliases = {};
23
27
  const skipMessageTypeKeys = new Set(Object.values(OPTIONAL_DUPLICATE_TYPE_ALIASES));
24
28
 
@@ -59,6 +63,7 @@ const ENUM_KEYS = [
59
63
  'ButtonRequestType',
60
64
  'PinMatrixRequestType',
61
65
  'WordRequestType',
66
+ 'ProtocolV2Capability',
62
67
  ];
63
68
 
64
69
  const parseEnumTypescript = (itemName, item) => {
@@ -317,6 +322,10 @@ optionalJsonFiles.forEach(jsonFile => {
317
322
  const jsonPath = path.join(__dirname, jsonFile);
318
323
  if (!fs.existsSync(jsonPath)) return;
319
324
  const optionalJson = readJson(jsonPath);
325
+ OPTIONAL_NESTED_TYPE_ALIASES.forEach(({ parent, name, alias }) => {
326
+ const definition = optionalJson.nested[parent]?.nested?.[name];
327
+ if (definition) optionalJson.nested[alias] = definition;
328
+ });
320
329
  optionalJsons.push(optionalJson);
321
330
  Object.keys(optionalJson.nested).forEach(e => {
322
331
  if (!json.nested[e]) return; // V2-only type, parsed after the V1 pass below
@@ -72,6 +72,18 @@ export const ProtocolV1 = {
72
72
  export const ProtocolV2 = {
73
73
  isAckFrame,
74
74
 
75
+ inspectFrame(schemas: ProtocolV2Schemas, frame: Uint8Array) {
76
+ const { messageTypeId, pbPayload, seq } = decodeV2Frame(frame);
77
+ const { messageName } = createProtocolV2MessageFromType(messageTypeId, schemas);
78
+ return {
79
+ messageName,
80
+ messageTypeId,
81
+ pbPayload,
82
+ seq,
83
+ type: messageName,
84
+ };
85
+ },
86
+
75
87
  encodeFrame(
76
88
  schemas: ProtocolV2Schemas,
77
89
  name: string,
@@ -95,8 +107,8 @@ export const ProtocolV2 = {
95
107
  },
96
108
 
97
109
  decodeFrame(schemas: ProtocolV2Schemas, frame: Uint8Array) {
98
- const { messageTypeId, pbPayload, seq } = decodeV2Frame(frame);
99
- const { Message, messageName } = createProtocolV2MessageFromType(messageTypeId, schemas);
110
+ const { messageTypeId, pbPayload, seq, messageName } = this.inspectFrame(schemas, frame);
111
+ const { Message } = createProtocolV2MessageFromType(messageTypeId, schemas);
100
112
  const rxByteBuffer = ByteBuffer.wrap(Buffer.from(pbPayload) as unknown as ArrayBuffer);
101
113
  const message = decodeProtobuf(Message, rxByteBuffer);
102
114
 
@@ -201,6 +201,7 @@ export class ProtocolV2Session {
201
201
  router,
202
202
  seq: protoSeq,
203
203
  });
204
+ const txMetadata = ProtocolV2.inspectFrame(schemas, frame);
204
205
 
205
206
  if (maxFrameBytes !== undefined && frame.length > maxFrameBytes) {
206
207
  throw new Error(
@@ -208,6 +209,16 @@ export class ProtocolV2Session {
208
209
  );
209
210
  }
210
211
 
212
+ if (!shouldReduceDebug) {
213
+ logger?.debug?.(`[${logPrefix}] TX`, {
214
+ method: name,
215
+ type: name,
216
+ typeId: txMetadata.messageTypeId,
217
+ seq: txMetadata.seq,
218
+ bytes: frame.length,
219
+ });
220
+ }
221
+
211
222
  // Lenient watchdog on the write phase only — see
212
223
  // PROTOCOL_V2_WRITE_WATCHDOG_TIMEOUT_MS for the rationale.
213
224
  await withProtocolTimeout(
@@ -237,6 +248,18 @@ export class ProtocolV2Session {
237
248
  }
238
249
  const isAck = ProtocolV2.isAckFrame(rxFrame);
239
250
  if (!isAck) {
251
+ const rxMetadata = ProtocolV2.inspectFrame(schemas, rxFrame);
252
+
253
+ if (!shouldReduceDebug) {
254
+ logger?.debug?.(`[${logPrefix}] RX`, {
255
+ method: name,
256
+ type: rxMetadata.type,
257
+ typeId: rxMetadata.messageTypeId,
258
+ seq: rxMetadata.seq,
259
+ bytes: rxFrame.length,
260
+ });
261
+ }
262
+
240
263
  const decoded = ProtocolV2.decodeFrame(schemas, rxFrame);
241
264
 
242
265
  const response = check.call(decoded);
@@ -2412,6 +2412,19 @@ export type Features = {
2412
2412
  onekey_se04_state?: string | null;
2413
2413
  attach_to_pin_user?: boolean;
2414
2414
  unlocked_attach_pin?: boolean;
2415
+ coprocessor_bt_name?: string;
2416
+ coprocessor_version?: string;
2417
+ coprocessor_bt_enable?: boolean;
2418
+ romloader_version?: string;
2419
+ onekey_romloader_version?: string;
2420
+ onekey_romloader_hash?: string;
2421
+ onekey_bootloader_version?: string;
2422
+ onekey_bootloader_hash?: string;
2423
+ onekey_bootloader_build_id?: string;
2424
+ onekey_coprocessor_bt_name?: string;
2425
+ onekey_coprocessor_version?: string;
2426
+ onekey_coprocessor_build_id?: string;
2427
+ onekey_coprocessor_hash?: string;
2415
2428
  };
2416
2429
 
2417
2430
  // OnekeyFeatures
@@ -4607,6 +4620,9 @@ export type ViewRawData = {
4607
4620
  export enum ViewSignLayout {
4608
4621
  LayoutDefault = 0,
4609
4622
  LayoutSafeTxCreate = 1,
4623
+ LayoutFinalConfirm = 2,
4624
+ Layout7702 = 3,
4625
+ LayoutFlat = 4,
4610
4626
  }
4611
4627
 
4612
4628
  // ViewSignPage
@@ -4948,12 +4964,9 @@ export type DeviceSession = {
4948
4964
  // DeviceSessionAskPin
4949
4965
  export type DeviceSessionAskPin = {};
4950
4966
 
4951
- // DeviceSessionPinResult
4952
- export type DeviceSessionPinResult = {
4953
- unlocked?: boolean;
4954
- unlocked_attach_pin?: boolean;
4955
- passphrase_protection?: boolean;
4956
- };
4967
+ export enum DeviceSessionAskPin_FailureSubCodes {
4968
+ UserCancel = 1,
4969
+ }
4957
4970
 
4958
4971
  // DeviceStatus
4959
4972
  export type DeviceStatus = {
@@ -5082,6 +5095,37 @@ export type FilesystemFormat = {
5082
5095
  // PortfolioUpdate
5083
5096
  export type PortfolioUpdate = {};
5084
5097
 
5098
+ export enum ProtocolV2FailureType {
5099
+ Failure_InvalidMessage = 1,
5100
+ Failure_UndefinedError = 2,
5101
+ Failure_UsageError = 3,
5102
+ Failure_DataError = 4,
5103
+ Failure_ProcessError = 5,
5104
+ }
5105
+
5106
+ export enum Enum_ProtocolV2Capability {
5107
+ Capability_Bitcoin = 1,
5108
+ Capability_Bitcoin_like = 2,
5109
+ Capability_Binance = 3,
5110
+ Capability_Cardano = 4,
5111
+ Capability_Crypto = 5,
5112
+ Capability_EOS = 6,
5113
+ Capability_Ethereum = 7,
5114
+ Capability_Lisk = 8,
5115
+ Capability_Monero = 9,
5116
+ Capability_NEM = 10,
5117
+ Capability_Ripple = 11,
5118
+ Capability_Stellar = 12,
5119
+ Capability_Tezos = 13,
5120
+ Capability_U2F = 14,
5121
+ Capability_Shamir = 15,
5122
+ Capability_ShamirGroups = 16,
5123
+ Capability_PassphraseEntry = 17,
5124
+ Capability_AttachToPin = 18,
5125
+ Capability_EthereumTypedData = 1000,
5126
+ }
5127
+ export type ProtocolV2Capability = keyof typeof Enum_ProtocolV2Capability;
5128
+
5085
5129
  // custom connect definitions
5086
5130
  export type MessageType = {
5087
5131
  AlephiumGetAddress: AlephiumGetAddress;
@@ -5701,7 +5745,6 @@ export type MessageType = {
5701
5745
  DeviceSessionGet: DeviceSessionGet;
5702
5746
  DeviceSession: DeviceSession;
5703
5747
  DeviceSessionAskPin: DeviceSessionAskPin;
5704
- DeviceSessionPinResult: DeviceSessionPinResult;
5705
5748
  DeviceStatus: DeviceStatus;
5706
5749
  DeviceStatusGet: DeviceStatusGet;
5707
5750
  DevGetOnboardingStatus: DevGetOnboardingStatus;