@ledgerhq/device-transport-kit-web-ble 0.0.0-wrong-error-when-in-experimental-provider-20251021162636 → 0.0.0-z-intent-queue-7-20251204111630

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.
@@ -1,2 +1,2 @@
1
- import{DeviceAlreadyConnectedError as D,DeviceConnectionStateMachine as f,GeneralDmkError as S,OpeningConnectionError as l,TransportConnectedDevice as m,UnknownDeviceError as h}from"@ledgerhq/device-management-kit";import{Left as g,Right as p}from"purify-ts";import{BehaviorSubject as w,from as _}from"rxjs";import{switchMap as T}from"rxjs/operators";import{ADVERTISING_DELAY as I,ADVERTISING_TIMEOUT as C,RECONNECT_DEVICE_TIMEOUT as b,RECONNECTION_LOOP_BACKOFF as E,REDISCOVER_TIMEOUT as B}from"../data/WebBleConfig";import{WebBleApduSender as M}from"./WebBleApduSender";const u="WEB-BLE-RN-STYLE";class R{constructor(e,i,t,n){this._deviceModelDataSource=e;this.loggerFactory=i;this._apduSenderFactory=t;this._apduReceiverFactory=n;this._logger=i("WebBleTransportRnStyle")}_logger;_connectionStateMachinesByDeviceId=new Map;_deviceRegistryById=new Map;_discoveredDevices$=new w([]);isSupported(){return typeof navigator<"u"&&!!navigator.bluetooth}getIdentifier(){return u}startDiscovering(){const e=this._deviceModelDataSource.getBluetoothServices().map(t=>({services:[t]})),i=this._deviceModelDataSource.getBluetoothServices();return _(navigator.bluetooth.requestDevice({filters:e,optionalServices:i})).pipe(T(async t=>{const{serviceUuid:n,ledgerServiceInfo:r}=await this._identifyLedgerGattService(t),c={id:t.id,deviceModel:r.deviceModel,transport:u};return this._deviceRegistryById.set(t.id,{device:t,serviceUuid:n,ledgerServiceInfo:r,discoveredDevice:c}),this._publishDiscoveredDevices(),c}))}stopDiscovering(){}listenToAvailableDevices(){return this._publishDiscoveredDevices(),this._discoveredDevices$.asObservable()}async connect(e){const i=this._deviceRegistryById.get(e.deviceId);if(!i)return g(new h(`Unknown device ${e.deviceId}`));if(this._connectionStateMachinesByDeviceId.has(e.deviceId))return g(new D(`Device ${e.deviceId} already connected`));try{const t=i.device;if(!t.gatt)throw new l("No GATT server available on device");t.gatt.connected||(await this._withTimeout(t.gatt.connect(),6e3,"GATT connect timed out"),await this._sleep(150));const{service:n,ledgerServiceInfo:r}=await this._getPrimaryLedgerGattService(t),{writeCharacteristic:c,notifyCharacteristic:d}=await this._resolveLedgerServiceCharacteristics(n,r),o=new M({writeCharacteristic:c,notifyCharacteristic:d,apduSenderFactory:this._apduSenderFactory,apduReceiverFactory:this._apduReceiverFactory},this.loggerFactory),v=new f({deviceId:e.deviceId,deviceApduSender:o,timeoutDuration:b,tryToReconnect:()=>{this._tryToReconnect(e.deviceId,e.onReconnect).catch(a=>this._logger.error("tryToReconnect() threw",{data:{e:a}}))},onTerminated:()=>{try{this._connectionStateMachinesByDeviceId.get(e.deviceId)?.closeConnection(),e.onDisconnect(e.deviceId)}finally{this._connectionStateMachinesByDeviceId.delete(e.deviceId);const a=this._deviceRegistryById.get(e.deviceId);a?.gattDisconnectListener&&(a.device.removeEventListener("gattserverdisconnected",a.gattDisconnectListener),a.gattDisconnectListener=void 0),this._publishDiscoveredDevices()}}});await o.setupConnection(),this._connectionStateMachinesByDeviceId.set(e.deviceId,v),i.serviceUuid=n.uuid,i.ledgerServiceInfo=r;const s=a=>this._handleGattServerDisconnected(e.deviceId);return i.gattDisconnectListener=s,t.addEventListener("gattserverdisconnected",s),this._publishDiscoveredDevices(),p(new m({id:e.deviceId,deviceModel:r.deviceModel,type:"BLE",transport:u,sendApdu:(...a)=>v.sendApdu(...a)}))}catch(t){return this._logger.error("connect() error",{data:{e:t}}),g(new l(t))}}async disconnect(e){const i=e.connectedDevice.id,t=this._connectionStateMachinesByDeviceId.get(i),n=this._deviceRegistryById.get(i);if(!t)return g(new h(`Unknown device ${i}`));try{return t.closeConnection(),this._connectionStateMachinesByDeviceId.delete(i),n?.gattDisconnectListener&&(n.device.removeEventListener("gattserverdisconnected",n.gattDisconnectListener),n.gattDisconnectListener=void 0),await this._safelyCancelGattConnection(i),this._publishDiscoveredDevices(),p(void 0)}catch(r){return g(new S({originalError:r}))}}_handleGattServerDisconnected(e){this._logger.debug(`[${e}] gattserverdisconnected`);const i=this._connectionStateMachinesByDeviceId.get(e);i&&i.eventDeviceDisconnected()}async _waitForAdvertisementInRange(e,i={}){const{startTimeoutMs:t=500,advTimeoutMs:n=1500}=i;if(typeof e.watchAdvertisements!="function")return!1;const r=new AbortController,c=setTimeout(()=>r.abort(),t),d=await e.watchAdvertisements({signal:r.signal}).then(()=>!0).catch(()=>!1);if(clearTimeout(c),!d)return!1;const o=await new Promise(v=>{const s=()=>{e.removeEventListener("advertisementreceived",s),v(!0)};e.addEventListener("advertisementreceived",s),setTimeout(()=>{e.removeEventListener("advertisementreceived",s),v(!1)},n)});return r.abort(),o}async _rediscoverPermittedDevice(e){if(typeof navigator.bluetooth.getDevices!="function")return null;try{this._logger.debug(`Attempting to rediscover device ${e}`);const t=(await navigator.bluetooth.getDevices()).find(n=>n.id===e)??null;if(t){const n=await this._waitForAdvertisementInRange(t,{startTimeoutMs:I,advTimeoutMs:C});this._logger.debug(`Rediscovered ${t.id}, inRange=${n}`)}return t}catch{return null}}async _tryToReconnect(e,i){for(await this._safelyCancelGattConnection(e);;){const t=this._deviceRegistryById.get(e),n=this._connectionStateMachinesByDeviceId.get(e);if(!t||!n){this._logger.debug(`[${e}] aborting reconnect: registry or state machine missing`);return}try{const r=await this._withTimeout(this._rediscoverPermittedDevice(e),B,"rediscovery timeout");if(!r)throw new Error("Device not found");if(!r.gatt)throw new Error("No GATT on device");try{await r.gatt.connect()}catch(a){this._logger.error(`[${e}] gatt.connect() failed`,{data:{e:a}}),r.gatt.connected&&r.gatt.disconnect()}const{service:c,ledgerServiceInfo:d}=await this._getPrimaryLedgerGattService(r),{writeCharacteristic:o,notifyCharacteristic:v}=await this._resolveLedgerServiceCharacteristics(c,d);n.setDependencies({writeCharacteristic:o,notifyCharacteristic:v}),await n.setupConnection(),n.eventDeviceConnected(),t.serviceUuid=c.uuid,t.ledgerServiceInfo=d,t.gattDisconnectListener&&r.removeEventListener("gattserverdisconnected",t.gattDisconnectListener);const s=a=>this._handleGattServerDisconnected(e);r.addEventListener("gattserverdisconnected",s),t.gattDisconnectListener=s,await i?.(e),this._publishDiscoveredDevices();return}catch(r){this._logger.error(`[${e}] reconnect attempt failed`,{data:{e:r}}),t?.device.gatt?.connected&&t.device.gatt.disconnect(),await this._sleep(E);continue}}}async _safelyCancelGattConnection(e){const i=this._deviceRegistryById.get(e);i&&(i.device.gatt?.connected&&i.device.gatt.disconnect(),await this._sleep(100))}async _identifyLedgerGattService(e){if(!e.gatt)throw new l("No GATT server available on device");try{await this._withTimeout(e.gatt.connect(),6e3,"connect timeout");const{service:i,ledgerServiceInfo:t}=await this._getPrimaryLedgerGattService(e);return{serviceUuid:i.uuid,ledgerServiceInfo:t}}finally{e.gatt?.disconnect(),await this._sleep(200)}}async _getPrimaryLedgerGattService(e){const i=this._deviceModelDataSource.getBluetoothServices(),t=this._deviceRegistryById.get(e.id)?.serviceUuid,n=t?[t,...i.filter(r=>r!==t)]:i.slice();for(const r of n)try{const c=await e.gatt.getPrimaryService(r),o=this._deviceModelDataSource.getBluetoothServicesInfos()[c.uuid];if(!o)throw new h(e.name||"");return{service:c,ledgerServiceInfo:o}}catch(c){if(c?.name==="SecurityError")throw new l(`Missing Web Bluetooth permission for service ${r}. Add it to optionalServices in requestDevice().`);try{const o=(await e.gatt.getPrimaryServices()).find(v=>v.uuid.toLowerCase()===r.toLowerCase());if(o){const s=this._deviceModelDataSource.getBluetoothServicesInfos()[o.uuid];if(!s)throw new h(e.name||"");return{service:o,ledgerServiceInfo:s}}}catch{this._logger.error("Failed to get primary services",{data:{deviceId:e.id}})}}throw new l("Ledger GATT service not found")}async _resolveLedgerServiceCharacteristics(e,i){const t=await e.getCharacteristic(i.notifyUuid);return{writeCharacteristic:await this._findWritableCharacteristic(e,i),notifyCharacteristic:t}}async _findWritableCharacteristic(e,i){const t=[i.writeCmdUuid,i.writeUuid].filter(Boolean),n=[];for(const r of t)try{const c=await e.getCharacteristic(r);if(n.push(c),c.properties.writeWithoutResponse||c.properties.write)return c}catch{this._logger.error("Failed to get write characteristic",{data:{deviceId:e.device.id}})}throw new l("No write characteristic available")}_publishDiscoveredDevices(){const e=[];for(const[t]of this._connectionStateMachinesByDeviceId){const n=this._deviceRegistryById.get(t);n?.ledgerServiceInfo&&e.push({id:t,deviceModel:n.ledgerServiceInfo.deviceModel,transport:u})}const i=Array.from(this._deviceRegistryById.values()).map(t=>t.discoveredDevice).filter(t=>!this._connectionStateMachinesByDeviceId.has(t.id));this._discoveredDevices$.next([...e,...i])}_withTimeout(e,i,t,n){return new Promise((r,c)=>{const d=setTimeout(()=>{c(new l(t)),n?.()},i);e.then(o=>{clearTimeout(d),r(o)},o=>{this._logger.error("withTimeout() promise rejected",{data:{e:o}}),clearTimeout(d),c(o)})})}_sleep(e){return new Promise(i=>setTimeout(i,e))}}const F=({deviceModelDataSource:y,loggerServiceFactory:e,apduSenderServiceFactory:i,apduReceiverServiceFactory:t})=>new R(y,e,i,t);export{R as WebBleTransport,u as webBleIdentifier,F as webBleTransportFactory};
1
+ import{DeviceAlreadyConnectedError as D,DeviceConnectionStateMachine as f,GeneralDmkError as m,OpeningConnectionError as l,TransportConnectedDevice as S,UnknownDeviceError as h}from"@ledgerhq/device-management-kit";import{Left as g,Right as p}from"purify-ts";import{BehaviorSubject as w,from as _}from"rxjs";import{switchMap as T}from"rxjs/operators";import{ADVERTISING_DELAY as I,ADVERTISING_TIMEOUT as C,RECONNECT_DEVICE_TIMEOUT as b,RECONNECTION_LOOP_BACKOFF as E,REDISCOVER_TIMEOUT as B}from"../data/WebBleConfig";import{WebBleApduSender as M}from"./WebBleApduSender";const u="WEB-BLE-RN-STYLE";class R{constructor(e,i,t,n){this._deviceModelDataSource=e;this.loggerFactory=i;this._apduSenderFactory=t;this._apduReceiverFactory=n;this._logger=i("WebBleTransportRnStyle")}_logger;_connectionStateMachinesByDeviceId=new Map;_deviceRegistryById=new Map;_discoveredDevices$=new w([]);isSupported(){return typeof navigator<"u"&&!!navigator.bluetooth}getIdentifier(){return u}startDiscovering(){const e=this._deviceModelDataSource.getBluetoothServices().map(t=>({services:[t]})),i=this._deviceModelDataSource.getBluetoothServices();return _(navigator.bluetooth.requestDevice({filters:e,optionalServices:i})).pipe(T(async t=>{const{serviceUuid:n,ledgerServiceInfo:r}=await this._identifyLedgerGattService(t),c={id:t.id,deviceModel:r.deviceModel,transport:u,name:t.name||void 0};return this._deviceRegistryById.set(t.id,{device:t,serviceUuid:n,ledgerServiceInfo:r,discoveredDevice:c}),this._publishDiscoveredDevices(),c}))}stopDiscovering(){}listenToAvailableDevices(){return this._publishDiscoveredDevices(),this._discoveredDevices$.asObservable()}async connect(e){const i=this._deviceRegistryById.get(e.deviceId);if(!i)return g(new h(`Unknown device ${e.deviceId}`));if(this._connectionStateMachinesByDeviceId.has(e.deviceId))return g(new D(`Device ${e.deviceId} already connected`));try{const t=i.device;if(!t.gatt)throw new l("No GATT server available on device");t.gatt.connected||(await this._withTimeout(t.gatt.connect(),6e3,"GATT connect timed out"),await this._sleep(150));const{service:n,ledgerServiceInfo:r}=await this._getPrimaryLedgerGattService(t),{writeCharacteristic:c,notifyCharacteristic:d}=await this._resolveLedgerServiceCharacteristics(n,r),o=new M({writeCharacteristic:c,notifyCharacteristic:d,apduSenderFactory:this._apduSenderFactory,apduReceiverFactory:this._apduReceiverFactory},this.loggerFactory),v=new f({deviceId:e.deviceId,deviceApduSender:o,timeoutDuration:b,tryToReconnect:()=>{this._tryToReconnect(e.deviceId,e.onReconnect).catch(a=>this._logger.error("tryToReconnect() threw",{data:{e:a}}))},onTerminated:()=>{try{this._connectionStateMachinesByDeviceId.get(e.deviceId)?.closeConnection(),e.onDisconnect(e.deviceId)}finally{this._connectionStateMachinesByDeviceId.delete(e.deviceId);const a=this._deviceRegistryById.get(e.deviceId);a?.gattDisconnectListener&&(a.device.removeEventListener("gattserverdisconnected",a.gattDisconnectListener),a.gattDisconnectListener=void 0),this._publishDiscoveredDevices()}}});await o.setupConnection(),this._connectionStateMachinesByDeviceId.set(e.deviceId,v),i.serviceUuid=n.uuid,i.ledgerServiceInfo=r;const s=a=>this._handleGattServerDisconnected(e.deviceId);return i.gattDisconnectListener=s,t.addEventListener("gattserverdisconnected",s),this._publishDiscoveredDevices(),p(new S({id:e.deviceId,deviceModel:r.deviceModel,type:"BLE",transport:u,sendApdu:(...a)=>v.sendApdu(...a),name:t.name||void 0}))}catch(t){return this._logger.error("connect() error",{data:{e:t}}),g(new l(t))}}async disconnect(e){const i=e.connectedDevice.id,t=this._connectionStateMachinesByDeviceId.get(i),n=this._deviceRegistryById.get(i);if(!t)return g(new h(`Unknown device ${i}`));try{return t.closeConnection(),this._connectionStateMachinesByDeviceId.delete(i),n?.gattDisconnectListener&&(n.device.removeEventListener("gattserverdisconnected",n.gattDisconnectListener),n.gattDisconnectListener=void 0),await this._safelyCancelGattConnection(i),this._publishDiscoveredDevices(),p(void 0)}catch(r){return g(new m({originalError:r}))}}_handleGattServerDisconnected(e){this._logger.debug(`[${e}] gattserverdisconnected`);const i=this._connectionStateMachinesByDeviceId.get(e);i&&i.eventDeviceDisconnected()}async _waitForAdvertisementInRange(e,i={}){const{startTimeoutMs:t=500,advTimeoutMs:n=1500}=i;if(typeof e.watchAdvertisements!="function")return!1;const r=new AbortController,c=setTimeout(()=>r.abort(),t),d=await e.watchAdvertisements({signal:r.signal}).then(()=>!0).catch(()=>!1);if(clearTimeout(c),!d)return!1;const o=await new Promise(v=>{const s=()=>{e.removeEventListener("advertisementreceived",s),v(!0)};e.addEventListener("advertisementreceived",s),setTimeout(()=>{e.removeEventListener("advertisementreceived",s),v(!1)},n)});return r.abort(),o}async _rediscoverPermittedDevice(e){if(typeof navigator.bluetooth.getDevices!="function")return null;try{this._logger.debug(`Attempting to rediscover device ${e}`);const t=(await navigator.bluetooth.getDevices()).find(n=>n.id===e)??null;if(t){const n=await this._waitForAdvertisementInRange(t,{startTimeoutMs:I,advTimeoutMs:C});this._logger.debug(`Rediscovered ${t.id}, inRange=${n}`)}return t}catch{return null}}async _tryToReconnect(e,i){for(await this._safelyCancelGattConnection(e);;){const t=this._deviceRegistryById.get(e),n=this._connectionStateMachinesByDeviceId.get(e);if(!t||!n){this._logger.debug(`[${e}] aborting reconnect: registry or state machine missing`);return}try{const r=await this._withTimeout(this._rediscoverPermittedDevice(e),B,"rediscovery timeout");if(!r)throw new Error("Device not found");if(!r.gatt)throw new Error("No GATT on device");try{await r.gatt.connect()}catch(a){this._logger.error(`[${e}] gatt.connect() failed`,{data:{e:a}}),r.gatt.connected&&r.gatt.disconnect()}const{service:c,ledgerServiceInfo:d}=await this._getPrimaryLedgerGattService(r),{writeCharacteristic:o,notifyCharacteristic:v}=await this._resolveLedgerServiceCharacteristics(c,d);n.setDependencies({writeCharacteristic:o,notifyCharacteristic:v}),await n.setupConnection(),n.eventDeviceConnected(),t.serviceUuid=c.uuid,t.ledgerServiceInfo=d,t.gattDisconnectListener&&r.removeEventListener("gattserverdisconnected",t.gattDisconnectListener);const s=a=>this._handleGattServerDisconnected(e);r.addEventListener("gattserverdisconnected",s),t.gattDisconnectListener=s,await i?.(e),this._publishDiscoveredDevices();return}catch(r){this._logger.error(`[${e}] reconnect attempt failed`,{data:{e:r}}),t?.device.gatt?.connected&&t.device.gatt.disconnect(),await this._sleep(E);continue}}}async _safelyCancelGattConnection(e){const i=this._deviceRegistryById.get(e);i&&(i.device.gatt?.connected&&i.device.gatt.disconnect(),await this._sleep(100))}async _identifyLedgerGattService(e){if(!e.gatt)throw new l("No GATT server available on device");try{await this._withTimeout(e.gatt.connect(),6e3,"connect timeout");const{service:i,ledgerServiceInfo:t}=await this._getPrimaryLedgerGattService(e);return{serviceUuid:i.uuid,ledgerServiceInfo:t}}finally{e.gatt?.disconnect(),await this._sleep(200)}}async _getPrimaryLedgerGattService(e){const i=this._deviceModelDataSource.getBluetoothServices(),t=this._deviceRegistryById.get(e.id)?.serviceUuid,n=t?[t,...i.filter(r=>r!==t)]:i.slice();for(const r of n)try{const c=await e.gatt.getPrimaryService(r),o=this._deviceModelDataSource.getBluetoothServicesInfos()[c.uuid];if(!o)throw new h(e.name||"");return{service:c,ledgerServiceInfo:o}}catch(c){if(c?.name==="SecurityError")throw new l(`Missing Web Bluetooth permission for service ${r}. Add it to optionalServices in requestDevice().`);try{const o=(await e.gatt.getPrimaryServices()).find(v=>v.uuid.toLowerCase()===r.toLowerCase());if(o){const s=this._deviceModelDataSource.getBluetoothServicesInfos()[o.uuid];if(!s)throw new h(e.name||"");return{service:o,ledgerServiceInfo:s}}}catch{this._logger.error("Failed to get primary services",{data:{deviceId:e.id}})}}throw new l("Ledger GATT service not found")}async _resolveLedgerServiceCharacteristics(e,i){const t=await e.getCharacteristic(i.notifyUuid);return{writeCharacteristic:await this._findWritableCharacteristic(e,i),notifyCharacteristic:t}}async _findWritableCharacteristic(e,i){const t=[i.writeCmdUuid,i.writeUuid].filter(Boolean),n=[];for(const r of t)try{const c=await e.getCharacteristic(r);if(n.push(c),c.properties.writeWithoutResponse||c.properties.write)return c}catch{this._logger.error("Failed to get write characteristic",{data:{deviceId:e.device.id}})}throw new l("No write characteristic available")}_publishDiscoveredDevices(){const e=[];for(const[t]of this._connectionStateMachinesByDeviceId){const n=this._deviceRegistryById.get(t);n?.ledgerServiceInfo&&e.push({id:t,deviceModel:n.ledgerServiceInfo.deviceModel,transport:u,name:n.device.name||void 0})}const i=Array.from(this._deviceRegistryById.values()).map(t=>t.discoveredDevice).filter(t=>!this._connectionStateMachinesByDeviceId.has(t.id));this._discoveredDevices$.next([...e,...i])}_withTimeout(e,i,t,n){return new Promise((r,c)=>{const d=setTimeout(()=>{c(new l(t)),n?.()},i);e.then(o=>{clearTimeout(d),r(o)},o=>{this._logger.error("withTimeout() promise rejected",{data:{e:o}}),clearTimeout(d),c(o)})})}_sleep(e){return new Promise(i=>setTimeout(i,e))}}const F=({deviceModelDataSource:y,loggerServiceFactory:e,apduSenderServiceFactory:i,apduReceiverServiceFactory:t})=>new R(y,e,i,t);export{R as WebBleTransport,u as webBleIdentifier,F as webBleTransportFactory};
2
2
  //# sourceMappingURL=WebBleTransport.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/api/transport/WebBleTransport.ts"],
4
- "sourcesContent": ["import {\n type ApduReceiverServiceFactory,\n type ApduSenderServiceFactory,\n type ConnectError,\n DeviceAlreadyConnectedError,\n DeviceConnectionStateMachine,\n type DeviceModelDataSource,\n type DmkError,\n GeneralDmkError,\n type LoggerPublisherService,\n OpeningConnectionError,\n type Transport,\n TransportConnectedDevice,\n type TransportDeviceModel,\n type TransportDiscoveredDevice,\n type TransportFactory,\n type TransportIdentifier,\n UnknownDeviceError,\n} from \"@ledgerhq/device-management-kit\";\nimport { type Either, Left, Right } from \"purify-ts\";\nimport { BehaviorSubject, from, type Observable } from \"rxjs\";\nimport { switchMap } from \"rxjs/operators\";\n\nimport {\n ADVERTISING_DELAY,\n ADVERTISING_TIMEOUT,\n RECONNECT_DEVICE_TIMEOUT,\n RECONNECTION_LOOP_BACKOFF,\n REDISCOVER_TIMEOUT,\n} from \"@api/data/WebBleConfig\";\n\nimport {\n WebBleApduSender,\n type WebBleApduSenderDependencies,\n} from \"./WebBleApduSender\";\n\nexport const webBleIdentifier: TransportIdentifier = \"WEB-BLE-RN-STYLE\";\n\ntype DeviceRegistryEntry = {\n device: BluetoothDevice;\n serviceUuid?: string;\n ledgerServiceInfo?: {\n writeCmdUuid: string;\n writeUuid?: string;\n notifyUuid: string;\n deviceModel: TransportDeviceModel;\n };\n discoveredDevice: TransportDiscoveredDevice;\n gattDisconnectListener?: (ev: Event) => void;\n};\n\nexport class WebBleTransport implements Transport {\n private _logger: LoggerPublisherService;\n\n private _connectionStateMachinesByDeviceId = new Map<\n string,\n DeviceConnectionStateMachine<WebBleApduSenderDependencies>\n >();\n private _deviceRegistryById = new Map<string, DeviceRegistryEntry>();\n private _discoveredDevices$ = new BehaviorSubject<\n TransportDiscoveredDevice[]\n >([]);\n\n constructor(\n private readonly _deviceModelDataSource: DeviceModelDataSource,\n private loggerFactory: (tag: string) => LoggerPublisherService,\n private readonly _apduSenderFactory: ApduSenderServiceFactory,\n private readonly _apduReceiverFactory: ApduReceiverServiceFactory,\n ) {\n this._logger = loggerFactory(\"WebBleTransportRnStyle\");\n }\n\n isSupported(): boolean {\n return typeof navigator !== \"undefined\" && !!navigator.bluetooth;\n }\n\n getIdentifier(): TransportIdentifier {\n return webBleIdentifier;\n }\n\n startDiscovering(): Observable<TransportDiscoveredDevice> {\n const bluetoothServiceUuids = this._deviceModelDataSource\n .getBluetoothServices()\n .map((serviceUuid) => ({ services: [serviceUuid] }));\n const allOptionalServiceUuids =\n this._deviceModelDataSource.getBluetoothServices();\n\n return from(\n navigator.bluetooth.requestDevice({\n filters: bluetoothServiceUuids,\n optionalServices: allOptionalServiceUuids,\n }),\n ).pipe(\n switchMap(async (bluetoothDevice) => {\n const { serviceUuid, ledgerServiceInfo } =\n await this._identifyLedgerGattService(bluetoothDevice);\n\n const discoveredDevice: TransportDiscoveredDevice = {\n id: bluetoothDevice.id,\n deviceModel: ledgerServiceInfo.deviceModel,\n transport: webBleIdentifier,\n };\n\n this._deviceRegistryById.set(bluetoothDevice.id, {\n device: bluetoothDevice,\n serviceUuid,\n ledgerServiceInfo,\n discoveredDevice,\n });\n\n this._publishDiscoveredDevices();\n return discoveredDevice;\n }),\n );\n }\n\n stopDiscovering(): void {\n /* no-op on Web Bluetooth */\n }\n\n listenToAvailableDevices(): Observable<TransportDiscoveredDevice[]> {\n this._publishDiscoveredDevices();\n return this._discoveredDevices$.asObservable();\n }\n\n async connect(params: {\n deviceId: string;\n onDisconnect: (deviceId: string) => void;\n onReconnect?: (deviceId: string) => Promise<void> | void;\n }): Promise<Either<ConnectError, TransportConnectedDevice>> {\n const registryEntry = this._deviceRegistryById.get(params.deviceId);\n if (!registryEntry)\n return Left(new UnknownDeviceError(`Unknown device ${params.deviceId}`));\n\n if (this._connectionStateMachinesByDeviceId.has(params.deviceId)) {\n return Left(\n new DeviceAlreadyConnectedError(\n `Device ${params.deviceId} already connected`,\n ),\n );\n }\n\n try {\n const bluetoothDevice = registryEntry.device;\n if (!bluetoothDevice.gatt) {\n throw new OpeningConnectionError(\"No GATT server available on device\");\n }\n\n if (!bluetoothDevice.gatt.connected) {\n await this._withTimeout(\n bluetoothDevice.gatt.connect(),\n 6000,\n \"GATT connect timed out\",\n );\n await this._sleep(150);\n }\n\n const { service: ledgerService, ledgerServiceInfo } =\n await this._getPrimaryLedgerGattService(bluetoothDevice);\n const {\n writeCharacteristic: gattWriteCharacteristic,\n notifyCharacteristic: gattNotifyCharacteristic,\n } = await this._resolveLedgerServiceCharacteristics(\n ledgerService,\n ledgerServiceInfo,\n );\n\n const apduSender = new WebBleApduSender(\n {\n writeCharacteristic: gattWriteCharacteristic,\n notifyCharacteristic: gattNotifyCharacteristic,\n apduSenderFactory: this._apduSenderFactory,\n apduReceiverFactory: this._apduReceiverFactory,\n },\n this.loggerFactory,\n );\n\n const connectionStateMachine =\n new DeviceConnectionStateMachine<WebBleApduSenderDependencies>({\n deviceId: params.deviceId,\n deviceApduSender: apduSender,\n timeoutDuration: RECONNECT_DEVICE_TIMEOUT,\n tryToReconnect: () => {\n this._tryToReconnect(params.deviceId, params.onReconnect).catch(\n (e) =>\n this._logger.error(\"tryToReconnect() threw\", { data: { e } }),\n );\n },\n onTerminated: () => {\n try {\n this._connectionStateMachinesByDeviceId\n .get(params.deviceId)\n ?.closeConnection();\n params.onDisconnect(params.deviceId);\n } finally {\n this._connectionStateMachinesByDeviceId.delete(params.deviceId);\n const entry = this._deviceRegistryById.get(params.deviceId);\n if (entry?.gattDisconnectListener) {\n entry.device.removeEventListener(\n \"gattserverdisconnected\",\n entry.gattDisconnectListener,\n );\n entry.gattDisconnectListener = undefined;\n }\n this._publishDiscoveredDevices();\n }\n },\n });\n\n await apduSender.setupConnection();\n\n this._connectionStateMachinesByDeviceId.set(\n params.deviceId,\n connectionStateMachine,\n );\n registryEntry.serviceUuid = ledgerService.uuid;\n registryEntry.ledgerServiceInfo = ledgerServiceInfo;\n\n const onGattDisconnected = (_ev: Event) =>\n this._handleGattServerDisconnected(params.deviceId);\n registryEntry.gattDisconnectListener = onGattDisconnected;\n bluetoothDevice.addEventListener(\n \"gattserverdisconnected\",\n onGattDisconnected,\n );\n\n this._publishDiscoveredDevices();\n\n return Right(\n new TransportConnectedDevice({\n id: params.deviceId,\n deviceModel: ledgerServiceInfo.deviceModel,\n type: \"BLE\",\n transport: webBleIdentifier,\n sendApdu: (...apduArgs) =>\n connectionStateMachine.sendApdu(...apduArgs),\n }),\n );\n } catch (e) {\n this._logger.error(\"connect() error\", { data: { e } });\n return Left(new OpeningConnectionError(e));\n }\n }\n\n async disconnect(params: {\n connectedDevice: TransportConnectedDevice;\n }): Promise<Either<DmkError, void>> {\n const deviceId = params.connectedDevice.id;\n const connectionStateMachine =\n this._connectionStateMachinesByDeviceId.get(deviceId);\n const registryEntry = this._deviceRegistryById.get(deviceId);\n if (!connectionStateMachine)\n return Left(new UnknownDeviceError(`Unknown device ${deviceId}`));\n\n try {\n connectionStateMachine.closeConnection();\n this._connectionStateMachinesByDeviceId.delete(deviceId);\n if (registryEntry?.gattDisconnectListener) {\n registryEntry.device.removeEventListener(\n \"gattserverdisconnected\",\n registryEntry.gattDisconnectListener,\n );\n registryEntry.gattDisconnectListener = undefined;\n }\n await this._safelyCancelGattConnection(deviceId);\n this._publishDiscoveredDevices();\n return Right(undefined);\n } catch (e) {\n return Left(new GeneralDmkError({ originalError: e }));\n }\n }\n\n private _handleGattServerDisconnected(deviceId: string) {\n this._logger.debug(`[${deviceId}] gattserverdisconnected`);\n const connectionStateMachine =\n this._connectionStateMachinesByDeviceId.get(deviceId);\n if (!connectionStateMachine) return;\n connectionStateMachine.eventDeviceDisconnected();\n }\n\n private async _waitForAdvertisementInRange(\n device: BluetoothDevice,\n opts: { startTimeoutMs?: number; advTimeoutMs?: number } = {},\n ): Promise<boolean> {\n const { startTimeoutMs = 500, advTimeoutMs = 1500 } = opts;\n if (typeof device.watchAdvertisements !== \"function\") return false;\n\n const abortController = new AbortController();\n const startTimer = setTimeout(\n () => abortController.abort(),\n startTimeoutMs,\n );\n const advertisementsStarted = await device\n .watchAdvertisements({ signal: abortController.signal })\n .then(() => true)\n .catch(() => false);\n clearTimeout(startTimer);\n if (!advertisementsStarted) return false;\n\n const advertisementSeen = await new Promise<boolean>((resolve) => {\n const handleAdvertisement = () => {\n device.removeEventListener(\n \"advertisementreceived\",\n handleAdvertisement,\n );\n resolve(true);\n };\n device.addEventListener(\"advertisementreceived\", handleAdvertisement);\n setTimeout(() => {\n device.removeEventListener(\n \"advertisementreceived\",\n handleAdvertisement,\n );\n resolve(false);\n }, advTimeoutMs);\n });\n\n abortController.abort();\n return advertisementSeen;\n }\n\n private async _rediscoverPermittedDevice(\n targetDeviceId: string,\n ): Promise<BluetoothDevice | null> {\n if (typeof navigator.bluetooth.getDevices !== \"function\") return null;\n try {\n this._logger.debug(`Attempting to rediscover device ${targetDeviceId}`);\n const permittedDevices = await navigator.bluetooth.getDevices();\n const matchingDevice =\n permittedDevices.find((d) => d.id === targetDeviceId) ?? null;\n\n if (matchingDevice) {\n const isInRange = await this._waitForAdvertisementInRange(\n matchingDevice,\n {\n startTimeoutMs: ADVERTISING_DELAY,\n advTimeoutMs: ADVERTISING_TIMEOUT,\n },\n );\n this._logger.debug(\n `Rediscovered ${matchingDevice.id}, inRange=${isInRange}`,\n );\n }\n return matchingDevice;\n } catch {\n return null;\n }\n }\n\n private async _tryToReconnect(\n deviceId: string,\n onReconnect?: (id: string) => Promise<void> | void,\n ) {\n await this._safelyCancelGattConnection(deviceId);\n\n while (true) {\n const registryEntry = this._deviceRegistryById.get(deviceId);\n const connectionStateMachine =\n this._connectionStateMachinesByDeviceId.get(deviceId);\n\n if (!registryEntry || !connectionStateMachine) {\n this._logger.debug(\n `[${deviceId}] aborting reconnect: registry or state machine missing`,\n );\n return;\n }\n\n try {\n const rediscoveredDevice = await this._withTimeout(\n this._rediscoverPermittedDevice(deviceId),\n REDISCOVER_TIMEOUT,\n \"rediscovery timeout\",\n );\n\n if (!rediscoveredDevice) throw new Error(\"Device not found\");\n\n if (!rediscoveredDevice.gatt) throw new Error(\"No GATT on device\");\n\n try {\n await rediscoveredDevice.gatt.connect();\n } catch (e) {\n this._logger.error(`[${deviceId}] gatt.connect() failed`, {\n data: { e },\n });\n if (rediscoveredDevice.gatt.connected)\n rediscoveredDevice.gatt.disconnect();\n }\n\n const { service: ledgerService, ledgerServiceInfo } =\n await this._getPrimaryLedgerGattService(rediscoveredDevice);\n\n const {\n writeCharacteristic: gattWriteCharacteristic,\n notifyCharacteristic: gattNotifyCharacteristic,\n } = await this._resolveLedgerServiceCharacteristics(\n ledgerService,\n ledgerServiceInfo,\n );\n\n connectionStateMachine.setDependencies({\n writeCharacteristic: gattWriteCharacteristic,\n notifyCharacteristic: gattNotifyCharacteristic,\n });\n await connectionStateMachine.setupConnection();\n connectionStateMachine.eventDeviceConnected();\n\n registryEntry.serviceUuid = ledgerService.uuid;\n registryEntry.ledgerServiceInfo = ledgerServiceInfo;\n\n if (registryEntry.gattDisconnectListener) {\n rediscoveredDevice.removeEventListener(\n \"gattserverdisconnected\",\n registryEntry.gattDisconnectListener,\n );\n }\n\n const onDisconnectedCallback = (_: Event) =>\n this._handleGattServerDisconnected(deviceId);\n\n rediscoveredDevice.addEventListener(\n \"gattserverdisconnected\",\n onDisconnectedCallback,\n );\n\n registryEntry.gattDisconnectListener = onDisconnectedCallback;\n\n await onReconnect?.(deviceId);\n\n this._publishDiscoveredDevices();\n\n return;\n } catch (e) {\n this._logger.error(`[${deviceId}] reconnect attempt failed`, {\n data: { e },\n });\n\n if (registryEntry?.device.gatt?.connected)\n registryEntry.device.gatt.disconnect();\n\n await this._sleep(RECONNECTION_LOOP_BACKOFF);\n continue;\n }\n }\n }\n\n private async _safelyCancelGattConnection(deviceId: string) {\n const registryEntry = this._deviceRegistryById.get(deviceId);\n if (!registryEntry) return;\n if (registryEntry.device.gatt?.connected)\n registryEntry.device.gatt.disconnect();\n await this._sleep(100);\n }\n\n private async _identifyLedgerGattService(device: BluetoothDevice): Promise<{\n serviceUuid: string;\n ledgerServiceInfo: NonNullable<DeviceRegistryEntry[\"ledgerServiceInfo\"]>;\n }> {\n if (!device.gatt) {\n throw new OpeningConnectionError(\"No GATT server available on device\");\n }\n try {\n await this._withTimeout(device.gatt.connect(), 6000, \"connect timeout\");\n const { service, ledgerServiceInfo } =\n await this._getPrimaryLedgerGattService(device);\n return { serviceUuid: service.uuid, ledgerServiceInfo };\n } finally {\n device.gatt?.disconnect();\n await this._sleep(200);\n }\n }\n\n private async _getPrimaryLedgerGattService(device: BluetoothDevice): Promise<{\n service: BluetoothRemoteGATTService;\n ledgerServiceInfo: NonNullable<DeviceRegistryEntry[\"ledgerServiceInfo\"]>;\n }> {\n const knownLedgerServiceUuids =\n this._deviceModelDataSource.getBluetoothServices();\n const lastSuccessfulServiceUuid = this._deviceRegistryById.get(\n device.id,\n )?.serviceUuid;\n const preferredSearchOrder = lastSuccessfulServiceUuid\n ? [\n lastSuccessfulServiceUuid,\n ...knownLedgerServiceUuids.filter(\n (u) => u !== lastSuccessfulServiceUuid,\n ),\n ]\n : knownLedgerServiceUuids.slice();\n\n for (const candidateUuid of preferredSearchOrder) {\n try {\n const primaryService =\n await device.gatt!.getPrimaryService(candidateUuid);\n const ledgerServiceInfoMap =\n this._deviceModelDataSource.getBluetoothServicesInfos();\n const ledgerServiceInfo = ledgerServiceInfoMap[primaryService.uuid];\n if (!ledgerServiceInfo) throw new UnknownDeviceError(device.name || \"\");\n return { service: primaryService, ledgerServiceInfo };\n } catch (e: unknown) {\n if ((e as Error)?.name === \"SecurityError\") {\n throw new OpeningConnectionError(\n `Missing Web Bluetooth permission for service ${candidateUuid}. ` +\n `Add it to optionalServices in requestDevice().`,\n );\n }\n try {\n const allPrimaryServices = await device.gatt!.getPrimaryServices();\n const matchedService = allPrimaryServices.find(\n (s) => s.uuid.toLowerCase() === candidateUuid.toLowerCase(),\n );\n if (matchedService) {\n const ledgerServiceInfoMap =\n this._deviceModelDataSource.getBluetoothServicesInfos();\n const ledgerServiceInfo = ledgerServiceInfoMap[matchedService.uuid];\n if (!ledgerServiceInfo)\n throw new UnknownDeviceError(device.name || \"\");\n return { service: matchedService, ledgerServiceInfo };\n }\n } catch {\n this._logger.error(\"Failed to get primary services\", {\n data: { deviceId: device.id },\n });\n }\n }\n }\n throw new OpeningConnectionError(\"Ledger GATT service not found\");\n }\n\n private async _resolveLedgerServiceCharacteristics(\n service: BluetoothRemoteGATTService,\n ledgerServiceInfo: NonNullable<DeviceRegistryEntry[\"ledgerServiceInfo\"]>,\n ): Promise<{\n writeCharacteristic: BluetoothRemoteGATTCharacteristic;\n notifyCharacteristic: BluetoothRemoteGATTCharacteristic;\n }> {\n const notifyCharacteristic = await service.getCharacteristic(\n ledgerServiceInfo.notifyUuid,\n );\n const writeCharacteristic = await this._findWritableCharacteristic(\n service,\n ledgerServiceInfo,\n );\n return { writeCharacteristic, notifyCharacteristic };\n }\n\n private async _findWritableCharacteristic(\n service: BluetoothRemoteGATTService,\n ledgerServiceInfo: NonNullable<DeviceRegistryEntry[\"ledgerServiceInfo\"]>,\n ): Promise<BluetoothRemoteGATTCharacteristic> {\n const preferredCharacteristicUuids = [\n ledgerServiceInfo.writeCmdUuid,\n ledgerServiceInfo.writeUuid,\n ].filter(Boolean) as string[];\n\n const attemptedCharacteristics: BluetoothRemoteGATTCharacteristic[] = [];\n\n for (const uuid of preferredCharacteristicUuids) {\n try {\n const characteristic = await service.getCharacteristic(uuid);\n attemptedCharacteristics.push(characteristic);\n\n if (characteristic.properties.writeWithoutResponse)\n return characteristic;\n if (characteristic.properties.write) return characteristic;\n } catch {\n this._logger.error(\"Failed to get write characteristic\", {\n data: { deviceId: service.device.id },\n });\n }\n }\n\n throw new OpeningConnectionError(\"No write characteristic available\");\n }\n\n private _publishDiscoveredDevices() {\n const connectedSummaries: TransportDiscoveredDevice[] = [];\n for (const [deviceId] of this._connectionStateMachinesByDeviceId) {\n const registryEntry = this._deviceRegistryById.get(deviceId);\n if (registryEntry?.ledgerServiceInfo) {\n connectedSummaries.push({\n id: deviceId,\n deviceModel: registryEntry.ledgerServiceInfo.deviceModel,\n transport: webBleIdentifier,\n });\n }\n }\n const scannedSummaries = Array.from(this._deviceRegistryById.values())\n .map((entry) => entry.discoveredDevice)\n .filter(\n (summary) => !this._connectionStateMachinesByDeviceId.has(summary.id),\n );\n\n this._discoveredDevices$.next([...connectedSummaries, ...scannedSummaries]);\n }\n\n private _withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n timeoutMessage: string,\n onTimeoutCancel?: () => void,\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timeoutHandle = setTimeout(() => {\n reject(new OpeningConnectionError(timeoutMessage));\n onTimeoutCancel?.();\n }, timeoutMs);\n promise.then(\n (value) => {\n clearTimeout(timeoutHandle);\n resolve(value);\n },\n (error) => {\n this._logger.error(\"withTimeout() promise rejected\", {\n data: { e: error },\n });\n clearTimeout(timeoutHandle);\n reject(error);\n },\n );\n });\n }\n\n private _sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\nexport const webBleTransportFactory: TransportFactory = ({\n deviceModelDataSource,\n loggerServiceFactory,\n apduSenderServiceFactory,\n apduReceiverServiceFactory,\n}) =>\n new WebBleTransport(\n deviceModelDataSource,\n loggerServiceFactory,\n apduSenderServiceFactory,\n apduReceiverServiceFactory,\n );\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n type ApduReceiverServiceFactory,\n type ApduSenderServiceFactory,\n type ConnectError,\n DeviceAlreadyConnectedError,\n DeviceConnectionStateMachine,\n type DeviceModelDataSource,\n type DmkError,\n GeneralDmkError,\n type LoggerPublisherService,\n OpeningConnectionError,\n type Transport,\n TransportConnectedDevice,\n type TransportDeviceModel,\n type TransportDiscoveredDevice,\n type TransportFactory,\n type TransportIdentifier,\n UnknownDeviceError,\n} from \"@ledgerhq/device-management-kit\";\nimport { type Either, Left, Right } from \"purify-ts\";\nimport { BehaviorSubject, from, type Observable } from \"rxjs\";\nimport { switchMap } from \"rxjs/operators\";\n\nimport {\n ADVERTISING_DELAY,\n ADVERTISING_TIMEOUT,\n RECONNECT_DEVICE_TIMEOUT,\n RECONNECTION_LOOP_BACKOFF,\n REDISCOVER_TIMEOUT,\n} from \"@api/data/WebBleConfig\";\n\nimport {\n WebBleApduSender,\n type WebBleApduSenderDependencies,\n} from \"./WebBleApduSender\";\n\nexport const webBleIdentifier: TransportIdentifier = \"WEB-BLE-RN-STYLE\";\n\ntype DeviceRegistryEntry = {\n device: BluetoothDevice;\n serviceUuid?: string;\n ledgerServiceInfo?: {\n writeCmdUuid: string;\n writeUuid?: string;\n notifyUuid: string;\n deviceModel: TransportDeviceModel;\n };\n discoveredDevice: TransportDiscoveredDevice;\n gattDisconnectListener?: (ev: Event) => void;\n};\n\nexport class WebBleTransport implements Transport {\n private _logger: LoggerPublisherService;\n\n private _connectionStateMachinesByDeviceId = new Map<\n string,\n DeviceConnectionStateMachine<WebBleApduSenderDependencies>\n >();\n private _deviceRegistryById = new Map<string, DeviceRegistryEntry>();\n private _discoveredDevices$ = new BehaviorSubject<\n TransportDiscoveredDevice[]\n >([]);\n\n constructor(\n private readonly _deviceModelDataSource: DeviceModelDataSource,\n private loggerFactory: (tag: string) => LoggerPublisherService,\n private readonly _apduSenderFactory: ApduSenderServiceFactory,\n private readonly _apduReceiverFactory: ApduReceiverServiceFactory,\n ) {\n this._logger = loggerFactory(\"WebBleTransportRnStyle\");\n }\n\n isSupported(): boolean {\n return typeof navigator !== \"undefined\" && !!navigator.bluetooth;\n }\n\n getIdentifier(): TransportIdentifier {\n return webBleIdentifier;\n }\n\n startDiscovering(): Observable<TransportDiscoveredDevice> {\n const bluetoothServiceUuids = this._deviceModelDataSource\n .getBluetoothServices()\n .map((serviceUuid) => ({ services: [serviceUuid] }));\n const allOptionalServiceUuids =\n this._deviceModelDataSource.getBluetoothServices();\n\n return from(\n navigator.bluetooth.requestDevice({\n filters: bluetoothServiceUuids,\n optionalServices: allOptionalServiceUuids,\n }),\n ).pipe(\n switchMap(async (bluetoothDevice) => {\n const { serviceUuid, ledgerServiceInfo } =\n await this._identifyLedgerGattService(bluetoothDevice);\n\n const discoveredDevice: TransportDiscoveredDevice = {\n id: bluetoothDevice.id,\n deviceModel: ledgerServiceInfo.deviceModel,\n transport: webBleIdentifier,\n name: bluetoothDevice.name || undefined,\n };\n\n this._deviceRegistryById.set(bluetoothDevice.id, {\n device: bluetoothDevice,\n serviceUuid,\n ledgerServiceInfo,\n discoveredDevice,\n });\n\n this._publishDiscoveredDevices();\n return discoveredDevice;\n }),\n );\n }\n\n stopDiscovering(): void {\n /* no-op on Web Bluetooth */\n }\n\n listenToAvailableDevices(): Observable<TransportDiscoveredDevice[]> {\n this._publishDiscoveredDevices();\n return this._discoveredDevices$.asObservable();\n }\n\n async connect(params: {\n deviceId: string;\n onDisconnect: (deviceId: string) => void;\n onReconnect?: (deviceId: string) => Promise<void> | void;\n }): Promise<Either<ConnectError, TransportConnectedDevice>> {\n const registryEntry = this._deviceRegistryById.get(params.deviceId);\n if (!registryEntry)\n return Left(new UnknownDeviceError(`Unknown device ${params.deviceId}`));\n\n if (this._connectionStateMachinesByDeviceId.has(params.deviceId)) {\n return Left(\n new DeviceAlreadyConnectedError(\n `Device ${params.deviceId} already connected`,\n ),\n );\n }\n\n try {\n const bluetoothDevice = registryEntry.device;\n if (!bluetoothDevice.gatt) {\n throw new OpeningConnectionError(\"No GATT server available on device\");\n }\n\n if (!bluetoothDevice.gatt.connected) {\n await this._withTimeout(\n bluetoothDevice.gatt.connect(),\n 6000,\n \"GATT connect timed out\",\n );\n await this._sleep(150);\n }\n\n const { service: ledgerService, ledgerServiceInfo } =\n await this._getPrimaryLedgerGattService(bluetoothDevice);\n const {\n writeCharacteristic: gattWriteCharacteristic,\n notifyCharacteristic: gattNotifyCharacteristic,\n } = await this._resolveLedgerServiceCharacteristics(\n ledgerService,\n ledgerServiceInfo,\n );\n\n const apduSender = new WebBleApduSender(\n {\n writeCharacteristic: gattWriteCharacteristic,\n notifyCharacteristic: gattNotifyCharacteristic,\n apduSenderFactory: this._apduSenderFactory,\n apduReceiverFactory: this._apduReceiverFactory,\n },\n this.loggerFactory,\n );\n\n const connectionStateMachine =\n new DeviceConnectionStateMachine<WebBleApduSenderDependencies>({\n deviceId: params.deviceId,\n deviceApduSender: apduSender,\n timeoutDuration: RECONNECT_DEVICE_TIMEOUT,\n tryToReconnect: () => {\n this._tryToReconnect(params.deviceId, params.onReconnect).catch(\n (e) =>\n this._logger.error(\"tryToReconnect() threw\", { data: { e } }),\n );\n },\n onTerminated: () => {\n try {\n this._connectionStateMachinesByDeviceId\n .get(params.deviceId)\n ?.closeConnection();\n params.onDisconnect(params.deviceId);\n } finally {\n this._connectionStateMachinesByDeviceId.delete(params.deviceId);\n const entry = this._deviceRegistryById.get(params.deviceId);\n if (entry?.gattDisconnectListener) {\n entry.device.removeEventListener(\n \"gattserverdisconnected\",\n entry.gattDisconnectListener,\n );\n entry.gattDisconnectListener = undefined;\n }\n this._publishDiscoveredDevices();\n }\n },\n });\n\n await apduSender.setupConnection();\n\n this._connectionStateMachinesByDeviceId.set(\n params.deviceId,\n connectionStateMachine,\n );\n registryEntry.serviceUuid = ledgerService.uuid;\n registryEntry.ledgerServiceInfo = ledgerServiceInfo;\n\n const onGattDisconnected = (_ev: Event) =>\n this._handleGattServerDisconnected(params.deviceId);\n registryEntry.gattDisconnectListener = onGattDisconnected;\n bluetoothDevice.addEventListener(\n \"gattserverdisconnected\",\n onGattDisconnected,\n );\n\n this._publishDiscoveredDevices();\n\n return Right(\n new TransportConnectedDevice({\n id: params.deviceId,\n deviceModel: ledgerServiceInfo.deviceModel,\n type: \"BLE\",\n transport: webBleIdentifier,\n sendApdu: (...apduArgs) =>\n connectionStateMachine.sendApdu(...apduArgs),\n name: bluetoothDevice.name || undefined,\n }),\n );\n } catch (e) {\n this._logger.error(\"connect() error\", { data: { e } });\n return Left(new OpeningConnectionError(e));\n }\n }\n\n async disconnect(params: {\n connectedDevice: TransportConnectedDevice;\n }): Promise<Either<DmkError, void>> {\n const deviceId = params.connectedDevice.id;\n const connectionStateMachine =\n this._connectionStateMachinesByDeviceId.get(deviceId);\n const registryEntry = this._deviceRegistryById.get(deviceId);\n if (!connectionStateMachine)\n return Left(new UnknownDeviceError(`Unknown device ${deviceId}`));\n\n try {\n connectionStateMachine.closeConnection();\n this._connectionStateMachinesByDeviceId.delete(deviceId);\n if (registryEntry?.gattDisconnectListener) {\n registryEntry.device.removeEventListener(\n \"gattserverdisconnected\",\n registryEntry.gattDisconnectListener,\n );\n registryEntry.gattDisconnectListener = undefined;\n }\n await this._safelyCancelGattConnection(deviceId);\n this._publishDiscoveredDevices();\n return Right(undefined);\n } catch (e) {\n return Left(new GeneralDmkError({ originalError: e }));\n }\n }\n\n private _handleGattServerDisconnected(deviceId: string) {\n this._logger.debug(`[${deviceId}] gattserverdisconnected`);\n const connectionStateMachine =\n this._connectionStateMachinesByDeviceId.get(deviceId);\n if (!connectionStateMachine) return;\n connectionStateMachine.eventDeviceDisconnected();\n }\n\n private async _waitForAdvertisementInRange(\n device: BluetoothDevice,\n opts: { startTimeoutMs?: number; advTimeoutMs?: number } = {},\n ): Promise<boolean> {\n const { startTimeoutMs = 500, advTimeoutMs = 1500 } = opts;\n if (typeof device.watchAdvertisements !== \"function\") return false;\n\n const abortController = new AbortController();\n const startTimer = setTimeout(\n () => abortController.abort(),\n startTimeoutMs,\n );\n const advertisementsStarted = await device\n .watchAdvertisements({ signal: abortController.signal })\n .then(() => true)\n .catch(() => false);\n clearTimeout(startTimer);\n if (!advertisementsStarted) return false;\n\n const advertisementSeen = await new Promise<boolean>((resolve) => {\n const handleAdvertisement = () => {\n device.removeEventListener(\n \"advertisementreceived\",\n handleAdvertisement,\n );\n resolve(true);\n };\n device.addEventListener(\"advertisementreceived\", handleAdvertisement);\n setTimeout(() => {\n device.removeEventListener(\n \"advertisementreceived\",\n handleAdvertisement,\n );\n resolve(false);\n }, advTimeoutMs);\n });\n\n abortController.abort();\n return advertisementSeen;\n }\n\n private async _rediscoverPermittedDevice(\n targetDeviceId: string,\n ): Promise<BluetoothDevice | null> {\n if (typeof navigator.bluetooth.getDevices !== \"function\") return null;\n try {\n this._logger.debug(`Attempting to rediscover device ${targetDeviceId}`);\n const permittedDevices = await navigator.bluetooth.getDevices();\n const matchingDevice =\n permittedDevices.find((d) => d.id === targetDeviceId) ?? null;\n\n if (matchingDevice) {\n const isInRange = await this._waitForAdvertisementInRange(\n matchingDevice,\n {\n startTimeoutMs: ADVERTISING_DELAY,\n advTimeoutMs: ADVERTISING_TIMEOUT,\n },\n );\n this._logger.debug(\n `Rediscovered ${matchingDevice.id}, inRange=${isInRange}`,\n );\n }\n return matchingDevice;\n } catch {\n return null;\n }\n }\n\n private async _tryToReconnect(\n deviceId: string,\n onReconnect?: (id: string) => Promise<void> | void,\n ) {\n await this._safelyCancelGattConnection(deviceId);\n\n while (true) {\n const registryEntry = this._deviceRegistryById.get(deviceId);\n const connectionStateMachine =\n this._connectionStateMachinesByDeviceId.get(deviceId);\n\n if (!registryEntry || !connectionStateMachine) {\n this._logger.debug(\n `[${deviceId}] aborting reconnect: registry or state machine missing`,\n );\n return;\n }\n\n try {\n const rediscoveredDevice = await this._withTimeout(\n this._rediscoverPermittedDevice(deviceId),\n REDISCOVER_TIMEOUT,\n \"rediscovery timeout\",\n );\n\n if (!rediscoveredDevice) throw new Error(\"Device not found\");\n\n if (!rediscoveredDevice.gatt) throw new Error(\"No GATT on device\");\n\n try {\n await rediscoveredDevice.gatt.connect();\n } catch (e) {\n this._logger.error(`[${deviceId}] gatt.connect() failed`, {\n data: { e },\n });\n if (rediscoveredDevice.gatt.connected)\n rediscoveredDevice.gatt.disconnect();\n }\n\n const { service: ledgerService, ledgerServiceInfo } =\n await this._getPrimaryLedgerGattService(rediscoveredDevice);\n\n const {\n writeCharacteristic: gattWriteCharacteristic,\n notifyCharacteristic: gattNotifyCharacteristic,\n } = await this._resolveLedgerServiceCharacteristics(\n ledgerService,\n ledgerServiceInfo,\n );\n\n connectionStateMachine.setDependencies({\n writeCharacteristic: gattWriteCharacteristic,\n notifyCharacteristic: gattNotifyCharacteristic,\n });\n await connectionStateMachine.setupConnection();\n connectionStateMachine.eventDeviceConnected();\n\n registryEntry.serviceUuid = ledgerService.uuid;\n registryEntry.ledgerServiceInfo = ledgerServiceInfo;\n\n if (registryEntry.gattDisconnectListener) {\n rediscoveredDevice.removeEventListener(\n \"gattserverdisconnected\",\n registryEntry.gattDisconnectListener,\n );\n }\n\n const onDisconnectedCallback = (_: Event) =>\n this._handleGattServerDisconnected(deviceId);\n\n rediscoveredDevice.addEventListener(\n \"gattserverdisconnected\",\n onDisconnectedCallback,\n );\n\n registryEntry.gattDisconnectListener = onDisconnectedCallback;\n\n await onReconnect?.(deviceId);\n\n this._publishDiscoveredDevices();\n\n return;\n } catch (e) {\n this._logger.error(`[${deviceId}] reconnect attempt failed`, {\n data: { e },\n });\n\n if (registryEntry?.device.gatt?.connected)\n registryEntry.device.gatt.disconnect();\n\n await this._sleep(RECONNECTION_LOOP_BACKOFF);\n continue;\n }\n }\n }\n\n private async _safelyCancelGattConnection(deviceId: string) {\n const registryEntry = this._deviceRegistryById.get(deviceId);\n if (!registryEntry) return;\n if (registryEntry.device.gatt?.connected)\n registryEntry.device.gatt.disconnect();\n await this._sleep(100);\n }\n\n private async _identifyLedgerGattService(device: BluetoothDevice): Promise<{\n serviceUuid: string;\n ledgerServiceInfo: NonNullable<DeviceRegistryEntry[\"ledgerServiceInfo\"]>;\n }> {\n if (!device.gatt) {\n throw new OpeningConnectionError(\"No GATT server available on device\");\n }\n try {\n await this._withTimeout(device.gatt.connect(), 6000, \"connect timeout\");\n const { service, ledgerServiceInfo } =\n await this._getPrimaryLedgerGattService(device);\n return { serviceUuid: service.uuid, ledgerServiceInfo };\n } finally {\n device.gatt?.disconnect();\n await this._sleep(200);\n }\n }\n\n private async _getPrimaryLedgerGattService(device: BluetoothDevice): Promise<{\n service: BluetoothRemoteGATTService;\n ledgerServiceInfo: NonNullable<DeviceRegistryEntry[\"ledgerServiceInfo\"]>;\n }> {\n const knownLedgerServiceUuids =\n this._deviceModelDataSource.getBluetoothServices();\n const lastSuccessfulServiceUuid = this._deviceRegistryById.get(\n device.id,\n )?.serviceUuid;\n const preferredSearchOrder = lastSuccessfulServiceUuid\n ? [\n lastSuccessfulServiceUuid,\n ...knownLedgerServiceUuids.filter(\n (u) => u !== lastSuccessfulServiceUuid,\n ),\n ]\n : knownLedgerServiceUuids.slice();\n\n for (const candidateUuid of preferredSearchOrder) {\n try {\n const primaryService =\n await device.gatt!.getPrimaryService(candidateUuid);\n const ledgerServiceInfoMap =\n this._deviceModelDataSource.getBluetoothServicesInfos();\n const ledgerServiceInfo = ledgerServiceInfoMap[primaryService.uuid];\n if (!ledgerServiceInfo) throw new UnknownDeviceError(device.name || \"\");\n return { service: primaryService, ledgerServiceInfo };\n } catch (e: unknown) {\n if ((e as Error)?.name === \"SecurityError\") {\n throw new OpeningConnectionError(\n `Missing Web Bluetooth permission for service ${candidateUuid}. ` +\n `Add it to optionalServices in requestDevice().`,\n );\n }\n try {\n const allPrimaryServices = await device.gatt!.getPrimaryServices();\n const matchedService = allPrimaryServices.find(\n (s) => s.uuid.toLowerCase() === candidateUuid.toLowerCase(),\n );\n if (matchedService) {\n const ledgerServiceInfoMap =\n this._deviceModelDataSource.getBluetoothServicesInfos();\n const ledgerServiceInfo = ledgerServiceInfoMap[matchedService.uuid];\n if (!ledgerServiceInfo)\n throw new UnknownDeviceError(device.name || \"\");\n return { service: matchedService, ledgerServiceInfo };\n }\n } catch {\n this._logger.error(\"Failed to get primary services\", {\n data: { deviceId: device.id },\n });\n }\n }\n }\n throw new OpeningConnectionError(\"Ledger GATT service not found\");\n }\n\n private async _resolveLedgerServiceCharacteristics(\n service: BluetoothRemoteGATTService,\n ledgerServiceInfo: NonNullable<DeviceRegistryEntry[\"ledgerServiceInfo\"]>,\n ): Promise<{\n writeCharacteristic: BluetoothRemoteGATTCharacteristic;\n notifyCharacteristic: BluetoothRemoteGATTCharacteristic;\n }> {\n const notifyCharacteristic = await service.getCharacteristic(\n ledgerServiceInfo.notifyUuid,\n );\n const writeCharacteristic = await this._findWritableCharacteristic(\n service,\n ledgerServiceInfo,\n );\n return { writeCharacteristic, notifyCharacteristic };\n }\n\n private async _findWritableCharacteristic(\n service: BluetoothRemoteGATTService,\n ledgerServiceInfo: NonNullable<DeviceRegistryEntry[\"ledgerServiceInfo\"]>,\n ): Promise<BluetoothRemoteGATTCharacteristic> {\n const preferredCharacteristicUuids = [\n ledgerServiceInfo.writeCmdUuid,\n ledgerServiceInfo.writeUuid,\n ].filter(Boolean) as string[];\n\n const attemptedCharacteristics: BluetoothRemoteGATTCharacteristic[] = [];\n\n for (const uuid of preferredCharacteristicUuids) {\n try {\n const characteristic = await service.getCharacteristic(uuid);\n attemptedCharacteristics.push(characteristic);\n\n if (characteristic.properties.writeWithoutResponse)\n return characteristic;\n if (characteristic.properties.write) return characteristic;\n } catch {\n this._logger.error(\"Failed to get write characteristic\", {\n data: { deviceId: service.device.id },\n });\n }\n }\n\n throw new OpeningConnectionError(\"No write characteristic available\");\n }\n\n private _publishDiscoveredDevices() {\n const connectedSummaries: TransportDiscoveredDevice[] = [];\n for (const [deviceId] of this._connectionStateMachinesByDeviceId) {\n const registryEntry = this._deviceRegistryById.get(deviceId);\n if (registryEntry?.ledgerServiceInfo) {\n connectedSummaries.push({\n id: deviceId,\n deviceModel: registryEntry.ledgerServiceInfo.deviceModel,\n transport: webBleIdentifier,\n name: registryEntry.device.name || undefined,\n });\n }\n }\n const scannedSummaries = Array.from(this._deviceRegistryById.values())\n .map((entry) => entry.discoveredDevice)\n .filter(\n (summary) => !this._connectionStateMachinesByDeviceId.has(summary.id),\n );\n\n this._discoveredDevices$.next([...connectedSummaries, ...scannedSummaries]);\n }\n\n private _withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n timeoutMessage: string,\n onTimeoutCancel?: () => void,\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timeoutHandle = setTimeout(() => {\n reject(new OpeningConnectionError(timeoutMessage));\n onTimeoutCancel?.();\n }, timeoutMs);\n promise.then(\n (value) => {\n clearTimeout(timeoutHandle);\n resolve(value);\n },\n (error) => {\n this._logger.error(\"withTimeout() promise rejected\", {\n data: { e: error },\n });\n clearTimeout(timeoutHandle);\n reject(error);\n },\n );\n });\n }\n\n private _sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\nexport const webBleTransportFactory: TransportFactory = ({\n deviceModelDataSource,\n loggerServiceFactory,\n apduSenderServiceFactory,\n apduReceiverServiceFactory,\n}) =>\n new WebBleTransport(\n deviceModelDataSource,\n loggerServiceFactory,\n apduSenderServiceFactory,\n apduReceiverServiceFactory,\n );\n"],
5
+ "mappings": "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",
6
6
  "names": ["DeviceAlreadyConnectedError", "DeviceConnectionStateMachine", "GeneralDmkError", "OpeningConnectionError", "TransportConnectedDevice", "UnknownDeviceError", "Left", "Right", "BehaviorSubject", "from", "switchMap", "ADVERTISING_DELAY", "ADVERTISING_TIMEOUT", "RECONNECT_DEVICE_TIMEOUT", "RECONNECTION_LOOP_BACKOFF", "REDISCOVER_TIMEOUT", "WebBleApduSender", "webBleIdentifier", "WebBleTransport", "_deviceModelDataSource", "loggerFactory", "_apduSenderFactory", "_apduReceiverFactory", "bluetoothServiceUuids", "serviceUuid", "allOptionalServiceUuids", "bluetoothDevice", "ledgerServiceInfo", "discoveredDevice", "params", "registryEntry", "ledgerService", "gattWriteCharacteristic", "gattNotifyCharacteristic", "apduSender", "connectionStateMachine", "e", "entry", "onGattDisconnected", "_ev", "apduArgs", "deviceId", "device", "opts", "startTimeoutMs", "advTimeoutMs", "abortController", "startTimer", "advertisementsStarted", "advertisementSeen", "resolve", "handleAdvertisement", "targetDeviceId", "matchingDevice", "d", "isInRange", "onReconnect", "rediscoveredDevice", "onDisconnectedCallback", "_", "service", "knownLedgerServiceUuids", "lastSuccessfulServiceUuid", "preferredSearchOrder", "u", "candidateUuid", "primaryService", "matchedService", "s", "notifyCharacteristic", "preferredCharacteristicUuids", "attemptedCharacteristics", "uuid", "characteristic", "connectedSummaries", "scannedSummaries", "summary", "promise", "timeoutMs", "timeoutMessage", "onTimeoutCancel", "reject", "timeoutHandle", "value", "error", "ms", "webBleTransportFactory", "deviceModelDataSource", "loggerServiceFactory", "apduSenderServiceFactory", "apduReceiverServiceFactory"]
7
7
  }
@@ -1,53 +1,57 @@
1
1
  {
2
- "name": "@ledgerhq/device-transport-kit-web-ble",
3
- "version": "1.2.0",
4
- "license": "Apache-2.0",
5
- "private": false,
2
+ "dependencies": {
3
+ "@sentry/minimal": "catalog:",
4
+ "purify-ts": "catalog:",
5
+ "uuid": "catalog:"
6
+ },
7
+ "devDependencies": {
8
+ "@ledgerhq/device-management-kit": "workspace:^",
9
+ "@ledgerhq/eslint-config-dsdk": "workspace:^",
10
+ "@ledgerhq/ldmk-tool": "workspace:^",
11
+ "@ledgerhq/prettier-config-dsdk": "workspace:^",
12
+ "@ledgerhq/tsconfig-dsdk": "workspace:^",
13
+ "@ledgerhq/vitest-config-dmk": "workspace:^",
14
+ "@types/uuid": "catalog:",
15
+ "@types/web-bluetooth": "catalog:",
16
+ "rxjs": "catalog:",
17
+ "ts-node": "catalog:"
18
+ },
6
19
  "exports": {
7
20
  ".": {
8
- "types": "./lib/types/index.d.ts",
9
- "import": "./lib/esm/index.js"
21
+ "import": "./lib/esm/index.js",
22
+ "types": "./lib/types/index.d.ts"
10
23
  }
11
24
  },
12
25
  "files": [
13
26
  "./lib",
14
27
  "package.json"
15
28
  ],
29
+ "license": "Apache-2.0",
30
+ "name": "@ledgerhq/device-transport-kit-web-ble",
31
+ "peerDependencies": {
32
+ "@ledgerhq/device-management-kit": "workspace:^",
33
+ "rxjs": "catalog:"
34
+ },
35
+ "private": false,
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/LedgerHQ/device-sdk-ts.git"
39
+ },
16
40
  "scripts": {
17
- "prebuild": "rimraf lib",
18
41
  "build": "pnpm ldmk-tool build --entryPoints src/index.ts,src/**/*.ts --tsconfig tsconfig.prod.json --platform web",
19
42
  "dev": "concurrently \"pnpm watch:builds\" \"pnpm watch:types\"",
20
- "watch:builds": "pnpm ldmk-tool watch --entryPoints src/index.ts,src/**/*.ts --tsconfig tsconfig.prod.json --platform web",
21
- "watch:types": "concurrently \"tsc --watch -p tsconfig.prod.json\" \"tsc-alias --watch -p tsconfig.prod.json\"",
22
43
  "lint": "eslint",
23
44
  "lint:fix": "pnpm lint --fix",
24
45
  "postpack": "find . -name '*.tgz' -exec cp {} ../../../dist/ \\; ",
46
+ "prebuild": "rimraf lib",
25
47
  "prettier": "prettier . --check",
26
48
  "prettier:fix": "prettier . --write",
27
- "typecheck": "tsc --noEmit",
28
49
  "test": "vitest run",
50
+ "test:coverage": "vitest run --coverage",
29
51
  "test:watch": "vitest",
30
- "test:coverage": "vitest run --coverage"
31
- },
32
- "dependencies": {
33
- "@sentry/minimal": "catalog:",
34
- "purify-ts": "catalog:",
35
- "uuid": "catalog:"
36
- },
37
- "devDependencies": {
38
- "@ledgerhq/device-management-kit": "workspace:*",
39
- "@ledgerhq/ldmk-tool": "workspace:*",
40
- "@ledgerhq/eslint-config-dsdk": "workspace:*",
41
- "@ledgerhq/prettier-config-dsdk": "workspace:*",
42
- "@ledgerhq/tsconfig-dsdk": "workspace:*",
43
- "@ledgerhq/vitest-config-dmk": "workspace:*",
44
- "@types/uuid": "catalog:",
45
- "@types/web-bluetooth": "catalog:",
46
- "rxjs": "catalog:",
47
- "ts-node": "catalog:"
52
+ "typecheck": "tsc --noEmit",
53
+ "watch:builds": "pnpm ldmk-tool watch --entryPoints src/index.ts,src/**/*.ts --tsconfig tsconfig.prod.json --platform web",
54
+ "watch:types": "concurrently \"tsc --watch -p tsconfig.prod.json\" \"tsc-alias --watch -p tsconfig.prod.json\""
48
55
  },
49
- "peerDependencies": {
50
- "@ledgerhq/device-management-kit": "workspace:*",
51
- "rxjs": "catalog:"
52
- }
56
+ "version": "0.0.0-z-intent-queue-7-20251204111630"
53
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WebBleTransport.d.ts","sourceRoot":"","sources":["../../../../src/api/transport/WebBleTransport.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,KAAK,YAAY,EAGjB,KAAK,qBAAqB,EAC1B,KAAK,QAAQ,EAEb,KAAK,sBAAsB,EAE3B,KAAK,SAAS,EACd,wBAAwB,EAExB,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EAEzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,MAAM,EAAe,MAAM,WAAW,CAAC;AACrD,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAgB9D,eAAO,MAAM,gBAAgB,EAAE,mBAAwC,CAAC;AAexE,qBAAa,eAAgB,YAAW,SAAS;IAa7C,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IAfvC,OAAO,CAAC,OAAO,CAAyB;IAExC,OAAO,CAAC,kCAAkC,CAGtC;IACJ,OAAO,CAAC,mBAAmB,CAA0C;IACrE,OAAO,CAAC,mBAAmB,CAErB;gBAGa,sBAAsB,EAAE,qBAAqB,EACtD,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,sBAAsB,EAC7C,kBAAkB,EAAE,wBAAwB,EAC5C,oBAAoB,EAAE,0BAA0B;IAKnE,WAAW,IAAI,OAAO;IAItB,aAAa,IAAI,mBAAmB;IAIpC,gBAAgB,IAAI,UAAU,CAAC,yBAAyB,CAAC;IAoCzD,eAAe,IAAI,IAAI;IAIvB,wBAAwB,IAAI,UAAU,CAAC,yBAAyB,EAAE,CAAC;IAK7D,OAAO,CAAC,MAAM,EAAE;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;QACzC,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC1D,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,wBAAwB,CAAC,CAAC;IAmHrD,UAAU,CAAC,MAAM,EAAE;QACvB,eAAe,EAAE,wBAAwB,CAAC;KAC3C,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IA0BnC,OAAO,CAAC,6BAA6B;YAQvB,4BAA4B;YAyC5B,0BAA0B;YA4B1B,eAAe;YAgGf,2BAA2B;YAQ3B,0BAA0B;YAkB1B,4BAA4B;YAyD5B,oCAAoC;YAiBpC,2BAA2B;IA6BzC,OAAO,CAAC,yBAAyB;IAqBjC,OAAO,CAAC,YAAY;IA2BpB,OAAO,CAAC,MAAM;CAGf;AAED,eAAO,MAAM,sBAAsB,EAAE,gBAWlC,CAAC"}
1
+ {"version":3,"file":"WebBleTransport.d.ts","sourceRoot":"","sources":["../../../../src/api/transport/WebBleTransport.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,KAAK,YAAY,EAGjB,KAAK,qBAAqB,EAC1B,KAAK,QAAQ,EAEb,KAAK,sBAAsB,EAE3B,KAAK,SAAS,EACd,wBAAwB,EAExB,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EAEzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,MAAM,EAAe,MAAM,WAAW,CAAC;AACrD,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAgB9D,eAAO,MAAM,gBAAgB,EAAE,mBAAwC,CAAC;AAexE,qBAAa,eAAgB,YAAW,SAAS;IAa7C,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IAfvC,OAAO,CAAC,OAAO,CAAyB;IAExC,OAAO,CAAC,kCAAkC,CAGtC;IACJ,OAAO,CAAC,mBAAmB,CAA0C;IACrE,OAAO,CAAC,mBAAmB,CAErB;gBAGa,sBAAsB,EAAE,qBAAqB,EACtD,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,sBAAsB,EAC7C,kBAAkB,EAAE,wBAAwB,EAC5C,oBAAoB,EAAE,0BAA0B;IAKnE,WAAW,IAAI,OAAO;IAItB,aAAa,IAAI,mBAAmB;IAIpC,gBAAgB,IAAI,UAAU,CAAC,yBAAyB,CAAC;IAqCzD,eAAe,IAAI,IAAI;IAIvB,wBAAwB,IAAI,UAAU,CAAC,yBAAyB,EAAE,CAAC;IAK7D,OAAO,CAAC,MAAM,EAAE;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;QACzC,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC1D,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,wBAAwB,CAAC,CAAC;IAoHrD,UAAU,CAAC,MAAM,EAAE;QACvB,eAAe,EAAE,wBAAwB,CAAC;KAC3C,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IA0BnC,OAAO,CAAC,6BAA6B;YAQvB,4BAA4B;YAyC5B,0BAA0B;YA4B1B,eAAe;YAgGf,2BAA2B;YAQ3B,0BAA0B;YAkB1B,4BAA4B;YAyD5B,oCAAoC;YAiBpC,2BAA2B;IA6BzC,OAAO,CAAC,yBAAyB;IAsBjC,OAAO,CAAC,YAAY;IA2BpB,OAAO,CAAC,MAAM;CAGf;AAED,eAAO,MAAM,sBAAsB,EAAE,gBAWlC,CAAC"}