@hardkas/accounts 0.6.0-alpha → 0.7.1-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
@@ -265,6 +265,7 @@ declare function importRealDevAccount(store: RealAccountStore, account: {
265
265
  readonly address: string;
266
266
  readonly publicKey?: string;
267
267
  readonly privateKey?: string;
268
+ readonly keystoreRef?: string;
268
269
  }): RealAccountStore;
269
270
  declare function removeRealDevAccount(store: RealAccountStore, name: string): RealAccountStore;
270
271
  declare function getRealDevAccount(store: RealAccountStore, name: string): RealDevAccount | null;
@@ -366,4 +367,12 @@ declare class KeystoreManager {
366
367
  static saveEncryptedKeystore(filePath: string, keystore: EncryptedKeystoreV2): Promise<void>;
367
368
  }
368
369
 
369
- export { type CreateKaspaWalletOptions, type EncryptedKeystoreV2, type EvmExportResult, 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, createLocalKaspaWallet, describeAccount, getDefaultRealAccountsPath, getKaspaSigningBackendStatus, getRealDevAccount, getRequiredEnv, importRealDevAccount, listHardkasAccounts, listRealDevAccounts, loadKaspaWasm, loadOrCreateRealAccountStore, loadRealAccountStore, loadRealAccountStoreSync, prepareEvmAccountExport, removeRealDevAccount, resolveHardkasAccount, resolveHardkasAccountAddress, resolveRealAccountOrAddress, saveRealAccountStore, signTxPlanArtifact, validateAccountName, validateAddressPrefix };
370
+ declare const DEV_ACCOUNTS_PASSWORD = "hardkas-local-dev";
371
+ declare function ensureDevAccounts(workspaceDir: string): Promise<void>;
372
+ declare function getOrCreateDevAccount(workspaceDir: string, index: number, alias: string): Promise<GeneratedKaspaDevAccount>;
373
+ declare function listDevAccountsSync(workspaceDir: string): {
374
+ name: string;
375
+ address: string;
376
+ }[];
377
+
378
+ export { type CreateKaspaWalletOptions, DEV_ACCOUNTS_PASSWORD, type EncryptedKeystoreV2, type EvmExportResult, 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, createLocalKaspaWallet, describeAccount, ensureDevAccounts, getDefaultRealAccountsPath, getKaspaSigningBackendStatus, getOrCreateDevAccount, getRealDevAccount, getRequiredEnv, importRealDevAccount, listDevAccountsSync, listHardkasAccounts, listRealDevAccounts, loadKaspaWasm, loadOrCreateRealAccountStore, loadRealAccountStore, loadRealAccountStoreSync, prepareEvmAccountExport, removeRealDevAccount, resolveHardkasAccount, resolveHardkasAccountAddress, resolveRealAccountOrAddress, saveRealAccountStore, signTxPlanArtifact, validateAccountName, validateAddressPrefix };
package/dist/index.js CHANGED
@@ -23,8 +23,9 @@ import fs from "fs";
23
23
  import path from "path";
24
24
  import { writeFileAtomicSync } from "@hardkas/core";
25
25
  import { HARDKAS_VERSION, ARTIFACT_SCHEMAS, ARTIFACT_VERSION } from "@hardkas/artifacts";
26
- function getDefaultRealAccountsPath(cwd = process.cwd()) {
27
- return path.join(cwd, ".hardkas", "accounts.real.json");
26
+ function getDefaultRealAccountsPath(cwd) {
27
+ const root = cwd ?? process.cwd();
28
+ return path.join(root, ".hardkas", "accounts.real.json");
28
29
  }
29
30
  function createEmptyRealAccountStore() {
30
31
  return {
@@ -155,15 +156,34 @@ function resolveHardkasAccount(options) {
155
156
  address: nameOrAddress
156
157
  };
157
158
  }
158
- if (config?.accounts && config.accounts[nameOrAddress]) {
159
- const accConfig = config.accounts[nameOrAddress];
159
+ let alias = nameOrAddress;
160
+ if (alias === "0") alias = "alice";
161
+ if (alias === "1") alias = "bob";
162
+ const workspaceRoot = config?.cwd || process.cwd();
163
+ const devAccountPath = path2.join(workspaceRoot, ".hardkas", "dev-accounts", `${alias}.json`);
164
+ if (fs2.existsSync(devAccountPath)) {
165
+ try {
166
+ const data = fs2.readFileSync(devAccountPath, "utf-8");
167
+ const keystore = JSON.parse(data);
168
+ if (keystore.type === "hardkas.encryptedKeystore.v2") {
169
+ return {
170
+ name: alias,
171
+ kind: "kaspa-private-key",
172
+ address: keystore.metadata?.address
173
+ };
174
+ }
175
+ } catch (e) {
176
+ }
177
+ }
178
+ if (config?.accounts && config.accounts[alias]) {
179
+ const accConfig = config.accounts[alias];
160
180
  return {
161
- name: nameOrAddress,
181
+ name: alias,
162
182
  ...accConfig
163
183
  };
164
184
  }
165
185
  const realStore = loadRealAccountStoreSync();
166
- const realAcc = realStore ? getRealDevAccount(realStore, nameOrAddress) : null;
186
+ const realAcc = realStore ? getRealDevAccount(realStore, alias) : null;
167
187
  if (realAcc) {
168
188
  return {
169
189
  name: realAcc.name,
@@ -173,7 +193,7 @@ function resolveHardkasAccount(options) {
173
193
  };
174
194
  }
175
195
  const detAccounts = createDeterministicAccounts();
176
- const det = detAccounts.find((a) => a.name === nameOrAddress);
196
+ const det = detAccounts.find((a) => a.name === alias);
177
197
  if (det) {
178
198
  return {
179
199
  name: det.name,
@@ -196,6 +216,28 @@ function listHardkasAccounts(config) {
196
216
  evmAddress: det.evmAddress
197
217
  });
198
218
  }
219
+ const workspaceRoot = config?.cwd || process.cwd();
220
+ const devAccountsDir = path2.join(workspaceRoot, ".hardkas", "dev-accounts");
221
+ if (fs2.existsSync(devAccountsDir)) {
222
+ const files = fs2.readdirSync(devAccountsDir);
223
+ for (const file of files) {
224
+ if (file.endsWith(".json")) {
225
+ try {
226
+ const name = path2.basename(file, ".json");
227
+ const data = fs2.readFileSync(path2.join(devAccountsDir, file), "utf-8");
228
+ const keystore = JSON.parse(data);
229
+ if (keystore.type === "hardkas.encryptedKeystore.v2") {
230
+ accounts.set(name, {
231
+ name,
232
+ kind: "kaspa-private-key",
233
+ address: keystore.payload?.address || keystore.metadata?.address
234
+ });
235
+ }
236
+ } catch (e) {
237
+ }
238
+ }
239
+ }
240
+ }
199
241
  const realStore = loadRealAccountStoreSync();
200
242
  if (realStore) {
201
243
  for (const realAcc of listRealDevAccounts(realStore)) {
@@ -208,6 +250,9 @@ function listHardkasAccounts(config) {
208
250
  }
209
251
  const keystoreDir = path2.join(process.cwd(), ".hardkas", "keystore");
210
252
  if (fs2.existsSync(keystoreDir)) {
253
+ if (!config || !config.cwd) {
254
+ throw new Error("Workspace root/cwd is required for hermetic keystore path resolution");
255
+ }
211
256
  const files = fs2.readdirSync(keystoreDir);
212
257
  for (const file of files) {
213
258
  if (file.endsWith(".json")) {
@@ -393,7 +438,10 @@ var KaspaWasmPrivateKeySigner = class {
393
438
  if (!u.outpoint.transactionId || u.outpoint.index === void 0) {
394
439
  throw new Error(`UTXO is missing transactionId or index. Re-run tx plan.`);
395
440
  }
396
- const spk = u.scriptPublicKey || "mock-script";
441
+ const spk = u.scriptPublicKey;
442
+ if (!spk) {
443
+ throw new Error("UTXO is missing scriptPublicKey. Real signing flows must never fabricate cryptographic state.");
444
+ }
397
445
  return new sdk.UtxoEntry(
398
446
  BigInt(u.amountSompi),
399
447
  spk,
@@ -839,7 +887,105 @@ var KeystoreManager = class {
839
887
  }
840
888
  }
841
889
  };
890
+
891
+ // src/dev-accounts.ts
892
+ import fs4 from "fs";
893
+ import path4 from "path";
894
+ import crypto2 from "crypto";
895
+ var DEV_ACCOUNTS_PASSWORD = "hardkas-local-dev";
896
+ var SIMNET_DETERMINISTIC_SEED = "hardkas-deterministic-simnet-seed-v1";
897
+ async function ensureDevAccounts(workspaceDir) {
898
+ const devAccountsDir = path4.join(workspaceDir, ".hardkas", "dev-accounts");
899
+ if (!fs4.existsSync(devAccountsDir)) {
900
+ await fs4.promises.mkdir(devAccountsDir, { recursive: true });
901
+ }
902
+ await getOrCreateDevAccount(workspaceDir, 0, "alice");
903
+ await getOrCreateDevAccount(workspaceDir, 1, "bob");
904
+ }
905
+ async function getOrCreateDevAccount(workspaceDir, index, alias) {
906
+ const devAccountsDir = path4.join(workspaceDir, ".hardkas", "dev-accounts");
907
+ const filePath = path4.join(devAccountsDir, `${alias}.json`);
908
+ if (fs4.existsSync(filePath)) {
909
+ const keystore2 = await KeystoreManager.loadEncryptedKeystore(filePath);
910
+ const unlock = await KeystoreManager.decryptEncryptedKeystore(keystore2, DEV_ACCOUNTS_PASSWORD);
911
+ if (!unlock.success || !unlock.payload) {
912
+ throw new Error(`Failed to decrypt dev account ${alias}. Expected password: ${DEV_ACCOUNTS_PASSWORD}`);
913
+ }
914
+ return {
915
+ address: unlock.payload.address,
916
+ privateKey: unlock.payload.privateKey,
917
+ publicKey: unlock.payload.publicKey
918
+ };
919
+ }
920
+ const seedString = `${SIMNET_DETERMINISTIC_SEED}-${index}`;
921
+ const privateKeyHex = crypto2.createHash("sha256").update(seedString).digest("hex");
922
+ let sdk;
923
+ try {
924
+ sdk = await import("@kaspa/core-lib");
925
+ } catch (e) {
926
+ console.warn(`
927
+ [Warning] Kaspa SDK (@kaspa/core-lib) is not installed in the workspace.
928
+ Could not generate dev account '${alias}'.`);
929
+ return { address: "", privateKey: "", publicKey: "" };
930
+ }
931
+ const privKey = new sdk.PrivateKey(privateKeyHex);
932
+ const pubKey = privKey.toPublicKey();
933
+ const address = pubKey.toAddress("simnet").toString();
934
+ const accountData = {
935
+ address,
936
+ privateKey: privKey.toString(),
937
+ publicKey: pubKey.toString()
938
+ };
939
+ if (!fs4.existsSync(devAccountsDir)) {
940
+ await fs4.promises.mkdir(devAccountsDir, { recursive: true });
941
+ }
942
+ const payload = {
943
+ address: accountData.address,
944
+ privateKey: accountData.privateKey,
945
+ network: "simnet"
946
+ };
947
+ if (accountData.publicKey) {
948
+ payload.publicKey = accountData.publicKey;
949
+ }
950
+ const keystore = await KeystoreManager.createEncryptedKeystore(
951
+ payload,
952
+ DEV_ACCOUNTS_PASSWORD,
953
+ {
954
+ label: alias,
955
+ network: "simnet"
956
+ }
957
+ );
958
+ await KeystoreManager.saveEncryptedKeystore(filePath, keystore);
959
+ return accountData;
960
+ }
961
+ function listDevAccountsSync(workspaceDir) {
962
+ const devAccountsDir = path4.join(workspaceDir, ".hardkas", "dev-accounts");
963
+ if (!fs4.existsSync(devAccountsDir)) {
964
+ return [];
965
+ }
966
+ const accounts = [];
967
+ const files = fs4.readdirSync(devAccountsDir);
968
+ for (const file of files) {
969
+ if (file.endsWith(".json")) {
970
+ const name = path4.basename(file, ".json");
971
+ try {
972
+ const data = fs4.readFileSync(path4.join(devAccountsDir, file), "utf-8");
973
+ const keystore = JSON.parse(data);
974
+ if (keystore.type === "hardkas.encryptedKeystore.v2") {
975
+ accounts.push({
976
+ name,
977
+ address: keystore.metadata?.address || ""
978
+ });
979
+ }
980
+ } catch (e) {
981
+ }
982
+ }
983
+ }
984
+ accounts.sort((a, b) => a.name.localeCompare(b.name));
985
+ return accounts;
986
+ }
842
987
  export {
988
+ DEV_ACCOUNTS_PASSWORD,
843
989
  KaspaSdkKeyGenerator,
844
990
  KaspaSdkRealTxSigner,
845
991
  KaspaWasmPrivateKeySigner,
@@ -853,11 +999,14 @@ export {
853
999
  createEmptyRealAccountStore,
854
1000
  createLocalKaspaWallet,
855
1001
  describeAccount,
1002
+ ensureDevAccounts,
856
1003
  getDefaultRealAccountsPath,
857
1004
  getKaspaSigningBackendStatus,
1005
+ getOrCreateDevAccount,
858
1006
  getRealDevAccount,
859
1007
  getRequiredEnv,
860
1008
  importRealDevAccount,
1009
+ listDevAccountsSync,
861
1010
  listHardkasAccounts,
862
1011
  listRealDevAccounts,
863
1012
  loadKaspaWasm,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/accounts",
3
- "version": "0.6.0-alpha",
3
+ "version": "0.7.1-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.6.0-alpha",
21
- "@hardkas/config": "0.6.0-alpha",
22
- "@hardkas/localnet": "0.6.0-alpha",
23
- "@hardkas/core": "0.6.0-alpha"
20
+ "@hardkas/artifacts": "0.7.1-alpha",
21
+ "@hardkas/config": "0.7.1-alpha",
22
+ "@hardkas/localnet": "0.7.1-alpha",
23
+ "@hardkas/core": "0.7.1-alpha"
24
24
  },
25
25
  "devDependencies": {
26
26
  "tsup": "^8.3.5",