@hardkas/accounts 0.9.4-alpha → 0.9.7-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)) {
@@ -346,6 +384,10 @@ function listHardkasAccounts(config) {
346
384
  }
347
385
  if (config?.accounts) {
348
386
  for (const [name, accConfig] of Object.entries(config.accounts)) {
387
+ const existing = accounts.get(name);
388
+ if (existing && existing.kind === "kaspa-private-key" && accConfig.kind === "simulated") {
389
+ continue;
390
+ }
349
391
  accounts.set(name, {
350
392
  name,
351
393
  ...accConfig
@@ -747,7 +789,7 @@ async function getOrCreateDevAccount(workspaceDir, index, alias) {
747
789
  const kp = privKey.toKeypair();
748
790
  address = kp.toAddress(network).toString();
749
791
  publicKey = kp.publicKey;
750
- privateKey = kp.privateKey;
792
+ privateKey = privateKeyHex;
751
793
  } else {
752
794
  let sdkModule;
753
795
  try {
@@ -1446,6 +1488,76 @@ var UnsupportedKaspaKeyGenerator = class {
1446
1488
  );
1447
1489
  }
1448
1490
  };
1491
+
1492
+ // src/keystore-lock.ts
1493
+ import fs5 from "fs";
1494
+ import path5 from "path";
1495
+ async function withKeystoreLock(filePath, operation) {
1496
+ const lockFilePath = `${filePath}.lock`;
1497
+ const staleTimeoutMs = parseInt(process.env.HARDKAS_KEYSTORE_LOCK_STALE_MS || "30000", 10);
1498
+ const acquireTimeoutMs = parseInt(process.env.HARDKAS_KEYSTORE_LOCK_TIMEOUT_MS || "10000", 10);
1499
+ const start = Date.now();
1500
+ while (true) {
1501
+ try {
1502
+ fs5.mkdirSync(path5.dirname(lockFilePath), { recursive: true });
1503
+ fs5.writeFileSync(lockFilePath, process.pid.toString(), { flag: "wx" });
1504
+ break;
1505
+ } catch (err) {
1506
+ if (err.code === "EEXIST") {
1507
+ const stats = fs5.statSync(lockFilePath, { throwIfNoEntry: false });
1508
+ if (stats && Date.now() - stats.mtimeMs > staleTimeoutMs) {
1509
+ try {
1510
+ fs5.unlinkSync(lockFilePath);
1511
+ } catch (e) {
1512
+ }
1513
+ continue;
1514
+ }
1515
+ if (Date.now() - start > acquireTimeoutMs) {
1516
+ const e = new Error("KEYSTORE_LOCK_TIMEOUT: Failed to acquire lock for keystore.json");
1517
+ e.code = "KEYSTORE_LOCK_TIMEOUT";
1518
+ throw e;
1519
+ }
1520
+ const jitter = Math.floor(Math.random() * 75) + 25;
1521
+ await new Promise((resolve) => setTimeout(resolve, jitter));
1522
+ } else {
1523
+ throw err;
1524
+ }
1525
+ }
1526
+ }
1527
+ try {
1528
+ return await operation();
1529
+ } finally {
1530
+ try {
1531
+ fs5.unlinkSync(lockFilePath);
1532
+ } catch (e) {
1533
+ }
1534
+ }
1535
+ }
1536
+ async function appendToKeystoreJson(workspaceRoot, alias, accountData) {
1537
+ const keystorePath = path5.join(workspaceRoot, ".hardkas", "keystore.json");
1538
+ const tempPath = path5.join(workspaceRoot, ".hardkas", `keystore-${process.pid}-${Date.now()}.json.tmp`);
1539
+ await withKeystoreLock(keystorePath, async () => {
1540
+ let ks = {};
1541
+ if (fs5.existsSync(keystorePath)) {
1542
+ try {
1543
+ const data = await fs5.promises.readFile(keystorePath, "utf-8");
1544
+ ks = JSON.parse(data);
1545
+ } catch (e) {
1546
+ }
1547
+ }
1548
+ ks[alias] = accountData;
1549
+ const fd = await fs5.promises.open(tempPath, "w");
1550
+ try {
1551
+ await fd.writeFile(JSON.stringify(ks, null, 2));
1552
+ await fd.sync();
1553
+ } finally {
1554
+ await fd.close();
1555
+ }
1556
+ await fs5.promises.rename(tempPath, keystorePath);
1557
+ const written = await fs5.promises.readFile(keystorePath, "utf-8");
1558
+ JSON.parse(written);
1559
+ });
1560
+ }
1449
1561
  export {
1450
1562
  DEV_ACCOUNTS_PASSWORD,
1451
1563
  HardkasFixtureSigner,
@@ -1458,6 +1570,7 @@ export {
1458
1570
  UnsupportedKaspaKeyGenerator,
1459
1571
  UnsupportedRealKaspaSigner,
1460
1572
  UnsupportedRealTxSigner,
1573
+ appendToKeystoreJson,
1461
1574
  assertSigningNetworkAllowed,
1462
1575
  createEmptyRealAccountStore,
1463
1576
  createLocalKaspaWallet,
@@ -1485,5 +1598,6 @@ export {
1485
1598
  signTxPlanArtifact,
1486
1599
  validateAccountName,
1487
1600
  validateAddressNetwork,
1488
- validateAddressPrefix
1601
+ validateAddressPrefix,
1602
+ withKeystoreLock
1489
1603
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/accounts",
3
- "version": "0.9.4-alpha",
3
+ "version": "0.9.7-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/config": "0.9.4-alpha",
23
- "@hardkas/artifacts": "0.9.4-alpha",
24
- "@hardkas/core": "0.9.4-alpha",
25
- "@hardkas/localnet": "0.9.4-alpha"
22
+ "@hardkas/artifacts": "0.9.7-alpha",
23
+ "@hardkas/core": "0.9.7-alpha",
24
+ "@hardkas/config": "0.9.7-alpha",
25
+ "@hardkas/localnet": "0.9.7-alpha"
26
26
  },
27
27
  "devDependencies": {
28
28
  "tsup": "^8.3.5",