@hardkas/accounts 0.9.3-alpha → 0.9.6-alpha

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/dist/index.d.ts CHANGED
@@ -385,6 +385,9 @@ declare class KeystoreManager {
385
385
  static saveEncryptedKeystore(filePath: string, keystore: EncryptedKeystoreV2): Promise<void>;
386
386
  }
387
387
 
388
+ declare function withKeystoreLock<T>(filePath: string, operation: () => Promise<T>): Promise<T>;
389
+ declare function appendToKeystoreJson(workspaceRoot: string, alias: string, accountData: any): Promise<void>;
390
+
388
391
  declare const DEV_ACCOUNTS_PASSWORD = "hardkas-local-dev";
389
392
  declare function ensureDevAccounts(workspaceDir: string): Promise<void>;
390
393
  declare function getOrCreateDevAccount(workspaceDir: string, index: number, alias: string): Promise<GeneratedKaspaDevAccount>;
@@ -393,4 +396,4 @@ declare function listDevAccountsSync(workspaceDir: string): {
393
396
  address: string;
394
397
  }[];
395
398
 
396
- export { type CreateKaspaWalletOptions, DEV_ACCOUNTS_PASSWORD, type EncryptedKeystoreV2, type EvmExportResult, type GeneratedKaspaDevAccount, type HardkasAccount, type HardkasAccountKind, type HardkasBaseAccount, type HardkasEvmPrivateKeyAccount, type HardkasExternalWalletAccount, HardkasFixtureSigner, type HardkasKaspaPrivateKeyAccount, type HardkasSigner, type HardkasSignerKind, type HardkasSimulatedAccount, type HardkasTxPlanSigner, type KaspaKeyGenerator, KaspaSdkKeyGenerator, type KaspaSdkKeyGeneratorOptions, KaspaSdkRealTxSigner, type KaspaSdkRealTxSignerOptions, type KaspaSigningBackendStatus, KaspaWasmPrivateKeySigner, type KeystoreCipherParams, type KeystoreKdfParams, KeystoreManager, type KeystorePayload, type KeystoreUnlockResult, type RealAccountStore, type RealDevAccount, type RealTxSigner, type RealTxSigningInput, type RealTxSigningResult, type ResolveAccountOptions, type SignTxPlanInput, type SignTxPlanResult, SimulatedSigner, SimulatedTxPlanSigner, UnsupportedKaspaKeyGenerator, UnsupportedRealKaspaSigner, UnsupportedRealTxSigner, assertSigningNetworkAllowed, createEmptyRealAccountStore, createLocalKaspaWallet, describeAccount, ensureDevAccounts, getDefaultRealAccountsPath, getKaspaSigningBackendStatus, getOrCreateDevAccount, getRealDevAccount, getRequiredEnv, importRealDevAccount, listDevAccountsSync, listHardkasAccounts, listRealDevAccounts, loadKaspaWasm, loadOrCreateRealAccountStore, loadRealAccountStore, loadRealAccountStoreSync, prepareEvmAccountExport, removeRealDevAccount, resolveHardkasAccount, resolveHardkasAccountAddress, resolveRealAccountOrAddress, saveRealAccountStore, signTxPlanArtifact, validateAccountName, validateAddressNetwork, validateAddressPrefix };
399
+ export { type CreateKaspaWalletOptions, DEV_ACCOUNTS_PASSWORD, type EncryptedKeystoreV2, type EvmExportResult, type GeneratedKaspaDevAccount, type HardkasAccount, type HardkasAccountKind, type HardkasBaseAccount, type HardkasEvmPrivateKeyAccount, type HardkasExternalWalletAccount, HardkasFixtureSigner, type HardkasKaspaPrivateKeyAccount, type HardkasSigner, type HardkasSignerKind, type HardkasSimulatedAccount, type HardkasTxPlanSigner, type KaspaKeyGenerator, KaspaSdkKeyGenerator, type KaspaSdkKeyGeneratorOptions, KaspaSdkRealTxSigner, type KaspaSdkRealTxSignerOptions, type KaspaSigningBackendStatus, KaspaWasmPrivateKeySigner, type KeystoreCipherParams, type KeystoreKdfParams, KeystoreManager, type KeystorePayload, type KeystoreUnlockResult, type RealAccountStore, type RealDevAccount, type RealTxSigner, type RealTxSigningInput, type RealTxSigningResult, type ResolveAccountOptions, type SignTxPlanInput, type SignTxPlanResult, SimulatedSigner, SimulatedTxPlanSigner, UnsupportedKaspaKeyGenerator, UnsupportedRealKaspaSigner, UnsupportedRealTxSigner, appendToKeystoreJson, assertSigningNetworkAllowed, createEmptyRealAccountStore, createLocalKaspaWallet, describeAccount, ensureDevAccounts, getDefaultRealAccountsPath, getKaspaSigningBackendStatus, getOrCreateDevAccount, getRealDevAccount, getRequiredEnv, importRealDevAccount, listDevAccountsSync, listHardkasAccounts, listRealDevAccounts, loadKaspaWasm, loadOrCreateRealAccountStore, loadRealAccountStore, loadRealAccountStoreSync, prepareEvmAccountExport, removeRealDevAccount, resolveHardkasAccount, resolveHardkasAccountAddress, resolveRealAccountOrAddress, saveRealAccountStore, signTxPlanArtifact, validateAccountName, validateAddressNetwork, validateAddressPrefix, withKeystoreLock };
package/dist/index.js CHANGED
@@ -240,6 +240,21 @@ function resolveHardkasAccount(options) {
240
240
  } catch (e) {
241
241
  }
242
242
  }
243
+ const keystoreJsonPath = path2.join(workspaceRoot, ".hardkas", "keystore.json");
244
+ if (fs2.existsSync(keystoreJsonPath)) {
245
+ try {
246
+ const data = fs2.readFileSync(keystoreJsonPath, "utf-8");
247
+ const ks = JSON.parse(data);
248
+ if (ks[alias]) {
249
+ return {
250
+ name: alias,
251
+ kind: ks[alias].type === "simulated" ? "simulated" : "kaspa-private-key",
252
+ address: ks[alias].address
253
+ };
254
+ }
255
+ } catch (e) {
256
+ }
257
+ }
243
258
  if (config?.accounts && config.accounts[alias]) {
244
259
  const accConfig = config.accounts[alias];
245
260
  return {
@@ -308,6 +323,29 @@ function listHardkasAccounts(config) {
308
323
  }
309
324
  }
310
325
  }
326
+ const keystoreJsonPath = path2.join(workspaceRoot, ".hardkas", "keystore.json");
327
+ if (fs2.existsSync(keystoreJsonPath)) {
328
+ try {
329
+ const data = fs2.readFileSync(keystoreJsonPath, "utf-8");
330
+ const ks = JSON.parse(data);
331
+ for (const [name, acc] of Object.entries(ks)) {
332
+ if (acc.type === "simulated") {
333
+ accounts.set(name, {
334
+ name,
335
+ kind: "simulated",
336
+ address: acc.address
337
+ });
338
+ } else {
339
+ accounts.set(name, {
340
+ name,
341
+ kind: "kaspa-private-key",
342
+ address: acc.address
343
+ });
344
+ }
345
+ }
346
+ } catch (e) {
347
+ }
348
+ }
311
349
  const realStore = loadRealAccountStoreSync({ cwd: workspaceRoot });
312
350
  if (realStore) {
313
351
  for (const realAcc of listRealDevAccounts(realStore)) {
@@ -1446,6 +1484,76 @@ var UnsupportedKaspaKeyGenerator = class {
1446
1484
  );
1447
1485
  }
1448
1486
  };
1487
+
1488
+ // src/keystore-lock.ts
1489
+ import fs5 from "fs";
1490
+ import path5 from "path";
1491
+ async function withKeystoreLock(filePath, operation) {
1492
+ const lockFilePath = `${filePath}.lock`;
1493
+ const staleTimeoutMs = parseInt(process.env.HARDKAS_KEYSTORE_LOCK_STALE_MS || "30000", 10);
1494
+ const acquireTimeoutMs = parseInt(process.env.HARDKAS_KEYSTORE_LOCK_TIMEOUT_MS || "10000", 10);
1495
+ const start = Date.now();
1496
+ while (true) {
1497
+ try {
1498
+ fs5.mkdirSync(path5.dirname(lockFilePath), { recursive: true });
1499
+ fs5.writeFileSync(lockFilePath, process.pid.toString(), { flag: "wx" });
1500
+ break;
1501
+ } catch (err) {
1502
+ if (err.code === "EEXIST") {
1503
+ const stats = fs5.statSync(lockFilePath, { throwIfNoEntry: false });
1504
+ if (stats && Date.now() - stats.mtimeMs > staleTimeoutMs) {
1505
+ try {
1506
+ fs5.unlinkSync(lockFilePath);
1507
+ } catch (e) {
1508
+ }
1509
+ continue;
1510
+ }
1511
+ if (Date.now() - start > acquireTimeoutMs) {
1512
+ const e = new Error("KEYSTORE_LOCK_TIMEOUT: Failed to acquire lock for keystore.json");
1513
+ e.code = "KEYSTORE_LOCK_TIMEOUT";
1514
+ throw e;
1515
+ }
1516
+ const jitter = Math.floor(Math.random() * 75) + 25;
1517
+ await new Promise((resolve) => setTimeout(resolve, jitter));
1518
+ } else {
1519
+ throw err;
1520
+ }
1521
+ }
1522
+ }
1523
+ try {
1524
+ return await operation();
1525
+ } finally {
1526
+ try {
1527
+ fs5.unlinkSync(lockFilePath);
1528
+ } catch (e) {
1529
+ }
1530
+ }
1531
+ }
1532
+ async function appendToKeystoreJson(workspaceRoot, alias, accountData) {
1533
+ const keystorePath = path5.join(workspaceRoot, ".hardkas", "keystore.json");
1534
+ const tempPath = path5.join(workspaceRoot, ".hardkas", `keystore-${process.pid}-${Date.now()}.json.tmp`);
1535
+ await withKeystoreLock(keystorePath, async () => {
1536
+ let ks = {};
1537
+ if (fs5.existsSync(keystorePath)) {
1538
+ try {
1539
+ const data = await fs5.promises.readFile(keystorePath, "utf-8");
1540
+ ks = JSON.parse(data);
1541
+ } catch (e) {
1542
+ }
1543
+ }
1544
+ ks[alias] = accountData;
1545
+ const fd = await fs5.promises.open(tempPath, "w");
1546
+ try {
1547
+ await fd.writeFile(JSON.stringify(ks, null, 2));
1548
+ await fd.sync();
1549
+ } finally {
1550
+ await fd.close();
1551
+ }
1552
+ await fs5.promises.rename(tempPath, keystorePath);
1553
+ const written = await fs5.promises.readFile(keystorePath, "utf-8");
1554
+ JSON.parse(written);
1555
+ });
1556
+ }
1449
1557
  export {
1450
1558
  DEV_ACCOUNTS_PASSWORD,
1451
1559
  HardkasFixtureSigner,
@@ -1458,6 +1566,7 @@ export {
1458
1566
  UnsupportedKaspaKeyGenerator,
1459
1567
  UnsupportedRealKaspaSigner,
1460
1568
  UnsupportedRealTxSigner,
1569
+ appendToKeystoreJson,
1461
1570
  assertSigningNetworkAllowed,
1462
1571
  createEmptyRealAccountStore,
1463
1572
  createLocalKaspaWallet,
@@ -1485,5 +1594,6 @@ export {
1485
1594
  signTxPlanArtifact,
1486
1595
  validateAccountName,
1487
1596
  validateAddressNetwork,
1488
- validateAddressPrefix
1597
+ validateAddressPrefix,
1598
+ withKeystoreLock
1489
1599
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/accounts",
3
- "version": "0.9.3-alpha",
3
+ "version": "0.9.6-alpha",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -19,10 +19,10 @@
19
19
  "dependencies": {
20
20
  "hash-wasm": "^4.12.0",
21
21
  "kaspa-wasm": "0.13.0",
22
- "@hardkas/artifacts": "0.9.3-alpha",
23
- "@hardkas/core": "0.9.3-alpha",
24
- "@hardkas/config": "0.9.3-alpha",
25
- "@hardkas/localnet": "0.9.3-alpha"
22
+ "@hardkas/core": "0.9.6-alpha",
23
+ "@hardkas/artifacts": "0.9.6-alpha",
24
+ "@hardkas/config": "0.9.6-alpha",
25
+ "@hardkas/localnet": "0.9.6-alpha"
26
26
  },
27
27
  "devDependencies": {
28
28
  "tsup": "^8.3.5",