@ledgerhq/device-transport-kit-speculos 0.0.0-e2e-speculos-20250905081749 → 0.0.0-e2e-speculos-20250908082435

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.
Files changed (59) hide show
  1. package/lib/cjs/src/api/E2eSpeculosTransport.js +2 -0
  2. package/lib/cjs/src/api/E2eSpeculosTransport.js.map +7 -0
  3. package/lib/cjs/src/api/SpeculosTransport.js +1 -1
  4. package/lib/cjs/src/api/SpeculosTransport.js.map +3 -3
  5. package/lib/cjs/src/index.js +1 -1
  6. package/lib/cjs/src/index.js.map +2 -2
  7. package/lib/cjs/src/internal/datasource/E2eHttpSpeculosDatasource.js +3 -0
  8. package/lib/cjs/src/internal/datasource/E2eHttpSpeculosDatasource.js.map +7 -0
  9. package/lib/cjs/src/internal/datasource/E2eSpeculosDatasource.js +2 -0
  10. package/lib/cjs/src/internal/datasource/E2eSpeculosDatasource.js.map +7 -0
  11. package/lib/cjs/src/internal/datasource/HttpSpeculosDatasource.js +1 -1
  12. package/lib/cjs/src/internal/datasource/HttpSpeculosDatasource.js.map +3 -3
  13. package/lib/cjs/src/internal/datasource/SpeculosDatasource.js +1 -1
  14. package/lib/cjs/src/internal/datasource/SpeculosDatasource.js.map +1 -1
  15. package/lib/cjs/src/internal/utils/axiosInstances.js +2 -0
  16. package/lib/cjs/src/internal/utils/axiosInstances.js.map +7 -0
  17. package/lib/esm/src/api/E2eSpeculosTransport.js +2 -0
  18. package/lib/esm/src/api/E2eSpeculosTransport.js.map +7 -0
  19. package/lib/esm/src/api/SpeculosTransport.js +1 -1
  20. package/lib/esm/src/api/SpeculosTransport.js.map +3 -3
  21. package/lib/esm/src/index.js +1 -1
  22. package/lib/esm/src/index.js.map +2 -2
  23. package/lib/esm/src/internal/datasource/E2eHttpSpeculosDatasource.js +3 -0
  24. package/lib/esm/src/internal/datasource/E2eHttpSpeculosDatasource.js.map +7 -0
  25. package/lib/esm/src/internal/datasource/E2eSpeculosDatasource.js +1 -0
  26. package/lib/esm/src/internal/datasource/E2eSpeculosDatasource.js.map +7 -0
  27. package/lib/esm/src/internal/datasource/HttpSpeculosDatasource.js +1 -1
  28. package/lib/esm/src/internal/datasource/HttpSpeculosDatasource.js.map +3 -3
  29. package/lib/esm/src/internal/utils/axiosInstances.js +2 -0
  30. package/lib/esm/src/internal/utils/axiosInstances.js.map +7 -0
  31. package/lib/types/src/api/{QuietSpeculosTransport.d.ts → E2eSpeculosTransport.d.ts} +2 -2
  32. package/lib/types/src/api/E2eSpeculosTransport.d.ts.map +1 -0
  33. package/lib/types/src/api/SpeculosTransport.d.ts +2 -3
  34. package/lib/types/src/api/SpeculosTransport.d.ts.map +1 -1
  35. package/lib/types/src/index.d.ts +1 -1
  36. package/lib/types/src/index.d.ts.map +1 -1
  37. package/lib/types/src/internal/datasource/E2eHttpSpeculosDatasource.d.ts +15 -0
  38. package/lib/types/src/internal/datasource/E2eHttpSpeculosDatasource.d.ts.map +1 -0
  39. package/lib/types/src/internal/datasource/E2eSpeculosDatasource.d.ts +7 -0
  40. package/lib/types/src/internal/datasource/E2eSpeculosDatasource.d.ts.map +1 -0
  41. package/lib/types/src/internal/datasource/HttpSpeculosDatasource.d.ts +1 -0
  42. package/lib/types/src/internal/datasource/HttpSpeculosDatasource.d.ts.map +1 -1
  43. package/lib/types/src/internal/datasource/SpeculosDatasource.d.ts +1 -0
  44. package/lib/types/src/internal/datasource/SpeculosDatasource.d.ts.map +1 -1
  45. package/lib/types/src/internal/utils/axiosInstances.d.ts +4 -0
  46. package/lib/types/src/internal/utils/axiosInstances.d.ts.map +1 -0
  47. package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
  48. package/package.json +3 -3
  49. package/lib/cjs/src/api/QuietSpeculosTransport.js +0 -2
  50. package/lib/cjs/src/api/QuietSpeculosTransport.js.map +0 -7
  51. package/lib/cjs/src/internal/datasource/HttpLegacySpeculosDatasource.js +0 -3
  52. package/lib/cjs/src/internal/datasource/HttpLegacySpeculosDatasource.js.map +0 -7
  53. package/lib/esm/src/api/QuietSpeculosTransport.js +0 -2
  54. package/lib/esm/src/api/QuietSpeculosTransport.js.map +0 -7
  55. package/lib/esm/src/internal/datasource/HttpLegacySpeculosDatasource.js +0 -3
  56. package/lib/esm/src/internal/datasource/HttpLegacySpeculosDatasource.js.map +0 -7
  57. package/lib/types/src/api/QuietSpeculosTransport.d.ts.map +0 -1
  58. package/lib/types/src/internal/datasource/HttpLegacySpeculosDatasource.d.ts +0 -12
  59. package/lib/types/src/internal/datasource/HttpLegacySpeculosDatasource.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/device-transport-kit-speculos",
3
- "version": "0.0.0-e2e-speculos-20250905081749",
3
+ "version": "0.0.0-e2e-speculos-20250908082435",
4
4
  "license": "Apache-2.0",
5
5
  "private": false,
6
6
  "exports": {
@@ -26,7 +26,7 @@
26
26
  "devDependencies": {
27
27
  "rxjs": "^7.8.2",
28
28
  "ts-node": "10.9.2",
29
- "@ledgerhq/device-management-kit": "0.0.0-e2e-speculos-20250905081749",
29
+ "@ledgerhq/device-management-kit": "0.0.0-e2e-speculos-20250908082435",
30
30
  "@ledgerhq/eslint-config-dsdk": "0.0.2",
31
31
  "@ledgerhq/ldmk-tool": "0.0.1",
32
32
  "@ledgerhq/prettier-config-dsdk": "0.0.2",
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "peerDependencies": {
37
37
  "rxjs": "^7.8.2",
38
- "@ledgerhq/device-management-kit": "0.0.0-e2e-speculos-20250905081749"
38
+ "@ledgerhq/device-management-kit": "0.0.0-e2e-speculos-20250908082435"
39
39
  },
40
40
  "scripts": {
41
41
  "prebuild": "rimraf lib",
@@ -1,2 +0,0 @@
1
- "use strict";var a=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var m=(s,e)=>{for(var r in e)a(s,r,{get:e[r],enumerable:!0})},y=(s,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of D(e))!h.call(s,t)&&t!==r&&a(s,t,{get:()=>e[t],enumerable:!(o=v(e,t))||o.enumerable});return s};var S=s=>y(a({},"__esModule",{value:!0}),s);var f={};m(f,{QuietSpeculosTransport:()=>g,quietSpeculosTransportFactory:()=>b});module.exports=S(f);var n=require("@ledgerhq/device-management-kit"),i=require("purify-ts"),d=require("rxjs"),u=require("../internal/datasource/HttpLegacySpeculosDatasource"),l=require("./SpeculosTransport");class g{logger;identifier=l.speculosIdentifier;_speculosDataSource;connectedDevice=null;speculosDevice={id:"SpeculosID",deviceModel:{id:n.DeviceModelId.STAX,productName:"Speculos - App Name - version",usbProductId:16,bootloaderUsbProductId:1,getBlockSize(){return 32},blockSize:32,usbOnly:!0,memorySize:320*1024,masks:[823132160]},transport:this.identifier};constructor(e,r,o){this.logger=e("QuietSpeculosTransport"),this._speculosDataSource=new u.HttpLegacySpeculosDatasource(o,1e4,"ldmk-transport-speculos")}isSupported(){return!0}getIdentifier(){return this.identifier}listenToAvailableDevices(){return(0,d.from)([[this.speculosDevice]])}startDiscovering(){return this.logger.debug("startDiscovering"),(0,d.from)([this.speculosDevice])}stopDiscovering(){this.logger.debug("stopDiscovering")}async connect(e){this.logger.debug("connect");try{const r=await this._speculosDataSource.postAdpu("B0010000");this.logger.debug(`Hex Response: ${r}`);const o=this.createApduResponse(r),t=new n.ApduParser(o);t.extract8BitUInt();const c=t.encodeToString(t.extractFieldLVEncoded()),p=t.encodeToString(t.extractFieldLVEncoded());this.logger.debug(`App Name: ${c} and version ${p}`),this.speculosDevice.deviceModel.productName=`Speculos - ${c} - ${p}`}catch{}try{const r={sendApdu:o=>this.sendApdu(e.deviceId,e.onDisconnect,o),deviceModel:this.speculosDevice.deviceModel,transport:this.identifier,id:"SpeculosID",type:"USB"};return this.connectedDevice=r,(0,i.Right)(r)}catch(r){return(0,i.Left)(new n.OpeningConnectionError(r))}}async disconnect(e){return this.logger.debug("disconnect"),this.connectedDevice=null,Promise.resolve((0,i.Right)(void 0))}async sendApdu(e,r,o){try{const t=(0,n.bufferToHexaString)(o).substring(2).toUpperCase();this.logger.debug(`[QuietSpeculosTransport] send APDU: ${t}`);const c=await this._speculosDataSource.postAdpu(t),p=this.createApduResponse(c);return(0,i.Right)(p)}catch(t){return this.connectedDevice&&(this.logger.debug("disconnecting due to APDU error"),r(e),await this.disconnect({connectedDevice:this.connectedDevice})),(0,i.Left)(new n.GeneralDmkError(t))}}createApduResponse(e){const r=e.slice(-4),o=e.slice(0,-4);return this.logger.debug(`[QuietSpeculosTransport] Status code hex: ${r}`),this.logger.debug(`[QuietSpeculosTransport] data hex: ${o}`),{statusCode:this.fromHexString(r),data:this.fromHexString(o)}}fromHexString(e){return e?new Uint8Array(e.match(/.{1,2}/g).map(r=>parseInt(r,16))):new Uint8Array(0)}}const b=(s="http://127.0.0.1:5000")=>({config:e,loggerServiceFactory:r})=>new g(r,e,s);0&&(module.exports={QuietSpeculosTransport,quietSpeculosTransportFactory});
2
- //# sourceMappingURL=QuietSpeculosTransport.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/api/QuietSpeculosTransport.ts"],
4
- "sourcesContent": ["import {\n ApduParser,\n type ApduResponse,\n bufferToHexaString,\n type ConnectError,\n type DeviceId,\n DeviceModelId,\n type DisconnectHandler,\n type DmkConfig,\n type DmkError,\n GeneralDmkError,\n type LoggerPublisherService,\n OpeningConnectionError,\n type Transport,\n type TransportConnectedDevice,\n type TransportDiscoveredDevice,\n type TransportFactory,\n type TransportIdentifier,\n} from \"@ledgerhq/device-management-kit\";\nimport { type Either, Left, Right } from \"purify-ts\";\nimport { from, type Observable } from \"rxjs\";\n\nimport { HttpLegacySpeculosDatasource } from \"@internal/datasource/HttpLegacySpeculosDatasource\";\n\nimport { speculosIdentifier } from \"./SpeculosTransport\";\n\nexport class QuietSpeculosTransport implements Transport {\n private logger: LoggerPublisherService;\n private readonly identifier: TransportIdentifier = speculosIdentifier;\n private readonly _speculosDataSource: HttpLegacySpeculosDatasource;\n\n private connectedDevice: TransportConnectedDevice | null = null;\n\n private readonly speculosDevice: TransportDiscoveredDevice = {\n id: \"SpeculosID\",\n deviceModel: {\n id: DeviceModelId.STAX,\n productName: \"Speculos - App Name - version\",\n usbProductId: 0x10,\n bootloaderUsbProductId: 0x0001,\n getBlockSize() {\n return 32;\n },\n blockSize: 32,\n usbOnly: true,\n memorySize: 320 * 1024,\n masks: [0x31100000],\n },\n transport: this.identifier,\n };\n\n constructor(\n loggerServiceFactory: (tag: string) => LoggerPublisherService,\n _config: DmkConfig,\n speculosUrl: string,\n ) {\n this.logger = loggerServiceFactory(\"QuietSpeculosTransport\");\n this._speculosDataSource = new HttpLegacySpeculosDatasource(\n speculosUrl,\n 10000,\n \"ldmk-transport-speculos\",\n );\n }\n\n isSupported(): boolean {\n return true;\n }\n\n getIdentifier(): TransportIdentifier {\n return this.identifier;\n }\n\n listenToAvailableDevices(): Observable<TransportDiscoveredDevice[]> {\n return from([[this.speculosDevice]]);\n }\n\n startDiscovering(): Observable<TransportDiscoveredDevice> {\n this.logger.debug(\"startDiscovering\");\n return from([this.speculosDevice]);\n }\n\n stopDiscovering(): void {\n this.logger.debug(\"stopDiscovering\");\n }\n\n async connect(params: {\n deviceId: DeviceId;\n onDisconnect: DisconnectHandler;\n }): Promise<Either<ConnectError, TransportConnectedDevice>> {\n this.logger.debug(\"connect\");\n\n // Probe app name/version via GET_VERSION (B0010000) if possible\n try {\n const hexResponse = await this._speculosDataSource.postAdpu(\"B0010000\");\n this.logger.debug(`Hex Response: ${hexResponse}`);\n const apduResponse = this.createApduResponse(hexResponse);\n const parser = new ApduParser(apduResponse);\n parser.extract8BitUInt();\n const appName = parser.encodeToString(parser.extractFieldLVEncoded());\n const appVersion = parser.encodeToString(parser.extractFieldLVEncoded());\n this.logger.debug(`App Name: ${appName} and version ${appVersion}`);\n\n this.speculosDevice.deviceModel.productName = `Speculos - ${appName} - ${appVersion}`;\n } catch {\n // ignore if the app doesn't support GET_VERSION\n }\n\n try {\n const connectedDevice: TransportConnectedDevice = {\n sendApdu: (apdu: Uint8Array) =>\n this.sendApdu(params.deviceId, params.onDisconnect, apdu),\n deviceModel: this.speculosDevice.deviceModel,\n transport: this.identifier,\n id: \"SpeculosID\",\n type: \"USB\",\n };\n\n this.connectedDevice = connectedDevice;\n return Right(connectedDevice);\n } catch (error) {\n return Left(new OpeningConnectionError(error as Error));\n }\n }\n\n async disconnect(_params: {\n connectedDevice: TransportConnectedDevice;\n }): Promise<Either<DmkError, void>> {\n this.logger.debug(\"disconnect\");\n this.connectedDevice = null;\n return Promise.resolve(Right(undefined));\n }\n\n async sendApdu(\n deviceId: DeviceId,\n onDisconnect: DisconnectHandler,\n apdu: Uint8Array,\n ): Promise<Either<DmkError, ApduResponse>> {\n try {\n const hex = bufferToHexaString(apdu).substring(2).toUpperCase();\n this.logger.debug(`[QuietSpeculosTransport] send APDU: ${hex}`);\n const hexResponse = await this._speculosDataSource.postAdpu(hex);\n const resp = this.createApduResponse(hexResponse);\n return Right(resp);\n } catch (error) {\n if (this.connectedDevice) {\n this.logger.debug(\"disconnecting due to APDU error\");\n onDisconnect(deviceId);\n await this.disconnect({ connectedDevice: this.connectedDevice });\n }\n return Left(new GeneralDmkError(error as Error));\n }\n }\n\n private createApduResponse(hexApdu: string): ApduResponse {\n const sw = hexApdu.slice(-4);\n const payload = hexApdu.slice(0, -4);\n this.logger.debug(`[QuietSpeculosTransport] Status code hex: ${sw}`);\n this.logger.debug(`[QuietSpeculosTransport] data hex: ${payload}`);\n return {\n statusCode: this.fromHexString(sw),\n data: this.fromHexString(payload),\n };\n }\n\n private fromHexString(hexString: string): Uint8Array {\n if (!hexString) return new Uint8Array(0);\n return new Uint8Array(\n hexString.match(/.{1,2}/g)!.map((b) => parseInt(b, 16)),\n );\n }\n}\n\nexport const quietSpeculosTransportFactory: (\n speculosUrl?: string,\n) => TransportFactory =\n (speculosUrl = \"http://127.0.0.1:5000\") =>\n ({ config, loggerServiceFactory }) =>\n new QuietSpeculosTransport(loggerServiceFactory, config, speculosUrl);\n"],
5
- "mappings": "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",
6
- "names": ["QuietSpeculosTransport_exports", "__export", "QuietSpeculosTransport", "quietSpeculosTransportFactory", "__toCommonJS", "import_device_management_kit", "import_purify_ts", "import_rxjs", "import_HttpLegacySpeculosDatasource", "import_SpeculosTransport", "loggerServiceFactory", "_config", "speculosUrl", "params", "hexResponse", "apduResponse", "parser", "appName", "appVersion", "connectedDevice", "apdu", "error", "_params", "deviceId", "onDisconnect", "hex", "resp", "hexApdu", "sw", "payload", "hexString", "b", "config"]
7
- }
@@ -1,3 +0,0 @@
1
- "use strict";var y=Object.create;var c=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var S=Object.getPrototypeOf,b=Object.prototype.hasOwnProperty;var w=(s,t)=>{for(var r in t)c(s,r,{get:t[r],enumerable:!0})},h=(s,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of A(t))!b.call(s,e)&&e!==r&&c(s,e,{get:()=>t[e],enumerable:!(n=x(t,e))||n.enumerable});return s};var l=(s,t,r)=>(r=s!=null?y(S(s)):{},h(t||!s||!s.__esModule?c(r,"default",{value:s,enumerable:!0}):r,s)),k=s=>h(c({},"__esModule",{value:!0}),s);var T={};w(T,{HttpLegacySpeculosDatasource:()=>R});module.exports=k(T);var p=l(require("axios")),g=l(require("http")),f=l(require("https"));const d=new Map;function v(s,t,r){const n=`${s}::${r}`,e=d.get(n);if(e)return e;const o=new g.default.Agent({keepAlive:!0,maxSockets:2,maxFreeSockets:1}),a=new f.default.Agent({keepAlive:!0,maxSockets:2,maxFreeSockets:1}),i=p.default.create({baseURL:s,timeout:t,proxy:!1,headers:{"X-Ledger-Client-Version":r},httpAgent:o,httpsAgent:a,transitional:{clarifyTimeoutError:!0}});return d.set(n,i),i}class R{constructor(t,r=1e4,n="ldmk-transport-speculos"){this.baseUrl=t;this.timeoutMs=r;this.client=v(t,r,n)}client;async postOnce(t,r){const n=new AbortController,e=setTimeout(()=>n.abort(),r);try{const{data:o}=await this.client.post("/apdu",{data:t},{timeout:r,signal:n.signal});return o.data}finally{clearTimeout(e)}}async postAdpu(t){const r=Math.min(1500,this.timeoutMs),n=Math.max(1,Math.floor(this.timeoutMs/r));let e;for(let o=0;o<n;o++)try{return await this.postOnce(t,r)}catch(a){e=a,await new Promise(i=>setTimeout(i,150))}throw e instanceof p.AxiosError||e instanceof Error?e:new Error(String(e))}async pressButton(t){const n={Ll:"left",Rr:"right",LRlr:"both",left:"left",right:"right",both:"both"}[t]??"right";await this.client.post(`/button/${n}`,{action:"press-and-release"},{timeout:1500})}async openEventStream(t,r){const e=(await this.client.get("/events",{params:{stream:"true"},responseType:"stream",timeout:0,headers:{Accept:"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","Accept-Encoding":"identity"}})).data;e.on("data",a=>{a.toString("utf8").split(`
2
- `).forEach(u=>{if(u.startsWith("data: ")){const m=u.slice(6);try{t(JSON.parse(m))}catch{t({data:m})}}})});const o=()=>r?.();return e.on("close",o),e.on("end",o),e.on("error",o),e}get base(){return this.baseUrl}}0&&(module.exports={HttpLegacySpeculosDatasource});
3
- //# sourceMappingURL=HttpLegacySpeculosDatasource.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../../src/internal/datasource/HttpLegacySpeculosDatasource.ts"],
4
- "sourcesContent": ["import axios, { AxiosError, type AxiosInstance } from \"axios\";\nimport http from \"http\";\nimport https from \"https\";\n\ntype SpeculosApduDTO = { data: string };\n\nconst _sharedClients = new Map<string, AxiosInstance>();\n\nfunction getSharedAxios(\n baseUrl: string,\n timeoutMs: number,\n clientHeader: string,\n): AxiosInstance {\n const key = `${baseUrl}::${clientHeader}`;\n const existing = _sharedClients.get(key);\n if (existing) return existing;\n\n const httpAgent = new http.Agent({\n keepAlive: true,\n maxSockets: 2,\n maxFreeSockets: 1,\n });\n const httpsAgent = new https.Agent({\n keepAlive: true,\n maxSockets: 2,\n maxFreeSockets: 1,\n });\n\n const inst = axios.create({\n baseURL: baseUrl,\n timeout: timeoutMs,\n proxy: false,\n headers: { \"X-Ledger-Client-Version\": clientHeader },\n httpAgent,\n httpsAgent,\n transitional: { clarifyTimeoutError: true },\n });\n\n _sharedClients.set(key, inst);\n return inst;\n}\n\nexport class HttpLegacySpeculosDatasource {\n private readonly client: AxiosInstance;\n\n constructor(\n private readonly baseUrl: string,\n private readonly timeoutMs: number = 10000,\n clientHeader: string = \"ldmk-transport-speculos\",\n ) {\n this.client = getSharedAxios(baseUrl, timeoutMs, clientHeader);\n }\n\n private async postOnce(apdu: string, ms: number): Promise<string> {\n const ac = new AbortController();\n const killer = setTimeout(() => ac.abort(), ms);\n try {\n const { data } = await this.client.post<SpeculosApduDTO>(\n \"/apdu\",\n { data: apdu },\n { timeout: ms, signal: ac.signal },\n );\n return data.data;\n } finally {\n clearTimeout(killer);\n }\n }\n\n async postAdpu(apdu: string): Promise<string> {\n const perTryMs = Math.min(1500, this.timeoutMs);\n const tries = Math.max(1, Math.floor(this.timeoutMs / perTryMs));\n let lastErr: unknown;\n for (let i = 0; i < tries; i++) {\n try {\n return await this.postOnce(apdu, perTryMs);\n } catch (e) {\n lastErr = e;\n await new Promise((r) => setTimeout(r, 150));\n }\n }\n if (lastErr instanceof AxiosError) throw lastErr;\n throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));\n }\n\n async pressButton(\n but: \"Ll\" | \"Rr\" | \"LRlr\" | \"left\" | \"right\" | \"both\",\n ): Promise<void> {\n const map: Record<string, \"left\" | \"right\" | \"both\"> = {\n Ll: \"left\",\n Rr: \"right\",\n LRlr: \"both\",\n left: \"left\",\n right: \"right\",\n both: \"both\",\n };\n const input = map[but] ?? \"right\";\n await this.client.post(\n `/button/${input}`,\n { action: \"press-and-release\" },\n { timeout: 1500 },\n );\n }\n\n async openEventStream(\n onEvent: (json: Record<string, unknown>) => void,\n onClose?: () => void,\n ): Promise<NodeJS.ReadableStream> {\n const response = await this.client.get(\"/events\", {\n params: { stream: \"true\" },\n responseType: \"stream\",\n timeout: 0, // keep SSE alive\n headers: {\n Accept: \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Accept-Encoding\": \"identity\", // avoid gzip buffering\n },\n });\n const stream = response.data as NodeJS.ReadableStream;\n\n stream.on(\"data\", (chunk: Buffer) => {\n const txt = chunk.toString(\"utf8\");\n txt.split(\"\\n\").forEach((line) => {\n if (line.startsWith(\"data: \")) {\n const payload = line.slice(6);\n try {\n onEvent(JSON.parse(payload));\n } catch {\n onEvent({ data: payload });\n }\n }\n });\n });\n\n const end = () => onClose?.();\n stream.on(\"close\", end);\n stream.on(\"end\", end);\n stream.on(\"error\", end);\n\n return stream;\n }\n\n get base(): string {\n return this.baseUrl;\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["HttpLegacySpeculosDatasource_exports", "__export", "HttpLegacySpeculosDatasource", "__toCommonJS", "import_axios", "import_http", "import_https", "_sharedClients", "getSharedAxios", "baseUrl", "timeoutMs", "clientHeader", "key", "existing", "httpAgent", "http", "httpsAgent", "https", "inst", "axios", "apdu", "ms", "ac", "killer", "data", "perTryMs", "tries", "lastErr", "i", "e", "r", "but", "input", "onEvent", "onClose", "stream", "chunk", "line", "payload", "end"]
7
- }
@@ -1,2 +0,0 @@
1
- import{ApduParser as d,bufferToHexaString as u,DeviceModelId as l,GeneralDmkError as g,OpeningConnectionError as v}from"@ledgerhq/device-management-kit";import{Left as p,Right as i}from"purify-ts";import{from as a}from"rxjs";import{HttpLegacySpeculosDatasource as D}from"../internal/datasource/HttpLegacySpeculosDatasource";import{speculosIdentifier as h}from"./SpeculosTransport";class m{logger;identifier=h;_speculosDataSource;connectedDevice=null;speculosDevice={id:"SpeculosID",deviceModel:{id:l.STAX,productName:"Speculos - App Name - version",usbProductId:16,bootloaderUsbProductId:1,getBlockSize(){return 32},blockSize:32,usbOnly:!0,memorySize:320*1024,masks:[823132160]},transport:this.identifier};constructor(r,e,t){this.logger=r("QuietSpeculosTransport"),this._speculosDataSource=new D(t,1e4,"ldmk-transport-speculos")}isSupported(){return!0}getIdentifier(){return this.identifier}listenToAvailableDevices(){return a([[this.speculosDevice]])}startDiscovering(){return this.logger.debug("startDiscovering"),a([this.speculosDevice])}stopDiscovering(){this.logger.debug("stopDiscovering")}async connect(r){this.logger.debug("connect");try{const e=await this._speculosDataSource.postAdpu("B0010000");this.logger.debug(`Hex Response: ${e}`);const t=this.createApduResponse(e),o=new d(t);o.extract8BitUInt();const s=o.encodeToString(o.extractFieldLVEncoded()),n=o.encodeToString(o.extractFieldLVEncoded());this.logger.debug(`App Name: ${s} and version ${n}`),this.speculosDevice.deviceModel.productName=`Speculos - ${s} - ${n}`}catch{}try{const e={sendApdu:t=>this.sendApdu(r.deviceId,r.onDisconnect,t),deviceModel:this.speculosDevice.deviceModel,transport:this.identifier,id:"SpeculosID",type:"USB"};return this.connectedDevice=e,i(e)}catch(e){return p(new v(e))}}async disconnect(r){return this.logger.debug("disconnect"),this.connectedDevice=null,Promise.resolve(i(void 0))}async sendApdu(r,e,t){try{const o=u(t).substring(2).toUpperCase();this.logger.debug(`[QuietSpeculosTransport] send APDU: ${o}`);const s=await this._speculosDataSource.postAdpu(o),n=this.createApduResponse(s);return i(n)}catch(o){return this.connectedDevice&&(this.logger.debug("disconnecting due to APDU error"),e(r),await this.disconnect({connectedDevice:this.connectedDevice})),p(new g(o))}}createApduResponse(r){const e=r.slice(-4),t=r.slice(0,-4);return this.logger.debug(`[QuietSpeculosTransport] Status code hex: ${e}`),this.logger.debug(`[QuietSpeculosTransport] data hex: ${t}`),{statusCode:this.fromHexString(e),data:this.fromHexString(t)}}fromHexString(r){return r?new Uint8Array(r.match(/.{1,2}/g).map(e=>parseInt(e,16))):new Uint8Array(0)}}const A=(c="http://127.0.0.1:5000")=>({config:r,loggerServiceFactory:e})=>new m(e,r,c);export{m as QuietSpeculosTransport,A as quietSpeculosTransportFactory};
2
- //# sourceMappingURL=QuietSpeculosTransport.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/api/QuietSpeculosTransport.ts"],
4
- "sourcesContent": ["import {\n ApduParser,\n type ApduResponse,\n bufferToHexaString,\n type ConnectError,\n type DeviceId,\n DeviceModelId,\n type DisconnectHandler,\n type DmkConfig,\n type DmkError,\n GeneralDmkError,\n type LoggerPublisherService,\n OpeningConnectionError,\n type Transport,\n type TransportConnectedDevice,\n type TransportDiscoveredDevice,\n type TransportFactory,\n type TransportIdentifier,\n} from \"@ledgerhq/device-management-kit\";\nimport { type Either, Left, Right } from \"purify-ts\";\nimport { from, type Observable } from \"rxjs\";\n\nimport { HttpLegacySpeculosDatasource } from \"@internal/datasource/HttpLegacySpeculosDatasource\";\n\nimport { speculosIdentifier } from \"./SpeculosTransport\";\n\nexport class QuietSpeculosTransport implements Transport {\n private logger: LoggerPublisherService;\n private readonly identifier: TransportIdentifier = speculosIdentifier;\n private readonly _speculosDataSource: HttpLegacySpeculosDatasource;\n\n private connectedDevice: TransportConnectedDevice | null = null;\n\n private readonly speculosDevice: TransportDiscoveredDevice = {\n id: \"SpeculosID\",\n deviceModel: {\n id: DeviceModelId.STAX,\n productName: \"Speculos - App Name - version\",\n usbProductId: 0x10,\n bootloaderUsbProductId: 0x0001,\n getBlockSize() {\n return 32;\n },\n blockSize: 32,\n usbOnly: true,\n memorySize: 320 * 1024,\n masks: [0x31100000],\n },\n transport: this.identifier,\n };\n\n constructor(\n loggerServiceFactory: (tag: string) => LoggerPublisherService,\n _config: DmkConfig,\n speculosUrl: string,\n ) {\n this.logger = loggerServiceFactory(\"QuietSpeculosTransport\");\n this._speculosDataSource = new HttpLegacySpeculosDatasource(\n speculosUrl,\n 10000,\n \"ldmk-transport-speculos\",\n );\n }\n\n isSupported(): boolean {\n return true;\n }\n\n getIdentifier(): TransportIdentifier {\n return this.identifier;\n }\n\n listenToAvailableDevices(): Observable<TransportDiscoveredDevice[]> {\n return from([[this.speculosDevice]]);\n }\n\n startDiscovering(): Observable<TransportDiscoveredDevice> {\n this.logger.debug(\"startDiscovering\");\n return from([this.speculosDevice]);\n }\n\n stopDiscovering(): void {\n this.logger.debug(\"stopDiscovering\");\n }\n\n async connect(params: {\n deviceId: DeviceId;\n onDisconnect: DisconnectHandler;\n }): Promise<Either<ConnectError, TransportConnectedDevice>> {\n this.logger.debug(\"connect\");\n\n // Probe app name/version via GET_VERSION (B0010000) if possible\n try {\n const hexResponse = await this._speculosDataSource.postAdpu(\"B0010000\");\n this.logger.debug(`Hex Response: ${hexResponse}`);\n const apduResponse = this.createApduResponse(hexResponse);\n const parser = new ApduParser(apduResponse);\n parser.extract8BitUInt();\n const appName = parser.encodeToString(parser.extractFieldLVEncoded());\n const appVersion = parser.encodeToString(parser.extractFieldLVEncoded());\n this.logger.debug(`App Name: ${appName} and version ${appVersion}`);\n\n this.speculosDevice.deviceModel.productName = `Speculos - ${appName} - ${appVersion}`;\n } catch {\n // ignore if the app doesn't support GET_VERSION\n }\n\n try {\n const connectedDevice: TransportConnectedDevice = {\n sendApdu: (apdu: Uint8Array) =>\n this.sendApdu(params.deviceId, params.onDisconnect, apdu),\n deviceModel: this.speculosDevice.deviceModel,\n transport: this.identifier,\n id: \"SpeculosID\",\n type: \"USB\",\n };\n\n this.connectedDevice = connectedDevice;\n return Right(connectedDevice);\n } catch (error) {\n return Left(new OpeningConnectionError(error as Error));\n }\n }\n\n async disconnect(_params: {\n connectedDevice: TransportConnectedDevice;\n }): Promise<Either<DmkError, void>> {\n this.logger.debug(\"disconnect\");\n this.connectedDevice = null;\n return Promise.resolve(Right(undefined));\n }\n\n async sendApdu(\n deviceId: DeviceId,\n onDisconnect: DisconnectHandler,\n apdu: Uint8Array,\n ): Promise<Either<DmkError, ApduResponse>> {\n try {\n const hex = bufferToHexaString(apdu).substring(2).toUpperCase();\n this.logger.debug(`[QuietSpeculosTransport] send APDU: ${hex}`);\n const hexResponse = await this._speculosDataSource.postAdpu(hex);\n const resp = this.createApduResponse(hexResponse);\n return Right(resp);\n } catch (error) {\n if (this.connectedDevice) {\n this.logger.debug(\"disconnecting due to APDU error\");\n onDisconnect(deviceId);\n await this.disconnect({ connectedDevice: this.connectedDevice });\n }\n return Left(new GeneralDmkError(error as Error));\n }\n }\n\n private createApduResponse(hexApdu: string): ApduResponse {\n const sw = hexApdu.slice(-4);\n const payload = hexApdu.slice(0, -4);\n this.logger.debug(`[QuietSpeculosTransport] Status code hex: ${sw}`);\n this.logger.debug(`[QuietSpeculosTransport] data hex: ${payload}`);\n return {\n statusCode: this.fromHexString(sw),\n data: this.fromHexString(payload),\n };\n }\n\n private fromHexString(hexString: string): Uint8Array {\n if (!hexString) return new Uint8Array(0);\n return new Uint8Array(\n hexString.match(/.{1,2}/g)!.map((b) => parseInt(b, 16)),\n );\n }\n}\n\nexport const quietSpeculosTransportFactory: (\n speculosUrl?: string,\n) => TransportFactory =\n (speculosUrl = \"http://127.0.0.1:5000\") =>\n ({ config, loggerServiceFactory }) =>\n new QuietSpeculosTransport(loggerServiceFactory, config, speculosUrl);\n"],
5
- "mappings": "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",
6
- "names": ["ApduParser", "bufferToHexaString", "DeviceModelId", "GeneralDmkError", "OpeningConnectionError", "Left", "Right", "from", "HttpLegacySpeculosDatasource", "speculosIdentifier", "QuietSpeculosTransport", "loggerServiceFactory", "_config", "speculosUrl", "params", "hexResponse", "apduResponse", "parser", "appName", "appVersion", "connectedDevice", "apdu", "error", "_params", "deviceId", "onDisconnect", "hex", "resp", "hexApdu", "sw", "payload", "hexString", "b", "quietSpeculosTransportFactory", "config"]
7
- }
@@ -1,3 +0,0 @@
1
- import u,{AxiosError as m}from"axios";import h from"http";import d from"https";const l=new Map;function g(i,r,e){const s=`${i}::${e}`,t=l.get(s);if(t)return t;const n=new h.Agent({keepAlive:!0,maxSockets:2,maxFreeSockets:1}),o=new d.Agent({keepAlive:!0,maxSockets:2,maxFreeSockets:1}),a=u.create({baseURL:i,timeout:r,proxy:!1,headers:{"X-Ledger-Client-Version":e},httpAgent:n,httpsAgent:o,transitional:{clarifyTimeoutError:!0}});return l.set(s,a),a}class A{constructor(r,e=1e4,s="ldmk-transport-speculos"){this.baseUrl=r;this.timeoutMs=e;this.client=g(r,e,s)}client;async postOnce(r,e){const s=new AbortController,t=setTimeout(()=>s.abort(),e);try{const{data:n}=await this.client.post("/apdu",{data:r},{timeout:e,signal:s.signal});return n.data}finally{clearTimeout(t)}}async postAdpu(r){const e=Math.min(1500,this.timeoutMs),s=Math.max(1,Math.floor(this.timeoutMs/e));let t;for(let n=0;n<s;n++)try{return await this.postOnce(r,e)}catch(o){t=o,await new Promise(a=>setTimeout(a,150))}throw t instanceof m||t instanceof Error?t:new Error(String(t))}async pressButton(r){const s={Ll:"left",Rr:"right",LRlr:"both",left:"left",right:"right",both:"both"}[r]??"right";await this.client.post(`/button/${s}`,{action:"press-and-release"},{timeout:1500})}async openEventStream(r,e){const t=(await this.client.get("/events",{params:{stream:"true"},responseType:"stream",timeout:0,headers:{Accept:"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","Accept-Encoding":"identity"}})).data;t.on("data",o=>{o.toString("utf8").split(`
2
- `).forEach(c=>{if(c.startsWith("data: ")){const p=c.slice(6);try{r(JSON.parse(p))}catch{r({data:p})}}})});const n=()=>e?.();return t.on("close",n),t.on("end",n),t.on("error",n),t}get base(){return this.baseUrl}}export{A as HttpLegacySpeculosDatasource};
3
- //# sourceMappingURL=HttpLegacySpeculosDatasource.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../../src/internal/datasource/HttpLegacySpeculosDatasource.ts"],
4
- "sourcesContent": ["import axios, { AxiosError, type AxiosInstance } from \"axios\";\nimport http from \"http\";\nimport https from \"https\";\n\ntype SpeculosApduDTO = { data: string };\n\nconst _sharedClients = new Map<string, AxiosInstance>();\n\nfunction getSharedAxios(\n baseUrl: string,\n timeoutMs: number,\n clientHeader: string,\n): AxiosInstance {\n const key = `${baseUrl}::${clientHeader}`;\n const existing = _sharedClients.get(key);\n if (existing) return existing;\n\n const httpAgent = new http.Agent({\n keepAlive: true,\n maxSockets: 2,\n maxFreeSockets: 1,\n });\n const httpsAgent = new https.Agent({\n keepAlive: true,\n maxSockets: 2,\n maxFreeSockets: 1,\n });\n\n const inst = axios.create({\n baseURL: baseUrl,\n timeout: timeoutMs,\n proxy: false,\n headers: { \"X-Ledger-Client-Version\": clientHeader },\n httpAgent,\n httpsAgent,\n transitional: { clarifyTimeoutError: true },\n });\n\n _sharedClients.set(key, inst);\n return inst;\n}\n\nexport class HttpLegacySpeculosDatasource {\n private readonly client: AxiosInstance;\n\n constructor(\n private readonly baseUrl: string,\n private readonly timeoutMs: number = 10000,\n clientHeader: string = \"ldmk-transport-speculos\",\n ) {\n this.client = getSharedAxios(baseUrl, timeoutMs, clientHeader);\n }\n\n private async postOnce(apdu: string, ms: number): Promise<string> {\n const ac = new AbortController();\n const killer = setTimeout(() => ac.abort(), ms);\n try {\n const { data } = await this.client.post<SpeculosApduDTO>(\n \"/apdu\",\n { data: apdu },\n { timeout: ms, signal: ac.signal },\n );\n return data.data;\n } finally {\n clearTimeout(killer);\n }\n }\n\n async postAdpu(apdu: string): Promise<string> {\n const perTryMs = Math.min(1500, this.timeoutMs);\n const tries = Math.max(1, Math.floor(this.timeoutMs / perTryMs));\n let lastErr: unknown;\n for (let i = 0; i < tries; i++) {\n try {\n return await this.postOnce(apdu, perTryMs);\n } catch (e) {\n lastErr = e;\n await new Promise((r) => setTimeout(r, 150));\n }\n }\n if (lastErr instanceof AxiosError) throw lastErr;\n throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));\n }\n\n async pressButton(\n but: \"Ll\" | \"Rr\" | \"LRlr\" | \"left\" | \"right\" | \"both\",\n ): Promise<void> {\n const map: Record<string, \"left\" | \"right\" | \"both\"> = {\n Ll: \"left\",\n Rr: \"right\",\n LRlr: \"both\",\n left: \"left\",\n right: \"right\",\n both: \"both\",\n };\n const input = map[but] ?? \"right\";\n await this.client.post(\n `/button/${input}`,\n { action: \"press-and-release\" },\n { timeout: 1500 },\n );\n }\n\n async openEventStream(\n onEvent: (json: Record<string, unknown>) => void,\n onClose?: () => void,\n ): Promise<NodeJS.ReadableStream> {\n const response = await this.client.get(\"/events\", {\n params: { stream: \"true\" },\n responseType: \"stream\",\n timeout: 0, // keep SSE alive\n headers: {\n Accept: \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Accept-Encoding\": \"identity\", // avoid gzip buffering\n },\n });\n const stream = response.data as NodeJS.ReadableStream;\n\n stream.on(\"data\", (chunk: Buffer) => {\n const txt = chunk.toString(\"utf8\");\n txt.split(\"\\n\").forEach((line) => {\n if (line.startsWith(\"data: \")) {\n const payload = line.slice(6);\n try {\n onEvent(JSON.parse(payload));\n } catch {\n onEvent({ data: payload });\n }\n }\n });\n });\n\n const end = () => onClose?.();\n stream.on(\"close\", end);\n stream.on(\"end\", end);\n stream.on(\"error\", end);\n\n return stream;\n }\n\n get base(): string {\n return this.baseUrl;\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["axios", "AxiosError", "http", "https", "_sharedClients", "getSharedAxios", "baseUrl", "timeoutMs", "clientHeader", "key", "existing", "httpAgent", "httpsAgent", "inst", "HttpLegacySpeculosDatasource", "apdu", "ms", "ac", "killer", "data", "perTryMs", "tries", "lastErr", "i", "e", "r", "but", "input", "onEvent", "onClose", "stream", "chunk", "line", "payload", "end"]
7
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"QuietSpeculosTransport.d.ts","sourceRoot":"","sources":["../../../../src/api/QuietSpeculosTransport.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,YAAY,EACjB,KAAK,QAAQ,EAEb,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,QAAQ,EAEb,KAAK,sBAAsB,EAE3B,KAAK,SAAS,EACd,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,MAAM,EAAe,MAAM,WAAW,CAAC;AACrD,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAM7C,qBAAa,sBAAuB,YAAW,SAAS;IACtD,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA2C;IACtE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA+B;IAEnE,OAAO,CAAC,eAAe,CAAyC;IAEhE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAgB7B;gBAGA,oBAAoB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,sBAAsB,EAC7D,OAAO,EAAE,SAAS,EAClB,WAAW,EAAE,MAAM;IAUrB,WAAW,IAAI,OAAO;IAItB,aAAa,IAAI,mBAAmB;IAIpC,wBAAwB,IAAI,UAAU,CAAC,yBAAyB,EAAE,CAAC;IAInE,gBAAgB,IAAI,UAAU,CAAC,yBAAyB,CAAC;IAKzD,eAAe,IAAI,IAAI;IAIjB,OAAO,CAAC,MAAM,EAAE;QACpB,QAAQ,EAAE,QAAQ,CAAC;QACnB,YAAY,EAAE,iBAAiB,CAAC;KACjC,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,wBAAwB,CAAC,CAAC;IAoCrD,UAAU,CAAC,OAAO,EAAE;QACxB,eAAe,EAAE,wBAAwB,CAAC;KAC3C,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAM7B,QAAQ,CACZ,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,iBAAiB,EAC/B,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAiB1C,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,aAAa;CAMtB;AAED,eAAO,MAAM,6BAA6B,EAAE,CAC1C,WAAW,CAAC,EAAE,MAAM,KACjB,gBAGoE,CAAC"}
@@ -1,12 +0,0 @@
1
- export declare class HttpLegacySpeculosDatasource {
2
- private readonly baseUrl;
3
- private readonly timeoutMs;
4
- private readonly client;
5
- constructor(baseUrl: string, timeoutMs?: number, clientHeader?: string);
6
- private postOnce;
7
- postAdpu(apdu: string): Promise<string>;
8
- pressButton(but: "Ll" | "Rr" | "LRlr" | "left" | "right" | "both"): Promise<void>;
9
- openEventStream(onEvent: (json: Record<string, unknown>) => void, onClose?: () => void): Promise<NodeJS.ReadableStream>;
10
- get base(): string;
11
- }
12
- //# sourceMappingURL=HttpLegacySpeculosDatasource.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HttpLegacySpeculosDatasource.d.ts","sourceRoot":"","sources":["../../../../../src/internal/datasource/HttpLegacySpeculosDatasource.ts"],"names":[],"mappings":"AA0CA,qBAAa,4BAA4B;IAIrC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAGpB,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAc,EAC1C,YAAY,GAAE,MAAkC;YAKpC,QAAQ;IAehB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBvC,WAAW,CACf,GAAG,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GACpD,OAAO,CAAC,IAAI,CAAC;IAiBV,eAAe,CACnB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,EAChD,OAAO,CAAC,EAAE,MAAM,IAAI,GACnB,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC;IAoCjC,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}