@hardkas/accounts 0.12.0-rc.24 → 0.12.0-rc.26

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.
@@ -2,7 +2,7 @@ import {
2
2
  LazyAccountAuthorizer,
3
3
  PrivateKeyAuthorizer,
4
4
  StaticSignatureScriptAuthorizer
5
- } from "./chunk-PKDTLCCQ.js";
5
+ } from "./chunk-YBCXJBA5.js";
6
6
  export {
7
7
  LazyAccountAuthorizer,
8
8
  PrivateKeyAuthorizer,
@@ -6,20 +6,288 @@ import {
6
6
  } from "./chunk-BNF566PS.js";
7
7
  import {
8
8
  resolveHardkasAccount
9
- } from "./chunk-2UQTGGML.js";
10
- import {
11
- KeystoreManager
12
- } from "./chunk-YLG2NIAU.js";
9
+ } from "./chunk-IRNHRG4N.js";
13
10
 
14
- // src/dev-accounts.ts
11
+ // src/kaspa-wasm-signer.ts
12
+ import { recomputeDeclaredContentHash } from "@hardkas/artifacts";
13
+ import { getNetworkPrefix as getNetworkPrefix2 } from "@hardkas/core";
14
+
15
+ // src/keystore.ts
15
16
  import fs from "fs";
16
17
  import path from "path";
17
18
  import crypto from "crypto";
18
- import { deterministicCompare, getNetworkPrefix as getNetworkPrefix2 } from "@hardkas/core";
19
+ import { argon2id } from "hash-wasm";
20
+ import { writeFileAtomic, stripBom } from "@hardkas/core";
21
+ var KeystoreManager = class {
22
+ /**
23
+ * Keystore container format version. Separate from ARTIFACT_VERSION.
24
+ * This versions the encrypted keystore envelope, not HardKAS artifacts.
25
+ */
26
+ static KEYSTORE_FORMAT_VERSION = "2.0.0";
27
+ static KEYSTORE_FORMAT_TYPE = "hardkas.encryptedKeystore.v2";
28
+ /**
29
+ * Creates an encrypted keystore from a payload and password.
30
+ */
31
+ static async createEncryptedKeystore(payload, password, options) {
32
+ if (!password) throw new Error("Password cannot be empty.");
33
+ if (password.length < 8)
34
+ throw new Error("Password must be at least 8 characters long.");
35
+ const salt = crypto.randomBytes(16);
36
+ const nonce = crypto.randomBytes(12);
37
+ const iterations = options.iterations || 3;
38
+ const memory = options.memory || 65536;
39
+ const parallelism = options.parallelism || 1;
40
+ const derivedKeyHex = await argon2id({
41
+ password,
42
+ salt,
43
+ parallelism,
44
+ iterations,
45
+ memorySize: memory,
46
+ hashLength: 32,
47
+ // 256 bits for AES-256
48
+ outputType: "hex"
49
+ });
50
+ const derivedKey = Buffer.from(derivedKeyHex, "hex");
51
+ const cipher = crypto.createCipheriv("aes-256-gcm", derivedKey, nonce);
52
+ const encryptedPayload = Buffer.concat([
53
+ cipher.update(JSON.stringify(payload), "utf8"),
54
+ cipher.final()
55
+ ]);
56
+ const tag = cipher.getAuthTag();
57
+ derivedKey.fill(0);
58
+ return {
59
+ version: this.KEYSTORE_FORMAT_VERSION,
60
+ type: this.KEYSTORE_FORMAT_TYPE,
61
+ kdf: {
62
+ algorithm: "argon2id",
63
+ memory,
64
+ iterations,
65
+ parallelism,
66
+ salt: salt.toString("base64")
67
+ },
68
+ cipher: {
69
+ algorithm: "aes-256-gcm",
70
+ nonce: nonce.toString("base64"),
71
+ tag: tag.toString("base64")
72
+ },
73
+ encryptedPayload: encryptedPayload.toString("base64"),
74
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
75
+ metadata: {
76
+ label: options.label,
77
+ network: options.network,
78
+ address: payload.address
79
+ }
80
+ };
81
+ }
82
+ /**
83
+ * Decrypts an encrypted keystore using a password.
84
+ */
85
+ static async decryptEncryptedKeystore(keystore, password) {
86
+ if (keystore.version !== this.KEYSTORE_FORMAT_VERSION) {
87
+ return {
88
+ success: false,
89
+ error: `Unsupported keystore version: ${keystore.version}`
90
+ };
91
+ }
92
+ try {
93
+ const salt = Buffer.from(keystore.kdf.salt, "base64");
94
+ const nonce = Buffer.from(keystore.cipher.nonce, "base64");
95
+ const tag = Buffer.from(keystore.cipher.tag, "base64");
96
+ const encryptedData = Buffer.from(keystore.encryptedPayload, "base64");
97
+ const derivedKeyHex = await argon2id({
98
+ password,
99
+ salt,
100
+ parallelism: keystore.kdf.parallelism,
101
+ iterations: keystore.kdf.iterations,
102
+ memorySize: keystore.kdf.memory,
103
+ hashLength: 32,
104
+ outputType: "hex"
105
+ });
106
+ const derivedKey = Buffer.from(derivedKeyHex, "hex");
107
+ const decipher = crypto.createDecipheriv("aes-256-gcm", derivedKey, nonce);
108
+ decipher.setAuthTag(tag);
109
+ const decrypted = Buffer.concat([decipher.update(encryptedData), decipher.final()]);
110
+ derivedKey.fill(0);
111
+ const payload = JSON.parse(decrypted.toString("utf8"));
112
+ return { success: true, payload };
113
+ } catch (e) {
114
+ return { success: false, error: "Invalid password or corrupted keystore." };
115
+ }
116
+ }
117
+ /**
118
+ * Verifies if the password is correct for the keystore.
119
+ */
120
+ static async verifyKeystorePassword(keystore, password) {
121
+ const result = await this.decryptEncryptedKeystore(keystore, password);
122
+ return result.success;
123
+ }
124
+ /**
125
+ * Changes the password of an encrypted keystore.
126
+ */
127
+ static async changeKeystorePassword(keystore, oldPassword, newPassword) {
128
+ const unlock = await this.decryptEncryptedKeystore(keystore, oldPassword);
129
+ if (!unlock.success || !unlock.payload) {
130
+ throw new Error("Invalid current password.");
131
+ }
132
+ return this.createEncryptedKeystore(unlock.payload, newPassword, {
133
+ label: keystore.metadata.label,
134
+ network: keystore.metadata.network,
135
+ iterations: keystore.kdf.iterations,
136
+ memory: keystore.kdf.memory,
137
+ parallelism: keystore.kdf.parallelism
138
+ });
139
+ }
140
+ /**
141
+ * Loads an encrypted keystore from the filesystem.
142
+ */
143
+ static async loadEncryptedKeystore(filePath) {
144
+ try {
145
+ const data = await fs.promises.readFile(filePath, "utf-8");
146
+ const keystore = JSON.parse(stripBom(data));
147
+ if (keystore.type !== this.KEYSTORE_FORMAT_TYPE) {
148
+ throw new Error(`Invalid keystore type: ${keystore.type}`);
149
+ }
150
+ return keystore;
151
+ } catch (e) {
152
+ throw new Error(
153
+ `Failed to load keystore at ${filePath}: ${e instanceof Error ? e instanceof Error ? e instanceof Error ? e.message : String(e) : String(e) : String(e)}`
154
+ );
155
+ }
156
+ }
157
+ /**
158
+ * Saves an encrypted keystore to the filesystem.
159
+ */
160
+ static async saveEncryptedKeystore(filePath, keystore) {
161
+ try {
162
+ const dir = path.dirname(filePath);
163
+ if (!fs.existsSync(dir)) {
164
+ await fs.promises.mkdir(dir, { recursive: true });
165
+ }
166
+ await writeFileAtomic(filePath, JSON.stringify(keystore, null, 2), {
167
+ encoding: "utf-8",
168
+ mode: 384
169
+ });
170
+ } catch (e) {
171
+ throw new Error(
172
+ `Failed to save keystore at ${filePath}: ${e instanceof Error ? e instanceof Error ? e instanceof Error ? e.message : String(e) : String(e) : String(e)}`
173
+ );
174
+ }
175
+ }
176
+ };
19
177
 
20
- // src/kaspa-wasm-signer.ts
21
- import { recomputeDeclaredContentHash } from "@hardkas/artifacts";
22
- import { getNetworkPrefix } from "@hardkas/core";
178
+ // src/dev-accounts.ts
179
+ import fs2 from "fs";
180
+ import path2 from "path";
181
+ import crypto2 from "crypto";
182
+ import { deterministicCompare, getNetworkPrefix, stripBom as stripBom2 } from "@hardkas/core";
183
+ var DEV_ACCOUNTS_PASSWORD = "hardkas-local-dev";
184
+ var SIMNET_DETERMINISTIC_SEED = "hardkas-deterministic-simnet-seed-v1";
185
+ async function ensureDevAccounts(workspaceDir) {
186
+ const devAccountsDir = path2.join(workspaceDir, ".hardkas", "dev-accounts");
187
+ if (!fs2.existsSync(devAccountsDir)) {
188
+ await fs2.promises.mkdir(devAccountsDir, { recursive: true });
189
+ }
190
+ await getOrCreateDevAccount(workspaceDir, 0, "alice");
191
+ await getOrCreateDevAccount(workspaceDir, 1, "bob");
192
+ await getOrCreateDevAccount(workspaceDir, 2, "carol");
193
+ await getOrCreateDevAccount(workspaceDir, 3, "dave");
194
+ await getOrCreateDevAccount(workspaceDir, 4, "erin");
195
+ }
196
+ async function getOrCreateDevAccount(workspaceDir, index, alias) {
197
+ const devAccountsDir = path2.join(workspaceDir, ".hardkas", "dev-accounts");
198
+ const filePath = path2.join(devAccountsDir, `${alias}.json`);
199
+ if (fs2.existsSync(filePath)) {
200
+ const keystore2 = await KeystoreManager.loadEncryptedKeystore(filePath);
201
+ const unlock = await KeystoreManager.decryptEncryptedKeystore(
202
+ keystore2,
203
+ DEV_ACCOUNTS_PASSWORD
204
+ );
205
+ if (!unlock.success || !unlock.payload) {
206
+ throw new Error(
207
+ `Failed to decrypt dev account ${alias}. Expected password: ${DEV_ACCOUNTS_PASSWORD}`
208
+ );
209
+ }
210
+ return {
211
+ address: unlock.payload.address,
212
+ privateKey: unlock.payload.privateKey,
213
+ publicKey: unlock.payload.publicKey
214
+ };
215
+ }
216
+ const seedString = `${SIMNET_DETERMINISTIC_SEED}-${index}`;
217
+ const privateKeyHex = crypto2.createHash("sha256").update(seedString).digest("hex");
218
+ const network = "simnet";
219
+ const { loadKaspaWasm: loadKaspaWasm2 } = await import("./signer-backend-LHWY7ULI.js");
220
+ const kaspaWasm = await loadKaspaWasm2();
221
+ const kp = new kaspaWasm.PrivateKey(privateKeyHex).toKeypair();
222
+ const address = kp.toAddress(getNetworkPrefix(network)).toString();
223
+ const publicKey = kp.publicKey;
224
+ const privateKey = privateKeyHex;
225
+ const accountData = {
226
+ address,
227
+ privateKey,
228
+ publicKey
229
+ };
230
+ if (!fs2.existsSync(devAccountsDir)) {
231
+ await fs2.promises.mkdir(devAccountsDir, { recursive: true });
232
+ }
233
+ const payload = {
234
+ address: accountData.address,
235
+ privateKey: accountData.privateKey,
236
+ network: "simnet"
237
+ };
238
+ if (accountData.publicKey) {
239
+ payload.publicKey = accountData.publicKey;
240
+ }
241
+ const keystore = await KeystoreManager.createEncryptedKeystore(
242
+ payload,
243
+ DEV_ACCOUNTS_PASSWORD,
244
+ {
245
+ label: alias,
246
+ network: "simnet"
247
+ }
248
+ );
249
+ await KeystoreManager.saveEncryptedKeystore(filePath, keystore);
250
+ return accountData;
251
+ }
252
+ function listDevAccountsSync(workspaceDir) {
253
+ const devAccountsDir = path2.join(workspaceDir, ".hardkas", "dev-accounts");
254
+ if (!fs2.existsSync(devAccountsDir)) {
255
+ return [];
256
+ }
257
+ const accounts = [];
258
+ const files = fs2.readdirSync(devAccountsDir);
259
+ for (const file of files) {
260
+ if (file.endsWith(".json")) {
261
+ const name = path2.basename(file, ".json");
262
+ try {
263
+ const data = fs2.readFileSync(path2.join(devAccountsDir, file), "utf-8");
264
+ const keystore = JSON.parse(stripBom2(data));
265
+ if (keystore.type === "hardkas.encryptedKeystore.v2") {
266
+ accounts.push({
267
+ name,
268
+ address: keystore.metadata?.address || ""
269
+ });
270
+ }
271
+ } catch (e) {
272
+ }
273
+ }
274
+ }
275
+ accounts.sort((a, b) => deterministicCompare(a.name, b.name));
276
+ return accounts;
277
+ }
278
+ async function createDevSigner(workspaceDir, accountNameOrAddress) {
279
+ const account = resolveHardkasAccount({
280
+ nameOrAddress: accountNameOrAddress,
281
+ config: { cwd: workspaceDir }
282
+ });
283
+ if (account.kind !== "kaspa") {
284
+ throw new Error(`Account '${accountNameOrAddress}' is not a private key account, cannot create local dev signer.`);
285
+ }
286
+ return new KaspaWasmPrivateKeySigner({
287
+ account,
288
+ allowMainnet: false
289
+ });
290
+ }
23
291
 
24
292
  // src/wasm-transaction.ts
25
293
  function assertValueConservation(input) {
@@ -96,6 +364,20 @@ function planOutputsWithChange(plan) {
96
364
  }
97
365
 
98
366
  // src/kaspa-wasm-signer.ts
367
+ var keystoreError = (code, message) => Object.assign(new Error(`${code}: ${message}`), { code });
368
+ async function unlockAccountKeystore(account, password) {
369
+ const devAccount = account.keystoreKind === "dev-account";
370
+ const secret = devAccount ? DEV_ACCOUNTS_PASSWORD : password;
371
+ if (!secret) {
372
+ throw keystoreError("KEYSTORE_PASSWORD_REQUIRED", `account '${account.name}' is an encrypted keystore and no password was given to open it.`);
373
+ }
374
+ const keystore = await KeystoreManager.loadEncryptedKeystore(account.keystorePath);
375
+ const unlock = await KeystoreManager.decryptEncryptedKeystore(keystore, secret);
376
+ if (!unlock.success || !unlock.payload?.privateKey) {
377
+ throw devAccount ? keystoreError("DEV_ACCOUNT_KEY_UNAVAILABLE", `the development keystore of account '${account.name}' does not open.`) : keystoreError("KEYSTORE_PASSWORD_INVALID", `the password does not open the keystore of account '${account.name}' (wrong password, or a damaged keystore).`);
378
+ }
379
+ return unlock.payload.privateKey;
380
+ }
99
381
  var KaspaWasmPrivateKeySigner = class {
100
382
  constructor(options) {
101
383
  this.options = options;
@@ -131,16 +413,10 @@ var KaspaWasmPrivateKeySigner = class {
131
413
  pkValue = account.privateKey;
132
414
  }
133
415
  if (!pkValue && account.keystorePath) {
134
- try {
135
- const KeystoreManager2 = (await import("./keystore-CMWEKGBF.js")).KeystoreManager;
136
- const DEV_ACCOUNTS_PASSWORD2 = (await import("./dev-accounts-JTJKQAPV.js")).DEV_ACCOUNTS_PASSWORD;
137
- const keystore = await KeystoreManager2.loadEncryptedKeystore(account.keystorePath);
138
- const unlock = await KeystoreManager2.decryptEncryptedKeystore(keystore, DEV_ACCOUNTS_PASSWORD2);
139
- if (unlock.success && unlock.payload) {
140
- pkValue = unlock.payload.privateKey;
141
- }
142
- } catch (e) {
143
- }
416
+ pkValue = await unlockAccountKeystore(
417
+ { name: account.name, keystorePath: account.keystorePath, keystoreKind: account.keystoreKind },
418
+ this.options.keystorePassword
419
+ );
144
420
  }
145
421
  if (!pkValue) {
146
422
  const err = new Error(`DEV_ACCOUNT_KEY_UNAVAILABLE: Missing required private key for account '${account.name}'.`);
@@ -152,8 +428,8 @@ var KaspaWasmPrivateKeySigner = class {
152
428
  err.code = "INVALID_PRIVATE_KEY_MATERIAL";
153
429
  throw err;
154
430
  }
155
- const expectedAddress = new sdk.PrivateKey(pkValue).toKeypair().toAddress(getNetworkPrefix(plan.networkId || "simnet")).toString();
156
- const { PrivateKeyAuthorizer } = await import("./authorizers-YESBCCTJ.js");
431
+ const expectedAddress = new sdk.PrivateKey(pkValue).toKeypair().toAddress(getNetworkPrefix2(plan.networkId || "simnet")).toString();
432
+ const { PrivateKeyAuthorizer } = await import("./authorizers-OAGU7NYR.js");
157
433
  const sourceInputs = plan.inputs || plan.selectedUtxos || [];
158
434
  for (let i = 0; i < numInputs; i++) {
159
435
  if (!authorizers[i]) {
@@ -332,127 +608,19 @@ function assertSigningNetworkAllowed(input) {
332
608
  }
333
609
  }
334
610
 
335
- // src/dev-accounts.ts
336
- var DEV_ACCOUNTS_PASSWORD = "hardkas-local-dev";
337
- var SIMNET_DETERMINISTIC_SEED = "hardkas-deterministic-simnet-seed-v1";
338
- async function ensureDevAccounts(workspaceDir) {
339
- const devAccountsDir = path.join(workspaceDir, ".hardkas", "dev-accounts");
340
- if (!fs.existsSync(devAccountsDir)) {
341
- await fs.promises.mkdir(devAccountsDir, { recursive: true });
342
- }
343
- await getOrCreateDevAccount(workspaceDir, 0, "alice");
344
- await getOrCreateDevAccount(workspaceDir, 1, "bob");
345
- await getOrCreateDevAccount(workspaceDir, 2, "carol");
346
- await getOrCreateDevAccount(workspaceDir, 3, "dave");
347
- await getOrCreateDevAccount(workspaceDir, 4, "erin");
348
- }
349
- async function getOrCreateDevAccount(workspaceDir, index, alias) {
350
- const devAccountsDir = path.join(workspaceDir, ".hardkas", "dev-accounts");
351
- const filePath = path.join(devAccountsDir, `${alias}.json`);
352
- if (fs.existsSync(filePath)) {
353
- const keystore2 = await KeystoreManager.loadEncryptedKeystore(filePath);
354
- const unlock = await KeystoreManager.decryptEncryptedKeystore(
355
- keystore2,
356
- DEV_ACCOUNTS_PASSWORD
357
- );
358
- if (!unlock.success || !unlock.payload) {
359
- throw new Error(
360
- `Failed to decrypt dev account ${alias}. Expected password: ${DEV_ACCOUNTS_PASSWORD}`
361
- );
362
- }
363
- return {
364
- address: unlock.payload.address,
365
- privateKey: unlock.payload.privateKey,
366
- publicKey: unlock.payload.publicKey
367
- };
368
- }
369
- const seedString = `${SIMNET_DETERMINISTIC_SEED}-${index}`;
370
- const privateKeyHex = crypto.createHash("sha256").update(seedString).digest("hex");
371
- const network = "simnet";
372
- const { loadKaspaWasm: loadKaspaWasm2 } = await import("./signer-backend-LHWY7ULI.js");
373
- const kaspaWasm = await loadKaspaWasm2();
374
- const kp = new kaspaWasm.PrivateKey(privateKeyHex).toKeypair();
375
- const address = kp.toAddress(getNetworkPrefix2(network)).toString();
376
- const publicKey = kp.publicKey;
377
- const privateKey = privateKeyHex;
378
- const accountData = {
379
- address,
380
- privateKey,
381
- publicKey
382
- };
383
- if (!fs.existsSync(devAccountsDir)) {
384
- await fs.promises.mkdir(devAccountsDir, { recursive: true });
385
- }
386
- const payload = {
387
- address: accountData.address,
388
- privateKey: accountData.privateKey,
389
- network: "simnet"
390
- };
391
- if (accountData.publicKey) {
392
- payload.publicKey = accountData.publicKey;
393
- }
394
- const keystore = await KeystoreManager.createEncryptedKeystore(
395
- payload,
396
- DEV_ACCOUNTS_PASSWORD,
397
- {
398
- label: alias,
399
- network: "simnet"
400
- }
401
- );
402
- await KeystoreManager.saveEncryptedKeystore(filePath, keystore);
403
- return accountData;
404
- }
405
- function listDevAccountsSync(workspaceDir) {
406
- const devAccountsDir = path.join(workspaceDir, ".hardkas", "dev-accounts");
407
- if (!fs.existsSync(devAccountsDir)) {
408
- return [];
409
- }
410
- const accounts = [];
411
- const files = fs.readdirSync(devAccountsDir);
412
- for (const file of files) {
413
- if (file.endsWith(".json")) {
414
- const name = path.basename(file, ".json");
415
- try {
416
- const data = fs.readFileSync(path.join(devAccountsDir, file), "utf-8");
417
- const keystore = JSON.parse(data);
418
- if (keystore.type === "hardkas.encryptedKeystore.v2") {
419
- accounts.push({
420
- name,
421
- address: keystore.metadata?.address || ""
422
- });
423
- }
424
- } catch (e) {
425
- }
426
- }
427
- }
428
- accounts.sort((a, b) => deterministicCompare(a.name, b.name));
429
- return accounts;
430
- }
431
- async function createDevSigner(workspaceDir, accountNameOrAddress) {
432
- const account = resolveHardkasAccount({
433
- nameOrAddress: accountNameOrAddress,
434
- config: { cwd: workspaceDir }
435
- });
436
- if (account.kind !== "kaspa") {
437
- throw new Error(`Account '${accountNameOrAddress}' is not a private key account, cannot create local dev signer.`);
438
- }
439
- return new KaspaWasmPrivateKeySigner({
440
- account,
441
- allowMainnet: false
442
- });
443
- }
444
-
445
611
  export {
446
- assertValueConservation,
447
- createBalancedTransaction,
448
- createScriptTransaction,
449
- toWasmScriptPublicKey,
450
- planOutputsWithChange,
612
+ KeystoreManager,
451
613
  DEV_ACCOUNTS_PASSWORD,
452
614
  ensureDevAccounts,
453
615
  getOrCreateDevAccount,
454
616
  listDevAccountsSync,
455
617
  createDevSigner,
618
+ assertValueConservation,
619
+ createBalancedTransaction,
620
+ createScriptTransaction,
621
+ toWasmScriptPublicKey,
622
+ planOutputsWithChange,
623
+ unlockAccountKeystore,
456
624
  KaspaWasmPrivateKeySigner,
457
625
  assertSigningNetworkAllowed
458
626
  };
@@ -2,13 +2,13 @@
2
2
  import fs2 from "fs";
3
3
  import path2 from "path";
4
4
  import { createDeterministicAccounts } from "@hardkas/localnet";
5
- import { CrossWorldAccountCollisionError, AccountNetworkMismatchError } from "@hardkas/core";
5
+ import { CrossWorldAccountCollisionError, AccountNetworkMismatchError, stripBom as stripBom2 } from "@hardkas/core";
6
6
 
7
7
  // src/real-accounts.ts
8
8
  import fs from "fs";
9
9
  import path from "path";
10
10
  import util from "util";
11
- import { writeFileAtomicSync } from "@hardkas/core";
11
+ import { writeFileAtomicSync, stripBom } from "@hardkas/core";
12
12
  import {
13
13
  HARDKAS_VERSION,
14
14
  ARTIFACT_SCHEMAS,
@@ -64,7 +64,7 @@ function loadRealAccountStoreSync(options) {
64
64
  }
65
65
  try {
66
66
  const data = fs.readFileSync(filePath, "utf-8");
67
- const store = JSON.parse(data);
67
+ const store = JSON.parse(stripBom(data));
68
68
  for (const a of store.accounts) {
69
69
  if ("privateKey" in a && a.privateKey !== void 0) {
70
70
  if (a.privateKey === null || a.privateKey === "" || a.privateKey === "[object Object]" || typeof a.privateKey === "object" || typeof a.privateKey === "string" && a.privateKey.includes("__wbg_ptr") || typeof a.privateKey === "object" && "__wbg_ptr" in a.privateKey) {
@@ -326,7 +326,7 @@ function listHardkasAccounts(config, executionTarget) {
326
326
  try {
327
327
  const name = path2.basename(file, ".json");
328
328
  const data = fs2.readFileSync(path2.join(devAccountsDir, file), "utf-8");
329
- const keystore = JSON.parse(data);
329
+ const keystore = JSON.parse(stripBom2(data));
330
330
  if (keystore.type === "hardkas.encryptedKeystore.v2") {
331
331
  if (!keystore.metadata?.network) {
332
332
  throw new AccountNetworkMismatchError({ expected: "known network", actual: "undefined", detail: `at ${path2.join(devAccountsDir, file)}` });
@@ -337,7 +337,8 @@ function listHardkasAccounts(config, executionTarget) {
337
337
  kind: "synthetic",
338
338
  executionMode: "simulator",
339
339
  address: `kaspa:sim_${name}`,
340
- keystorePath: path2.join(devAccountsDir, file)
340
+ keystorePath: path2.join(devAccountsDir, file),
341
+ keystoreKind: "dev-account"
341
342
  });
342
343
  } else {
343
344
  accounts.set(name, {
@@ -345,7 +346,8 @@ function listHardkasAccounts(config, executionTarget) {
345
346
  kind: "kaspa",
346
347
  network: keystore.metadata.network,
347
348
  address: keystore.payload?.address || keystore.metadata?.address,
348
- keystorePath: path2.join(devAccountsDir, file)
349
+ keystorePath: path2.join(devAccountsDir, file),
350
+ keystoreKind: "dev-account"
349
351
  });
350
352
  }
351
353
  }
@@ -359,7 +361,7 @@ function listHardkasAccounts(config, executionTarget) {
359
361
  if (fs2.existsSync(keystoreJsonPath)) {
360
362
  try {
361
363
  const data = fs2.readFileSync(keystoreJsonPath, "utf-8");
362
- const ks = JSON.parse(data);
364
+ const ks = JSON.parse(stripBom2(data));
363
365
  for (const [name, acc] of Object.entries(ks)) {
364
366
  if (acc.type === "simulated") {
365
367
  if (targetMode === "simulator") {
@@ -400,7 +402,7 @@ function listHardkasAccounts(config, executionTarget) {
400
402
  });
401
403
  }
402
404
  }
403
- const keystoreDir = path2.join(process.cwd(), ".hardkas", "keystore");
405
+ const keystoreDir = path2.join(workspaceRoot, ".hardkas", "keystore");
404
406
  if (fs2.existsSync(keystoreDir)) {
405
407
  const files = fs2.readdirSync(keystoreDir);
406
408
  for (const file of files) {
@@ -408,7 +410,7 @@ function listHardkasAccounts(config, executionTarget) {
408
410
  try {
409
411
  const name = path2.basename(file, ".json");
410
412
  const data = fs2.readFileSync(path2.join(keystoreDir, file), "utf-8");
411
- const keystore = JSON.parse(data);
413
+ const keystore = JSON.parse(stripBom2(data));
412
414
  if (keystore.type === "hardkas.encryptedKeystore.v2") {
413
415
  if (!keystore.metadata?.network) {
414
416
  throw new AccountNetworkMismatchError({ expected: "known network", actual: "undefined", detail: `at ${path2.join(keystoreDir, file)}` });
@@ -62,7 +62,7 @@ var LazyAccountAuthorizer = class {
62
62
  accountName;
63
63
  workspaceRoot;
64
64
  async authorize(context) {
65
- const { resolveHardkasAccount } = await import("./resolve-FO4P46YC.js");
65
+ const { resolveHardkasAccount } = await import("./resolve-FPK6KS5J.js");
66
66
  const account = await resolveHardkasAccount({
67
67
  nameOrAddress: this.accountName,
68
68
  config: { cwd: this.workspaceRoot }
@@ -72,16 +72,11 @@ var LazyAccountAuthorizer = class {
72
72
  pkValue = account.privateKey;
73
73
  }
74
74
  if (!pkValue && account.keystorePath) {
75
- try {
76
- const { KeystoreManager } = await import("./keystore-CMWEKGBF.js");
77
- const { DEV_ACCOUNTS_PASSWORD } = await import("./dev-accounts-JTJKQAPV.js");
78
- const keystore = await KeystoreManager.loadEncryptedKeystore(account.keystorePath);
79
- const unlock = await KeystoreManager.decryptEncryptedKeystore(keystore, DEV_ACCOUNTS_PASSWORD);
80
- if (unlock.success && unlock.payload) {
81
- pkValue = unlock.payload.privateKey;
82
- }
83
- } catch (e) {
84
- }
75
+ const { unlockAccountKeystore } = await import("./kaspa-wasm-signer-RBV2EPB7.js");
76
+ pkValue = await unlockAccountKeystore(
77
+ { name: this.accountName, keystorePath: account.keystorePath, keystoreKind: account.keystoreKind },
78
+ void 0
79
+ );
85
80
  }
86
81
  if (!pkValue) {
87
82
  throw new Error(`DEV_ACCOUNT_KEY_UNAVAILABLE: Missing required private key for account '${this.accountName}'.`);
package/dist/index.d.ts CHANGED
@@ -101,6 +101,12 @@ interface HardkasKaspaAccount extends HardkasBaseAccount {
101
101
  privateKeyEnv?: string;
102
102
  privateKey?: string;
103
103
  keystorePath?: string;
104
+ /**
105
+ * Set by the resolver for the workspace's development accounts (`.hardkas/dev-accounts/`), whose
106
+ * keystores use the published development password. Any other keystore opens only with its owner's
107
+ * password, given explicitly.
108
+ */
109
+ keystoreKind?: "dev-account";
104
110
  address: string;
105
111
  }
106
112
  interface HardkasExternalWalletAccount extends HardkasBaseAccount {
@@ -198,6 +204,8 @@ declare function signTxPlanArtifact(input: {
198
204
  authorizers?: Readonly<Record<number, TxInputAuthorizer>>;
199
205
  config?: HardkasConfig;
200
206
  allowMainnet?: boolean;
207
+ /** The password of the account's keystore, in memory only: never stored, logged or echoed. */
208
+ keystorePassword?: string;
201
209
  }): Promise<SignedTxArtifact>;
202
210
 
203
211
  interface KaspaSigningBackendStatus {
@@ -607,7 +615,20 @@ interface KaspaWasmSignerOptions {
607
615
  account?: HardkasKaspaAccount;
608
616
  allowMainnet?: boolean;
609
617
  wasmConfig?: WasmProviderConfig;
618
+ /** The password of the account's keystore, in memory only: never stored, logged or echoed. */
619
+ keystorePassword?: string;
610
620
  }
621
+ /**
622
+ * Opens the keystore of `account` and returns its private key. A development account (marked by the
623
+ * resolver for `.hardkas/dev-accounts/`) opens with the published development password; any other
624
+ * keystore only with `password`, its owner's, given explicitly. Nothing is tried silently: a missing
625
+ * password is KEYSTORE_PASSWORD_REQUIRED, one that does not open the keystore KEYSTORE_PASSWORD_INVALID.
626
+ */
627
+ declare function unlockAccountKeystore(account: {
628
+ name: string;
629
+ keystorePath: string;
630
+ keystoreKind?: "dev-account" | undefined;
631
+ }, password: string | undefined): Promise<string>;
611
632
  /**
612
633
  * Real Kaspa signer using the official WASM SDK (the pinned managed toolchain).
613
634
  */
@@ -925,4 +946,4 @@ declare class WalletStateStoreJson {
925
946
  nextChangeIndex(walletId: string): number;
926
947
  }
927
948
 
928
- export { AddressManager, type BalancedOutput, type ChainType, type CovenantFundingInput, type CovenantGenesisRequest, type CovenantTransactionResult, type CovenantTransitionRequest, type CovenantUtxo, type CreateKaspaWalletOptions, DEV_ACCOUNTS_PASSWORD, type DeriveRequest, type DerivedAddress, type EncryptedKeystoreV2, type EvmExportResult, type GeneratedKaspaDevAccount, type HardkasAccount, type HardkasAccountKind, type HardkasBaseAccount, type HardkasEvmPrivateKeyAccount, type HardkasExternalWalletAccount, type HardkasKaspaAccount, type HardkasSigner, type HardkasSignerKind, type HardkasSyntheticAccount, type HardkasTxPlanSigner, type HelperDeriveRequest, type InputAuthorization, type KaspaKeyGenerator, KaspaSdkKeyGenerator, type KaspaSdkKeyGeneratorOptions, KaspaSdkRealTxSigner, type KaspaSdkRealTxSignerOptions, type KaspaSigningBackendStatus, KaspaWasmPrivateKeySigner, type KaspaWasmSignerOptions, type KeystoreCipherParams, type KeystoreKdfParams, KeystoreManager, type KeystorePayload, type KeystoreUnlockResult, LazyAccountAuthorizer, type NetworkType, type PathRequest, PrivateKeyAuthorizer, type RealAccountStore, type RealDevAccount, type RealTxSigner, type RealTxSigningInput, type RealTxSigningResult, SILVER_SPEND_DRAFT_SCHEMA, type ScriptFundingRequest, type ScriptFundingResult, type ScriptOutput, type SignTxPlanInput, type SignTxPlanResult, type SilverContractUtxo, type SilverDraftArg, type SilverSignatureArg, type SilverSignerSlot, type SilverSpendArg, type SilverSpendDraft, type SilverSpendDraftRequest, type SilverSpendResult, type SilverSweepRequest, SimulatedSigner, StaticSignatureScriptAuthorizer, type TxInputAuthorizationContext, type TxInputAuthorizer, UnsupportedKaspaKeyGenerator, UnsupportedRealKaspaSigner, UnsupportedRealTxSigner, type WalletArtifact, type WalletClaims, type WalletCreateRequest, type WalletImportRequest, WalletManager, WalletManagerImpl, type WalletMetadata, type WalletState, WalletStateStoreJson, type WalletStateStoreOptions, type WasmInputSigner, type WasmProviderConfig, type WasmUtxoEntrySource, type WasmUtxoInput, appendToKeystoreJson, assertAccountCompatible, assertSigningNetworkAllowed, assertValueConservation, attachInspectRedactor, buildCovenantGenesis, buildCovenantTransition, buildScriptFunding, buildSilverSweep, createBalancedTransaction, createDevSigner, createEmptyRealAccountStore, createLocalKaspaWallet, createScriptTransaction, describeAccount, detectCapabilities, ensureDevAccounts, finalizeSilverSpend, getDefaultRealAccountsPath, getKaspaSigningBackendStatus, getOrCreateDevAccount, getRealDevAccount, getRequiredEnv, importRealDevAccount, listDevAccountsSync, listHardkasAccounts, listRealDevAccounts, loadKaspaWasm, loadKaspaWasmSync, loadOrCreateRealAccountStore, loadRealAccountStore, loadRealAccountStoreSync, planOutputsWithChange, prepareEvmAccountExport, prepareSilverSpend, redactAccountForLog, removeRealDevAccount, resolveHardkasAccount, resolveHardkasAccountAddress, resolveRealAccountOrAddress, saveRealAccountStore, signSilverSpend, signTxPlanArtifact, toWasmScriptPublicKey, validateAccountName, validateAddressNetwork, validateAddressPrefix, withKeystoreLock };
949
+ export { AddressManager, type BalancedOutput, type ChainType, type CovenantFundingInput, type CovenantGenesisRequest, type CovenantTransactionResult, type CovenantTransitionRequest, type CovenantUtxo, type CreateKaspaWalletOptions, DEV_ACCOUNTS_PASSWORD, type DeriveRequest, type DerivedAddress, type EncryptedKeystoreV2, type EvmExportResult, type GeneratedKaspaDevAccount, type HardkasAccount, type HardkasAccountKind, type HardkasBaseAccount, type HardkasEvmPrivateKeyAccount, type HardkasExternalWalletAccount, type HardkasKaspaAccount, type HardkasSigner, type HardkasSignerKind, type HardkasSyntheticAccount, type HardkasTxPlanSigner, type HelperDeriveRequest, type InputAuthorization, type KaspaKeyGenerator, KaspaSdkKeyGenerator, type KaspaSdkKeyGeneratorOptions, KaspaSdkRealTxSigner, type KaspaSdkRealTxSignerOptions, type KaspaSigningBackendStatus, KaspaWasmPrivateKeySigner, type KaspaWasmSignerOptions, type KeystoreCipherParams, type KeystoreKdfParams, KeystoreManager, type KeystorePayload, type KeystoreUnlockResult, LazyAccountAuthorizer, type NetworkType, type PathRequest, PrivateKeyAuthorizer, type RealAccountStore, type RealDevAccount, type RealTxSigner, type RealTxSigningInput, type RealTxSigningResult, SILVER_SPEND_DRAFT_SCHEMA, type ScriptFundingRequest, type ScriptFundingResult, type ScriptOutput, type SignTxPlanInput, type SignTxPlanResult, type SilverContractUtxo, type SilverDraftArg, type SilverSignatureArg, type SilverSignerSlot, type SilverSpendArg, type SilverSpendDraft, type SilverSpendDraftRequest, type SilverSpendResult, type SilverSweepRequest, SimulatedSigner, StaticSignatureScriptAuthorizer, type TxInputAuthorizationContext, type TxInputAuthorizer, UnsupportedKaspaKeyGenerator, UnsupportedRealKaspaSigner, UnsupportedRealTxSigner, type WalletArtifact, type WalletClaims, type WalletCreateRequest, type WalletImportRequest, WalletManager, WalletManagerImpl, type WalletMetadata, type WalletState, WalletStateStoreJson, type WalletStateStoreOptions, type WasmInputSigner, type WasmProviderConfig, type WasmUtxoEntrySource, type WasmUtxoInput, appendToKeystoreJson, assertAccountCompatible, assertSigningNetworkAllowed, assertValueConservation, attachInspectRedactor, buildCovenantGenesis, buildCovenantTransition, buildScriptFunding, buildSilverSweep, createBalancedTransaction, createDevSigner, createEmptyRealAccountStore, createLocalKaspaWallet, createScriptTransaction, describeAccount, detectCapabilities, ensureDevAccounts, finalizeSilverSpend, getDefaultRealAccountsPath, getKaspaSigningBackendStatus, getOrCreateDevAccount, getRealDevAccount, getRequiredEnv, importRealDevAccount, listDevAccountsSync, listHardkasAccounts, listRealDevAccounts, loadKaspaWasm, loadKaspaWasmSync, loadOrCreateRealAccountStore, loadRealAccountStore, loadRealAccountStoreSync, planOutputsWithChange, prepareEvmAccountExport, prepareSilverSpend, redactAccountForLog, removeRealDevAccount, resolveHardkasAccount, resolveHardkasAccountAddress, resolveRealAccountOrAddress, saveRealAccountStore, signSilverSpend, signTxPlanArtifact, toWasmScriptPublicKey, unlockAccountKeystore, validateAccountName, validateAddressNetwork, validateAddressPrefix, withKeystoreLock };
package/dist/index.js CHANGED
@@ -1,6 +1,12 @@
1
+ import {
2
+ LazyAccountAuthorizer,
3
+ PrivateKeyAuthorizer,
4
+ StaticSignatureScriptAuthorizer
5
+ } from "./chunk-YBCXJBA5.js";
1
6
  import {
2
7
  DEV_ACCOUNTS_PASSWORD,
3
8
  KaspaWasmPrivateKeySigner,
9
+ KeystoreManager,
4
10
  assertSigningNetworkAllowed,
5
11
  assertValueConservation,
6
12
  createBalancedTransaction,
@@ -10,8 +16,9 @@ import {
10
16
  getOrCreateDevAccount,
11
17
  listDevAccountsSync,
12
18
  planOutputsWithChange,
13
- toWasmScriptPublicKey
14
- } from "./chunk-Q22JFUWC.js";
19
+ toWasmScriptPublicKey,
20
+ unlockAccountKeystore
21
+ } from "./chunk-G6PYXAIU.js";
15
22
  import {
16
23
  parseWasmTxToRpc
17
24
  } from "./chunk-GM2BY4VS.js";
@@ -43,15 +50,7 @@ import {
43
50
  validateAccountName,
44
51
  validateAddressNetwork,
45
52
  validateAddressPrefix
46
- } from "./chunk-2UQTGGML.js";
47
- import {
48
- KeystoreManager
49
- } from "./chunk-YLG2NIAU.js";
50
- import {
51
- LazyAccountAuthorizer,
52
- PrivateKeyAuthorizer,
53
- StaticSignatureScriptAuthorizer
54
- } from "./chunk-PKDTLCCQ.js";
53
+ } from "./chunk-IRNHRG4N.js";
55
54
 
56
55
  // src/simulated.ts
57
56
  var SimulatedSigner = class {
@@ -196,6 +195,9 @@ async function signTxPlanArtifact(input) {
196
195
  if (input.config?.wasm) {
197
196
  signerOptions.wasmConfig = input.config.wasm;
198
197
  }
198
+ if (input.keystorePassword !== void 0) {
199
+ signerOptions.keystorePassword = input.keystorePassword;
200
+ }
199
201
  const signer = new KaspaWasmPrivateKeySigner(signerOptions);
200
202
  const result = await signer.signTxPlan({
201
203
  planArtifact,
@@ -784,8 +786,10 @@ var KaspaSdkKeyGenerator = class {
784
786
  try {
785
787
  return await rawLoader();
786
788
  } catch (e) {
789
+ if (e?.code === "WASM_TOOLCHAIN_NOT_INSTALLED" || e?.code === "WASM_TOOLCHAIN_INTEGRITY_FAILED") throw e;
787
790
  const err = new Error(
788
- "WALLET_BACKEND_UNAVAILABLE: Kaspa cryptography adapter missing. Real account generation requires WASM execution.\nUse 'hardkas accounts real import' to add a test fixture manually for now."
791
+ `WALLET_BACKEND_UNAVAILABLE: the Kaspa WASM SDK could not be loaded, so real accounts cannot be generated (${e?.message ?? String(e)}).
792
+ Check it with: hardkas toolchain status`
789
793
  );
790
794
  err.code = "WALLET_BACKEND_UNAVAILABLE";
791
795
  throw err;
@@ -1289,6 +1293,7 @@ export {
1289
1293
  signSilverSpend,
1290
1294
  signTxPlanArtifact,
1291
1295
  toWasmScriptPublicKey,
1296
+ unlockAccountKeystore,
1292
1297
  validateAccountName,
1293
1298
  validateAddressNetwork,
1294
1299
  validateAddressPrefix,
@@ -0,0 +1,13 @@
1
+ import {
2
+ KaspaWasmPrivateKeySigner,
3
+ assertSigningNetworkAllowed,
4
+ unlockAccountKeystore
5
+ } from "./chunk-G6PYXAIU.js";
6
+ import "./chunk-GM2BY4VS.js";
7
+ import "./chunk-BNF566PS.js";
8
+ import "./chunk-IRNHRG4N.js";
9
+ export {
10
+ KaspaWasmPrivateKeySigner,
11
+ assertSigningNetworkAllowed,
12
+ unlockAccountKeystore
13
+ };
@@ -4,7 +4,7 @@ import {
4
4
  listHardkasAccounts,
5
5
  resolveHardkasAccount,
6
6
  resolveHardkasAccountAddress
7
- } from "./chunk-2UQTGGML.js";
7
+ } from "./chunk-IRNHRG4N.js";
8
8
  export {
9
9
  assertAccountCompatible,
10
10
  describeAccount,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/accounts",
3
- "version": "0.12.0-rc.24",
3
+ "version": "0.12.0-rc.26",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -23,11 +23,11 @@
23
23
  ],
24
24
  "dependencies": {
25
25
  "hash-wasm": "^4.12.0",
26
- "@hardkas/artifacts": "0.12.0-rc.24",
27
- "@hardkas/config": "0.12.0-rc.24",
28
- "@hardkas/core": "0.12.0-rc.24",
29
- "@hardkas/localnet": "0.12.0-rc.24",
30
- "@hardkas/tx-builder": "0.12.0-rc.24"
26
+ "@hardkas/core": "0.12.0-rc.26",
27
+ "@hardkas/artifacts": "0.12.0-rc.26",
28
+ "@hardkas/localnet": "0.12.0-rc.26",
29
+ "@hardkas/config": "0.12.0-rc.26",
30
+ "@hardkas/tx-builder": "0.12.0-rc.26"
31
31
  },
32
32
  "devDependencies": {
33
33
  "tsup": "^8.3.5",
@@ -1,166 +0,0 @@
1
- // src/keystore.ts
2
- import fs from "fs";
3
- import path from "path";
4
- import crypto from "crypto";
5
- import { argon2id } from "hash-wasm";
6
- import { writeFileAtomic } from "@hardkas/core";
7
- var KeystoreManager = class {
8
- /**
9
- * Keystore container format version. Separate from ARTIFACT_VERSION.
10
- * This versions the encrypted keystore envelope, not HardKAS artifacts.
11
- */
12
- static KEYSTORE_FORMAT_VERSION = "2.0.0";
13
- static KEYSTORE_FORMAT_TYPE = "hardkas.encryptedKeystore.v2";
14
- /**
15
- * Creates an encrypted keystore from a payload and password.
16
- */
17
- static async createEncryptedKeystore(payload, password, options) {
18
- if (!password) throw new Error("Password cannot be empty.");
19
- if (password.length < 8)
20
- throw new Error("Password must be at least 8 characters long.");
21
- const salt = crypto.randomBytes(16);
22
- const nonce = crypto.randomBytes(12);
23
- const iterations = options.iterations || 3;
24
- const memory = options.memory || 65536;
25
- const parallelism = options.parallelism || 1;
26
- const derivedKeyHex = await argon2id({
27
- password,
28
- salt,
29
- parallelism,
30
- iterations,
31
- memorySize: memory,
32
- hashLength: 32,
33
- // 256 bits for AES-256
34
- outputType: "hex"
35
- });
36
- const derivedKey = Buffer.from(derivedKeyHex, "hex");
37
- const cipher = crypto.createCipheriv("aes-256-gcm", derivedKey, nonce);
38
- const encryptedPayload = Buffer.concat([
39
- cipher.update(JSON.stringify(payload), "utf8"),
40
- cipher.final()
41
- ]);
42
- const tag = cipher.getAuthTag();
43
- derivedKey.fill(0);
44
- return {
45
- version: this.KEYSTORE_FORMAT_VERSION,
46
- type: this.KEYSTORE_FORMAT_TYPE,
47
- kdf: {
48
- algorithm: "argon2id",
49
- memory,
50
- iterations,
51
- parallelism,
52
- salt: salt.toString("base64")
53
- },
54
- cipher: {
55
- algorithm: "aes-256-gcm",
56
- nonce: nonce.toString("base64"),
57
- tag: tag.toString("base64")
58
- },
59
- encryptedPayload: encryptedPayload.toString("base64"),
60
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
61
- metadata: {
62
- label: options.label,
63
- network: options.network,
64
- address: payload.address
65
- }
66
- };
67
- }
68
- /**
69
- * Decrypts an encrypted keystore using a password.
70
- */
71
- static async decryptEncryptedKeystore(keystore, password) {
72
- if (keystore.version !== this.KEYSTORE_FORMAT_VERSION) {
73
- return {
74
- success: false,
75
- error: `Unsupported keystore version: ${keystore.version}`
76
- };
77
- }
78
- try {
79
- const salt = Buffer.from(keystore.kdf.salt, "base64");
80
- const nonce = Buffer.from(keystore.cipher.nonce, "base64");
81
- const tag = Buffer.from(keystore.cipher.tag, "base64");
82
- const encryptedData = Buffer.from(keystore.encryptedPayload, "base64");
83
- const derivedKeyHex = await argon2id({
84
- password,
85
- salt,
86
- parallelism: keystore.kdf.parallelism,
87
- iterations: keystore.kdf.iterations,
88
- memorySize: keystore.kdf.memory,
89
- hashLength: 32,
90
- outputType: "hex"
91
- });
92
- const derivedKey = Buffer.from(derivedKeyHex, "hex");
93
- const decipher = crypto.createDecipheriv("aes-256-gcm", derivedKey, nonce);
94
- decipher.setAuthTag(tag);
95
- const decrypted = Buffer.concat([decipher.update(encryptedData), decipher.final()]);
96
- derivedKey.fill(0);
97
- const payload = JSON.parse(decrypted.toString("utf8"));
98
- return { success: true, payload };
99
- } catch (e) {
100
- return { success: false, error: "Invalid password or corrupted keystore." };
101
- }
102
- }
103
- /**
104
- * Verifies if the password is correct for the keystore.
105
- */
106
- static async verifyKeystorePassword(keystore, password) {
107
- const result = await this.decryptEncryptedKeystore(keystore, password);
108
- return result.success;
109
- }
110
- /**
111
- * Changes the password of an encrypted keystore.
112
- */
113
- static async changeKeystorePassword(keystore, oldPassword, newPassword) {
114
- const unlock = await this.decryptEncryptedKeystore(keystore, oldPassword);
115
- if (!unlock.success || !unlock.payload) {
116
- throw new Error("Invalid current password.");
117
- }
118
- return this.createEncryptedKeystore(unlock.payload, newPassword, {
119
- label: keystore.metadata.label,
120
- network: keystore.metadata.network,
121
- iterations: keystore.kdf.iterations,
122
- memory: keystore.kdf.memory,
123
- parallelism: keystore.kdf.parallelism
124
- });
125
- }
126
- /**
127
- * Loads an encrypted keystore from the filesystem.
128
- */
129
- static async loadEncryptedKeystore(filePath) {
130
- try {
131
- const data = await fs.promises.readFile(filePath, "utf-8");
132
- const keystore = JSON.parse(data);
133
- if (keystore.type !== this.KEYSTORE_FORMAT_TYPE) {
134
- throw new Error(`Invalid keystore type: ${keystore.type}`);
135
- }
136
- return keystore;
137
- } catch (e) {
138
- throw new Error(
139
- `Failed to load keystore at ${filePath}: ${e instanceof Error ? e instanceof Error ? e instanceof Error ? e.message : String(e) : String(e) : String(e)}`
140
- );
141
- }
142
- }
143
- /**
144
- * Saves an encrypted keystore to the filesystem.
145
- */
146
- static async saveEncryptedKeystore(filePath, keystore) {
147
- try {
148
- const dir = path.dirname(filePath);
149
- if (!fs.existsSync(dir)) {
150
- await fs.promises.mkdir(dir, { recursive: true });
151
- }
152
- await writeFileAtomic(filePath, JSON.stringify(keystore, null, 2), {
153
- encoding: "utf-8",
154
- mode: 384
155
- });
156
- } catch (e) {
157
- throw new Error(
158
- `Failed to save keystore at ${filePath}: ${e instanceof Error ? e instanceof Error ? e instanceof Error ? e.message : String(e) : String(e) : String(e)}`
159
- );
160
- }
161
- }
162
- };
163
-
164
- export {
165
- KeystoreManager
166
- };
@@ -1,18 +0,0 @@
1
- import {
2
- DEV_ACCOUNTS_PASSWORD,
3
- createDevSigner,
4
- ensureDevAccounts,
5
- getOrCreateDevAccount,
6
- listDevAccountsSync
7
- } from "./chunk-Q22JFUWC.js";
8
- import "./chunk-GM2BY4VS.js";
9
- import "./chunk-BNF566PS.js";
10
- import "./chunk-2UQTGGML.js";
11
- import "./chunk-YLG2NIAU.js";
12
- export {
13
- DEV_ACCOUNTS_PASSWORD,
14
- createDevSigner,
15
- ensureDevAccounts,
16
- getOrCreateDevAccount,
17
- listDevAccountsSync
18
- };
@@ -1,6 +0,0 @@
1
- import {
2
- KeystoreManager
3
- } from "./chunk-YLG2NIAU.js";
4
- export {
5
- KeystoreManager
6
- };