@hardkas/accounts 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Javier Rodriguez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,340 @@
1
+ import { HardkasConfig } from '@hardkas/config';
2
+ import { TxPlanArtifact, SignedTxArtifact, HardkasArtifactBase } from '@hardkas/artifacts';
3
+ import { NetworkId } from '@hardkas/core';
4
+
5
+ type HardkasAccountKind = "simulated" | "kaspa-private-key" | "external-wallet" | "evm-private-key";
6
+ interface KeystorePayload {
7
+ address: string;
8
+ privateKey: string;
9
+ publicKey?: string;
10
+ network: string;
11
+ }
12
+ interface KeystoreKdfParams {
13
+ algorithm: "argon2id" | "scrypt";
14
+ memory: number;
15
+ iterations: number;
16
+ parallelism: number;
17
+ salt: string;
18
+ }
19
+ interface KeystoreCipherParams {
20
+ algorithm: "aes-256-gcm";
21
+ nonce: string;
22
+ tag: string;
23
+ }
24
+ /**
25
+ * Encrypted keystore envelope format.
26
+ * version/type here refer to the keystore container format, NOT artifact schema version.
27
+ * This is intentionally separate from ARTIFACT_VERSION.
28
+ */
29
+ interface EncryptedKeystoreV2 {
30
+ version: "2.0.0";
31
+ type: "hardkas.encryptedKeystore.v2";
32
+ kdf: KeystoreKdfParams;
33
+ cipher: KeystoreCipherParams;
34
+ encryptedPayload: string;
35
+ createdAt: string;
36
+ metadata: {
37
+ label: string;
38
+ network: string;
39
+ [key: string]: any;
40
+ };
41
+ }
42
+ interface KeystoreUnlockResult {
43
+ success: boolean;
44
+ payload?: KeystorePayload;
45
+ error?: string;
46
+ }
47
+ interface HardkasBaseAccount {
48
+ name: string;
49
+ kind: HardkasAccountKind;
50
+ address?: string;
51
+ }
52
+ interface HardkasSimulatedAccount extends HardkasBaseAccount {
53
+ kind: "simulated";
54
+ address: string;
55
+ }
56
+ interface HardkasKaspaPrivateKeyAccount extends HardkasBaseAccount {
57
+ kind: "kaspa-private-key";
58
+ privateKeyEnv?: string | undefined;
59
+ address?: string;
60
+ }
61
+ interface HardkasExternalWalletAccount extends HardkasBaseAccount {
62
+ kind: "external-wallet";
63
+ walletId?: string;
64
+ address?: string;
65
+ }
66
+ interface HardkasEvmPrivateKeyAccount extends HardkasBaseAccount {
67
+ kind: "evm-private-key";
68
+ privateKeyEnv?: string | undefined;
69
+ address?: string;
70
+ }
71
+ type HardkasAccount = HardkasSimulatedAccount | HardkasKaspaPrivateKeyAccount | HardkasExternalWalletAccount | HardkasEvmPrivateKeyAccount;
72
+ type HardkasSignerKind = "simulated" | "kaspa-private-key" | "external-wallet" | "unsupported";
73
+ interface SignTxPlanInput {
74
+ planArtifact: any;
75
+ accountName: string;
76
+ }
77
+ interface SignTxPlanResult {
78
+ signatureKind: HardkasSignerKind;
79
+ signerAddress: string;
80
+ txId?: string;
81
+ signedTransaction: {
82
+ format: "hex" | "simulated" | "unknown";
83
+ payload: string;
84
+ };
85
+ signature?: {
86
+ value: string;
87
+ };
88
+ }
89
+ interface HardkasTxPlanSigner {
90
+ kind: HardkasSignerKind;
91
+ signTxPlan(input: SignTxPlanInput): Promise<SignTxPlanResult>;
92
+ }
93
+ interface HardkasSigner<TTx = unknown, TSignedTx = unknown> {
94
+ account: HardkasAccount;
95
+ signTransaction(tx: TTx): Promise<TSignedTx>;
96
+ }
97
+
98
+ declare class SimulatedSigner implements HardkasSigner {
99
+ readonly account: HardkasSimulatedAccount;
100
+ constructor(account: HardkasSimulatedAccount);
101
+ signTransaction(tx: unknown): Promise<unknown>;
102
+ }
103
+
104
+ interface ResolveAccountOptions {
105
+ nameOrAddress: string;
106
+ config?: HardkasConfig | undefined;
107
+ }
108
+ declare function resolveHardkasAccount(options: ResolveAccountOptions): HardkasAccount;
109
+ declare function listHardkasAccounts(config?: HardkasConfig): HardkasAccount[];
110
+ declare function resolveHardkasAccountAddress(accountOrAddress: string, config?: HardkasConfig): string;
111
+ declare function describeAccount(account: HardkasAccount): Record<string, unknown>;
112
+
113
+ declare function getRequiredEnv(name: string): string;
114
+
115
+ declare function redactSecret(value: string): string;
116
+
117
+ /**
118
+ * Simulated signer for simnet development.
119
+ * Produces deterministic signatures without real private keys.
120
+ */
121
+ declare class SimulatedTxPlanSigner implements HardkasTxPlanSigner {
122
+ kind: HardkasSignerKind;
123
+ signTxPlan(input: SignTxPlanInput): Promise<SignTxPlanResult>;
124
+ }
125
+ /**
126
+ * Placeholder for real Kaspa signing.
127
+ */
128
+ declare class UnsupportedRealKaspaSigner implements HardkasTxPlanSigner {
129
+ kind: HardkasSignerKind;
130
+ signTxPlan(_input: SignTxPlanInput): Promise<SignTxPlanResult>;
131
+ }
132
+ /**
133
+ * Main entry point for signing transaction plan artifacts.
134
+ */
135
+ declare function signTxPlanArtifact(input: {
136
+ planArtifact: TxPlanArtifact;
137
+ account: HardkasAccount;
138
+ config?: HardkasConfig;
139
+ allowMainnet?: boolean;
140
+ }): Promise<SignedTxArtifact>;
141
+
142
+ interface KaspaSigningBackendStatus {
143
+ available: boolean;
144
+ name: string;
145
+ version?: string;
146
+ error?: string;
147
+ }
148
+ /**
149
+ * Loads the official Kaspa WASM SDK dynamically.
150
+ * This ensures the toolkit remains usable even if the SDK is not installed.
151
+ */
152
+ declare function loadKaspaWasm(): Promise<any>;
153
+ /**
154
+ * Checks if the Kaspa WASM SDK is available without throwing.
155
+ */
156
+ declare function getKaspaSigningBackendStatus(): Promise<KaspaSigningBackendStatus>;
157
+
158
+ /**
159
+ * Real Kaspa signer using the official WASM SDK.
160
+ * Only works if the 'kaspa' package is installed.
161
+ */
162
+ declare class KaspaWasmPrivateKeySigner implements HardkasTxPlanSigner {
163
+ private options;
164
+ kind: HardkasSignerKind;
165
+ constructor(options: {
166
+ account: HardkasKaspaPrivateKeyAccount;
167
+ allowMainnet?: boolean | undefined;
168
+ });
169
+ signTxPlan(input: SignTxPlanInput): Promise<SignTxPlanResult>;
170
+ }
171
+ /**
172
+ * Security guard for network types.
173
+ */
174
+ declare function assertSigningNetworkAllowed(input: {
175
+ network: NetworkId;
176
+ mode: string;
177
+ allowMainnet?: boolean | undefined;
178
+ }): void;
179
+
180
+ interface RealAccountStore extends HardkasArtifactBase {
181
+ readonly schema: "hardkas.realAccountStore.v1";
182
+ readonly networkId: NetworkId;
183
+ readonly mode: "real";
184
+ readonly connectionMode?: "node" | "rpc";
185
+ readonly warning: string;
186
+ readonly accounts: readonly RealDevAccount[];
187
+ }
188
+ interface RealDevAccount {
189
+ readonly name: string;
190
+ readonly address: string;
191
+ readonly publicKey?: string;
192
+ readonly privateKey?: string;
193
+ readonly createdAt: string;
194
+ }
195
+ declare function getDefaultRealAccountsPath(cwd?: string): string;
196
+ declare function createEmptyRealAccountStore(): RealAccountStore;
197
+ declare function loadRealAccountStoreSync(options?: {
198
+ readonly cwd?: string;
199
+ readonly path?: string;
200
+ }): RealAccountStore | null;
201
+ declare function loadRealAccountStore(options?: {
202
+ readonly cwd?: string;
203
+ readonly path?: string;
204
+ }): Promise<RealAccountStore | null>;
205
+ declare function loadOrCreateRealAccountStore(options?: {
206
+ readonly cwd?: string;
207
+ readonly path?: string;
208
+ }): Promise<RealAccountStore>;
209
+ declare function saveRealAccountStore(store: RealAccountStore, options?: {
210
+ readonly cwd?: string;
211
+ readonly path?: string;
212
+ }): Promise<void>;
213
+ declare function validateAccountName(name: string): void;
214
+ declare function validateAddressPrefix(address: string): void;
215
+ declare function importRealDevAccount(store: RealAccountStore, account: {
216
+ readonly name: string;
217
+ readonly address: string;
218
+ readonly publicKey?: string;
219
+ readonly privateKey?: string;
220
+ }): RealAccountStore;
221
+ declare function removeRealDevAccount(store: RealAccountStore, name: string): RealAccountStore;
222
+ declare function getRealDevAccount(store: RealAccountStore, name: string): RealDevAccount | null;
223
+ declare function listRealDevAccounts(store: RealAccountStore): readonly RealDevAccount[];
224
+ /**
225
+ * Resolves a name (alias) or a direct Kaspa address from the real store.
226
+ */
227
+ declare function resolveRealAccountOrAddress(store: RealAccountStore | null, nameOrAddress: string): {
228
+ address: string;
229
+ name?: string;
230
+ };
231
+
232
+ interface RealTxSigningInput {
233
+ readonly plan: TxPlanArtifact;
234
+ readonly account: RealDevAccount;
235
+ }
236
+ interface RealTxSigningResult {
237
+ readonly signedTransaction: {
238
+ readonly format: "kaspa-sdk" | "hex" | "json" | "simulated" | "unknown";
239
+ readonly payload: string;
240
+ };
241
+ readonly txId?: string;
242
+ }
243
+ interface RealTxSigner {
244
+ sign(input: RealTxSigningInput): Promise<RealTxSigningResult>;
245
+ }
246
+ declare class UnsupportedRealTxSigner implements RealTxSigner {
247
+ sign(): Promise<RealTxSigningResult>;
248
+ }
249
+
250
+ interface KaspaSdkRealTxSignerOptions {
251
+ readonly sdkLoader?: () => Promise<any>;
252
+ }
253
+ declare class KaspaSdkRealTxSigner implements RealTxSigner {
254
+ private readonly sdkLoader;
255
+ constructor(options?: KaspaSdkRealTxSignerOptions);
256
+ sign(input: RealTxSigningInput): Promise<RealTxSigningResult>;
257
+ }
258
+
259
+ interface GeneratedKaspaDevAccount {
260
+ readonly address: string;
261
+ readonly publicKey?: string;
262
+ readonly privateKey: string;
263
+ readonly mnemonic?: string;
264
+ }
265
+ interface KaspaKeyGenerator {
266
+ generateAccount(options?: {
267
+ readonly networkId?: "simnet" | "testnet-10" | "mainnet";
268
+ }): Promise<GeneratedKaspaDevAccount>;
269
+ }
270
+ /**
271
+ * Placeholder implementation for Kaspa key generation.
272
+ * This ensures we don't implement custom crypto logic and wait for a verified SDK integration.
273
+ */
274
+ declare class UnsupportedKaspaKeyGenerator implements KaspaKeyGenerator {
275
+ generateAccount(): Promise<GeneratedKaspaDevAccount>;
276
+ }
277
+
278
+ interface KaspaSdkKeyGeneratorOptions {
279
+ readonly networkId?: "simnet" | "testnet-10" | "mainnet";
280
+ readonly sdkLoader?: () => Promise<any>;
281
+ }
282
+ /**
283
+ * Adapter for Kaspa SDK key generation.
284
+ * Uses dynamic imports to avoid breaking if the SDK is not installed.
285
+ */
286
+ declare class KaspaSdkKeyGenerator implements KaspaKeyGenerator {
287
+ private readonly networkId;
288
+ private readonly sdkLoader;
289
+ constructor(options?: KaspaSdkKeyGeneratorOptions);
290
+ generateAccount(options?: {
291
+ readonly networkId?: "simnet" | "testnet-10" | "mainnet";
292
+ }): Promise<GeneratedKaspaDevAccount>;
293
+ }
294
+
295
+ /**
296
+ * HardKAS Keystore V2 Implementation
297
+ *
298
+ * Uses Argon2id for KDF and AES-256-GCM for encryption.
299
+ * Designed for local developer workflows.
300
+ */
301
+ declare class KeystoreManager {
302
+ /**
303
+ * Keystore container format version. Separate from ARTIFACT_VERSION.
304
+ * This versions the encrypted keystore envelope, not HardKAS artifacts.
305
+ */
306
+ private static readonly KEYSTORE_FORMAT_VERSION;
307
+ private static readonly KEYSTORE_FORMAT_TYPE;
308
+ /**
309
+ * Creates an encrypted keystore from a payload and password.
310
+ */
311
+ static createEncryptedKeystore(payload: KeystorePayload, password: string, options: {
312
+ label: string;
313
+ network: string;
314
+ iterations?: number;
315
+ memory?: number;
316
+ parallelism?: number;
317
+ }): Promise<EncryptedKeystoreV2>;
318
+ /**
319
+ * Decrypts an encrypted keystore using a password.
320
+ */
321
+ static decryptEncryptedKeystore(keystore: EncryptedKeystoreV2, password: string): Promise<KeystoreUnlockResult>;
322
+ /**
323
+ * Verifies if the password is correct for the keystore.
324
+ */
325
+ static verifyKeystorePassword(keystore: EncryptedKeystoreV2, password: string): Promise<boolean>;
326
+ /**
327
+ * Changes the password of an encrypted keystore.
328
+ */
329
+ static changeKeystorePassword(keystore: EncryptedKeystoreV2, oldPassword: string, newPassword: string): Promise<EncryptedKeystoreV2>;
330
+ /**
331
+ * Loads an encrypted keystore from the filesystem.
332
+ */
333
+ static loadEncryptedKeystore(filePath: string): Promise<EncryptedKeystoreV2>;
334
+ /**
335
+ * Saves an encrypted keystore to the filesystem.
336
+ */
337
+ static saveEncryptedKeystore(filePath: string, keystore: EncryptedKeystoreV2): Promise<void>;
338
+ }
339
+
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 };
package/dist/index.js ADDED
@@ -0,0 +1,801 @@
1
+ // src/simulated.ts
2
+ var SimulatedSigner = class {
3
+ constructor(account) {
4
+ this.account = account;
5
+ }
6
+ account;
7
+ async signTransaction(tx) {
8
+ return {
9
+ tx,
10
+ signature: "simulated",
11
+ account: this.account.name
12
+ };
13
+ }
14
+ };
15
+
16
+ // src/resolve.ts
17
+ import fs2 from "fs";
18
+ import path2 from "path";
19
+ import { createDeterministicAccounts } from "@hardkas/localnet";
20
+
21
+ // src/real-accounts.ts
22
+ import fs from "fs";
23
+ import path from "path";
24
+ import { HARDKAS_VERSION, ARTIFACT_SCHEMAS, ARTIFACT_VERSION } from "@hardkas/artifacts";
25
+ function getDefaultRealAccountsPath(cwd = process.cwd()) {
26
+ return path.join(cwd, ".hardkas", "accounts.real.json");
27
+ }
28
+ function createEmptyRealAccountStore() {
29
+ return {
30
+ schema: ARTIFACT_SCHEMAS.REAL_ACCOUNT_STORE,
31
+ hardkasVersion: HARDKAS_VERSION,
32
+ version: ARTIFACT_VERSION,
33
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
34
+ networkId: "simnet",
35
+ mode: "real",
36
+ connectionMode: "node",
37
+ warning: "Development keys only. Do not use on mainnet. Private keys are stored in plaintext.",
38
+ accounts: []
39
+ };
40
+ }
41
+ function loadRealAccountStoreSync(options) {
42
+ const filePath = options?.path || getDefaultRealAccountsPath(options?.cwd);
43
+ if (!fs.existsSync(filePath)) {
44
+ return null;
45
+ }
46
+ try {
47
+ const data = fs.readFileSync(filePath, "utf-8");
48
+ return JSON.parse(data);
49
+ } catch (e) {
50
+ throw new Error(`Failed to load real account store at ${filePath}: ${e instanceof Error ? e.message : String(e)}`);
51
+ }
52
+ }
53
+ async function loadRealAccountStore(options) {
54
+ return loadRealAccountStoreSync(options);
55
+ }
56
+ async function loadOrCreateRealAccountStore(options) {
57
+ const store = await loadRealAccountStore(options);
58
+ if (store) return store;
59
+ const newStore = createEmptyRealAccountStore();
60
+ await saveRealAccountStore(newStore, options);
61
+ return newStore;
62
+ }
63
+ async function saveRealAccountStore(store, options) {
64
+ 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
+ try {
70
+ fs.writeFileSync(filePath, JSON.stringify(store, null, 2), "utf-8");
71
+ } catch (e) {
72
+ throw new Error(`Failed to save real account store at ${filePath}: ${e instanceof Error ? e.message : String(e)}`);
73
+ }
74
+ }
75
+ function validateAccountName(name) {
76
+ if (!name) {
77
+ throw new Error("Account name is required.");
78
+ }
79
+ const nameRegex = /^[a-zA-Z0-9_-]+$/;
80
+ if (!nameRegex.test(name)) {
81
+ throw new Error(`Invalid account name '${name}'. Only letters, numbers, dashes and underscores are allowed.`);
82
+ }
83
+ }
84
+ function validateAddressPrefix(address) {
85
+ if (!address) {
86
+ throw new Error("Address is required.");
87
+ }
88
+ const validPrefixes = ["kaspa:", "kaspatest:", "kaspasim:"];
89
+ const hasValidPrefix = validPrefixes.some((prefix) => address.startsWith(prefix));
90
+ if (!hasValidPrefix) {
91
+ throw new Error(`Invalid address '${address}'. Must start with one of: ${validPrefixes.join(", ")}`);
92
+ }
93
+ }
94
+ function importRealDevAccount(store, account) {
95
+ validateAccountName(account.name);
96
+ validateAddressPrefix(account.address);
97
+ if (store.accounts.some((a) => a.name.toLowerCase() === account.name.toLowerCase())) {
98
+ throw new Error(`Account with name '${account.name}' already exists.`);
99
+ }
100
+ const newAccount = {
101
+ ...account,
102
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
103
+ };
104
+ return {
105
+ ...store,
106
+ accounts: [...store.accounts, newAccount]
107
+ };
108
+ }
109
+ function removeRealDevAccount(store, name) {
110
+ const index = store.accounts.findIndex((a) => a.name.toLowerCase() === name.toLowerCase());
111
+ if (index === -1) {
112
+ throw new Error(`Account with name '${name}' not found.`);
113
+ }
114
+ const newAccounts = [...store.accounts];
115
+ newAccounts.splice(index, 1);
116
+ return {
117
+ ...store,
118
+ accounts: newAccounts
119
+ };
120
+ }
121
+ function getRealDevAccount(store, name) {
122
+ return store.accounts.find((a) => a.name.toLowerCase() === name.toLowerCase()) || null;
123
+ }
124
+ function listRealDevAccounts(store) {
125
+ return store.accounts;
126
+ }
127
+ function resolveRealAccountOrAddress(store, nameOrAddress) {
128
+ const account = store ? getRealDevAccount(store, nameOrAddress) : null;
129
+ if (account) {
130
+ return { address: account.address, name: account.name };
131
+ }
132
+ if (nameOrAddress.startsWith("kaspa:") || nameOrAddress.startsWith("kaspatest:") || nameOrAddress.startsWith("kaspasim:")) {
133
+ return { address: nameOrAddress };
134
+ }
135
+ throw new Error(`'${nameOrAddress}' is not a registered real account name and is not a valid Kaspa address.`);
136
+ }
137
+
138
+ // src/resolve.ts
139
+ function resolveHardkasAccount(options) {
140
+ const { nameOrAddress, config } = options;
141
+ if (nameOrAddress.startsWith("kaspa:") || nameOrAddress.startsWith("kaspatest:") || nameOrAddress.startsWith("kaspasim:")) {
142
+ return {
143
+ name: nameOrAddress,
144
+ kind: "external-wallet",
145
+ address: nameOrAddress
146
+ };
147
+ }
148
+ if (config?.accounts && config.accounts[nameOrAddress]) {
149
+ const accConfig = config.accounts[nameOrAddress];
150
+ return {
151
+ name: nameOrAddress,
152
+ ...accConfig
153
+ };
154
+ }
155
+ const realStore = loadRealAccountStoreSync();
156
+ const realAcc = realStore ? getRealDevAccount(realStore, nameOrAddress) : null;
157
+ if (realAcc) {
158
+ return {
159
+ name: realAcc.name,
160
+ kind: "kaspa-private-key",
161
+ // Assuming Kaspa for now, could be extensible
162
+ address: realAcc.address
163
+ };
164
+ }
165
+ const detAccounts = createDeterministicAccounts();
166
+ const det = detAccounts.find((a) => a.name === nameOrAddress);
167
+ if (det) {
168
+ return {
169
+ name: det.name,
170
+ kind: "simulated",
171
+ address: det.address
172
+ };
173
+ }
174
+ const available = listHardkasAccounts(config).map((a) => a.name).join(", ");
175
+ throw new Error(`Unknown HardKAS account '${nameOrAddress}'. Available accounts: ${available}`);
176
+ }
177
+ function listHardkasAccounts(config) {
178
+ const accounts = /* @__PURE__ */ new Map();
179
+ const detAccounts = createDeterministicAccounts();
180
+ for (const det of detAccounts) {
181
+ accounts.set(det.name, {
182
+ name: det.name,
183
+ kind: "simulated",
184
+ address: det.address
185
+ });
186
+ }
187
+ const realStore = loadRealAccountStoreSync();
188
+ if (realStore) {
189
+ for (const realAcc of listRealDevAccounts(realStore)) {
190
+ accounts.set(realAcc.name, {
191
+ name: realAcc.name,
192
+ kind: "kaspa-private-key",
193
+ address: realAcc.address
194
+ });
195
+ }
196
+ }
197
+ const keystoreDir = path2.join(process.cwd(), ".hardkas", "keystore");
198
+ if (fs2.existsSync(keystoreDir)) {
199
+ const files = fs2.readdirSync(keystoreDir);
200
+ for (const file of files) {
201
+ if (file.endsWith(".json")) {
202
+ try {
203
+ const name = path2.basename(file, ".json");
204
+ const data = fs2.readFileSync(path2.join(keystoreDir, file), "utf-8");
205
+ const keystore = JSON.parse(data);
206
+ if (keystore.type === "hardkas.encryptedKeystore.v2") {
207
+ accounts.set(name, {
208
+ name,
209
+ kind: "kaspa-private-key",
210
+ address: keystore.payload?.address || keystore.metadata?.address
211
+ // Payloads are encrypted, but address might be in metadata
212
+ });
213
+ }
214
+ } catch (e) {
215
+ }
216
+ }
217
+ }
218
+ }
219
+ if (config?.accounts) {
220
+ for (const [name, accConfig] of Object.entries(config.accounts)) {
221
+ accounts.set(name, {
222
+ name,
223
+ ...accConfig
224
+ });
225
+ }
226
+ }
227
+ return Array.from(accounts.values());
228
+ }
229
+ function resolveHardkasAccountAddress(accountOrAddress, config) {
230
+ if (accountOrAddress.startsWith("kaspa:") || accountOrAddress.startsWith("kaspatest:") || accountOrAddress.startsWith("kaspasim:")) {
231
+ return accountOrAddress;
232
+ }
233
+ const account = resolveHardkasAccount({ nameOrAddress: accountOrAddress, config });
234
+ if (!account.address) {
235
+ throw new Error(`Account '${account.name}' does not have a resolved address yet.`);
236
+ }
237
+ return account.address;
238
+ }
239
+ function describeAccount(account) {
240
+ const desc = {
241
+ name: account.name,
242
+ kind: account.kind
243
+ };
244
+ if (account.address) {
245
+ desc.address = account.address;
246
+ }
247
+ if (account.kind === "kaspa-private-key" || account.kind === "evm-private-key") {
248
+ desc.privateKeyEnv = account.privateKeyEnv;
249
+ }
250
+ if (account.kind === "external-wallet" && account.walletId) {
251
+ desc.walletId = account.walletId;
252
+ }
253
+ return desc;
254
+ }
255
+
256
+ // src/env.ts
257
+ function getRequiredEnv(name) {
258
+ const value = process.env[name];
259
+ if (!value || value.trim() === "") {
260
+ throw new Error(`Missing required environment variable '${name}'.`);
261
+ }
262
+ return value;
263
+ }
264
+
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
+ // src/signer.ts
275
+ import {
276
+ createSimulatedSignedTxArtifact,
277
+ calculateContentHash as calculateContentHash2,
278
+ HARDKAS_VERSION as HARDKAS_VERSION2
279
+ } from "@hardkas/artifacts";
280
+
281
+ // src/signer-backend.ts
282
+ async function loadKaspaWasm() {
283
+ try {
284
+ const sdk = await import("kaspa");
285
+ return sdk;
286
+ } catch (error) {
287
+ throw new Error(
288
+ "Kaspa WASM signing backend is not available. Please install the official 'kaspa' package: pnpm add kaspa"
289
+ );
290
+ }
291
+ }
292
+ async function getKaspaSigningBackendStatus() {
293
+ try {
294
+ const sdk = await loadKaspaWasm();
295
+ return {
296
+ available: true,
297
+ name: "Kaspa WASM SDK",
298
+ version: sdk.version || "unknown"
299
+ };
300
+ } catch (error) {
301
+ return {
302
+ available: false,
303
+ name: "None",
304
+ error: error instanceof Error ? error.message : String(error)
305
+ };
306
+ }
307
+ }
308
+
309
+ // src/kaspa-wasm-signer.ts
310
+ import {
311
+ calculateContentHash
312
+ } from "@hardkas/artifacts";
313
+ var KaspaWasmPrivateKeySigner = class {
314
+ constructor(options) {
315
+ this.options = options;
316
+ }
317
+ options;
318
+ kind = "kaspa-private-key";
319
+ async signTxPlan(input) {
320
+ const plan = input.planArtifact;
321
+ const account = this.options.account;
322
+ const sdk = await loadKaspaWasm();
323
+ assertSigningNetworkAllowed({
324
+ network: plan.networkId,
325
+ mode: plan.mode,
326
+ allowMainnet: this.options.allowMainnet
327
+ });
328
+ const pkValue = account.privateKeyEnv ? process.env[account.privateKeyEnv] : void 0;
329
+ if (!pkValue) {
330
+ throw new Error(`Missing required private key for account '${account.name}'.`);
331
+ }
332
+ try {
333
+ const privateKey = new sdk.PrivateKey(pkValue);
334
+ const utxos = plan.inputs.map((u) => {
335
+ if (!u.outpoint.transactionId || u.outpoint.index === void 0) {
336
+ throw new Error(`UTXO is missing transactionId or index. Re-run tx plan.`);
337
+ }
338
+ const spk = u.scriptPublicKey || "mock-script";
339
+ return new sdk.UtxoEntry(
340
+ BigInt(u.amountSompi),
341
+ spk,
342
+ u.outpoint.transactionId,
343
+ u.outpoint.index,
344
+ plan.from.address
345
+ );
346
+ });
347
+ const outputs = plan.outputs.map((o) => {
348
+ if (!o.address) throw new Error("Output is missing address.");
349
+ return new sdk.PaymentOutput(
350
+ new sdk.Address(o.address),
351
+ BigInt(o.amountSompi)
352
+ );
353
+ });
354
+ const changeAddress = plan.change?.address ? new sdk.Address(plan.change.address) : void 0;
355
+ const priorityFee = BigInt(plan.estimatedFeeSompi);
356
+ const unsignedTx = sdk.createTransaction(
357
+ utxos,
358
+ outputs,
359
+ changeAddress,
360
+ priorityFee
361
+ );
362
+ const signedTx = sdk.signTransaction(unsignedTx, [privateKey], true);
363
+ const rawTx = signedTx.serialize ? signedTx.serialize() : JSON.stringify(signedTx.toRpcTransaction());
364
+ return {
365
+ signatureKind: "kaspa-private-key",
366
+ signerAddress: account.address || privateKey.toAddress(plan.networkId).toString(),
367
+ signedTransaction: {
368
+ format: "hex",
369
+ payload: rawTx
370
+ },
371
+ txId: signedTx.id,
372
+ signature: {
373
+ // We use the txid as the signature identifier in the artifact
374
+ value: signedTx.id || calculateContentHash(plan)
375
+ }
376
+ };
377
+ } catch (error) {
378
+ throw new Error(`Kaspa WASM signing failed: ${error instanceof Error ? error.message : String(error)}`);
379
+ }
380
+ }
381
+ };
382
+ function assertSigningNetworkAllowed(input) {
383
+ const isMainnet = input.network === "mainnet";
384
+ if (isMainnet && !input.allowMainnet) {
385
+ throw new Error(
386
+ "Mainnet signing is disabled by default. Use --allow-mainnet-signing only if you understand the risks."
387
+ );
388
+ }
389
+ }
390
+
391
+ // src/signer.ts
392
+ var SimulatedTxPlanSigner = class {
393
+ kind = "simulated";
394
+ async signTxPlan(input) {
395
+ const plan = input.planArtifact;
396
+ return {
397
+ signatureKind: "simulated",
398
+ signerAddress: plan.from.address,
399
+ signedTransaction: {
400
+ format: "simulated",
401
+ payload: `simulated-signed-tx:${plan.planId}`
402
+ }
403
+ };
404
+ }
405
+ };
406
+ var UnsupportedRealKaspaSigner = class {
407
+ kind = "unsupported";
408
+ async signTxPlan(_input) {
409
+ throw new Error(
410
+ "Real Kaspa signing requires an official Kaspa transaction signing library. No supported signer backend is configured."
411
+ );
412
+ }
413
+ };
414
+ async function signTxPlanArtifact(input) {
415
+ const { planArtifact, account } = input;
416
+ if (planArtifact.schema === "hardkas.txPlan") {
417
+ } else if (planArtifact.status !== "built" && planArtifact.status !== "unsigned") {
418
+ throw new Error(`Cannot sign artifact with status: ${planArtifact.status}`);
419
+ }
420
+ if (planArtifact.mode === "simulated") {
421
+ if (account.kind !== "simulated") {
422
+ throw new Error(`Simulated plans must be signed with simulated accounts (account '${account.name}' is '${account.kind}').`);
423
+ }
424
+ } else {
425
+ if (account.kind === "simulated") {
426
+ throw new Error(`Real Kaspa transaction plans (mode: ${planArtifact.mode}) cannot be signed with simulated accounts.`);
427
+ }
428
+ }
429
+ if (planArtifact.networkId === "mainnet" && !input.allowMainnet) {
430
+ throw new Error("Mainnet signing is disabled by default. Use --allow-mainnet-signing only if you understand the risks.");
431
+ }
432
+ if (account.kind === "simulated") {
433
+ return createSimulatedSignedTxArtifact(
434
+ planArtifact,
435
+ `simulated-signed-tx:${planArtifact.planId}`
436
+ );
437
+ }
438
+ if (account.kind === "kaspa-private-key") {
439
+ const status = await getKaspaSigningBackendStatus();
440
+ if (!status.available) {
441
+ throw new Error(`Real Kaspa signing is not available: ${status.error || "Unknown error"}. Ensure 'kaspa' package is installed.`);
442
+ }
443
+ const signer = new KaspaWasmPrivateKeySigner({
444
+ account,
445
+ allowMainnet: input.allowMainnet
446
+ });
447
+ const result = await signer.signTxPlan({
448
+ planArtifact,
449
+ accountName: account.name
450
+ });
451
+ const artifact = {
452
+ schema: "hardkas.signedTx",
453
+ hardkasVersion: HARDKAS_VERSION2,
454
+ version: "1.0.0-alpha",
455
+ status: "signed",
456
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
457
+ signedId: `signed_${planArtifact.planId}_${Date.now().toString(36)}`,
458
+ txId: result.txId || "",
459
+ // Ensure txId is present
460
+ sourcePlanId: planArtifact.planId,
461
+ networkId: planArtifact.networkId,
462
+ mode: planArtifact.mode,
463
+ from: { address: planArtifact.from.address },
464
+ to: { address: planArtifact.to.address },
465
+ amountSompi: planArtifact.amountSompi,
466
+ signedTransaction: {
467
+ format: result.signedTransaction?.format === "hex" ? "hex" : "unknown",
468
+ payload: result.signedTransaction?.payload || ""
469
+ }
470
+ };
471
+ artifact.contentHash = calculateContentHash2(artifact);
472
+ return artifact;
473
+ }
474
+ if (account.kind === "external-wallet") {
475
+ throw new Error("External wallet signing is not implemented yet.");
476
+ }
477
+ if (account.kind === "evm-private-key") {
478
+ throw new Error("EVM accounts are reserved for future Igra support and cannot sign Kaspa L1 transactions.");
479
+ }
480
+ throw new Error(`Unsupported account kind for signing: ${account.kind}`);
481
+ }
482
+
483
+ // src/real-signer.ts
484
+ var UnsupportedRealTxSigner = class {
485
+ async sign() {
486
+ throw new Error(
487
+ "Real transaction signing is not configured yet. Install/configure a supported Kaspa SDK signer adapter."
488
+ );
489
+ }
490
+ };
491
+
492
+ // src/kaspa-sdk-real-signer.ts
493
+ var KaspaSdkRealTxSigner = class {
494
+ sdkLoader;
495
+ constructor(options) {
496
+ this.sdkLoader = options?.sdkLoader || loadKaspaWasm;
497
+ }
498
+ async sign(input) {
499
+ const { plan, account } = input;
500
+ let sdk;
501
+ try {
502
+ sdk = await this.sdkLoader();
503
+ } catch (e) {
504
+ throw new Error("Kaspa SDK real transaction signer dependency is not installed. Install/configure the supported Kaspa WASM SDK adapter.");
505
+ }
506
+ if (!sdk) {
507
+ throw new Error("Kaspa SDK real transaction signer dependency is not installed. Install/configure the supported Kaspa WASM SDK adapter.");
508
+ }
509
+ if (!account.privateKey) {
510
+ throw new Error("Account has no private key available for signing.");
511
+ }
512
+ if (plan.from.address !== account.address) {
513
+ throw new Error(`Address mismatch: Plan requires ${plan.from.address}, but account has ${account.address}.`);
514
+ }
515
+ try {
516
+ const privateKey = new sdk.PrivateKey(account.privateKey);
517
+ const utxos = plan.inputs.map((u) => {
518
+ if (!u.scriptPublicKey) {
519
+ throw new Error(`UTXO ${u.outpoint.transactionId}:${u.outpoint.index} is missing scriptPublicKey required for signing.`);
520
+ }
521
+ const spk = u.scriptPublicKey;
522
+ return new sdk.UtxoEntry(
523
+ BigInt(u.amountSompi),
524
+ spk,
525
+ u.outpoint.transactionId,
526
+ u.outpoint.index,
527
+ plan.from.address
528
+ );
529
+ });
530
+ const outputs = [
531
+ new sdk.PaymentOutput(
532
+ new sdk.Address(plan.to.address),
533
+ BigInt(plan.amountSompi)
534
+ )
535
+ ];
536
+ const changeAddress = plan.change ? new sdk.Address(plan.change.address) : void 0;
537
+ const priorityFee = BigInt(plan.estimatedFeeSompi);
538
+ const unsignedTx = sdk.createTransaction(
539
+ utxos,
540
+ outputs,
541
+ changeAddress,
542
+ priorityFee
543
+ );
544
+ const signedTx = sdk.signTransaction(unsignedTx, [privateKey], true);
545
+ const payload = signedTx.serialize ? signedTx.serialize() : JSON.stringify(signedTx.toRpcTransaction());
546
+ const txId = signedTx.id;
547
+ return {
548
+ signedTransaction: {
549
+ format: "kaspa-sdk",
550
+ payload
551
+ },
552
+ txId
553
+ };
554
+ } catch (e) {
555
+ const msg = e instanceof Error ? e.message : String(e);
556
+ if (msg.includes("is not a constructor") || msg.includes("is not a function")) {
557
+ throw new Error(`Kaspa SDK signer adapter could not find required transaction signing primitives: ${msg}`);
558
+ }
559
+ throw new Error(`Real transaction signing failed in Kaspa SDK: ${msg}`);
560
+ }
561
+ }
562
+ };
563
+
564
+ // src/real-keygen.ts
565
+ var UnsupportedKaspaKeyGenerator = class {
566
+ async generateAccount() {
567
+ throw new Error(
568
+ "Real Kaspa key generation is not configured. Install/configure a supported Kaspa SDK adapter."
569
+ );
570
+ }
571
+ };
572
+
573
+ // src/kaspa-sdk-keygen.ts
574
+ var KaspaSdkKeyGenerator = class {
575
+ networkId;
576
+ sdkLoader;
577
+ constructor(options) {
578
+ this.networkId = options?.networkId || "simnet";
579
+ const rawLoader = options?.sdkLoader || (async () => {
580
+ return await import("kaspa");
581
+ });
582
+ this.sdkLoader = async () => {
583
+ try {
584
+ return await rawLoader();
585
+ } catch (e) {
586
+ throw new Error(
587
+ "Kaspa SDK key generation dependency is not installed. Install/configure the supported Kaspa WASM SDK adapter. Use 'hardkas accounts real import' to add accounts manually for now."
588
+ );
589
+ }
590
+ };
591
+ }
592
+ async generateAccount(options) {
593
+ const sdk = await this.sdkLoader();
594
+ const network = options?.networkId || this.networkId;
595
+ try {
596
+ if (typeof sdk.PrivateKey === "function") {
597
+ const privKey = new sdk.PrivateKey();
598
+ const pubKey = privKey.toPublicKey();
599
+ const address = pubKey.toAddress(network).toString();
600
+ const privateKeyStr = privKey.toString();
601
+ const publicKeyStr = pubKey.toString();
602
+ return {
603
+ address,
604
+ publicKey: publicKeyStr,
605
+ privateKey: privateKeyStr
606
+ };
607
+ }
608
+ throw new Error("Loaded Kaspa SDK does not expose expected PrivateKey constructor.");
609
+ } catch (e) {
610
+ throw new Error(`Failed to generate account using SDK: ${e instanceof Error ? e.message : String(e)}`);
611
+ }
612
+ }
613
+ };
614
+
615
+ // src/keystore.ts
616
+ import fs3 from "fs";
617
+ import path3 from "path";
618
+ import crypto from "crypto";
619
+ import { argon2id } from "hash-wasm";
620
+ var KeystoreManager = class {
621
+ /**
622
+ * Keystore container format version. Separate from ARTIFACT_VERSION.
623
+ * This versions the encrypted keystore envelope, not HardKAS artifacts.
624
+ */
625
+ static KEYSTORE_FORMAT_VERSION = "2.0.0";
626
+ static KEYSTORE_FORMAT_TYPE = "hardkas.encryptedKeystore.v2";
627
+ /**
628
+ * Creates an encrypted keystore from a payload and password.
629
+ */
630
+ static async createEncryptedKeystore(payload, password, options) {
631
+ if (!password) throw new Error("Password cannot be empty.");
632
+ if (password.length < 8) throw new Error("Password must be at least 8 characters long.");
633
+ const salt = crypto.randomBytes(16);
634
+ const nonce = crypto.randomBytes(12);
635
+ const iterations = options.iterations || 3;
636
+ const memory = options.memory || 65536;
637
+ const parallelism = options.parallelism || 1;
638
+ const derivedKeyHex = await argon2id({
639
+ password,
640
+ salt,
641
+ parallelism,
642
+ iterations,
643
+ memorySize: memory,
644
+ hashLength: 32,
645
+ // 256 bits for AES-256
646
+ outputType: "hex"
647
+ });
648
+ const derivedKey = Buffer.from(derivedKeyHex, "hex");
649
+ const cipher = crypto.createCipheriv("aes-256-gcm", derivedKey, nonce);
650
+ const encryptedPayload = Buffer.concat([
651
+ cipher.update(JSON.stringify(payload), "utf8"),
652
+ cipher.final()
653
+ ]);
654
+ const tag = cipher.getAuthTag();
655
+ derivedKey.fill(0);
656
+ return {
657
+ version: this.KEYSTORE_FORMAT_VERSION,
658
+ type: this.KEYSTORE_FORMAT_TYPE,
659
+ kdf: {
660
+ algorithm: "argon2id",
661
+ memory,
662
+ iterations,
663
+ parallelism,
664
+ salt: salt.toString("base64")
665
+ },
666
+ cipher: {
667
+ algorithm: "aes-256-gcm",
668
+ nonce: nonce.toString("base64"),
669
+ tag: tag.toString("base64")
670
+ },
671
+ encryptedPayload: encryptedPayload.toString("base64"),
672
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
673
+ metadata: {
674
+ label: options.label,
675
+ network: options.network,
676
+ address: payload.address
677
+ }
678
+ };
679
+ }
680
+ /**
681
+ * Decrypts an encrypted keystore using a password.
682
+ */
683
+ static async decryptEncryptedKeystore(keystore, password) {
684
+ if (keystore.version !== this.KEYSTORE_FORMAT_VERSION) {
685
+ return { success: false, error: `Unsupported keystore version: ${keystore.version}` };
686
+ }
687
+ try {
688
+ const salt = Buffer.from(keystore.kdf.salt, "base64");
689
+ const nonce = Buffer.from(keystore.cipher.nonce, "base64");
690
+ const tag = Buffer.from(keystore.cipher.tag, "base64");
691
+ const encryptedData = Buffer.from(keystore.encryptedPayload, "base64");
692
+ const derivedKeyHex = await argon2id({
693
+ password,
694
+ salt,
695
+ parallelism: keystore.kdf.parallelism,
696
+ iterations: keystore.kdf.iterations,
697
+ memorySize: keystore.kdf.memory,
698
+ hashLength: 32,
699
+ outputType: "hex"
700
+ });
701
+ const derivedKey = Buffer.from(derivedKeyHex, "hex");
702
+ const decipher = crypto.createDecipheriv("aes-256-gcm", derivedKey, nonce);
703
+ decipher.setAuthTag(tag);
704
+ const decrypted = Buffer.concat([
705
+ decipher.update(encryptedData),
706
+ decipher.final()
707
+ ]);
708
+ derivedKey.fill(0);
709
+ const payload = JSON.parse(decrypted.toString("utf8"));
710
+ return { success: true, payload };
711
+ } catch (e) {
712
+ return { success: false, error: "Invalid password or corrupted keystore." };
713
+ }
714
+ }
715
+ /**
716
+ * Verifies if the password is correct for the keystore.
717
+ */
718
+ static async verifyKeystorePassword(keystore, password) {
719
+ const result = await this.decryptEncryptedKeystore(keystore, password);
720
+ return result.success;
721
+ }
722
+ /**
723
+ * Changes the password of an encrypted keystore.
724
+ */
725
+ static async changeKeystorePassword(keystore, oldPassword, newPassword) {
726
+ const unlock = await this.decryptEncryptedKeystore(keystore, oldPassword);
727
+ if (!unlock.success || !unlock.payload) {
728
+ throw new Error("Invalid current password.");
729
+ }
730
+ return this.createEncryptedKeystore(unlock.payload, newPassword, {
731
+ label: keystore.metadata.label,
732
+ network: keystore.metadata.network,
733
+ iterations: keystore.kdf.iterations,
734
+ memory: keystore.kdf.memory,
735
+ parallelism: keystore.kdf.parallelism
736
+ });
737
+ }
738
+ /**
739
+ * Loads an encrypted keystore from the filesystem.
740
+ */
741
+ static async loadEncryptedKeystore(filePath) {
742
+ try {
743
+ const data = await fs3.promises.readFile(filePath, "utf-8");
744
+ const keystore = JSON.parse(data);
745
+ if (keystore.type !== this.KEYSTORE_FORMAT_TYPE) {
746
+ throw new Error(`Invalid keystore type: ${keystore.type}`);
747
+ }
748
+ return keystore;
749
+ } catch (e) {
750
+ throw new Error(`Failed to load keystore at ${filePath}: ${e instanceof Error ? e.message : String(e)}`);
751
+ }
752
+ }
753
+ /**
754
+ * Saves an encrypted keystore to the filesystem.
755
+ */
756
+ static async saveEncryptedKeystore(filePath, keystore) {
757
+ try {
758
+ const dir = path3.dirname(filePath);
759
+ if (!fs3.existsSync(dir)) {
760
+ await fs3.promises.mkdir(dir, { recursive: true });
761
+ }
762
+ await fs3.promises.writeFile(filePath, JSON.stringify(keystore, null, 2), "utf-8");
763
+ } catch (e) {
764
+ throw new Error(`Failed to save keystore at ${filePath}: ${e instanceof Error ? e.message : String(e)}`);
765
+ }
766
+ }
767
+ };
768
+ export {
769
+ KaspaSdkKeyGenerator,
770
+ KaspaSdkRealTxSigner,
771
+ KaspaWasmPrivateKeySigner,
772
+ KeystoreManager,
773
+ SimulatedSigner,
774
+ SimulatedTxPlanSigner,
775
+ UnsupportedKaspaKeyGenerator,
776
+ UnsupportedRealKaspaSigner,
777
+ UnsupportedRealTxSigner,
778
+ assertSigningNetworkAllowed,
779
+ createEmptyRealAccountStore,
780
+ describeAccount,
781
+ getDefaultRealAccountsPath,
782
+ getKaspaSigningBackendStatus,
783
+ getRealDevAccount,
784
+ getRequiredEnv,
785
+ importRealDevAccount,
786
+ listHardkasAccounts,
787
+ listRealDevAccounts,
788
+ loadKaspaWasm,
789
+ loadOrCreateRealAccountStore,
790
+ loadRealAccountStore,
791
+ loadRealAccountStoreSync,
792
+ redactSecret,
793
+ removeRealDevAccount,
794
+ resolveHardkasAccount,
795
+ resolveHardkasAccountAddress,
796
+ resolveRealAccountOrAddress,
797
+ saveRealAccountStore,
798
+ signTxPlanArtifact,
799
+ validateAccountName,
800
+ validateAddressPrefix
801
+ };
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@hardkas/accounts",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.js",
10
+ "types": "./dist/index.d.ts"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "LICENSE",
16
+ "README.md"
17
+ ],
18
+ "dependencies": {
19
+ "hash-wasm": "^4.12.0",
20
+ "@hardkas/config": "0.1.0",
21
+ "@hardkas/localnet": "0.1.0",
22
+ "@hardkas/artifacts": "0.1.0",
23
+ "@hardkas/core": "0.1.0"
24
+ },
25
+ "devDependencies": {
26
+ "tsup": "^8.3.5",
27
+ "typescript": "^5.7.2",
28
+ "vitest": "^2.1.8"
29
+ },
30
+ "license": "MIT",
31
+ "author": "Javier Rodriguez",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/jrodrg92/Hardkas.git",
35
+ "directory": "packages/accounts"
36
+ },
37
+ "bugs": {
38
+ "url": "https://github.com/jrodrg92/Hardkas/issues"
39
+ },
40
+ "homepage": "https://github.com/jrodrg92/Hardkas/tree/main/packages/accounts#readme",
41
+ "scripts": {
42
+ "build": "tsup src/index.ts --format esm --dts --clean --external kaspa",
43
+ "dev": "tsup src/index.ts --format esm --watch --dts --external kaspa",
44
+ "test": "vitest run",
45
+ "typecheck": "tsc --noEmit"
46
+ }
47
+ }