@onekeyfe/hd-transport 1.2.2-alpha.100 → 1.2.2-alpha.102

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport",
3
- "version": "1.2.2-alpha.100",
3
+ "version": "1.2.2-alpha.102",
4
4
  "description": "Transport layer abstractions and utilities for OneKey hardware SDK.",
5
5
  "author": "OneKey",
6
6
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -28,5 +28,5 @@
28
28
  "long": "^4.0.0",
29
29
  "protobufjs": "^6.11.2"
30
30
  },
31
- "gitHead": "c40dad085297b0e3cc2020bd218c146dff6ed3e1"
31
+ "gitHead": "abddc95e03d794d9c6fce7765d59de1f48a684d0"
32
32
  }
package/src/constants.ts CHANGED
@@ -26,7 +26,7 @@ export const PROTOCOL_V2_FRAME_MAX_BYTES = 4200;
26
26
  /** FilesystemFileWrite chunk size over WebUSB. */
27
27
  export const PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE = 4000;
28
28
 
29
- /** FilesystemFileWrite chunk size over BLE. */
29
+ /** Generic FilesystemFileWrite chunk size over BLE, including support for long filesystem paths. */
30
30
  export const PROTOCOL_V2_BLE_FILE_CHUNK_SIZE = 1800;
31
31
 
32
32
  /**
@@ -1,6 +1,7 @@
1
1
  import { ProtocolV2SequenceCursor } from './sequence-cursor';
2
2
  import { ProtocolV2LinkError } from './errors';
3
3
  import { ProtocolV2Session, getErrorMessage } from './session';
4
+ import { PROTOCOL_V2_DEFAULT_RESPONSE_TIMEOUT_MS } from '../../constants';
4
5
 
5
6
  import type { MessageFromOneKey, TransportCallOptions } from '../../types';
6
7
  import type { ProtocolV2CallContext, ProtocolV2Schemas, ProtocolV2SessionOptions } from './session';
@@ -61,15 +62,45 @@ export class ProtocolV2LinkManager<Key> {
61
62
  options?: TransportCallOptions
62
63
  ): Promise<MessageFromOneKey> {
63
64
  const generation = this.generations.get(key) ?? 0;
65
+ const previousQueue = this.callQueues.get(key);
66
+ const timeoutMs =
67
+ options?.timeoutMs && options.timeoutMs > 0
68
+ ? options.timeoutMs
69
+ : PROTOCOL_V2_DEFAULT_RESPONSE_TIMEOUT_MS;
70
+ const queuedAt = Date.now();
71
+ let queueTimeout: ReturnType<typeof setTimeout> | undefined;
72
+ let queueTimeoutError: Error | undefined;
73
+ const timeoutWhileQueued = new Promise<never>((_, reject) => {
74
+ queueTimeout = setTimeout(() => {
75
+ queueTimeout = undefined;
76
+ queueTimeoutError = this.createQueuedCallTimeoutError(key, name, timeoutMs);
77
+ reject(queueTimeoutError);
78
+ }, timeoutMs);
79
+ });
64
80
  const run = () => {
81
+ if (queueTimeout) {
82
+ clearTimeout(queueTimeout);
83
+ queueTimeout = undefined;
84
+ }
85
+ if (queueTimeoutError) {
86
+ throw queueTimeoutError;
87
+ }
65
88
  this.assertCallGeneration(key, generation);
66
- return this.executeCall(key, createAdapter, name, data, options);
89
+ const remainingTimeoutMs = previousQueue ? timeoutMs - (Date.now() - queuedAt) : timeoutMs;
90
+ if (remainingTimeoutMs <= 0) {
91
+ throw this.createQueuedCallTimeoutError(key, name, timeoutMs);
92
+ }
93
+ return this.executeCall(key, createAdapter, name, data, {
94
+ ...options,
95
+ timeoutMs: remainingTimeoutMs,
96
+ });
67
97
  };
68
- const previous = this.callQueues.get(key) ?? Promise.resolve();
69
- const result = previous.then(run, run);
70
- const queue = result.catch(() => undefined);
98
+ const previous = previousQueue ?? Promise.resolve();
99
+ const execution = previous.then(run, run);
100
+ const result = Promise.race([execution, timeoutWhileQueued]);
101
+ const queue = execution.catch(() => undefined);
71
102
  this.callQueues.set(key, queue);
72
- result
103
+ execution
73
104
  .then(
74
105
  () => this.clearSettledCallQueue(key, queue),
75
106
  () => this.clearSettledCallQueue(key, queue)
@@ -206,6 +237,16 @@ export class ProtocolV2LinkManager<Key> {
206
237
  }
207
238
  }
208
239
 
240
+ private createQueuedCallTimeoutError(key: Key, name: string, timeoutMs: number): Error {
241
+ const adapterTimeoutError = this.links.get(key)?.adapter.createTimeoutError;
242
+ return adapterTimeoutError
243
+ ? adapterTimeoutError(name, timeoutMs)
244
+ : new ProtocolV2LinkError(
245
+ 'response-timeout',
246
+ `Protocol V2 call timeout after ${timeoutMs}ms while queued for ${name}`
247
+ );
248
+ }
249
+
209
250
  private assertCallGeneration(key: Key, generation: number) {
210
251
  const currentGeneration = this.generations.get(key) ?? 0;
211
252
  if (currentGeneration === generation) return;
@@ -60,6 +60,7 @@ export type ProtocolV2CallOptions = {
60
60
  onIntermediateResponse?: (response: MessageFromOneKey) => void;
61
61
  onWriteCompleted?: (metrics: TransportWriteMetrics) => void;
62
62
  returnAfterWrite?: boolean;
63
+ onResponseAfterWrite?: (response: MessageFromOneKey) => void;
63
64
  writeWithResponse?: boolean;
64
65
  };
65
66
 
@@ -81,6 +82,33 @@ export function hexToBytes(hex: string): Uint8Array {
81
82
  return bytes;
82
83
  }
83
84
 
85
+ export function detectProtocolV2LinkDisabledError({
86
+ schemas,
87
+ assembler,
88
+ bytes,
89
+ }: {
90
+ schemas: ProtocolV2Schemas;
91
+ assembler: ProtocolV2FrameAssembler;
92
+ bytes: Uint8Array;
93
+ }) {
94
+ try {
95
+ for (const frame of assembler.drain(bytes)) {
96
+ const response = check.call(ProtocolV2.decodeFrame(schemas, frame));
97
+ if (response.type === 'Failure') {
98
+ const failureCode = response.message?.code;
99
+ const firmwareMessage = response.message?.message;
100
+ if (isProtocolV2LinkDisabledFailure(failureCode, firmwareMessage)) {
101
+ return createProtocolV2LinkDisabledError(failureCode, firmwareMessage);
102
+ }
103
+ }
104
+ }
105
+ } catch {
106
+ // Cross-protocol detection may receive a normal Protocol V1 notification.
107
+ assembler.reset();
108
+ }
109
+ return undefined;
110
+ }
111
+
84
112
  export function bytesToHex(bytes: Uint8Array): string {
85
113
  return Array.from(bytes)
86
114
  .map(b => b.toString(16).padStart(2, '0'))
@@ -199,6 +227,11 @@ export class ProtocolV2Session {
199
227
  // response, but their frames must never interleave with the active request write.
200
228
  private pendingWrite: Promise<unknown> = Promise.resolve();
201
229
 
230
+ private pendingResponseAfterWrite?: {
231
+ expectedTypes: Set<string>;
232
+ onResponse?: (response: MessageFromOneKey) => void;
233
+ };
234
+
202
235
  private lastResponseSequence?: number;
203
236
 
204
237
  constructor(options: ProtocolV2SessionOptions) {
@@ -297,7 +330,11 @@ export class ProtocolV2Session {
297
330
  };
298
331
 
299
332
  const runCall = async (): Promise<MessageFromOneKey> => {
300
- await prepareCall?.(baseCallContext);
333
+ // A write-only call may still have a terminal response in flight. Preserve
334
+ // the continuous receive queue until the next call consumes that response.
335
+ if (!this.pendingResponseAfterWrite) {
336
+ await prepareCall?.(baseCallContext);
337
+ }
301
338
  const protoSeq = this.sequenceCursor.next();
302
339
  const frame = ProtocolV2.encodeFrame(schemas, name, data, {
303
340
  packetSrc,
@@ -323,6 +360,12 @@ export class ProtocolV2Session {
323
360
  }
324
361
 
325
362
  if (callOptions.returnAfterWrite) {
363
+ if (callOptions.expectedTypes?.length) {
364
+ this.pendingResponseAfterWrite = {
365
+ expectedTypes: new Set(callOptions.expectedTypes),
366
+ onResponse: callOptions.onResponseAfterWrite,
367
+ };
368
+ }
326
369
  return { type: 'WriteCompleted', message: {} };
327
370
  }
328
371
 
@@ -395,7 +438,26 @@ export class ProtocolV2Session {
395
438
  this.lastResponseSequence = decoded.seq;
396
439
 
397
440
  const response = check.call(decoded);
398
- if (callOptions.intermediateTypes?.includes(response.type)) {
441
+ const { pendingResponseAfterWrite } = this;
442
+ let belongsToWriteOnlyCall = false;
443
+ if (pendingResponseAfterWrite) {
444
+ belongsToWriteOnlyCall = pendingResponseAfterWrite.expectedTypes.has(response.type);
445
+ if (belongsToWriteOnlyCall || COMMON_TERMINAL_RESPONSE_TYPES.has(response.type)) {
446
+ this.pendingResponseAfterWrite = undefined;
447
+ if (belongsToWriteOnlyCall) {
448
+ try {
449
+ pendingResponseAfterWrite.onResponse?.(response);
450
+ } catch (error) {
451
+ logger?.error?.(
452
+ `${logPrefix} delayed response callback failed: ${String(error)}`
453
+ );
454
+ }
455
+ }
456
+ }
457
+ }
458
+ if (belongsToWriteOnlyCall) {
459
+ // The delayed response belongs to the preceding write-only call.
460
+ } else if (callOptions.intermediateTypes?.includes(response.type)) {
399
461
  callOptions.onIntermediateResponse?.(response);
400
462
  } else if (isExpectedTerminalResponse(response, callOptions.expectedTypes)) {
401
463
  return response;
@@ -433,6 +495,7 @@ export async function probeProtocolV2({
433
495
  logPrefix = 'ProtocolV2',
434
496
  onBeforeProbe,
435
497
  onProbeFailed,
498
+ shouldRethrow,
436
499
  }: {
437
500
  call: (
438
501
  name: string,
@@ -444,6 +507,7 @@ export async function probeProtocolV2({
444
507
  logPrefix?: string;
445
508
  onBeforeProbe?: () => Promise<void> | void;
446
509
  onProbeFailed?: (error: unknown) => Promise<void> | void;
510
+ shouldRethrow?: (error: unknown) => boolean;
447
511
  }) {
448
512
  let probeError: unknown;
449
513
  try {
@@ -468,7 +532,7 @@ export async function probeProtocolV2({
468
532
  }
469
533
  probeError = new Error(`unexpected response type ${response.type}`);
470
534
  } catch (error) {
471
- if (isProtocolV2LinkDisabledError(error)) {
535
+ if (isProtocolV2LinkDisabledError(error) || shouldRethrow?.(error)) {
472
536
  throw error;
473
537
  }
474
538
  probeError = error;
@@ -1950,6 +1950,7 @@ export type EthereumSignTxOneKey = {
1950
1950
  data_length?: number;
1951
1951
  chain_id: number;
1952
1952
  tx_type?: number;
1953
+ expected_address?: string;
1953
1954
  };
1954
1955
 
1955
1956
  // EthereumAccessListOneKey
@@ -1971,6 +1972,7 @@ export type EthereumSignTxEIP1559OneKey = {
1971
1972
  data_length: number;
1972
1973
  chain_id: number;
1973
1974
  access_list: EthereumAccessListOneKey[];
1975
+ expected_address?: string;
1974
1976
  };
1975
1977
 
1976
1978
  // EthereumAuthorizationSignature
@@ -3824,6 +3826,7 @@ export type SolanaSignedTx = {
3824
3826
 
3825
3827
  export enum SolanaOffChainMessageVersion {
3826
3828
  MESSAGE_VERSION_0 = 0,
3829
+ MESSAGE_VERSION_1 = 1,
3827
3830
  }
3828
3831
 
3829
3832
  export enum SolanaOffChainMessageFormat {
@@ -3838,6 +3841,7 @@ export type SolanaSignOffChainMessage = {
3838
3841
  message_version?: SolanaOffChainMessageVersion;
3839
3842
  message_format?: SolanaOffChainMessageFormat;
3840
3843
  application_domain?: string;
3844
+ required_signers: string[];
3841
3845
  };
3842
3846
 
3843
3847
  // SolanaSignUnsafeMessage
@@ -4550,12 +4554,6 @@ export enum CommandFlags {
4550
4554
  Factory_Only = 1,
4551
4555
  }
4552
4556
 
4553
- // experimental_message
4554
- export type experimental_message = {};
4555
-
4556
- // experimental_field
4557
- export type experimental_field = {};
4558
-
4559
4557
  export type TextMemo = {
4560
4558
  text: string;
4561
4559
  };
@@ -4660,6 +4658,12 @@ export type UiAnimationRequest = {
4660
4658
  type?: UiAnimationType;
4661
4659
  };
4662
4660
 
4661
+ // experimental_message
4662
+ export type experimental_message = {};
4663
+
4664
+ // experimental_field
4665
+ export type experimental_field = {};
4666
+
4663
4667
  // ProtocolInfoRequest
4664
4668
  export type ProtocolInfoRequest = {
4665
4669
  eventless_wallet_session?: boolean;
@@ -4766,6 +4770,19 @@ export type DeviceMiscUsbMscControl = {
4766
4770
  enable: boolean;
4767
4771
  };
4768
4772
 
4773
+ // DeviceFindMyTokenUpdate
4774
+ export type DeviceFindMyTokenUpdate = {
4775
+ token: string;
4776
+ };
4777
+
4778
+ // DeviceFindMyTokenStateGet
4779
+ export type DeviceFindMyTokenStateGet = {};
4780
+
4781
+ // DeviceFindMyTokenState
4782
+ export type DeviceFindMyTokenState = {
4783
+ burned: boolean;
4784
+ };
4785
+
4769
4786
  export enum DeviceFactoryAck {
4770
4787
  FACTORY_ACK_SUCCESS = 0,
4771
4788
  FACTORY_ACK_FAIL = 1,
@@ -4788,15 +4805,19 @@ export type DeviceFactoryInfo = {
4788
4805
  factory_test_completed?: boolean;
4789
4806
  factory_burn_in_completed?: boolean;
4790
4807
  manufacture_time?: DeviceFactoryInfoManufactureTime;
4808
+ data?: string;
4791
4809
  };
4792
4810
 
4793
4811
  // DeviceFactoryInfoSet
4794
4812
  export type DeviceFactoryInfoSet = {
4795
4813
  info: DeviceFactoryInfo;
4814
+ full_data?: boolean;
4796
4815
  };
4797
4816
 
4798
4817
  // DeviceFactoryInfoGet
4799
- export type DeviceFactoryInfoGet = {};
4818
+ export type DeviceFactoryInfoGet = {
4819
+ full_data?: boolean;
4820
+ };
4800
4821
 
4801
4822
  // DeviceFactoryPermanentLock
4802
4823
  export type DeviceFactoryPermanentLock = {
@@ -4837,6 +4858,12 @@ export enum DeviceFirmwareUpdateTaskStatus {
4837
4858
  FW_MGMT_UPDATER_TASK_STATUS_FAILED_ENTRY_OUT_OF_BOUNDS = 10,
4838
4859
  }
4839
4860
 
4861
+ export enum DeviceFirmwareUpdatePhase {
4862
+ FW_MGMT_UPDATER_PHASE_PREPARE = 0,
4863
+ FW_MGMT_UPDATER_PHASE_INSTALL = 1,
4864
+ FW_MGMT_UPDATER_PHASE_VERIFY = 2,
4865
+ }
4866
+
4840
4867
  // DeviceFirmwareTarget
4841
4868
  export type DeviceFirmwareTarget = {
4842
4869
  target_id: DeviceFirmwareTargetType;
@@ -4849,12 +4876,22 @@ export type DeviceFirmwareUpdateStage = {
4849
4876
  };
4850
4877
 
4851
4878
  // DeviceFirmwareUpdateRequest
4852
- export type DeviceFirmwareUpdateRequest = {};
4879
+ export type DeviceFirmwareUpdateRequest = {
4880
+ reboot_after_update?: boolean;
4881
+ };
4882
+
4883
+ // DeviceFirmwareUpdatePhaseInfo
4884
+ export type DeviceFirmwareUpdatePhaseInfo = {
4885
+ phase: DeviceFirmwareUpdatePhase;
4886
+ progress_percent: number;
4887
+ };
4853
4888
 
4854
4889
  // DeviceFirmwareUpdateRecord
4855
4890
  export type DeviceFirmwareUpdateRecord = {
4856
4891
  target_id: DeviceFirmwareTargetType;
4857
4892
  status?: DeviceFirmwareUpdateTaskStatus;
4893
+ progress_percent?: number;
4894
+ phase_info?: DeviceFirmwareUpdatePhaseInfo;
4858
4895
  payload_version?: number;
4859
4896
  path?: string;
4860
4897
  };
@@ -4862,6 +4899,8 @@ export type DeviceFirmwareUpdateRecord = {
4862
4899
  // DeviceFirmwareUpdateRecordFields
4863
4900
  export type DeviceFirmwareUpdateRecordFields = {
4864
4901
  status?: boolean;
4902
+ progress_percent?: boolean;
4903
+ phase_info?: boolean;
4865
4904
  payload_version?: boolean;
4866
4905
  path?: boolean;
4867
4906
  };
@@ -4992,13 +5031,13 @@ export enum DeviceSessionSeedDomain {
4992
5031
  export type DeviceSessionGet = {
4993
5032
  session_id?: string;
4994
5033
  btc_test_address?: string;
4995
- seed_domains: DeviceSessionSeedDomain[];
4996
5034
  };
4997
5035
 
4998
5036
  // DeviceSession
4999
5037
  export type DeviceSession = {
5000
5038
  session_id?: string;
5001
5039
  btc_test_address?: string;
5040
+ seed_domains: DeviceSessionSeedDomain[];
5002
5041
  };
5003
5042
 
5004
5043
  export enum DeviceSessionPinType {
@@ -5016,6 +5055,7 @@ export type DeviceSessionAskPin = {
5016
5055
  export type DeviceSessionAskPassphrase = {
5017
5056
  passphrase?: string;
5018
5057
  on_device: boolean;
5058
+ seed_domains: DeviceSessionSeedDomain[];
5019
5059
  };
5020
5060
 
5021
5061
  export enum DeviceSessionAskPin_FailureSubCodes {
@@ -5207,6 +5247,12 @@ export type ViewDetail = {
5207
5247
  has_icon: boolean;
5208
5248
  };
5209
5249
 
5250
+ // ViewCustomField
5251
+ export type ViewCustomField = {
5252
+ key: string;
5253
+ value: string;
5254
+ };
5255
+
5210
5256
  export enum ViewTipType {
5211
5257
  Default = 0,
5212
5258
  Highlight = 1,
@@ -5220,12 +5266,33 @@ export type ViewTip = {
5220
5266
  type: ViewTipType;
5221
5267
  text?: string;
5222
5268
  text_id?: number;
5269
+ text_arg?: string;
5223
5270
  };
5224
5271
 
5225
- // ViewRawData
5226
- export type ViewRawData = {
5272
+ // ViewActionCard
5273
+ export type ViewActionCard = {
5227
5274
  initial_data: string;
5228
- placeholder: number;
5275
+ };
5276
+
5277
+ // ViewContentPreview
5278
+ export type ViewContentPreview = {
5279
+ content_key: number;
5280
+ preview: string;
5281
+ total_bytes?: number;
5282
+ };
5283
+
5284
+ // ViewContentEntry
5285
+ export type ViewContentEntry = {
5286
+ entry_key: number;
5287
+ value: string;
5288
+ };
5289
+
5290
+ // ViewContentPage
5291
+ export type ViewContentPage = {
5292
+ page_index: number;
5293
+ page_count: number;
5294
+ chunk?: string;
5295
+ entry?: ViewContentEntry;
5229
5296
  };
5230
5297
 
5231
5298
  export enum ViewSignLayout {
@@ -5243,10 +5310,21 @@ export type ViewSignPage = {
5243
5310
  amount?: UintType;
5244
5311
  general: ViewDetail[];
5245
5312
  tip?: ViewTip;
5246
- raw_data?: ViewRawData;
5313
+ action_card?: ViewActionCard;
5247
5314
  slide_to_confirm?: boolean;
5248
5315
  layout?: ViewSignLayout;
5249
5316
  title_id?: number;
5317
+ title_arg?: string;
5318
+ content?: ViewContentPreview;
5319
+ custom_field?: ViewCustomField;
5320
+ };
5321
+
5322
+ // ViewWarningPage
5323
+ export type ViewWarningPage = {
5324
+ title_id: number;
5325
+ text_id: number;
5326
+ text_arg?: string;
5327
+ cancellable?: boolean;
5250
5328
  };
5251
5329
 
5252
5330
  // ViewVerifyPage
@@ -5259,6 +5337,7 @@ export type ViewVerifyPage = {
5259
5337
  value_key?: number;
5260
5338
  title_id?: number;
5261
5339
  chain_id?: number;
5340
+ content?: ViewContentPreview;
5262
5341
  };
5263
5342
 
5264
5343
  export enum ProtocolV2FailureType {
@@ -5858,8 +5937,6 @@ export type MessageType = {
5858
5937
  TronSignMessage: TronSignMessage;
5859
5938
  TronMessageSignature: TronMessageSignature;
5860
5939
  facotry: facotry;
5861
- experimental_message: experimental_message;
5862
- experimental_field: experimental_field;
5863
5940
  TextMemo: TextMemo;
5864
5941
  RefundMemo: RefundMemo;
5865
5942
  CoinPurchaseMemo: CoinPurchaseMemo;
@@ -5875,6 +5952,8 @@ export type MessageType = {
5875
5952
  UnlockPath: UnlockPath;
5876
5953
  UnlockedPathRequest: UnlockedPathRequest;
5877
5954
  UiAnimationRequest: UiAnimationRequest;
5955
+ experimental_message: experimental_message;
5956
+ experimental_field: experimental_field;
5878
5957
  ProtocolInfoRequest: ProtocolInfoRequest;
5879
5958
  ProtocolInfo: ProtocolInfo;
5880
5959
  DeviceReboot: DeviceReboot;
@@ -5888,6 +5967,9 @@ export type MessageType = {
5888
5967
  DeviceCertificateSignature: DeviceCertificateSignature;
5889
5968
  DeviceCertificateSign: DeviceCertificateSign;
5890
5969
  DeviceMiscUsbMscControl: DeviceMiscUsbMscControl;
5970
+ DeviceFindMyTokenUpdate: DeviceFindMyTokenUpdate;
5971
+ DeviceFindMyTokenStateGet: DeviceFindMyTokenStateGet;
5972
+ DeviceFindMyTokenState: DeviceFindMyTokenState;
5891
5973
  DeviceFactoryInfoManufactureTime: DeviceFactoryInfoManufactureTime;
5892
5974
  DeviceFactoryInfo: DeviceFactoryInfo;
5893
5975
  DeviceFactoryInfoSet: DeviceFactoryInfoSet;
@@ -5897,6 +5979,7 @@ export type MessageType = {
5897
5979
  DeviceFirmwareTarget: DeviceFirmwareTarget;
5898
5980
  DeviceFirmwareUpdateStage: DeviceFirmwareUpdateStage;
5899
5981
  DeviceFirmwareUpdateRequest: DeviceFirmwareUpdateRequest;
5982
+ DeviceFirmwareUpdatePhaseInfo: DeviceFirmwareUpdatePhaseInfo;
5900
5983
  DeviceFirmwareUpdateRecord: DeviceFirmwareUpdateRecord;
5901
5984
  DeviceFirmwareUpdateRecordFields: DeviceFirmwareUpdateRecordFields;
5902
5985
  DeviceFirmwareUpdateStatusGet: DeviceFirmwareUpdateStatusGet;
@@ -5935,9 +6018,14 @@ export type MessageType = {
5935
6018
  PortfolioUpdate: PortfolioUpdate;
5936
6019
  ViewAmount: ViewAmount;
5937
6020
  ViewDetail: ViewDetail;
6021
+ ViewCustomField: ViewCustomField;
5938
6022
  ViewTip: ViewTip;
5939
- ViewRawData: ViewRawData;
6023
+ ViewActionCard: ViewActionCard;
6024
+ ViewContentPreview: ViewContentPreview;
6025
+ ViewContentEntry: ViewContentEntry;
6026
+ ViewContentPage: ViewContentPage;
5940
6027
  ViewSignPage: ViewSignPage;
6028
+ ViewWarningPage: ViewWarningPage;
5941
6029
  ViewVerifyPage: ViewVerifyPage;
5942
6030
  };
5943
6031
 
@@ -59,6 +59,8 @@ export type AcquireInput = {
59
59
  * transport must probe the protocol on the wire, bypassing any cached result.
60
60
  */
61
61
  forceProtocolDetection?: boolean;
62
+ /** Reuse expectedProtocol only when this transport previously confirmed it for the same endpoint. */
63
+ skipProtocolProbe?: boolean;
62
64
  };
63
65
 
64
66
  export type MessageFromOneKey = { type: string; message: Record<string, any> };
@@ -77,6 +79,8 @@ export type TransportCallOptions = {
77
79
  onWriteCompleted?: (metrics: TransportWriteMetrics) => void;
78
80
  /** Resolve after the complete request frame is written without waiting for a response. */
79
81
  returnAfterWrite?: boolean;
82
+ /** Observe the delayed terminal response of a write-only call while a later call is active. */
83
+ onResponseAfterWrite?: (response: MessageFromOneKey) => void;
80
84
  /** Prefer acknowledged BLE characteristic writes for this call when supported. */
81
85
  writeWithResponse?: boolean;
82
86
  };
@@ -141,6 +145,8 @@ export type LowlevelTransportSharedPlugin = {
141
145
  receive: (uuid?: string) => Promise<string>;
142
146
  connect: (uuid: string) => Promise<void>;
143
147
  disconnect: (uuid: string) => Promise<void>;
148
+ /** Maximum Protocol V2 bytes accepted by one BLE characteristic write. */
149
+ getProtocolV2PacketCapacity?: (uuid: string) => number | undefined | Promise<number | undefined>;
144
150
 
145
151
  init: () => Promise<void>;
146
152
  version: string;