Skip to main content

mock-server

Talk to the DMK device mock server (apps/device-mock-server, default http://127.0.0.1:9752) with curl. Make fake devices, connect them, add APDU mocks, send APDUs, break commands on purpose. ALWAYS read this skill when the user says "mock server", makes/changes a mock device, adds mocks, forces an APDU error, or pokes a device Ledger Live/DMK is on.

Quellinformationen

Repository
LedgerHQ/device-sdk-ts
Letzte Quellaktivität
28. August 2026 um 14:03
Erkannte Sprache von SKILL.md
Englisch
Sterne
48
Forks
38

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
mock-server
description
Talk to the DMK device mock server (apps/device-mock-server, default http://127.0.0.1:9752) with curl. Make fake devices, connect them, add APDU mocks, send APDUs, break commands on purpose. ALWAYS read this skill when the user says "mock server", makes/changes a mock device, adds mocks, forces an APDU error, or pokes a device Ledger Live/DMK is on.
# Mock server Fake Ledger devices over REST. You do curl. Server hands back JSON. Big book of every route: `apps/device-mock-server/openapi.yaml`. Read it when this file is not enough. ## Rules to remember - URL is `http://127.0.0.1:9752`. - Every call needs `Authorization: Bearer <token>`. Only `POST /auth` and `GET /health` go free. - Get token: `POST /auth`. Or steal the one Ledger Live/DMK uses. - Curl to `127.0.0.1` needs `required_permissions: ["all"]`. - Server forgets everything on restart. No disk. Set once per shell: ```bash BASE=http://127.0.0.1:9752 TOKEN=<bearer-token> AUTH="Authorization: Bearer $TOKEN" JSON="Content-Type: application/json" ``` ## Client device (Ledger Live / DMK) Client makes its own device when it connects. To touch it: - Ask user for the FULL token. Logs show only first 8 letters. - Find device with `GET /devices`. Change it with `PATCH`. - NEVER delete then remake it. New id = client lost forever. ## The curl commands ```bash # Token + health curl -s -X POST $BASE/auth # -> { token, expires_at } curl -s $BASE/health # Devices curl -s $BASE/devices -H "$AUTH" curl -s $BASE/devices/<id> -H "$AUTH" curl -s -X POST $BASE/devices -H "$AUTH" -H "$JSON" \ -d '{"name":"Ledger Flex","device_type":"flex","firmware_version":"1.9.1"}' curl -s -X PATCH $BASE/devices/<id> -H "$AUTH" -H "$JSON" \ -d '{"firmware_version":"1.10.0"}' curl -s -X DELETE $BASE/devices/<id> -H "$AUTH" # Plug / unplug curl -s -X POST $BASE/devices/<id>/connect -H "$AUTH" # or /disconnect # Send APDU curl -s -X POST $BASE/devices/<id>/apdu -H "$AUTH" -H "$JSON" -d '{"apdu":"e001000000"}' # Mocks curl -s $BASE/devices/<id>/mocks -H "$AUTH" curl -s -X POST $BASE/devices/<id>/mocks -H "$AUTH" -H "$JSON" -d '{"prefix":"b001","response":"5515"}' curl -s -X PATCH $BASE/devices/<id>/mocks/<mockId> -H "$AUTH" -H "$JSON" -d '{"prefix":"b001","response":"9000"}' curl -s -X DELETE $BASE/devices/<id>/mocks/<mockId> -H "$AUTH" curl -s -X DELETE $BASE/devices/<id>/mocks -H "$AUTH" # kill all # Save / load session curl -s $BASE/export -H "$AUTH" curl -s -X POST $BASE/import -H "$AUTH" -H "$JSON" -d '<SessionExport json>' # Speculos seed (⚠️ plaintext — test mnemonics only, never real keys) curl -s -X PUT $BASE/sessions/current/seed -H "$AUTH" -H "$JSON" \ -d '{"seed":"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"}' ``` `device_type`: `nanoS`, `nanoSP`, `nanoX`, `stax`, `flex`, `apexp`. `PATCH` keeps the id and only changes fields you send. ## Open App / Close App Format: `e0 d8 00 00 <len> <app-name-ascii-hex>` — Close: `b0 a7 00 00 00`. ```bash # Open Bitcoin (7 chars → 07, "Bitcoin" = 426974636f696e) curl -s -X POST $BASE/devices/<id>/apdu -H "$AUTH" -H "$JSON" \ -d '{"apdu":"e0d8000007426974636f696e"}' # Open Ethereum (8 chars → 08, "Ethereum" = 457468657265756d) curl -s -X POST $BASE/devices/<id>/apdu -H "$AUTH" -H "$JSON" \ -d '{"apdu":"e0d8000008457468657265756d"}' # Close App (any app) curl -s -X POST $BASE/devices/<id>/apdu -H "$AUTH" -H "$JSON" \ -d '{"apdu":"b0a7000000"}' ``` All three return `{"response":"9000"}` on success. Open App returns `6807` if the app is not in the device's `apps` list (add it via `POST /devices` or `PATCH /devices/<id>`). Build the hex for any app on the fly: ```bash app="Solana" hex=$(printf '%s' "$app" | xxd -p | tr -d '\n') len=$(printf '%02x' ${#app}) curl -s -X POST $BASE/devices/<id>/apdu -H "$AUTH" -H "$JSON" \ -d "{\"apdu\":\"e0d800${len}${hex}\"}" ``` ## Mocks: how they work - Mock catches any APDU that STARTS WITH `prefix`. - One `response`, or a list `responses` (used one by one, then loops). - Longest prefix wins. Newest wins ties. Mock beats the server's own answer. - Answer = `<data><status>`. `9000` = ok. `6d00` = no/unknown. `5515` = locked. ```bash # Say device is locked: curl -s -X POST $BASE/devices/<id>/mocks -H "$AUTH" -H "$JSON" -d '{"prefix":"b001","response":"5515"}' # Break a command on purpose: curl -s -X POST $BASE/devices/<id>/mocks -H "$AUTH" -H "$JSON" -d '{"prefix":"e00300","response":"6d00"}' # Ok, ok, then fail, on repeat: curl -s -X POST $BASE/devices/<id>/mocks -H "$AUTH" -H "$JSON" \ -d '{"prefix":"e0aa0000","responses":["cafe9000","cafe9000","6d00"]}' ``` Add mock = new behavior. Delete mock = old behavior back. ## Speculos seed Each session starts with the default test mnemonic. Override it per-session before opening an app (the seed is forwarded to Speculinho on every `/acquire`): ```bash curl -s -X PUT $BASE/sessions/current/seed -H "$AUTH" -H "$JSON" \ -d '{"seed":"glory promote mansion idle axis finger extend february uncover one trip resolve toe"}' ``` ⚠️ **Not secure.** Stored in plaintext in server memory and sent over plain HTTP. Use only test/dummy mnemonics — never a real production key. ## Onboarding Make a fresh, not-onboarded device and walk it through Ledger Live's SyncOnboarding steps. Ask for `onboarded: false` at create time (omit it, or `true`, for a normal onboarded device): ```bash curl -s -X POST $BASE/devices -H "$AUTH" -H "$JSON" \ -d '{"name":"Ledger Nano X","device_type":"nanoX","firmware_version":"1.3.0","onboarded":false}' ``` State lives in the GetOsVersion (`e001000000`) answer's `seFlags`: byte 0 has the onboarded bit, byte 3 the step. Poll `e001000000` to read it and to move the flow along. - Starts at WELCOME (step `00`), not onboarded. Dwells here until you send `e0030000` (enter early check). - Now at EARLY_CHECK (step `0f`). Dwells here until you send `e0030001` (exit early check). - After exit, each `e001000000` poll auto-advances one step: ChooseName `0c` -> Pin `06` -> SetupChoice `05` -> NewDevice `07` -> NewDeviceConfirming `08` -> SafetyWarning `0a` -> Ready `0b`. - At Ready, byte 0 flips to `e6` (onboarded set) and `GET /devices/<id>` now says `onboarded: true`. ```bash # Walk it: enter, exit, then poll until Ready. curl -s -X POST $BASE/devices/<id>/apdu -H "$AUTH" -H "$JSON" -d '{"apdu":"e0030000"}' # enter early check curl -s -X POST $BASE/devices/<id>/apdu -H "$AUTH" -H "$JSON" -d '{"apdu":"e0030001"}' # exit early check curl -s -X POST $BASE/devices/<id>/apdu -H "$AUTH" -H "$JSON" -d '{"apdu":"e001000000"}' # poll (repeat to advance) ``` ## Newest firmware Server has no "latest" list. Read the real version from Ledger, then `PATCH`: - Page: https://support.ledger.com/article/7103926130845-zd (Stax, Flex, Nano Gen5, Nano X, Nano S Plus). - Read the page fresh each time. Numbers change. ## Touch the screen (Speculos) Some APDUs wait for a screen tap (e.g. Web3 Check `e032010000` on Ethereum). No tap = hang until timeout (`6d00`). Tap while APDU is flying: ```bash # Stax 400x672: accept = x=200,y=537 ; reject = x=200,y=604 curl -s -X POST $BASE/devices/<id>/speculos/finger -H "$AUTH" -H "$JSON" \ -d '{"action":"press-and-release","x":200,"y":537}' ```
Auf GitHub ansehen