@hardkas/sdk 0.8.16-alpha → 0.8.18-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/client.d.ts +84 -0
- package/dist/index.d.ts +443 -0
- package/dist/index.js +144 -9
- package/package.json +13 -13
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
interface HardkasClientOptions {
|
|
2
|
+
baseUrl?: string;
|
|
3
|
+
network?: string;
|
|
4
|
+
}
|
|
5
|
+
interface ClientEnvelope<T> {
|
|
6
|
+
ok: boolean;
|
|
7
|
+
data?: T;
|
|
8
|
+
error?: {
|
|
9
|
+
code: string;
|
|
10
|
+
message: string;
|
|
11
|
+
};
|
|
12
|
+
warnings: string[];
|
|
13
|
+
meta: {
|
|
14
|
+
workspace: string;
|
|
15
|
+
network: string;
|
|
16
|
+
mode?: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
declare function createHardkasClient(options?: HardkasClientOptions): {
|
|
20
|
+
accounts: {
|
|
21
|
+
list: () => Promise<ClientEnvelope<any[]>>;
|
|
22
|
+
};
|
|
23
|
+
tx: {
|
|
24
|
+
plan: (params: {
|
|
25
|
+
from: string;
|
|
26
|
+
to: string;
|
|
27
|
+
amountSompi: string;
|
|
28
|
+
feeRate?: string;
|
|
29
|
+
}) => Promise<ClientEnvelope<any>>;
|
|
30
|
+
sign: (params: {
|
|
31
|
+
planId: string;
|
|
32
|
+
account: string;
|
|
33
|
+
}) => Promise<ClientEnvelope<any>>;
|
|
34
|
+
send: (params: {
|
|
35
|
+
signedTxId?: string;
|
|
36
|
+
from?: string;
|
|
37
|
+
to?: string;
|
|
38
|
+
amountSompi?: string;
|
|
39
|
+
feeRate?: string;
|
|
40
|
+
allowDevAutoSign?: boolean;
|
|
41
|
+
}) => Promise<ClientEnvelope<any>>;
|
|
42
|
+
receipt: (id: string) => Promise<ClientEnvelope<any>>;
|
|
43
|
+
};
|
|
44
|
+
artifacts: {
|
|
45
|
+
explain: (id: string) => Promise<ClientEnvelope<any>>;
|
|
46
|
+
replay: (id: string) => Promise<ClientEnvelope<any>>;
|
|
47
|
+
watch: (callback: (artifact: any) => void, options?: {
|
|
48
|
+
type?: string;
|
|
49
|
+
lineage?: boolean;
|
|
50
|
+
replay?: boolean;
|
|
51
|
+
transport?: "sse" | "poll";
|
|
52
|
+
intervalMs?: number;
|
|
53
|
+
}) => () => void;
|
|
54
|
+
};
|
|
55
|
+
workflow: {
|
|
56
|
+
transfer: (params: {
|
|
57
|
+
from: string;
|
|
58
|
+
to: string;
|
|
59
|
+
amountSompi: string;
|
|
60
|
+
feeRate?: string;
|
|
61
|
+
allowDevAutoSign?: boolean;
|
|
62
|
+
}) => Promise<ClientEnvelope<any>>;
|
|
63
|
+
};
|
|
64
|
+
localnet: {
|
|
65
|
+
status: () => Promise<ClientEnvelope<any>>;
|
|
66
|
+
};
|
|
67
|
+
dev: {
|
|
68
|
+
status: () => Promise<ClientEnvelope<any>>;
|
|
69
|
+
};
|
|
70
|
+
session: {
|
|
71
|
+
start: () => Promise<ClientEnvelope<any>>;
|
|
72
|
+
snapshot: () => Promise<ClientEnvelope<any>>;
|
|
73
|
+
replay: (options?: {
|
|
74
|
+
untilArtifact?: string;
|
|
75
|
+
strict?: boolean;
|
|
76
|
+
}) => Promise<ClientEnvelope<any>>;
|
|
77
|
+
diffReplay: (artifactId: string) => Promise<ClientEnvelope<any>>;
|
|
78
|
+
timeTravel: (artifactId: string) => Promise<ClientEnvelope<any>>;
|
|
79
|
+
export: () => Promise<ClientEnvelope<any>>;
|
|
80
|
+
import: (data: any, force?: boolean) => Promise<ClientEnvelope<any>>;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export { type ClientEnvelope, type HardkasClientOptions, createHardkasClient };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import * as _hardkas_config from '@hardkas/config';
|
|
2
|
+
import { LoadedHardkasConfig } from '@hardkas/config';
|
|
3
|
+
export { defineHardkasConfig } from '@hardkas/config';
|
|
4
|
+
import { TxPlanArtifact, SignedTxArtifact, TxReceiptArtifact, HardkasArtifactBase, WorkflowArtifact, ExternalHardkasSigner } from '@hardkas/artifacts';
|
|
5
|
+
export { ARTIFACT_SCHEMAS, HARDKAS_VERSION, SignedTxArtifact, TxPlanArtifact, TxReceiptArtifact, TxTraceArtifact, createTxPlanArtifact, writeArtifact } from '@hardkas/artifacts';
|
|
6
|
+
import { KaspaRpcClient } from '@hardkas/kaspa-rpc';
|
|
7
|
+
import { EventEnvelope, NetworkId } from '@hardkas/core';
|
|
8
|
+
export { ArtifactId, HardkasError, KaspaAddress, LineageId, NetworkId, SOMPI_PER_KAS, TxId, formatSompi, parseKasToSompi } from '@hardkas/core';
|
|
9
|
+
import { HardkasAccount } from '@hardkas/accounts';
|
|
10
|
+
export { signTxPlanArtifact } from '@hardkas/accounts';
|
|
11
|
+
import { L2NetworkProfile } from '@hardkas/l2';
|
|
12
|
+
export { buildPaymentPlan } from '@hardkas/tx-builder';
|
|
13
|
+
export { ClientEnvelope, HardkasClientOptions, createHardkasClient } from './client.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* HardKAS Accounts Module
|
|
17
|
+
* @alpha
|
|
18
|
+
*/
|
|
19
|
+
declare class HardkasAccounts {
|
|
20
|
+
private sdk;
|
|
21
|
+
constructor(sdk: Hardkas);
|
|
22
|
+
/**
|
|
23
|
+
* Resolves an account by name or address.
|
|
24
|
+
*/
|
|
25
|
+
resolve(nameOrAddress: string): Promise<HardkasAccount>;
|
|
26
|
+
/**
|
|
27
|
+
* Fetches the balance for an account.
|
|
28
|
+
*/
|
|
29
|
+
getBalance(accountNameOrAddress: string): Promise<{
|
|
30
|
+
sompi: bigint;
|
|
31
|
+
formatted: string;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Alias for getBalance.
|
|
35
|
+
*/
|
|
36
|
+
balance(accountNameOrAddress: string): Promise<{
|
|
37
|
+
sompi: bigint;
|
|
38
|
+
formatted: string;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Lists all configured account names.
|
|
42
|
+
*/
|
|
43
|
+
list(): Promise<string[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Funds an account from another account (defaults to 'default' account).
|
|
46
|
+
*/
|
|
47
|
+
fund(accountNameOrAddress: string, options?: {
|
|
48
|
+
from?: string;
|
|
49
|
+
amount?: string | bigint;
|
|
50
|
+
}): Promise<any>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* HardKAS Transaction Module
|
|
55
|
+
* @alpha
|
|
56
|
+
*/
|
|
57
|
+
declare class HardkasTx {
|
|
58
|
+
private sdk;
|
|
59
|
+
constructor(sdk: Hardkas);
|
|
60
|
+
/**
|
|
61
|
+
* Plans a transaction.
|
|
62
|
+
*/
|
|
63
|
+
plan(options: {
|
|
64
|
+
from: string | HardkasAccount;
|
|
65
|
+
to: string | HardkasAccount;
|
|
66
|
+
amount: string | number | bigint;
|
|
67
|
+
feeRate?: bigint;
|
|
68
|
+
workflowId?: string;
|
|
69
|
+
policy?: string;
|
|
70
|
+
networkProfile?: string;
|
|
71
|
+
assumption?: string;
|
|
72
|
+
}): Promise<TxPlanArtifact>;
|
|
73
|
+
/**
|
|
74
|
+
* Creates a transaction plan explicitly for consolidation.
|
|
75
|
+
* This overrides normal selection logic and uses precisely the provided UTXOs.
|
|
76
|
+
*/
|
|
77
|
+
createConsolidationPlan(options: {
|
|
78
|
+
account: HardkasAccount | string;
|
|
79
|
+
selectedUtxos: any[];
|
|
80
|
+
destination: string;
|
|
81
|
+
network?: string;
|
|
82
|
+
feeRate?: bigint;
|
|
83
|
+
totalUtxosSeen?: number;
|
|
84
|
+
}): Promise<TxPlanArtifact>;
|
|
85
|
+
/**
|
|
86
|
+
* Signs a transaction plan.
|
|
87
|
+
*/
|
|
88
|
+
sign(plan: TxPlanArtifact | SignedTxArtifact, account?: HardkasAccount | string, options?: {
|
|
89
|
+
append?: boolean;
|
|
90
|
+
threshold?: number;
|
|
91
|
+
requiredSigners?: string[];
|
|
92
|
+
}): Promise<SignedTxArtifact>;
|
|
93
|
+
/**
|
|
94
|
+
* Simulates a transaction on the local state without broadcasting to a real Kaspa node.
|
|
95
|
+
* Modifies the local deterministic state and outputs receipt/trace artifacts.
|
|
96
|
+
*/
|
|
97
|
+
simulate(target: string | Partial<TxPlanArtifact> | SignedTxArtifact, options?: {
|
|
98
|
+
persist?: boolean;
|
|
99
|
+
}): Promise<{
|
|
100
|
+
receipt: TxReceiptArtifact;
|
|
101
|
+
receiptPath?: string;
|
|
102
|
+
tracePath?: string;
|
|
103
|
+
}>;
|
|
104
|
+
/**
|
|
105
|
+
* Sends a signed transaction to the real RPC network.
|
|
106
|
+
*/
|
|
107
|
+
send(signedArtifact: SignedTxArtifact, urlOrOptions?: string | {
|
|
108
|
+
persist?: boolean;
|
|
109
|
+
}): Promise<{
|
|
110
|
+
receipt: TxReceiptArtifact;
|
|
111
|
+
receiptPath?: string;
|
|
112
|
+
artifactId?: string;
|
|
113
|
+
mode?: string;
|
|
114
|
+
simulated?: boolean;
|
|
115
|
+
submitted?: boolean;
|
|
116
|
+
txId?: string;
|
|
117
|
+
}>;
|
|
118
|
+
/**
|
|
119
|
+
* Explicitly appends a signature to a partially signed transaction.
|
|
120
|
+
*/
|
|
121
|
+
appendSignature(plan: SignedTxArtifact, account?: HardkasAccount | string): Promise<SignedTxArtifact>;
|
|
122
|
+
/**
|
|
123
|
+
* Fetches the current status of a transaction by ID.
|
|
124
|
+
*/
|
|
125
|
+
status(txId: string): Promise<any>;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* HardKAS L2 Module
|
|
130
|
+
* @alpha
|
|
131
|
+
*/
|
|
132
|
+
declare class HardkasL2 {
|
|
133
|
+
/**
|
|
134
|
+
* Lists all available L2 network profiles.
|
|
135
|
+
*/
|
|
136
|
+
listProfiles(): readonly L2NetworkProfile[];
|
|
137
|
+
/**
|
|
138
|
+
* Gets a specific L2 network profile by name.
|
|
139
|
+
*/
|
|
140
|
+
getProfile(name: string): L2NetworkProfile | null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* HardKAS Operational Query Module
|
|
145
|
+
*
|
|
146
|
+
* Note: readEvents, correlate, and correlation types were removed from
|
|
147
|
+
* @hardkas/query. These will be re-implemented when the query API stabilizes.
|
|
148
|
+
* @alpha
|
|
149
|
+
*/
|
|
150
|
+
declare class HardkasQuery {
|
|
151
|
+
private sdk;
|
|
152
|
+
private _engine;
|
|
153
|
+
constructor(sdk: Hardkas);
|
|
154
|
+
/**
|
|
155
|
+
* Internal lazy-loaded query engine.
|
|
156
|
+
*/
|
|
157
|
+
private getEngine;
|
|
158
|
+
/**
|
|
159
|
+
* Synchronizes the query store with the filesystem artifacts.
|
|
160
|
+
*/
|
|
161
|
+
sync(options?: {
|
|
162
|
+
force?: boolean;
|
|
163
|
+
}): Promise<any>;
|
|
164
|
+
/**
|
|
165
|
+
* Fetches events from the query store.
|
|
166
|
+
*/
|
|
167
|
+
events(filter?: {
|
|
168
|
+
domain?: string;
|
|
169
|
+
kind?: string;
|
|
170
|
+
correlationId?: string;
|
|
171
|
+
artifactId?: string;
|
|
172
|
+
}): Promise<readonly EventEnvelope[]>;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* HardKAS Localnet Simulation Module
|
|
177
|
+
*/
|
|
178
|
+
declare class HardkasLocalnet {
|
|
179
|
+
private sdk;
|
|
180
|
+
constructor(sdk: Hardkas);
|
|
181
|
+
/**
|
|
182
|
+
* Status check for the localnet simulation.
|
|
183
|
+
*/
|
|
184
|
+
isAlive(): Promise<boolean>;
|
|
185
|
+
/**
|
|
186
|
+
* Future: control localnet process/container from here.
|
|
187
|
+
*/
|
|
188
|
+
start(): Promise<void>;
|
|
189
|
+
/**
|
|
190
|
+
* Resets the localnet state (simulated or node).
|
|
191
|
+
*/
|
|
192
|
+
reset(): Promise<void>;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
interface ReplayVerifyOptions {
|
|
196
|
+
path?: string;
|
|
197
|
+
workflowId?: string;
|
|
198
|
+
}
|
|
199
|
+
interface ReplayVerifyResult {
|
|
200
|
+
passed: boolean;
|
|
201
|
+
artifactsScanned: number;
|
|
202
|
+
lineage: "valid" | "invalid";
|
|
203
|
+
determinism: "verified" | "failed";
|
|
204
|
+
contamination: "clean" | "contaminated";
|
|
205
|
+
report: any;
|
|
206
|
+
error?: string;
|
|
207
|
+
}
|
|
208
|
+
declare class HardkasReplay {
|
|
209
|
+
private sdk;
|
|
210
|
+
constructor(sdk: Hardkas);
|
|
211
|
+
/**
|
|
212
|
+
* Verifies the deterministic artifact lineage of a transaction replay
|
|
213
|
+
* against the mathematically reconstructed localnet state.
|
|
214
|
+
*/
|
|
215
|
+
verify(targetOrOptions?: string | {
|
|
216
|
+
schema?: string;
|
|
217
|
+
artifactId?: string;
|
|
218
|
+
} | ReplayVerifyOptions, options?: ReplayVerifyOptions): Promise<ReplayVerifyResult>;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* HardKAS Lineage Module
|
|
223
|
+
* @alpha
|
|
224
|
+
*/
|
|
225
|
+
declare class HardkasLineage {
|
|
226
|
+
private sdk;
|
|
227
|
+
constructor(sdk: Hardkas);
|
|
228
|
+
/**
|
|
229
|
+
* Traces the lineage of an artifact, identifying ancestors and descendants.
|
|
230
|
+
*/
|
|
231
|
+
trace(target: string | {
|
|
232
|
+
artifactId?: string;
|
|
233
|
+
contentHash?: string;
|
|
234
|
+
}, options?: {
|
|
235
|
+
direction?: "ancestors" | "descendants";
|
|
236
|
+
}): Promise<any>;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Deterministic Workspace Abstraction.
|
|
241
|
+
* Encapsulates all filesystem boundary interactions and isolates paths
|
|
242
|
+
* from the global process.cwd(), ensuring agent/script replayability.
|
|
243
|
+
*/
|
|
244
|
+
declare class HardkasWorkspace {
|
|
245
|
+
readonly root: string;
|
|
246
|
+
constructor(cwd: string);
|
|
247
|
+
get hardkasDir(): string;
|
|
248
|
+
get artifactsDir(): string;
|
|
249
|
+
get localnetStatePath(): string;
|
|
250
|
+
get keystoreDir(): string;
|
|
251
|
+
/**
|
|
252
|
+
* Safely resolves a path relative to the workspace root.
|
|
253
|
+
*/
|
|
254
|
+
resolvePath(...segments: string[]): string;
|
|
255
|
+
/**
|
|
256
|
+
* Safely builds a relative path from the workspace root to the target.
|
|
257
|
+
*/
|
|
258
|
+
relativeFromRoot(absolutePath: string): string;
|
|
259
|
+
/**
|
|
260
|
+
* Ensures the core .hardkas directory exists.
|
|
261
|
+
*/
|
|
262
|
+
ensureHardkasDir(): void;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
interface WriteArtifactOptions {
|
|
266
|
+
/**
|
|
267
|
+
* Explicitly override the canonical artifacts directory.
|
|
268
|
+
* By default, it writes to sdk.workspace.artifactsDir.
|
|
269
|
+
*/
|
|
270
|
+
outputDir?: string;
|
|
271
|
+
/**
|
|
272
|
+
* Explicitly override the default filename.
|
|
273
|
+
* By default, it generates `${schema}-${contentHash}.json`
|
|
274
|
+
*/
|
|
275
|
+
fileName?: string;
|
|
276
|
+
/**
|
|
277
|
+
* If true, verifies integrity and schema but does not touch the filesystem.
|
|
278
|
+
* Useful for Agent planning or previews.
|
|
279
|
+
*/
|
|
280
|
+
dryRun?: boolean;
|
|
281
|
+
/** Telemetry for Event Sourcing */
|
|
282
|
+
workflowId?: string;
|
|
283
|
+
correlationId?: string;
|
|
284
|
+
networkId?: string;
|
|
285
|
+
}
|
|
286
|
+
interface WriteArtifactResult {
|
|
287
|
+
absolutePath?: string;
|
|
288
|
+
dryRun: boolean;
|
|
289
|
+
contentHash: string;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Deterministic Artifact I/O boundary.
|
|
293
|
+
*/
|
|
294
|
+
declare class HardkasArtifactsManager {
|
|
295
|
+
private workspace;
|
|
296
|
+
private cache;
|
|
297
|
+
constructor(workspace: HardkasWorkspace);
|
|
298
|
+
/**
|
|
299
|
+
* Caches an in-memory artifact.
|
|
300
|
+
*/
|
|
301
|
+
cacheArtifact(artifact: any): void;
|
|
302
|
+
/**
|
|
303
|
+
* Writes a valid artifact to disk (canonical or custom path).
|
|
304
|
+
*/
|
|
305
|
+
write(artifact: HardkasArtifactBase, options?: WriteArtifactOptions): Promise<WriteArtifactResult>;
|
|
306
|
+
/**
|
|
307
|
+
* Retrieves an artifact from the in-memory cache.
|
|
308
|
+
*/
|
|
309
|
+
getCached(id: string): any;
|
|
310
|
+
/**
|
|
311
|
+
* Reads an artifact by path or ID/hash from the workspace.
|
|
312
|
+
*/
|
|
313
|
+
read(id: string, options?: {
|
|
314
|
+
expectedSchema?: string;
|
|
315
|
+
}): Promise<any>;
|
|
316
|
+
/**
|
|
317
|
+
* Alias for read().
|
|
318
|
+
*/
|
|
319
|
+
get(id: string, options?: {
|
|
320
|
+
expectedSchema?: string;
|
|
321
|
+
}): Promise<any>;
|
|
322
|
+
/**
|
|
323
|
+
* Lists all artifacts in the workspace.
|
|
324
|
+
*/
|
|
325
|
+
list(): Promise<any[]>;
|
|
326
|
+
/**
|
|
327
|
+
* Cryptographically verifies the determinism and integrity of an artifact.
|
|
328
|
+
* Throws an error with details if corruption or mismatch is found.
|
|
329
|
+
*/
|
|
330
|
+
verify(target: any, options?: {
|
|
331
|
+
throwOnInvalid?: boolean;
|
|
332
|
+
strict?: boolean;
|
|
333
|
+
enforceMetadata?: boolean;
|
|
334
|
+
}): Promise<any>;
|
|
335
|
+
/**
|
|
336
|
+
* Migrates a legacy artifact to v4 using a migration receipt.
|
|
337
|
+
*/
|
|
338
|
+
migrate(target: any, migrationId: string): Promise<{
|
|
339
|
+
migrated: any;
|
|
340
|
+
receipt: any;
|
|
341
|
+
}>;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
interface WorkflowRunOptions {
|
|
345
|
+
steps: Array<{
|
|
346
|
+
type: string;
|
|
347
|
+
[key: string]: any;
|
|
348
|
+
}>;
|
|
349
|
+
dryRun?: boolean;
|
|
350
|
+
}
|
|
351
|
+
declare class HardkasWorkflow {
|
|
352
|
+
private readonly sdk;
|
|
353
|
+
constructor(sdk: Hardkas);
|
|
354
|
+
/**
|
|
355
|
+
* Executes a sequence of declarative steps and returns a definitive WorkflowArtifact.
|
|
356
|
+
*/
|
|
357
|
+
run(options: WorkflowRunOptions): Promise<WorkflowArtifact>;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
interface TaskArgs {
|
|
361
|
+
[key: string]: string | boolean | undefined;
|
|
362
|
+
}
|
|
363
|
+
interface TaskContext {
|
|
364
|
+
hardkas: Hardkas;
|
|
365
|
+
args: TaskArgs;
|
|
366
|
+
}
|
|
367
|
+
type TaskAction = (ctx: TaskContext) => Promise<void>;
|
|
368
|
+
/**
|
|
369
|
+
* Defines a new HardKAS task.
|
|
370
|
+
* Used in hardkas.config.ts to extend CLI functionality.
|
|
371
|
+
*/
|
|
372
|
+
declare const defineTask: {
|
|
373
|
+
(name: string, action: TaskAction): void;
|
|
374
|
+
(name: string, description: string, action: TaskAction): void;
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
interface HardkasOptions {
|
|
378
|
+
cwd?: string;
|
|
379
|
+
configPath?: string;
|
|
380
|
+
mode?: "developer" | "agent";
|
|
381
|
+
network?: string;
|
|
382
|
+
autoBootstrap?: boolean;
|
|
383
|
+
signer?: ExternalHardkasSigner;
|
|
384
|
+
logger?: {
|
|
385
|
+
info: (msg: string) => void;
|
|
386
|
+
warn: (msg: string) => void;
|
|
387
|
+
error: (msg: string) => void;
|
|
388
|
+
debug: (msg: string) => void;
|
|
389
|
+
[key: string]: any;
|
|
390
|
+
};
|
|
391
|
+
policy?: {
|
|
392
|
+
allowNetwork?: boolean;
|
|
393
|
+
allowMainnet?: boolean;
|
|
394
|
+
allowExternalWallet?: boolean;
|
|
395
|
+
requireDryRun?: boolean;
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* HardKAS SDK - Main Entry Point
|
|
400
|
+
*
|
|
401
|
+
* Provides a high-level facade for interacting with the Kaspa ecosystem.
|
|
402
|
+
* Acts as a DI container and coordinator.
|
|
403
|
+
*/
|
|
404
|
+
declare class Hardkas {
|
|
405
|
+
readonly config: LoadedHardkasConfig;
|
|
406
|
+
readonly workspace: HardkasWorkspace;
|
|
407
|
+
readonly artifacts: HardkasArtifactsManager;
|
|
408
|
+
readonly accounts: HardkasAccounts;
|
|
409
|
+
readonly tx: HardkasTx;
|
|
410
|
+
readonly l2: HardkasL2;
|
|
411
|
+
readonly query: HardkasQuery;
|
|
412
|
+
readonly localnet: HardkasLocalnet;
|
|
413
|
+
readonly replay: HardkasReplay;
|
|
414
|
+
readonly lineage: HardkasLineage;
|
|
415
|
+
readonly workflow: HardkasWorkflow;
|
|
416
|
+
readonly signer?: ExternalHardkasSigner | undefined;
|
|
417
|
+
readonly mode: "developer" | "agent";
|
|
418
|
+
readonly policy: Required<NonNullable<HardkasOptions["policy"]>>;
|
|
419
|
+
readonly rpc: KaspaRpcClient;
|
|
420
|
+
private constructor();
|
|
421
|
+
private resolveRpcUrl;
|
|
422
|
+
/**
|
|
423
|
+
* Opens a HardKAS project in the given directory.
|
|
424
|
+
*/
|
|
425
|
+
static open(dirOrOptions?: string | HardkasOptions): Promise<Hardkas>;
|
|
426
|
+
/**
|
|
427
|
+
* Alias for open(). Used in most examples.
|
|
428
|
+
*/
|
|
429
|
+
static create(dirOrOptions?: string | HardkasOptions): Promise<Hardkas>;
|
|
430
|
+
/**
|
|
431
|
+
* Current active network name.
|
|
432
|
+
*/
|
|
433
|
+
get network(): NetworkId;
|
|
434
|
+
get sdkConfig(): _hardkas_config.HardkasConfig;
|
|
435
|
+
get cwd(): string;
|
|
436
|
+
/**
|
|
437
|
+
* Validates an action against the active security policy.
|
|
438
|
+
* Throws HardkasError if the policy is violated.
|
|
439
|
+
*/
|
|
440
|
+
enforcePolicy(action: "network" | "mainnet" | "external-wallet" | "mutation", context?: string): void;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export { Hardkas, HardkasAccounts, HardkasArtifactsManager, HardkasL2, HardkasLineage, HardkasLocalnet, type HardkasOptions, HardkasQuery, HardkasReplay, HardkasTx, HardkasWorkspace, type TaskArgs, type TaskContext, defineTask };
|
package/dist/index.js
CHANGED
|
@@ -23,7 +23,7 @@ var HardkasAccounts = class {
|
|
|
23
23
|
async resolve(nameOrAddress) {
|
|
24
24
|
return resolveHardkasAccount({
|
|
25
25
|
nameOrAddress,
|
|
26
|
-
config: this.sdk.config.config
|
|
26
|
+
config: { ...this.sdk.config.config, cwd: this.sdk.workspace.root }
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
@@ -106,7 +106,7 @@ import {
|
|
|
106
106
|
getBroadcastableSignedTransaction
|
|
107
107
|
} from "@hardkas/artifacts";
|
|
108
108
|
import { coreEvents } from "@hardkas/core";
|
|
109
|
-
import { signTxPlanArtifact } from "@hardkas/accounts";
|
|
109
|
+
import { signTxPlanArtifact, validateAddressNetwork } from "@hardkas/accounts";
|
|
110
110
|
import { parseKasToSompi } from "@hardkas/core";
|
|
111
111
|
function normalizeSimulatedPlanInput(target, fallbackId) {
|
|
112
112
|
if (target.schema === ARTIFACT_SCHEMAS.TX_PLAN && Array.isArray(target.inputs)) {
|
|
@@ -158,15 +158,21 @@ var HardkasTx = class {
|
|
|
158
158
|
if (amountSompi === 0n) {
|
|
159
159
|
throw new Error("Kaspa value-transfer outputs require amount > 0.\nFor metadata/notary/DID marker transactions use --amount 1.\nFuture: hardkas tx anchor.");
|
|
160
160
|
}
|
|
161
|
-
let builderUtxos = [];
|
|
162
161
|
const activeNetwork = this.sdk.config.config.defaultNetwork || "simnet";
|
|
162
|
+
const allowMainnet = this.sdk.config.config.networks?.mainnet?.allowMainnet === true;
|
|
163
|
+
validateAddressNetwork(fromAccount.address, activeNetwork, allowMainnet);
|
|
164
|
+
validateAddressNetwork(toAccount.address, activeNetwork, allowMainnet);
|
|
165
|
+
if (options.changeAddress) {
|
|
166
|
+
validateAddressNetwork(options.changeAddress, activeNetwork, allowMainnet);
|
|
167
|
+
}
|
|
168
|
+
let allFetchedUtxos = [];
|
|
163
169
|
if (activeNetwork === "simulated" || this.sdk.config.config.networks?.[activeNetwork]?.kind === "simulated") {
|
|
164
170
|
const { loadOrCreateLocalnetState, getSpendableUtxos } = await import("@hardkas/localnet");
|
|
165
171
|
const localState = await loadOrCreateLocalnetState({
|
|
166
172
|
cwd: this.sdk.workspace.root
|
|
167
173
|
});
|
|
168
174
|
const unspent = getSpendableUtxos(localState, fromAccount.address);
|
|
169
|
-
|
|
175
|
+
allFetchedUtxos = unspent.map((u) => {
|
|
170
176
|
const parts = u.id.split(":");
|
|
171
177
|
const index = Number(parts[parts.length - 1]);
|
|
172
178
|
const transactionId = parts.slice(0, -1).join(":");
|
|
@@ -179,16 +185,52 @@ var HardkasTx = class {
|
|
|
179
185
|
});
|
|
180
186
|
} else {
|
|
181
187
|
const rpcUtxos = await this.sdk.rpc.getUtxosByAddress(fromAccount.address);
|
|
182
|
-
|
|
188
|
+
allFetchedUtxos = rpcUtxos.map((u) => ({
|
|
183
189
|
outpoint: {
|
|
184
190
|
transactionId: u.outpoint.transactionId,
|
|
185
191
|
index: u.outpoint.index
|
|
186
192
|
},
|
|
187
193
|
address: u.address,
|
|
188
|
-
amountSompi: u.amountSompi,
|
|
194
|
+
amountSompi: BigInt(u.amountSompi),
|
|
189
195
|
scriptPublicKey: u.scriptPublicKey || ""
|
|
190
196
|
}));
|
|
191
197
|
}
|
|
198
|
+
const sortedUtxos = [...allFetchedUtxos].sort((a, b) => {
|
|
199
|
+
if (a.amountSompi > b.amountSompi) return -1;
|
|
200
|
+
if (a.amountSompi < b.amountSompi) return 1;
|
|
201
|
+
return 0;
|
|
202
|
+
});
|
|
203
|
+
const MAX_INPUTS_PER_TX = 512;
|
|
204
|
+
const WARN_INPUTS = 128;
|
|
205
|
+
const HARD_LIMIT = 1e3;
|
|
206
|
+
const MARGIN_FEE_PER_INPUT = 1500n * (options.feeRate ?? 1n);
|
|
207
|
+
let selectedAmount = 0n;
|
|
208
|
+
let selectedInputsCount = 0;
|
|
209
|
+
const builderUtxos = [];
|
|
210
|
+
for (const utxo of sortedUtxos) {
|
|
211
|
+
builderUtxos.push(utxo);
|
|
212
|
+
selectedAmount += utxo.amountSompi;
|
|
213
|
+
selectedInputsCount++;
|
|
214
|
+
const requiredTotal = amountSompi + BigInt(selectedInputsCount) * MARGIN_FEE_PER_INPUT;
|
|
215
|
+
if (selectedAmount >= requiredTotal) {
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
if (selectedInputsCount >= HARD_LIMIT) {
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (selectedAmount < amountSompi) {
|
|
223
|
+
throw new Error(`Insufficient funds: needed ${amountSompi} sompi but only found ${selectedAmount} sompi across ${selectedInputsCount} UTXOs.`);
|
|
224
|
+
}
|
|
225
|
+
if (selectedInputsCount > MAX_INPUTS_PER_TX) {
|
|
226
|
+
const err = new Error(`TOO_MANY_INPUTS_FOR_SINGLE_TX: Transaction requires ${selectedInputsCount} inputs to cover the amount, which exceeds the safe limit of ${MAX_INPUTS_PER_TX} inputs.
|
|
227
|
+
Hint: Run 'hardkas accounts consolidate' to merge dust UTXOs.`);
|
|
228
|
+
err.code = "TOO_MANY_INPUTS_FOR_SINGLE_TX";
|
|
229
|
+
throw err;
|
|
230
|
+
}
|
|
231
|
+
if (selectedInputsCount >= WARN_INPUTS) {
|
|
232
|
+
console.warn(`\u26A0\uFE0F WARNING: Transaction requires ${selectedInputsCount} inputs. Consider running 'hardkas accounts consolidate'.`);
|
|
233
|
+
}
|
|
192
234
|
const builderPlan = buildPaymentPlan({
|
|
193
235
|
fromAddress: fromAccount.address,
|
|
194
236
|
availableUtxos: builderUtxos,
|
|
@@ -228,7 +270,12 @@ var HardkasTx = class {
|
|
|
228
270
|
ctx: {
|
|
229
271
|
...systemRuntimeContext,
|
|
230
272
|
...options.workflowId ? { workflowId: options.workflowId } : {},
|
|
231
|
-
assumptionLevel: resolvedAssumptionLevel
|
|
273
|
+
assumptionLevel: resolvedAssumptionLevel,
|
|
274
|
+
utxoSelection: {
|
|
275
|
+
totalUtxosSeen: allFetchedUtxos.length,
|
|
276
|
+
selectedUtxos: selectedInputsCount,
|
|
277
|
+
selectionStrategy: "largest-first"
|
|
278
|
+
}
|
|
232
279
|
}
|
|
233
280
|
});
|
|
234
281
|
if (options.policy || options.policies) {
|
|
@@ -281,6 +328,96 @@ var HardkasTx = class {
|
|
|
281
328
|
}
|
|
282
329
|
return basePlan;
|
|
283
330
|
}
|
|
331
|
+
/**
|
|
332
|
+
* Creates a transaction plan explicitly for consolidation.
|
|
333
|
+
* This overrides normal selection logic and uses precisely the provided UTXOs.
|
|
334
|
+
*/
|
|
335
|
+
async createConsolidationPlan(options) {
|
|
336
|
+
let resolvedAccount;
|
|
337
|
+
if (typeof options.account === "string") {
|
|
338
|
+
resolvedAccount = await this.sdk.accounts.resolve(options.account);
|
|
339
|
+
} else {
|
|
340
|
+
resolvedAccount = options.account;
|
|
341
|
+
}
|
|
342
|
+
if (!resolvedAccount.address) {
|
|
343
|
+
throw new Error(`Account '${resolvedAccount.name || options.account}' has no address.`);
|
|
344
|
+
}
|
|
345
|
+
const activeNetwork = options.network || this.sdk.config.config.defaultNetwork || "simnet";
|
|
346
|
+
const isSimulated = activeNetwork === "simulated" || this.sdk.config.config.networks?.[activeNetwork]?.kind === "simulated";
|
|
347
|
+
let totalAmount = 0n;
|
|
348
|
+
const builderUtxos = options.selectedUtxos.map((u) => {
|
|
349
|
+
const amount = BigInt(u.amountSompi);
|
|
350
|
+
totalAmount += amount;
|
|
351
|
+
return {
|
|
352
|
+
outpoint: {
|
|
353
|
+
transactionId: u.outpoint.transactionId,
|
|
354
|
+
index: u.outpoint.index
|
|
355
|
+
},
|
|
356
|
+
address: u.address,
|
|
357
|
+
amountSompi: amount,
|
|
358
|
+
scriptPublicKey: u.scriptPublicKey || ""
|
|
359
|
+
};
|
|
360
|
+
});
|
|
361
|
+
const feeRate = options.feeRate ?? 1n;
|
|
362
|
+
const massPerInput = 1500n;
|
|
363
|
+
const estimatedMass = BigInt(options.selectedUtxos.length) * massPerInput + 500n;
|
|
364
|
+
const expectedFee = estimatedMass * feeRate;
|
|
365
|
+
if (totalAmount <= expectedFee) {
|
|
366
|
+
throw new Error(`Consolidation failed: Total selected UTXO amount (${totalAmount}) is less than or equal to the estimated fee (${expectedFee}).`);
|
|
367
|
+
}
|
|
368
|
+
const outputAmount = totalAmount - expectedFee;
|
|
369
|
+
const builderPlan = buildPaymentPlan({
|
|
370
|
+
fromAddress: resolvedAccount.address,
|
|
371
|
+
availableUtxos: builderUtxos,
|
|
372
|
+
outputs: [
|
|
373
|
+
{
|
|
374
|
+
address: options.destination,
|
|
375
|
+
amountSompi: outputAmount
|
|
376
|
+
}
|
|
377
|
+
],
|
|
378
|
+
feeRateSompiPerMass: feeRate
|
|
379
|
+
});
|
|
380
|
+
let resolvedAssumptionLevel = isSimulated ? "local-simulated" : "local-rpc";
|
|
381
|
+
const basePlan = createTxPlanArtifact({
|
|
382
|
+
networkId: activeNetwork,
|
|
383
|
+
mode: isSimulated ? "simulated" : "real",
|
|
384
|
+
from: {
|
|
385
|
+
input: resolvedAccount.name || resolvedAccount.address,
|
|
386
|
+
address: resolvedAccount.address,
|
|
387
|
+
accountName: resolvedAccount.name
|
|
388
|
+
},
|
|
389
|
+
to: {
|
|
390
|
+
input: options.destination,
|
|
391
|
+
address: options.destination
|
|
392
|
+
},
|
|
393
|
+
amountSompi: outputAmount,
|
|
394
|
+
plan: builderPlan,
|
|
395
|
+
ctx: {
|
|
396
|
+
...systemRuntimeContext,
|
|
397
|
+
assumptionLevel: resolvedAssumptionLevel,
|
|
398
|
+
utxoSelection: {
|
|
399
|
+
strategy: "consolidation-smallest-first",
|
|
400
|
+
totalUtxosSeen: options.totalUtxosSeen ?? options.selectedUtxos.length,
|
|
401
|
+
selectedUtxos: options.selectedUtxos.length,
|
|
402
|
+
purpose: "wallet-consolidation"
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
const { CURRENT_HASH_VERSION: CURRENT_HASH_VERSION2, calculateContentHash: calculateContentHash2 } = await import("@hardkas/artifacts");
|
|
407
|
+
const newHash = calculateContentHash2(basePlan, CURRENT_HASH_VERSION2);
|
|
408
|
+
basePlan.contentHash = newHash;
|
|
409
|
+
if (basePlan.lineage) {
|
|
410
|
+
basePlan.lineage.lineageId = newHash;
|
|
411
|
+
basePlan.lineage.parentArtifactId = "";
|
|
412
|
+
basePlan.lineage.rootArtifactId = newHash;
|
|
413
|
+
const finalHash = calculateContentHash2(basePlan, CURRENT_HASH_VERSION2);
|
|
414
|
+
basePlan.contentHash = finalHash;
|
|
415
|
+
basePlan.lineage.artifactId = finalHash;
|
|
416
|
+
basePlan.planId = `plan-${finalHash.slice(0, 16)}`;
|
|
417
|
+
}
|
|
418
|
+
this.sdk.artifacts.cacheArtifact(basePlan);
|
|
419
|
+
return basePlan;
|
|
420
|
+
}
|
|
284
421
|
/**
|
|
285
422
|
* Signs a transaction plan.
|
|
286
423
|
*/
|
|
@@ -655,7 +792,6 @@ var HardkasTx = class {
|
|
|
655
792
|
...planArtifact.policyRefs ? { policyRefs: planArtifact.policyRefs } : {},
|
|
656
793
|
...planArtifact.networkProfileRef ? { networkProfileRef: planArtifact.networkProfileRef } : {},
|
|
657
794
|
...planArtifact.assumptionRef ? { assumptionRef: planArtifact.assumptionRef } : {},
|
|
658
|
-
sourceSignedId: signedId !== "unknown" ? signedId : void 0,
|
|
659
795
|
lineage: {
|
|
660
796
|
artifactId: "",
|
|
661
797
|
// To be computed
|
|
@@ -822,7 +958,6 @@ var HardkasTx = class {
|
|
|
822
958
|
...signedArtifact.policyRefs ? { policyRefs: signedArtifact.policyRefs } : {},
|
|
823
959
|
...signedArtifact.networkProfileRef ? { networkProfileRef: signedArtifact.networkProfileRef } : {},
|
|
824
960
|
...signedArtifact.assumptionRef ? { assumptionRef: signedArtifact.assumptionRef } : {},
|
|
825
|
-
sourceSignedId: signedArtifact.contentHash || signedArtifact.signedId,
|
|
826
961
|
tracePath: void 0,
|
|
827
962
|
lineage: createLineageTransition(signedArtifact, "hardkas.txReceipt")
|
|
828
963
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hardkas/sdk",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.18-alpha",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -24,18 +24,18 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@kaspa/core-lib": "^1.6.5",
|
|
27
|
-
"@hardkas/
|
|
28
|
-
"@hardkas/
|
|
29
|
-
"@hardkas/
|
|
30
|
-
"@hardkas/
|
|
31
|
-
"@hardkas/kaspa-rpc": "0.8.
|
|
32
|
-
"@hardkas/l2": "0.8.
|
|
33
|
-
"@hardkas/
|
|
34
|
-
"@hardkas/
|
|
35
|
-
"@hardkas/query": "0.8.
|
|
36
|
-
"@hardkas/
|
|
37
|
-
"@hardkas/
|
|
38
|
-
"@hardkas/wallet-adapter": "0.8.
|
|
27
|
+
"@hardkas/artifacts": "0.8.18-alpha",
|
|
28
|
+
"@hardkas/core": "0.8.18-alpha",
|
|
29
|
+
"@hardkas/config": "0.8.18-alpha",
|
|
30
|
+
"@hardkas/accounts": "0.8.18-alpha",
|
|
31
|
+
"@hardkas/kaspa-rpc": "0.8.18-alpha",
|
|
32
|
+
"@hardkas/l2": "0.8.18-alpha",
|
|
33
|
+
"@hardkas/query": "0.8.18-alpha",
|
|
34
|
+
"@hardkas/localnet": "0.8.18-alpha",
|
|
35
|
+
"@hardkas/query-store": "0.8.18-alpha",
|
|
36
|
+
"@hardkas/simulator": "0.8.18-alpha",
|
|
37
|
+
"@hardkas/tx-builder": "0.8.18-alpha",
|
|
38
|
+
"@hardkas/wallet-adapter": "0.8.18-alpha"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^20.12.7",
|