@ledgerhq/coin-tester-solana 1.8.0-nightly.20251218023953 → 1.8.0-nightly.20251220023811

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/coin-tester-solana",
3
- "version": "1.8.0-nightly.20251218023953",
3
+ "version": "1.8.0-nightly.20251220023811",
4
4
  "description": "Ledger Solana Coin Tester",
5
5
  "main": "src/scenarii.test.ts",
6
6
  "keywords": [
@@ -47,16 +47,17 @@
47
47
  "@solana/spl-token": "0.4.9",
48
48
  "@solana/web3.js": "1.95.4",
49
49
  "bignumber.js": "^9",
50
+ "bip39": "^3.1.0",
50
51
  "docker-compose": "^1",
52
+ "ed25519-hd-key": "^1.3.0",
51
53
  "msw": "^2",
52
- "@ledgerhq/coin-framework": "^6.11.0-nightly.20251218023953",
53
- "@ledgerhq/coin-tester": "^0.14.0-nightly.20251218023953",
54
- "@ledgerhq/coin-solana": "^0.39.0-nightly.20251218023953",
55
- "@ledgerhq/cryptoassets": "^13.35.0-nightly.20251218023953",
56
- "@ledgerhq/live-env": "^2.23.0-nightly.20251218023953",
57
- "@ledgerhq/live-signer-solana": "^0.8.0-nightly.20251218023953",
58
- "@ledgerhq/types-cryptoassets": "^7.31.0-nightly.20251218023953",
59
- "@ledgerhq/types-live": "^6.91.0-nightly.20251218023953"
54
+ "@ledgerhq/coin-framework": "^6.11.0-nightly.20251220023811",
55
+ "@ledgerhq/coin-tester": "^0.14.0-nightly.20251220023811",
56
+ "@ledgerhq/coin-solana": "^0.39.0-nightly.20251220023811",
57
+ "@ledgerhq/cryptoassets": "^13.35.0-nightly.20251220023811",
58
+ "@ledgerhq/live-env": "^2.23.0-nightly.20251220023811",
59
+ "@ledgerhq/types-cryptoassets": "^7.31.0-nightly.20251220023811",
60
+ "@ledgerhq/types-live": "^6.91.0-nightly.20251220023811"
60
61
  },
61
62
  "devDependencies": {
62
63
  "@types/jest": "^29",
@@ -1,8 +1,6 @@
1
1
  import { Scenario, ScenarioTransaction } from "@ledgerhq/coin-tester/main";
2
2
  import { SolanaAccount, Transaction as SolanaTransaction } from "@ledgerhq/coin-solana/types";
3
- import { killSpeculos, spawnSpeculos } from "@ledgerhq/coin-tester/signers/speculos";
4
3
  import resolver from "@ledgerhq/coin-solana/hw-getAddress";
5
- import { LegacySignerSolana } from "@ledgerhq/live-signer-solana";
6
4
  import {
7
5
  RECIPIENT,
8
6
  SOLANA,
@@ -30,16 +28,13 @@ import {
30
28
  initVoteAccount,
31
29
  } from "../connection";
32
30
  import { createBridges } from "@ledgerhq/coin-solana/bridge/js";
31
+ import { buildSigner } from "../signer";
33
32
 
34
33
  global.console = require("console");
35
34
  jest.setTimeout(100_000);
36
35
 
37
36
  type SolanaScenarioTransaction = ScenarioTransaction<SolanaTransaction, SolanaAccount>;
38
37
 
39
- // Note this config runs with NanoX
40
- // https://github.com/LedgerHQ/ledger-live/blob/develop/libs/coin-tester/docker-compose.yml
41
- export const defaultNanoApp = { firmware: "2.4.2", version: "1.9.2" } as const;
42
-
43
38
  function makeScenarioTransactions(address: string): SolanaScenarioTransaction[] {
44
39
  if (!VOTE_ACCOUNT) {
45
40
  throw new Error("Vote account not initialized");
@@ -411,13 +406,10 @@ function makeScenarioTransactions(address: string): SolanaScenarioTransaction[]
411
406
  export const scenarioSolana: Scenario<SolanaTransaction, SolanaAccount> = {
412
407
  name: "Ledger Live Basic Solana Transactions",
413
408
  setup: async () => {
414
- const [{ getOnSpeculosConfirmation, transport }] = await Promise.all([
415
- spawnSpeculos(`/${defaultNanoApp.firmware}/Solana/app_${defaultNanoApp.version}.elf`),
416
- spawnAgave(),
417
- ]);
409
+ await spawnAgave();
418
410
 
419
- const signerContext: Parameters<typeof resolver>[0] = (_, fn) =>
420
- fn(new LegacySignerSolana(transport));
411
+ const signer = await buildSigner();
412
+ const signerContext: Parameters<typeof resolver>[0] = (_, fn) => fn(signer);
421
413
 
422
414
  const getAddress = resolver(signerContext);
423
415
  const { address } = await getAddress("", {
@@ -452,11 +444,8 @@ export const scenarioSolana: Scenario<SolanaTransaction, SolanaAccount> = {
452
444
  account,
453
445
  accountBridge,
454
446
  currencyBridge,
455
- onSignerConfirmation: getOnSpeculosConfirmation("Approve"),
456
447
  };
457
448
  },
458
449
  getTransactions: makeScenarioTransactions,
459
- teardown: async () => {
460
- await Promise.all([killSpeculos(), killAgave()]);
461
- },
450
+ teardown: killAgave,
462
451
  };
@@ -1,5 +1,4 @@
1
1
  import { executeScenario } from "@ledgerhq/coin-tester/main";
2
- import { killSpeculos } from "@ledgerhq/coin-tester/signers/speculos";
3
2
  import { scenarioSolana } from "./scenarii/solana";
4
3
  import { killAgave } from "./agave";
5
4
  // Import fixtures to setup mock store
@@ -7,7 +6,7 @@ import "./fixtures";
7
6
 
8
7
  ["exit", "SIGINT", "SIGQUIT", "SIGTERM", "SIGUSR1", "SIGUSR2", "uncaughtException"].map(e =>
9
8
  process.on(e, async () => {
10
- await Promise.all([killSpeculos(), killAgave()]);
9
+ await killAgave();
11
10
  }),
12
11
  );
13
12
 
@@ -17,7 +16,7 @@ describe("Solana Deterministic Tester", () => {
17
16
  await executeScenario(scenarioSolana);
18
17
  } catch (e) {
19
18
  if (e !== "done") {
20
- await Promise.all([killSpeculos(), killAgave()]);
19
+ await killAgave();
21
20
  throw e;
22
21
  }
23
22
  }
package/src/signer.ts ADDED
@@ -0,0 +1,37 @@
1
+ import { derivePath } from "ed25519-hd-key";
2
+ import { generateMnemonic, mnemonicToSeed } from "bip39";
3
+ import { Keypair, VersionedMessage, VersionedTransaction } from "@solana/web3.js";
4
+ import { SolanaAddress, SolanaSignature, SolanaSigner } from "@ledgerhq/coin-solana/signer";
5
+
6
+ function getAddress(keyPair: Keypair): Promise<SolanaAddress> {
7
+ const address = keyPair.publicKey.toBuffer();
8
+ return Promise.resolve({ address });
9
+ }
10
+
11
+ function signTransaction(keyPair: Keypair, transaction: Buffer): Promise<SolanaSignature> {
12
+ const tx = new VersionedTransaction(VersionedMessage.deserialize(transaction));
13
+ tx.sign([keyPair]);
14
+
15
+ const signature = Buffer.from(tx.signatures[0] ?? []);
16
+ return Promise.resolve({ signature });
17
+ }
18
+
19
+ export async function buildSigner(): Promise<SolanaSigner> {
20
+ const mnemonic = generateMnemonic();
21
+ const seed = await mnemonicToSeed(mnemonic);
22
+ const seedHex = seed.toString("hex");
23
+
24
+ const keyPair = (path: string) => Keypair.fromSeed(derivePath(`m/${path}`, seedHex).key);
25
+
26
+ return {
27
+ getAddress: (path: string) => getAddress(keyPair(path)),
28
+ signTransaction: (path: string, transaction: Buffer) =>
29
+ signTransaction(keyPair(path), transaction),
30
+ getAppConfiguration: () => {
31
+ throw new Error("Not implemented");
32
+ },
33
+ signMessage: () => {
34
+ throw new Error("Not implemented");
35
+ },
36
+ };
37
+ }