import * as transport from '@onekeyfe/hd-transport'; import transport__default, { ProtocolType, OneKeyDeviceInfoBase, TransportCallOptions } from '@onekeyfe/hd-transport'; import { Device, Characteristic, Subscription, BleManager } from 'react-native-ble-plx'; import { Deferred } from '@onekeyfe/hd-shared'; import EventEmitter from 'events'; declare class BleTransport { id: string; name: string; device: Device; mtuSize: number | undefined; writeCharacteristic: Characteristic; notifyCharacteristic: Characteristic; notifySubscription?: Subscription; disconnectSubscription?: Subscription; notifyTransactionId?: string; monitorToken?: number; constructor(device: Device, writeCharacteristic: Characteristic, notifyCharacteristic: Characteristic); /** * Bulk-transfer write (Protocol V1 FirmwareUpload / EmmcFileWrite only). * * Must stay writeWithoutResponse on every platform. writeWithResponse serialises * each packet into its own connection-interval round trip, which on iOS turned a * 1.7MB firmware upload (~13.5k packets) into a >10 minute transfer that never * finished before the app-level timeout. Protocol V2 and ordinary V1 control * messages pick their write type separately and are unaffected by this method. */ writeWithRetry(data: string): Promise; } type TransportOptions = { scanTimeout?: number; }; type BleAcquireInput = { uuid: string; forceCleanRunPromise?: boolean; expectedProtocol?: ProtocolType; protocolHint?: ProtocolType; }; type FirmwareInstallBleAcquireInput = BleAcquireInput & { /** * Reuse the already-verified protocol after an expected firmware-install * disconnect. The install loader accepts status requests but may not answer * the generic protocol probe used by a normal acquire. */ skipProtocolProbe?: boolean; }; type FirmwareUploadWriteRetryType = 'congested'; type ResolvedBleCharacteristics = { writeCharacteristic: Characteristic; notifyCharacteristic: Characteristic; }; declare const getFirmwareUploadWriteRetryType: (error: unknown) => FirmwareUploadWriteRetryType | null; /** * Per-packet write budget. iOS only resolves writeWithoutResponse once CoreBluetooth * reports the peripheral ready again; a peripheral wedged by its own firmware reboot * stops reporting ready while staying connected, so the write promise never settles. * Response timeouts cannot cover that — they are armed after the writes complete — * and an unbounded write leaves the whole transport unusable until the process dies. * A healthy packet completes in milliseconds, so this only fires on a dead link. */ declare const BLE_WRITE_PACKET_TIMEOUT_MS = 10000; declare const BLE_NATIVE_TEARDOWN_TIMEOUT_MS = 3000; /** * Android reports a lost bond (ACTION_KEY_MISSING) while it encrypts a new link, so only * a failure this soon after the link started can be explained by it. Later disconnects, * such as a firmware-update reboot, must keep their own meaning. */ declare const ANDROID_KEY_MISSING_LINK_WINDOW_MS = 10000; /** The broadcast and the GATT disconnect it explains travel separately; either can land first. */ declare const ANDROID_KEY_MISSING_GRACE_MS = 500; /** * Android reports a bonded link's first encryption result within about half a second of * connecting. Past this, the result is treated as unknown and the link is used as before. */ declare const ANDROID_ENCRYPTION_RESULT_TIMEOUT_MS = 1500; /** * A system re-pairing needs the user to accept a pairing request and confirm the code on the * device. The Bluetooth stack gives up after 30s and then reports key missing. */ declare const ANDROID_SYSTEM_REPAIR_TIMEOUT_MS = 35000; /** Consecutive wedged writes on one device before the BLE manager itself is recreated. */ declare const BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = 2; type ProtocolV2BleTuning = { iosPacketLength?: number; androidPacketLength?: number; }; declare function configureProtocolV2BleTuning(tuning?: ProtocolV2BleTuning): void; declare function resetProtocolV2BleTuning(): void; declare function getProtocolV2BleTuning(): { iosPacketLength: number; androidPacketLength: number; }; /** * With no cached GATT table the stack runs its own discovery (up to ~8s) before the MTU * exchange, so the bound sits above that; a stuck exchange never completes. */ declare const ANDROID_MTU_EXCHANGE_TIMEOUT_MS = 12000; /** * Android keeps an LE link, with per-link ATT state such as a pending MTU exchange, for its * 4s GATT link idle timer after the last client closes; a reconnect inside it reuses the link. */ declare const ANDROID_LINK_DROP_QUIET_MS = 5000; /** * JS backstop for connect. The native adapter applies its own 3s budget, but it * schedules that timeout on its serial queue, so a busy queue (e.g. right after a * firmware install tears the link down) can leave the promise unsettled — observed * blocking a reconnect for 61s until the app-level timeout. Healthy connects finish * inside the native budget, so this only fires when the native timeout did not. */ declare const BLE_CONNECT_TIMEOUT_MS: number; /** * Service discovery and characteristic resolution run after connect() succeeds, but * CoreBluetooth schedules them on the same serial queue. If that queue is wedged by a * device reboot, these calls can remain pending forever unless they have their own * budget. */ declare const BLE_GATT_SETUP_TIMEOUT_MS = 10000; /** * How many times a known device may fail its own protocol before we probe the others * again. Reconnect polling during a device reboot repeats this every few seconds, and * probing Protocol V2 costs a 10s Ping timeout, so paying it on every attempt for a * device we just spoke V1 to dominates the wait. A firmware update can legitimately * change a device's protocol, so the shortcut has to expire rather than stick. */ declare const PROTOCOL_REPROBE_FALLBACK_ATTEMPTS = 3; /** BLE setup timeouts since the last successful setup before the manager is recreated. */ declare const BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD = 2; declare const BLE_SETUP_WEDGED_MESSAGE = "BLE setup wedged repeatedly"; type IOneKeyDevice = OneKeyDeviceInfoBase & Device; declare class ReactNativeBleTransport { blePlxManager: BleManager | undefined; _messages: ReturnType | undefined; _messagesV2: ReturnType | undefined; private protocolV2SchemaConfiguration; name: string; configured: boolean; stopped: boolean; private readonly bondAbortController; scanTimeout: number; runPromise: Deferred | null; private runPromiseDeviceId; emitter?: EventEmitter; firmwareUploadWriteRecoveryIds: Set; /** Per-device protocol type detected by active wire-level probe after connect. */ private deviceProtocol; /** * Protocol a probe is currently trying, before the device has confirmed it. Calls * must route with it, but acquire() must not treat it as a detected protocol: a * probe that never answers would otherwise leave the reuse fast path handing out a * transport that was never validated. */ private probingProtocols; /** Consecutive write timeouts per device; reset by any write that completes. */ private writeTimeoutCounts; /** BLE setup timeouts per device since the last complete characteristic resolution. */ private connectionSetupTimeoutCounts; private deviceProtocolHints; /** Protocol this device actually answered on, kept across reconnects of one session. */ private sessionProtocols; /** Endpoints that answered a V2 probe in this transport lifetime. Survives disconnect. */ private confirmedProtocolV2; /** Consecutive detections that failed while trusting sessionProtocols. */ private protocolReprobeFailures; /** Endpoints whose last detection got no answer; 'woken' once their Initialize wake is spent. */ private silentDetections; /** Android endpoints whose cached GATT table is suspect; the next connect refreshes it. */ private androidGattCacheRefreshes; /** * Native encryption/pairing failures seen before Protocol V2 probe starts. * Pro2/Neo GATT connect can succeed on a stale iOS bond; the CCCD write then * fails with ATT 5/15. Remember it so detectProtocol fails immediately. */ private staleBondErrors; /** When the current Android link attempt began; bounds which key-missing signals apply. */ private androidLinkStartedAt; /** iOS acquire attempts whose new link the peer ended; two in a row mean a stale bond. */ private iosPeerTermination; /** Strict or previously confirmed V2 target while acquire installs notifications. */ private acquiringProtocolV2; private protocolV2Assemblers; private protocolV2FrameQueues; private protocolV2FramePromises; private protocolV2Links; private monitorTokens; private disconnectEventTokens; private protocolV2HighVolumeLogSignatures; private androidHighPriorityDevices; private androidPriorityResetTimers; private nextMonitorToken; /** Serializes transport lifecycle changes for the same physical device. */ private lifecycleOperations; private stopPromise?; private scanCleanups; constructor(options: TransportOptions); init(logger: any, emitter: EventEmitter): void; configure(signedData: any): void; configureProtocolV2(signedData: any): void; listen(): void; getPlxManager(): Promise; private waitForManagerReset; resolveCharacteristics(device: Device): Promise; attachDisconnectSubscription(transport: BleTransport, device: Device, uuid: string): void; private emitDeviceDisconnect; reconnectFirmwareUploadTransport(uuid: string, transport: BleTransport): Promise; /** * 获取设备列表 * 在搜索超过超时时间或设备数量大于 5 台时,返回 OneKey 设备, * @returns */ enumerate(): Promise; private installTransportForAcquire; acquire(input: FirmwareInstallBleAcquireInput): Promise<{ uuid: string; protocolType: ProtocolType; }>; private acquireUnlocked; _monitorCharacteristic(characteristic: Characteristic, uuid: string, monitorToken: number, notifyTransactionId: string): Subscription; release(uuid: string, onclose?: boolean): Promise; private releaseUnlocked; private releaseNative; post(session: string, name: string, data: Record): Promise; call(uuid: string, name: string, data: Record, options?: TransportCallOptions): Promise; /** * Android 16+ keeps a bond the device no longer holds keys for. The device drops the link * and the only structured evidence is ACTION_KEY_MISSING, so a link loss right after * connect is re-read as an invalid bond when that signal belongs to the same attempt. */ private resolveAndroidBondInvalid; /** * iOS says why a link ended only on the operation it interrupted, so the native codes are read * and logged here. Codes only: the reason text is localized and cannot be matched or searched. */ private noteIosLinkError; /** * iPhones that do not report a lost bond only show the device ending each new link. One such * attempt keeps its error so Core retries; the second in a row is the stale bond. */ private resolveIosBondInvalid; /** * Android 16+ encrypts a bonded link on its own right after connecting. Subscribing to * notifications before that finishes gets the CCCD write rejected, and the framework's retry * encrypts again with the same stale key; firmware that allows one failure per link then drops * it before the system can re-pair. Holding GATT until the result lets a lost bond be re-paired * in place. Without the platform signal this resolves immediately. */ private waitForAndroidLinkSecurity; private callProtocolV1; stop(): Promise; disconnect(session: string): Promise; private disconnectUnlocked; private runNativeTeardown; private runBestEffortNativeOperation; private runLifecycleOperation; cancel(): Promise; /** * Android: request the MTU with nothing queued ahead and never close the client while it is * outstanding; a link that times out or stays at MTU 23 is dropped. */ private negotiateAndroidMtu; /** Close the client and wait out the link idle timer so the next connect gets a fresh link. */ private dropAndroidLink; /** Run a native connect under the JS backstop budget. */ private connectWithTimeout; /** Resolve the complete GATT shape under a budget so acquire() always settles. */ private resolveCharacteristicsWithTimeout; /** * Give up on a BLE setup operation the native layer did not settle. The abandoned * operation still owns native connection/GATT state that can poison the next attempt, * so it is cleared here without awaiting the same queue that stopped responding. * Returns true when the manager itself was reset so the caller can stop Core retries. */ private abandonStalledConnection; private createWedgedBleSetupError; private getCachedTransport; /** * Write one packet under a bounded budget. A write that never settles means the * peripheral is wedged even though the GATT link still reports connected, so the * link is torn down: releasing JS state alone would leave the poisoned peripheral * cached and every later call would hang on it again. */ private writeBlePacket; /** * Drop a link whose writes stopped completing. The JS state is purged synchronously * so the next acquire() cannot reuse the dead transport, while the native teardown is * intentionally NOT awaited: it talks to the very layer that just stopped settling * promises, so awaiting it could hang exactly like the write it is recovering from. */ private tearDownWedgedLink; private resetPlxManager; private createProtocolMismatchError; private createProtocolDetectionError; private clearProbeProtocol; /** Protocol to route a call with: confirmed if known, otherwise the one being probed. */ private getActiveProtocol; private detectProtocol; /** * A sleeping Classic drops GetFeatures/Ping and only leaves its screensaver on Initialize, which * resets the wallet session, so it is sent once after a fully silent detection. The firmware does * not reliably answer it, so its timeout must not drop the link. It only runs when V1 is probed * first, so a late reply lands on the V1 probe rather than on a V2 one. */ private wakeSilentProtocolV1Device; private resetProbeStateAfterProtocolProbe; private probeProtocolV1; private probeProtocolV2; private handleProtocolV2Notification; private getProtocolV2FrameQueue; private resolveProtocolV2Frame; private resetProtocolV2Frames; private rejectProtocolV2Frames; private rememberStaleBondError; private throwIfStaleBondError; private readProtocolV2Frame; private writeProtocolV2Packet; private writeProtocolV2Frame; private callProtocolV2; private ensureProtocolV2HighThroughputMtu; private clearAndroidPriorityResetTimer; private enableAndroidHighConnectionPriority; private scheduleAndroidBalancedConnectionPriority; private restoreAndroidConnectionPriority; private createProtocolV2Adapter; getProtocolType(path: string): ProtocolType | undefined; } export { ANDROID_ENCRYPTION_RESULT_TIMEOUT_MS, ANDROID_KEY_MISSING_GRACE_MS, ANDROID_KEY_MISSING_LINK_WINDOW_MS, ANDROID_LINK_DROP_QUIET_MS, ANDROID_MTU_EXCHANGE_TIMEOUT_MS, ANDROID_SYSTEM_REPAIR_TIMEOUT_MS, BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD, BLE_CONNECT_TIMEOUT_MS, BLE_GATT_SETUP_TIMEOUT_MS, BLE_NATIVE_TEARDOWN_TIMEOUT_MS, BLE_SETUP_WEDGED_MESSAGE, BLE_WRITE_PACKET_TIMEOUT_MS, BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD, IOneKeyDevice, PROTOCOL_REPROBE_FALLBACK_ATTEMPTS, ProtocolV2BleTuning, configureProtocolV2BleTuning, ReactNativeBleTransport as default, getFirmwareUploadWriteRetryType, getProtocolV2BleTuning, resetProtocolV2BleTuning };