@hardkas/l2 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.js +68 -28
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -137,11 +137,15 @@ function validateL2Profile(profile) {
|
|
|
137
137
|
return { ok: false, errors: ["Profile must be an object"] };
|
|
138
138
|
}
|
|
139
139
|
if (profile.schema !== "hardkas.l2Profile.v1") {
|
|
140
|
-
errors.push(
|
|
140
|
+
errors.push(
|
|
141
|
+
`Invalid schema: expected 'hardkas.l2Profile.v1', got '${profile.schema}'`
|
|
142
|
+
);
|
|
141
143
|
}
|
|
142
144
|
if (profile.security) {
|
|
143
145
|
if (profile.security.bridgePhase !== "zk" && profile.security.trustlessExit === true) {
|
|
144
|
-
errors.push(
|
|
146
|
+
errors.push(
|
|
147
|
+
`Security invariant violation: trustlessExit=true is only allowed when bridgePhase='zk'. Current phase: ${profile.security.bridgePhase}`
|
|
148
|
+
);
|
|
145
149
|
}
|
|
146
150
|
}
|
|
147
151
|
return {
|
|
@@ -168,7 +172,9 @@ var EvmJsonRpcClient = class {
|
|
|
168
172
|
this.timeoutMs = options.timeoutMs ?? 1e4;
|
|
169
173
|
this.fetcher = options.fetcher ?? globalThis.fetch;
|
|
170
174
|
if (!this.fetcher) {
|
|
171
|
-
throw new Error(
|
|
175
|
+
throw new Error(
|
|
176
|
+
"No fetch implementation found. Ensure global fetch is available or provide a fetcher."
|
|
177
|
+
);
|
|
172
178
|
}
|
|
173
179
|
}
|
|
174
180
|
async callRpc(method, params = []) {
|
|
@@ -193,7 +199,9 @@ var EvmJsonRpcClient = class {
|
|
|
193
199
|
}
|
|
194
200
|
const json = await response.json();
|
|
195
201
|
if (json.error) {
|
|
196
|
-
throw new Error(
|
|
202
|
+
throw new Error(
|
|
203
|
+
`JSON-RPC error: ${json.error.message} (code: ${json.error.code})`
|
|
204
|
+
);
|
|
197
205
|
}
|
|
198
206
|
return json.result;
|
|
199
207
|
} finally {
|
|
@@ -219,7 +227,10 @@ var EvmJsonRpcClient = class {
|
|
|
219
227
|
}
|
|
220
228
|
async getTransactionCount(address, blockTag = "latest") {
|
|
221
229
|
this.validateAddress(address);
|
|
222
|
-
const hex = await this.callRpc("eth_getTransactionCount", [
|
|
230
|
+
const hex = await this.callRpc("eth_getTransactionCount", [
|
|
231
|
+
address,
|
|
232
|
+
blockTag
|
|
233
|
+
]);
|
|
223
234
|
return BigInt(hex);
|
|
224
235
|
}
|
|
225
236
|
async call(request, blockTag = "latest") {
|
|
@@ -241,7 +252,9 @@ var EvmJsonRpcClient = class {
|
|
|
241
252
|
}
|
|
242
253
|
validateTxHash(txHash, fieldName) {
|
|
243
254
|
if (!/^0x[a-fA-F0-9]{64}$/.test(txHash)) {
|
|
244
|
-
throw new Error(
|
|
255
|
+
throw new Error(
|
|
256
|
+
`Invalid EVM ${fieldName}: must be a 0x-prefixed 64-character hex string.`
|
|
257
|
+
);
|
|
245
258
|
}
|
|
246
259
|
}
|
|
247
260
|
validateCallRequest(request) {
|
|
@@ -257,12 +270,16 @@ var EvmJsonRpcClient = class {
|
|
|
257
270
|
throw new Error(`Invalid ${fieldName}: must be a non-empty string.`);
|
|
258
271
|
}
|
|
259
272
|
if (!/^0x[a-fA-F0-9]{40}$/.test(address)) {
|
|
260
|
-
throw new Error(
|
|
273
|
+
throw new Error(
|
|
274
|
+
`Invalid EVM ${fieldName}: must be a 0x-prefixed 40-character hex string.`
|
|
275
|
+
);
|
|
261
276
|
}
|
|
262
277
|
}
|
|
263
278
|
validateHexData(data, fieldName) {
|
|
264
279
|
if (!/^0x([a-fA-F0-9]{2})*$/.test(data)) {
|
|
265
|
-
throw new Error(
|
|
280
|
+
throw new Error(
|
|
281
|
+
`Invalid hex ${fieldName}: must be a 0x-prefixed even-length hex string.`
|
|
282
|
+
);
|
|
266
283
|
}
|
|
267
284
|
}
|
|
268
285
|
validateHexQuantity(qty, fieldName) {
|
|
@@ -351,31 +368,45 @@ var ViemIgraTxSigner = class {
|
|
|
351
368
|
async sign(input) {
|
|
352
369
|
const { plan, account } = input;
|
|
353
370
|
if (plan.schema !== "hardkas.igraTxPlan.v1") {
|
|
354
|
-
throw new Error(
|
|
371
|
+
throw new Error(
|
|
372
|
+
`Invalid plan schema: ${plan.schema}. Expected hardkas.igraTxPlan.v1`
|
|
373
|
+
);
|
|
355
374
|
}
|
|
356
375
|
if (plan.status !== "built") {
|
|
357
|
-
throw new Error(
|
|
376
|
+
throw new Error(
|
|
377
|
+
`Plan must be in 'built' status to be signed. Current: ${plan.status}`
|
|
378
|
+
);
|
|
358
379
|
}
|
|
359
380
|
if (!account) {
|
|
360
381
|
throw new Error("Signer requires an account input.");
|
|
361
382
|
}
|
|
362
383
|
if (!account.privateKey) {
|
|
363
|
-
throw new Error(
|
|
384
|
+
throw new Error(
|
|
385
|
+
`Account '${account.name}' has no private key available for signing.`
|
|
386
|
+
);
|
|
364
387
|
}
|
|
365
388
|
if (!account.address || !account.address.startsWith("0x")) {
|
|
366
389
|
throw new Error("Igra L2 signing requires an EVM 0x account address.");
|
|
367
390
|
}
|
|
368
391
|
if (plan.request.from && plan.request.from.toLowerCase() !== account.address.toLowerCase()) {
|
|
369
|
-
throw new Error(
|
|
392
|
+
throw new Error(
|
|
393
|
+
`Account address '${account.address}' does not match plan 'from' address '${plan.request.from}'.`
|
|
394
|
+
);
|
|
370
395
|
}
|
|
371
396
|
if (plan.request.gasLimit === void 0 || plan.request.gasLimit === null) {
|
|
372
|
-
throw new Error(
|
|
397
|
+
throw new Error(
|
|
398
|
+
"Igra transaction plan is incomplete. Rebuild the plan with gas limit."
|
|
399
|
+
);
|
|
373
400
|
}
|
|
374
401
|
if (plan.request.gasPriceWei === void 0 || plan.request.gasPriceWei === null) {
|
|
375
|
-
throw new Error(
|
|
402
|
+
throw new Error(
|
|
403
|
+
"Igra transaction plan is incomplete. Rebuild the plan with gas price."
|
|
404
|
+
);
|
|
376
405
|
}
|
|
377
406
|
if (plan.request.nonce === void 0 || plan.request.nonce === null) {
|
|
378
|
-
throw new Error(
|
|
407
|
+
throw new Error(
|
|
408
|
+
"Igra transaction plan is incomplete. Rebuild the plan with nonce."
|
|
409
|
+
);
|
|
379
410
|
}
|
|
380
411
|
let normalizedPk = account.privateKey;
|
|
381
412
|
if (!normalizedPk.startsWith("0x")) {
|
|
@@ -391,7 +422,9 @@ var ViemIgraTxSigner = class {
|
|
|
391
422
|
viem = await this.viemLoader();
|
|
392
423
|
accounts = await this.accountsLoader();
|
|
393
424
|
} catch (e) {
|
|
394
|
-
throw new Error(
|
|
425
|
+
throw new Error(
|
|
426
|
+
"EVM signing dependency (viem) is not installed. Install viem to enable Igra L2 signing."
|
|
427
|
+
);
|
|
395
428
|
}
|
|
396
429
|
try {
|
|
397
430
|
const viemAccount = accounts.privateKeyToAccount(normalizedPk);
|
|
@@ -411,7 +444,9 @@ var ViemIgraTxSigner = class {
|
|
|
411
444
|
txHash: viem.keccak256 ? viem.keccak256(signed) : void 0
|
|
412
445
|
};
|
|
413
446
|
} catch (e) {
|
|
414
|
-
throw new Error(
|
|
447
|
+
throw new Error(
|
|
448
|
+
`Igra signing failed: ${e instanceof Error ? e.message : String(e)}`
|
|
449
|
+
);
|
|
415
450
|
}
|
|
416
451
|
}
|
|
417
452
|
};
|
|
@@ -454,14 +489,12 @@ var IGRA_BRIDGE_ASSUMPTIONS = {
|
|
|
454
489
|
"pre-ZK implies stronger trust assumptions.",
|
|
455
490
|
"MPC implies threshold committee trust assumptions.",
|
|
456
491
|
"ZK phase enables validity-proof based trustless exit.",
|
|
457
|
-
"HardKAS does not perform bridge operations in 0.7.
|
|
492
|
+
"HardKAS does not perform bridge operations in 0.7.4-alpha."
|
|
458
493
|
],
|
|
459
494
|
updatedAt: "2026-05-07T00:00:00Z"
|
|
460
495
|
// Reference date for Phase 33
|
|
461
496
|
};
|
|
462
|
-
var BRIDGE_ASSUMPTIONS_REGISTRY = [
|
|
463
|
-
IGRA_BRIDGE_ASSUMPTIONS
|
|
464
|
-
];
|
|
497
|
+
var BRIDGE_ASSUMPTIONS_REGISTRY = [IGRA_BRIDGE_ASSUMPTIONS];
|
|
465
498
|
function getL2BridgeAssumptions(network) {
|
|
466
499
|
return BRIDGE_ASSUMPTIONS_REGISTRY.find((a) => a.l2Network === network) || null;
|
|
467
500
|
}
|
|
@@ -470,25 +503,32 @@ function listL2BridgeAssumptions() {
|
|
|
470
503
|
}
|
|
471
504
|
function validateL2BridgeAssumptions(input) {
|
|
472
505
|
const errors = [];
|
|
473
|
-
if (!input || typeof input !== "object")
|
|
506
|
+
if (!input || typeof input !== "object")
|
|
507
|
+
return { ok: false, errors: ["Input must be an object"] };
|
|
474
508
|
const v = input;
|
|
475
|
-
if (v.schema !== "hardkas.l2BridgeAssumptions.v1")
|
|
476
|
-
|
|
509
|
+
if (v.schema !== "hardkas.l2BridgeAssumptions.v1")
|
|
510
|
+
errors.push("Invalid schema: expected 'hardkas.l2BridgeAssumptions.v1'");
|
|
511
|
+
if (typeof v.hardkasVersion !== "string" || !v.hardkasVersion)
|
|
512
|
+
errors.push("Missing hardkasVersion");
|
|
477
513
|
if (typeof v.l2Network !== "string" || !v.l2Network) errors.push("Missing l2Network");
|
|
478
514
|
const validPhases = ["pre-zk", "mpc", "zk", "unknown"];
|
|
479
|
-
if (!validPhases.includes(v.bridgePhase))
|
|
515
|
+
if (!validPhases.includes(v.bridgePhase))
|
|
516
|
+
errors.push(`Invalid bridgePhase: ${v.bridgePhase}`);
|
|
480
517
|
if (v.bridgePhase !== "zk" && v.trustlessExit === true) {
|
|
481
518
|
errors.push("trustlessExit must be false if bridgePhase is not 'zk'");
|
|
482
519
|
}
|
|
483
|
-
if (!Array.isArray(v.notes) || v.notes.length === 0)
|
|
520
|
+
if (!Array.isArray(v.notes) || v.notes.length === 0)
|
|
521
|
+
errors.push("Notes must be a non-empty array");
|
|
484
522
|
if (!v.updatedAt) errors.push("Missing updatedAt");
|
|
485
523
|
return { ok: errors.length === 0, errors };
|
|
486
524
|
}
|
|
487
525
|
function assertValidL2BridgeAssumptions(input) {
|
|
488
526
|
const { ok, errors } = validateL2BridgeAssumptions(input);
|
|
489
527
|
if (!ok) {
|
|
490
|
-
throw new Error(
|
|
491
|
-
|
|
528
|
+
throw new Error(
|
|
529
|
+
`Invalid L2 bridge assumptions:
|
|
530
|
+
${errors.map((e) => `- ${e}`).join("\n")}`
|
|
531
|
+
);
|
|
492
532
|
}
|
|
493
533
|
return input;
|
|
494
534
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hardkas/l2",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4-alpha",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/index.js"
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"viem": "^2.48.8",
|
|
11
|
-
"@hardkas/artifacts": "0.7.
|
|
11
|
+
"@hardkas/artifacts": "0.7.4-alpha"
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"tsup": "^8.3.5",
|