@hardkas/artifacts 0.2.2-alpha.1 → 0.4.0-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 +115 -14
- package/dist/index.js +253 -92
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ArtifactType, NetworkId, ExecutionMode, ContentHash, WorkflowId, ArtifactId, LineageId, EventSequence, KaspaAddress,
|
|
1
|
+
import { ArtifactType, NetworkId, ExecutionMode, ContentHash, WorkflowId, ArtifactId, LineageId, EventSequence, TxId, KaspaAddress, CorruptionCode, CorruptionSeverity, EventEnvelope } from '@hardkas/core';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { TxOutput, Utxo, TxPlan as TxPlan$1 } from '@hardkas/tx-builder';
|
|
4
4
|
|
|
5
|
-
declare const HARDKAS_VERSION = "0.
|
|
5
|
+
declare const HARDKAS_VERSION = "0.4.0-alpha";
|
|
6
6
|
declare const ARTIFACT_SCHEMAS: {
|
|
7
7
|
readonly LOCALNET_STATE: "hardkas.localnetState.v1";
|
|
8
8
|
readonly REAL_ACCOUNT_STORE: "hardkas.realAccountStore.v1";
|
|
@@ -1058,6 +1058,7 @@ type Snapshot = z.infer<typeof SnapshotSchema>;
|
|
|
1058
1058
|
type TxReceipt = z.infer<typeof TxReceiptSchema>;
|
|
1059
1059
|
type SignedTx = z.infer<typeof SignedTxSchema>;
|
|
1060
1060
|
type TxTrace = z.infer<typeof TxTraceSchema>;
|
|
1061
|
+
type DagContext$1 = z.infer<typeof DagContextSchema>;
|
|
1061
1062
|
|
|
1062
1063
|
interface ArtifactValidationResult {
|
|
1063
1064
|
ok: boolean;
|
|
@@ -1385,18 +1386,70 @@ interface TxTraceArtifact extends BaseArtifact<"txTrace"> {
|
|
|
1385
1386
|
dagContext?: DagContext | undefined;
|
|
1386
1387
|
}
|
|
1387
1388
|
|
|
1389
|
+
interface DeploymentRecord extends HardkasArtifactBase {
|
|
1390
|
+
schema: "hardkas.deployment.v1";
|
|
1391
|
+
/** Human-readable label (e.g., "initial-funding", "vault-covenant-v1") */
|
|
1392
|
+
label: string;
|
|
1393
|
+
/** Network where this was deployed */
|
|
1394
|
+
networkId: NetworkId;
|
|
1395
|
+
/** Deployment status */
|
|
1396
|
+
status: "planned" | "sent" | "confirmed" | "failed" | "unknown";
|
|
1397
|
+
/** The transaction ID (if sent) */
|
|
1398
|
+
txId?: TxId;
|
|
1399
|
+
/** Reference to the plan artifact that produced this deployment */
|
|
1400
|
+
planArtifactId?: ArtifactId;
|
|
1401
|
+
/** Reference to the receipt artifact (if confirmed) */
|
|
1402
|
+
receiptArtifactId?: ArtifactId;
|
|
1403
|
+
/** Deployed addresses or outputs (for covenant/contract deployments) */
|
|
1404
|
+
deployedAddresses?: string[];
|
|
1405
|
+
/** Deployment metadata */
|
|
1406
|
+
deployer?: string;
|
|
1407
|
+
/** Content hash of the deployed payload (bytecode, script, or tx content) */
|
|
1408
|
+
payloadHash?: string;
|
|
1409
|
+
/** Timestamp of deployment */
|
|
1410
|
+
deployedAt: string;
|
|
1411
|
+
/** HardKAS version used */
|
|
1412
|
+
hardkasVersion: string;
|
|
1413
|
+
/** Canonical content hash of this record */
|
|
1414
|
+
contentHash?: ContentHash;
|
|
1415
|
+
/** Notes */
|
|
1416
|
+
notes?: string;
|
|
1417
|
+
}
|
|
1418
|
+
interface DeploymentIndex extends HardkasArtifactBase {
|
|
1419
|
+
schema: "hardkas.deploymentIndex.v1";
|
|
1420
|
+
networkId: NetworkId;
|
|
1421
|
+
deployments: DeploymentSummary[];
|
|
1422
|
+
lastUpdated: string;
|
|
1423
|
+
}
|
|
1424
|
+
interface DeploymentSummary {
|
|
1425
|
+
label: string;
|
|
1426
|
+
networkId: NetworkId;
|
|
1427
|
+
status: string;
|
|
1428
|
+
txId?: string;
|
|
1429
|
+
deployedAt: string;
|
|
1430
|
+
contentHash: string;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
declare const SEMANTIC_EXCLUSIONS: Set<string>;
|
|
1434
|
+
/**
|
|
1435
|
+
* Current canonicalization version.
|
|
1436
|
+
* v1: BigInt(123) -> "123" (Collision with String "123")
|
|
1437
|
+
* v2: BigInt(123) -> "n:123" (Distinguishable)
|
|
1438
|
+
* v3: String normalization (\r\n -> \n, NFC) for cross-platform stability.
|
|
1439
|
+
*/
|
|
1440
|
+
declare const CURRENT_HASH_VERSION = 3;
|
|
1388
1441
|
/**
|
|
1389
1442
|
* Deterministically stringifies an object by sorting keys recursively.
|
|
1390
|
-
* Handles BigInt by converting to string.
|
|
1391
|
-
* Excludes
|
|
1443
|
+
* Handles BigInt by converting to string with type marker.
|
|
1444
|
+
* Excludes fields in SEMANTIC_EXCLUSIONS during serialization.
|
|
1392
1445
|
* Skips keys with undefined values (matching JSON.stringify behavior).
|
|
1393
1446
|
*/
|
|
1394
|
-
declare function canonicalStringify(obj: any): string;
|
|
1447
|
+
declare function canonicalStringify(obj: any, version?: number): string;
|
|
1395
1448
|
/**
|
|
1396
1449
|
* Calculates a SHA-256 hash of the canonical JSON representation.
|
|
1397
|
-
* Always excludes
|
|
1450
|
+
* Always excludes fields in SEMANTIC_EXCLUSIONS from the calculation.
|
|
1398
1451
|
*/
|
|
1399
|
-
declare function calculateContentHash(obj: any): string;
|
|
1452
|
+
declare function calculateContentHash(obj: any, version?: number): string;
|
|
1400
1453
|
|
|
1401
1454
|
interface Clock {
|
|
1402
1455
|
now(): number;
|
|
@@ -1408,12 +1461,13 @@ interface VerificationContext {
|
|
|
1408
1461
|
networkId?: NetworkId;
|
|
1409
1462
|
parent?: unknown;
|
|
1410
1463
|
}
|
|
1411
|
-
type VerificationSeverity =
|
|
1464
|
+
type VerificationSeverity = CorruptionSeverity | "info" | "critical";
|
|
1412
1465
|
type VerificationIssue = {
|
|
1413
|
-
code: string;
|
|
1466
|
+
code: CorruptionCode | string;
|
|
1414
1467
|
severity: VerificationSeverity;
|
|
1415
1468
|
message: string;
|
|
1416
1469
|
path?: string | undefined;
|
|
1470
|
+
pathStr?: string | undefined;
|
|
1417
1471
|
artifactId?: string | undefined;
|
|
1418
1472
|
};
|
|
1419
1473
|
type ArtifactVerificationResult = {
|
|
@@ -1428,7 +1482,7 @@ type ArtifactVerificationResult = {
|
|
|
1428
1482
|
/**
|
|
1429
1483
|
* Sorts UTXOs deterministically by outpoint (transactionId:index).
|
|
1430
1484
|
*/
|
|
1431
|
-
declare function sortUtxosByOutpoint(utxos:
|
|
1485
|
+
declare function sortUtxosByOutpoint<T>(utxos: T[]): T[];
|
|
1432
1486
|
/**
|
|
1433
1487
|
* Verifies an artifact's integrity.
|
|
1434
1488
|
* Can take a raw object or a file path.
|
|
@@ -1440,9 +1494,9 @@ declare function verifyArtifactIntegrity(artifactOrPath: unknown): Promise<Artif
|
|
|
1440
1494
|
declare function verifyArtifactSemantics(artifact: unknown, context?: VerificationContext): ArtifactVerificationResult;
|
|
1441
1495
|
/**
|
|
1442
1496
|
* Verifies an artifact's replay consistency.
|
|
1443
|
-
*
|
|
1497
|
+
* Honest implementation: reports as unsupported or not implemented.
|
|
1444
1498
|
*/
|
|
1445
|
-
declare function verifyArtifactReplay(artifact: unknown,
|
|
1499
|
+
declare function verifyArtifactReplay(artifact: unknown, _context?: VerificationContext): Promise<ArtifactVerificationResult>;
|
|
1446
1500
|
/**
|
|
1447
1501
|
* @deprecated Use verifyArtifactIntegrity instead.
|
|
1448
1502
|
*/
|
|
@@ -1651,6 +1705,9 @@ declare function createSimulatedTxReceipt(plan: TxPlan, txId: string, extra?: {
|
|
|
1651
1705
|
spentUtxoIds?: string[];
|
|
1652
1706
|
createdUtxoIds?: string[];
|
|
1653
1707
|
daaScore?: string;
|
|
1708
|
+
preStateHash?: string;
|
|
1709
|
+
postStateHash?: string;
|
|
1710
|
+
dagContext?: DagContext$1;
|
|
1654
1711
|
}): TxReceipt;
|
|
1655
1712
|
/**
|
|
1656
1713
|
* Validates and extracts the raw transaction from a signed artifact.
|
|
@@ -1748,9 +1805,53 @@ interface LineageValidationResult {
|
|
|
1748
1805
|
ok: boolean;
|
|
1749
1806
|
issues: VerificationIssue[];
|
|
1750
1807
|
}
|
|
1808
|
+
interface LineageOptions {
|
|
1809
|
+
strict?: boolean;
|
|
1810
|
+
}
|
|
1751
1811
|
/**
|
|
1752
1812
|
* Validates the lineage relationship between an artifact and its parent.
|
|
1753
1813
|
*/
|
|
1754
|
-
declare function verifyLineage(artifact: any, parent?: any): LineageValidationResult;
|
|
1814
|
+
declare function verifyLineage(artifact: any, parent?: any, options?: LineageOptions): LineageValidationResult;
|
|
1815
|
+
|
|
1816
|
+
interface DiffEntry {
|
|
1817
|
+
path: string;
|
|
1818
|
+
kind: "added" | "removed" | "changed";
|
|
1819
|
+
left?: any;
|
|
1820
|
+
right?: any;
|
|
1821
|
+
}
|
|
1822
|
+
interface ArtifactDiff {
|
|
1823
|
+
identical: boolean;
|
|
1824
|
+
entries: DiffEntry[];
|
|
1825
|
+
}
|
|
1826
|
+
/**
|
|
1827
|
+
* Performs a semantic diff between two artifacts, ignoring volatile metadata.
|
|
1828
|
+
* Uses the same exclusion rules as canonical hashing.
|
|
1829
|
+
* Redacts secrets from the output.
|
|
1830
|
+
*/
|
|
1831
|
+
declare function diffArtifacts(left: any, right: any): ArtifactDiff;
|
|
1832
|
+
|
|
1833
|
+
declare function createDeploymentRecord(opts: {
|
|
1834
|
+
label: string;
|
|
1835
|
+
networkId: NetworkId;
|
|
1836
|
+
status?: "planned" | "sent" | "confirmed" | "failed" | "unknown";
|
|
1837
|
+
txId?: TxId;
|
|
1838
|
+
planArtifactId?: ArtifactId;
|
|
1839
|
+
receiptArtifactId?: ArtifactId;
|
|
1840
|
+
deployedAddresses?: string[];
|
|
1841
|
+
deployer?: string;
|
|
1842
|
+
payloadHash?: string;
|
|
1843
|
+
notes?: string;
|
|
1844
|
+
}): DeploymentRecord;
|
|
1845
|
+
declare function updateDeploymentStatus(record: DeploymentRecord, newStatus: DeploymentRecord["status"], txId?: TxId): DeploymentRecord;
|
|
1846
|
+
|
|
1847
|
+
/**
|
|
1848
|
+
* Manages deployment records on the filesystem.
|
|
1849
|
+
* Storage: .hardkas/deployments/<networkId>/<label>.json
|
|
1850
|
+
*/
|
|
1851
|
+
declare function saveDeployment(rootDir: string, record: DeploymentRecord): Promise<string>;
|
|
1852
|
+
declare function loadDeployment(rootDir: string, networkId: string, label: string): Promise<DeploymentRecord | null>;
|
|
1853
|
+
declare function listDeployments(rootDir: string, networkId?: string): Promise<DeploymentSummary[]>;
|
|
1854
|
+
declare function updateDeployment(rootDir: string, networkId: string, label: string, update: Partial<DeploymentRecord>): Promise<DeploymentRecord>;
|
|
1855
|
+
declare function deleteDeployment(rootDir: string, networkId: string, label: string): Promise<boolean>;
|
|
1755
1856
|
|
|
1756
|
-
export { ARTIFACT_SCHEMAS, ARTIFACT_VERSION, AccountRefSchema, type ArtifactExplanation, ArtifactLineageSchema, type ArtifactLookup, type ArtifactValidationResult, type ArtifactVerificationResult, type AssumptionLevel, type BaseArtifact, BaseArtifactSchema, BasicCorrelationInvariant, BasicLineageInvariant, type Clock, type CreateTxPlanArtifactOptions, type DagContext, DagContextSchema, type FeeAuditResult, HARDKAS_VERSION, type HardkasArtifactBase, type HardkasArtifactMode, type HardkasArtifactSchema, HashInvariant, type IgraSignedTxArtifact, type IgraTxPlanArtifact, type IgraTxReceiptArtifact, type IgraTxRequestArtifact, type Invariant, type InvariantContext, type InvariantViolation, InvariantWatcher, LifecycleInvariant, type LineageValidationResult, LocalnetUtxoSchemaV2, NetworkInvariant, ReplayInvariant, SchemaInvariant, type SignedTx, type SignedTxArtifact, type SignedTxArtifactV1, SignedTxSchema, type Snapshot, type SnapshotArtifact, SnapshotSchema, type TxOutputArtifact, type TxPlan, type TxPlanArtifact, type TxPlanArtifactV1, TxPlanSchema, type TxReceipt, type TxReceiptArtifact, type TxReceiptArtifactV1, TxReceiptSchema, type TxTrace, type TxTraceArtifact, type TxTraceArtifactV1, TxTraceSchema, type UtxoArtifact, type VerificationContext, type VerificationIssue, type VerificationSeverity, type WatcherOptions, assertDecimalBigIntString, assertEvmAddress, assertEvmTxHash, assertHexData, assertValidIgraSignedTxArtifact, assertValidIgraTxPlanArtifact, assertValidIgraTxReceiptArtifact, assertValidSignedTxArtifact, assertValidTxPlanArtifact, assertValidTxReceiptArtifact, bigIntReplacer, calculateContentHash, canonicalStringify, createIgraDeployPlanId, createIgraPlanId, createIgraSignedId, createSimulatedSignedTxArtifact, createSimulatedTxReceipt, createTxPlanArtifact, defaultClock, explainArtifact, formatSignedTxArtifact, formatTxPlanArtifact, formatTxReceiptArtifact, getBroadcastableSignedTransaction, getDefaultL2ReceiptsDir, getDefaultReceiptPath, getL2ReceiptPath, isIgraTxPlanArtifact, listIgraTxReceiptArtifacts, loadIgraTxReceiptArtifact, migrateToCanonical, readArtifact, readSignedTxArtifact, readTxPlanArtifact, readTxReceiptArtifact, recomputeMass, saveIgraTxReceiptArtifact, sortUtxosByOutpoint, txOutputFromArtifact, txOutputToArtifact, utxoFromArtifact, utxoToArtifact, validateArtifact, validateIgraSignedTxArtifact, validateIgraTxPlanArtifact, validateIgraTxReceiptArtifact, validateSignedTxArtifact, validateTxPlanArtifact, validateTxReceiptArtifact, verifyArtifact, verifyArtifactFile, verifyArtifactIntegrity, verifyArtifactReplay, verifyArtifactSemantics, verifyFeeSemantics, verifyLineage, writeArtifact };
|
|
1857
|
+
export { ARTIFACT_SCHEMAS, ARTIFACT_VERSION, AccountRefSchema, type ArtifactDiff, type ArtifactExplanation, ArtifactLineageSchema, type ArtifactLookup, type ArtifactValidationResult, type ArtifactVerificationResult, type AssumptionLevel, type BaseArtifact, BaseArtifactSchema, BasicCorrelationInvariant, BasicLineageInvariant, CURRENT_HASH_VERSION, type Clock, type CreateTxPlanArtifactOptions, type DagContext, DagContextSchema, type DeploymentIndex, type DeploymentRecord, type DeploymentSummary, type DiffEntry, type FeeAuditResult, HARDKAS_VERSION, type HardkasArtifactBase, type HardkasArtifactMode, type HardkasArtifactSchema, HashInvariant, type IgraSignedTxArtifact, type IgraTxPlanArtifact, type IgraTxReceiptArtifact, type IgraTxRequestArtifact, type Invariant, type InvariantContext, type InvariantViolation, InvariantWatcher, LifecycleInvariant, type LineageOptions, type LineageValidationResult, LocalnetUtxoSchemaV2, NetworkInvariant, ReplayInvariant, SEMANTIC_EXCLUSIONS, SchemaInvariant, type SignedTx, type SignedTxArtifact, type SignedTxArtifactV1, SignedTxSchema, type Snapshot, type SnapshotArtifact, SnapshotSchema, type TxOutputArtifact, type TxPlan, type TxPlanArtifact, type TxPlanArtifactV1, TxPlanSchema, type TxReceipt, type TxReceiptArtifact, type TxReceiptArtifactV1, TxReceiptSchema, type TxTrace, type TxTraceArtifact, type TxTraceArtifactV1, TxTraceSchema, type UtxoArtifact, type VerificationContext, type VerificationIssue, type VerificationSeverity, type WatcherOptions, assertDecimalBigIntString, assertEvmAddress, assertEvmTxHash, assertHexData, assertValidIgraSignedTxArtifact, assertValidIgraTxPlanArtifact, assertValidIgraTxReceiptArtifact, assertValidSignedTxArtifact, assertValidTxPlanArtifact, assertValidTxReceiptArtifact, bigIntReplacer, calculateContentHash, canonicalStringify, createDeploymentRecord, createIgraDeployPlanId, createIgraPlanId, createIgraSignedId, createSimulatedSignedTxArtifact, createSimulatedTxReceipt, createTxPlanArtifact, defaultClock, deleteDeployment, diffArtifacts, explainArtifact, formatSignedTxArtifact, formatTxPlanArtifact, formatTxReceiptArtifact, getBroadcastableSignedTransaction, getDefaultL2ReceiptsDir, getDefaultReceiptPath, getL2ReceiptPath, isIgraTxPlanArtifact, listDeployments, listIgraTxReceiptArtifacts, loadDeployment, loadIgraTxReceiptArtifact, migrateToCanonical, readArtifact, readSignedTxArtifact, readTxPlanArtifact, readTxReceiptArtifact, recomputeMass, saveDeployment, saveIgraTxReceiptArtifact, sortUtxosByOutpoint, txOutputFromArtifact, txOutputToArtifact, updateDeployment, updateDeploymentStatus, utxoFromArtifact, utxoToArtifact, validateArtifact, validateIgraSignedTxArtifact, validateIgraTxPlanArtifact, validateIgraTxReceiptArtifact, validateSignedTxArtifact, validateTxPlanArtifact, validateTxReceiptArtifact, verifyArtifact, verifyArtifactFile, verifyArtifactIntegrity, verifyArtifactReplay, verifyArtifactSemantics, verifyFeeSemantics, verifyLineage, writeArtifact };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/constants.ts
|
|
2
|
-
var HARDKAS_VERSION = "0.
|
|
2
|
+
var HARDKAS_VERSION = "0.4.0-alpha";
|
|
3
3
|
var ARTIFACT_SCHEMAS = {
|
|
4
4
|
LOCALNET_STATE: "hardkas.localnetState.v1",
|
|
5
5
|
REAL_ACCOUNT_STORE: "hardkas.realAccountStore.v1",
|
|
@@ -133,42 +133,52 @@ function createIgraDeployPlanId(hash) {
|
|
|
133
133
|
|
|
134
134
|
// src/canonical.ts
|
|
135
135
|
import { createHash } from "crypto";
|
|
136
|
-
|
|
136
|
+
var SEMANTIC_EXCLUSIONS = /* @__PURE__ */ new Set([
|
|
137
|
+
"contentHash",
|
|
138
|
+
"artifactId",
|
|
139
|
+
"planId",
|
|
140
|
+
"lineage",
|
|
141
|
+
"createdAt",
|
|
142
|
+
"rpcUrl",
|
|
143
|
+
"indexedAt",
|
|
144
|
+
"file_path",
|
|
145
|
+
"file_mtime_ms",
|
|
146
|
+
"hardkasVersion",
|
|
147
|
+
"hashVersion",
|
|
148
|
+
// Exclude hash version from hash
|
|
149
|
+
"parentArtifactId",
|
|
150
|
+
"signedId",
|
|
151
|
+
"deployedAt"
|
|
152
|
+
]);
|
|
153
|
+
var CURRENT_HASH_VERSION = 3;
|
|
154
|
+
function canonicalStringify(obj, version = CURRENT_HASH_VERSION) {
|
|
137
155
|
if (obj === null || typeof obj !== "object") {
|
|
138
156
|
if (typeof obj === "bigint") {
|
|
139
|
-
|
|
157
|
+
if (version >= 2) {
|
|
158
|
+
return JSON.stringify(`n:${obj.toString()}`);
|
|
159
|
+
}
|
|
160
|
+
return JSON.stringify(obj.toString());
|
|
161
|
+
}
|
|
162
|
+
if (typeof obj === "string" && version >= 3) {
|
|
163
|
+
const normalized = obj.normalize("NFC").replace(/\r\n/g, "\n");
|
|
164
|
+
return JSON.stringify(normalized);
|
|
140
165
|
}
|
|
141
166
|
return JSON.stringify(obj);
|
|
142
167
|
}
|
|
143
168
|
if (Array.isArray(obj)) {
|
|
144
|
-
return "[" + obj.map((item) => canonicalStringify(item)).join(",") + "]";
|
|
145
|
-
}
|
|
146
|
-
const SEMANTIC_EXCLUSIONS = /* @__PURE__ */ new Set([
|
|
147
|
-
"contentHash",
|
|
148
|
-
"artifactId",
|
|
149
|
-
"planId",
|
|
150
|
-
"lineage",
|
|
151
|
-
"createdAt",
|
|
152
|
-
"rpcUrl",
|
|
153
|
-
"indexedAt",
|
|
154
|
-
"file_path",
|
|
155
|
-
"file_mtime_ms",
|
|
156
|
-
"hardkasVersion",
|
|
157
|
-
"version",
|
|
158
|
-
"parentArtifactId",
|
|
159
|
-
"signedId"
|
|
160
|
-
]);
|
|
169
|
+
return "[" + obj.map((item) => canonicalStringify(item, version)).join(",") + "]";
|
|
170
|
+
}
|
|
161
171
|
const sortedKeys = Object.keys(obj).filter(
|
|
162
172
|
(key) => !SEMANTIC_EXCLUSIONS.has(key) && obj[key] !== void 0
|
|
163
173
|
).sort();
|
|
164
174
|
const result = sortedKeys.map((key) => {
|
|
165
175
|
const value = obj[key];
|
|
166
|
-
return JSON.stringify(key) + ":" + canonicalStringify(value);
|
|
176
|
+
return JSON.stringify(key) + ":" + canonicalStringify(value, version);
|
|
167
177
|
}).join(",");
|
|
168
178
|
return "{" + result + "}";
|
|
169
179
|
}
|
|
170
|
-
function calculateContentHash(obj) {
|
|
171
|
-
const canonical = canonicalStringify(obj);
|
|
180
|
+
function calculateContentHash(obj, version = CURRENT_HASH_VERSION) {
|
|
181
|
+
const canonical = canonicalStringify(obj, version);
|
|
172
182
|
return createHash("sha256").update(canonical).digest("hex");
|
|
173
183
|
}
|
|
174
184
|
|
|
@@ -397,14 +407,15 @@ function verifyFeeSemantics(artifact) {
|
|
|
397
407
|
}
|
|
398
408
|
|
|
399
409
|
// src/lineage.ts
|
|
400
|
-
function verifyLineage(artifact, parent) {
|
|
410
|
+
function verifyLineage(artifact, parent, options = {}) {
|
|
401
411
|
const issues = [];
|
|
402
412
|
const addIssue = (code, message, severity = "error") => {
|
|
403
413
|
issues.push({ code, severity, message });
|
|
404
414
|
};
|
|
405
415
|
const lineage = artifact.lineage;
|
|
406
416
|
if (!lineage) {
|
|
407
|
-
|
|
417
|
+
const severity = options.strict ? "error" : "warning";
|
|
418
|
+
addIssue("MISSING_LINEAGE", "Artifact has no lineage metadata", severity);
|
|
408
419
|
return {
|
|
409
420
|
ok: issues.every((i) => i.severity !== "error"),
|
|
410
421
|
issues
|
|
@@ -429,26 +440,32 @@ function verifyLineage(artifact, parent) {
|
|
|
429
440
|
if (!parentLineage) {
|
|
430
441
|
addIssue("PARENT_MISSING_LINEAGE", "Parent artifact has no lineage metadata");
|
|
431
442
|
} else {
|
|
443
|
+
if (!lineage.parentArtifactId) {
|
|
444
|
+
addIssue("MISSING_PARENT_ID", "Artifact is missing parentArtifactId reference, but parent was provided for verification.");
|
|
445
|
+
} else if (lineage.parentArtifactId !== parentLineage.artifactId) {
|
|
446
|
+
addIssue("PARENT_ID_MISMATCH", `Parent Artifact ID mismatch: expected ${parentLineage.artifactId}, got ${lineage.parentArtifactId}`);
|
|
447
|
+
}
|
|
432
448
|
if (lineage.lineageId !== parentLineage.lineageId) {
|
|
433
449
|
addIssue("LINEAGE_ID_MISMATCH", `Lineage ID mismatch: expected ${parentLineage.lineageId}, got ${lineage.lineageId}`);
|
|
434
450
|
}
|
|
435
451
|
if (lineage.rootArtifactId !== parentLineage.rootArtifactId) {
|
|
436
|
-
addIssue("
|
|
437
|
-
}
|
|
438
|
-
if (lineage.parentArtifactId && lineage.parentArtifactId !== parentLineage.artifactId) {
|
|
439
|
-
addIssue("PARENT_ID_MISMATCH", `Parent Artifact ID mismatch: expected ${parentLineage.artifactId}, got ${lineage.parentArtifactId}`);
|
|
452
|
+
addIssue("ROOT_ARTIFACT_ID_MISMATCH", `Root Artifact ID mismatch: expected ${parentLineage.rootArtifactId}, got ${lineage.rootArtifactId}`);
|
|
440
453
|
}
|
|
441
454
|
if (lineage.sequence !== void 0 && parentLineage.sequence !== void 0) {
|
|
442
455
|
if (lineage.sequence <= parentLineage.sequence) {
|
|
443
|
-
|
|
456
|
+
const severity = options.strict ? "error" : "warning";
|
|
457
|
+
addIssue("NON_MONOTONIC_SEQUENCE", `Non-monotonic sequence: current (${lineage.sequence}) <= parent (${parentLineage.sequence}).`, severity);
|
|
444
458
|
}
|
|
445
459
|
}
|
|
446
460
|
}
|
|
447
461
|
if (artifact.networkId !== parent.networkId) {
|
|
448
|
-
addIssue("
|
|
462
|
+
addIssue("NETWORK_MISMATCH", `Network mismatch: parent is ${parent.networkId}, current is ${artifact.networkId}`);
|
|
449
463
|
}
|
|
450
464
|
if (artifact.mode !== parent.mode) {
|
|
451
|
-
addIssue("
|
|
465
|
+
addIssue("MODE_MISMATCH", `Mode mismatch: parent is ${parent.mode}, current is ${artifact.mode}`);
|
|
466
|
+
}
|
|
467
|
+
if (lineage.artifactId === lineage.parentArtifactId) {
|
|
468
|
+
addIssue("SELF_PARENT", "Artifact cannot be its own parent.");
|
|
452
469
|
}
|
|
453
470
|
}
|
|
454
471
|
if (parent) {
|
|
@@ -485,9 +502,9 @@ async function verifyArtifactIntegrity(artifactOrPath) {
|
|
|
485
502
|
errors: [],
|
|
486
503
|
issues: []
|
|
487
504
|
};
|
|
488
|
-
const addError = (code, message,
|
|
505
|
+
const addError = (code, message, path4) => {
|
|
489
506
|
result.errors.push(message);
|
|
490
|
-
result.issues.push({ code, severity: "error", message, path:
|
|
507
|
+
result.issues.push({ code, severity: "error", message, path: path4 });
|
|
491
508
|
};
|
|
492
509
|
let artifact;
|
|
493
510
|
try {
|
|
@@ -506,21 +523,22 @@ async function verifyArtifactIntegrity(artifactOrPath) {
|
|
|
506
523
|
result.version = v.version;
|
|
507
524
|
result.expectedHash = v.contentHash;
|
|
508
525
|
if (!v.version || !v.schema) {
|
|
509
|
-
addError("
|
|
526
|
+
addError("ARTIFACT_SCHEMA_MISSING", "Missing version or schema (Artifact might be v1 or legacy)");
|
|
510
527
|
return result;
|
|
511
528
|
}
|
|
512
529
|
const [currentMajor] = ARTIFACT_VERSION.split(".");
|
|
513
530
|
const [artifactMajor] = v.version.split(".");
|
|
514
531
|
if (currentMajor !== artifactMajor) {
|
|
515
|
-
addError("
|
|
532
|
+
addError("ARTIFACT_SCHEMA_INVALID", `Incompatible version: current system is v${currentMajor}, artifact is v${artifactMajor}`);
|
|
516
533
|
return result;
|
|
517
534
|
}
|
|
518
|
-
const
|
|
535
|
+
const hashVersion = v.hashVersion || 1;
|
|
536
|
+
const actualHash = calculateContentHash(v, hashVersion);
|
|
519
537
|
result.actualHash = actualHash;
|
|
520
538
|
if (!v.contentHash) {
|
|
521
|
-
addError("
|
|
539
|
+
addError("ARTIFACT_HASH_MISMATCH", "Missing contentHash field");
|
|
522
540
|
} else if (actualHash !== v.contentHash) {
|
|
523
|
-
addError("
|
|
541
|
+
addError("ARTIFACT_HASH_MISMATCH", `Hash mismatch: expected ${v.contentHash}, got ${actualHash}`);
|
|
524
542
|
}
|
|
525
543
|
let schema;
|
|
526
544
|
switch (v.schema) {
|
|
@@ -545,16 +563,20 @@ async function verifyArtifactIntegrity(artifactOrPath) {
|
|
|
545
563
|
if (!validation.success) {
|
|
546
564
|
validation.error.issues.forEach((e) => {
|
|
547
565
|
const pathStr = e.path.join(".");
|
|
548
|
-
addError("
|
|
566
|
+
addError("ARTIFACT_SCHEMA_INVALID", `${pathStr}: ${e.message}`, pathStr);
|
|
549
567
|
});
|
|
550
568
|
}
|
|
551
569
|
} else {
|
|
552
|
-
addError("
|
|
570
|
+
addError("ARTIFACT_SCHEMA_INVALID", `Unsupported or unknown artifact schema: ${v.schema}`);
|
|
553
571
|
}
|
|
554
572
|
result.ok = result.issues.every((i) => i.severity !== "error" && i.severity !== "critical");
|
|
555
573
|
return result;
|
|
556
574
|
} catch (e) {
|
|
557
|
-
|
|
575
|
+
if (e instanceof SyntaxError) {
|
|
576
|
+
addError("ARTIFACT_JSON_INVALID", `Invalid JSON: ${e.message}`);
|
|
577
|
+
} else {
|
|
578
|
+
addError("ARTIFACT_ID_INVALID", `Unexpected verification error: ${e.message}`);
|
|
579
|
+
}
|
|
558
580
|
return result;
|
|
559
581
|
}
|
|
560
582
|
}
|
|
@@ -600,22 +622,10 @@ function verifyArtifactSemantics(artifact, context = {}) {
|
|
|
600
622
|
});
|
|
601
623
|
}
|
|
602
624
|
}
|
|
603
|
-
|
|
604
|
-
}
|
|
605
|
-
const lineageAudit = verifyLineage(v, context.parent);
|
|
625
|
+
const lineageAudit = verifyLineage(v, context.parent, { strict });
|
|
606
626
|
if (!lineageAudit.ok || strict && !v.lineage) {
|
|
607
|
-
if (!v.lineage && strict) {
|
|
608
|
-
addIssue({
|
|
609
|
-
code: "MISSING_LINEAGE",
|
|
610
|
-
severity: "error",
|
|
611
|
-
message: "Strict mode requires formal lineage metadata."
|
|
612
|
-
});
|
|
613
|
-
}
|
|
614
627
|
lineageAudit.issues.forEach((issue) => {
|
|
615
|
-
addIssue(
|
|
616
|
-
...issue,
|
|
617
|
-
severity: strict ? "error" : "warning"
|
|
618
|
-
});
|
|
628
|
+
addIssue(issue);
|
|
619
629
|
});
|
|
620
630
|
}
|
|
621
631
|
if (strict) {
|
|
@@ -642,31 +652,17 @@ function verifyArtifactSemantics(artifact, context = {}) {
|
|
|
642
652
|
});
|
|
643
653
|
}
|
|
644
654
|
}
|
|
645
|
-
const lineage = v.lineage;
|
|
646
|
-
if (lineage) {
|
|
647
|
-
const { artifactId, parentArtifactId, rootArtifactId } = lineage;
|
|
648
|
-
if (artifactId === parentArtifactId) {
|
|
649
|
-
addIssue({
|
|
650
|
-
code: "LINEAGE_INCONSISTENCY",
|
|
651
|
-
severity: "error",
|
|
652
|
-
message: "Artifact cannot be its own parent."
|
|
653
|
-
});
|
|
654
|
-
}
|
|
655
|
-
if (!parentArtifactId && artifactId !== rootArtifactId) {
|
|
656
|
-
addIssue({
|
|
657
|
-
code: "LINEAGE_INCONSISTENCY",
|
|
658
|
-
severity: "error",
|
|
659
|
-
message: "Root artifactId must match artifactId when no parent exists."
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
655
|
return result;
|
|
664
656
|
}
|
|
665
|
-
async function verifyArtifactReplay(artifact,
|
|
657
|
+
async function verifyArtifactReplay(artifact, _context = {}) {
|
|
666
658
|
return {
|
|
667
|
-
ok:
|
|
668
|
-
issues: [
|
|
669
|
-
|
|
659
|
+
ok: false,
|
|
660
|
+
issues: [{
|
|
661
|
+
code: "REPLAY_UNSUPPORTED_CHECK",
|
|
662
|
+
severity: "warning",
|
|
663
|
+
message: "Replay verification (full consensus simulation) is currently unsupported in this build."
|
|
664
|
+
}],
|
|
665
|
+
errors: ["Replay verification (consensus) unsupported"]
|
|
670
666
|
};
|
|
671
667
|
}
|
|
672
668
|
var verifyArtifact = verifyArtifactIntegrity;
|
|
@@ -890,16 +886,11 @@ function migrateToCanonical(v1Artifact) {
|
|
|
890
886
|
// src/io.ts
|
|
891
887
|
import fs2 from "fs/promises";
|
|
892
888
|
import path from "path";
|
|
889
|
+
import { writeFileAtomic } from "@hardkas/core";
|
|
893
890
|
var bigIntReplacer = (_key, value) => typeof value === "bigint" ? value.toString() : value;
|
|
894
891
|
async function writeArtifact(filePath, artifact) {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
await fs2.mkdir(dir, { recursive: true });
|
|
898
|
-
const content = typeof artifact === "string" ? artifact : JSON.stringify(artifact, bigIntReplacer, 2) + "\n";
|
|
899
|
-
await fs2.writeFile(filePath, content, "utf-8");
|
|
900
|
-
} catch (error) {
|
|
901
|
-
throw new Error(`Failed to write artifact at ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
902
|
-
}
|
|
892
|
+
const content = typeof artifact === "string" ? artifact : JSON.stringify(artifact, bigIntReplacer, 2) + "\n";
|
|
893
|
+
await writeFileAtomic(filePath, content);
|
|
903
894
|
}
|
|
904
895
|
function getDefaultReceiptPath(txId, cwd = process.cwd()) {
|
|
905
896
|
return path.join(cwd, "artifacts", "receipts", `${txId}.json`);
|
|
@@ -1061,6 +1052,7 @@ function createTxPlanArtifact(options) {
|
|
|
1061
1052
|
schema: "hardkas.txPlan",
|
|
1062
1053
|
hardkasVersion: HARDKAS_VERSION,
|
|
1063
1054
|
version: ARTIFACT_VERSION,
|
|
1055
|
+
hashVersion: CURRENT_HASH_VERSION,
|
|
1064
1056
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1065
1057
|
networkId: options.networkId,
|
|
1066
1058
|
mode: options.mode,
|
|
@@ -1095,7 +1087,7 @@ function createTxPlanArtifact(options) {
|
|
|
1095
1087
|
amountSompi: options.plan.change.amountSompi.toString()
|
|
1096
1088
|
};
|
|
1097
1089
|
}
|
|
1098
|
-
const hash = calculateContentHash(artifact);
|
|
1090
|
+
const hash = calculateContentHash(artifact, CURRENT_HASH_VERSION);
|
|
1099
1091
|
artifact.planId = `plan-${hash.slice(0, 16)}`;
|
|
1100
1092
|
artifact.contentHash = hash;
|
|
1101
1093
|
return artifact;
|
|
@@ -1107,7 +1099,7 @@ function createSimulatedSignedTxArtifact(plan, payload) {
|
|
|
1107
1099
|
schema: "hardkas.signedTx",
|
|
1108
1100
|
hardkasVersion: HARDKAS_VERSION,
|
|
1109
1101
|
version: ARTIFACT_VERSION,
|
|
1110
|
-
hashVersion:
|
|
1102
|
+
hashVersion: CURRENT_HASH_VERSION,
|
|
1111
1103
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1112
1104
|
status: "signed",
|
|
1113
1105
|
sourcePlanId: plan.planId,
|
|
@@ -1121,7 +1113,7 @@ function createSimulatedSignedTxArtifact(plan, payload) {
|
|
|
1121
1113
|
payload
|
|
1122
1114
|
}
|
|
1123
1115
|
};
|
|
1124
|
-
const hash = calculateContentHash(artifact);
|
|
1116
|
+
const hash = calculateContentHash(artifact, CURRENT_HASH_VERSION);
|
|
1125
1117
|
artifact.signedId = `signed-${hash.slice(0, 16)}`;
|
|
1126
1118
|
artifact.txId = `simulated-${plan.planId}-${hash.slice(0, 8)}`;
|
|
1127
1119
|
artifact.contentHash = hash;
|
|
@@ -1132,7 +1124,7 @@ function createSimulatedTxReceipt(plan, txId, extra) {
|
|
|
1132
1124
|
schema: "hardkas.txReceipt",
|
|
1133
1125
|
hardkasVersion: HARDKAS_VERSION,
|
|
1134
1126
|
version: ARTIFACT_VERSION,
|
|
1135
|
-
hashVersion:
|
|
1127
|
+
hashVersion: CURRENT_HASH_VERSION,
|
|
1136
1128
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1137
1129
|
txId,
|
|
1138
1130
|
status: "accepted",
|
|
@@ -1145,9 +1137,12 @@ function createSimulatedTxReceipt(plan, txId, extra) {
|
|
|
1145
1137
|
changeSompi: plan.change?.amountSompi,
|
|
1146
1138
|
spentUtxoIds: extra?.spentUtxoIds,
|
|
1147
1139
|
createdUtxoIds: extra?.createdUtxoIds,
|
|
1148
|
-
daaScore: extra?.daaScore
|
|
1140
|
+
daaScore: extra?.daaScore,
|
|
1141
|
+
preStateHash: extra?.preStateHash,
|
|
1142
|
+
postStateHash: extra?.postStateHash,
|
|
1143
|
+
dagContext: extra?.dagContext
|
|
1149
1144
|
};
|
|
1150
|
-
const hash = calculateContentHash(artifact);
|
|
1145
|
+
const hash = calculateContentHash(artifact, CURRENT_HASH_VERSION);
|
|
1151
1146
|
artifact.contentHash = hash;
|
|
1152
1147
|
return artifact;
|
|
1153
1148
|
}
|
|
@@ -1372,6 +1367,162 @@ function validateTxHash(txHash) {
|
|
|
1372
1367
|
throw new Error(`Invalid EVM txHash: must be a 0x-prefixed 64-character hex string. Got: ${txHash}`);
|
|
1373
1368
|
}
|
|
1374
1369
|
}
|
|
1370
|
+
|
|
1371
|
+
// src/diff.ts
|
|
1372
|
+
import { maskSecrets } from "@hardkas/core";
|
|
1373
|
+
function diffArtifacts(left, right) {
|
|
1374
|
+
const entries = [];
|
|
1375
|
+
const leftRedacted = maskSecrets(left);
|
|
1376
|
+
const rightRedacted = maskSecrets(right);
|
|
1377
|
+
compareRecursive(leftRedacted, rightRedacted, "$", entries);
|
|
1378
|
+
return {
|
|
1379
|
+
identical: entries.length === 0,
|
|
1380
|
+
entries
|
|
1381
|
+
};
|
|
1382
|
+
}
|
|
1383
|
+
function compareRecursive(left, right, path4, entries) {
|
|
1384
|
+
if (isPrimitive(left) || isPrimitive(right)) {
|
|
1385
|
+
if (left !== right) {
|
|
1386
|
+
entries.push({ path: path4, kind: "changed", left, right });
|
|
1387
|
+
}
|
|
1388
|
+
return;
|
|
1389
|
+
}
|
|
1390
|
+
if (Array.isArray(left) || Array.isArray(right)) {
|
|
1391
|
+
if (!Array.isArray(left) || !Array.isArray(right)) {
|
|
1392
|
+
entries.push({ path: path4, kind: "changed", left, right });
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
const maxLength = Math.max(left.length, right.length);
|
|
1396
|
+
for (let i = 0; i < maxLength; i++) {
|
|
1397
|
+
if (i >= left.length) {
|
|
1398
|
+
entries.push({ path: `${path4}[${i}]`, kind: "added", right: right[i] });
|
|
1399
|
+
} else if (i >= right.length) {
|
|
1400
|
+
entries.push({ path: `${path4}[${i}]`, kind: "removed", left: left[i] });
|
|
1401
|
+
} else {
|
|
1402
|
+
compareRecursive(left[i], right[i], `${path4}[${i}]`, entries);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
1407
|
+
const leftKeys = Object.keys(left).filter((k) => !SEMANTIC_EXCLUSIONS.has(k));
|
|
1408
|
+
const rightKeys = Object.keys(right).filter((k) => !SEMANTIC_EXCLUSIONS.has(k));
|
|
1409
|
+
const allKeys = /* @__PURE__ */ new Set([...leftKeys, ...rightKeys]);
|
|
1410
|
+
for (const key of allKeys) {
|
|
1411
|
+
const nextPath = path4 === "$" ? key : `${path4}.${key}`;
|
|
1412
|
+
if (!leftKeys.includes(key)) {
|
|
1413
|
+
entries.push({ path: nextPath, kind: "added", right: right[key] });
|
|
1414
|
+
} else if (!rightKeys.includes(key)) {
|
|
1415
|
+
entries.push({ path: nextPath, kind: "removed", left: left[key] });
|
|
1416
|
+
} else {
|
|
1417
|
+
compareRecursive(left[key], right[key], nextPath, entries);
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
function isPrimitive(val) {
|
|
1422
|
+
if (val === null) return true;
|
|
1423
|
+
return typeof val !== "object" && typeof val !== "function";
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
// src/deployment.ts
|
|
1427
|
+
function createDeploymentRecord(opts) {
|
|
1428
|
+
const record = {
|
|
1429
|
+
schema: "hardkas.deployment.v1",
|
|
1430
|
+
label: opts.label,
|
|
1431
|
+
networkId: opts.networkId,
|
|
1432
|
+
status: opts.status || "planned",
|
|
1433
|
+
deployedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1434
|
+
hardkasVersion: HARDKAS_VERSION,
|
|
1435
|
+
version: ARTIFACT_VERSION,
|
|
1436
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1437
|
+
mode: "real"
|
|
1438
|
+
};
|
|
1439
|
+
if (opts.txId) record.txId = opts.txId;
|
|
1440
|
+
if (opts.planArtifactId) record.planArtifactId = opts.planArtifactId;
|
|
1441
|
+
if (opts.receiptArtifactId) record.receiptArtifactId = opts.receiptArtifactId;
|
|
1442
|
+
if (opts.deployedAddresses) record.deployedAddresses = opts.deployedAddresses;
|
|
1443
|
+
if (opts.deployer) record.deployer = opts.deployer;
|
|
1444
|
+
if (opts.payloadHash) record.payloadHash = opts.payloadHash;
|
|
1445
|
+
if (opts.notes) record.notes = opts.notes;
|
|
1446
|
+
record.contentHash = calculateContentHash(record, CURRENT_HASH_VERSION);
|
|
1447
|
+
return record;
|
|
1448
|
+
}
|
|
1449
|
+
function updateDeploymentStatus(record, newStatus, txId) {
|
|
1450
|
+
const updated = {
|
|
1451
|
+
...record,
|
|
1452
|
+
status: newStatus,
|
|
1453
|
+
deployedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1454
|
+
};
|
|
1455
|
+
if (txId) updated.txId = txId;
|
|
1456
|
+
delete updated.contentHash;
|
|
1457
|
+
updated.contentHash = calculateContentHash(updated, CURRENT_HASH_VERSION);
|
|
1458
|
+
return updated;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
// src/deployment-store.ts
|
|
1462
|
+
import fs4 from "fs/promises";
|
|
1463
|
+
import { existsSync } from "fs";
|
|
1464
|
+
import path3 from "path";
|
|
1465
|
+
import { writeFileAtomic as writeFileAtomic2 } from "@hardkas/core";
|
|
1466
|
+
async function saveDeployment(rootDir, record) {
|
|
1467
|
+
const deploymentsDir = path3.join(rootDir, ".hardkas", "deployments", record.networkId);
|
|
1468
|
+
const targetPath = path3.join(deploymentsDir, `${record.label}.json`);
|
|
1469
|
+
await writeFileAtomic2(targetPath, JSON.stringify(record, null, 2));
|
|
1470
|
+
return targetPath;
|
|
1471
|
+
}
|
|
1472
|
+
async function loadDeployment(rootDir, networkId, label) {
|
|
1473
|
+
const targetPath = path3.join(rootDir, ".hardkas", "deployments", networkId, `${label}.json`);
|
|
1474
|
+
if (!existsSync(targetPath)) return null;
|
|
1475
|
+
const content = await fs4.readFile(targetPath, "utf-8");
|
|
1476
|
+
return JSON.parse(content);
|
|
1477
|
+
}
|
|
1478
|
+
async function listDeployments(rootDir, networkId) {
|
|
1479
|
+
const baseDir = path3.join(rootDir, ".hardkas", "deployments");
|
|
1480
|
+
if (!existsSync(baseDir)) return [];
|
|
1481
|
+
const summaries = [];
|
|
1482
|
+
const networks = networkId ? [networkId] : await fs4.readdir(baseDir);
|
|
1483
|
+
for (const net of networks) {
|
|
1484
|
+
const netDir = path3.join(baseDir, net);
|
|
1485
|
+
if (!existsSync(netDir)) continue;
|
|
1486
|
+
const files = await fs4.readdir(netDir);
|
|
1487
|
+
for (const file of files) {
|
|
1488
|
+
if (!file.endsWith(".json")) continue;
|
|
1489
|
+
try {
|
|
1490
|
+
const content = await fs4.readFile(path3.join(netDir, file), "utf-8");
|
|
1491
|
+
const record = JSON.parse(content);
|
|
1492
|
+
const summary = {
|
|
1493
|
+
label: record.label,
|
|
1494
|
+
networkId: record.networkId,
|
|
1495
|
+
status: record.status,
|
|
1496
|
+
deployedAt: record.deployedAt,
|
|
1497
|
+
contentHash: record.contentHash || ""
|
|
1498
|
+
};
|
|
1499
|
+
if (record.txId) summary.txId = record.txId;
|
|
1500
|
+
summaries.push(summary);
|
|
1501
|
+
} catch (e) {
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
return summaries.sort((a, b) => new Date(b.deployedAt).getTime() - new Date(a.deployedAt).getTime());
|
|
1506
|
+
}
|
|
1507
|
+
async function updateDeployment(rootDir, networkId, label, update) {
|
|
1508
|
+
const existing = await loadDeployment(rootDir, networkId, label);
|
|
1509
|
+
if (!existing) {
|
|
1510
|
+
throw new Error(`Deployment '${label}' not found on network '${networkId}'.`);
|
|
1511
|
+
}
|
|
1512
|
+
const updated = {
|
|
1513
|
+
...existing,
|
|
1514
|
+
...update,
|
|
1515
|
+
deployedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1516
|
+
};
|
|
1517
|
+
await saveDeployment(rootDir, updated);
|
|
1518
|
+
return updated;
|
|
1519
|
+
}
|
|
1520
|
+
async function deleteDeployment(rootDir, networkId, label) {
|
|
1521
|
+
const targetPath = path3.join(rootDir, ".hardkas", "deployments", networkId, `${label}.json`);
|
|
1522
|
+
if (!existsSync(targetPath)) return false;
|
|
1523
|
+
await fs4.unlink(targetPath);
|
|
1524
|
+
return true;
|
|
1525
|
+
}
|
|
1375
1526
|
export {
|
|
1376
1527
|
ARTIFACT_SCHEMAS,
|
|
1377
1528
|
ARTIFACT_VERSION,
|
|
@@ -1380,6 +1531,7 @@ export {
|
|
|
1380
1531
|
BaseArtifactSchema,
|
|
1381
1532
|
BasicCorrelationInvariant,
|
|
1382
1533
|
BasicLineageInvariant,
|
|
1534
|
+
CURRENT_HASH_VERSION,
|
|
1383
1535
|
DagContextSchema,
|
|
1384
1536
|
HARDKAS_VERSION,
|
|
1385
1537
|
HashInvariant,
|
|
@@ -1388,6 +1540,7 @@ export {
|
|
|
1388
1540
|
LocalnetUtxoSchemaV2,
|
|
1389
1541
|
NetworkInvariant,
|
|
1390
1542
|
ReplayInvariant,
|
|
1543
|
+
SEMANTIC_EXCLUSIONS,
|
|
1391
1544
|
SchemaInvariant,
|
|
1392
1545
|
SignedTxSchema,
|
|
1393
1546
|
SnapshotSchema,
|
|
@@ -1407,6 +1560,7 @@ export {
|
|
|
1407
1560
|
bigIntReplacer,
|
|
1408
1561
|
calculateContentHash,
|
|
1409
1562
|
canonicalStringify,
|
|
1563
|
+
createDeploymentRecord,
|
|
1410
1564
|
createIgraDeployPlanId,
|
|
1411
1565
|
createIgraPlanId,
|
|
1412
1566
|
createIgraSignedId,
|
|
@@ -1414,6 +1568,8 @@ export {
|
|
|
1414
1568
|
createSimulatedTxReceipt,
|
|
1415
1569
|
createTxPlanArtifact,
|
|
1416
1570
|
defaultClock,
|
|
1571
|
+
deleteDeployment,
|
|
1572
|
+
diffArtifacts,
|
|
1417
1573
|
explainArtifact,
|
|
1418
1574
|
formatSignedTxArtifact,
|
|
1419
1575
|
formatTxPlanArtifact,
|
|
@@ -1423,7 +1579,9 @@ export {
|
|
|
1423
1579
|
getDefaultReceiptPath,
|
|
1424
1580
|
getL2ReceiptPath,
|
|
1425
1581
|
isIgraTxPlanArtifact,
|
|
1582
|
+
listDeployments,
|
|
1426
1583
|
listIgraTxReceiptArtifacts,
|
|
1584
|
+
loadDeployment,
|
|
1427
1585
|
loadIgraTxReceiptArtifact,
|
|
1428
1586
|
migrateToCanonical,
|
|
1429
1587
|
readArtifact,
|
|
@@ -1431,10 +1589,13 @@ export {
|
|
|
1431
1589
|
readTxPlanArtifact,
|
|
1432
1590
|
readTxReceiptArtifact,
|
|
1433
1591
|
recomputeMass,
|
|
1592
|
+
saveDeployment,
|
|
1434
1593
|
saveIgraTxReceiptArtifact,
|
|
1435
1594
|
sortUtxosByOutpoint,
|
|
1436
1595
|
txOutputFromArtifact,
|
|
1437
1596
|
txOutputToArtifact,
|
|
1597
|
+
updateDeployment,
|
|
1598
|
+
updateDeploymentStatus,
|
|
1438
1599
|
utxoFromArtifact,
|
|
1439
1600
|
utxoToArtifact,
|
|
1440
1601
|
validateArtifact,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hardkas/artifacts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-alpha",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Javier Rodriguez",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"types": "./dist/index.d.ts",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"zod": "^3.24.1",
|
|
27
|
-
"@hardkas/core": "0.
|
|
28
|
-
"@hardkas/tx-builder": "0.
|
|
27
|
+
"@hardkas/core": "0.4.0-alpha",
|
|
28
|
+
"@hardkas/tx-builder": "0.4.0-alpha"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"tsup": "^8.3.5",
|