Skip to content

feat(mobile): migrate emulator proxy transport to DMK WebSocket protocol#14865

Draft
OlivierFreyssinet wants to merge 3 commits intodevelopfrom
feat/LIVE-27000-dmk-ws-proxy-transport
Draft

feat(mobile): migrate emulator proxy transport to DMK WebSocket protocol#14865
OlivierFreyssinet wants to merge 3 commits intodevelopfrom
feat/LIVE-27000-dmk-ws-proxy-transport

Conversation

@OlivierFreyssinet
Copy link
Contributor

@OlivierFreyssinet OlivierFreyssinet commented Feb 26, 2026

✅ Checklist

  • npx changeset was attached.
  • Covered by automatic tests. No automated tests yet — requires manual testing with a physical Ledger device connected via the CLI proxy server to an emulator.
  • Impact of the changes:
    • CLI ledger-live proxy command (rewritten to use DMK + WebSocket-only protocol)
    • Ledger Live Mobile device discovery on emulators (new useWsProxyDevicesDiscovery hook in SelectDevice2)
    • Debug HTTP Transport settings screen (now also persists proxy URL to Redux for the new flow)
    • New @ledgerhq/live-dmk-ws-proxy package (DMK transport, bridge, discovery hook, shared protocol types)
    • Legacy httpdebug transport module is preserved for Speculos E2E test compatibility

📝 Description

Problem: The emulator proxy transport in Ledger Live Mobile relies on legacy LedgerJS packages (@ledgerhq/hw-transport-http, @ledgerhq/hw-transport-node-hid) with an HTTP polling discovery model and a knownDevices Redux hack. This prevents access to DMK features (session management, device actions) and doesn't align with the ongoing DMK migration.

Solution: Introduce a new @ledgerhq/live-dmk-ws-proxy package that provides:

  • WsProxyTransport: DMK Transport implementation with push-based device discovery over WebSocket and APDU exchange
  • DeviceManagementKitWSProxyTransport: Bridge class extending legacy hw-transport that exposes sessionId and dmk properties
  • useWsProxyDevicesDiscovery: React hook for SelectDevice2 integration, following the same pattern as BLE/HID discovery hooks
  • Shared WS protocol types (protocol.ts): Single source of truth for all message types, imported by both CLI server and mobile client

The CLI proxy server (ledger-live proxy) is rewritten to use DeviceManagementKit with nodeHidTransportFactory, replacing express/cors/body-parser with a lean http + ws setup. Device discovery is now push-based (server broadcasts device list changes to all connected clients).

The proxy URL can be configured at build time via DEVICE_PROXY_URL env var or at runtime via the Debug HTTP Transport settings screen. Both sources are merged by the discovery hook through a BehaviorSubject side-channel.

The legacy httpdebug transport module and addKnownDevice flow are preserved for Speculos E2E test compatibility.

❓ Context


🧐 Checklist for the PR Reviewers

  • The code aligns with the requirements described in the linked JIRA or GitHub issue.
  • The PR description clearly documents the changes made and explains any technical trade-offs or design decisions.
  • There are no undocumented trade-offs, technical debt, or maintainability issues.
  • The PR has been tested thoroughly, and any potential edge cases have been considered and handled.
  • Any new dependencies have been justified and documented.
  • Performance considerations have been taken into account. (changes have been profiled or benchmarked if necessary)

Made with Cursor

…protocol

Replace the legacy HTTP proxy transport (hw-transport-http + express) with
a DMK-based WebSocket proxy for Ledger Live Mobile emulator development.

New package @ledgerhq/live-dmk-ws-proxy provides:
- WsProxyTransport: DMK Transport with push-based device discovery
- DeviceManagementKitWSProxyTransport: legacy hw-transport bridge
- useWsProxyDevicesDiscovery: React hook for SelectDevice2 integration
- Shared WS protocol types used by both CLI server and mobile client

CLI proxy server rewritten to use DMK + nodeHidTransportFactory with
WebSocket-only protocol (removed express/cors/body-parser deps).

The legacy httpdebug transport module is preserved for Speculos E2E tests.

LIVE-27000

Made-with: Cursor
return;
}
console.log(
`${TAG} ← ${url}: ${msg.type}`,

Check failure

Code scanning / CodeQL

Use of externally-controlled format string High

Format string depends on a
user-provided value
.
Format string depends on a
user-provided value
.
Format string depends on a
user-provided value
.
Format string depends on a
user-provided value
.

Copilot Autofix

AI about 19 hours ago

General approach: avoid putting untrusted data into the format string argument of any logging function that uses util.format semantics (console.log, console.error, or wrappers like log). Instead, pass a constant format string as the first argument and supply untrusted values as subsequent arguments, typically with a %s placeholder or just as additional arguments after a constant prefix.

Best concrete fix for WsProxyTransport.openConnection: change the console.log in ws.onmessage so that the first argument is a constant string and both url and msg.type are provided as separate arguments. This preserves the exact logged content while ensuring untrusted values aren’t part of the format string. For example:

console.log(
  "%s ← %s: %s",
  TAG,
  url,
  msg.type,
  msg.type === "devices" ? `(${msg.devices.length} devices)` : "",
);

This change is limited to the highlighted logging call around line 256–259 in libs/live-dmk-ws-proxy/src/transport/WsProxyTransport.ts. No new imports or helpers are required; we just adjust the argument structure of the existing console.log. This single change addresses all reported variants associated with this logging site (the variants are all about different taint sources reaching the same sink). The rest of the code in the shown snippets does not put untrusted data directly into format strings as the first argument, so no edits are necessary there.


Suggested changeset 1
libs/live-dmk-ws-proxy/src/transport/WsProxyTransport.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/libs/live-dmk-ws-proxy/src/transport/WsProxyTransport.ts b/libs/live-dmk-ws-proxy/src/transport/WsProxyTransport.ts
--- a/libs/live-dmk-ws-proxy/src/transport/WsProxyTransport.ts
+++ b/libs/live-dmk-ws-proxy/src/transport/WsProxyTransport.ts
@@ -254,7 +254,10 @@
         return;
       }
       console.log(
-        `${TAG} ← ${url}: ${msg.type}`,
+        "%s ← %s: %s",
+        TAG,
+        url,
+        msg.type,
         msg.type === "devices" ? `(${msg.devices.length} devices)` : "",
       );
       this.handleMessage(conn, msg);
EOF
@@ -254,7 +254,10 @@
return;
}
console.log(
`${TAG}${url}: ${msg.type}`,
"%s ← %s: %s",
TAG,
url,
msg.type,
msg.type === "devices" ? `(${msg.devices.length} devices)` : "",
);
this.handleMessage(conn, msg);
Copilot is powered by AI and may make mistakes. Always verify output.
CLI proxy (apps/cli):
- Remove session-readiness wait that hangs with disabled refresher
- Add APDU queue to serialize concurrent sendApdu calls
- Add session cleanup on re-open to avoid stale sessions
- Fix deviceModel field mappings (model/name instead of id/productName)
- Improve error logging to stringify non-Error objects
- Bump node-hid 2.1.2 → 3.3.0 for device-transport-kit-node-hid

Mobile app (apps/ledger-live-mobile):
- Rework DebugHttpTransport screen into WS Proxy configuration UI
- Add @ledgerhq/live-dmk-ws-proxy dependency
- Rename navigation entry from "HTTP Transport" to "WS Proxy"

WS proxy transport lib (libs/live-dmk-ws-proxy):
- Refactor WsProxyTransport to manage WS connections at instance level
  via eager URL manager, independent of subscriber lifecycle
- Fix modelId mapping in useWsProxyDevicesDiscovery (model, not id)
- Preserve WS connections on hook cleanup for active sessions
- Add console.log tracing throughout transport and bridge

Package fixes:
- Fix live-dmk-speculos module resolution (main → lib/index.js,
  exports import → default for rspack CJS compat)

Made-with: Cursor
@OlivierFreyssinet OlivierFreyssinet force-pushed the feat/LIVE-27000-dmk-ws-proxy-transport branch from ca8bbc2 to cc3c52e Compare February 27, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli mobile Has changes in LLM

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant