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

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.11",
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": "8928100acb893d72361eb74422d5e2a0f7af77d8"
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,8 @@ export type EthereumSignTxOneKey = {
1950
1950
  data_length?: number;
1951
1951
  chain_id: number;
1952
1952
  tx_type?: number;
1953
+ expected_address?: string;
1954
+ source_fingerprint?: number;
1953
1955
  };
1954
1956
 
1955
1957
  // EthereumAccessListOneKey
@@ -1971,6 +1973,8 @@ export type EthereumSignTxEIP1559OneKey = {
1971
1973
  data_length: number;
1972
1974
  chain_id: number;
1973
1975
  access_list: EthereumAccessListOneKey[];
1976
+ expected_address?: string;
1977
+ source_fingerprint?: number;
1974
1978
  };
1975
1979
 
1976
1980
  // EthereumAuthorizationSignature
@@ -2023,6 +2027,7 @@ export type EthereumSignMessageOneKey = {
2023
2027
  address_n: number[];
2024
2028
  message: string;
2025
2029
  chain_id?: number;
2030
+ source_fingerprint?: number;
2026
2031
  };
2027
2032
 
2028
2033
  // EthereumMessageSignatureOneKey
@@ -3815,6 +3820,7 @@ export type SolanaSignTx = {
3815
3820
  address_n: number[];
3816
3821
  raw_tx: string;
3817
3822
  extra_info?: SolanaTxExtraInfo;
3823
+ source_fingerprint?: number;
3818
3824
  };
3819
3825
 
3820
3826
  // SolanaSignedTx
@@ -3838,12 +3844,14 @@ export type SolanaSignOffChainMessage = {
3838
3844
  message_version?: SolanaOffChainMessageVersion;
3839
3845
  message_format?: SolanaOffChainMessageFormat;
3840
3846
  application_domain?: string;
3847
+ source_fingerprint?: number;
3841
3848
  };
3842
3849
 
3843
3850
  // SolanaSignUnsafeMessage
3844
3851
  export type SolanaSignUnsafeMessage = {
3845
3852
  address_n: number[];
3846
3853
  message: string;
3854
+ source_fingerprint?: number;
3847
3855
  };
3848
3856
 
3849
3857
  // SolanaMessageSignature
@@ -4550,12 +4558,6 @@ export enum CommandFlags {
4550
4558
  Factory_Only = 1,
4551
4559
  }
4552
4560
 
4553
- // experimental_message
4554
- export type experimental_message = {};
4555
-
4556
- // experimental_field
4557
- export type experimental_field = {};
4558
-
4559
4561
  export type TextMemo = {
4560
4562
  text: string;
4561
4563
  };
@@ -4594,6 +4596,7 @@ export type EthereumSignTypedDataQR = {
4594
4596
  chain_id?: number;
4595
4597
  metamask_v4_compat?: boolean;
4596
4598
  request_id?: string;
4599
+ source_fingerprint?: number;
4597
4600
  };
4598
4601
 
4599
4602
  // SetBusy
@@ -4660,6 +4663,12 @@ export type UiAnimationRequest = {
4660
4663
  type?: UiAnimationType;
4661
4664
  };
4662
4665
 
4666
+ // experimental_message
4667
+ export type experimental_message = {};
4668
+
4669
+ // experimental_field
4670
+ export type experimental_field = {};
4671
+
4663
4672
  // ProtocolInfoRequest
4664
4673
  export type ProtocolInfoRequest = {
4665
4674
  eventless_wallet_session?: boolean;
@@ -4766,6 +4775,19 @@ export type DeviceMiscUsbMscControl = {
4766
4775
  enable: boolean;
4767
4776
  };
4768
4777
 
4778
+ // DeviceFindMyTokenUpdate
4779
+ export type DeviceFindMyTokenUpdate = {
4780
+ token: string;
4781
+ };
4782
+
4783
+ // DeviceFindMyTokenStateGet
4784
+ export type DeviceFindMyTokenStateGet = {};
4785
+
4786
+ // DeviceFindMyTokenState
4787
+ export type DeviceFindMyTokenState = {
4788
+ burned: boolean;
4789
+ };
4790
+
4769
4791
  export enum DeviceFactoryAck {
4770
4792
  FACTORY_ACK_SUCCESS = 0,
4771
4793
  FACTORY_ACK_FAIL = 1,
@@ -4837,6 +4859,12 @@ export enum DeviceFirmwareUpdateTaskStatus {
4837
4859
  FW_MGMT_UPDATER_TASK_STATUS_FAILED_ENTRY_OUT_OF_BOUNDS = 10,
4838
4860
  }
4839
4861
 
4862
+ export enum DeviceFirmwareUpdatePhase {
4863
+ FW_MGMT_UPDATER_PHASE_PREPARE = 0,
4864
+ FW_MGMT_UPDATER_PHASE_INSTALL = 1,
4865
+ FW_MGMT_UPDATER_PHASE_VERIFY = 2,
4866
+ }
4867
+
4840
4868
  // DeviceFirmwareTarget
4841
4869
  export type DeviceFirmwareTarget = {
4842
4870
  target_id: DeviceFirmwareTargetType;
@@ -4849,12 +4877,22 @@ export type DeviceFirmwareUpdateStage = {
4849
4877
  };
4850
4878
 
4851
4879
  // DeviceFirmwareUpdateRequest
4852
- export type DeviceFirmwareUpdateRequest = {};
4880
+ export type DeviceFirmwareUpdateRequest = {
4881
+ reboot_after_update?: boolean;
4882
+ };
4883
+
4884
+ // DeviceFirmwareUpdatePhaseInfo
4885
+ export type DeviceFirmwareUpdatePhaseInfo = {
4886
+ phase: DeviceFirmwareUpdatePhase;
4887
+ progress_percent: number;
4888
+ };
4853
4889
 
4854
4890
  // DeviceFirmwareUpdateRecord
4855
4891
  export type DeviceFirmwareUpdateRecord = {
4856
4892
  target_id: DeviceFirmwareTargetType;
4857
4893
  status?: DeviceFirmwareUpdateTaskStatus;
4894
+ progress_percent?: number;
4895
+ phase_info?: DeviceFirmwareUpdatePhaseInfo;
4858
4896
  payload_version?: number;
4859
4897
  path?: string;
4860
4898
  };
@@ -4862,6 +4900,8 @@ export type DeviceFirmwareUpdateRecord = {
4862
4900
  // DeviceFirmwareUpdateRecordFields
4863
4901
  export type DeviceFirmwareUpdateRecordFields = {
4864
4902
  status?: boolean;
4903
+ progress_percent?: boolean;
4904
+ phase_info?: boolean;
4865
4905
  payload_version?: boolean;
4866
4906
  path?: boolean;
4867
4907
  };
@@ -4992,13 +5032,13 @@ export enum DeviceSessionSeedDomain {
4992
5032
  export type DeviceSessionGet = {
4993
5033
  session_id?: string;
4994
5034
  btc_test_address?: string;
4995
- seed_domains: DeviceSessionSeedDomain[];
4996
5035
  };
4997
5036
 
4998
5037
  // DeviceSession
4999
5038
  export type DeviceSession = {
5000
5039
  session_id?: string;
5001
5040
  btc_test_address?: string;
5041
+ seed_domains: DeviceSessionSeedDomain[];
5002
5042
  };
5003
5043
 
5004
5044
  export enum DeviceSessionPinType {
@@ -5016,6 +5056,7 @@ export type DeviceSessionAskPin = {
5016
5056
  export type DeviceSessionAskPassphrase = {
5017
5057
  passphrase?: string;
5018
5058
  on_device: boolean;
5059
+ seed_domains: DeviceSessionSeedDomain[];
5019
5060
  };
5020
5061
 
5021
5062
  export enum DeviceSessionAskPin_FailureSubCodes {
@@ -5207,6 +5248,12 @@ export type ViewDetail = {
5207
5248
  has_icon: boolean;
5208
5249
  };
5209
5250
 
5251
+ // ViewCustomField
5252
+ export type ViewCustomField = {
5253
+ key: string;
5254
+ value: string;
5255
+ };
5256
+
5210
5257
  export enum ViewTipType {
5211
5258
  Default = 0,
5212
5259
  Highlight = 1,
@@ -5220,12 +5267,33 @@ export type ViewTip = {
5220
5267
  type: ViewTipType;
5221
5268
  text?: string;
5222
5269
  text_id?: number;
5270
+ text_arg?: string;
5223
5271
  };
5224
5272
 
5225
- // ViewRawData
5226
- export type ViewRawData = {
5273
+ // ViewActionCard
5274
+ export type ViewActionCard = {
5227
5275
  initial_data: string;
5228
- placeholder: number;
5276
+ };
5277
+
5278
+ // ViewContentPreview
5279
+ export type ViewContentPreview = {
5280
+ content_key: number;
5281
+ preview: string;
5282
+ total_bytes?: number;
5283
+ };
5284
+
5285
+ // ViewContentEntry
5286
+ export type ViewContentEntry = {
5287
+ entry_key: number;
5288
+ value: string;
5289
+ };
5290
+
5291
+ // ViewContentPage
5292
+ export type ViewContentPage = {
5293
+ page_index: number;
5294
+ page_count: number;
5295
+ chunk?: string;
5296
+ entry?: ViewContentEntry;
5229
5297
  };
5230
5298
 
5231
5299
  export enum ViewSignLayout {
@@ -5243,10 +5311,21 @@ export type ViewSignPage = {
5243
5311
  amount?: UintType;
5244
5312
  general: ViewDetail[];
5245
5313
  tip?: ViewTip;
5246
- raw_data?: ViewRawData;
5314
+ action_card?: ViewActionCard;
5247
5315
  slide_to_confirm?: boolean;
5248
5316
  layout?: ViewSignLayout;
5249
5317
  title_id?: number;
5318
+ title_arg?: string;
5319
+ content?: ViewContentPreview;
5320
+ custom_field?: ViewCustomField;
5321
+ };
5322
+
5323
+ // ViewWarningPage
5324
+ export type ViewWarningPage = {
5325
+ title_id: number;
5326
+ text_id: number;
5327
+ text_arg?: string;
5328
+ cancellable?: boolean;
5250
5329
  };
5251
5330
 
5252
5331
  // ViewVerifyPage
@@ -5259,6 +5338,7 @@ export type ViewVerifyPage = {
5259
5338
  value_key?: number;
5260
5339
  title_id?: number;
5261
5340
  chain_id?: number;
5341
+ content?: ViewContentPreview;
5262
5342
  };
5263
5343
 
5264
5344
  export enum ProtocolV2FailureType {
@@ -5858,8 +5938,6 @@ export type MessageType = {
5858
5938
  TronSignMessage: TronSignMessage;
5859
5939
  TronMessageSignature: TronMessageSignature;
5860
5940
  facotry: facotry;
5861
- experimental_message: experimental_message;
5862
- experimental_field: experimental_field;
5863
5941
  TextMemo: TextMemo;
5864
5942
  RefundMemo: RefundMemo;
5865
5943
  CoinPurchaseMemo: CoinPurchaseMemo;
@@ -5875,6 +5953,8 @@ export type MessageType = {
5875
5953
  UnlockPath: UnlockPath;
5876
5954
  UnlockedPathRequest: UnlockedPathRequest;
5877
5955
  UiAnimationRequest: UiAnimationRequest;
5956
+ experimental_message: experimental_message;
5957
+ experimental_field: experimental_field;
5878
5958
  ProtocolInfoRequest: ProtocolInfoRequest;
5879
5959
  ProtocolInfo: ProtocolInfo;
5880
5960
  DeviceReboot: DeviceReboot;
@@ -5888,6 +5968,9 @@ export type MessageType = {
5888
5968
  DeviceCertificateSignature: DeviceCertificateSignature;
5889
5969
  DeviceCertificateSign: DeviceCertificateSign;
5890
5970
  DeviceMiscUsbMscControl: DeviceMiscUsbMscControl;
5971
+ DeviceFindMyTokenUpdate: DeviceFindMyTokenUpdate;
5972
+ DeviceFindMyTokenStateGet: DeviceFindMyTokenStateGet;
5973
+ DeviceFindMyTokenState: DeviceFindMyTokenState;
5891
5974
  DeviceFactoryInfoManufactureTime: DeviceFactoryInfoManufactureTime;
5892
5975
  DeviceFactoryInfo: DeviceFactoryInfo;
5893
5976
  DeviceFactoryInfoSet: DeviceFactoryInfoSet;
@@ -5897,6 +5980,7 @@ export type MessageType = {
5897
5980
  DeviceFirmwareTarget: DeviceFirmwareTarget;
5898
5981
  DeviceFirmwareUpdateStage: DeviceFirmwareUpdateStage;
5899
5982
  DeviceFirmwareUpdateRequest: DeviceFirmwareUpdateRequest;
5983
+ DeviceFirmwareUpdatePhaseInfo: DeviceFirmwareUpdatePhaseInfo;
5900
5984
  DeviceFirmwareUpdateRecord: DeviceFirmwareUpdateRecord;
5901
5985
  DeviceFirmwareUpdateRecordFields: DeviceFirmwareUpdateRecordFields;
5902
5986
  DeviceFirmwareUpdateStatusGet: DeviceFirmwareUpdateStatusGet;
@@ -5935,9 +6019,14 @@ export type MessageType = {
5935
6019
  PortfolioUpdate: PortfolioUpdate;
5936
6020
  ViewAmount: ViewAmount;
5937
6021
  ViewDetail: ViewDetail;
6022
+ ViewCustomField: ViewCustomField;
5938
6023
  ViewTip: ViewTip;
5939
- ViewRawData: ViewRawData;
6024
+ ViewActionCard: ViewActionCard;
6025
+ ViewContentPreview: ViewContentPreview;
6026
+ ViewContentEntry: ViewContentEntry;
6027
+ ViewContentPage: ViewContentPage;
5940
6028
  ViewSignPage: ViewSignPage;
6029
+ ViewWarningPage: ViewWarningPage;
5941
6030
  ViewVerifyPage: ViewVerifyPage;
5942
6031
  };
5943
6032
 
@@ -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;