@elgora/cli 12.0.0 → 12.1.0
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/README.md +3 -1
- package/dist/cli.js +451 -152
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -38,6 +38,8 @@ answer.
|
|
|
38
38
|
returns an issue list and exits non-zero on failure. It needs no wallet or
|
|
39
39
|
network and does not replace hosted semantic readiness review.
|
|
40
40
|
- `spec-commitment` reproduces the challenge's `spec_commitment` offline.
|
|
41
|
+
- `solver:solvable` lists open bounties still before their Submission
|
|
42
|
+
deadline, filtered by escrow amount, time left and challenge keywords.
|
|
41
43
|
- `solver:check <bounty_id> <folder_or_file>` runs the Submission check that
|
|
42
44
|
`solver:submit` and `guardian:open` also run, without submitting, and exits
|
|
43
45
|
1 on any issue.
|
|
@@ -164,7 +166,7 @@ for that invocation without touching the environment. It takes a network name
|
|
|
164
166
|
passed — for that run only:
|
|
165
167
|
|
|
166
168
|
```sh
|
|
167
|
-
elgora-cli
|
|
169
|
+
elgora-cli spec-commitment bounty_challenge.md # Base mainnet, the default
|
|
168
170
|
elgora-cli claim --network base-sepolia 7 # testnet, by name
|
|
169
171
|
elgora-cli claim --network 84532 7 # the same, by chain id
|
|
170
172
|
export ELGORA_CHAIN_ID=84532 # testnet for every run in this shell
|
package/dist/cli.js
CHANGED
|
@@ -1233,11 +1233,6 @@ function extractFlagValue(argv, flag) {
|
|
|
1233
1233
|
return { value, argv: remaining };
|
|
1234
1234
|
}
|
|
1235
1235
|
|
|
1236
|
-
// ../../packages/core/src/bounty-challenge-headings.ts
|
|
1237
|
-
function hasLineBreak(text) {
|
|
1238
|
-
return /[\r\u2028\u2029]/.test(text);
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
1236
|
// ../../packages/core/src/bounty-challenge-markdown.ts
|
|
1242
1237
|
import { keccak256 as keccak2562, toBytes as toBytes2 } from "viem";
|
|
1243
1238
|
import { z as z3 } from "zod";
|
|
@@ -1346,6 +1341,7 @@ function isKnownProtocolProfile(version) {
|
|
|
1346
1341
|
|
|
1347
1342
|
// ../../packages/core/src/bounty-challenge-markdown.ts
|
|
1348
1343
|
var FRONTMATTER_DELIMITER = "---";
|
|
1344
|
+
var YAML_LIST_ITEM = /^\s+-\s/;
|
|
1349
1345
|
var ALLOWED_FRONTMATTER_KEYS = [
|
|
1350
1346
|
...BOUNTY_CHALLENGE_FRONTMATTER_KEYS,
|
|
1351
1347
|
...BOUNTY_CHALLENGE_OPTIONAL_FRONTMATTER_KEYS
|
|
@@ -1461,6 +1457,15 @@ function splitConstraintsBlock(lines, issues) {
|
|
|
1461
1457
|
index += 1;
|
|
1462
1458
|
const parsed = frontmatterEntry(entry.trim());
|
|
1463
1459
|
if (!parsed || parsed.value === "") {
|
|
1460
|
+
if (parsed && YAML_LIST_ITEM.test(lines[index + 1] ?? "")) {
|
|
1461
|
+
while (YAML_LIST_ITEM.test(lines[index + 1] ?? "")) index += 1;
|
|
1462
|
+
seenKeys.add(parsed.key);
|
|
1463
|
+
issues.push({
|
|
1464
|
+
path: `frontmatter.constraints.${parsed.key}`,
|
|
1465
|
+
message: `"${parsed.key}" must be an inline list on one line, written as ${parsed.key}: [a, b]`
|
|
1466
|
+
});
|
|
1467
|
+
continue;
|
|
1468
|
+
}
|
|
1464
1469
|
issues.push({
|
|
1465
1470
|
path: `frontmatter.constraints.line_${index + 2}`,
|
|
1466
1471
|
message: "Constraint entries must use snake_case_key: value"
|
|
@@ -1500,6 +1505,9 @@ function frontmatterEntry(line) {
|
|
|
1500
1505
|
const value = line.slice(key.length).trimStart();
|
|
1501
1506
|
return hasLineBreak(value) ? null : { key: key.slice(0, -1), value };
|
|
1502
1507
|
}
|
|
1508
|
+
function hasLineBreak(text) {
|
|
1509
|
+
return /[\r\u2028\u2029]/.test(text);
|
|
1510
|
+
}
|
|
1503
1511
|
function parsePublicationTermsFrontmatter(lines, issues) {
|
|
1504
1512
|
const values = /* @__PURE__ */ new Map();
|
|
1505
1513
|
let foundUnsupportedKey = false;
|
|
@@ -4302,6 +4310,9 @@ function settlementAmounts(escrowAmount, treasuryFeeBps, guardianFeeBps) {
|
|
|
4302
4310
|
};
|
|
4303
4311
|
}
|
|
4304
4312
|
|
|
4313
|
+
// ../../packages/core/src/api/bounty-list.ts
|
|
4314
|
+
import { z as z6 } from "zod";
|
|
4315
|
+
|
|
4305
4316
|
// ../../packages/core/src/api/bounty-preparation.ts
|
|
4306
4317
|
import { ZodError, z as z5 } from "zod";
|
|
4307
4318
|
|
|
@@ -4349,6 +4360,12 @@ var ELGORA_HUB_OWNERSHIP_READ_ABI = [
|
|
|
4349
4360
|
getAbiItem2({ abi: ELGORA_HUB_ABI, name: "pendingOwner" }),
|
|
4350
4361
|
...ELGORA_HUB_ERRORS
|
|
4351
4362
|
];
|
|
4363
|
+
var SUBMISSION_CAP_READ_ABI = [
|
|
4364
|
+
getAbiItem2({ abi: ELGORA_HUB_ABI, name: "submissionGuard" }),
|
|
4365
|
+
...parseAbi([
|
|
4366
|
+
"function maximumSubmissions(uint256 bountyId) view returns (uint256)"
|
|
4367
|
+
])
|
|
4368
|
+
];
|
|
4352
4369
|
var ELGORA_HUB_BOUNTY_CREATED_EVENT = getAbiItem2({
|
|
4353
4370
|
abi: ELGORA_HUB_ABI,
|
|
4354
4371
|
name: "BountyCreated"
|
|
@@ -4541,9 +4558,54 @@ var artifactUploadUrlRequestSchema = z5.object({
|
|
|
4541
4558
|
ciphertext_byte_length: z5.number().int().positive().max(MAX_SOLVER_SUBMISSION_CIPHERTEXT_BYTES)
|
|
4542
4559
|
}).strict();
|
|
4543
4560
|
|
|
4561
|
+
// ../../packages/core/src/api/bounty-list.ts
|
|
4562
|
+
var BOUNTY_LIST_MAX_FIRST = 100;
|
|
4563
|
+
var integerString = z6.string().regex(/^(0|[1-9]\d*)$/, {
|
|
4564
|
+
message: "Must be a non-negative integer"
|
|
4565
|
+
});
|
|
4566
|
+
var bountyFilterFields = {
|
|
4567
|
+
min_amount: integerString.optional(),
|
|
4568
|
+
max_amount: integerString.optional(),
|
|
4569
|
+
min_time_left: integerString.optional(),
|
|
4570
|
+
max_time_left: integerString.optional()
|
|
4571
|
+
};
|
|
4572
|
+
var bountyListParamsSchema = z6.object({
|
|
4573
|
+
...bountyFilterFields,
|
|
4574
|
+
status: z6.enum(BOUNTY_STATUSES).optional(),
|
|
4575
|
+
first: integerString.transform(Number).refine((value) => value >= 1 && value <= BOUNTY_LIST_MAX_FIRST, {
|
|
4576
|
+
message: `Must be from 1 to ${BOUNTY_LIST_MAX_FIRST}`
|
|
4577
|
+
}).optional(),
|
|
4578
|
+
skip: integerString.transform(Number).optional()
|
|
4579
|
+
}).strict();
|
|
4580
|
+
var hexSchema = z6.custom(
|
|
4581
|
+
(value) => typeof value === "string" && /^0x[0-9a-f]*$/i.test(value)
|
|
4582
|
+
);
|
|
4583
|
+
var listedBountySchema = z6.object({
|
|
4584
|
+
bounty_id: z6.string(),
|
|
4585
|
+
status: z6.enum(BOUNTY_STATUSES),
|
|
4586
|
+
poster: hexSchema,
|
|
4587
|
+
spec_commitment: hexSchema,
|
|
4588
|
+
escrow: z6.object({ token_address: hexSchema, amount: z6.string() }),
|
|
4589
|
+
submission_deadline: z6.number().int(),
|
|
4590
|
+
submission_count: z6.number().int(),
|
|
4591
|
+
winner: hexSchema.nullable(),
|
|
4592
|
+
created_at: z6.number().int()
|
|
4593
|
+
});
|
|
4594
|
+
var bountyListResponseSchema = z6.object({
|
|
4595
|
+
chain_id: z6.number().int(),
|
|
4596
|
+
hub_address: hexSchema,
|
|
4597
|
+
/** Bounties matching the filter, before `first` and `skip`. */
|
|
4598
|
+
total: z6.number().int(),
|
|
4599
|
+
bounties: z6.array(listedBountySchema)
|
|
4600
|
+
});
|
|
4601
|
+
function challengeMatchesKeywords(challenge, keywords) {
|
|
4602
|
+
const text = challenge.toLowerCase();
|
|
4603
|
+
return keywords.every((keyword) => text.includes(keyword.toLowerCase()));
|
|
4604
|
+
}
|
|
4605
|
+
|
|
4544
4606
|
// ../../packages/core/src/api/config.ts
|
|
4545
4607
|
import { createHash } from "crypto";
|
|
4546
|
-
import { z as
|
|
4608
|
+
import { z as z7 } from "zod";
|
|
4547
4609
|
function withDeploymentEnvDefaults(env) {
|
|
4548
4610
|
const merged = { ...env };
|
|
4549
4611
|
const setIfBlank = (key, value) => {
|
|
@@ -4564,11 +4626,11 @@ function withDeploymentEnvDefaults(env) {
|
|
|
4564
4626
|
setIfBlank("ELGORA_SUBGRAPH_ENDPOINT", deployment?.ELGORA_SUBGRAPH_ENDPOINT);
|
|
4565
4627
|
return merged;
|
|
4566
4628
|
}
|
|
4567
|
-
var chainIdField =
|
|
4629
|
+
var chainIdField = z7.coerce.number().int().positive().refine((chainId) => SUPPORTED_CHAINS[chainId] !== void 0, {
|
|
4568
4630
|
message: `ELGORA_CHAIN_ID must be a supported chain: ${Object.keys(SUPPORTED_CHAINS).join(", ")}`
|
|
4569
4631
|
});
|
|
4570
|
-
var hubAddressField =
|
|
4571
|
-
var publicDeploymentEnvSchema =
|
|
4632
|
+
var hubAddressField = z7.string().refine(isHexAddress, "ELGORA_HUB_ADDRESS must be a 20-byte EVM address").transform((value) => value.toLowerCase());
|
|
4633
|
+
var publicDeploymentEnvSchema = z7.object({
|
|
4572
4634
|
ELGORA_CHAIN_ID: chainIdField,
|
|
4573
4635
|
ELGORA_HUB_ADDRESS: hubAddressField
|
|
4574
4636
|
});
|
|
@@ -4584,30 +4646,30 @@ function loadPublicDeploymentConfig(env = process.env) {
|
|
|
4584
4646
|
var envShape = {
|
|
4585
4647
|
ELGORA_CHAIN_ID: chainIdField,
|
|
4586
4648
|
ELGORA_HUB_ADDRESS: hubAddressField,
|
|
4587
|
-
ELGORA_ESCROW_TOKEN_ADDRESS:
|
|
4649
|
+
ELGORA_ESCROW_TOKEN_ADDRESS: z7.string().refine(
|
|
4588
4650
|
isHexAddress,
|
|
4589
4651
|
"ELGORA_ESCROW_TOKEN_ADDRESS must be a 20-byte EVM address"
|
|
4590
4652
|
).transform((value) => value.toLowerCase()),
|
|
4591
|
-
ELGORA_TIMELOCK_REVEAL_DELAY_SECONDS:
|
|
4592
|
-
ELGORA_RPC_URL:
|
|
4653
|
+
ELGORA_TIMELOCK_REVEAL_DELAY_SECONDS: z7.coerce.number().int().nonnegative().default(DEFAULT_TIMELOCK_REVEAL_DELAY_SECONDS),
|
|
4654
|
+
ELGORA_RPC_URL: z7.string().min(1, "ELGORA_RPC_URL is required"),
|
|
4593
4655
|
/**
|
|
4594
4656
|
* Only consulted for a chain with no recorded deployment — a local anvil
|
|
4595
4657
|
* stack, whose addresses change on every deploy. A recorded deployment's
|
|
4596
4658
|
* scheme always wins, because settlement validation compares against it.
|
|
4597
4659
|
*/
|
|
4598
|
-
ELGORA_PAYOUT_SCHEME_ADDRESS:
|
|
4660
|
+
ELGORA_PAYOUT_SCHEME_ADDRESS: z7.string().refine(
|
|
4599
4661
|
isHexAddress,
|
|
4600
4662
|
"ELGORA_PAYOUT_SCHEME_ADDRESS must be a 20-byte EVM address"
|
|
4601
4663
|
).transform((value) => value.toLowerCase()).optional(),
|
|
4602
|
-
ELGORA_DATABASE_URL:
|
|
4603
|
-
ELGORA_SUBGRAPH_ENDPOINT:
|
|
4604
|
-
ELGORA_ARTIFACT_STORAGE_ENDPOINT:
|
|
4605
|
-
ELGORA_ARTIFACT_STORAGE_REGION:
|
|
4606
|
-
ELGORA_ARTIFACT_STORAGE_BUCKET:
|
|
4607
|
-
ELGORA_ARTIFACT_STORAGE_ACCESS_KEY_ID:
|
|
4608
|
-
ELGORA_ARTIFACT_STORAGE_SECRET_ACCESS_KEY:
|
|
4609
|
-
ELGORA_DELIVERY_PUBLIC_KEY:
|
|
4610
|
-
ELGORA_DELIVERY_PRIVATE_KEY:
|
|
4664
|
+
ELGORA_DATABASE_URL: z7.string().min(1, "ELGORA_DATABASE_URL is required"),
|
|
4665
|
+
ELGORA_SUBGRAPH_ENDPOINT: z7.string().min(1, "ELGORA_SUBGRAPH_ENDPOINT is required"),
|
|
4666
|
+
ELGORA_ARTIFACT_STORAGE_ENDPOINT: z7.string().min(1, "ELGORA_ARTIFACT_STORAGE_ENDPOINT is required"),
|
|
4667
|
+
ELGORA_ARTIFACT_STORAGE_REGION: z7.string().min(1, "ELGORA_ARTIFACT_STORAGE_REGION is required"),
|
|
4668
|
+
ELGORA_ARTIFACT_STORAGE_BUCKET: z7.string().min(1, "ELGORA_ARTIFACT_STORAGE_BUCKET is required"),
|
|
4669
|
+
ELGORA_ARTIFACT_STORAGE_ACCESS_KEY_ID: z7.string().min(1, "ELGORA_ARTIFACT_STORAGE_ACCESS_KEY_ID is required"),
|
|
4670
|
+
ELGORA_ARTIFACT_STORAGE_SECRET_ACCESS_KEY: z7.string().min(1, "ELGORA_ARTIFACT_STORAGE_SECRET_ACCESS_KEY is required"),
|
|
4671
|
+
ELGORA_DELIVERY_PUBLIC_KEY: z7.string().min(1, "ELGORA_DELIVERY_PUBLIC_KEY is required"),
|
|
4672
|
+
ELGORA_DELIVERY_PRIVATE_KEY: z7.string().min(1, "ELGORA_DELIVERY_PRIVATE_KEY is required")
|
|
4611
4673
|
};
|
|
4612
4674
|
var publicationEnvShape = {
|
|
4613
4675
|
ELGORA_CHAIN_ID: envShape.ELGORA_CHAIN_ID,
|
|
@@ -4615,89 +4677,89 @@ var publicationEnvShape = {
|
|
|
4615
4677
|
ELGORA_ESCROW_TOKEN_ADDRESS: envShape.ELGORA_ESCROW_TOKEN_ADDRESS,
|
|
4616
4678
|
ELGORA_DATABASE_URL: envShape.ELGORA_DATABASE_URL,
|
|
4617
4679
|
ELGORA_SUBGRAPH_ENDPOINT: envShape.ELGORA_SUBGRAPH_ENDPOINT,
|
|
4618
|
-
ELGORA_PUBLICATION_REVIEW_ENABLED:
|
|
4619
|
-
ELGORA_READINESS_TIMEOUT_MS:
|
|
4680
|
+
ELGORA_PUBLICATION_REVIEW_ENABLED: z7.string().trim().toLowerCase().pipe(z7.enum(["true", "false"])).default("true").transform((value) => value === "true"),
|
|
4681
|
+
ELGORA_READINESS_TIMEOUT_MS: z7.coerce.number().int().min(1).max(READINESS_TIMEOUT_MS).default(READINESS_TIMEOUT_MS)
|
|
4620
4682
|
};
|
|
4621
|
-
var envSchema =
|
|
4622
|
-
var bountyPublicationEnvSchema =
|
|
4683
|
+
var envSchema = z7.object(envShape);
|
|
4684
|
+
var bountyPublicationEnvSchema = z7.object(publicationEnvShape);
|
|
4623
4685
|
|
|
4624
4686
|
// ../../packages/core/src/api/solver-submission-responses.ts
|
|
4625
4687
|
import { isHex as isHex3 } from "viem";
|
|
4626
|
-
import { z as
|
|
4627
|
-
var hexAddressSchema =
|
|
4628
|
-
var hexBytes32Schema =
|
|
4629
|
-
var hexDataSchema =
|
|
4630
|
-
var artifactUploadUrlResponseSchema =
|
|
4631
|
-
locator:
|
|
4632
|
-
upload_url:
|
|
4633
|
-
method:
|
|
4634
|
-
expires_at:
|
|
4688
|
+
import { z as z8 } from "zod";
|
|
4689
|
+
var hexAddressSchema = z8.string().refine(isHexAddress, "Must be a hex-encoded address");
|
|
4690
|
+
var hexBytes32Schema = z8.string().refine(isHexBytes32, "Must be 32-byte hex");
|
|
4691
|
+
var hexDataSchema = z8.string().refine((value) => isHex3(value), "Must be hex-encoded calldata");
|
|
4692
|
+
var artifactUploadUrlResponseSchema = z8.object({
|
|
4693
|
+
locator: z8.string().min(1),
|
|
4694
|
+
upload_url: z8.string().min(1),
|
|
4695
|
+
method: z8.literal("PUT"),
|
|
4696
|
+
expires_at: z8.string().min(1)
|
|
4635
4697
|
});
|
|
4636
|
-
var solverSubmissionPrepareResponseSchema =
|
|
4637
|
-
content_record:
|
|
4638
|
-
content_kind:
|
|
4698
|
+
var solverSubmissionPrepareResponseSchema = z8.object({
|
|
4699
|
+
content_record: z8.object({
|
|
4700
|
+
content_kind: z8.literal(SOLVER_SUBMISSION_CONTENT_KIND),
|
|
4639
4701
|
submission_commitment: hexBytes32Schema,
|
|
4640
|
-
byte_length:
|
|
4641
|
-
created_at:
|
|
4702
|
+
byte_length: z8.number().int().nonnegative(),
|
|
4703
|
+
created_at: z8.string().min(1)
|
|
4642
4704
|
}),
|
|
4643
|
-
submit_transaction:
|
|
4644
|
-
chain_id:
|
|
4705
|
+
submit_transaction: z8.object({
|
|
4706
|
+
chain_id: z8.number().int().positive(),
|
|
4645
4707
|
to: hexAddressSchema,
|
|
4646
|
-
value:
|
|
4708
|
+
value: z8.literal("0"),
|
|
4647
4709
|
data: hexDataSchema,
|
|
4648
|
-
function_name:
|
|
4649
|
-
args:
|
|
4650
|
-
bounty_id:
|
|
4710
|
+
function_name: z8.literal("submit"),
|
|
4711
|
+
args: z8.object({
|
|
4712
|
+
bounty_id: z8.string().min(1),
|
|
4651
4713
|
submission_commitment: hexBytes32Schema,
|
|
4652
4714
|
guardian_roster_hash: hexBytes32Schema,
|
|
4653
|
-
extra_data:
|
|
4715
|
+
extra_data: z8.literal("0x")
|
|
4654
4716
|
})
|
|
4655
4717
|
})
|
|
4656
4718
|
});
|
|
4657
|
-
var solverSubmissionContentResponseSchema =
|
|
4658
|
-
content_record:
|
|
4659
|
-
bounty_id:
|
|
4660
|
-
canonical_json:
|
|
4719
|
+
var solverSubmissionContentResponseSchema = z8.object({
|
|
4720
|
+
content_record: z8.object({
|
|
4721
|
+
bounty_id: z8.string().min(1),
|
|
4722
|
+
canonical_json: z8.string().min(1)
|
|
4661
4723
|
}),
|
|
4662
|
-
ciphertext_download_url:
|
|
4663
|
-
expires_at:
|
|
4724
|
+
ciphertext_download_url: z8.string().min(1),
|
|
4725
|
+
expires_at: z8.string().min(1)
|
|
4664
4726
|
});
|
|
4665
|
-
var bountySubmissionDetailResponseSchema =
|
|
4666
|
-
bounty:
|
|
4727
|
+
var bountySubmissionDetailResponseSchema = z8.object({
|
|
4728
|
+
bounty: z8.object({
|
|
4667
4729
|
guardian_roster_hash: hexBytes32Schema,
|
|
4668
|
-
guardian_roster:
|
|
4669
|
-
|
|
4670
|
-
name:
|
|
4730
|
+
guardian_roster: z8.array(
|
|
4731
|
+
z8.object({
|
|
4732
|
+
name: z8.string(),
|
|
4671
4733
|
account: hexAddressSchema,
|
|
4672
|
-
encryption_public_key:
|
|
4734
|
+
encryption_public_key: z8.string().min(1)
|
|
4673
4735
|
})
|
|
4674
4736
|
).min(1)
|
|
4675
4737
|
}),
|
|
4676
|
-
challenge:
|
|
4738
|
+
challenge: z8.string().nullable()
|
|
4677
4739
|
});
|
|
4678
4740
|
|
|
4679
4741
|
// ../../packages/core/src/api/verification-records.ts
|
|
4680
|
-
import { z as
|
|
4681
|
-
var hexAddressSchema2 =
|
|
4682
|
-
var hexBytes32Schema2 =
|
|
4683
|
-
var integerStringSchema =
|
|
4684
|
-
var verdictEntrySchema =
|
|
4685
|
-
name:
|
|
4686
|
-
outcome:
|
|
4742
|
+
import { z as z9 } from "zod";
|
|
4743
|
+
var hexAddressSchema2 = z9.string().refine(isHexAddress, "Must be a hex-encoded address").transform((value) => value.toLowerCase());
|
|
4744
|
+
var hexBytes32Schema2 = z9.string().refine(isHexBytes32, "Must be 32-byte hex").transform((value) => value.toLowerCase());
|
|
4745
|
+
var integerStringSchema = z9.string().regex(/^(0|[1-9][0-9]*)$/);
|
|
4746
|
+
var verdictEntrySchema = z9.object({
|
|
4747
|
+
name: z9.string().min(1),
|
|
4748
|
+
outcome: z9.enum(["awarded", "no_valid_submission"]).nullable(),
|
|
4687
4749
|
winner: hexAddressSchema2.nullable(),
|
|
4688
4750
|
report_commitment: hexBytes32Schema2.nullable(),
|
|
4689
|
-
committed_at:
|
|
4690
|
-
supporting:
|
|
4751
|
+
committed_at: z9.string().datetime({ offset: true }).nullable(),
|
|
4752
|
+
supporting: z9.boolean()
|
|
4691
4753
|
}).strict();
|
|
4692
|
-
var formattedVerificationRecordSchema =
|
|
4693
|
-
chain_id:
|
|
4754
|
+
var formattedVerificationRecordSchema = z9.object({
|
|
4755
|
+
chain_id: z9.number().int().positive(),
|
|
4694
4756
|
hub_address: hexAddressSchema2,
|
|
4695
4757
|
bounty_id: integerStringSchema,
|
|
4696
|
-
status:
|
|
4758
|
+
status: z9.enum(["awarded", "no_valid_submission", "timed_out"]),
|
|
4697
4759
|
spec_commitment: hexBytes32Schema2,
|
|
4698
4760
|
winner: hexAddressSchema2.nullable(),
|
|
4699
|
-
verdicts:
|
|
4700
|
-
settlement:
|
|
4761
|
+
verdicts: z9.record(z9.string(), verdictEntrySchema),
|
|
4762
|
+
settlement: z9.object({
|
|
4701
4763
|
escrow_amount: integerStringSchema,
|
|
4702
4764
|
settlement_recipient: hexAddressSchema2,
|
|
4703
4765
|
settlement_amount: integerStringSchema,
|
|
@@ -4708,10 +4770,10 @@ var formattedVerificationRecordSchema = z8.object({
|
|
|
4708
4770
|
settled_tx_hash: hexBytes32Schema2,
|
|
4709
4771
|
settled_block_number: integerStringSchema
|
|
4710
4772
|
}).strict(),
|
|
4711
|
-
content_record:
|
|
4712
|
-
spec_content_byte_length:
|
|
4773
|
+
content_record: z9.object({
|
|
4774
|
+
spec_content_byte_length: z9.number().int().positive()
|
|
4713
4775
|
}).strict(),
|
|
4714
|
-
verified_at:
|
|
4776
|
+
verified_at: z9.string().datetime({ offset: true })
|
|
4715
4777
|
}).strict();
|
|
4716
4778
|
function parseBountyVerificationRecord(input, expected) {
|
|
4717
4779
|
const slice = input;
|
|
@@ -4733,66 +4795,66 @@ function parseBountyVerificationRecord(input, expected) {
|
|
|
4733
4795
|
}
|
|
4734
4796
|
|
|
4735
4797
|
// ../../packages/core/src/api/winning-solution-delivery.ts
|
|
4736
|
-
import { z as
|
|
4737
|
-
var hexBytes32Schema3 =
|
|
4738
|
-
var hexAddressSchema3 =
|
|
4739
|
-
var deliveryKeyIdSchema =
|
|
4740
|
-
var winningSolutionWrappedKeySchema =
|
|
4741
|
-
enc:
|
|
4742
|
-
ciphertext:
|
|
4798
|
+
import { z as z10 } from "zod";
|
|
4799
|
+
var hexBytes32Schema3 = z10.string().refine(isHexBytes32, "Must be 32-byte hex").refine((value) => value !== ZERO_BYTES32, "Must not be zero").transform((value) => value.toLowerCase());
|
|
4800
|
+
var hexAddressSchema3 = z10.string().refine((value) => /^0x[0-9a-fA-F]{40}$/.test(value), "Must be an address").transform((value) => value.toLowerCase());
|
|
4801
|
+
var deliveryKeyIdSchema = z10.string().min(1).max(128);
|
|
4802
|
+
var winningSolutionWrappedKeySchema = z10.strictObject({
|
|
4803
|
+
enc: z10.string().min(1),
|
|
4804
|
+
ciphertext: z10.string().min(1)
|
|
4743
4805
|
});
|
|
4744
|
-
var deliveryWrapRequestSchema =
|
|
4806
|
+
var deliveryWrapRequestSchema = z10.strictObject({
|
|
4745
4807
|
solver_address: hexAddressSchema3,
|
|
4746
4808
|
submission_commitment: hexBytes32Schema3,
|
|
4747
4809
|
wrapped_key: winningSolutionWrappedKeySchema
|
|
4748
4810
|
});
|
|
4749
|
-
var deliveryWrapRecordSchema =
|
|
4750
|
-
bounty_id:
|
|
4811
|
+
var deliveryWrapRecordSchema = z10.strictObject({
|
|
4812
|
+
bounty_id: z10.string().min(1),
|
|
4751
4813
|
guardian_address: hexAddressSchema3,
|
|
4752
4814
|
solver_address: hexAddressSchema3,
|
|
4753
4815
|
submission_commitment: hexBytes32Schema3,
|
|
4754
4816
|
delivery_key_id: deliveryKeyIdSchema,
|
|
4755
|
-
created_at:
|
|
4817
|
+
created_at: z10.string().min(1)
|
|
4756
4818
|
});
|
|
4757
|
-
var deliveryWrapResponseSchema =
|
|
4758
|
-
status:
|
|
4819
|
+
var deliveryWrapResponseSchema = z10.strictObject({
|
|
4820
|
+
status: z10.literal("stored"),
|
|
4759
4821
|
wrap: deliveryWrapRecordSchema
|
|
4760
4822
|
});
|
|
4761
|
-
var deliveryRetrieveRequestSchema =
|
|
4823
|
+
var deliveryRetrieveRequestSchema = z10.strictObject({
|
|
4762
4824
|
poster_ephemeral_public_key: x25519PublicKeySchema
|
|
4763
4825
|
});
|
|
4764
|
-
var deliveryRetrieveResponseSchema =
|
|
4826
|
+
var deliveryRetrieveResponseSchema = z10.strictObject({
|
|
4765
4827
|
submission_commitment: hexBytes32Schema3,
|
|
4766
4828
|
wrapped_key: winningSolutionWrappedKeySchema
|
|
4767
4829
|
});
|
|
4768
|
-
var deliveryStatusResponseSchema =
|
|
4769
|
-
exists:
|
|
4830
|
+
var deliveryStatusResponseSchema = z10.strictObject({
|
|
4831
|
+
exists: z10.boolean()
|
|
4770
4832
|
});
|
|
4771
|
-
var deliveryKeyConfigResponseSchema =
|
|
4833
|
+
var deliveryKeyConfigResponseSchema = z10.strictObject({
|
|
4772
4834
|
delivery_key_id: deliveryKeyIdSchema,
|
|
4773
|
-
public_key:
|
|
4835
|
+
public_key: z10.string().min(1)
|
|
4774
4836
|
});
|
|
4775
4837
|
|
|
4776
4838
|
// ../../packages/core/src/api/written-verdicts.ts
|
|
4777
4839
|
import { keccak256 as keccak2564, toBytes as toBytes3, zeroAddress } from "viem";
|
|
4778
|
-
import { z as
|
|
4840
|
+
import { z as z11 } from "zod";
|
|
4779
4841
|
var WRITTEN_VERDICT_FORMAT_VERSION = 0;
|
|
4780
4842
|
var FRONTMATTER_DELIMITER2 = "---";
|
|
4781
|
-
var decimalSchema =
|
|
4782
|
-
var bountyIdSchema2 =
|
|
4783
|
-
var addressSchema2 =
|
|
4784
|
-
var bytes32Schema3 =
|
|
4843
|
+
var decimalSchema = z11.string().regex(/^[1-9][0-9]*$/, "Must be a positive integer").transform(Number).refine(Number.isSafeInteger, "Must be a safe integer");
|
|
4844
|
+
var bountyIdSchema2 = z11.string().regex(/^(0|[1-9][0-9]*)$/, "Must be a non-negative integer");
|
|
4845
|
+
var addressSchema2 = z11.string().refine(isHexAddress, "Must be a hex-encoded address").refine((value) => value === value.toLowerCase(), "Must use lowercase hex").transform((value) => value);
|
|
4846
|
+
var bytes32Schema3 = z11.string().refine(isHexBytes32, "Must be 32-byte hex").refine((value) => value === value.toLowerCase(), "Must use lowercase hex").transform((value) => value);
|
|
4785
4847
|
var commonFields = {
|
|
4786
|
-
format_version:
|
|
4848
|
+
format_version: z11.literal(WRITTEN_VERDICT_FORMAT_VERSION.toString()).transform(() => WRITTEN_VERDICT_FORMAT_VERSION),
|
|
4787
4849
|
chain_id: decimalSchema,
|
|
4788
4850
|
hub_address: addressSchema2,
|
|
4789
4851
|
bounty_id: bountyIdSchema2,
|
|
4790
|
-
verdict_body:
|
|
4852
|
+
verdict_body: z11.string().refine((value) => value.trim().length > 0, "Must not be empty")
|
|
4791
4853
|
};
|
|
4792
|
-
var writtenVerdictSchema =
|
|
4793
|
-
|
|
4854
|
+
var writtenVerdictSchema = z11.discriminatedUnion("outcome", [
|
|
4855
|
+
z11.object({
|
|
4794
4856
|
...commonFields,
|
|
4795
|
-
outcome:
|
|
4857
|
+
outcome: z11.literal("awarded"),
|
|
4796
4858
|
winner: addressSchema2.refine(
|
|
4797
4859
|
(value) => value !== zeroAddress,
|
|
4798
4860
|
"Must not be the zero address"
|
|
@@ -4802,10 +4864,10 @@ var writtenVerdictSchema = z10.discriminatedUnion("outcome", [
|
|
|
4802
4864
|
"Must not be zero bytes"
|
|
4803
4865
|
)
|
|
4804
4866
|
}).strict(),
|
|
4805
|
-
|
|
4867
|
+
z11.object({
|
|
4806
4868
|
...commonFields,
|
|
4807
|
-
outcome:
|
|
4808
|
-
winner:
|
|
4869
|
+
outcome: z11.literal("no_valid_submission"),
|
|
4870
|
+
winner: z11.literal(zeroAddress)
|
|
4809
4871
|
}).strict()
|
|
4810
4872
|
]);
|
|
4811
4873
|
function buildWrittenVerdictMarkdown(input) {
|
|
@@ -4900,17 +4962,17 @@ import { parseEventLogs } from "viem";
|
|
|
4900
4962
|
|
|
4901
4963
|
// ../../packages/core/src/api-client-config.ts
|
|
4902
4964
|
var LOCAL_DEV_API_BASE_URL = "http://127.0.0.1:3000";
|
|
4903
|
-
function loadApiClientConfig(env
|
|
4904
|
-
return { apiBaseUrl: resolveApiBaseUrl(env
|
|
4965
|
+
function loadApiClientConfig(env) {
|
|
4966
|
+
return { apiBaseUrl: resolveApiBaseUrl(env) };
|
|
4905
4967
|
}
|
|
4906
|
-
function loadClientDeploymentConfig(env
|
|
4968
|
+
function loadClientDeploymentConfig(env) {
|
|
4907
4969
|
return {
|
|
4908
4970
|
...loadPublicDeploymentConfig(env),
|
|
4909
|
-
...loadApiClientConfig(env
|
|
4971
|
+
...loadApiClientConfig(env)
|
|
4910
4972
|
};
|
|
4911
4973
|
}
|
|
4912
|
-
function resolveApiBaseUrl(env
|
|
4913
|
-
const value =
|
|
4974
|
+
function resolveApiBaseUrl(env) {
|
|
4975
|
+
const value = env.ELGORA_API_BASE_URL?.trim() || defaultApiBaseUrl(env);
|
|
4914
4976
|
try {
|
|
4915
4977
|
new URL(value);
|
|
4916
4978
|
} catch {
|
|
@@ -6221,7 +6283,7 @@ function typedDataForRequest(request, block) {
|
|
|
6221
6283
|
}
|
|
6222
6284
|
|
|
6223
6285
|
// ../../packages/core/src/auth/request-approval-header.ts
|
|
6224
|
-
import { z as
|
|
6286
|
+
import { z as z12 } from "zod";
|
|
6225
6287
|
async function buildAuthorizationHeader(params) {
|
|
6226
6288
|
const url = new URL(params.requestUrl);
|
|
6227
6289
|
const typedData = typedDataForRequest(
|
|
@@ -6248,8 +6310,8 @@ async function authorizeRequest(params) {
|
|
|
6248
6310
|
block: await readChallengeBlock(params)
|
|
6249
6311
|
});
|
|
6250
6312
|
}
|
|
6251
|
-
var challengeBlockSchema =
|
|
6252
|
-
error:
|
|
6313
|
+
var challengeBlockSchema = z12.object({
|
|
6314
|
+
error: z12.object({ block_number: z12.string(), block_hash: z12.string() })
|
|
6253
6315
|
});
|
|
6254
6316
|
async function readChallengeBlock(params) {
|
|
6255
6317
|
const response = await fetch(params.requestUrl, {
|
|
@@ -6623,10 +6685,10 @@ function readSubmissionArchive(archive) {
|
|
|
6623
6685
|
assertSubmissionFiles(files);
|
|
6624
6686
|
return { files, ...describeFiles(files) };
|
|
6625
6687
|
}
|
|
6626
|
-
function requireCurrentFormat(alg, bountyId,
|
|
6688
|
+
function requireCurrentFormat(alg, bountyId, command20) {
|
|
6627
6689
|
if (alg !== SUBMISSION_ENCRYPTION_TYPE_V1) {
|
|
6628
6690
|
throw new Error(
|
|
6629
|
-
`Bounty ${bountyId} declares ${BOUNTY_CHALLENGE_PROFILE}, which this CLI does not handle. Use CLI 11 for it: npx @elgora/cli@11 ${
|
|
6691
|
+
`Bounty ${bountyId} declares ${BOUNTY_CHALLENGE_PROFILE}, which this CLI does not handle. Use CLI 11 for it: npx @elgora/cli@11 ${command20}`
|
|
6630
6692
|
);
|
|
6631
6693
|
}
|
|
6632
6694
|
}
|
|
@@ -7108,6 +7170,8 @@ var BOUNTY_FIELDS = `
|
|
|
7108
7170
|
submissionCount
|
|
7109
7171
|
createdTxHash
|
|
7110
7172
|
createdAt
|
|
7173
|
+
createdBlockNumber
|
|
7174
|
+
createdLogIndex
|
|
7111
7175
|
consensusReachedAt
|
|
7112
7176
|
consensusOutcome
|
|
7113
7177
|
consensusWinner
|
|
@@ -7115,6 +7179,7 @@ var BOUNTY_FIELDS = `
|
|
|
7115
7179
|
settledTxHash
|
|
7116
7180
|
settledAt
|
|
7117
7181
|
settledBlockNumber
|
|
7182
|
+
settledLogIndex
|
|
7118
7183
|
updatedAt
|
|
7119
7184
|
`;
|
|
7120
7185
|
var LIST_BOUNTIES_QUERY = `
|
|
@@ -7141,6 +7206,7 @@ var SUBMISSION_FIELDS = `
|
|
|
7141
7206
|
submissionCommitment
|
|
7142
7207
|
recordedAt
|
|
7143
7208
|
recordedBlockNumber
|
|
7209
|
+
recordedLogIndex
|
|
7144
7210
|
recordedTxHash
|
|
7145
7211
|
submissionCallCount
|
|
7146
7212
|
`;
|
|
@@ -7153,8 +7219,18 @@ var VERDICT_FIELDS = `
|
|
|
7153
7219
|
payoutData
|
|
7154
7220
|
committedTxHash
|
|
7155
7221
|
committedAt
|
|
7222
|
+
committedBlockNumber
|
|
7223
|
+
committedLogIndex
|
|
7156
7224
|
updatedAt
|
|
7157
7225
|
`;
|
|
7226
|
+
var CLAIM_FIELDS = `
|
|
7227
|
+
claimant
|
|
7228
|
+
amount
|
|
7229
|
+
claimedAt
|
|
7230
|
+
claimedBlockNumber
|
|
7231
|
+
claimedLogIndex
|
|
7232
|
+
claimedTxHash
|
|
7233
|
+
`;
|
|
7158
7234
|
var GUARDIAN_ROSTER_SNAPSHOT_FIELDS = `
|
|
7159
7235
|
id
|
|
7160
7236
|
memberCount
|
|
@@ -7181,7 +7257,6 @@ var BOUNTY_DETAIL_QUERY = `
|
|
|
7181
7257
|
reportCommitments
|
|
7182
7258
|
awardedPayoutData
|
|
7183
7259
|
timedOutRefundAmount
|
|
7184
|
-
settledLogIndex
|
|
7185
7260
|
claimsQueued(first: 1, orderBy: queuedLogIndex, orderDirection: desc) {
|
|
7186
7261
|
recipient
|
|
7187
7262
|
amount
|
|
@@ -7197,6 +7272,9 @@ var BOUNTY_DETAIL_QUERY = `
|
|
|
7197
7272
|
verdicts {
|
|
7198
7273
|
${VERDICT_FIELDS}
|
|
7199
7274
|
}
|
|
7275
|
+
claims(orderBy: claimedAt, orderDirection: asc) {
|
|
7276
|
+
${CLAIM_FIELDS}
|
|
7277
|
+
}
|
|
7200
7278
|
}
|
|
7201
7279
|
}
|
|
7202
7280
|
`;
|
|
@@ -7208,6 +7286,7 @@ var ANALYTICS_SNAPSHOT_QUERY = `
|
|
|
7208
7286
|
$rosterSkip: Int!
|
|
7209
7287
|
$submissionSkip: Int!
|
|
7210
7288
|
$verdictSkip: Int!
|
|
7289
|
+
$claimSkip: Int!
|
|
7211
7290
|
$block: Block_height
|
|
7212
7291
|
) {
|
|
7213
7292
|
_meta(block: $block) {
|
|
@@ -7260,6 +7339,16 @@ var ANALYTICS_SNAPSHOT_QUERY = `
|
|
|
7260
7339
|
bountyId
|
|
7261
7340
|
${VERDICT_FIELDS}
|
|
7262
7341
|
}
|
|
7342
|
+
claims(
|
|
7343
|
+
first: $first
|
|
7344
|
+
skip: $claimSkip
|
|
7345
|
+
orderBy: id
|
|
7346
|
+
orderDirection: asc
|
|
7347
|
+
block: $block
|
|
7348
|
+
) {
|
|
7349
|
+
bountyId
|
|
7350
|
+
${CLAIM_FIELDS}
|
|
7351
|
+
}
|
|
7263
7352
|
}
|
|
7264
7353
|
`;
|
|
7265
7354
|
var DEPLOYMENT_CONFIG_QUERY = `
|
|
@@ -7386,11 +7475,13 @@ function createElgoraSubgraphClient(options) {
|
|
|
7386
7475
|
const rosterSnapshots = [];
|
|
7387
7476
|
const submissions = [];
|
|
7388
7477
|
const verdicts = [];
|
|
7478
|
+
const claims = [];
|
|
7389
7479
|
let indexedBlockNumber = null;
|
|
7390
7480
|
let bountySkip = 0;
|
|
7391
7481
|
let rosterSkip = 0;
|
|
7392
7482
|
let submissionSkip = 0;
|
|
7393
7483
|
let verdictSkip = 0;
|
|
7484
|
+
let claimSkip = 0;
|
|
7394
7485
|
for (; ; ) {
|
|
7395
7486
|
const data = await execute(
|
|
7396
7487
|
ANALYTICS_SNAPSHOT_QUERY,
|
|
@@ -7401,7 +7492,8 @@ function createElgoraSubgraphClient(options) {
|
|
|
7401
7492
|
includeGuardianHistory,
|
|
7402
7493
|
rosterSkip,
|
|
7403
7494
|
submissionSkip,
|
|
7404
|
-
verdictSkip
|
|
7495
|
+
verdictSkip,
|
|
7496
|
+
claimSkip
|
|
7405
7497
|
}
|
|
7406
7498
|
);
|
|
7407
7499
|
const meta = readRecord(data._meta);
|
|
@@ -7420,23 +7512,27 @@ function createElgoraSubgraphClient(options) {
|
|
|
7420
7512
|
const rosterPage = includeGuardianHistory ? asArray(data.guardianRosterSnapshots, "guardianRosterSnapshots") : [];
|
|
7421
7513
|
const submissionPage = asArray(data.submissions, "submissions");
|
|
7422
7514
|
const verdictPage = asArray(data.verdicts, "verdicts");
|
|
7515
|
+
const claimPage = asArray(data.claims, "claims");
|
|
7423
7516
|
bounties.push(...bountyPage.map(mapAnalyticsBounty));
|
|
7424
7517
|
rosterSnapshots.push(...rosterPage.map(mapAnalyticsGuardianRoster));
|
|
7425
7518
|
submissions.push(...submissionPage.map(mapListedSubmission));
|
|
7426
7519
|
verdicts.push(...verdictPage.map(mapListedVerdict));
|
|
7427
|
-
|
|
7520
|
+
claims.push(...claimPage.map(mapListedClaim));
|
|
7521
|
+
if (bountyPage.length < BOUNTY_PAGE_SIZE && rosterPage.length < BOUNTY_PAGE_SIZE && submissionPage.length < BOUNTY_PAGE_SIZE && verdictPage.length < BOUNTY_PAGE_SIZE && claimPage.length < BOUNTY_PAGE_SIZE) {
|
|
7428
7522
|
return {
|
|
7429
7523
|
indexedBlockNumber,
|
|
7430
7524
|
bounties,
|
|
7431
7525
|
rosterSnapshots,
|
|
7432
7526
|
submissions,
|
|
7433
|
-
verdicts
|
|
7527
|
+
verdicts,
|
|
7528
|
+
claims
|
|
7434
7529
|
};
|
|
7435
7530
|
}
|
|
7436
7531
|
bountySkip += bountyPage.length;
|
|
7437
7532
|
rosterSkip += rosterPage.length;
|
|
7438
7533
|
submissionSkip += submissionPage.length;
|
|
7439
7534
|
verdictSkip += verdictPage.length;
|
|
7535
|
+
claimSkip += claimPage.length;
|
|
7440
7536
|
}
|
|
7441
7537
|
},
|
|
7442
7538
|
async getBounty(bountyId) {
|
|
@@ -7525,6 +7621,11 @@ function mapBounty(row) {
|
|
|
7525
7621
|
submissionCount: asNumber(record.submissionCount, "submissionCount"),
|
|
7526
7622
|
createdTxHash: asHex(record.createdTxHash, "createdTxHash"),
|
|
7527
7623
|
createdAt: asString(record.createdAt, "createdAt"),
|
|
7624
|
+
createdBlockNumber: asString(
|
|
7625
|
+
record.createdBlockNumber,
|
|
7626
|
+
"createdBlockNumber"
|
|
7627
|
+
),
|
|
7628
|
+
createdLogIndex: asNumber(record.createdLogIndex, "createdLogIndex"),
|
|
7528
7629
|
consensusReachedAt: asNullableString(
|
|
7529
7630
|
record.consensusReachedAt,
|
|
7530
7631
|
"consensusReachedAt"
|
|
@@ -7541,6 +7642,7 @@ function mapBounty(row) {
|
|
|
7541
7642
|
record.settledBlockNumber,
|
|
7542
7643
|
"settledBlockNumber"
|
|
7543
7644
|
),
|
|
7645
|
+
settledLogIndex: record.settledLogIndex == null ? null : asNumber(record.settledLogIndex, "settledLogIndex"),
|
|
7544
7646
|
updatedAt: asString(record.updatedAt, "updatedAt")
|
|
7545
7647
|
};
|
|
7546
7648
|
}
|
|
@@ -7624,7 +7726,8 @@ function mapBountyDetail(row) {
|
|
|
7624
7726
|
submissions: asArray(record.submissions, "submissions").map(
|
|
7625
7727
|
mapSubmissionFields
|
|
7626
7728
|
),
|
|
7627
|
-
verdicts: asArray(record.verdicts, "verdicts").map(mapVerdict)
|
|
7729
|
+
verdicts: asArray(record.verdicts, "verdicts").map(mapVerdict),
|
|
7730
|
+
claims: asArray(record.claims, "claims").map(mapClaim)
|
|
7628
7731
|
};
|
|
7629
7732
|
}
|
|
7630
7733
|
function mapVerdict(row) {
|
|
@@ -7641,6 +7744,11 @@ function mapVerdict(row) {
|
|
|
7641
7744
|
payoutData: asHex(record.payoutData, "payoutData"),
|
|
7642
7745
|
committedTxHash: asHex(record.committedTxHash, "committedTxHash"),
|
|
7643
7746
|
committedAt: asString(record.committedAt, "committedAt"),
|
|
7747
|
+
committedBlockNumber: asString(
|
|
7748
|
+
record.committedBlockNumber,
|
|
7749
|
+
"committedBlockNumber"
|
|
7750
|
+
),
|
|
7751
|
+
committedLogIndex: asNumber(record.committedLogIndex, "committedLogIndex"),
|
|
7644
7752
|
updatedAt: asString(record.updatedAt, "updatedAt")
|
|
7645
7753
|
};
|
|
7646
7754
|
}
|
|
@@ -7651,6 +7759,27 @@ function mapListedVerdict(row) {
|
|
|
7651
7759
|
...mapVerdict(record)
|
|
7652
7760
|
};
|
|
7653
7761
|
}
|
|
7762
|
+
function mapClaim(row) {
|
|
7763
|
+
const record = readRecord(row);
|
|
7764
|
+
return {
|
|
7765
|
+
claimant: asHex(record.claimant, "claimant"),
|
|
7766
|
+
amount: asString(record.amount, "amount"),
|
|
7767
|
+
claimedAt: asString(record.claimedAt, "claimedAt"),
|
|
7768
|
+
claimedBlockNumber: asString(
|
|
7769
|
+
record.claimedBlockNumber,
|
|
7770
|
+
"claimedBlockNumber"
|
|
7771
|
+
),
|
|
7772
|
+
claimedLogIndex: asNumber(record.claimedLogIndex, "claimedLogIndex"),
|
|
7773
|
+
claimedTxHash: asHex(record.claimedTxHash, "claimedTxHash")
|
|
7774
|
+
};
|
|
7775
|
+
}
|
|
7776
|
+
function mapListedClaim(row) {
|
|
7777
|
+
const record = readRecord(row);
|
|
7778
|
+
return {
|
|
7779
|
+
bountyId: asString(record.bountyId, "bountyId"),
|
|
7780
|
+
...mapClaim(record)
|
|
7781
|
+
};
|
|
7782
|
+
}
|
|
7654
7783
|
function mapListedSubmission(row) {
|
|
7655
7784
|
const record = readRecord(row);
|
|
7656
7785
|
return {
|
|
@@ -7671,6 +7800,7 @@ function mapSubmissionFields(row) {
|
|
|
7671
7800
|
record.recordedBlockNumber,
|
|
7672
7801
|
"recordedBlockNumber"
|
|
7673
7802
|
),
|
|
7803
|
+
recordedLogIndex: asNumber(record.recordedLogIndex, "recordedLogIndex"),
|
|
7674
7804
|
recordedTxHash: asHex(record.recordedTxHash, "recordedTxHash"),
|
|
7675
7805
|
submissionCallCount: asNumber(
|
|
7676
7806
|
record.submissionCallCount,
|
|
@@ -8386,7 +8516,7 @@ function resolveChainId(selector) {
|
|
|
8386
8516
|
}
|
|
8387
8517
|
|
|
8388
8518
|
// src/version.ts
|
|
8389
|
-
var CLI_VERSION = true ? "12.
|
|
8519
|
+
var CLI_VERSION = true ? "12.1.0" : "0.0.0-dev";
|
|
8390
8520
|
var CLI_NODE_ENGINES = true ? "24.x || 26.x" : "24.x || 26.x";
|
|
8391
8521
|
|
|
8392
8522
|
// src/node-engines.ts
|
|
@@ -9739,12 +9869,163 @@ async function checkSubmission(input) {
|
|
|
9739
9869
|
}
|
|
9740
9870
|
var command15 = { main: main15, OPTIONS: OPTIONS15, USAGE: USAGE15 };
|
|
9741
9871
|
|
|
9872
|
+
// src/bounty-filter-flags.ts
|
|
9873
|
+
var BOUNTY_FILTER_OPTIONS = {
|
|
9874
|
+
"--min-amount": "value",
|
|
9875
|
+
"--max-amount": "value",
|
|
9876
|
+
"--min-time-left": "value",
|
|
9877
|
+
"--max-time-left": "value",
|
|
9878
|
+
"--keyword": "list"
|
|
9879
|
+
};
|
|
9880
|
+
var BOUNTY_FILTER_USAGE = "[--min-amount <units>] [--max-amount <units>]\n [--min-time-left <seconds>] [--max-time-left <seconds>]\n [--keyword <word>]...";
|
|
9881
|
+
var NUMERIC_FILTERS = [
|
|
9882
|
+
["--min-amount", "min_amount"],
|
|
9883
|
+
["--max-amount", "max_amount"],
|
|
9884
|
+
["--min-time-left", "min_time_left"],
|
|
9885
|
+
["--max-time-left", "max_time_left"]
|
|
9886
|
+
];
|
|
9887
|
+
function readBountyFilterFlags(args) {
|
|
9888
|
+
const fields = {};
|
|
9889
|
+
for (const [flag, field] of NUMERIC_FILTERS) {
|
|
9890
|
+
const value = args.value(flag);
|
|
9891
|
+
if (value === void 0) continue;
|
|
9892
|
+
if (!/^(0|[1-9]\d*)$/.test(value)) {
|
|
9893
|
+
throw new Error(`${flag} must be a non-negative integer`);
|
|
9894
|
+
}
|
|
9895
|
+
fields[field] = value;
|
|
9896
|
+
}
|
|
9897
|
+
return fields;
|
|
9898
|
+
}
|
|
9899
|
+
|
|
9900
|
+
// src/solver-notifications.ts
|
|
9901
|
+
var OPTIONS16 = {
|
|
9902
|
+
"--webhook-url": "value",
|
|
9903
|
+
...BOUNTY_FILTER_OPTIONS,
|
|
9904
|
+
...API_OPTIONS,
|
|
9905
|
+
...ACCOUNT_OPTIONS
|
|
9906
|
+
};
|
|
9907
|
+
var USAGE16 = `elgora-cli solver:notifications subscribe --webhook-url <https_url>
|
|
9908
|
+
${BOUNTY_FILTER_USAGE}
|
|
9909
|
+
elgora-cli solver:notifications list
|
|
9910
|
+
elgora-cli solver:notifications unsubscribe <subscription_id>`;
|
|
9911
|
+
var PATH = "/api/notifications/subscriptions";
|
|
9912
|
+
async function main16(env = process.env, argv = process.argv.slice(2)) {
|
|
9913
|
+
const parsed = parseArgs(argv, OPTIONS16);
|
|
9914
|
+
const request = readNotificationRequest(parsed, env);
|
|
9915
|
+
const config = loadApiDeployment(env, parsed);
|
|
9916
|
+
const { signer } = await connectAccount(env, parsed, config);
|
|
9917
|
+
const url = new URL(PATH, config.apiBaseUrl);
|
|
9918
|
+
const body = JSON.stringify(request);
|
|
9919
|
+
const authorization = await authorizeRequest({
|
|
9920
|
+
requestUrl: url.toString(),
|
|
9921
|
+
method: "POST",
|
|
9922
|
+
contentType: "application/json",
|
|
9923
|
+
body,
|
|
9924
|
+
chainId: config.chainId,
|
|
9925
|
+
hubAddress: config.hubAddress,
|
|
9926
|
+
address: signer.address,
|
|
9927
|
+
sign: signer.approvals.signTypedData
|
|
9928
|
+
});
|
|
9929
|
+
const response = await postText(url, body, "application/json", authorization);
|
|
9930
|
+
process.stdout.write(
|
|
9931
|
+
`${JSON.stringify({ event: `notifications.${request.action}`, ...response })}
|
|
9932
|
+
`
|
|
9933
|
+
);
|
|
9934
|
+
}
|
|
9935
|
+
function readNotificationRequest(args, env) {
|
|
9936
|
+
const [action, ...rest] = args.positionals;
|
|
9937
|
+
if (action === "list" && rest.length === 0) return { action };
|
|
9938
|
+
if (action === "unsubscribe" && rest.length === 1) {
|
|
9939
|
+
return { action, subscription_id: rest[0] };
|
|
9940
|
+
}
|
|
9941
|
+
if (action !== "subscribe" || rest.length > 0) throw usageError(USAGE16);
|
|
9942
|
+
const url = args.value("--webhook-url");
|
|
9943
|
+
if (!url) throw usageError(USAGE16);
|
|
9944
|
+
const secret = env.ELGORA_WEBHOOK_SECRET?.trim();
|
|
9945
|
+
if (!secret) {
|
|
9946
|
+
throw new Error(
|
|
9947
|
+
"ELGORA_WEBHOOK_SECRET is required to subscribe: the shared secret your webhook verifies signatures with"
|
|
9948
|
+
);
|
|
9949
|
+
}
|
|
9950
|
+
return {
|
|
9951
|
+
action,
|
|
9952
|
+
event: "bounty_posted",
|
|
9953
|
+
filter: {
|
|
9954
|
+
...readBountyFilterFlags(args),
|
|
9955
|
+
keywords: args.list("--keyword")
|
|
9956
|
+
},
|
|
9957
|
+
sink: { type: "webhook", url, secret }
|
|
9958
|
+
};
|
|
9959
|
+
}
|
|
9960
|
+
var command16 = { main: main16, OPTIONS: OPTIONS16, USAGE: USAGE16 };
|
|
9961
|
+
|
|
9962
|
+
// src/solver-solvable.ts
|
|
9963
|
+
import { isAddressEqual as isAddressEqual2 } from "viem";
|
|
9964
|
+
var OPTIONS17 = {
|
|
9965
|
+
...BOUNTY_FILTER_OPTIONS,
|
|
9966
|
+
...API_OPTIONS,
|
|
9967
|
+
...HUB_OPTIONS
|
|
9968
|
+
};
|
|
9969
|
+
var USAGE17 = `elgora-cli solver:solvable ${BOUNTY_FILTER_USAGE}`;
|
|
9970
|
+
async function main17(env = process.env, argv = process.argv.slice(2)) {
|
|
9971
|
+
const parsed = parseArgs(argv, OPTIONS17);
|
|
9972
|
+
const params = readSolvableParams(parsed);
|
|
9973
|
+
const keywords = parsed.list("--keyword");
|
|
9974
|
+
const config = loadClientDeploymentConfig(deploymentEnv(env, parsed));
|
|
9975
|
+
const solvable = [];
|
|
9976
|
+
for (let skip = 0; ; skip += BOUNTY_LIST_MAX_FIRST) {
|
|
9977
|
+
params.set("skip", String(skip));
|
|
9978
|
+
const page = bountyListResponseSchema.parse(
|
|
9979
|
+
await getJson(config.apiBaseUrl, `/api/bounties?${params}`)
|
|
9980
|
+
);
|
|
9981
|
+
if (page.chain_id !== config.chainId || !isAddressEqual2(page.hub_address, config.hubAddress)) {
|
|
9982
|
+
throw new Error(
|
|
9983
|
+
`Elgora API lists bounties for chain ${page.chain_id} ElgoraHub ${page.hub_address}, not this deployment`
|
|
9984
|
+
);
|
|
9985
|
+
}
|
|
9986
|
+
for (const bounty of page.bounties) {
|
|
9987
|
+
if (keywords.length === 0 || await challengeMatches(config.apiBaseUrl, bounty, keywords)) {
|
|
9988
|
+
solvable.push(bounty);
|
|
9989
|
+
}
|
|
9990
|
+
}
|
|
9991
|
+
if (skip + BOUNTY_LIST_MAX_FIRST >= page.total) break;
|
|
9992
|
+
}
|
|
9993
|
+
process.stdout.write(`${JSON.stringify(solvable)}
|
|
9994
|
+
`);
|
|
9995
|
+
}
|
|
9996
|
+
function readSolvableParams(args) {
|
|
9997
|
+
if (args.positionals.length > 0) throw usageError(USAGE17);
|
|
9998
|
+
const params = new URLSearchParams({
|
|
9999
|
+
status: "open",
|
|
10000
|
+
first: String(BOUNTY_LIST_MAX_FIRST)
|
|
10001
|
+
});
|
|
10002
|
+
for (const [param, value] of Object.entries(readBountyFilterFlags(args))) {
|
|
10003
|
+
if (value !== void 0) params.set(param, value);
|
|
10004
|
+
}
|
|
10005
|
+
return params;
|
|
10006
|
+
}
|
|
10007
|
+
async function challengeMatches(apiBaseUrl, bounty, keywords) {
|
|
10008
|
+
const { challenge } = await requestBountySubmissionDetail({
|
|
10009
|
+
apiBaseUrl,
|
|
10010
|
+
bountyId: bounty.bounty_id
|
|
10011
|
+
});
|
|
10012
|
+
if (challenge === null || deriveBountyChallengeContentCommitment(challenge).toLowerCase() !== bounty.spec_commitment) {
|
|
10013
|
+
process.stderr.write(
|
|
10014
|
+
`Skipped bounty ${bounty.bounty_id}: the Elgora API served no challenge matching its spec_commitment
|
|
10015
|
+
`
|
|
10016
|
+
);
|
|
10017
|
+
return false;
|
|
10018
|
+
}
|
|
10019
|
+
return challengeMatchesKeywords(challenge, keywords);
|
|
10020
|
+
}
|
|
10021
|
+
var command17 = { main: main17, OPTIONS: OPTIONS17, USAGE: USAGE17 };
|
|
10022
|
+
|
|
9742
10023
|
// src/spec-commitment.ts
|
|
9743
|
-
var
|
|
9744
|
-
var
|
|
9745
|
-
async function
|
|
10024
|
+
var OPTIONS18 = {};
|
|
10025
|
+
var USAGE18 = "elgora-cli spec-commitment <bounty_challenge_md_path|->";
|
|
10026
|
+
async function main18(_env = process.env, argv = process.argv.slice(2)) {
|
|
9746
10027
|
const markdown = await readBountyChallengeMarkdown2(
|
|
9747
|
-
parseArgs(argv,
|
|
10028
|
+
parseArgs(argv, OPTIONS18).positionals
|
|
9748
10029
|
);
|
|
9749
10030
|
const specCommitment = deriveBountyChallengeContentCommitment(markdown);
|
|
9750
10031
|
console.log(
|
|
@@ -9757,16 +10038,16 @@ async function main16(_env = process.env, argv = process.argv.slice(2)) {
|
|
|
9757
10038
|
}
|
|
9758
10039
|
function readBountyChallengeMarkdown2(argv) {
|
|
9759
10040
|
const path7 = argv[0];
|
|
9760
|
-
if (!path7 || argv.length !== 1) throw usageError(
|
|
10041
|
+
if (!path7 || argv.length !== 1) throw usageError(USAGE18);
|
|
9761
10042
|
return readInput(path7);
|
|
9762
10043
|
}
|
|
9763
|
-
var
|
|
10044
|
+
var command18 = { main: main18, OPTIONS: OPTIONS18, USAGE: USAGE18 };
|
|
9764
10045
|
|
|
9765
10046
|
// src/verification-record.ts
|
|
9766
|
-
var
|
|
9767
|
-
var
|
|
9768
|
-
async function
|
|
9769
|
-
const parsed = parseArgs(argv,
|
|
10047
|
+
var OPTIONS19 = { ...API_OPTIONS, ...HUB_OPTIONS };
|
|
10048
|
+
var USAGE19 = "elgora-cli verification-record <bounty_id>";
|
|
10049
|
+
async function main19(env = process.env, argv = process.argv.slice(2)) {
|
|
10050
|
+
const parsed = parseArgs(argv, OPTIONS19);
|
|
9770
10051
|
const args = readVerificationRecordArgs(parsed.positionals);
|
|
9771
10052
|
const config = loadClientDeploymentConfig(deploymentEnv(env, parsed));
|
|
9772
10053
|
const record = await requestVerificationRecord({
|
|
@@ -9818,11 +10099,11 @@ function readVerificationRecordArgs(argv) {
|
|
|
9818
10099
|
const [bountyIdText] = argv;
|
|
9819
10100
|
const bountyId = bountyIdText?.trim();
|
|
9820
10101
|
if (argv.length !== 1 || !bountyId || !isBountyId(bountyId)) {
|
|
9821
|
-
throw usageError(
|
|
10102
|
+
throw usageError(USAGE19);
|
|
9822
10103
|
}
|
|
9823
10104
|
return { bountyId: BigInt(bountyId) };
|
|
9824
10105
|
}
|
|
9825
|
-
var
|
|
10106
|
+
var command19 = { main: main19, OPTIONS: OPTIONS19, USAGE: USAGE19 };
|
|
9826
10107
|
|
|
9827
10108
|
// src/cli.ts
|
|
9828
10109
|
if (process.env.DOTENV_CONFIG_PATH) {
|
|
@@ -9849,12 +10130,14 @@ var COMMANDS = {
|
|
|
9849
10130
|
"roster:add-guardian": command11,
|
|
9850
10131
|
"roster:prepare-guardian-proof": command12,
|
|
9851
10132
|
"roster:verify-guardian-proof": command13,
|
|
10133
|
+
"solver:solvable": command17,
|
|
10134
|
+
"solver:notifications": command16,
|
|
9852
10135
|
"solver:check": command15,
|
|
9853
10136
|
"solver:submit": command14,
|
|
9854
10137
|
claim: command2,
|
|
9855
10138
|
"check-challenge": command,
|
|
9856
|
-
"spec-commitment":
|
|
9857
|
-
"verification-record":
|
|
10139
|
+
"spec-commitment": command18,
|
|
10140
|
+
"verification-record": command19
|
|
9858
10141
|
};
|
|
9859
10142
|
var OPTION_HELP = {
|
|
9860
10143
|
"--api-base-url": "--api-base-url <url> Elgora API (else ELGORA_API_BASE_URL)",
|
|
@@ -9864,7 +10147,13 @@ var OPTION_HELP = {
|
|
|
9864
10147
|
"--reveal-delay-seconds": "--reveal-delay-seconds <n> seconds after the Submission deadline before\n Guardian keys release (default 0)",
|
|
9865
10148
|
"--prepare-only": "--prepare-only print the transactions instead of sending them",
|
|
9866
10149
|
"--previous": "--previous <commitment> the previous challenge commitment, sent with\n the signed request",
|
|
9867
|
-
"--guardian-address": "--guardian-address <address> the Guardian whose own Verdicts are reported"
|
|
10150
|
+
"--guardian-address": "--guardian-address <address> the Guardian whose own Verdicts are reported",
|
|
10151
|
+
"--min-amount": "--min-amount <units> smallest escrow, in token units (USDC: 1000000 = 1)",
|
|
10152
|
+
"--max-amount": "--max-amount <units> largest escrow, in token units",
|
|
10153
|
+
"--min-time-left": "--min-time-left <seconds> least time left before the Submission deadline",
|
|
10154
|
+
"--max-time-left": "--max-time-left <seconds> most time left before the Submission deadline",
|
|
10155
|
+
"--webhook-url": "--webhook-url <https_url> your webhook; it must verify Elgora's signature",
|
|
10156
|
+
"--keyword": "--keyword <word> must appear in the challenge, ignoring case;\n repeat it to require several"
|
|
9868
10157
|
};
|
|
9869
10158
|
var DEPLOYMENT_OPTIONS = [
|
|
9870
10159
|
"--api-base-url",
|
|
@@ -9928,6 +10217,16 @@ var COMMAND_HELP = {
|
|
|
9928
10217
|
description: "Takes the unmodified stdout of roster:prepare-guardian-proof and of\n the Guardian's guardian:prove-roster-key, reconstructs the signed\n payload from the fixture the admin generated (never sent to the\n Guardian), and checks through the chain that the signature is valid\n for the exact proposed account, which also covers contract and\n EIP-7702 accounts (ERC-1271). Exits non-zero on any mismatch.\n Advisory only \u2014 convinces\n the admin, proves nothing to ElgoraHub, and does not itself add the\n Guardian; run roster:add-guardian separately once satisfied.",
|
|
9929
10218
|
required: []
|
|
9930
10219
|
},
|
|
10220
|
+
"solver:solvable": {
|
|
10221
|
+
title: "List open bounties a Solver can still submit to.",
|
|
10222
|
+
description: "Read open bounties before their Submission deadline from the public\n Elgora API, newest first, filtered by escrow amount, time left and\n keywords. Keywords match the challenge text only after its bytes hash\n to the bounty's spec_commitment. Prints one JSON array. Advisory only:\n solver:submit checks ElgoraHub before it signs. No wallet or secret.",
|
|
10223
|
+
required: []
|
|
10224
|
+
},
|
|
10225
|
+
"solver:notifications": {
|
|
10226
|
+
title: "Get a signed webhook call for each new matching bounty.",
|
|
10227
|
+
description: "Subscribe this wallet's webhook to new bounties that match the filter,\n list its subscriptions, or unsubscribe one. Subscribing sends a signed\n webhook.verify call first and succeeds only on a 2xx answer. Every call\n carries X-Webhook-Signature (hex HMAC-SHA256 of the body) and Standard\n Webhooks headers, keyed with ELGORA_WEBHOOK_SECRET, which Elgora stores\n encrypted. A notification is advisory: read the bounty before acting.",
|
|
10228
|
+
required: []
|
|
10229
|
+
},
|
|
9931
10230
|
"solver:check": {
|
|
9932
10231
|
title: "Check a Submission the way a Guardian will, before submitting.",
|
|
9933
10232
|
description: "Run a Guardian's format and constraint checks on a folder or file\n without submitting anything. Exits 1 on any issue.",
|
|
@@ -9980,8 +10279,8 @@ async function run(rawArgv) {
|
|
|
9980
10279
|
printCommandHelpOrUsage(rest[0]);
|
|
9981
10280
|
return;
|
|
9982
10281
|
}
|
|
9983
|
-
const
|
|
9984
|
-
if (!
|
|
10282
|
+
const command20 = COMMANDS[subcommand];
|
|
10283
|
+
if (!command20) {
|
|
9985
10284
|
process.stderr.write(`Unknown command: ${subcommand}
|
|
9986
10285
|
`);
|
|
9987
10286
|
printUsage();
|
|
@@ -9994,8 +10293,8 @@ async function run(rawArgv) {
|
|
|
9994
10293
|
}
|
|
9995
10294
|
let args;
|
|
9996
10295
|
try {
|
|
9997
|
-
args = parseArgs(rest,
|
|
9998
|
-
if ("--signer" in
|
|
10296
|
+
args = parseArgs(rest, command20.OPTIONS);
|
|
10297
|
+
if ("--signer" in command20.OPTIONS) readSignerOptions(args);
|
|
9999
10298
|
} catch (error) {
|
|
10000
10299
|
process.stderr.write(
|
|
10001
10300
|
`Error: ${error instanceof Error ? error.message : String(error)}
|
|
@@ -10012,10 +10311,10 @@ Run \`elgora-cli help ${subcommand}\` for its arguments and options.
|
|
|
10012
10311
|
process.exitCode = 1;
|
|
10013
10312
|
return;
|
|
10014
10313
|
}
|
|
10015
|
-
const networkNotice = usesDeployment(
|
|
10314
|
+
const networkNotice = usesDeployment(command20.OPTIONS) ? defaultNetworkNotice(env) : void 0;
|
|
10016
10315
|
if (networkNotice) process.stderr.write(`${networkNotice}
|
|
10017
10316
|
`);
|
|
10018
|
-
const needsLocalKey = "--signer" in
|
|
10317
|
+
const needsLocalKey = "--signer" in command20.OPTIONS && (args.value("--signer") ?? "local") === "local";
|
|
10019
10318
|
const missing = missingRequiredEnv(
|
|
10020
10319
|
[
|
|
10021
10320
|
...COMMAND_HELP[subcommand]?.required ?? [],
|
|
@@ -10042,7 +10341,7 @@ Run \`elgora-cli help ${subcommand}\` for its arguments and options.
|
|
|
10042
10341
|
process.exitCode = 1;
|
|
10043
10342
|
return;
|
|
10044
10343
|
}
|
|
10045
|
-
await
|
|
10344
|
+
await command20.main(env, rest);
|
|
10046
10345
|
}
|
|
10047
10346
|
function usesDeployment(options) {
|
|
10048
10347
|
return DEPLOYMENT_OPTIONS.some((option) => option in options);
|
|
@@ -10083,14 +10382,14 @@ function printUsage() {
|
|
|
10083
10382
|
}
|
|
10084
10383
|
function printCommandHelpOrUsage(name) {
|
|
10085
10384
|
const help = name ? COMMAND_HELP[name] : void 0;
|
|
10086
|
-
const
|
|
10087
|
-
if (!help || !
|
|
10385
|
+
const command20 = name ? COMMANDS[name] : void 0;
|
|
10386
|
+
if (!help || !command20) {
|
|
10088
10387
|
printUsage();
|
|
10089
10388
|
process.exitCode = name ? 1 : 0;
|
|
10090
10389
|
return;
|
|
10091
10390
|
}
|
|
10092
|
-
const options =
|
|
10093
|
-
const lines = [`Usage: ${
|
|
10391
|
+
const options = command20.OPTIONS;
|
|
10392
|
+
const lines = [`Usage: ${command20.USAGE}`, "", help.description];
|
|
10094
10393
|
const described = Object.keys(options).filter(
|
|
10095
10394
|
(option) => option in OPTION_HELP
|
|
10096
10395
|
);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elgora/cli",
|
|
3
|
-
"version": "12.
|
|
4
|
-
"description": "Command-line client for Elgora, a decentralized bounty marketplace for
|
|
3
|
+
"version": "12.1.0",
|
|
4
|
+
"description": "Command-line client for Elgora, a decentralized open bounty marketplace for AI agents. Lets Posters, Solvers, and Guardians interact with Elgora's public API and on-chain contracts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"dotenv": "17.4.2",
|
|
35
35
|
"tlock-js": "0.9.0",
|
|
36
36
|
"viem": "2.46.1",
|
|
37
|
-
"zod": "4.
|
|
37
|
+
"zod": "4.6.6"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@elgora/core": "workspace:*",
|