@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 +10 -1
- package/dist/index.js +157 -8
- package/package.json +5 -5
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
|
-
|
|
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
|
|
27
|
-
|
|
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
|
-
|
|
159
|
-
|
|
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:
|
|
181
|
+
name: alias,
|
|
162
182
|
...accConfig
|
|
163
183
|
};
|
|
164
184
|
}
|
|
165
185
|
const realStore = loadRealAccountStoreSync();
|
|
166
|
-
const realAcc = realStore ? getRealDevAccount(realStore,
|
|
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 ===
|
|
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
|
|
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.
|
|
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.
|
|
21
|
-
"@hardkas/config": "0.
|
|
22
|
-
"@hardkas/localnet": "0.
|
|
23
|
-
"@hardkas/core": "0.
|
|
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",
|