@ledgerhq/coin-tester 0.12.0 → 0.13.0-nightly.20251126160702

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @ledgerhq/coin-tester
2
2
 
3
+ ## 0.13.0-nightly.20251126160702
4
+
5
+ ### Minor Changes
6
+
7
+ - [#12563](https://github.com/LedgerHQ/ledger-live/pull/12563) [`b4a4e16`](https://github.com/LedgerHQ/ledger-live/commit/b4a4e160aae6fd64f944ab25633f6931dc4358d3) Thanks [@fAnselmi-Ledger](https://github.com/fAnselmi-Ledger)! - Add DMK speculos transport and device controller
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`b4a4e16`](https://github.com/LedgerHQ/ledger-live/commit/b4a4e160aae6fd64f944ab25633f6931dc4358d3)]:
12
+ - @ledgerhq/live-dmk-speculos@0.2.0-nightly.20251126160702
13
+
3
14
  ## 0.12.0
4
15
 
5
16
  ### Minor Changes
@@ -1,4 +1,4 @@
1
- import SpeculosTransportHttp from "@ledgerhq/hw-transport-node-speculos-http";
1
+ import { DeviceManagementKitTransportSpeculos } from "@ledgerhq/live-dmk-speculos";
2
2
  export declare const delay: (timing: number) => Promise<unknown>;
3
3
  export declare function ensureEnv(): void;
4
4
  export declare function spawnSpeculos(nanoAppEndpoint: `/${string}`, options?: {
@@ -7,7 +7,7 @@ export declare function spawnSpeculos(nanoAppEndpoint: `/${string}`, options?: {
7
7
  endpoint: `/${string}`;
8
8
  }>;
9
9
  }): Promise<{
10
- transport: SpeculosTransportHttp;
10
+ transport: DeviceManagementKitTransportSpeculos;
11
11
  getOnSpeculosConfirmation: (approvalText?: string) => () => Promise<void>;
12
12
  }>;
13
13
  export declare function killSpeculos(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"speculos.d.ts","sourceRoot":"","sources":["../../src/signers/speculos.ts"],"names":[],"mappings":"AAMA,OAAO,qBAAqB,MAAM,2CAA2C,CAAC;AAM9E,eAAO,MAAM,KAAK,WAAY,MAAM,qBAAwD,CAAC;AAE7F,wBAAgB,SAAS,SAexB;AAeD,wBAAsB,aAAa,CACjC,eAAe,EAAE,IAAI,MAAM,EAAE,EAC7B,OAAO,CAAC,EAAE;IACR,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,IAAI,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC7D,GACA,OAAO,CAAC;IACT,SAAS,EAAE,qBAAqB,CAAC;IACjC,yBAAyB,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,KAAK,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E,CAAC,CAmFD;AAED,wBAAsB,YAAY,kBAQjC"}
1
+ {"version":3,"file":"speculos.d.ts","sourceRoot":"","sources":["../../src/signers/speculos.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,oCAAoC,EAAE,MAAM,6BAA6B,CAAC;AAOnF,eAAO,MAAM,KAAK,WAAY,MAAM,qBAAwD,CAAC;AAE7F,wBAAgB,SAAS,SAexB;AAeD,wBAAsB,aAAa,CACjC,eAAe,EAAE,IAAI,MAAM,EAAE,EAC7B,OAAO,CAAC,EAAE;IACR,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,IAAI,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC7D,GACA,OAAO,CAAC;IACT,SAAS,EAAE,oCAAoC,CAAC;IAChD,yBAAyB,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,KAAK,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E,CAAC,CAmGD;AAED,wBAAsB,YAAY,kBAQjC"}
@@ -35,7 +35,8 @@ const chalk_1 = __importDefault(require("chalk"));
35
35
  const promises_1 = __importDefault(require("fs/promises"));
36
36
  const compose = __importStar(require("docker-compose"));
37
37
  const axios_1 = __importStar(require("axios"));
38
- const hw_transport_node_speculos_http_1 = __importDefault(require("@ledgerhq/hw-transport-node-speculos-http"));
38
+ const live_dmk_speculos_1 = require("@ledgerhq/live-dmk-speculos");
39
+ const speculos_device_controller_1 = require("@ledgerhq/speculos-device-controller");
39
40
  const { SPECULOS_API_PORT } = process.env;
40
41
  const cwd = path_1.default.join(__dirname);
41
42
  const delay = (timing) => new Promise(resolve => setTimeout(resolve, timing));
@@ -98,7 +99,7 @@ async function spawnSpeculos(nanoAppEndpoint, options) {
98
99
  const { out } = await compose.logs("speculos", { cwd, env: process.env });
99
100
  if (out.includes("Server started")) {
100
101
  console.log(chalk_1.default.bgYellowBright.black(" - SPECULOS READY ✅ - "));
101
- return hw_transport_node_speculos_http_1.default.open({
102
+ return live_dmk_speculos_1.DeviceManagementKitTransportSpeculos.open({
102
103
  apiPort: SPECULOS_API_PORT,
103
104
  });
104
105
  }
@@ -106,23 +107,39 @@ async function spawnSpeculos(nanoAppEndpoint, options) {
106
107
  return checkSpeculosLogs();
107
108
  }
108
109
  function getOnSpeculosConfirmation(approvalText = "Accept") {
109
- async function onSpeculosConfirmation(e) {
110
- if (e?.type === "device-signature-requested") {
111
- const { data } = await axios_1.default.get(`http://localhost:${SPECULOS_API_PORT}/events?currentscreenonly=true`);
112
- if (data.events[0].text !== approvalText) {
113
- await axios_1.default.post(`http://localhost:${SPECULOS_API_PORT}/button/right`, {
114
- action: "press-and-release",
110
+ return async function onSpeculosConfirmation(e) {
111
+ if (e?.type !== "device-signature-requested")
112
+ return;
113
+ const baseURL = `http://127.0.0.1:${SPECULOS_API_PORT}`;
114
+ const buttonClient = (0, speculos_device_controller_1.deviceControllerClientFactory)(baseURL).buttonFactory();
115
+ const maxAttempts = 80;
116
+ const delayMs = 250;
117
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
118
+ try {
119
+ const { data } = await axios_1.default.get(`${baseURL}/events?currentscreenonly=true`, {
120
+ timeout: 2000,
115
121
  });
116
- onSpeculosConfirmation(e);
122
+ const text = data?.events?.[0]?.text;
123
+ if (text === approvalText) {
124
+ await buttonClient.both();
125
+ return;
126
+ }
127
+ // not on the approval screen yet—scroll right and retry
128
+ await buttonClient.right();
117
129
  }
118
- else {
119
- await axios_1.default.post(`http://localhost:${SPECULOS_API_PORT}/button/both`, {
120
- action: "press-and-release",
121
- });
130
+ catch (err) {
131
+ // retry on network issues
132
+ if (axios_1.default.isAxiosError(err)) {
133
+ // fall through to retry
134
+ }
135
+ else {
136
+ throw err;
137
+ }
122
138
  }
139
+ await (0, exports.delay)(delayMs);
123
140
  }
124
- }
125
- return onSpeculosConfirmation;
141
+ throw new Error(`Speculos confirmation not reached after ${maxAttempts} attempts`);
142
+ };
126
143
  }
127
144
  return checkSpeculosLogs().then(transport => {
128
145
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"speculos.js","sourceRoot":"","sources":["../../src/signers/speculos.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"speculos.js","sourceRoot":"","sources":["../../src/signers/speculos.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import SpeculosTransportHttp from "@ledgerhq/hw-transport-node-speculos-http";
1
+ import { DeviceManagementKitTransportSpeculos } from "@ledgerhq/live-dmk-speculos";
2
2
  export declare const delay: (timing: number) => Promise<unknown>;
3
3
  export declare function ensureEnv(): void;
4
4
  export declare function spawnSpeculos(nanoAppEndpoint: `/${string}`, options?: {
@@ -7,7 +7,7 @@ export declare function spawnSpeculos(nanoAppEndpoint: `/${string}`, options?: {
7
7
  endpoint: `/${string}`;
8
8
  }>;
9
9
  }): Promise<{
10
- transport: SpeculosTransportHttp;
10
+ transport: DeviceManagementKitTransportSpeculos;
11
11
  getOnSpeculosConfirmation: (approvalText?: string) => () => Promise<void>;
12
12
  }>;
13
13
  export declare function killSpeculos(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"speculos.d.ts","sourceRoot":"","sources":["../../src/signers/speculos.ts"],"names":[],"mappings":"AAMA,OAAO,qBAAqB,MAAM,2CAA2C,CAAC;AAM9E,eAAO,MAAM,KAAK,WAAY,MAAM,qBAAwD,CAAC;AAE7F,wBAAgB,SAAS,SAexB;AAeD,wBAAsB,aAAa,CACjC,eAAe,EAAE,IAAI,MAAM,EAAE,EAC7B,OAAO,CAAC,EAAE;IACR,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,IAAI,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC7D,GACA,OAAO,CAAC;IACT,SAAS,EAAE,qBAAqB,CAAC;IACjC,yBAAyB,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,KAAK,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E,CAAC,CAmFD;AAED,wBAAsB,YAAY,kBAQjC"}
1
+ {"version":3,"file":"speculos.d.ts","sourceRoot":"","sources":["../../src/signers/speculos.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,oCAAoC,EAAE,MAAM,6BAA6B,CAAC;AAOnF,eAAO,MAAM,KAAK,WAAY,MAAM,qBAAwD,CAAC;AAE7F,wBAAgB,SAAS,SAexB;AAeD,wBAAsB,aAAa,CACjC,eAAe,EAAE,IAAI,MAAM,EAAE,EAC7B,OAAO,CAAC,EAAE;IACR,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,IAAI,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC7D,GACA,OAAO,CAAC;IACT,SAAS,EAAE,oCAAoC,CAAC;IAChD,yBAAyB,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,KAAK,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E,CAAC,CAmGD;AAED,wBAAsB,YAAY,kBAQjC"}
@@ -3,7 +3,8 @@ import chalk from "chalk";
3
3
  import fs from "fs/promises";
4
4
  import * as compose from "docker-compose";
5
5
  import axios, { AxiosError } from "axios";
6
- import SpeculosTransportHttp from "@ledgerhq/hw-transport-node-speculos-http";
6
+ import { DeviceManagementKitTransportSpeculos } from "@ledgerhq/live-dmk-speculos";
7
+ import { deviceControllerClientFactory } from "@ledgerhq/speculos-device-controller";
7
8
  const { SPECULOS_API_PORT } = process.env;
8
9
  const cwd = path.join(__dirname);
9
10
  export const delay = (timing) => new Promise(resolve => setTimeout(resolve, timing));
@@ -65,7 +66,7 @@ export async function spawnSpeculos(nanoAppEndpoint, options) {
65
66
  const { out } = await compose.logs("speculos", { cwd, env: process.env });
66
67
  if (out.includes("Server started")) {
67
68
  console.log(chalk.bgYellowBright.black(" - SPECULOS READY ✅ - "));
68
- return SpeculosTransportHttp.open({
69
+ return DeviceManagementKitTransportSpeculos.open({
69
70
  apiPort: SPECULOS_API_PORT,
70
71
  });
71
72
  }
@@ -73,23 +74,39 @@ export async function spawnSpeculos(nanoAppEndpoint, options) {
73
74
  return checkSpeculosLogs();
74
75
  }
75
76
  function getOnSpeculosConfirmation(approvalText = "Accept") {
76
- async function onSpeculosConfirmation(e) {
77
- if (e?.type === "device-signature-requested") {
78
- const { data } = await axios.get(`http://localhost:${SPECULOS_API_PORT}/events?currentscreenonly=true`);
79
- if (data.events[0].text !== approvalText) {
80
- await axios.post(`http://localhost:${SPECULOS_API_PORT}/button/right`, {
81
- action: "press-and-release",
77
+ return async function onSpeculosConfirmation(e) {
78
+ if (e?.type !== "device-signature-requested")
79
+ return;
80
+ const baseURL = `http://127.0.0.1:${SPECULOS_API_PORT}`;
81
+ const buttonClient = deviceControllerClientFactory(baseURL).buttonFactory();
82
+ const maxAttempts = 80;
83
+ const delayMs = 250;
84
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
85
+ try {
86
+ const { data } = await axios.get(`${baseURL}/events?currentscreenonly=true`, {
87
+ timeout: 2000,
82
88
  });
83
- onSpeculosConfirmation(e);
89
+ const text = data?.events?.[0]?.text;
90
+ if (text === approvalText) {
91
+ await buttonClient.both();
92
+ return;
93
+ }
94
+ // not on the approval screen yet—scroll right and retry
95
+ await buttonClient.right();
84
96
  }
85
- else {
86
- await axios.post(`http://localhost:${SPECULOS_API_PORT}/button/both`, {
87
- action: "press-and-release",
88
- });
97
+ catch (err) {
98
+ // retry on network issues
99
+ if (axios.isAxiosError(err)) {
100
+ // fall through to retry
101
+ }
102
+ else {
103
+ throw err;
104
+ }
89
105
  }
106
+ await delay(delayMs);
90
107
  }
91
- }
92
- return onSpeculosConfirmation;
108
+ throw new Error(`Speculos confirmation not reached after ${maxAttempts} attempts`);
109
+ };
93
110
  }
94
111
  return checkSpeculosLogs().then(transport => {
95
112
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"speculos.js","sourceRoot":"","sources":["../../src/signers/speculos.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"speculos.js","sourceRoot":"","sources":["../../src/signers/speculos.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,15 +1,16 @@
1
1
  {
2
2
  "name": "@ledgerhq/coin-tester",
3
- "version": "0.12.0",
3
+ "version": "0.13.0-nightly.20251126160702",
4
4
  "description": "Deterministic testing of Ledger coin-modules",
5
5
  "license": "Apache-2.0",
6
6
  "dependencies": {
7
+ "@ledgerhq/speculos-device-controller": "0.1.0",
7
8
  "axios": "1.12.2",
8
9
  "chalk": "^4.1.2",
9
10
  "docker-compose": "^1.1.0",
10
11
  "lodash": "^4.17.21",
11
12
  "rxjs": "7.8.1",
12
- "@ledgerhq/hw-transport-node-speculos-http": "^6.31.0",
13
+ "@ledgerhq/live-dmk-speculos": "^0.2.0-nightly.20251126160702",
13
14
  "@ledgerhq/types-devices": "^6.27.0"
14
15
  },
15
16
  "devDependencies": {
@@ -19,7 +20,7 @@
19
20
  "ts-jest": "^28.0.8",
20
21
  "typescript": "^5.1.3",
21
22
  "@ledgerhq/types-cryptoassets": "^7.30.0",
22
- "@ledgerhq/types-live": "^6.89.0"
23
+ "@ledgerhq/types-live": "^6.90.0-nightly.20251126160702"
23
24
  },
24
25
  "typesVersions": {
25
26
  "*": {
@@ -4,7 +4,8 @@ import fs from "fs/promises";
4
4
  import * as compose from "docker-compose";
5
5
  import axios, { AxiosError } from "axios";
6
6
  import { SignOperationEvent } from "@ledgerhq/types-live";
7
- import SpeculosTransportHttp from "@ledgerhq/hw-transport-node-speculos-http";
7
+ import { DeviceManagementKitTransportSpeculos } from "@ledgerhq/live-dmk-speculos";
8
+ import { deviceControllerClientFactory } from "@ledgerhq/speculos-device-controller";
8
9
  import { ENV } from "../types";
9
10
 
10
11
  const { SPECULOS_API_PORT } = process.env as ENV;
@@ -48,7 +49,7 @@ export async function spawnSpeculos(
48
49
  libraries?: Array<{ name: string; endpoint: `/${string}` }>;
49
50
  },
50
51
  ): Promise<{
51
- transport: SpeculosTransportHttp;
52
+ transport: DeviceManagementKitTransportSpeculos;
52
53
  getOnSpeculosConfirmation: (approvalText?: string) => () => Promise<void>;
53
54
  }> {
54
55
  ensureEnv();
@@ -89,12 +90,12 @@ export async function spawnSpeculos(
89
90
  },
90
91
  });
91
92
 
92
- async function checkSpeculosLogs(): Promise<SpeculosTransportHttp> {
93
+ async function checkSpeculosLogs(): Promise<DeviceManagementKitTransportSpeculos> {
93
94
  const { out } = await compose.logs("speculos", { cwd, env: process.env });
94
95
 
95
96
  if (out.includes("Server started")) {
96
97
  console.log(chalk.bgYellowBright.black(" - SPECULOS READY ✅ - "));
97
- return SpeculosTransportHttp.open({
98
+ return DeviceManagementKitTransportSpeculos.open({
98
99
  apiPort: SPECULOS_API_PORT,
99
100
  });
100
101
  }
@@ -104,27 +105,43 @@ export async function spawnSpeculos(
104
105
  }
105
106
 
106
107
  function getOnSpeculosConfirmation(approvalText = "Accept") {
107
- async function onSpeculosConfirmation(e?: SignOperationEvent): Promise<void> {
108
- if (e?.type === "device-signature-requested") {
109
- const { data } = await axios.get(
110
- `http://localhost:${SPECULOS_API_PORT}/events?currentscreenonly=true`,
111
- );
112
-
113
- if (data.events[0].text !== approvalText) {
114
- await axios.post(`http://localhost:${SPECULOS_API_PORT}/button/right`, {
115
- action: "press-and-release",
116
- });
108
+ return async function onSpeculosConfirmation(e?: SignOperationEvent): Promise<void> {
109
+ if (e?.type !== "device-signature-requested") return;
110
+
111
+ const baseURL = `http://127.0.0.1:${SPECULOS_API_PORT}`;
112
+ const buttonClient = deviceControllerClientFactory(baseURL).buttonFactory();
117
113
 
118
- onSpeculosConfirmation(e);
119
- } else {
120
- await axios.post(`http://localhost:${SPECULOS_API_PORT}/button/both`, {
121
- action: "press-and-release",
114
+ const maxAttempts = 80;
115
+ const delayMs = 250;
116
+
117
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
118
+ try {
119
+ const { data } = await axios.get(`${baseURL}/events?currentscreenonly=true`, {
120
+ timeout: 2000,
122
121
  });
122
+
123
+ const text = data?.events?.[0]?.text;
124
+ if (text === approvalText) {
125
+ await buttonClient.both();
126
+ return;
127
+ }
128
+
129
+ // not on the approval screen yet—scroll right and retry
130
+ await buttonClient.right();
131
+ } catch (err) {
132
+ // retry on network issues
133
+ if (axios.isAxiosError(err)) {
134
+ // fall through to retry
135
+ } else {
136
+ throw err;
137
+ }
123
138
  }
139
+
140
+ await delay(delayMs);
124
141
  }
125
- }
126
142
 
127
- return onSpeculosConfirmation;
143
+ throw new Error(`Speculos confirmation not reached after ${maxAttempts} attempts`);
144
+ };
128
145
  }
129
146
 
130
147
  return checkSpeculosLogs().then(transport => {