@hardkas/accounts 0.7.1-alpha → 0.7.4-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.js +142 -62
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -22,7 +22,11 @@ import { createDeterministicAccounts } from "@hardkas/localnet";
|
|
|
22
22
|
import fs from "fs";
|
|
23
23
|
import path from "path";
|
|
24
24
|
import { writeFileAtomicSync } from "@hardkas/core";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
HARDKAS_VERSION,
|
|
27
|
+
ARTIFACT_SCHEMAS,
|
|
28
|
+
ARTIFACT_VERSION
|
|
29
|
+
} from "@hardkas/artifacts";
|
|
26
30
|
function getDefaultRealAccountsPath(cwd) {
|
|
27
31
|
const root = cwd ?? process.cwd();
|
|
28
32
|
return path.join(root, ".hardkas", "accounts.real.json");
|
|
@@ -51,15 +55,21 @@ function loadRealAccountStoreSync(options) {
|
|
|
51
55
|
const plaintextAccounts = store.accounts.filter((a) => a.privateKey);
|
|
52
56
|
if (plaintextAccounts.length > 0) {
|
|
53
57
|
const names = plaintextAccounts.map((a) => a.name).join(", ");
|
|
54
|
-
console.warn(
|
|
55
|
-
|
|
58
|
+
console.warn(
|
|
59
|
+
`
|
|
60
|
+
\u26A0\uFE0F [SECURITY WARNING] Plaintext private keys detected in legacy account store for: ${names}`
|
|
61
|
+
);
|
|
56
62
|
console.warn(` Location: ${filePath}`);
|
|
57
|
-
console.warn(
|
|
58
|
-
`
|
|
63
|
+
console.warn(
|
|
64
|
+
` Recommendation: Re-import these accounts using encrypted keystores.
|
|
65
|
+
`
|
|
66
|
+
);
|
|
59
67
|
}
|
|
60
68
|
return store;
|
|
61
69
|
} catch (e) {
|
|
62
|
-
throw new Error(
|
|
70
|
+
throw new Error(
|
|
71
|
+
`Failed to load real account store at ${filePath}: ${e instanceof Error ? e.message : String(e)}`
|
|
72
|
+
);
|
|
63
73
|
}
|
|
64
74
|
}
|
|
65
75
|
async function loadRealAccountStore(options) {
|
|
@@ -80,7 +90,9 @@ async function saveRealAccountStore(store, options) {
|
|
|
80
90
|
mode: 384
|
|
81
91
|
});
|
|
82
92
|
} catch (e) {
|
|
83
|
-
throw new Error(
|
|
93
|
+
throw new Error(
|
|
94
|
+
`Failed to save real account store at ${filePath}: ${e instanceof Error ? e.message : String(e)}`
|
|
95
|
+
);
|
|
84
96
|
}
|
|
85
97
|
}
|
|
86
98
|
function validateAccountName(name) {
|
|
@@ -89,7 +101,9 @@ function validateAccountName(name) {
|
|
|
89
101
|
}
|
|
90
102
|
const nameRegex = /^[a-zA-Z0-9_-]+$/;
|
|
91
103
|
if (!nameRegex.test(name)) {
|
|
92
|
-
throw new Error(
|
|
104
|
+
throw new Error(
|
|
105
|
+
`Invalid account name '${name}'. Only letters, numbers, dashes and underscores are allowed.`
|
|
106
|
+
);
|
|
93
107
|
}
|
|
94
108
|
}
|
|
95
109
|
function validateAddressPrefix(address) {
|
|
@@ -99,7 +113,9 @@ function validateAddressPrefix(address) {
|
|
|
99
113
|
const validPrefixes = ["kaspa:", "kaspatest:", "kaspasim:"];
|
|
100
114
|
const hasValidPrefix = validPrefixes.some((prefix) => address.startsWith(prefix));
|
|
101
115
|
if (!hasValidPrefix) {
|
|
102
|
-
throw new Error(
|
|
116
|
+
throw new Error(
|
|
117
|
+
`Invalid address '${address}'. Must start with one of: ${validPrefixes.join(", ")}`
|
|
118
|
+
);
|
|
103
119
|
}
|
|
104
120
|
}
|
|
105
121
|
function importRealDevAccount(store, account) {
|
|
@@ -118,7 +134,9 @@ function importRealDevAccount(store, account) {
|
|
|
118
134
|
};
|
|
119
135
|
}
|
|
120
136
|
function removeRealDevAccount(store, name) {
|
|
121
|
-
const index = store.accounts.findIndex(
|
|
137
|
+
const index = store.accounts.findIndex(
|
|
138
|
+
(a) => a.name.toLowerCase() === name.toLowerCase()
|
|
139
|
+
);
|
|
122
140
|
if (index === -1) {
|
|
123
141
|
throw new Error(`Account with name '${name}' not found.`);
|
|
124
142
|
}
|
|
@@ -143,7 +161,9 @@ function resolveRealAccountOrAddress(store, nameOrAddress) {
|
|
|
143
161
|
if (nameOrAddress.startsWith("kaspa:") || nameOrAddress.startsWith("kaspatest:") || nameOrAddress.startsWith("kaspasim:")) {
|
|
144
162
|
return { address: nameOrAddress };
|
|
145
163
|
}
|
|
146
|
-
throw new Error(
|
|
164
|
+
throw new Error(
|
|
165
|
+
`'${nameOrAddress}' is not a registered real account name and is not a valid Kaspa address.`
|
|
166
|
+
);
|
|
147
167
|
}
|
|
148
168
|
|
|
149
169
|
// src/resolve.ts
|
|
@@ -160,7 +180,12 @@ function resolveHardkasAccount(options) {
|
|
|
160
180
|
if (alias === "0") alias = "alice";
|
|
161
181
|
if (alias === "1") alias = "bob";
|
|
162
182
|
const workspaceRoot = config?.cwd || process.cwd();
|
|
163
|
-
const devAccountPath = path2.join(
|
|
183
|
+
const devAccountPath = path2.join(
|
|
184
|
+
workspaceRoot,
|
|
185
|
+
".hardkas",
|
|
186
|
+
"dev-accounts",
|
|
187
|
+
`${alias}.json`
|
|
188
|
+
);
|
|
164
189
|
if (fs2.existsSync(devAccountPath)) {
|
|
165
190
|
try {
|
|
166
191
|
const data = fs2.readFileSync(devAccountPath, "utf-8");
|
|
@@ -203,7 +228,9 @@ function resolveHardkasAccount(options) {
|
|
|
203
228
|
};
|
|
204
229
|
}
|
|
205
230
|
const available = listHardkasAccounts(config).map((a) => a.name).join(", ");
|
|
206
|
-
throw new Error(
|
|
231
|
+
throw new Error(
|
|
232
|
+
`Unknown HardKAS account '${nameOrAddress}'. Available accounts: ${available}`
|
|
233
|
+
);
|
|
207
234
|
}
|
|
208
235
|
function listHardkasAccounts(config) {
|
|
209
236
|
const accounts = /* @__PURE__ */ new Map();
|
|
@@ -251,7 +278,9 @@ function listHardkasAccounts(config) {
|
|
|
251
278
|
const keystoreDir = path2.join(process.cwd(), ".hardkas", "keystore");
|
|
252
279
|
if (fs2.existsSync(keystoreDir)) {
|
|
253
280
|
if (!config || !config.cwd) {
|
|
254
|
-
throw new Error(
|
|
281
|
+
throw new Error(
|
|
282
|
+
"Workspace root/cwd is required for hermetic keystore path resolution"
|
|
283
|
+
);
|
|
255
284
|
}
|
|
256
285
|
const files = fs2.readdirSync(keystoreDir);
|
|
257
286
|
for (const file of files) {
|
|
@@ -286,7 +315,9 @@ function listHardkasAccounts(config) {
|
|
|
286
315
|
function resolveHardkasAccountAddress(accountOrAddress, config, context = "L1") {
|
|
287
316
|
if (accountOrAddress.startsWith("kaspa:") || accountOrAddress.startsWith("kaspatest:") || accountOrAddress.startsWith("kaspasim:")) {
|
|
288
317
|
if (context === "L2") {
|
|
289
|
-
throw new Error(
|
|
318
|
+
throw new Error(
|
|
319
|
+
`Invalid L2 address provided: ${accountOrAddress}. Expected EVM address or account alias.`
|
|
320
|
+
);
|
|
290
321
|
}
|
|
291
322
|
return accountOrAddress;
|
|
292
323
|
}
|
|
@@ -297,7 +328,9 @@ function resolveHardkasAccountAddress(accountOrAddress, config, context = "L1")
|
|
|
297
328
|
if (context === "L2") {
|
|
298
329
|
const evmAddress = account.evmAddress;
|
|
299
330
|
if (!evmAddress) {
|
|
300
|
-
throw new Error(
|
|
331
|
+
throw new Error(
|
|
332
|
+
`Account '${account.name}' does not have an EVM address configured for L2.`
|
|
333
|
+
);
|
|
301
334
|
}
|
|
302
335
|
return evmAddress;
|
|
303
336
|
}
|
|
@@ -326,13 +359,19 @@ function describeAccount(account) {
|
|
|
326
359
|
// src/evm-export.ts
|
|
327
360
|
async function prepareEvmAccountExport(account, networkId, options = {}) {
|
|
328
361
|
if (networkId === "mainnet" || networkId.startsWith("testnet")) {
|
|
329
|
-
throw new Error(
|
|
362
|
+
throw new Error(
|
|
363
|
+
`EVM account export is NOT allowed on network "${networkId}" for security reasons.`
|
|
364
|
+
);
|
|
330
365
|
}
|
|
331
366
|
if (networkId !== "simnet" && networkId !== "localnet") {
|
|
332
|
-
throw new Error(
|
|
367
|
+
throw new Error(
|
|
368
|
+
`EVM account export is only supported on local development networks (simnet, localnet).`
|
|
369
|
+
);
|
|
333
370
|
}
|
|
334
371
|
if (account.kind !== "evm-private-key") {
|
|
335
|
-
throw new Error(
|
|
372
|
+
throw new Error(
|
|
373
|
+
`Account "${account.name}" is not an EVM/L2 account (kind: ${account.kind}). Only explicit EVM accounts can be exported.`
|
|
374
|
+
);
|
|
336
375
|
}
|
|
337
376
|
if (!account.address || !account.address.startsWith("0x")) {
|
|
338
377
|
throw new Error(`Account "${account.name}" does not have a valid EVM address.`);
|
|
@@ -348,7 +387,9 @@ async function prepareEvmAccountExport(account, networkId, options = {}) {
|
|
|
348
387
|
if (account.privateKeyEnv) {
|
|
349
388
|
privateKey = process.env[account.privateKeyEnv];
|
|
350
389
|
if (!privateKey) {
|
|
351
|
-
throw new Error(
|
|
390
|
+
throw new Error(
|
|
391
|
+
`Private key environment variable "${account.privateKeyEnv}" is not set.`
|
|
392
|
+
);
|
|
352
393
|
}
|
|
353
394
|
} else {
|
|
354
395
|
privateKey = account.privateKey;
|
|
@@ -358,7 +399,9 @@ async function prepareEvmAccountExport(account, networkId, options = {}) {
|
|
|
358
399
|
result.privateKey = privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`;
|
|
359
400
|
result.isSecret = true;
|
|
360
401
|
} else {
|
|
361
|
-
throw new Error(
|
|
402
|
+
throw new Error(
|
|
403
|
+
`Private key for account "${account.name}" could not be retrieved.`
|
|
404
|
+
);
|
|
362
405
|
}
|
|
363
406
|
}
|
|
364
407
|
return result;
|
|
@@ -410,9 +453,7 @@ async function getKaspaSigningBackendStatus() {
|
|
|
410
453
|
}
|
|
411
454
|
|
|
412
455
|
// src/kaspa-wasm-signer.ts
|
|
413
|
-
import {
|
|
414
|
-
calculateContentHash
|
|
415
|
-
} from "@hardkas/artifacts";
|
|
456
|
+
import { calculateContentHash } from "@hardkas/artifacts";
|
|
416
457
|
var KaspaWasmPrivateKeySigner = class {
|
|
417
458
|
constructor(options) {
|
|
418
459
|
this.options = options;
|
|
@@ -440,7 +481,9 @@ var KaspaWasmPrivateKeySigner = class {
|
|
|
440
481
|
}
|
|
441
482
|
const spk = u.scriptPublicKey;
|
|
442
483
|
if (!spk) {
|
|
443
|
-
throw new Error(
|
|
484
|
+
throw new Error(
|
|
485
|
+
"UTXO is missing scriptPublicKey. Real signing flows must never fabricate cryptographic state."
|
|
486
|
+
);
|
|
444
487
|
}
|
|
445
488
|
return new sdk.UtxoEntry(
|
|
446
489
|
BigInt(u.amountSompi),
|
|
@@ -452,10 +495,7 @@ var KaspaWasmPrivateKeySigner = class {
|
|
|
452
495
|
});
|
|
453
496
|
const outputs = plan.outputs.map((o) => {
|
|
454
497
|
if (!o.address) throw new Error("Output is missing address.");
|
|
455
|
-
return new sdk.PaymentOutput(
|
|
456
|
-
new sdk.Address(o.address),
|
|
457
|
-
BigInt(o.amountSompi)
|
|
458
|
-
);
|
|
498
|
+
return new sdk.PaymentOutput(new sdk.Address(o.address), BigInt(o.amountSompi));
|
|
459
499
|
});
|
|
460
500
|
const changeAddress = plan.change?.address ? new sdk.Address(plan.change.address) : void 0;
|
|
461
501
|
const priorityFee = BigInt(plan.estimatedFeeSompi);
|
|
@@ -481,7 +521,9 @@ var KaspaWasmPrivateKeySigner = class {
|
|
|
481
521
|
}
|
|
482
522
|
};
|
|
483
523
|
} catch (error) {
|
|
484
|
-
throw new Error(
|
|
524
|
+
throw new Error(
|
|
525
|
+
`Kaspa WASM signing failed: ${error instanceof Error ? error.message : String(error)}`
|
|
526
|
+
);
|
|
485
527
|
}
|
|
486
528
|
}
|
|
487
529
|
};
|
|
@@ -526,15 +568,21 @@ async function signTxPlanArtifact(input) {
|
|
|
526
568
|
}
|
|
527
569
|
if (planArtifact.mode === "simulated") {
|
|
528
570
|
if (account.kind !== "simulated") {
|
|
529
|
-
throw new Error(
|
|
571
|
+
throw new Error(
|
|
572
|
+
`Simulated plans must be signed with simulated accounts (account '${account.name}' is '${account.kind}').`
|
|
573
|
+
);
|
|
530
574
|
}
|
|
531
575
|
} else {
|
|
532
576
|
if (account.kind === "simulated") {
|
|
533
|
-
throw new Error(
|
|
577
|
+
throw new Error(
|
|
578
|
+
`Real Kaspa transaction plans (mode: ${planArtifact.mode}) cannot be signed with simulated accounts.`
|
|
579
|
+
);
|
|
534
580
|
}
|
|
535
581
|
}
|
|
536
582
|
if (planArtifact.networkId === "mainnet" && !input.allowMainnet) {
|
|
537
|
-
throw new Error(
|
|
583
|
+
throw new Error(
|
|
584
|
+
"Mainnet signing is disabled by default. Use --allow-mainnet-signing only if you understand the risks."
|
|
585
|
+
);
|
|
538
586
|
}
|
|
539
587
|
if (account.kind === "simulated") {
|
|
540
588
|
return createSimulatedSignedTxArtifact(
|
|
@@ -546,7 +594,9 @@ async function signTxPlanArtifact(input) {
|
|
|
546
594
|
if (account.kind === "kaspa-private-key") {
|
|
547
595
|
const status = await getKaspaSigningBackendStatus();
|
|
548
596
|
if (!status.available) {
|
|
549
|
-
throw new Error(
|
|
597
|
+
throw new Error(
|
|
598
|
+
`Real Kaspa signing is not available: ${status.error || "Unknown error"}. Ensure 'kaspa' package is installed.`
|
|
599
|
+
);
|
|
550
600
|
}
|
|
551
601
|
const signer = new KaspaWasmPrivateKeySigner({
|
|
552
602
|
account,
|
|
@@ -573,7 +623,8 @@ async function signTxPlanArtifact(input) {
|
|
|
573
623
|
signedTransaction: {
|
|
574
624
|
format: result.signedTransaction?.format === "hex" ? "hex" : "unknown",
|
|
575
625
|
payload: result.signedTransaction?.payload || ""
|
|
576
|
-
}
|
|
626
|
+
},
|
|
627
|
+
...planArtifact.workflowId ? { workflowId: planArtifact.workflowId } : {}
|
|
577
628
|
};
|
|
578
629
|
const contentHash = calculateContentHash2(artifact);
|
|
579
630
|
artifact.signedId = `signed-${contentHash.slice(0, 16)}`;
|
|
@@ -584,7 +635,9 @@ async function signTxPlanArtifact(input) {
|
|
|
584
635
|
throw new Error("External wallet signing is not implemented yet.");
|
|
585
636
|
}
|
|
586
637
|
if (account.kind === "evm-private-key") {
|
|
587
|
-
throw new Error(
|
|
638
|
+
throw new Error(
|
|
639
|
+
"EVM accounts are reserved for future Igra support and cannot sign Kaspa L1 transactions."
|
|
640
|
+
);
|
|
588
641
|
}
|
|
589
642
|
const accountRecord = account;
|
|
590
643
|
throw new Error(`Unsupported account kind for signing: ${accountRecord.kind}`);
|
|
@@ -604,7 +657,7 @@ var KaspaSdkKeyGenerator = class {
|
|
|
604
657
|
return await rawLoader();
|
|
605
658
|
} catch (e) {
|
|
606
659
|
throw new Error(
|
|
607
|
-
"Kaspa
|
|
660
|
+
"Kaspa cryptography adapter missing. Real account generation requires WASM execution.\nRun: npm install @kaspa/wallet-wasm\nUse 'hardkas accounts real import' to add accounts manually for now."
|
|
608
661
|
);
|
|
609
662
|
}
|
|
610
663
|
};
|
|
@@ -625,9 +678,13 @@ var KaspaSdkKeyGenerator = class {
|
|
|
625
678
|
privateKey: privateKeyStr
|
|
626
679
|
};
|
|
627
680
|
}
|
|
628
|
-
throw new Error(
|
|
681
|
+
throw new Error(
|
|
682
|
+
"Loaded Kaspa SDK does not expose expected PrivateKey constructor."
|
|
683
|
+
);
|
|
629
684
|
} catch (e) {
|
|
630
|
-
throw new Error(
|
|
685
|
+
throw new Error(
|
|
686
|
+
`Failed to generate account using SDK: ${e instanceof Error ? e.message : String(e)}`
|
|
687
|
+
);
|
|
631
688
|
}
|
|
632
689
|
}
|
|
633
690
|
};
|
|
@@ -661,22 +718,30 @@ var KaspaSdkRealTxSigner = class {
|
|
|
661
718
|
try {
|
|
662
719
|
sdk = await this.sdkLoader();
|
|
663
720
|
} catch (e) {
|
|
664
|
-
throw new Error(
|
|
721
|
+
throw new Error(
|
|
722
|
+
"Kaspa SDK real transaction signer dependency is not installed. Install/configure the supported Kaspa WASM SDK adapter."
|
|
723
|
+
);
|
|
665
724
|
}
|
|
666
725
|
if (!sdk) {
|
|
667
|
-
throw new Error(
|
|
726
|
+
throw new Error(
|
|
727
|
+
"Kaspa SDK real transaction signer dependency is not installed. Install/configure the supported Kaspa WASM SDK adapter."
|
|
728
|
+
);
|
|
668
729
|
}
|
|
669
730
|
if (!account.privateKey) {
|
|
670
731
|
throw new Error("Account has no private key available for signing.");
|
|
671
732
|
}
|
|
672
733
|
if (plan.from.address !== account.address) {
|
|
673
|
-
throw new Error(
|
|
734
|
+
throw new Error(
|
|
735
|
+
`Address mismatch: Plan requires ${plan.from.address}, but account has ${account.address}.`
|
|
736
|
+
);
|
|
674
737
|
}
|
|
675
738
|
try {
|
|
676
739
|
const privateKey = new sdk.PrivateKey(account.privateKey);
|
|
677
740
|
const utxos = plan.inputs.map((u) => {
|
|
678
741
|
if (!u.scriptPublicKey) {
|
|
679
|
-
throw new Error(
|
|
742
|
+
throw new Error(
|
|
743
|
+
`UTXO ${u.outpoint.transactionId}:${u.outpoint.index} is missing scriptPublicKey required for signing.`
|
|
744
|
+
);
|
|
680
745
|
}
|
|
681
746
|
const spk = u.scriptPublicKey;
|
|
682
747
|
return new sdk.UtxoEntry(
|
|
@@ -688,10 +753,7 @@ var KaspaSdkRealTxSigner = class {
|
|
|
688
753
|
);
|
|
689
754
|
});
|
|
690
755
|
const outputs = [
|
|
691
|
-
new sdk.PaymentOutput(
|
|
692
|
-
new sdk.Address(plan.to.address),
|
|
693
|
-
BigInt(plan.amountSompi)
|
|
694
|
-
)
|
|
756
|
+
new sdk.PaymentOutput(new sdk.Address(plan.to.address), BigInt(plan.amountSompi))
|
|
695
757
|
];
|
|
696
758
|
const changeAddress = plan.change ? new sdk.Address(plan.change.address) : void 0;
|
|
697
759
|
const priorityFee = BigInt(plan.estimatedFeeSompi);
|
|
@@ -714,7 +776,9 @@ var KaspaSdkRealTxSigner = class {
|
|
|
714
776
|
} catch (e) {
|
|
715
777
|
const msg = e instanceof Error ? e.message : String(e);
|
|
716
778
|
if (msg.includes("is not a constructor") || msg.includes("is not a function")) {
|
|
717
|
-
throw new Error(
|
|
779
|
+
throw new Error(
|
|
780
|
+
`Kaspa SDK signer adapter could not find required transaction signing primitives: ${msg}`
|
|
781
|
+
);
|
|
718
782
|
}
|
|
719
783
|
throw new Error(`Real transaction signing failed in Kaspa SDK: ${msg}`);
|
|
720
784
|
}
|
|
@@ -748,7 +812,8 @@ var KeystoreManager = class {
|
|
|
748
812
|
*/
|
|
749
813
|
static async createEncryptedKeystore(payload, password, options) {
|
|
750
814
|
if (!password) throw new Error("Password cannot be empty.");
|
|
751
|
-
if (password.length < 8)
|
|
815
|
+
if (password.length < 8)
|
|
816
|
+
throw new Error("Password must be at least 8 characters long.");
|
|
752
817
|
const salt = crypto.randomBytes(16);
|
|
753
818
|
const nonce = crypto.randomBytes(12);
|
|
754
819
|
const iterations = options.iterations || 3;
|
|
@@ -801,7 +866,10 @@ var KeystoreManager = class {
|
|
|
801
866
|
*/
|
|
802
867
|
static async decryptEncryptedKeystore(keystore, password) {
|
|
803
868
|
if (keystore.version !== this.KEYSTORE_FORMAT_VERSION) {
|
|
804
|
-
return {
|
|
869
|
+
return {
|
|
870
|
+
success: false,
|
|
871
|
+
error: `Unsupported keystore version: ${keystore.version}`
|
|
872
|
+
};
|
|
805
873
|
}
|
|
806
874
|
try {
|
|
807
875
|
const salt = Buffer.from(keystore.kdf.salt, "base64");
|
|
@@ -820,10 +888,7 @@ var KeystoreManager = class {
|
|
|
820
888
|
const derivedKey = Buffer.from(derivedKeyHex, "hex");
|
|
821
889
|
const decipher = crypto.createDecipheriv("aes-256-gcm", derivedKey, nonce);
|
|
822
890
|
decipher.setAuthTag(tag);
|
|
823
|
-
const decrypted = Buffer.concat([
|
|
824
|
-
decipher.update(encryptedData),
|
|
825
|
-
decipher.final()
|
|
826
|
-
]);
|
|
891
|
+
const decrypted = Buffer.concat([decipher.update(encryptedData), decipher.final()]);
|
|
827
892
|
derivedKey.fill(0);
|
|
828
893
|
const payload = JSON.parse(decrypted.toString("utf8"));
|
|
829
894
|
return { success: true, payload };
|
|
@@ -866,7 +931,9 @@ var KeystoreManager = class {
|
|
|
866
931
|
}
|
|
867
932
|
return keystore;
|
|
868
933
|
} catch (e) {
|
|
869
|
-
throw new Error(
|
|
934
|
+
throw new Error(
|
|
935
|
+
`Failed to load keystore at ${filePath}: ${e instanceof Error ? e.message : String(e)}`
|
|
936
|
+
);
|
|
870
937
|
}
|
|
871
938
|
}
|
|
872
939
|
/**
|
|
@@ -883,7 +950,9 @@ var KeystoreManager = class {
|
|
|
883
950
|
mode: 384
|
|
884
951
|
});
|
|
885
952
|
} catch (e) {
|
|
886
|
-
throw new Error(
|
|
953
|
+
throw new Error(
|
|
954
|
+
`Failed to save keystore at ${filePath}: ${e instanceof Error ? e.message : String(e)}`
|
|
955
|
+
);
|
|
887
956
|
}
|
|
888
957
|
}
|
|
889
958
|
};
|
|
@@ -907,9 +976,14 @@ async function getOrCreateDevAccount(workspaceDir, index, alias) {
|
|
|
907
976
|
const filePath = path4.join(devAccountsDir, `${alias}.json`);
|
|
908
977
|
if (fs4.existsSync(filePath)) {
|
|
909
978
|
const keystore2 = await KeystoreManager.loadEncryptedKeystore(filePath);
|
|
910
|
-
const unlock = await KeystoreManager.decryptEncryptedKeystore(
|
|
979
|
+
const unlock = await KeystoreManager.decryptEncryptedKeystore(
|
|
980
|
+
keystore2,
|
|
981
|
+
DEV_ACCOUNTS_PASSWORD
|
|
982
|
+
);
|
|
911
983
|
if (!unlock.success || !unlock.payload) {
|
|
912
|
-
throw new Error(
|
|
984
|
+
throw new Error(
|
|
985
|
+
`Failed to decrypt dev account ${alias}. Expected password: ${DEV_ACCOUNTS_PASSWORD}`
|
|
986
|
+
);
|
|
913
987
|
}
|
|
914
988
|
return {
|
|
915
989
|
address: unlock.payload.address,
|
|
@@ -919,15 +993,21 @@ async function getOrCreateDevAccount(workspaceDir, index, alias) {
|
|
|
919
993
|
}
|
|
920
994
|
const seedString = `${SIMNET_DETERMINISTIC_SEED}-${index}`;
|
|
921
995
|
const privateKeyHex = crypto2.createHash("sha256").update(seedString).digest("hex");
|
|
922
|
-
let
|
|
996
|
+
let sdkModule;
|
|
923
997
|
try {
|
|
924
|
-
|
|
998
|
+
sdkModule = await import(
|
|
999
|
+
/* @vite-ignore */
|
|
1000
|
+
"@kaspa/core-lib"
|
|
1001
|
+
);
|
|
925
1002
|
} catch (e) {
|
|
926
|
-
console.warn(
|
|
1003
|
+
console.warn(
|
|
1004
|
+
`
|
|
927
1005
|
[Warning] Kaspa SDK (@kaspa/core-lib) is not installed in the workspace.
|
|
928
|
-
Could not generate dev account '${alias}'.`
|
|
1006
|
+
Could not generate dev account '${alias}'.`
|
|
1007
|
+
);
|
|
929
1008
|
return { address: "", privateKey: "", publicKey: "" };
|
|
930
1009
|
}
|
|
1010
|
+
const sdk = sdkModule.default || sdkModule;
|
|
931
1011
|
const privKey = new sdk.PrivateKey(privateKeyHex);
|
|
932
1012
|
const pubKey = privKey.toPublicKey();
|
|
933
1013
|
const address = pubKey.toAddress("simnet").toString();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hardkas/accounts",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4-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/
|
|
21
|
-
"@hardkas/
|
|
22
|
-
"@hardkas/localnet": "0.7.
|
|
23
|
-
"@hardkas/core": "0.7.
|
|
20
|
+
"@hardkas/config": "0.7.4-alpha",
|
|
21
|
+
"@hardkas/artifacts": "0.7.4-alpha",
|
|
22
|
+
"@hardkas/localnet": "0.7.4-alpha",
|
|
23
|
+
"@hardkas/core": "0.7.4-alpha"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"tsup": "^8.3.5",
|