@hardkas/artifacts 0.7.1-alpha → 0.7.4-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 +117 -19
- package/dist/index.js +405 -157
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ declare const ARTIFACT_SCHEMAS: {
|
|
|
15
15
|
readonly IGRA_SIGNED_TX: "hardkas.igraSignedTx.v1";
|
|
16
16
|
readonly IGRA_TX_RECEIPT: "hardkas.igraTxReceipt.v1";
|
|
17
17
|
};
|
|
18
|
-
type HardkasArtifactSchema = typeof ARTIFACT_SCHEMAS[keyof typeof ARTIFACT_SCHEMAS] | string;
|
|
18
|
+
type HardkasArtifactSchema = (typeof ARTIFACT_SCHEMAS)[keyof typeof ARTIFACT_SCHEMAS] | string;
|
|
19
19
|
type HardkasArtifactMode = "simulated" | "node" | "rpc" | "l2-rpc" | "real";
|
|
20
20
|
|
|
21
21
|
declare const ARTIFACT_VERSION = "1.0.0-alpha";
|
|
@@ -968,6 +968,26 @@ declare const TxReceiptSchema: z.ZodObject<{
|
|
|
968
968
|
errors?: string[] | undefined;
|
|
969
969
|
metadata?: any;
|
|
970
970
|
}>;
|
|
971
|
+
declare const SignatureEntrySchema: z.ZodObject<{
|
|
972
|
+
signer: z.ZodString;
|
|
973
|
+
signature: z.ZodString;
|
|
974
|
+
}, "strip", z.ZodTypeAny, {
|
|
975
|
+
signer: string;
|
|
976
|
+
signature: string;
|
|
977
|
+
}, {
|
|
978
|
+
signer: string;
|
|
979
|
+
signature: string;
|
|
980
|
+
}>;
|
|
981
|
+
declare const SignatureMetadataEntrySchema: z.ZodObject<{
|
|
982
|
+
signer: z.ZodString;
|
|
983
|
+
signedAt: z.ZodString;
|
|
984
|
+
}, "strip", z.ZodTypeAny, {
|
|
985
|
+
signer: string;
|
|
986
|
+
signedAt: string;
|
|
987
|
+
}, {
|
|
988
|
+
signer: string;
|
|
989
|
+
signedAt: string;
|
|
990
|
+
}>;
|
|
971
991
|
declare const SignedTxSchema: z.ZodObject<{
|
|
972
992
|
schemaVersion: z.ZodOptional<z.ZodString>;
|
|
973
993
|
hardkasVersion: z.ZodString;
|
|
@@ -1020,7 +1040,7 @@ declare const SignedTxSchema: z.ZodObject<{
|
|
|
1020
1040
|
}>>;
|
|
1021
1041
|
} & {
|
|
1022
1042
|
schema: z.ZodLiteral<"hardkas.signedTx">;
|
|
1023
|
-
status: z.
|
|
1043
|
+
status: z.ZodEnum<["partially_signed", "signed"]>;
|
|
1024
1044
|
signedId: z.ZodString;
|
|
1025
1045
|
sourcePlanId: z.ZodString;
|
|
1026
1046
|
networkId: z.ZodEnum<["mainnet", "testnet-10", "testnet-11", "testnet-12", "simnet", "simnet-1", "devnet", "simulated"]>;
|
|
@@ -1052,7 +1072,8 @@ declare const SignedTxSchema: z.ZodObject<{
|
|
|
1052
1072
|
input?: string | undefined;
|
|
1053
1073
|
}>;
|
|
1054
1074
|
amountSompi: z.ZodString;
|
|
1055
|
-
|
|
1075
|
+
unsignedPayloadHash: z.ZodOptional<z.ZodString>;
|
|
1076
|
+
signedTransaction: z.ZodOptional<z.ZodObject<{
|
|
1056
1077
|
format: z.ZodString;
|
|
1057
1078
|
payload: z.ZodString;
|
|
1058
1079
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -1061,11 +1082,49 @@ declare const SignedTxSchema: z.ZodObject<{
|
|
|
1061
1082
|
}, {
|
|
1062
1083
|
format: string;
|
|
1063
1084
|
payload: string;
|
|
1064
|
-
}
|
|
1085
|
+
}>>;
|
|
1065
1086
|
txId: z.ZodOptional<z.ZodString>;
|
|
1087
|
+
multisig: z.ZodOptional<z.ZodObject<{
|
|
1088
|
+
threshold: z.ZodNumber;
|
|
1089
|
+
requiredSigners: z.ZodArray<z.ZodString, "many">;
|
|
1090
|
+
signatures: z.ZodArray<z.ZodObject<{
|
|
1091
|
+
signer: z.ZodString;
|
|
1092
|
+
signature: z.ZodString;
|
|
1093
|
+
}, "strip", z.ZodTypeAny, {
|
|
1094
|
+
signer: string;
|
|
1095
|
+
signature: string;
|
|
1096
|
+
}, {
|
|
1097
|
+
signer: string;
|
|
1098
|
+
signature: string;
|
|
1099
|
+
}>, "many">;
|
|
1100
|
+
}, "strip", z.ZodTypeAny, {
|
|
1101
|
+
threshold: number;
|
|
1102
|
+
requiredSigners: string[];
|
|
1103
|
+
signatures: {
|
|
1104
|
+
signer: string;
|
|
1105
|
+
signature: string;
|
|
1106
|
+
}[];
|
|
1107
|
+
}, {
|
|
1108
|
+
threshold: number;
|
|
1109
|
+
requiredSigners: string[];
|
|
1110
|
+
signatures: {
|
|
1111
|
+
signer: string;
|
|
1112
|
+
signature: string;
|
|
1113
|
+
}[];
|
|
1114
|
+
}>>;
|
|
1115
|
+
signatureMetadata: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1116
|
+
signer: z.ZodString;
|
|
1117
|
+
signedAt: z.ZodString;
|
|
1118
|
+
}, "strip", z.ZodTypeAny, {
|
|
1119
|
+
signer: string;
|
|
1120
|
+
signedAt: string;
|
|
1121
|
+
}, {
|
|
1122
|
+
signer: string;
|
|
1123
|
+
signedAt: string;
|
|
1124
|
+
}>, "many">>;
|
|
1066
1125
|
metadata: z.ZodOptional<z.ZodAny>;
|
|
1067
1126
|
}, "strip", z.ZodTypeAny, {
|
|
1068
|
-
status: "signed";
|
|
1127
|
+
status: "partially_signed" | "signed";
|
|
1069
1128
|
version: "1.0.0-alpha";
|
|
1070
1129
|
schema: "hardkas.signedTx";
|
|
1071
1130
|
hardkasVersion: string;
|
|
@@ -1085,10 +1144,14 @@ declare const SignedTxSchema: z.ZodObject<{
|
|
|
1085
1144
|
amountSompi: string;
|
|
1086
1145
|
signedId: string;
|
|
1087
1146
|
sourcePlanId: string;
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1147
|
+
multisig?: {
|
|
1148
|
+
threshold: number;
|
|
1149
|
+
requiredSigners: string[];
|
|
1150
|
+
signatures: {
|
|
1151
|
+
signer: string;
|
|
1152
|
+
signature: string;
|
|
1153
|
+
}[];
|
|
1154
|
+
} | undefined;
|
|
1092
1155
|
schemaVersion?: string | undefined;
|
|
1093
1156
|
hashVersion?: string | number | undefined;
|
|
1094
1157
|
contentHash?: string | undefined;
|
|
@@ -1113,8 +1176,17 @@ declare const SignedTxSchema: z.ZodObject<{
|
|
|
1113
1176
|
} | undefined;
|
|
1114
1177
|
txId?: string | undefined;
|
|
1115
1178
|
metadata?: any;
|
|
1179
|
+
unsignedPayloadHash?: string | undefined;
|
|
1180
|
+
signedTransaction?: {
|
|
1181
|
+
format: string;
|
|
1182
|
+
payload: string;
|
|
1183
|
+
} | undefined;
|
|
1184
|
+
signatureMetadata?: {
|
|
1185
|
+
signer: string;
|
|
1186
|
+
signedAt: string;
|
|
1187
|
+
}[] | undefined;
|
|
1116
1188
|
}, {
|
|
1117
|
-
status: "signed";
|
|
1189
|
+
status: "partially_signed" | "signed";
|
|
1118
1190
|
version: "1.0.0-alpha";
|
|
1119
1191
|
schema: "hardkas.signedTx";
|
|
1120
1192
|
hardkasVersion: string;
|
|
@@ -1134,10 +1206,14 @@ declare const SignedTxSchema: z.ZodObject<{
|
|
|
1134
1206
|
amountSompi: string;
|
|
1135
1207
|
signedId: string;
|
|
1136
1208
|
sourcePlanId: string;
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1209
|
+
multisig?: {
|
|
1210
|
+
threshold: number;
|
|
1211
|
+
requiredSigners: string[];
|
|
1212
|
+
signatures: {
|
|
1213
|
+
signer: string;
|
|
1214
|
+
signature: string;
|
|
1215
|
+
}[];
|
|
1216
|
+
} | undefined;
|
|
1141
1217
|
schemaVersion?: string | undefined;
|
|
1142
1218
|
hashVersion?: string | number | undefined;
|
|
1143
1219
|
contentHash?: string | undefined;
|
|
@@ -1162,6 +1238,15 @@ declare const SignedTxSchema: z.ZodObject<{
|
|
|
1162
1238
|
} | undefined;
|
|
1163
1239
|
txId?: string | undefined;
|
|
1164
1240
|
metadata?: any;
|
|
1241
|
+
unsignedPayloadHash?: string | undefined;
|
|
1242
|
+
signedTransaction?: {
|
|
1243
|
+
format: string;
|
|
1244
|
+
payload: string;
|
|
1245
|
+
} | undefined;
|
|
1246
|
+
signatureMetadata?: {
|
|
1247
|
+
signer: string;
|
|
1248
|
+
signedAt: string;
|
|
1249
|
+
}[] | undefined;
|
|
1165
1250
|
}>;
|
|
1166
1251
|
declare const TxTraceSchema: z.ZodObject<{
|
|
1167
1252
|
schemaVersion: z.ZodOptional<z.ZodString>;
|
|
@@ -2045,7 +2130,7 @@ interface TxPlanArtifact extends BaseArtifact<"txPlan"> {
|
|
|
2045
2130
|
} | undefined;
|
|
2046
2131
|
}
|
|
2047
2132
|
interface SignedTxArtifact extends BaseArtifact<"signedTx"> {
|
|
2048
|
-
status: "signed";
|
|
2133
|
+
status: "partially_signed" | "signed";
|
|
2049
2134
|
signedId: ArtifactId;
|
|
2050
2135
|
sourcePlanId: string;
|
|
2051
2136
|
from: {
|
|
@@ -2059,11 +2144,24 @@ interface SignedTxArtifact extends BaseArtifact<"signedTx"> {
|
|
|
2059
2144
|
input?: string | undefined;
|
|
2060
2145
|
};
|
|
2061
2146
|
amountSompi: string;
|
|
2062
|
-
|
|
2147
|
+
unsignedPayloadHash?: string | undefined;
|
|
2148
|
+
signedTransaction?: {
|
|
2063
2149
|
format: string;
|
|
2064
2150
|
payload: string;
|
|
2065
|
-
};
|
|
2151
|
+
} | undefined;
|
|
2066
2152
|
txId?: TxId | undefined;
|
|
2153
|
+
multisig?: {
|
|
2154
|
+
threshold: number;
|
|
2155
|
+
requiredSigners: string[];
|
|
2156
|
+
signatures: Array<{
|
|
2157
|
+
signer: string;
|
|
2158
|
+
signature: string;
|
|
2159
|
+
}>;
|
|
2160
|
+
} | undefined;
|
|
2161
|
+
signatureMetadata?: Array<{
|
|
2162
|
+
signer: string;
|
|
2163
|
+
signedAt: string;
|
|
2164
|
+
}> | undefined;
|
|
2067
2165
|
metadata?: any | undefined;
|
|
2068
2166
|
}
|
|
2069
2167
|
interface TxReceiptArtifact extends BaseArtifact<"txReceipt"> {
|
|
@@ -2208,7 +2306,7 @@ declare const STRICT_PATH_KEYS: Set<string>;
|
|
|
2208
2306
|
* Excludes fields in SEMANTIC_EXCLUSIONS during serialization.
|
|
2209
2307
|
* Skips keys with undefined values (matching JSON.stringify behavior).
|
|
2210
2308
|
*/
|
|
2211
|
-
declare function canonicalStringify(obj: unknown, version?: number, keyName?: string): string;
|
|
2309
|
+
declare function canonicalStringify(obj: unknown, version?: number, keyName?: string, isRoot?: boolean): string;
|
|
2212
2310
|
/**
|
|
2213
2311
|
* Calculates a SHA-256 hash of the canonical JSON representation.
|
|
2214
2312
|
* Always excludes fields in SEMANTIC_EXCLUSIONS from the calculation.
|
|
@@ -2732,4 +2830,4 @@ declare function listDeployments(rootDir: string, networkId?: string): Promise<D
|
|
|
2732
2830
|
declare function updateDeployment(rootDir: string, networkId: string, label: string, update: Partial<DeploymentRecord>): Promise<DeploymentRecord>;
|
|
2733
2831
|
declare function deleteDeployment(rootDir: string, networkId: string, label: string): Promise<boolean>;
|
|
2734
2832
|
|
|
2735
|
-
export { ARTIFACT_SCHEMAS, ARTIFACT_VERSION, AccountRefSchema, type ArtifactDiff, type ArtifactExplanation, ArtifactLineageSchema, type ArtifactLookup, type ArtifactPayload, 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 DraftArtifact, 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, type MigrationResult, type MigrationStep, NetworkInvariant, ReplayInvariant, type RuntimeSession, RuntimeSessionSchema, SEMANTIC_EXCLUSIONS, STRICT_PATH_KEYS, SchemaInvariant, type ScriptCapability, ScriptCapabilitySchema, ScriptMetadataSchema, 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, type Workflow, type WorkflowArtifact, WorkflowSchema, assertDecimalBigIntString, assertEvmAddress, assertEvmTxHash, assertHexData, assertValidIgraSignedTxArtifact, assertValidIgraTxPlanArtifact, assertValidIgraTxReceiptArtifact, assertValidSignedTxArtifact, assertValidTxPlanArtifact, assertValidTxReceiptArtifact, bigIntReplacer, calculateContentHash, canMigrate, canonicalStringify, createDeploymentRecord, createIgraDeployPlanId, createIgraPlanId, createIgraSignedId, createSimulatedSignedTxArtifact, createSimulatedTxReceipt, createTxPlanArtifact, defaultClock, deleteDeployment, detectArtifactVersion, diffArtifacts, explainArtifact, formatSignedTxArtifact, formatTxPlanArtifact, formatTxReceiptArtifact, getBroadcastableSignedTransaction, getDefaultL2ReceiptsDir, getDefaultReceiptPath, getL2ReceiptPath, getMigrationPath, getRegisteredMigrationSteps, isIgraTxPlanArtifact, listDeployments, listIgraTxReceiptArtifacts, loadDeployment, loadIgraTxReceiptArtifact, migrateArtifactPayload, migrateToCanonical, readArtifact, readSignedTxArtifact, readTxPlanArtifact, readTxReceiptArtifact, recomputeMass, registerMigrationStep, saveDeployment, saveIgraTxReceiptArtifact, sortUtxosByOutpoint, txOutputFromArtifact, txOutputToArtifact, updateDeployment, updateDeploymentStatus, utxoFromArtifact, utxoToArtifact, validateArtifact, validateIgraSignedTxArtifact, validateIgraTxPlanArtifact, validateIgraTxReceiptArtifact, validateSignedTxArtifact, validateTxPlanArtifact, validateTxReceiptArtifact, verifyArtifact, verifyArtifactFile, verifyArtifactIntegrity, verifyArtifactReplay, verifyArtifactSemantics, verifyFeeSemantics, verifyLineage, writeArtifact };
|
|
2833
|
+
export { ARTIFACT_SCHEMAS, ARTIFACT_VERSION, AccountRefSchema, type ArtifactDiff, type ArtifactExplanation, ArtifactLineageSchema, type ArtifactLookup, type ArtifactPayload, 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 DraftArtifact, 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, type MigrationResult, type MigrationStep, NetworkInvariant, ReplayInvariant, type RuntimeSession, RuntimeSessionSchema, SEMANTIC_EXCLUSIONS, STRICT_PATH_KEYS, SchemaInvariant, type ScriptCapability, ScriptCapabilitySchema, ScriptMetadataSchema, SignatureEntrySchema, SignatureMetadataEntrySchema, 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, type Workflow, type WorkflowArtifact, WorkflowSchema, assertDecimalBigIntString, assertEvmAddress, assertEvmTxHash, assertHexData, assertValidIgraSignedTxArtifact, assertValidIgraTxPlanArtifact, assertValidIgraTxReceiptArtifact, assertValidSignedTxArtifact, assertValidTxPlanArtifact, assertValidTxReceiptArtifact, bigIntReplacer, calculateContentHash, canMigrate, canonicalStringify, createDeploymentRecord, createIgraDeployPlanId, createIgraPlanId, createIgraSignedId, createSimulatedSignedTxArtifact, createSimulatedTxReceipt, createTxPlanArtifact, defaultClock, deleteDeployment, detectArtifactVersion, diffArtifacts, explainArtifact, formatSignedTxArtifact, formatTxPlanArtifact, formatTxReceiptArtifact, getBroadcastableSignedTransaction, getDefaultL2ReceiptsDir, getDefaultReceiptPath, getL2ReceiptPath, getMigrationPath, getRegisteredMigrationSteps, isIgraTxPlanArtifact, listDeployments, listIgraTxReceiptArtifacts, loadDeployment, loadIgraTxReceiptArtifact, migrateArtifactPayload, migrateToCanonical, readArtifact, readSignedTxArtifact, readTxPlanArtifact, readTxReceiptArtifact, recomputeMass, registerMigrationStep, 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,7 +1,7 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var package_default = {
|
|
3
3
|
name: "@hardkas/artifacts",
|
|
4
|
-
version: "0.7.
|
|
4
|
+
version: "0.7.4-alpha",
|
|
5
5
|
type: "module",
|
|
6
6
|
license: "MIT",
|
|
7
7
|
author: "Javier Rodriguez",
|
|
@@ -62,9 +62,11 @@ function isIgraTxPlanArtifact(value) {
|
|
|
62
62
|
}
|
|
63
63
|
function validateIgraTxPlanArtifact(value) {
|
|
64
64
|
const errors = [];
|
|
65
|
-
if (typeof value !== "object" || value === null)
|
|
65
|
+
if (typeof value !== "object" || value === null)
|
|
66
|
+
return { ok: false, errors: ["Artifact must be an object"] };
|
|
66
67
|
const v = value;
|
|
67
|
-
if (v.schema !== ARTIFACT_SCHEMAS.IGRA_TX_PLAN)
|
|
68
|
+
if (v.schema !== ARTIFACT_SCHEMAS.IGRA_TX_PLAN)
|
|
69
|
+
errors.push(`Invalid schema: expected '${ARTIFACT_SCHEMAS.IGRA_TX_PLAN}'`);
|
|
68
70
|
validateCommon(v, errors);
|
|
69
71
|
if (v.status !== "built") errors.push("Invalid status: expected 'built'");
|
|
70
72
|
if (typeof v.planId !== "string" || !v.planId) errors.push("Missing planId");
|
|
@@ -84,29 +86,36 @@ function validateIgraTxPlanArtifact(value) {
|
|
|
84
86
|
assertHexData(r.data, "request.data", errors);
|
|
85
87
|
assertDecimalBigIntString(r.valueWei, "request.valueWei", errors);
|
|
86
88
|
if (r.gasLimit) assertDecimalBigIntString(r.gasLimit, "request.gasLimit", errors);
|
|
87
|
-
if (r.gasPriceWei)
|
|
89
|
+
if (r.gasPriceWei)
|
|
90
|
+
assertDecimalBigIntString(r.gasPriceWei, "request.gasPriceWei", errors);
|
|
88
91
|
if (r.nonce) assertDecimalBigIntString(r.nonce, "request.nonce", errors);
|
|
89
92
|
}
|
|
90
93
|
if (v.estimatedGas) assertDecimalBigIntString(v.estimatedGas, "estimatedGas", errors);
|
|
91
|
-
if (v.estimatedFeeWei)
|
|
94
|
+
if (v.estimatedFeeWei)
|
|
95
|
+
assertDecimalBigIntString(v.estimatedFeeWei, "estimatedFeeWei", errors);
|
|
92
96
|
return { ok: errors.length === 0, errors };
|
|
93
97
|
}
|
|
94
98
|
function assertValidIgraTxPlanArtifact(value) {
|
|
95
99
|
const result = validateIgraTxPlanArtifact(value);
|
|
96
100
|
if (!result.ok) {
|
|
97
|
-
throw new Error(
|
|
98
|
-
|
|
101
|
+
throw new Error(
|
|
102
|
+
`Invalid Igra tx plan artifact:
|
|
103
|
+
${result.errors.map((e) => `- ${e}`).join("\n")}`
|
|
104
|
+
);
|
|
99
105
|
}
|
|
100
106
|
}
|
|
101
107
|
function validateIgraSignedTxArtifact(value) {
|
|
102
108
|
const errors = [];
|
|
103
|
-
if (typeof value !== "object" || value === null)
|
|
109
|
+
if (typeof value !== "object" || value === null)
|
|
110
|
+
return { ok: false, errors: ["Artifact must be an object"] };
|
|
104
111
|
const v = value;
|
|
105
|
-
if (v.schema !== ARTIFACT_SCHEMAS.IGRA_SIGNED_TX)
|
|
112
|
+
if (v.schema !== ARTIFACT_SCHEMAS.IGRA_SIGNED_TX)
|
|
113
|
+
errors.push(`Invalid schema: expected '${ARTIFACT_SCHEMAS.IGRA_SIGNED_TX}'`);
|
|
106
114
|
validateCommon(v, errors);
|
|
107
115
|
if (v.status !== "signed") errors.push("Invalid status: expected 'signed'");
|
|
108
116
|
if (typeof v.signedId !== "string" || !v.signedId) errors.push("Missing signedId");
|
|
109
|
-
if (typeof v.sourcePlanId !== "string" || !v.sourcePlanId)
|
|
117
|
+
if (typeof v.sourcePlanId !== "string" || !v.sourcePlanId)
|
|
118
|
+
errors.push("Missing sourcePlanId");
|
|
110
119
|
assertHexData(v.rawTransaction, "rawTransaction", errors);
|
|
111
120
|
if (v.txHash) assertEvmTxHash(v.txHash, "txHash", errors);
|
|
112
121
|
return { ok: errors.length === 0, errors };
|
|
@@ -114,17 +123,22 @@ function validateIgraSignedTxArtifact(value) {
|
|
|
114
123
|
function assertValidIgraSignedTxArtifact(value) {
|
|
115
124
|
const result = validateIgraSignedTxArtifact(value);
|
|
116
125
|
if (!result.ok) {
|
|
117
|
-
throw new Error(
|
|
118
|
-
|
|
126
|
+
throw new Error(
|
|
127
|
+
`Invalid Igra signed tx artifact:
|
|
128
|
+
${result.errors.map((e) => `- ${e}`).join("\n")}`
|
|
129
|
+
);
|
|
119
130
|
}
|
|
120
131
|
}
|
|
121
132
|
function validateIgraTxReceiptArtifact(value) {
|
|
122
133
|
const errors = [];
|
|
123
|
-
if (typeof value !== "object" || value === null)
|
|
134
|
+
if (typeof value !== "object" || value === null)
|
|
135
|
+
return { ok: false, errors: ["Artifact must be an object"] };
|
|
124
136
|
const v = value;
|
|
125
|
-
if (v.schema !== ARTIFACT_SCHEMAS.IGRA_TX_RECEIPT)
|
|
137
|
+
if (v.schema !== ARTIFACT_SCHEMAS.IGRA_TX_RECEIPT)
|
|
138
|
+
errors.push(`Invalid schema: expected '${ARTIFACT_SCHEMAS.IGRA_TX_RECEIPT}'`);
|
|
126
139
|
validateCommon(v, errors);
|
|
127
|
-
if (!["submitted", "confirmed", "failed"].includes(v.status))
|
|
140
|
+
if (!["submitted", "confirmed", "failed"].includes(v.status))
|
|
141
|
+
errors.push("Invalid status");
|
|
128
142
|
assertEvmTxHash(v.txHash, "txHash", errors);
|
|
129
143
|
if (typeof v.rpcUrl !== "string" || !v.rpcUrl) errors.push("Missing rpcUrl");
|
|
130
144
|
if (v.blockNumber) assertDecimalBigIntString(v.blockNumber, "blockNumber", errors);
|
|
@@ -133,8 +147,10 @@ function validateIgraTxReceiptArtifact(value) {
|
|
|
133
147
|
function assertValidIgraTxReceiptArtifact(value) {
|
|
134
148
|
const result = validateIgraTxReceiptArtifact(value);
|
|
135
149
|
if (!result.ok) {
|
|
136
|
-
throw new Error(
|
|
137
|
-
|
|
150
|
+
throw new Error(
|
|
151
|
+
`Invalid Igra tx receipt artifact:
|
|
152
|
+
${result.errors.map((e) => `- ${e}`).join("\n")}`
|
|
153
|
+
);
|
|
138
154
|
}
|
|
139
155
|
}
|
|
140
156
|
function validateCommon(v, errors) {
|
|
@@ -161,7 +177,9 @@ function assertEvmAddress(value, field, errors) {
|
|
|
161
177
|
}
|
|
162
178
|
function assertEvmTxHash(value, field, errors) {
|
|
163
179
|
if (typeof value !== "string" || !/^0x[a-fA-F0-9]{64}$/.test(value)) {
|
|
164
|
-
errors.push(
|
|
180
|
+
errors.push(
|
|
181
|
+
`Invalid ${field}: must be a 0x-prefixed 64-character EVM transaction hash`
|
|
182
|
+
);
|
|
165
183
|
}
|
|
166
184
|
}
|
|
167
185
|
function createIgraPlanId(hash) {
|
|
@@ -202,7 +220,10 @@ var SEMANTIC_EXCLUSIONS = /* @__PURE__ */ new Set([
|
|
|
202
220
|
"sourceSignedId",
|
|
203
221
|
"submittedAt",
|
|
204
222
|
"confirmedAt",
|
|
205
|
-
"dagContext"
|
|
223
|
+
"dagContext",
|
|
224
|
+
"executionId",
|
|
225
|
+
"workflowId",
|
|
226
|
+
"signatureMetadata"
|
|
206
227
|
]);
|
|
207
228
|
var CURRENT_HASH_VERSION = 3;
|
|
208
229
|
var STRICT_PATH_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -216,7 +237,16 @@ var STRICT_PATH_KEYS = /* @__PURE__ */ new Set([
|
|
|
216
237
|
"relativePath",
|
|
217
238
|
"absolutePath"
|
|
218
239
|
]);
|
|
219
|
-
function canonicalStringify(obj, version = CURRENT_HASH_VERSION, keyName) {
|
|
240
|
+
function canonicalStringify(obj, version = CURRENT_HASH_VERSION, keyName, isRoot = true) {
|
|
241
|
+
if (typeof obj === "symbol" || typeof obj === "function") {
|
|
242
|
+
throw new Error(`Type ${typeof obj} is not canonicalizable.`);
|
|
243
|
+
}
|
|
244
|
+
if (typeof obj === "undefined") {
|
|
245
|
+
if (isRoot) {
|
|
246
|
+
throw new Error(`Type undefined is not canonicalizable at the root.`);
|
|
247
|
+
}
|
|
248
|
+
return "null";
|
|
249
|
+
}
|
|
220
250
|
if (obj === null || typeof obj !== "object") {
|
|
221
251
|
if (typeof obj === "bigint") {
|
|
222
252
|
if (version >= 2) {
|
|
@@ -234,7 +264,7 @@ function canonicalStringify(obj, version = CURRENT_HASH_VERSION, keyName) {
|
|
|
234
264
|
return JSON.stringify(obj);
|
|
235
265
|
}
|
|
236
266
|
if (Array.isArray(obj)) {
|
|
237
|
-
return "[" + obj.map((item) => canonicalStringify(item, version, keyName)).join(",") + "]";
|
|
267
|
+
return "[" + obj.map((item) => canonicalStringify(item, version, keyName, false)).join(",") + "]";
|
|
238
268
|
}
|
|
239
269
|
if (obj instanceof Map) {
|
|
240
270
|
throw new Error("Map is not canonicalizable. Use a plain object.");
|
|
@@ -254,7 +284,7 @@ function canonicalStringify(obj, version = CURRENT_HASH_VERSION, keyName) {
|
|
|
254
284
|
).sort(deterministicCompare);
|
|
255
285
|
const result = sortedKeys.map((key) => {
|
|
256
286
|
const value = obj[key];
|
|
257
|
-
return JSON.stringify(key) + ":" + canonicalStringify(value, version, key);
|
|
287
|
+
return JSON.stringify(key) + ":" + canonicalStringify(value, version, key, false);
|
|
258
288
|
}).join(",");
|
|
259
289
|
return "{" + result + "}";
|
|
260
290
|
}
|
|
@@ -265,7 +295,10 @@ function calculateContentHash(obj, version = CURRENT_HASH_VERSION) {
|
|
|
265
295
|
|
|
266
296
|
// src/schemas.ts
|
|
267
297
|
import { z } from "zod";
|
|
268
|
-
import {
|
|
298
|
+
import {
|
|
299
|
+
kaspaNetworkIdSchema,
|
|
300
|
+
executionModeSchema
|
|
301
|
+
} from "@hardkas/core";
|
|
269
302
|
var ARTIFACT_VERSION = "1.0.0-alpha";
|
|
270
303
|
var ArtifactLineageSchema = z.object({
|
|
271
304
|
artifactId: z.string(),
|
|
@@ -322,17 +355,21 @@ var TxPlanSchema = BaseArtifactSchema.extend({
|
|
|
322
355
|
amountSompi: z.string(),
|
|
323
356
|
estimatedFeeSompi: z.string(),
|
|
324
357
|
estimatedMass: z.string(),
|
|
325
|
-
inputs: z.array(
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
358
|
+
inputs: z.array(
|
|
359
|
+
z.object({
|
|
360
|
+
outpoint: z.object({
|
|
361
|
+
transactionId: z.string(),
|
|
362
|
+
index: z.number()
|
|
363
|
+
}),
|
|
364
|
+
amountSompi: z.string()
|
|
365
|
+
})
|
|
366
|
+
),
|
|
367
|
+
outputs: z.array(
|
|
368
|
+
z.object({
|
|
369
|
+
address: z.string(),
|
|
370
|
+
amountSompi: z.string()
|
|
371
|
+
})
|
|
372
|
+
),
|
|
336
373
|
change: z.object({
|
|
337
374
|
address: z.string(),
|
|
338
375
|
amountSompi: z.string()
|
|
@@ -346,11 +383,13 @@ var DagContextSchema = z.object({
|
|
|
346
383
|
branchId: z.string().optional(),
|
|
347
384
|
acceptedTxIds: z.array(z.string()).optional(),
|
|
348
385
|
displacedTxIds: z.array(z.string()).optional(),
|
|
349
|
-
conflictSet: z.array(
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
386
|
+
conflictSet: z.array(
|
|
387
|
+
z.object({
|
|
388
|
+
outpoint: z.string(),
|
|
389
|
+
winnerTxId: z.string(),
|
|
390
|
+
loserTxIds: z.array(z.string())
|
|
391
|
+
})
|
|
392
|
+
).optional(),
|
|
354
393
|
nonSelectedContext: z.boolean().optional()
|
|
355
394
|
});
|
|
356
395
|
var LocalnetUtxoSchemaV2 = z.object({
|
|
@@ -367,10 +406,12 @@ var SnapshotSchema = BaseArtifactSchema.extend({
|
|
|
367
406
|
accountsHash: z.string().optional(),
|
|
368
407
|
utxoSetHash: z.string().optional(),
|
|
369
408
|
stateHash: z.string().optional(),
|
|
370
|
-
accounts: z.array(
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
409
|
+
accounts: z.array(
|
|
410
|
+
z.object({
|
|
411
|
+
name: z.string(),
|
|
412
|
+
address: z.string()
|
|
413
|
+
})
|
|
414
|
+
),
|
|
374
415
|
utxos: z.array(LocalnetUtxoSchemaV2)
|
|
375
416
|
});
|
|
376
417
|
var TxReceiptSchema = BaseArtifactSchema.extend({
|
|
@@ -399,9 +440,17 @@ var TxReceiptSchema = BaseArtifactSchema.extend({
|
|
|
399
440
|
errors: z.array(z.string()).optional(),
|
|
400
441
|
metadata: z.any().optional()
|
|
401
442
|
});
|
|
443
|
+
var SignatureEntrySchema = z.object({
|
|
444
|
+
signer: z.string(),
|
|
445
|
+
signature: z.string()
|
|
446
|
+
});
|
|
447
|
+
var SignatureMetadataEntrySchema = z.object({
|
|
448
|
+
signer: z.string(),
|
|
449
|
+
signedAt: z.string().datetime()
|
|
450
|
+
});
|
|
402
451
|
var SignedTxSchema = BaseArtifactSchema.extend({
|
|
403
452
|
schema: z.literal("hardkas.signedTx"),
|
|
404
|
-
status: z.
|
|
453
|
+
status: z.enum(["partially_signed", "signed"]),
|
|
405
454
|
signedId: z.string(),
|
|
406
455
|
sourcePlanId: z.string(),
|
|
407
456
|
networkId: kaspaNetworkIdSchema,
|
|
@@ -409,11 +458,18 @@ var SignedTxSchema = BaseArtifactSchema.extend({
|
|
|
409
458
|
from: AccountRefSchema,
|
|
410
459
|
to: AccountRefSchema,
|
|
411
460
|
amountSompi: z.string(),
|
|
461
|
+
unsignedPayloadHash: z.string().optional(),
|
|
412
462
|
signedTransaction: z.object({
|
|
413
463
|
format: z.string(),
|
|
414
464
|
payload: z.string()
|
|
415
|
-
}),
|
|
465
|
+
}).optional(),
|
|
416
466
|
txId: z.string().optional(),
|
|
467
|
+
multisig: z.object({
|
|
468
|
+
threshold: z.number(),
|
|
469
|
+
requiredSigners: z.array(z.string()),
|
|
470
|
+
signatures: z.array(SignatureEntrySchema)
|
|
471
|
+
}).optional(),
|
|
472
|
+
signatureMetadata: z.array(SignatureMetadataEntrySchema).optional(),
|
|
417
473
|
metadata: z.any().optional()
|
|
418
474
|
});
|
|
419
475
|
var TxTraceSchema = BaseArtifactSchema.extend({
|
|
@@ -421,12 +477,14 @@ var TxTraceSchema = BaseArtifactSchema.extend({
|
|
|
421
477
|
txId: z.string(),
|
|
422
478
|
networkId: kaspaNetworkIdSchema,
|
|
423
479
|
mode: executionModeSchema,
|
|
424
|
-
steps: z.array(
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
480
|
+
steps: z.array(
|
|
481
|
+
z.object({
|
|
482
|
+
phase: z.string(),
|
|
483
|
+
status: z.string(),
|
|
484
|
+
timestamp: z.string().datetime(),
|
|
485
|
+
details: z.any().optional()
|
|
486
|
+
})
|
|
487
|
+
),
|
|
430
488
|
dagContext: DagContextSchema.optional()
|
|
431
489
|
});
|
|
432
490
|
var WorkflowSchema = BaseArtifactSchema.extend({
|
|
@@ -434,14 +492,16 @@ var WorkflowSchema = BaseArtifactSchema.extend({
|
|
|
434
492
|
workflowId: z.string(),
|
|
435
493
|
status: z.enum(["pending", "running", "completed", "failed"]),
|
|
436
494
|
inputs: z.record(z.any()).optional(),
|
|
437
|
-
steps: z.array(
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
495
|
+
steps: z.array(
|
|
496
|
+
z.object({
|
|
497
|
+
type: z.string(),
|
|
498
|
+
status: z.enum(["pending", "success", "failed", "skipped"]),
|
|
499
|
+
startedAt: z.string().datetime().optional(),
|
|
500
|
+
completedAt: z.string().datetime().optional(),
|
|
501
|
+
producedArtifactId: z.string().optional(),
|
|
502
|
+
error: z.string().optional()
|
|
503
|
+
})
|
|
504
|
+
),
|
|
445
505
|
parentArtifacts: z.array(z.string()).optional(),
|
|
446
506
|
producedArtifacts: z.array(z.string()),
|
|
447
507
|
generationRange: z.object({
|
|
@@ -513,8 +573,14 @@ function verifyFeeSemantics(artifact) {
|
|
|
513
573
|
const plan = artifact;
|
|
514
574
|
artifactMass = BigInt(plan.estimatedMass || 0);
|
|
515
575
|
artifactFee = BigInt(plan.estimatedFeeSompi || 0);
|
|
516
|
-
inputTotal = (plan.inputs || []).reduce(
|
|
517
|
-
|
|
576
|
+
inputTotal = (plan.inputs || []).reduce(
|
|
577
|
+
(sum, i) => sum + BigInt(i.amountSompi || 0),
|
|
578
|
+
0n
|
|
579
|
+
);
|
|
580
|
+
outputTotal = (plan.outputs || []).reduce(
|
|
581
|
+
(sum, o) => sum + BigInt(o.amountSompi || 0),
|
|
582
|
+
0n
|
|
583
|
+
);
|
|
518
584
|
if (plan.change) outputTotal += BigInt(plan.change.amountSompi || 0);
|
|
519
585
|
} else if (artifact.schema === "hardkas.txReceipt") {
|
|
520
586
|
const receipt = artifact;
|
|
@@ -524,15 +590,21 @@ function verifyFeeSemantics(artifact) {
|
|
|
524
590
|
}
|
|
525
591
|
const recomputedMass = recomputeMass(artifact);
|
|
526
592
|
if (recomputedMass !== artifactMass && artifactMass !== 0n) {
|
|
527
|
-
issues.push(
|
|
593
|
+
issues.push(
|
|
594
|
+
`Mass mismatch: artifact reports ${artifactMass}, recomputed ${recomputedMass}`
|
|
595
|
+
);
|
|
528
596
|
}
|
|
529
597
|
const impliedFeeRate = artifactMass > 0n ? artifactFee / artifactMass : 1n;
|
|
530
598
|
const recomputedFee = recomputedMass * impliedFeeRate;
|
|
531
599
|
if (recomputedFee !== artifactFee && artifactFee !== 0n) {
|
|
532
|
-
issues.push(
|
|
600
|
+
issues.push(
|
|
601
|
+
`Fee mismatch: artifact reports ${artifactFee}, recomputed ${recomputedFee} (at rate ${impliedFeeRate})`
|
|
602
|
+
);
|
|
533
603
|
}
|
|
534
604
|
if (inputTotal > 0n && inputTotal < outputTotal + artifactFee) {
|
|
535
|
-
issues.push(
|
|
605
|
+
issues.push(
|
|
606
|
+
`Economic violation: Total inputs (${inputTotal}) less than outputs + fee (${outputTotal + artifactFee})`
|
|
607
|
+
);
|
|
536
608
|
}
|
|
537
609
|
if (artifactFee < 0n) {
|
|
538
610
|
issues.push("Economic violation: Negative fee detected");
|
|
@@ -577,17 +649,26 @@ function verifyLineage(artifact, parent, options = {}) {
|
|
|
577
649
|
}
|
|
578
650
|
const isHash = (s) => typeof s === "string" && /^[0-9a-f]{64}$/i.test(s);
|
|
579
651
|
if (!lineage.artifactId || !lineage.lineageId || !lineage.rootArtifactId) {
|
|
580
|
-
addIssue(
|
|
652
|
+
addIssue(
|
|
653
|
+
"INVALID_LINEAGE_STRUCTURE",
|
|
654
|
+
"Lineage block is missing required fields (artifactId, lineageId, or rootArtifactId)"
|
|
655
|
+
);
|
|
581
656
|
} else {
|
|
582
|
-
if (!isHash(lineage.artifactId))
|
|
583
|
-
|
|
584
|
-
if (!isHash(lineage.
|
|
657
|
+
if (!isHash(lineage.artifactId))
|
|
658
|
+
addIssue("INVALID_LINEAGE_FORMAT", "artifactId must be a 64-char hex string");
|
|
659
|
+
if (!isHash(lineage.lineageId))
|
|
660
|
+
addIssue("INVALID_LINEAGE_FORMAT", "lineageId must be a 64-char hex string");
|
|
661
|
+
if (!isHash(lineage.rootArtifactId))
|
|
662
|
+
addIssue("INVALID_LINEAGE_FORMAT", "rootArtifactId must be a 64-char hex string");
|
|
585
663
|
if (lineage.parentArtifactId && !isHash(lineage.parentArtifactId)) {
|
|
586
664
|
addIssue("INVALID_LINEAGE_FORMAT", "parentArtifactId must be a 64-char hex string");
|
|
587
665
|
}
|
|
588
666
|
}
|
|
589
667
|
if (artifact.contentHash && lineage.artifactId !== artifact.contentHash) {
|
|
590
|
-
addIssue(
|
|
668
|
+
addIssue(
|
|
669
|
+
"LINEAGE_IDENTITY_MISMATCH",
|
|
670
|
+
`Lineage artifactId (${lineage.artifactId}) does not match contentHash (${artifact.contentHash})`
|
|
671
|
+
);
|
|
591
672
|
}
|
|
592
673
|
if (parent) {
|
|
593
674
|
const parentLineage = parent.lineage;
|
|
@@ -595,28 +676,50 @@ function verifyLineage(artifact, parent, options = {}) {
|
|
|
595
676
|
addIssue("PARENT_MISSING_LINEAGE", "Parent artifact has no lineage metadata");
|
|
596
677
|
} else {
|
|
597
678
|
if (!lineage.parentArtifactId) {
|
|
598
|
-
addIssue(
|
|
679
|
+
addIssue(
|
|
680
|
+
"MISSING_PARENT_ID",
|
|
681
|
+
"Artifact is missing parentArtifactId reference, but parent was provided for verification."
|
|
682
|
+
);
|
|
599
683
|
} else if (lineage.parentArtifactId !== parentLineage.artifactId) {
|
|
600
|
-
addIssue(
|
|
684
|
+
addIssue(
|
|
685
|
+
"PARENT_ID_MISMATCH",
|
|
686
|
+
`Parent Artifact ID mismatch: expected ${parentLineage.artifactId}, got ${lineage.parentArtifactId}`
|
|
687
|
+
);
|
|
601
688
|
}
|
|
602
689
|
if (lineage.lineageId !== parentLineage.lineageId) {
|
|
603
|
-
addIssue(
|
|
690
|
+
addIssue(
|
|
691
|
+
"LINEAGE_ID_MISMATCH",
|
|
692
|
+
`Lineage ID mismatch: expected ${parentLineage.lineageId}, got ${lineage.lineageId}`
|
|
693
|
+
);
|
|
604
694
|
}
|
|
605
695
|
if (lineage.rootArtifactId !== parentLineage.rootArtifactId) {
|
|
606
|
-
addIssue(
|
|
696
|
+
addIssue(
|
|
697
|
+
"ROOT_ARTIFACT_ID_MISMATCH",
|
|
698
|
+
`Root Artifact ID mismatch: expected ${parentLineage.rootArtifactId}, got ${lineage.rootArtifactId}`
|
|
699
|
+
);
|
|
607
700
|
}
|
|
608
701
|
if (lineage.sequence !== void 0 && parentLineage.sequence !== void 0) {
|
|
609
702
|
if (lineage.sequence <= parentLineage.sequence) {
|
|
610
703
|
const severity = options.strict ? "error" : "warning";
|
|
611
|
-
addIssue(
|
|
704
|
+
addIssue(
|
|
705
|
+
"NON_MONOTONIC_SEQUENCE",
|
|
706
|
+
`Non-monotonic sequence: current (${lineage.sequence}) <= parent (${parentLineage.sequence}).`,
|
|
707
|
+
severity
|
|
708
|
+
);
|
|
612
709
|
}
|
|
613
710
|
}
|
|
614
711
|
}
|
|
615
712
|
if (artifact.networkId !== parent.networkId) {
|
|
616
|
-
addIssue(
|
|
713
|
+
addIssue(
|
|
714
|
+
"NETWORK_MISMATCH",
|
|
715
|
+
`Network mismatch: parent is ${parent.networkId}, current is ${artifact.networkId}`
|
|
716
|
+
);
|
|
617
717
|
}
|
|
618
718
|
if (artifact.mode !== parent.mode) {
|
|
619
|
-
addIssue(
|
|
719
|
+
addIssue(
|
|
720
|
+
"MODE_MISMATCH",
|
|
721
|
+
`Mode mismatch: parent is ${parent.mode}, current is ${artifact.mode}`
|
|
722
|
+
);
|
|
620
723
|
}
|
|
621
724
|
if (lineage.artifactId === lineage.parentArtifactId) {
|
|
622
725
|
addIssue("SELF_PARENT", "Artifact cannot be its own parent.");
|
|
@@ -630,7 +733,10 @@ function verifyLineage(artifact, parent, options = {}) {
|
|
|
630
733
|
};
|
|
631
734
|
const allowed = validTransitions[parent.schema] || [];
|
|
632
735
|
if (!allowed.includes(artifact.schema)) {
|
|
633
|
-
addIssue(
|
|
736
|
+
addIssue(
|
|
737
|
+
"INVALID_TRANSITION",
|
|
738
|
+
`Invalid lineage transition: ${parent.schema} -> ${artifact.schema}`
|
|
739
|
+
);
|
|
634
740
|
}
|
|
635
741
|
}
|
|
636
742
|
return {
|
|
@@ -692,13 +798,19 @@ async function verifyArtifactIntegrity(artifactOrPath) {
|
|
|
692
798
|
return result;
|
|
693
799
|
}
|
|
694
800
|
if (!v.version || !v.schema) {
|
|
695
|
-
addError(
|
|
801
|
+
addError(
|
|
802
|
+
"ARTIFACT_SCHEMA_MISSING",
|
|
803
|
+
"Missing version or schema (Artifact might be v1 or legacy)"
|
|
804
|
+
);
|
|
696
805
|
return result;
|
|
697
806
|
}
|
|
698
807
|
const [currentMajor] = ARTIFACT_VERSION.split(".");
|
|
699
808
|
const [artifactMajor] = v.version.split(".");
|
|
700
809
|
if (currentMajor !== artifactMajor) {
|
|
701
|
-
addError(
|
|
810
|
+
addError(
|
|
811
|
+
"ARTIFACT_SCHEMA_INVALID",
|
|
812
|
+
`Incompatible version: current system is v${currentMajor}, artifact is v${artifactMajor}`
|
|
813
|
+
);
|
|
702
814
|
return result;
|
|
703
815
|
}
|
|
704
816
|
const hashVersion = v.hashVersion || 1;
|
|
@@ -707,7 +819,10 @@ async function verifyArtifactIntegrity(artifactOrPath) {
|
|
|
707
819
|
if (!v.contentHash) {
|
|
708
820
|
addError("ARTIFACT_HASH_MISMATCH", "Missing contentHash field");
|
|
709
821
|
} else if (actualHash !== v.contentHash) {
|
|
710
|
-
addError(
|
|
822
|
+
addError(
|
|
823
|
+
"ARTIFACT_HASH_MISMATCH",
|
|
824
|
+
`Hash mismatch: expected ${v.contentHash}, got ${actualHash}`
|
|
825
|
+
);
|
|
711
826
|
}
|
|
712
827
|
let schema;
|
|
713
828
|
switch (v.schema) {
|
|
@@ -739,9 +854,14 @@ async function verifyArtifactIntegrity(artifactOrPath) {
|
|
|
739
854
|
});
|
|
740
855
|
}
|
|
741
856
|
} else {
|
|
742
|
-
addError(
|
|
857
|
+
addError(
|
|
858
|
+
"ARTIFACT_SCHEMA_INVALID",
|
|
859
|
+
`Unsupported or unknown artifact schema: ${v.schema}`
|
|
860
|
+
);
|
|
743
861
|
}
|
|
744
|
-
result.ok = result.issues.every(
|
|
862
|
+
result.ok = result.issues.every(
|
|
863
|
+
(i) => i.severity !== "error" && i.severity !== "critical"
|
|
864
|
+
);
|
|
745
865
|
return result;
|
|
746
866
|
} catch (e) {
|
|
747
867
|
if (e instanceof SyntaxError) {
|
|
@@ -765,7 +885,8 @@ function verifyArtifactSemantics(artifact, context = {}) {
|
|
|
765
885
|
const addIssue = (issue) => {
|
|
766
886
|
if (issue.severity === "error" || issue.severity === "critical") result.ok = false;
|
|
767
887
|
result.issues.push(issue);
|
|
768
|
-
if (issue.severity === "error" || issue.severity === "critical")
|
|
888
|
+
if (issue.severity === "error" || issue.severity === "critical")
|
|
889
|
+
result.errors.push(issue.message);
|
|
769
890
|
};
|
|
770
891
|
const feeAudit = verifyFeeSemantics(artifact);
|
|
771
892
|
if (!feeAudit.ok) {
|
|
@@ -803,13 +924,43 @@ function verifyArtifactSemantics(artifact, context = {}) {
|
|
|
803
924
|
});
|
|
804
925
|
}
|
|
805
926
|
if (strict) {
|
|
806
|
-
if (!v.workflowId)
|
|
807
|
-
|
|
808
|
-
|
|
927
|
+
if (!v.workflowId)
|
|
928
|
+
addIssue({
|
|
929
|
+
code: "MISSING_WORKFLOW_ID",
|
|
930
|
+
severity: "error",
|
|
931
|
+
message: "Strict mode requires workflowId"
|
|
932
|
+
});
|
|
933
|
+
if (!v.assumptionLevel && v.schema !== "hardkas.workflow.v1")
|
|
934
|
+
addIssue({
|
|
935
|
+
code: "MISSING_ASSUMPTION_LEVEL",
|
|
936
|
+
severity: "error",
|
|
937
|
+
message: "Strict mode requires assumptionLevel"
|
|
938
|
+
});
|
|
939
|
+
if (!v.executionMode && !v.mode)
|
|
940
|
+
addIssue({
|
|
941
|
+
code: "MISSING_EXECUTION_MODE",
|
|
942
|
+
severity: "error",
|
|
943
|
+
message: "Strict mode requires executionMode"
|
|
944
|
+
});
|
|
809
945
|
} else {
|
|
810
|
-
if (!v.workflowId)
|
|
811
|
-
|
|
812
|
-
|
|
946
|
+
if (!v.workflowId)
|
|
947
|
+
addIssue({
|
|
948
|
+
code: "MISSING_WORKFLOW_ID",
|
|
949
|
+
severity: "warning",
|
|
950
|
+
message: "Missing workflowId"
|
|
951
|
+
});
|
|
952
|
+
if (!v.assumptionLevel && v.schema !== "hardkas.workflow.v1")
|
|
953
|
+
addIssue({
|
|
954
|
+
code: "MISSING_ASSUMPTION_LEVEL",
|
|
955
|
+
severity: "warning",
|
|
956
|
+
message: "Missing assumptionLevel"
|
|
957
|
+
});
|
|
958
|
+
if (!v.executionMode && !v.mode)
|
|
959
|
+
addIssue({
|
|
960
|
+
code: "MISSING_EXECUTION_MODE",
|
|
961
|
+
severity: "warning",
|
|
962
|
+
message: "Missing executionMode"
|
|
963
|
+
});
|
|
813
964
|
}
|
|
814
965
|
const networkId = context.networkId || v.networkId;
|
|
815
966
|
const networkIdStr = networkId;
|
|
@@ -840,11 +991,13 @@ function verifyArtifactSemantics(artifact, context = {}) {
|
|
|
840
991
|
async function verifyArtifactReplay(artifact, _context = {}) {
|
|
841
992
|
return {
|
|
842
993
|
ok: false,
|
|
843
|
-
issues: [
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
994
|
+
issues: [
|
|
995
|
+
{
|
|
996
|
+
code: "REPLAY_UNSUPPORTED_CHECK",
|
|
997
|
+
severity: "warning",
|
|
998
|
+
message: "Replay verification (full consensus simulation) is currently unsupported in this build."
|
|
999
|
+
}
|
|
1000
|
+
],
|
|
848
1001
|
errors: ["Replay verification (consensus) unsupported"]
|
|
849
1002
|
};
|
|
850
1003
|
}
|
|
@@ -863,12 +1016,16 @@ var HashInvariant = class {
|
|
|
863
1016
|
if (typeof contentHash !== "string") return [];
|
|
864
1017
|
const actualHash = calculateContentHash(v);
|
|
865
1018
|
if (actualHash !== contentHash) {
|
|
866
|
-
return [
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
1019
|
+
return [
|
|
1020
|
+
{
|
|
1021
|
+
code: this.id,
|
|
1022
|
+
severity: "error",
|
|
1023
|
+
message: `Hash mismatch: expected ${contentHash}, got ${actualHash}`,
|
|
1024
|
+
metadata: {
|
|
1025
|
+
artifactId: typeof v.artifactId === "string" ? v.artifactId : void 0
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
];
|
|
872
1029
|
}
|
|
873
1030
|
return [];
|
|
874
1031
|
}
|
|
@@ -883,19 +1040,23 @@ var SchemaInvariant = class {
|
|
|
883
1040
|
const schema = v.schema;
|
|
884
1041
|
const version = v.version;
|
|
885
1042
|
if (typeof schema !== "string" || typeof version !== "string") {
|
|
886
|
-
return [
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1043
|
+
return [
|
|
1044
|
+
{
|
|
1045
|
+
code: this.id,
|
|
1046
|
+
severity: "error",
|
|
1047
|
+
message: "Artifact missing schema or version metadata"
|
|
1048
|
+
}
|
|
1049
|
+
];
|
|
891
1050
|
}
|
|
892
1051
|
const supportedSchemas = Object.values(ARTIFACT_SCHEMAS);
|
|
893
1052
|
if (!supportedSchemas.includes(schema)) {
|
|
894
|
-
return [
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
1053
|
+
return [
|
|
1054
|
+
{
|
|
1055
|
+
code: this.id,
|
|
1056
|
+
severity: "error",
|
|
1057
|
+
message: `Unsupported schema: ${schema}`
|
|
1058
|
+
}
|
|
1059
|
+
];
|
|
899
1060
|
}
|
|
900
1061
|
return [];
|
|
901
1062
|
}
|
|
@@ -938,12 +1099,16 @@ var BasicLineageInvariant = class {
|
|
|
938
1099
|
if (!lineage || typeof parentArtifactId !== "string" || !artifactStore) return [];
|
|
939
1100
|
const parent = await artifactStore.getArtifact(parentArtifactId);
|
|
940
1101
|
if (!parent) {
|
|
941
|
-
return [
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
1102
|
+
return [
|
|
1103
|
+
{
|
|
1104
|
+
code: this.id,
|
|
1105
|
+
severity: "warning",
|
|
1106
|
+
message: `Parent artifact ${parentArtifactId} not found in store`,
|
|
1107
|
+
metadata: {
|
|
1108
|
+
childId: typeof v.artifactId === "string" ? v.artifactId : void 0
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
];
|
|
947
1112
|
}
|
|
948
1113
|
return [];
|
|
949
1114
|
}
|
|
@@ -971,7 +1136,13 @@ var ReplayInvariant = class {
|
|
|
971
1136
|
};
|
|
972
1137
|
|
|
973
1138
|
// src/invariants/watcher.ts
|
|
974
|
-
import {
|
|
1139
|
+
import {
|
|
1140
|
+
createEventEnvelope,
|
|
1141
|
+
asWorkflowId,
|
|
1142
|
+
asCorrelationId,
|
|
1143
|
+
asNetworkId,
|
|
1144
|
+
asEventSequence
|
|
1145
|
+
} from "@hardkas/core";
|
|
975
1146
|
var InvariantWatcher = class {
|
|
976
1147
|
invariants;
|
|
977
1148
|
eventBus;
|
|
@@ -1109,9 +1280,7 @@ function getMigrationPath(fromVersion, toVersion) {
|
|
|
1109
1280
|
visited.add(fromVersion);
|
|
1110
1281
|
while (queue.length > 0) {
|
|
1111
1282
|
const current = queue.shift();
|
|
1112
|
-
const outgoing = migrationRegistry.filter(
|
|
1113
|
-
(s) => s.fromVersion === current.version
|
|
1114
|
-
);
|
|
1283
|
+
const outgoing = migrationRegistry.filter((s) => s.fromVersion === current.version);
|
|
1115
1284
|
for (const step of outgoing) {
|
|
1116
1285
|
const newPath = [...current.path, step];
|
|
1117
1286
|
if (step.toVersion === toVersion) {
|
|
@@ -1210,7 +1379,9 @@ async function readArtifact(filePath) {
|
|
|
1210
1379
|
if (error.code === "ENOENT") {
|
|
1211
1380
|
throw new Error(`Artifact file not found at ${filePath}`);
|
|
1212
1381
|
}
|
|
1213
|
-
throw new Error(
|
|
1382
|
+
throw new Error(
|
|
1383
|
+
`Failed to read/parse artifact at ${filePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
1384
|
+
);
|
|
1214
1385
|
}
|
|
1215
1386
|
}
|
|
1216
1387
|
async function readTxPlanArtifact(filePath) {
|
|
@@ -1297,13 +1468,20 @@ function formatSignedTxArtifact(artifact) {
|
|
|
1297
1468
|
lines.push("");
|
|
1298
1469
|
lines.push(`Network: ${artifact.networkId}`);
|
|
1299
1470
|
lines.push(`Mode: ${artifact.mode}`);
|
|
1471
|
+
lines.push(`Status: ${(artifact.status || "signed").toUpperCase()}`);
|
|
1300
1472
|
lines.push("");
|
|
1301
1473
|
lines.push(`From: ${artifact.from.address}`);
|
|
1302
1474
|
lines.push(`To: ${artifact.to.address}`);
|
|
1303
1475
|
lines.push(`Amount: ${formatSompi(BigInt(artifact.amountSompi))}`);
|
|
1304
1476
|
lines.push("");
|
|
1305
|
-
|
|
1306
|
-
|
|
1477
|
+
if (artifact.signedTransaction) {
|
|
1478
|
+
lines.push(`Format: ${artifact.signedTransaction.format}`);
|
|
1479
|
+
lines.push(`Tx ID: ${artifact.txId || "unknown (pending broadcast)"}`);
|
|
1480
|
+
} else if (artifact.multisig) {
|
|
1481
|
+
lines.push(
|
|
1482
|
+
`Signatures: ${artifact.multisig.signatures.length} of ${artifact.multisig.threshold} collected`
|
|
1483
|
+
);
|
|
1484
|
+
}
|
|
1307
1485
|
return lines.join("\n");
|
|
1308
1486
|
}
|
|
1309
1487
|
|
|
@@ -1330,7 +1508,12 @@ function utxoFromArtifact(artifact) {
|
|
|
1330
1508
|
address: artifact.address,
|
|
1331
1509
|
amountSompi: safeParseBigInt(artifact.amountSompi, "UtxoArtifact.amountSompi"),
|
|
1332
1510
|
scriptPublicKey: artifact.scriptPublicKey,
|
|
1333
|
-
...artifact.blockDaaScore !== void 0 ? {
|
|
1511
|
+
...artifact.blockDaaScore !== void 0 ? {
|
|
1512
|
+
blockDaaScore: safeParseBigInt(
|
|
1513
|
+
artifact.blockDaaScore,
|
|
1514
|
+
"UtxoArtifact.blockDaaScore"
|
|
1515
|
+
)
|
|
1516
|
+
} : {},
|
|
1334
1517
|
...artifact.isCoinbase !== void 0 ? { isCoinbase: artifact.isCoinbase } : {}
|
|
1335
1518
|
};
|
|
1336
1519
|
}
|
|
@@ -1388,7 +1571,8 @@ function createTxPlanArtifact(options) {
|
|
|
1388
1571
|
address: o.address,
|
|
1389
1572
|
amountSompi: o.amountSompi.toString()
|
|
1390
1573
|
})),
|
|
1391
|
-
rpcUrl: options.rpcUrl
|
|
1574
|
+
rpcUrl: options.rpcUrl,
|
|
1575
|
+
...options.ctx.workflowId ? { workflowId: options.ctx.workflowId } : {}
|
|
1392
1576
|
};
|
|
1393
1577
|
if (options.plan.change) {
|
|
1394
1578
|
artifact.change = {
|
|
@@ -1422,7 +1606,8 @@ function createSimulatedSignedTxArtifact(plan, payload, ctx) {
|
|
|
1422
1606
|
signedTransaction: {
|
|
1423
1607
|
format: "simulated",
|
|
1424
1608
|
payload
|
|
1425
|
-
}
|
|
1609
|
+
},
|
|
1610
|
+
...plan.workflowId ? { workflowId: plan.workflowId } : {}
|
|
1426
1611
|
};
|
|
1427
1612
|
const hash = calculateContentHash(artifact, CURRENT_HASH_VERSION);
|
|
1428
1613
|
artifact.signedId = `signed-${hash.slice(0, 16)}`;
|
|
@@ -1451,7 +1636,8 @@ function createSimulatedTxReceipt(plan, txId, ctx, extra) {
|
|
|
1451
1636
|
daaScore: extra?.daaScore,
|
|
1452
1637
|
preStateHash: extra?.preStateHash,
|
|
1453
1638
|
postStateHash: extra?.postStateHash,
|
|
1454
|
-
dagContext: extra?.dagContext
|
|
1639
|
+
dagContext: extra?.dagContext,
|
|
1640
|
+
...plan.workflowId ? { workflowId: plan.workflowId } : {}
|
|
1455
1641
|
};
|
|
1456
1642
|
const hash = calculateContentHash(artifact, CURRENT_HASH_VERSION);
|
|
1457
1643
|
artifact.contentHash = hash;
|
|
@@ -1470,13 +1656,17 @@ function getBroadcastableSignedTransaction(artifact) {
|
|
|
1470
1656
|
// src/validate.ts
|
|
1471
1657
|
function validateTxPlanArtifact(value) {
|
|
1472
1658
|
const errors = [];
|
|
1473
|
-
if (typeof value !== "object" || value === null)
|
|
1659
|
+
if (typeof value !== "object" || value === null)
|
|
1660
|
+
return { ok: false, errors: ["Artifact must be an object"] };
|
|
1474
1661
|
const v = value;
|
|
1475
|
-
if (v.schema !== ARTIFACT_SCHEMAS.TX_PLAN)
|
|
1662
|
+
if (v.schema !== ARTIFACT_SCHEMAS.TX_PLAN)
|
|
1663
|
+
errors.push(`Invalid schema: expected '${ARTIFACT_SCHEMAS.TX_PLAN}'`);
|
|
1476
1664
|
validateCommon2(v, errors);
|
|
1477
1665
|
if (typeof v.planId !== "string" || !v.planId) errors.push("Missing planId");
|
|
1478
|
-
if (!v.from || typeof v.from.address !== "string")
|
|
1479
|
-
|
|
1666
|
+
if (!v.from || typeof v.from.address !== "string")
|
|
1667
|
+
errors.push("Missing or invalid 'from' address");
|
|
1668
|
+
if (!v.to || typeof v.to.address !== "string")
|
|
1669
|
+
errors.push("Missing or invalid 'to' address");
|
|
1480
1670
|
assertDecimalBigIntString2(v.amountSompi, "amountSompi", errors);
|
|
1481
1671
|
if (!Array.isArray(v.inputs)) errors.push("Missing or invalid 'inputs' array");
|
|
1482
1672
|
if (!Array.isArray(v.outputs)) errors.push("Missing or invalid 'outputs' array");
|
|
@@ -1484,18 +1674,24 @@ function validateTxPlanArtifact(value) {
|
|
|
1484
1674
|
}
|
|
1485
1675
|
function assertValidTxPlanArtifact(value) {
|
|
1486
1676
|
const result = validateTxPlanArtifact(value);
|
|
1487
|
-
if (!result.ok)
|
|
1488
|
-
|
|
1677
|
+
if (!result.ok)
|
|
1678
|
+
throw new Error(
|
|
1679
|
+
`Invalid tx plan artifact:
|
|
1680
|
+
${result.errors.map((e) => `- ${e}`).join("\n")}`
|
|
1681
|
+
);
|
|
1489
1682
|
}
|
|
1490
1683
|
function validateSignedTxArtifact(value) {
|
|
1491
1684
|
const errors = [];
|
|
1492
|
-
if (typeof value !== "object" || value === null)
|
|
1685
|
+
if (typeof value !== "object" || value === null)
|
|
1686
|
+
return { ok: false, errors: ["Artifact must be an object"] };
|
|
1493
1687
|
const v = value;
|
|
1494
|
-
if (v.schema !== ARTIFACT_SCHEMAS.SIGNED_TX)
|
|
1688
|
+
if (v.schema !== ARTIFACT_SCHEMAS.SIGNED_TX)
|
|
1689
|
+
errors.push(`Invalid schema: expected '${ARTIFACT_SCHEMAS.SIGNED_TX}'`);
|
|
1495
1690
|
validateCommon2(v, errors);
|
|
1496
1691
|
if (v.status !== "signed") errors.push("Invalid status: expected 'signed'");
|
|
1497
1692
|
if (typeof v.signedId !== "string" || !v.signedId) errors.push("Missing signedId");
|
|
1498
|
-
if (typeof v.sourcePlanId !== "string" || !v.sourcePlanId)
|
|
1693
|
+
if (typeof v.sourcePlanId !== "string" || !v.sourcePlanId)
|
|
1694
|
+
errors.push("Missing sourcePlanId");
|
|
1499
1695
|
if (!v.signedTransaction) {
|
|
1500
1696
|
errors.push("Missing signedTransaction object");
|
|
1501
1697
|
} else {
|
|
@@ -1508,16 +1704,22 @@ function validateSignedTxArtifact(value) {
|
|
|
1508
1704
|
}
|
|
1509
1705
|
function assertValidSignedTxArtifact(value) {
|
|
1510
1706
|
const result = validateSignedTxArtifact(value);
|
|
1511
|
-
if (!result.ok)
|
|
1512
|
-
|
|
1707
|
+
if (!result.ok)
|
|
1708
|
+
throw new Error(
|
|
1709
|
+
`Invalid signed tx artifact:
|
|
1710
|
+
${result.errors.map((e) => `- ${e}`).join("\n")}`
|
|
1711
|
+
);
|
|
1513
1712
|
}
|
|
1514
1713
|
function validateTxReceiptArtifact(value) {
|
|
1515
1714
|
const errors = [];
|
|
1516
|
-
if (typeof value !== "object" || value === null)
|
|
1715
|
+
if (typeof value !== "object" || value === null)
|
|
1716
|
+
return { ok: false, errors: ["Artifact must be an object"] };
|
|
1517
1717
|
const v = value;
|
|
1518
|
-
if (v.schema !== ARTIFACT_SCHEMAS.TX_RECEIPT)
|
|
1718
|
+
if (v.schema !== ARTIFACT_SCHEMAS.TX_RECEIPT)
|
|
1719
|
+
errors.push(`Invalid schema: expected '${ARTIFACT_SCHEMAS.TX_RECEIPT}'`);
|
|
1519
1720
|
validateCommon2(v, errors);
|
|
1520
|
-
if (!["submitted", "confirmed", "failed"].includes(v.status))
|
|
1721
|
+
if (!["submitted", "confirmed", "failed"].includes(v.status))
|
|
1722
|
+
errors.push("Invalid status");
|
|
1521
1723
|
if (typeof v.txId !== "string" || !v.txId) errors.push("Missing txId");
|
|
1522
1724
|
assertDecimalBigIntString2(v.amountSompi, "amountSompi", errors);
|
|
1523
1725
|
assertDecimalBigIntString2(v.feeSompi, "feeSompi", errors);
|
|
@@ -1525,11 +1727,15 @@ function validateTxReceiptArtifact(value) {
|
|
|
1525
1727
|
}
|
|
1526
1728
|
function assertValidTxReceiptArtifact(value) {
|
|
1527
1729
|
const result = validateTxReceiptArtifact(value);
|
|
1528
|
-
if (!result.ok)
|
|
1529
|
-
|
|
1730
|
+
if (!result.ok)
|
|
1731
|
+
throw new Error(
|
|
1732
|
+
`Invalid tx receipt artifact:
|
|
1733
|
+
${result.errors.map((e) => `- ${e}`).join("\n")}`
|
|
1734
|
+
);
|
|
1530
1735
|
}
|
|
1531
1736
|
function validateArtifact(data) {
|
|
1532
|
-
if (!data || typeof data !== "object")
|
|
1737
|
+
if (!data || typeof data !== "object")
|
|
1738
|
+
return { ok: false, errors: ["Artifact must be an object"] };
|
|
1533
1739
|
const v = data;
|
|
1534
1740
|
const schema = v.schema;
|
|
1535
1741
|
switch (schema) {
|
|
@@ -1552,7 +1758,8 @@ function validateArtifact(data) {
|
|
|
1552
1758
|
function validateCommon2(v, errors) {
|
|
1553
1759
|
if (!v.hardkasVersion) errors.push("Missing hardkasVersion");
|
|
1554
1760
|
if (typeof v.networkId !== "string" || !v.networkId) errors.push("Missing networkId");
|
|
1555
|
-
if (!["simulated", "node", "rpc", "l2-rpc", "real"].includes(v.mode))
|
|
1761
|
+
if (!["simulated", "node", "rpc", "l2-rpc", "real"].includes(v.mode))
|
|
1762
|
+
errors.push("Invalid mode");
|
|
1556
1763
|
if (!v.createdAt) errors.push("Missing createdAt");
|
|
1557
1764
|
}
|
|
1558
1765
|
function assertDecimalBigIntString2(value, field, errors) {
|
|
@@ -1589,9 +1796,18 @@ async function explainArtifact(artifactUnknown) {
|
|
|
1589
1796
|
security: {
|
|
1590
1797
|
strictOk: status === "valid",
|
|
1591
1798
|
issues: [
|
|
1592
|
-
...integrity.issues.map((i) => ({
|
|
1593
|
-
|
|
1594
|
-
|
|
1799
|
+
...integrity.issues.map((i) => ({
|
|
1800
|
+
...i,
|
|
1801
|
+
severity: i.severity
|
|
1802
|
+
})),
|
|
1803
|
+
...semantic.issues.map((i) => ({
|
|
1804
|
+
...i,
|
|
1805
|
+
severity: i.severity
|
|
1806
|
+
})),
|
|
1807
|
+
...lineage.issues.map((i) => ({
|
|
1808
|
+
...i,
|
|
1809
|
+
severity: i.severity
|
|
1810
|
+
}))
|
|
1595
1811
|
]
|
|
1596
1812
|
},
|
|
1597
1813
|
metadata: artifact.metadata || {}
|
|
@@ -1603,9 +1819,17 @@ async function explainArtifact(artifactUnknown) {
|
|
|
1603
1819
|
let changeAmount = 0n;
|
|
1604
1820
|
if (type === "txPlan") {
|
|
1605
1821
|
const plan = artifact;
|
|
1606
|
-
inputTotal = (plan.inputs || []).reduce(
|
|
1607
|
-
|
|
1608
|
-
|
|
1822
|
+
inputTotal = (plan.inputs || []).reduce(
|
|
1823
|
+
(sum, i) => sum + BigInt(i.amountSompi || 0),
|
|
1824
|
+
0n
|
|
1825
|
+
);
|
|
1826
|
+
outputTotal = (plan.outputs || []).reduce(
|
|
1827
|
+
(sum, o) => sum + BigInt(o.amountSompi || 0),
|
|
1828
|
+
0n
|
|
1829
|
+
);
|
|
1830
|
+
changeAmount = plan.change ? BigInt(
|
|
1831
|
+
plan.change.amountSompi || 0
|
|
1832
|
+
) : 0n;
|
|
1609
1833
|
}
|
|
1610
1834
|
explanation.economics = {
|
|
1611
1835
|
ok: feeAudit.ok,
|
|
@@ -1678,7 +1902,9 @@ async function listIgraTxReceiptArtifacts(options) {
|
|
|
1678
1902
|
}
|
|
1679
1903
|
function validateTxHash(txHash) {
|
|
1680
1904
|
if (!/^0x[a-fA-F0-9]{64}$/.test(txHash)) {
|
|
1681
|
-
throw new Error(
|
|
1905
|
+
throw new Error(
|
|
1906
|
+
`Invalid EVM txHash: must be a 0x-prefixed 64-character hex string. Got: ${txHash}`
|
|
1907
|
+
);
|
|
1682
1908
|
}
|
|
1683
1909
|
}
|
|
1684
1910
|
|
|
@@ -1757,7 +1983,10 @@ function createDeploymentRecord(opts) {
|
|
|
1757
1983
|
...opts.payloadHash ? { payloadHash: opts.payloadHash } : {},
|
|
1758
1984
|
...opts.notes ? { notes: opts.notes } : {}
|
|
1759
1985
|
};
|
|
1760
|
-
const contentHash = calculateContentHash(
|
|
1986
|
+
const contentHash = calculateContentHash(
|
|
1987
|
+
recordDraft,
|
|
1988
|
+
CURRENT_HASH_VERSION
|
|
1989
|
+
);
|
|
1761
1990
|
return {
|
|
1762
1991
|
...recordDraft,
|
|
1763
1992
|
contentHash
|
|
@@ -1770,7 +1999,10 @@ function updateDeploymentStatus(record, newStatus, txId) {
|
|
|
1770
1999
|
deployedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1771
2000
|
...txId ? { txId } : {}
|
|
1772
2001
|
};
|
|
1773
|
-
const contentHash = calculateContentHash(
|
|
2002
|
+
const contentHash = calculateContentHash(
|
|
2003
|
+
updatedDraft,
|
|
2004
|
+
CURRENT_HASH_VERSION
|
|
2005
|
+
);
|
|
1774
2006
|
return {
|
|
1775
2007
|
...updatedDraft,
|
|
1776
2008
|
contentHash
|
|
@@ -1789,7 +2021,13 @@ async function saveDeployment(rootDir, record) {
|
|
|
1789
2021
|
return targetPath;
|
|
1790
2022
|
}
|
|
1791
2023
|
async function loadDeployment(rootDir, networkId, label) {
|
|
1792
|
-
const targetPath = path3.join(
|
|
2024
|
+
const targetPath = path3.join(
|
|
2025
|
+
rootDir,
|
|
2026
|
+
".hardkas",
|
|
2027
|
+
"deployments",
|
|
2028
|
+
networkId,
|
|
2029
|
+
`${label}.json`
|
|
2030
|
+
);
|
|
1793
2031
|
if (!existsSync(targetPath)) return null;
|
|
1794
2032
|
const content = await fs4.readFile(targetPath, "utf-8");
|
|
1795
2033
|
return JSON.parse(content);
|
|
@@ -1821,7 +2059,9 @@ async function listDeployments(rootDir, networkId) {
|
|
|
1821
2059
|
}
|
|
1822
2060
|
}
|
|
1823
2061
|
}
|
|
1824
|
-
return summaries.sort(
|
|
2062
|
+
return summaries.sort(
|
|
2063
|
+
(a, b) => new Date(b.deployedAt).getTime() - new Date(a.deployedAt).getTime()
|
|
2064
|
+
);
|
|
1825
2065
|
}
|
|
1826
2066
|
async function updateDeployment(rootDir, networkId, label, update) {
|
|
1827
2067
|
const existing = await loadDeployment(rootDir, networkId, label);
|
|
@@ -1837,7 +2077,13 @@ async function updateDeployment(rootDir, networkId, label, update) {
|
|
|
1837
2077
|
return updated;
|
|
1838
2078
|
}
|
|
1839
2079
|
async function deleteDeployment(rootDir, networkId, label) {
|
|
1840
|
-
const targetPath = path3.join(
|
|
2080
|
+
const targetPath = path3.join(
|
|
2081
|
+
rootDir,
|
|
2082
|
+
".hardkas",
|
|
2083
|
+
"deployments",
|
|
2084
|
+
networkId,
|
|
2085
|
+
`${label}.json`
|
|
2086
|
+
);
|
|
1841
2087
|
if (!existsSync(targetPath)) return false;
|
|
1842
2088
|
await fs4.unlink(targetPath);
|
|
1843
2089
|
return true;
|
|
@@ -1865,6 +2111,8 @@ export {
|
|
|
1865
2111
|
SchemaInvariant,
|
|
1866
2112
|
ScriptCapabilitySchema,
|
|
1867
2113
|
ScriptMetadataSchema,
|
|
2114
|
+
SignatureEntrySchema,
|
|
2115
|
+
SignatureMetadataEntrySchema,
|
|
1868
2116
|
SignedTxSchema,
|
|
1869
2117
|
SnapshotSchema,
|
|
1870
2118
|
TxPlanSchema,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hardkas/artifacts",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4-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/
|
|
28
|
-
"@hardkas/
|
|
27
|
+
"@hardkas/tx-builder": "0.7.4-alpha",
|
|
28
|
+
"@hardkas/core": "0.7.4-alpha"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"tsup": "^8.3.5",
|