@hardkas/sdk 0.8.1-alpha → 0.8.3-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 +5 -6
- package/dist/index.js +120 -19
- package/package.json +13 -13
package/dist/index.d.ts
CHANGED
|
@@ -63,9 +63,12 @@ declare class HardkasTx {
|
|
|
63
63
|
plan(options: {
|
|
64
64
|
from: string | HardkasAccount;
|
|
65
65
|
to: string | HardkasAccount;
|
|
66
|
-
amount: string | bigint;
|
|
66
|
+
amount: string | number | bigint;
|
|
67
67
|
feeRate?: bigint;
|
|
68
68
|
workflowId?: string;
|
|
69
|
+
policy?: string;
|
|
70
|
+
networkProfile?: string;
|
|
71
|
+
assumption?: string;
|
|
69
72
|
}): Promise<TxPlanArtifact>;
|
|
70
73
|
/**
|
|
71
74
|
* Signs a transaction plan.
|
|
@@ -304,11 +307,7 @@ declare class HardkasArtifactsManager {
|
|
|
304
307
|
* Cryptographically verifies the determinism and integrity of an artifact.
|
|
305
308
|
* Throws an error with details if corruption or mismatch is found.
|
|
306
309
|
*/
|
|
307
|
-
verify(target:
|
|
308
|
-
schema?: string;
|
|
309
|
-
artifactId?: string;
|
|
310
|
-
contentHash?: string;
|
|
311
|
-
}, options?: {
|
|
310
|
+
verify(target: any, options?: {
|
|
312
311
|
throwOnInvalid?: boolean;
|
|
313
312
|
}): Promise<any>;
|
|
314
313
|
}
|
package/dist/index.js
CHANGED
|
@@ -153,7 +153,7 @@ var HardkasTx = class {
|
|
|
153
153
|
throw new Error(`From account ${fromAccount.name} has no address.`);
|
|
154
154
|
if (!toAccount.address)
|
|
155
155
|
throw new Error(`To account ${toAccount.name} has no address.`);
|
|
156
|
-
const amountSompi = typeof options.amount === "string" ? parseKasToSompi(options.amount) : typeof options.amount === "number" ?
|
|
156
|
+
const amountSompi = typeof options.amount === "string" ? parseKasToSompi(options.amount) : typeof options.amount === "number" ? parseKasToSompi(options.amount.toString()) : options.amount;
|
|
157
157
|
if (amountSompi === 0n) {
|
|
158
158
|
throw new Error("Kaspa value-transfer outputs require amount > 0.\nFor metadata/notary/DID marker transactions use --amount 1.\nFuture: hardkas tx anchor.");
|
|
159
159
|
}
|
|
@@ -200,7 +200,7 @@ var HardkasTx = class {
|
|
|
200
200
|
feeRateSompiPerMass: options.feeRate ?? 1n
|
|
201
201
|
});
|
|
202
202
|
const isSimulated = activeNetwork === "simulated" || this.sdk.config.config.networks?.[activeNetwork]?.kind === "simulated";
|
|
203
|
-
|
|
203
|
+
const basePlan = createTxPlanArtifact({
|
|
204
204
|
networkId: activeNetwork,
|
|
205
205
|
mode: isSimulated ? "simulated" : "real",
|
|
206
206
|
from: {
|
|
@@ -216,11 +216,52 @@ var HardkasTx = class {
|
|
|
216
216
|
plan: builderPlan,
|
|
217
217
|
ctx: options.workflowId ? { ...systemRuntimeContext, workflowId: options.workflowId } : systemRuntimeContext
|
|
218
218
|
});
|
|
219
|
+
if (options.policy) {
|
|
220
|
+
try {
|
|
221
|
+
const pol = await this.sdk.artifacts.read(options.policy);
|
|
222
|
+
basePlan.policyRef = pol.contentHash || pol.artifactId || options.policy;
|
|
223
|
+
} catch (e) {
|
|
224
|
+
basePlan.policyRef = options.policy;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (options.networkProfile) {
|
|
228
|
+
try {
|
|
229
|
+
const net = await this.sdk.artifacts.read(options.networkProfile);
|
|
230
|
+
basePlan.networkProfileRef = net.contentHash || net.artifactId || options.networkProfile;
|
|
231
|
+
} catch (e) {
|
|
232
|
+
basePlan.networkProfileRef = options.networkProfile;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (options.assumption) {
|
|
236
|
+
try {
|
|
237
|
+
const asm = await this.sdk.artifacts.read(options.assumption);
|
|
238
|
+
basePlan.assumptionRef = asm.contentHash || asm.artifactId || options.assumption;
|
|
239
|
+
} catch (e) {
|
|
240
|
+
basePlan.assumptionRef = options.assumption;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const { CURRENT_HASH_VERSION: CURRENT_HASH_VERSION2, calculateContentHash: calculateContentHash2 } = await import("@hardkas/artifacts");
|
|
244
|
+
const newHash = calculateContentHash2(basePlan, CURRENT_HASH_VERSION2);
|
|
245
|
+
basePlan.contentHash = newHash;
|
|
246
|
+
if (basePlan.lineage) {
|
|
247
|
+
basePlan.lineage.artifactId = newHash;
|
|
248
|
+
basePlan.lineage.parentArtifactId = newHash;
|
|
249
|
+
basePlan.lineage.rootArtifactId = newHash;
|
|
250
|
+
const finalHash = calculateContentHash2(basePlan, CURRENT_HASH_VERSION2);
|
|
251
|
+
basePlan.contentHash = finalHash;
|
|
252
|
+
basePlan.lineage.artifactId = finalHash;
|
|
253
|
+
basePlan.lineage.parentArtifactId = finalHash;
|
|
254
|
+
basePlan.lineage.rootArtifactId = finalHash;
|
|
255
|
+
}
|
|
256
|
+
return basePlan;
|
|
219
257
|
}
|
|
220
258
|
/**
|
|
221
259
|
* Signs a transaction plan.
|
|
222
260
|
*/
|
|
223
261
|
async sign(plan, account, options) {
|
|
262
|
+
if (typeof plan === "object" && plan !== null && plan.contentHash) {
|
|
263
|
+
await this.sdk.artifacts.verify(plan, { throwOnInvalid: true });
|
|
264
|
+
}
|
|
224
265
|
let resolvedAccount;
|
|
225
266
|
if (typeof account === "string") {
|
|
226
267
|
resolvedAccount = await this.sdk.accounts.resolve(account);
|
|
@@ -298,7 +339,7 @@ var HardkasTx = class {
|
|
|
298
339
|
lineage: {
|
|
299
340
|
artifactId: "",
|
|
300
341
|
// To be computed from contentHash
|
|
301
|
-
lineageId: partialTx.lineage?.lineageId ||
|
|
342
|
+
lineageId: partialTx.lineage?.lineageId || partialTx.contentHash || "0".repeat(64),
|
|
302
343
|
parentArtifactId: partialTx.contentHash || partialTx.signedId,
|
|
303
344
|
rootArtifactId: partialTx.lineage?.rootArtifactId || partialTx.sourcePlanId
|
|
304
345
|
}
|
|
@@ -382,7 +423,7 @@ var HardkasTx = class {
|
|
|
382
423
|
lineage: {
|
|
383
424
|
artifactId: "",
|
|
384
425
|
// To be computed
|
|
385
|
-
lineageId: plan.lineage?.lineageId ||
|
|
426
|
+
lineageId: plan.lineage?.lineageId || plan.contentHash || "0".repeat(64),
|
|
386
427
|
parentArtifactId: plan.contentHash || plan.planId,
|
|
387
428
|
rootArtifactId: plan.contentHash || plan.planId
|
|
388
429
|
},
|
|
@@ -401,6 +442,9 @@ var HardkasTx = class {
|
|
|
401
442
|
if (draft.lineage) draft.lineage.artifactId = draft.signedId;
|
|
402
443
|
signedArtifact = draft;
|
|
403
444
|
} else {
|
|
445
|
+
if (resolvedAccount.address !== plan.from.address) {
|
|
446
|
+
throw new Error(`Signer account '${resolvedAccount.address}' is not authorized to sign for '${plan.from.address}'.`);
|
|
447
|
+
}
|
|
404
448
|
signedArtifact = await signTxPlanArtifact({
|
|
405
449
|
planArtifact: plan,
|
|
406
450
|
account: resolvedAccount,
|
|
@@ -437,6 +481,9 @@ var HardkasTx = class {
|
|
|
437
481
|
* Modifies the local deterministic state and outputs receipt/trace artifacts.
|
|
438
482
|
*/
|
|
439
483
|
async simulate(target, options = {}) {
|
|
484
|
+
if (typeof target === "object" && target !== null && target.contentHash) {
|
|
485
|
+
await this.sdk.artifacts.verify(target, { throwOnInvalid: true });
|
|
486
|
+
}
|
|
440
487
|
const persist = options.persist ?? true;
|
|
441
488
|
const {
|
|
442
489
|
loadOrCreateLocalnetState,
|
|
@@ -537,9 +584,22 @@ var HardkasTx = class {
|
|
|
537
584
|
submittedAt: simResult.receipt.createdAt,
|
|
538
585
|
confirmedAt: simResult.receipt.createdAt,
|
|
539
586
|
rpcUrl: "simulated://local",
|
|
540
|
-
tracePath
|
|
587
|
+
tracePath,
|
|
588
|
+
lineage: {
|
|
589
|
+
artifactId: "",
|
|
590
|
+
// To be computed
|
|
591
|
+
lineageId: targetObj.lineage?.lineageId || targetObj.contentHash || "0".repeat(64),
|
|
592
|
+
parentArtifactId: targetObj.contentHash || "0".repeat(64),
|
|
593
|
+
rootArtifactId: targetObj.lineage?.rootArtifactId || "0".repeat(64),
|
|
594
|
+
sequence: (targetObj.lineage?.sequence || 1) + 1
|
|
595
|
+
}
|
|
541
596
|
};
|
|
542
597
|
receiptBase.contentHash = calculateContentHash(receiptBase, CURRENT_HASH_VERSION);
|
|
598
|
+
if (receiptBase.lineage) {
|
|
599
|
+
receiptBase.lineage.artifactId = receiptBase.contentHash;
|
|
600
|
+
receiptBase.contentHash = calculateContentHash(receiptBase, CURRENT_HASH_VERSION);
|
|
601
|
+
receiptBase.lineage.artifactId = receiptBase.contentHash;
|
|
602
|
+
}
|
|
543
603
|
const receipt = Object.freeze(receiptBase);
|
|
544
604
|
const traceSteps = events.map((ev) => ({
|
|
545
605
|
phase: ev.phase || ev.message || "unknown",
|
|
@@ -596,6 +656,9 @@ var HardkasTx = class {
|
|
|
596
656
|
* Sends a signed transaction to the real RPC network.
|
|
597
657
|
*/
|
|
598
658
|
async send(signedArtifact, urlOrOptions) {
|
|
659
|
+
if (typeof signedArtifact === "object" && signedArtifact !== null && signedArtifact.contentHash) {
|
|
660
|
+
await this.sdk.artifacts.verify(signedArtifact, { throwOnInvalid: true });
|
|
661
|
+
}
|
|
599
662
|
const verification = verifySignedTxSemantics(signedArtifact);
|
|
600
663
|
if (!verification.ok) {
|
|
601
664
|
throw new Error(
|
|
@@ -675,12 +738,26 @@ var HardkasTx = class {
|
|
|
675
738
|
feeSompi: signedArtifact.metadata?.estimatedFeeSompi || "0",
|
|
676
739
|
submittedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
677
740
|
...url ? { rpcUrl: url } : {},
|
|
678
|
-
...signedArtifact.workflowId ? { workflowId: signedArtifact.workflowId } : {}
|
|
741
|
+
...signedArtifact.workflowId ? { workflowId: signedArtifact.workflowId } : {},
|
|
742
|
+
tracePath: void 0,
|
|
743
|
+
lineage: {
|
|
744
|
+
artifactId: "",
|
|
745
|
+
// To be computed
|
|
746
|
+
lineageId: signedArtifact.lineage?.lineageId || signedArtifact.contentHash || "0".repeat(64),
|
|
747
|
+
parentArtifactId: signedArtifact.contentHash || "0".repeat(64),
|
|
748
|
+
rootArtifactId: signedArtifact.lineage?.rootArtifactId || "0".repeat(64),
|
|
749
|
+
sequence: (signedArtifact.lineage?.sequence || 1) + 1
|
|
750
|
+
}
|
|
679
751
|
};
|
|
680
752
|
realReceiptBase.contentHash = calculateContentHash(
|
|
681
753
|
realReceiptBase,
|
|
682
754
|
CURRENT_HASH_VERSION
|
|
683
755
|
);
|
|
756
|
+
if (realReceiptBase.lineage) {
|
|
757
|
+
realReceiptBase.lineage.artifactId = realReceiptBase.contentHash;
|
|
758
|
+
realReceiptBase.contentHash = calculateContentHash(realReceiptBase, CURRENT_HASH_VERSION);
|
|
759
|
+
realReceiptBase.lineage.artifactId = realReceiptBase.contentHash;
|
|
760
|
+
}
|
|
684
761
|
const receipt = realReceiptBase;
|
|
685
762
|
const receiptPath = getDefaultReceiptPath(receipt.txId, this.sdk.config.cwd);
|
|
686
763
|
await writeArtifact(receiptPath, receipt);
|
|
@@ -985,6 +1062,21 @@ var HardkasReplay = class {
|
|
|
985
1062
|
* against the mathematically reconstructed localnet state.
|
|
986
1063
|
*/
|
|
987
1064
|
async verify(targetOrOptions, options) {
|
|
1065
|
+
const throwOnInvalid = options?.throwOnInvalid !== false;
|
|
1066
|
+
if (typeof targetOrOptions === "object" && targetOrOptions !== null && targetOrOptions.contentHash) {
|
|
1067
|
+
const verifyRes = await this.sdk.artifacts.verify(targetOrOptions, { throwOnInvalid });
|
|
1068
|
+
if (!verifyRes.valid && !throwOnInvalid) {
|
|
1069
|
+
return {
|
|
1070
|
+
passed: false,
|
|
1071
|
+
artifactsScanned: 1,
|
|
1072
|
+
lineage: "invalid",
|
|
1073
|
+
determinism: "failed",
|
|
1074
|
+
contamination: "clean",
|
|
1075
|
+
report: null,
|
|
1076
|
+
error: `Artifact verification failed: ${verifyRes.reason}`
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
988
1080
|
let opts = options || {};
|
|
989
1081
|
if (typeof targetOrOptions === "string") {
|
|
990
1082
|
opts.path = targetOrOptions;
|
|
@@ -1368,29 +1460,38 @@ var HardkasArtifactsManager = class {
|
|
|
1368
1460
|
*/
|
|
1369
1461
|
async verify(target, options = {}) {
|
|
1370
1462
|
const throwOnInvalid = options.throwOnInvalid ?? true;
|
|
1371
|
-
const id = typeof target === "string" ? target : target.artifactId || target.contentHash || "";
|
|
1372
|
-
if (!id) {
|
|
1373
|
-
if (throwOnInvalid) throw new Error("No artifact target provided for verification.");
|
|
1374
|
-
return { valid: false, reason: "unknown", message: "No artifact target provided for verification." };
|
|
1375
|
-
}
|
|
1376
1463
|
let artifact;
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
if (
|
|
1381
|
-
|
|
1464
|
+
let id;
|
|
1465
|
+
if (typeof target === "string") {
|
|
1466
|
+
id = target;
|
|
1467
|
+
if (!id) {
|
|
1468
|
+
if (throwOnInvalid) throw new Error("No artifact target provided for verification.");
|
|
1469
|
+
return { valid: false, reason: "unknown", message: "No artifact target provided for verification." };
|
|
1470
|
+
}
|
|
1471
|
+
try {
|
|
1472
|
+
artifact = await this.read(id);
|
|
1473
|
+
} catch (e) {
|
|
1474
|
+
if (throwOnInvalid) throw e;
|
|
1475
|
+
return { valid: false, reason: "missing_artifact", message: e.message, artifactId: id };
|
|
1476
|
+
}
|
|
1477
|
+
} else {
|
|
1478
|
+
artifact = target;
|
|
1479
|
+
id = artifact.artifactId || artifact.contentHash || "";
|
|
1382
1480
|
}
|
|
1383
1481
|
const { verifyArtifactIntegrity: verifyArtifactIntegrity2 } = await import("@hardkas/artifacts");
|
|
1384
1482
|
const result = await verifyArtifactIntegrity2(artifact);
|
|
1385
1483
|
if (!result.ok) {
|
|
1484
|
+
const mappedReason = result.issues[0]?.code === "HASH_MISMATCH" ? "content_hash_mismatch" : result.issues[0]?.code === "MISSING_CONTENT_HASH" ? "missing_content_hash" : result.issues[0]?.code === "MISSING_SIGNATURE" ? "missing_signature" : "schema_invalid";
|
|
1386
1485
|
if (throwOnInvalid) {
|
|
1387
1486
|
throw new Error(`Artifact ${id} corrupted or invalid: ` + JSON.stringify(result.issues, null, 2));
|
|
1388
1487
|
}
|
|
1389
1488
|
return {
|
|
1390
1489
|
valid: false,
|
|
1391
|
-
reason:
|
|
1490
|
+
reason: mappedReason,
|
|
1392
1491
|
message: result.issues.map((i) => i.message).join(", "),
|
|
1393
1492
|
artifactId: id,
|
|
1493
|
+
expected: result.expectedHash,
|
|
1494
|
+
actual: result.actualHash,
|
|
1394
1495
|
details: result.issues
|
|
1395
1496
|
};
|
|
1396
1497
|
}
|
|
@@ -1733,8 +1834,8 @@ var Hardkas = class _Hardkas {
|
|
|
1733
1834
|
resolveRpcUrl() {
|
|
1734
1835
|
const networkId = this.config.config.defaultNetwork || "simnet";
|
|
1735
1836
|
const target = this.config.config.networks?.[networkId];
|
|
1736
|
-
if (target &&
|
|
1737
|
-
return target.rpcUrl
|
|
1837
|
+
if (target && "rpcUrl" in target && typeof target.rpcUrl === "string") {
|
|
1838
|
+
return target.rpcUrl;
|
|
1738
1839
|
}
|
|
1739
1840
|
return "ws://127.0.0.1:18210";
|
|
1740
1841
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hardkas/sdk",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3-alpha",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -23,18 +23,18 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@hardkas/artifacts": "0.8.
|
|
27
|
-
"@hardkas/accounts": "0.8.
|
|
28
|
-
"@hardkas/
|
|
29
|
-
"@hardkas/config": "0.8.
|
|
30
|
-
"@hardkas/
|
|
31
|
-
"@hardkas/l2": "0.8.
|
|
32
|
-
"@hardkas/
|
|
33
|
-
"@hardkas/
|
|
34
|
-
"@hardkas/
|
|
35
|
-
"@hardkas/
|
|
36
|
-
"@hardkas/
|
|
37
|
-
"@hardkas/
|
|
26
|
+
"@hardkas/artifacts": "0.8.3-alpha",
|
|
27
|
+
"@hardkas/accounts": "0.8.3-alpha",
|
|
28
|
+
"@hardkas/kaspa-rpc": "0.8.3-alpha",
|
|
29
|
+
"@hardkas/config": "0.8.3-alpha",
|
|
30
|
+
"@hardkas/core": "0.8.3-alpha",
|
|
31
|
+
"@hardkas/l2": "0.8.3-alpha",
|
|
32
|
+
"@hardkas/localnet": "0.8.3-alpha",
|
|
33
|
+
"@hardkas/simulator": "0.8.3-alpha",
|
|
34
|
+
"@hardkas/wallet-adapter": "0.8.3-alpha",
|
|
35
|
+
"@hardkas/query": "0.8.3-alpha",
|
|
36
|
+
"@hardkas/tx-builder": "0.8.3-alpha",
|
|
37
|
+
"@hardkas/query-store": "0.8.3-alpha"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"tsup": "^8.3.5",
|