@hardkas/accounts 0.2.2-alpha → 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
@@ -112,8 +112,6 @@ declare function describeAccount(account: HardkasAccount): Record<string, unknow
112
112
 
113
113
  declare function getRequiredEnv(name: string): string;
114
114
 
115
- declare function redactSecret(value: string): string;
116
-
117
115
  /**
118
116
  * Simulated signer for simnet development.
119
117
  * Produces deterministic signatures without real private keys.
@@ -189,7 +187,10 @@ interface RealDevAccount {
189
187
  readonly name: string;
190
188
  readonly address: string;
191
189
  readonly publicKey?: string;
190
+ /** @deprecated Use keystoreRef for encrypted storage. Plaintext keys in this field are considered legacy/unsafe. */
192
191
  readonly privateKey?: string;
192
+ /** Reference to the encrypted keystore file in .hardkas/keystore/ */
193
+ readonly keystoreRef?: string;
193
194
  readonly createdAt: string;
194
195
  }
195
196
  declare function getDefaultRealAccountsPath(cwd?: string): string;
@@ -337,4 +338,4 @@ declare class KeystoreManager {
337
338
  static saveEncryptedKeystore(filePath: string, keystore: EncryptedKeystoreV2): Promise<void>;
338
339
  }
339
340
 
340
- export { type EncryptedKeystoreV2, type GeneratedKaspaDevAccount, type HardkasAccount, type HardkasAccountKind, type HardkasBaseAccount, type HardkasEvmPrivateKeyAccount, type HardkasExternalWalletAccount, 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, describeAccount, getDefaultRealAccountsPath, getKaspaSigningBackendStatus, getRealDevAccount, getRequiredEnv, importRealDevAccount, listHardkasAccounts, listRealDevAccounts, loadKaspaWasm, loadOrCreateRealAccountStore, loadRealAccountStore, loadRealAccountStoreSync, redactSecret, removeRealDevAccount, resolveHardkasAccount, resolveHardkasAccountAddress, resolveRealAccountOrAddress, saveRealAccountStore, signTxPlanArtifact, validateAccountName, validateAddressPrefix };
341
+ export { type EncryptedKeystoreV2, type GeneratedKaspaDevAccount, type HardkasAccount, type HardkasAccountKind, type HardkasBaseAccount, type HardkasEvmPrivateKeyAccount, type HardkasExternalWalletAccount, 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, describeAccount, getDefaultRealAccountsPath, getKaspaSigningBackendStatus, getRealDevAccount, getRequiredEnv, importRealDevAccount, listHardkasAccounts, listRealDevAccounts, loadKaspaWasm, loadOrCreateRealAccountStore, loadRealAccountStore, loadRealAccountStoreSync, removeRealDevAccount, resolveHardkasAccount, resolveHardkasAccountAddress, resolveRealAccountOrAddress, saveRealAccountStore, signTxPlanArtifact, validateAccountName, validateAddressPrefix };
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
  }
@@ -262,15 +272,6 @@ function getRequiredEnv(name) {
262
272
  return value;
263
273
  }
264
274
 
265
- // src/redact.ts
266
- function redactSecret(value) {
267
- if (!value) return "";
268
- if (value.length <= 10) {
269
- return "***";
270
- }
271
- return `${value.slice(0, 6)}...${value.slice(-4)}`;
272
- }
273
-
274
275
  // src/signer.ts
275
276
  import {
276
277
  createSimulatedSignedTxArtifact,
@@ -454,7 +455,6 @@ async function signTxPlanArtifact(input) {
454
455
  version: "1.0.0-alpha",
455
456
  status: "signed",
456
457
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
457
- signedId: `signed_${planArtifact.planId}_${Date.now().toString(36)}`,
458
458
  txId: result.txId || "",
459
459
  // Ensure txId is present
460
460
  sourcePlanId: planArtifact.planId,
@@ -468,7 +468,9 @@ async function signTxPlanArtifact(input) {
468
468
  payload: result.signedTransaction?.payload || ""
469
469
  }
470
470
  };
471
- artifact.contentHash = calculateContentHash2(artifact);
471
+ const contentHash = calculateContentHash2(artifact);
472
+ artifact.signedId = `signed-${contentHash.slice(0, 16)}`;
473
+ artifact.contentHash = contentHash;
472
474
  return artifact;
473
475
  }
474
476
  if (account.kind === "external-wallet") {
@@ -617,6 +619,7 @@ import fs3 from "fs";
617
619
  import path3 from "path";
618
620
  import crypto from "crypto";
619
621
  import { argon2id } from "hash-wasm";
622
+ import { writeFileAtomic } from "@hardkas/core";
620
623
  var KeystoreManager = class {
621
624
  /**
622
625
  * Keystore container format version. Separate from ARTIFACT_VERSION.
@@ -759,7 +762,10 @@ var KeystoreManager = class {
759
762
  if (!fs3.existsSync(dir)) {
760
763
  await fs3.promises.mkdir(dir, { recursive: true });
761
764
  }
762
- 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
+ });
763
769
  } catch (e) {
764
770
  throw new Error(`Failed to save keystore at ${filePath}: ${e instanceof Error ? e.message : String(e)}`);
765
771
  }
@@ -789,7 +795,6 @@ export {
789
795
  loadOrCreateRealAccountStore,
790
796
  loadRealAccountStore,
791
797
  loadRealAccountStoreSync,
792
- redactSecret,
793
798
  removeRealDevAccount,
794
799
  resolveHardkasAccount,
795
800
  resolveHardkasAccountAddress,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/accounts",
3
- "version": "0.2.2-alpha",
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",
21
- "@hardkas/core": "0.2.2-alpha",
22
- "@hardkas/config": "0.2.2-alpha",
23
- "@hardkas/localnet": "0.2.2-alpha"
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",