@hardkas/accounts 0.2.2-alpha.1 → 0.3.0-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
@@ -187,7 +187,10 @@ interface RealDevAccount {
187
187
  readonly name: string;
188
188
  readonly address: string;
189
189
  readonly publicKey?: string;
190
+ /** @deprecated Use keystoreRef for encrypted storage. Plaintext keys in this field are considered legacy/unsafe. */
190
191
  readonly privateKey?: string;
192
+ /** Reference to the encrypted keystore file in .hardkas/keystore/ */
193
+ readonly keystoreRef?: string;
191
194
  readonly createdAt: string;
192
195
  }
193
196
  declare function getDefaultRealAccountsPath(cwd?: string): string;
package/dist/index.js CHANGED
@@ -21,6 +21,7 @@ import { createDeterministicAccounts } from "@hardkas/localnet";
21
21
  // src/real-accounts.ts
22
22
  import fs from "fs";
23
23
  import path from "path";
24
+ import { writeFileAtomicSync } from "@hardkas/core";
24
25
  import { HARDKAS_VERSION, ARTIFACT_SCHEMAS, ARTIFACT_VERSION } from "@hardkas/artifacts";
25
26
  function getDefaultRealAccountsPath(cwd = process.cwd()) {
26
27
  return path.join(cwd, ".hardkas", "accounts.real.json");
@@ -34,7 +35,7 @@ function createEmptyRealAccountStore() {
34
35
  networkId: "simnet",
35
36
  mode: "real",
36
37
  connectionMode: "node",
37
- warning: "Development keys only. Do not use on mainnet. Private keys are stored in plaintext.",
38
+ warning: "HardKAS: Development account store. Encrypted storage is default. Unsafe plaintext storage is legacy.",
38
39
  accounts: []
39
40
  };
40
41
  }
@@ -45,7 +46,17 @@ function loadRealAccountStoreSync(options) {
45
46
  }
46
47
  try {
47
48
  const data = fs.readFileSync(filePath, "utf-8");
48
- return JSON.parse(data);
49
+ const store = JSON.parse(data);
50
+ const plaintextAccounts = store.accounts.filter((a) => a.privateKey);
51
+ if (plaintextAccounts.length > 0) {
52
+ const names = plaintextAccounts.map((a) => a.name).join(", ");
53
+ console.warn(`
54
+ \u26A0\uFE0F [SECURITY WARNING] Plaintext private keys detected in legacy account store for: ${names}`);
55
+ console.warn(` Location: ${filePath}`);
56
+ console.warn(` Recommendation: Re-import these accounts using encrypted keystores.
57
+ `);
58
+ }
59
+ return store;
49
60
  } catch (e) {
50
61
  throw new Error(`Failed to load real account store at ${filePath}: ${e instanceof Error ? e.message : String(e)}`);
51
62
  }
@@ -62,12 +73,11 @@ async function loadOrCreateRealAccountStore(options) {
62
73
  }
63
74
  async function saveRealAccountStore(store, options) {
64
75
  const filePath = options?.path || getDefaultRealAccountsPath(options?.cwd);
65
- const dir = path.dirname(filePath);
66
- if (!fs.existsSync(dir)) {
67
- fs.mkdirSync(dir, { recursive: true });
68
- }
69
76
  try {
70
- fs.writeFileSync(filePath, JSON.stringify(store, null, 2), "utf-8");
77
+ writeFileAtomicSync(filePath, JSON.stringify(store, null, 2), {
78
+ encoding: "utf-8",
79
+ mode: 384
80
+ });
71
81
  } catch (e) {
72
82
  throw new Error(`Failed to save real account store at ${filePath}: ${e instanceof Error ? e.message : String(e)}`);
73
83
  }
@@ -445,7 +455,6 @@ async function signTxPlanArtifact(input) {
445
455
  version: "1.0.0-alpha",
446
456
  status: "signed",
447
457
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
448
- signedId: `signed_${planArtifact.planId}_${Date.now().toString(36)}`,
449
458
  txId: result.txId || "",
450
459
  // Ensure txId is present
451
460
  sourcePlanId: planArtifact.planId,
@@ -459,7 +468,9 @@ async function signTxPlanArtifact(input) {
459
468
  payload: result.signedTransaction?.payload || ""
460
469
  }
461
470
  };
462
- artifact.contentHash = calculateContentHash2(artifact);
471
+ const contentHash = calculateContentHash2(artifact);
472
+ artifact.signedId = `signed-${contentHash.slice(0, 16)}`;
473
+ artifact.contentHash = contentHash;
463
474
  return artifact;
464
475
  }
465
476
  if (account.kind === "external-wallet") {
@@ -608,6 +619,7 @@ import fs3 from "fs";
608
619
  import path3 from "path";
609
620
  import crypto from "crypto";
610
621
  import { argon2id } from "hash-wasm";
622
+ import { writeFileAtomic } from "@hardkas/core";
611
623
  var KeystoreManager = class {
612
624
  /**
613
625
  * Keystore container format version. Separate from ARTIFACT_VERSION.
@@ -750,7 +762,10 @@ var KeystoreManager = class {
750
762
  if (!fs3.existsSync(dir)) {
751
763
  await fs3.promises.mkdir(dir, { recursive: true });
752
764
  }
753
- await fs3.promises.writeFile(filePath, JSON.stringify(keystore, null, 2), "utf-8");
765
+ await writeFileAtomic(filePath, JSON.stringify(keystore, null, 2), {
766
+ encoding: "utf-8",
767
+ mode: 384
768
+ });
754
769
  } catch (e) {
755
770
  throw new Error(`Failed to save keystore at ${filePath}: ${e instanceof Error ? e.message : String(e)}`);
756
771
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/accounts",
3
- "version": "0.2.2-alpha.1",
3
+ "version": "0.3.0-alpha",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -17,10 +17,10 @@
17
17
  ],
18
18
  "dependencies": {
19
19
  "hash-wasm": "^4.12.0",
20
- "@hardkas/artifacts": "0.2.2-alpha.1",
21
- "@hardkas/config": "0.2.2-alpha.1",
22
- "@hardkas/core": "0.2.2-alpha.1",
23
- "@hardkas/localnet": "0.2.2-alpha.1"
20
+ "@hardkas/artifacts": "0.3.0-alpha",
21
+ "@hardkas/config": "0.3.0-alpha",
22
+ "@hardkas/localnet": "0.3.0-alpha",
23
+ "@hardkas/core": "0.3.0-alpha"
24
24
  },
25
25
  "devDependencies": {
26
26
  "tsup": "^8.3.5",