@faremeter/wallet-ledger 0.1.2 → 0.5.0

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": "@faremeter/wallet-ledger",
3
- "version": "0.1.2",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -8,14 +8,15 @@
8
8
  "@ledgerhq/hw-app-eth": "^6.36.0",
9
9
  "@ledgerhq/hw-app-solana": "^7.2.0",
10
10
  "@ledgerhq/hw-transport": "^6.31.0",
11
- "@ledgerhq/hw-transport-webusb": "^6.29.0",
12
11
  "@ledgerhq/hw-transport-node-hid": "^6.29.0",
13
- "@solana/web3.js": "^1.95.0",
14
- "arktype": "^2.1.20",
15
- "viem": "^2.23.6"
12
+ "@ledgerhq/hw-transport-webusb": "^6.29.0",
13
+ "@logtape/logtape": "1.0.4",
14
+ "@solana/web3.js": "1.98.4",
15
+ "arktype": "2.1.21",
16
+ "viem": "2.37.2"
16
17
  },
17
18
  "devDependencies": {
18
- "typescript": "^5.5.4",
19
- "tsc-esm-fix": "^3.1.2"
19
+ "tsc-esm-fix": "3.1.2",
20
+ "typescript": "5.9.2"
20
21
  }
21
22
  }
package/src/evm.ts CHANGED
@@ -13,7 +13,7 @@ import { baseSepolia, mainnet, sepolia } from "viem/chains";
13
13
  import Eth from "@ledgerhq/hw-app-eth/lib-es/Eth";
14
14
  import { type } from "arktype";
15
15
  import { createTransport } from "./transport";
16
- import type { LedgerEvmWallet } from "./types";
16
+ import type { LedgerEvmWallet, UserInterface } from "./types";
17
17
 
18
18
  interface NetworkConfig {
19
19
  chain: Chain;
@@ -45,6 +45,7 @@ const NETWORK_CONFIGS = new Map<string, NetworkConfig>([
45
45
  ]);
46
46
 
47
47
  export async function createLedgerEvmWallet(
48
+ ui: UserInterface,
48
49
  network: string,
49
50
  derivationPath: string,
50
51
  ): Promise<LedgerEvmWallet> {
@@ -169,12 +170,10 @@ export async function createLedgerEvmWallet(
169
170
  types,
170
171
  });
171
172
 
172
- console.log("\nEIP-712 hashes calculated:");
173
- console.log(" Domain separator:", domainSeparator);
174
- console.log(" Message hash:", messageHash);
175
- console.log(
176
- "\nPlease approve the transaction on your Ledger device...",
177
- );
173
+ ui.message("\nEIP-712 hashes calculated:");
174
+ ui.message(` Domain separator: ${domainSeparator}`);
175
+ ui.message(` Message hash: ${messageHash}`);
176
+ ui.message(`\nPlease approve the transaction on your Ledger device...`);
178
177
 
179
178
  const result = await eth.signEIP712HashedMessage(
180
179
  derivationPath,
@@ -186,7 +185,7 @@ export async function createLedgerEvmWallet(
186
185
  `0x${result.r}${result.s}${result.v.toString(16).padStart(2, "0")}` as Hex;
187
186
  return signature;
188
187
  } catch (error) {
189
- console.error("EIP-712 signing failed:", error);
188
+ ui.message(`EIP-712 signing failed: ${error}`);
190
189
  throw error;
191
190
  }
192
191
  },
package/src/index.ts CHANGED
@@ -2,3 +2,4 @@ export { createLedgerEvmWallet } from "./evm";
2
2
  export { createLedgerSolanaWallet } from "./solana";
3
3
  export { selectLedgerAccount } from "./utils";
4
4
  export type { LedgerEvmWallet, LedgerSolanaWallet } from "./types";
5
+ export * from "./interface";
@@ -0,0 +1,25 @@
1
+ import type { UserInterface } from "./types";
2
+
3
+ export type createReadlineInterfaceArgs = {
4
+ stdin: NodeJS.ReadableStream;
5
+ stdout: NodeJS.WritableStream;
6
+ };
7
+
8
+ export async function createReadlineInterface(
9
+ args: createReadlineInterfaceArgs,
10
+ ) {
11
+ const readline = await import("readline");
12
+ const rl = readline.createInterface({
13
+ input: args.stdin,
14
+ output: args.stdout,
15
+ });
16
+
17
+ return {
18
+ message: (msg: string) => void args.stdout.write(msg + "\n"),
19
+ question: async (q: string) =>
20
+ new Promise<string>((resolve) => {
21
+ rl.question(q, resolve);
22
+ }),
23
+ close: async () => rl.close(),
24
+ } satisfies UserInterface;
25
+ }
package/src/logger.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { getLogger } from "@logtape/logtape";
2
+
3
+ export const logger = getLogger(["faremeter", "wallet-ledger"]);
package/src/transport.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { logger } from "./logger";
1
2
  import type Transport from "@ledgerhq/hw-transport";
2
3
 
3
4
  const LEDGER_ERRORS: Record<string, string> = {
@@ -67,7 +68,7 @@ export async function createTransport(maxRetries = 3): Promise<Transport> {
67
68
  i < maxRetries - 1 &&
68
69
  (errorMessage.includes("USB") || errorMessage.includes("device"))
69
70
  ) {
70
- console.log(`USB connection attempt ${i + 1} failed, retrying...`);
71
+ logger.warning(`USB connection attempt ${i + 1} failed, retrying...`);
71
72
  await new Promise((resolve) => setTimeout(resolve, 1000));
72
73
  continue;
73
74
  }
package/src/types.ts CHANGED
@@ -29,3 +29,9 @@ export interface LedgerTransportWrapper {
29
29
  transport: Transport;
30
30
  close: () => Promise<void>;
31
31
  }
32
+
33
+ export interface UserInterface {
34
+ message: (msg: string) => void;
35
+ question: (prompt: string) => Promise<string>;
36
+ close: () => Promise<void>;
37
+ }
package/src/utils.ts CHANGED
@@ -2,6 +2,7 @@ import Eth from "@ledgerhq/hw-app-eth/lib-es/Eth";
2
2
  import Solana from "@ledgerhq/hw-app-solana/lib-es/Solana";
3
3
  import { PublicKey } from "@solana/web3.js";
4
4
  import { createTransport, translateLedgerError } from "./transport";
5
+ import type { UserInterface } from "./types";
5
6
 
6
7
  function evmDerivationPath(index: number) {
7
8
  return `m/44'/60'/${index}'/0/0`;
@@ -12,11 +13,12 @@ function solanaDerivationPath(index: number) {
12
13
  }
13
14
 
14
15
  export async function selectLedgerAccount(
16
+ ui: UserInterface,
15
17
  type: "evm" | "solana",
16
18
  numAccounts = 5,
17
19
  ): Promise<{ path: string; address: string } | null> {
18
20
  const isEvm = type === "evm";
19
- console.log(
21
+ ui.message(
20
22
  `\nScanning first ${numAccounts} ${isEvm ? "Ethereum" : "Solana"} accounts...`,
21
23
  );
22
24
 
@@ -39,7 +41,7 @@ export async function selectLedgerAccount(
39
41
  ? address
40
42
  : `0x${address}`;
41
43
  accounts.push({ path, address: normalizedAddress });
42
- console.log(`${i + 1}. ${normalizedAddress}`);
44
+ ui.message(`${i + 1}. ${normalizedAddress}`);
43
45
  }
44
46
  } else {
45
47
  const solana = new Solana(transport);
@@ -54,28 +56,19 @@ export async function selectLedgerAccount(
54
56
  const publicKey = new PublicKey(result.address);
55
57
  const address = publicKey.toBase58();
56
58
  accounts.push({ path, address });
57
- console.log(`${i + 1}. ${address}`);
59
+ ui.message(`${i + 1}. ${address}`);
58
60
  }
59
61
  }
60
62
  } finally {
61
63
  await transport.close();
62
64
  }
63
65
 
64
- const readline = await import("readline");
65
- const rl = readline.createInterface({
66
- input: process.stdin,
67
- output: process.stdout,
68
- });
69
-
70
- const selection = await new Promise<string>((resolve) => {
71
- rl.question(`\nSelect account (1-${numAccounts}): `, resolve);
72
- });
73
- rl.close();
66
+ const selection = await ui.question(`\nSelect account (1-${numAccounts}): `);
74
67
 
75
68
  const index = parseInt(selection) - 1;
76
69
 
77
70
  if (index < 0 || index >= accounts.length) {
78
- console.log("Invalid selection");
71
+ ui.message("Invalid selection");
79
72
  return null;
80
73
  }
81
74