@elgora/cli 9.1.0 → 10.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 +16 -12
- package/dist/cli.js +422 -523
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -71,6 +71,8 @@ var BOUNTY_CHALLENGE_PROFILE = "elgora_markdown_bounty_challenge_v0";
|
|
|
71
71
|
var WINNER_TAKE_ALL_PAYOUT_POLICY = "winner_take_all";
|
|
72
72
|
var SUBMISSION_ENCRYPTION_TYPE = "guardian_timelock_hpke_aes_256_gcm_v0";
|
|
73
73
|
var ZERO_BYTES32 = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
74
|
+
var READINESS_APPROVAL_VALIDITY_SECONDS = 7 * 24 * 60 * 60;
|
|
75
|
+
var READINESS_TIMEOUT_MS = 12e4;
|
|
74
76
|
|
|
75
77
|
// ../../packages/core/src/bounty-challenge-markdown.ts
|
|
76
78
|
var FRONTMATTER_DELIMITER = "---";
|
|
@@ -384,107 +386,37 @@ function isBountyChallengeFrontmatterKey(value) {
|
|
|
384
386
|
}
|
|
385
387
|
|
|
386
388
|
// ../../packages/core/src/bounty-publication-response.ts
|
|
387
|
-
import { isHex as
|
|
388
|
-
import { z as z3 } from "zod";
|
|
389
|
-
|
|
390
|
-
// ../../packages/core/src/auth/readiness-signoff.ts
|
|
391
|
-
import {
|
|
392
|
-
isAddressEqual,
|
|
393
|
-
isHex as isHex2,
|
|
394
|
-
recoverTypedDataAddress,
|
|
395
|
-
size as size2
|
|
396
|
-
} from "viem";
|
|
389
|
+
import { isHex as isHex2 } from "viem";
|
|
397
390
|
import { z as z2 } from "zod";
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
var
|
|
401
|
-
var
|
|
402
|
-
|
|
403
|
-
{ name: "endpointId", type: "string" },
|
|
404
|
-
{ name: "audience", type: "string" },
|
|
405
|
-
{ name: "bodyHash", type: "bytes32" },
|
|
406
|
-
{ name: "query", type: "string" },
|
|
407
|
-
{ name: "blockNumber", type: "uint256" },
|
|
408
|
-
{ name: "blockHash", type: "bytes32" }
|
|
409
|
-
]
|
|
410
|
-
};
|
|
411
|
-
function buildElgoraEip712Domain(params) {
|
|
412
|
-
return {
|
|
413
|
-
name: "Elgora",
|
|
414
|
-
version: "1",
|
|
415
|
-
chainId: params.chainId,
|
|
416
|
-
verifyingContract: params.hubAddress
|
|
417
|
-
};
|
|
418
|
-
}
|
|
419
|
-
function buildApiRequestApprovalTypedData(params) {
|
|
420
|
-
return {
|
|
421
|
-
domain: buildElgoraEip712Domain({
|
|
422
|
-
chainId: params.chainId,
|
|
423
|
-
hubAddress: params.hubAddress
|
|
424
|
-
}),
|
|
425
|
-
types: API_REQUEST_APPROVAL_TYPES,
|
|
426
|
-
primaryType: API_REQUEST_APPROVAL_PRIMARY_TYPE,
|
|
427
|
-
message: params.message
|
|
428
|
-
};
|
|
429
|
-
}
|
|
430
|
-
function endpointIdFor(input) {
|
|
431
|
-
return `${input.method.toUpperCase()} ${input.path}`;
|
|
432
|
-
}
|
|
433
|
-
function audienceFor(host) {
|
|
434
|
-
return host.toLowerCase();
|
|
435
|
-
}
|
|
436
|
-
function queryFor(query) {
|
|
437
|
-
return new URLSearchParams(query).toString();
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// ../../packages/core/src/auth/readiness-signoff.ts
|
|
441
|
-
var READINESS_APPROVAL_VALIDITY_SECONDS = 7 * 24 * 60 * 60;
|
|
442
|
-
var bytes32Schema = z2.string().refine(isHexBytes32).transform((value) => value);
|
|
443
|
-
var timestampSchema = z2.number().int().nonnegative().max(9999999999);
|
|
444
|
-
var readinessSignoffMessageSchema = z2.object({
|
|
445
|
-
audience: z2.string().min(1).max(512),
|
|
391
|
+
var addressSchema = z2.string().refine(isHexAddress, "Must be a 20-byte EVM address").transform((value) => value);
|
|
392
|
+
var bytes32Schema = z2.string().refine(isHexBytes32, "Must be a bytes32 hex string").transform((value) => value);
|
|
393
|
+
var hexBytesSchema = z2.string().refine(isHex2, "Must be hex-encoded calldata").transform((value) => value);
|
|
394
|
+
var bountyChallengeContentRecordSchema = z2.object({
|
|
395
|
+
content_kind: z2.literal("bounty_challenge_spec"),
|
|
446
396
|
spec_commitment: bytes32Schema,
|
|
447
|
-
|
|
448
|
-
model: z2.string().min(1).max(256),
|
|
449
|
-
issued_at: timestampSchema,
|
|
450
|
-
expires_at: timestampSchema
|
|
451
|
-
}).strict();
|
|
452
|
-
var signatureSchema = z2.string().refine((value) => isHex2(value) && size2(value) === 65).transform((value) => value);
|
|
453
|
-
var readinessSignoffSchema = readinessSignoffMessageSchema.extend({ signature: signatureSchema }).refine((signoff) => signoff.expires_at > signoff.issued_at, {
|
|
454
|
-
path: ["expires_at"],
|
|
455
|
-
message: "Must expire after issuance"
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
// ../../packages/core/src/bounty-publication-response.ts
|
|
459
|
-
var addressSchema = z3.string().refine(isHexAddress, "Must be a 20-byte EVM address").transform((value) => value);
|
|
460
|
-
var bytes32Schema2 = z3.string().refine(isHexBytes32, "Must be a bytes32 hex string").transform((value) => value);
|
|
461
|
-
var hexBytesSchema = z3.string().refine(isHex3, "Must be hex-encoded calldata").transform((value) => value);
|
|
462
|
-
var bountyChallengeContentRecordSchema = z3.object({
|
|
463
|
-
content_kind: z3.literal("bounty_challenge_spec"),
|
|
464
|
-
spec_commitment: bytes32Schema2,
|
|
465
|
-
byte_length: z3.number().int().positive(),
|
|
397
|
+
byte_length: z2.number().int().positive(),
|
|
466
398
|
token_address: addressSchema,
|
|
467
|
-
created_at:
|
|
399
|
+
created_at: z2.string().datetime({ offset: true })
|
|
468
400
|
}).strict();
|
|
469
|
-
var bountyPublicationResponseSchema =
|
|
401
|
+
var bountyPublicationResponseSchema = z2.object({
|
|
470
402
|
content_record: bountyChallengeContentRecordSchema,
|
|
471
|
-
create_bounty_transaction:
|
|
472
|
-
chain_id:
|
|
403
|
+
create_bounty_transaction: z2.object({
|
|
404
|
+
chain_id: z2.number().int().positive(),
|
|
473
405
|
to: addressSchema,
|
|
474
|
-
value:
|
|
406
|
+
value: z2.literal("0"),
|
|
475
407
|
data: hexBytesSchema,
|
|
476
|
-
function_name:
|
|
477
|
-
args:
|
|
478
|
-
spec_commitment:
|
|
479
|
-
escrow_amount:
|
|
480
|
-
submission_deadline:
|
|
408
|
+
function_name: z2.literal("create_bounty"),
|
|
409
|
+
args: z2.object({
|
|
410
|
+
spec_commitment: bytes32Schema,
|
|
411
|
+
escrow_amount: z2.string().refine(isPositiveInteger),
|
|
412
|
+
submission_deadline: z2.number().int().positive()
|
|
481
413
|
}).strict()
|
|
482
414
|
}).strict(),
|
|
483
|
-
protocol_fee_policy:
|
|
415
|
+
protocol_fee_policy: z2.object({
|
|
484
416
|
treasury_recipient: addressSchema,
|
|
485
|
-
treasury_fee_bps:
|
|
417
|
+
treasury_fee_bps: z2.number().int().min(0).max(1e4),
|
|
486
418
|
guardian_fee_recipient: addressSchema,
|
|
487
|
-
guardian_fee_bps:
|
|
419
|
+
guardian_fee_bps: z2.number().int().min(0).max(1e4)
|
|
488
420
|
}).strict()
|
|
489
421
|
}).strict().superRefine((response, context) => {
|
|
490
422
|
if (response.content_record.spec_commitment !== response.create_bounty_transaction.args.spec_commitment) {
|
|
@@ -495,47 +427,33 @@ var bountyPublicationResponseSchema = z3.object({
|
|
|
495
427
|
});
|
|
496
428
|
}
|
|
497
429
|
});
|
|
498
|
-
var priorIssueSchema =
|
|
499
|
-
issue_index:
|
|
500
|
-
message:
|
|
430
|
+
var priorIssueSchema = z2.object({
|
|
431
|
+
issue_index: z2.number().int().nonnegative(),
|
|
432
|
+
message: z2.string().trim().min(1).max(1500)
|
|
501
433
|
}).strict();
|
|
502
434
|
var priorIssueStatusSchema = priorIssueSchema.extend({
|
|
503
|
-
status:
|
|
435
|
+
status: z2.enum(["resolved", "open"])
|
|
504
436
|
}).strict();
|
|
505
|
-
var readinessFindingSchema =
|
|
506
|
-
path:
|
|
507
|
-
message:
|
|
508
|
-
code:
|
|
509
|
-
anchor:
|
|
510
|
-
hazard:
|
|
437
|
+
var readinessFindingSchema = z2.object({
|
|
438
|
+
path: z2.string().trim().min(1).max(120),
|
|
439
|
+
message: z2.string().trim().min(1).max(1500),
|
|
440
|
+
code: z2.string().min(1).optional(),
|
|
441
|
+
anchor: z2.string().trim().min(1).max(120).optional(),
|
|
442
|
+
hazard: z2.boolean().optional()
|
|
511
443
|
});
|
|
512
444
|
var MAX_READINESS_FINDINGS = 20;
|
|
513
|
-
var bountyReviewResponseSchema =
|
|
514
|
-
content_record: bountyChallengeContentRecordSchema,
|
|
515
|
-
readiness:
|
|
516
|
-
decision:
|
|
517
|
-
|
|
445
|
+
var bountyReviewResponseSchema = z2.object({
|
|
446
|
+
content_record: bountyChallengeContentRecordSchema.omit({ created_at: true }),
|
|
447
|
+
readiness: z2.object({
|
|
448
|
+
decision: z2.literal("ready"),
|
|
449
|
+
// Publication reuses the approval of these exact bytes until then.
|
|
450
|
+
approved_until: z2.string().datetime({ offset: true }),
|
|
518
451
|
// The dissenting pass's findings on a ready check; never blocking.
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
prior_issues_open: z3.array(priorIssueSchema)
|
|
452
|
+
warnings: z2.array(readinessFindingSchema).max(MAX_READINESS_FINDINGS),
|
|
453
|
+
prior_issues_resolved: z2.array(priorIssueSchema),
|
|
454
|
+
prior_issues_open: z2.array(priorIssueSchema)
|
|
523
455
|
})
|
|
524
|
-
}).superRefine((response, context) => {
|
|
525
|
-
if (response.readiness.signoff.spec_commitment.toLowerCase() !== response.content_record.spec_commitment.toLowerCase()) {
|
|
526
|
-
context.addIssue({
|
|
527
|
-
code: "custom",
|
|
528
|
-
path: ["readiness", "signoff", "spec_commitment"],
|
|
529
|
-
message: "Must match content_record.spec_commitment"
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
456
|
});
|
|
533
|
-
var readinessSignerResponseSchema = z3.object({
|
|
534
|
-
signer_address: addressSchema,
|
|
535
|
-
reviewer_hash: bytes32Schema2,
|
|
536
|
-
configured_model: z3.string().min(1),
|
|
537
|
-
audience: z3.string().min(1)
|
|
538
|
-
}).strict();
|
|
539
457
|
|
|
540
458
|
// ../../packages/core/src/chain-registry.ts
|
|
541
459
|
import { base, baseSepolia, foundry } from "viem/chains";
|
|
@@ -559,7 +477,7 @@ var FOUNDRY_CHAIN_ID = foundry.id;
|
|
|
559
477
|
import { Aes256Gcm, CipherSuite, HkdfSha256 } from "@hpke/core";
|
|
560
478
|
import { DhkemX25519HkdfSha256 } from "@hpke/dhkem-x25519";
|
|
561
479
|
import { concatBytes, keccak256 as keccak2562, toBytes as toBytes2 } from "viem";
|
|
562
|
-
import { z as
|
|
480
|
+
import { z as z3 } from "zod";
|
|
563
481
|
|
|
564
482
|
// ../../packages/core/src/base64.ts
|
|
565
483
|
var BASE64_ENCODE_CHUNK_BYTES = 3 * 16384;
|
|
@@ -645,42 +563,42 @@ var BASE64URL_RE = /^[A-Za-z0-9_-]+$/;
|
|
|
645
563
|
var SOLVER_SUBMISSION_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
646
564
|
var MEDIA_TYPE_RE = /^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/;
|
|
647
565
|
var KEY_ID_RE = /^[A-Za-z0-9][ -~]*$/;
|
|
648
|
-
var base64UrlSchema =
|
|
649
|
-
var lowerAddressSchema =
|
|
650
|
-
var
|
|
651
|
-
var sha256HexSchema =
|
|
652
|
-
var keyIdSchema =
|
|
653
|
-
var artifactNameSchema =
|
|
566
|
+
var base64UrlSchema = z3.string().regex(BASE64URL_RE);
|
|
567
|
+
var lowerAddressSchema = z3.string().refine(isLowercaseHexAddress);
|
|
568
|
+
var bytes32Schema2 = z3.string().refine(isLowercaseBytes32);
|
|
569
|
+
var sha256HexSchema = z3.string().refine(isSha256Hex);
|
|
570
|
+
var keyIdSchema = z3.string().min(1).max(128).regex(KEY_ID_RE);
|
|
571
|
+
var artifactNameSchema = z3.string().max(
|
|
654
572
|
MAX_SOLVER_SUBMISSION_NAME_CHARACTERS,
|
|
655
573
|
`Artifact filename exceeds ${MAX_SOLVER_SUBMISSION_NAME_CHARACTERS} ASCII characters (including extension). Solvers may shorten it only if the published challenge permits, before the deadline.`
|
|
656
574
|
).regex(SOLVER_SUBMISSION_NAME_RE);
|
|
657
|
-
var mediaTypeSchema =
|
|
658
|
-
var bountyIdSchema =
|
|
659
|
-
var chainIdSchema =
|
|
660
|
-
var privateArtifactContextSchema =
|
|
661
|
-
type:
|
|
575
|
+
var mediaTypeSchema = z3.string().regex(MEDIA_TYPE_RE);
|
|
576
|
+
var bountyIdSchema = z3.string().refine(isBountyId);
|
|
577
|
+
var chainIdSchema = z3.number().int().positive().lte(Number.MAX_SAFE_INTEGER);
|
|
578
|
+
var privateArtifactContextSchema = z3.strictObject({
|
|
579
|
+
type: z3.literal("solver_submission"),
|
|
662
580
|
chain_id: chainIdSchema,
|
|
663
581
|
hub_address: lowerAddressSchema,
|
|
664
582
|
bounty_id: bountyIdSchema,
|
|
665
583
|
actor_address: lowerAddressSchema
|
|
666
584
|
});
|
|
667
|
-
var guardianRecipientSchema =
|
|
585
|
+
var guardianRecipientSchema = z3.strictObject({
|
|
668
586
|
key_id: keyIdSchema,
|
|
669
|
-
suite:
|
|
587
|
+
suite: z3.literal(PRIVATE_ARTIFACT_HPKE_SUITE),
|
|
670
588
|
public_key: base64UrlSchema.length(
|
|
671
589
|
43,
|
|
672
590
|
"public_key must encode a 32-byte X25519 public key"
|
|
673
591
|
)
|
|
674
592
|
});
|
|
675
|
-
var guardianRecipientPrivateKeySchema =
|
|
593
|
+
var guardianRecipientPrivateKeySchema = z3.strictObject({
|
|
676
594
|
key_id: keyIdSchema,
|
|
677
|
-
suite:
|
|
595
|
+
suite: z3.literal(PRIVATE_ARTIFACT_HPKE_SUITE),
|
|
678
596
|
private_key: base64UrlSchema.length(
|
|
679
597
|
43,
|
|
680
598
|
"private_key must encode a 32-byte X25519 private key"
|
|
681
599
|
)
|
|
682
600
|
});
|
|
683
|
-
var guardianRecipientsSchema =
|
|
601
|
+
var guardianRecipientsSchema = z3.array(guardianRecipientSchema).min(1).superRefine((recipients, ctx) => {
|
|
684
602
|
const seen = /* @__PURE__ */ new Set();
|
|
685
603
|
for (const recipient of recipients) {
|
|
686
604
|
if (seen.has(recipient.key_id)) {
|
|
@@ -693,24 +611,24 @@ var guardianRecipientsSchema = z4.array(guardianRecipientSchema).min(1).superRef
|
|
|
693
611
|
seen.add(recipient.key_id);
|
|
694
612
|
}
|
|
695
613
|
});
|
|
696
|
-
var guardianRecipientPrivateKeysSchema =
|
|
697
|
-
var artifactManifestEntrySchema =
|
|
614
|
+
var guardianRecipientPrivateKeysSchema = z3.array(guardianRecipientPrivateKeySchema).min(1);
|
|
615
|
+
var artifactManifestEntrySchema = z3.strictObject({
|
|
698
616
|
name: artifactNameSchema,
|
|
699
617
|
media_type: mediaTypeSchema,
|
|
700
|
-
size_bytes:
|
|
618
|
+
size_bytes: z3.number().int().nonnegative().lte(Number.MAX_SAFE_INTEGER),
|
|
701
619
|
sha256: sha256HexSchema
|
|
702
620
|
});
|
|
703
|
-
var privateArtifactPublicManifestSchema =
|
|
704
|
-
kind:
|
|
621
|
+
var privateArtifactPublicManifestSchema = z3.strictObject({
|
|
622
|
+
kind: z3.literal(PRIVATE_ARTIFACT_PUBLIC_MANIFEST_KIND),
|
|
705
623
|
context: privateArtifactContextSchema
|
|
706
624
|
});
|
|
707
625
|
var encryptedBundleArtifactSchema = artifactManifestEntrySchema.extend({
|
|
708
626
|
bytes: base64UrlSchema
|
|
709
627
|
});
|
|
710
|
-
var privateArtifactEncryptedBundleSchema =
|
|
711
|
-
kind:
|
|
628
|
+
var privateArtifactEncryptedBundleSchema = z3.strictObject({
|
|
629
|
+
kind: z3.literal(PRIVATE_ARTIFACT_ENCRYPTED_BUNDLE_KIND),
|
|
712
630
|
context: privateArtifactContextSchema,
|
|
713
|
-
artifacts:
|
|
631
|
+
artifacts: z3.array(encryptedBundleArtifactSchema).min(1).max(
|
|
714
632
|
MAX_SOLVER_SUBMISSION_FILES,
|
|
715
633
|
`Submission exceeds the maximum of ${MAX_SOLVER_SUBMISSION_FILES} files.`
|
|
716
634
|
).refine(
|
|
@@ -718,33 +636,33 @@ var privateArtifactEncryptedBundleSchema = z4.strictObject({
|
|
|
718
636
|
"artifact names must be unique case-insensitively"
|
|
719
637
|
)
|
|
720
638
|
});
|
|
721
|
-
var privateArtifactRevealPolicySchema =
|
|
722
|
-
kind:
|
|
723
|
-
network:
|
|
724
|
-
chain_hash:
|
|
725
|
-
round:
|
|
726
|
-
not_before:
|
|
639
|
+
var privateArtifactRevealPolicySchema = z3.strictObject({
|
|
640
|
+
kind: z3.literal(PRIVATE_ARTIFACT_REVEAL_POLICY_KIND),
|
|
641
|
+
network: z3.string().min(1),
|
|
642
|
+
chain_hash: z3.string().min(1),
|
|
643
|
+
round: z3.string().refine(isPositiveInteger),
|
|
644
|
+
not_before: z3.number().int().nonnegative().lte(Number.MAX_SAFE_INTEGER)
|
|
727
645
|
});
|
|
728
|
-
var wrappedRecipientKeySchema =
|
|
646
|
+
var wrappedRecipientKeySchema = z3.strictObject({
|
|
729
647
|
key_id: keyIdSchema,
|
|
730
|
-
suite:
|
|
648
|
+
suite: z3.literal(PRIVATE_ARTIFACT_HPKE_SUITE),
|
|
731
649
|
enc: base64UrlSchema,
|
|
732
650
|
ciphertext: base64UrlSchema
|
|
733
651
|
});
|
|
734
|
-
var wrappedKeyBagSchema =
|
|
735
|
-
kind:
|
|
736
|
-
keys:
|
|
652
|
+
var wrappedKeyBagSchema = z3.strictObject({
|
|
653
|
+
kind: z3.literal(PRIVATE_ARTIFACT_WRAPPED_KEY_BAG_KIND),
|
|
654
|
+
keys: z3.array(wrappedRecipientKeySchema).min(1)
|
|
737
655
|
});
|
|
738
|
-
var privateArtifactEnvelopeSchema =
|
|
739
|
-
kind:
|
|
740
|
-
alg:
|
|
656
|
+
var privateArtifactEnvelopeSchema = z3.strictObject({
|
|
657
|
+
kind: z3.literal(PRIVATE_ARTIFACT_ENVELOPE_KIND),
|
|
658
|
+
alg: z3.literal(SUBMISSION_ENCRYPTION_TYPE),
|
|
741
659
|
context: privateArtifactContextSchema,
|
|
742
660
|
public_manifest: privateArtifactPublicManifestSchema,
|
|
743
661
|
public_manifest_sha256: sha256HexSchema,
|
|
744
662
|
encrypted_bundle_sha256: sha256HexSchema,
|
|
745
663
|
ciphertext_sha256: sha256HexSchema,
|
|
746
664
|
guardian_recipients: guardianRecipientsSchema,
|
|
747
|
-
guardian_recipients_commitment:
|
|
665
|
+
guardian_recipients_commitment: bytes32Schema2,
|
|
748
666
|
reveal_policy: privateArtifactRevealPolicySchema,
|
|
749
667
|
envelope_nonce: base64UrlSchema.length(
|
|
750
668
|
22,
|
|
@@ -752,7 +670,7 @@ var privateArtifactEnvelopeSchema = z4.strictObject({
|
|
|
752
670
|
),
|
|
753
671
|
iv: base64UrlSchema.length(16, "iv must encode 12 bytes"),
|
|
754
672
|
wrapped_key_bag: base64UrlSchema,
|
|
755
|
-
ciphertext_locator:
|
|
673
|
+
ciphertext_locator: z3.string().min(1)
|
|
756
674
|
});
|
|
757
675
|
function parsePrivateArtifactEnvelope(input) {
|
|
758
676
|
return privateArtifactEnvelopeSchema.parse(input);
|
|
@@ -810,11 +728,11 @@ var x25519PrivateKeySchema = base64UrlSchema.length(
|
|
|
810
728
|
43,
|
|
811
729
|
"must encode a 32-byte X25519 private key"
|
|
812
730
|
);
|
|
813
|
-
var winningSolutionDeliveryContextSchema =
|
|
731
|
+
var winningSolutionDeliveryContextSchema = z3.strictObject({
|
|
814
732
|
chain_id: chainIdSchema,
|
|
815
733
|
hub_address: lowerAddressSchema,
|
|
816
734
|
bounty_id: bountyIdSchema,
|
|
817
|
-
submission_commitment:
|
|
735
|
+
submission_commitment: bytes32Schema2
|
|
818
736
|
});
|
|
819
737
|
async function generateX25519KeyPair(input) {
|
|
820
738
|
const suite = createHpkeSuite();
|
|
@@ -891,7 +809,7 @@ function buildWinningSolutionDeliveryInfo(contextCommitment) {
|
|
|
891
809
|
var GUARDIAN_ROSTER_KEY_PROOF_INFO = "elgora/guardian-roster-key-proof/hpke-fixture/v0";
|
|
892
810
|
var GUARDIAN_ROSTER_KEY_PROOF_MESSAGE_TYPE = "elgora_guardian_roster_key_proof_v0";
|
|
893
811
|
var GUARDIAN_ROSTER_KEY_PROOF_FIXTURE_BYTES = 32;
|
|
894
|
-
var guardianRosterKeyProofContextSchema =
|
|
812
|
+
var guardianRosterKeyProofContextSchema = z3.strictObject({
|
|
895
813
|
chain_id: chainIdSchema,
|
|
896
814
|
hub_address: lowerAddressSchema,
|
|
897
815
|
proposed_account: lowerAddressSchema,
|
|
@@ -1219,7 +1137,7 @@ async function wrapAesKeyForRecipients(input) {
|
|
|
1219
1137
|
}
|
|
1220
1138
|
async function openAesKeyForRecipient(input) {
|
|
1221
1139
|
const suite = createHpkeSuite();
|
|
1222
|
-
const wrappedKeys =
|
|
1140
|
+
const wrappedKeys = z3.array(wrappedRecipientKeySchema).parse(input.wrappedKeys);
|
|
1223
1141
|
const privateKeys = guardianRecipientPrivateKeysSchema.parse(
|
|
1224
1142
|
input.privateKeys
|
|
1225
1143
|
);
|
|
@@ -1615,7 +1533,7 @@ var DEPLOYMENTS = {
|
|
|
1615
1533
|
ELGORA_ESCROW_TOKEN_ADDRESS: "0x036cbd53842c5426634e7929541ec2318f3dcf7e",
|
|
1616
1534
|
payoutSchemeAddress: "0x752d4305b8567b777d479dfa9847dc4f5ffb5750",
|
|
1617
1535
|
ELGORA_SUBGRAPH_ENDPOINT: "https://api.goldsky.com/api/public/project_cmtu7wslg04s501ovc2je3beh/subgraphs/elgora-elgorahub/testnet-production/gn",
|
|
1618
|
-
ELGORA_API_BASE_URL: "https://
|
|
1536
|
+
ELGORA_API_BASE_URL: "https://testnet.elgora.ai",
|
|
1619
1537
|
deployBlock: 46353511,
|
|
1620
1538
|
deployTransaction: "0xed3d3c8af3c69f9f8d4ec47da7179fe4b89bd4a4cd8d8232dbbd3d3f3d38e74b",
|
|
1621
1539
|
sourceCommit: "1377da5c38dc5c90d8608ffa3cb15ad6f8567a01"
|
|
@@ -3930,7 +3848,7 @@ function settlementAmounts(escrowAmount, treasuryFeeBps, guardianFeeBps) {
|
|
|
3930
3848
|
import { zeroAddress } from "viem";
|
|
3931
3849
|
|
|
3932
3850
|
// ../../packages/core/src/api/bounty-preparation.ts
|
|
3933
|
-
import { ZodError, z as
|
|
3851
|
+
import { ZodError, z as z4 } from "zod";
|
|
3934
3852
|
|
|
3935
3853
|
// ../../packages/core/src/submission-timelock.ts
|
|
3936
3854
|
import {
|
|
@@ -4191,7 +4109,7 @@ import {
|
|
|
4191
4109
|
getAbiItem as getAbiItem2,
|
|
4192
4110
|
parseAbi,
|
|
4193
4111
|
parseSignature,
|
|
4194
|
-
recoverTypedDataAddress
|
|
4112
|
+
recoverTypedDataAddress
|
|
4195
4113
|
} from "viem";
|
|
4196
4114
|
var ELGORA_HUB_ERRORS = ELGORA_HUB_ABI.filter(
|
|
4197
4115
|
(item) => item.type === "error"
|
|
@@ -4348,7 +4266,7 @@ async function prepareAuthorizedCreateBountyTransaction(input) {
|
|
|
4348
4266
|
if (unsupported) return null;
|
|
4349
4267
|
throw error;
|
|
4350
4268
|
}
|
|
4351
|
-
if ((await
|
|
4269
|
+
if ((await recoverTypedDataAddress({ ...authorization, signature })).toLowerCase() !== poster.toLowerCase()) {
|
|
4352
4270
|
throw new Error("USDC authorization was not signed by the funding Poster.");
|
|
4353
4271
|
}
|
|
4354
4272
|
const { r, s, yParity } = parseSignature(signature);
|
|
@@ -4424,14 +4342,14 @@ var BoundaryValidationError = class extends Error {
|
|
|
4424
4342
|
this.issues = issues;
|
|
4425
4343
|
}
|
|
4426
4344
|
};
|
|
4427
|
-
var artifactUploadUrlRequestSchema =
|
|
4428
|
-
ciphertext_sha256:
|
|
4429
|
-
ciphertext_byte_length:
|
|
4345
|
+
var artifactUploadUrlRequestSchema = z4.object({
|
|
4346
|
+
ciphertext_sha256: z4.string().refine(isSha256Hex),
|
|
4347
|
+
ciphertext_byte_length: z4.number().int().positive().max(MAX_SOLVER_SUBMISSION_CIPHERTEXT_BYTES)
|
|
4430
4348
|
}).strict();
|
|
4431
4349
|
|
|
4432
4350
|
// ../../packages/core/src/api/config.ts
|
|
4433
4351
|
import { createHash } from "crypto";
|
|
4434
|
-
import { z as
|
|
4352
|
+
import { z as z5 } from "zod";
|
|
4435
4353
|
function withDeploymentEnvDefaults(env) {
|
|
4436
4354
|
const merged = { ...env };
|
|
4437
4355
|
const setIfBlank = (key, value) => {
|
|
@@ -4452,11 +4370,11 @@ function withDeploymentEnvDefaults(env) {
|
|
|
4452
4370
|
setIfBlank("ELGORA_SUBGRAPH_ENDPOINT", deployment?.ELGORA_SUBGRAPH_ENDPOINT);
|
|
4453
4371
|
return merged;
|
|
4454
4372
|
}
|
|
4455
|
-
var chainIdField =
|
|
4373
|
+
var chainIdField = z5.coerce.number().int().positive().refine((chainId) => SUPPORTED_CHAINS[chainId] !== void 0, {
|
|
4456
4374
|
message: `ELGORA_CHAIN_ID must be a supported chain: ${Object.keys(SUPPORTED_CHAINS).join(", ")}`
|
|
4457
4375
|
});
|
|
4458
|
-
var hubAddressField =
|
|
4459
|
-
var publicDeploymentEnvSchema =
|
|
4376
|
+
var hubAddressField = z5.string().refine(isHexAddress, "ELGORA_HUB_ADDRESS must be a 20-byte EVM address").transform((value) => value.toLowerCase());
|
|
4377
|
+
var publicDeploymentEnvSchema = z5.object({
|
|
4460
4378
|
ELGORA_CHAIN_ID: chainIdField,
|
|
4461
4379
|
ELGORA_HUB_ADDRESS: hubAddressField
|
|
4462
4380
|
});
|
|
@@ -4472,50 +4390,42 @@ function loadPublicDeploymentConfig(env = process.env) {
|
|
|
4472
4390
|
var envShape = {
|
|
4473
4391
|
ELGORA_CHAIN_ID: chainIdField,
|
|
4474
4392
|
ELGORA_HUB_ADDRESS: hubAddressField,
|
|
4475
|
-
ELGORA_ESCROW_TOKEN_ADDRESS:
|
|
4393
|
+
ELGORA_ESCROW_TOKEN_ADDRESS: z5.string().refine(
|
|
4476
4394
|
isHexAddress,
|
|
4477
4395
|
"ELGORA_ESCROW_TOKEN_ADDRESS must be a 20-byte EVM address"
|
|
4478
4396
|
).transform((value) => value.toLowerCase()),
|
|
4479
|
-
ELGORA_TIMELOCK_REVEAL_DELAY_SECONDS:
|
|
4480
|
-
ELGORA_RPC_URL:
|
|
4397
|
+
ELGORA_TIMELOCK_REVEAL_DELAY_SECONDS: z5.coerce.number().int().nonnegative().default(DEFAULT_TIMELOCK_REVEAL_DELAY_SECONDS),
|
|
4398
|
+
ELGORA_RPC_URL: z5.string().min(1, "ELGORA_RPC_URL is required"),
|
|
4481
4399
|
/**
|
|
4482
4400
|
* Only consulted for a chain with no recorded deployment — a local anvil
|
|
4483
4401
|
* stack, whose addresses change on every deploy. A recorded deployment's
|
|
4484
4402
|
* scheme always wins, because settlement validation compares against it.
|
|
4485
4403
|
*/
|
|
4486
|
-
ELGORA_PAYOUT_SCHEME_ADDRESS:
|
|
4404
|
+
ELGORA_PAYOUT_SCHEME_ADDRESS: z5.string().refine(
|
|
4487
4405
|
isHexAddress,
|
|
4488
4406
|
"ELGORA_PAYOUT_SCHEME_ADDRESS must be a 20-byte EVM address"
|
|
4489
4407
|
).transform((value) => value.toLowerCase()).optional(),
|
|
4490
|
-
ELGORA_DATABASE_URL:
|
|
4491
|
-
ELGORA_SUBGRAPH_ENDPOINT:
|
|
4492
|
-
ELGORA_ARTIFACT_STORAGE_ENDPOINT:
|
|
4493
|
-
ELGORA_ARTIFACT_STORAGE_REGION:
|
|
4494
|
-
ELGORA_ARTIFACT_STORAGE_BUCKET:
|
|
4495
|
-
ELGORA_ARTIFACT_STORAGE_ACCESS_KEY_ID:
|
|
4496
|
-
ELGORA_ARTIFACT_STORAGE_SECRET_ACCESS_KEY:
|
|
4497
|
-
ELGORA_DELIVERY_PUBLIC_KEY:
|
|
4498
|
-
ELGORA_DELIVERY_PRIVATE_KEY:
|
|
4408
|
+
ELGORA_DATABASE_URL: z5.string().min(1, "ELGORA_DATABASE_URL is required"),
|
|
4409
|
+
ELGORA_SUBGRAPH_ENDPOINT: z5.string().min(1, "ELGORA_SUBGRAPH_ENDPOINT is required"),
|
|
4410
|
+
ELGORA_ARTIFACT_STORAGE_ENDPOINT: z5.string().min(1, "ELGORA_ARTIFACT_STORAGE_ENDPOINT is required"),
|
|
4411
|
+
ELGORA_ARTIFACT_STORAGE_REGION: z5.string().min(1, "ELGORA_ARTIFACT_STORAGE_REGION is required"),
|
|
4412
|
+
ELGORA_ARTIFACT_STORAGE_BUCKET: z5.string().min(1, "ELGORA_ARTIFACT_STORAGE_BUCKET is required"),
|
|
4413
|
+
ELGORA_ARTIFACT_STORAGE_ACCESS_KEY_ID: z5.string().min(1, "ELGORA_ARTIFACT_STORAGE_ACCESS_KEY_ID is required"),
|
|
4414
|
+
ELGORA_ARTIFACT_STORAGE_SECRET_ACCESS_KEY: z5.string().min(1, "ELGORA_ARTIFACT_STORAGE_SECRET_ACCESS_KEY is required"),
|
|
4415
|
+
ELGORA_DELIVERY_PUBLIC_KEY: z5.string().min(1, "ELGORA_DELIVERY_PUBLIC_KEY is required"),
|
|
4416
|
+
ELGORA_DELIVERY_PRIVATE_KEY: z5.string().min(1, "ELGORA_DELIVERY_PRIVATE_KEY is required")
|
|
4499
4417
|
};
|
|
4500
|
-
var readinessAudienceSchema = z6.string().trim().toLowerCase().min(1).max(512).refine((host) => {
|
|
4501
|
-
try {
|
|
4502
|
-
const url = new URL(`https://${host}`);
|
|
4503
|
-
return url.host === host && url.pathname === "/" && !url.username && !url.password && !url.search && !url.hash;
|
|
4504
|
-
} catch {
|
|
4505
|
-
return false;
|
|
4506
|
-
}
|
|
4507
|
-
}, "Must be a canonical hostname with optional port, without a URL path");
|
|
4508
4418
|
var publicationEnvShape = {
|
|
4509
4419
|
ELGORA_CHAIN_ID: envShape.ELGORA_CHAIN_ID,
|
|
4510
4420
|
ELGORA_HUB_ADDRESS: envShape.ELGORA_HUB_ADDRESS,
|
|
4511
4421
|
ELGORA_ESCROW_TOKEN_ADDRESS: envShape.ELGORA_ESCROW_TOKEN_ADDRESS,
|
|
4512
4422
|
ELGORA_DATABASE_URL: envShape.ELGORA_DATABASE_URL,
|
|
4513
4423
|
ELGORA_SUBGRAPH_ENDPOINT: envShape.ELGORA_SUBGRAPH_ENDPOINT,
|
|
4514
|
-
ELGORA_PUBLICATION_REVIEW_ENABLED:
|
|
4515
|
-
ELGORA_READINESS_TIMEOUT_MS:
|
|
4424
|
+
ELGORA_PUBLICATION_REVIEW_ENABLED: z5.string().trim().toLowerCase().pipe(z5.enum(["true", "false"])).default("true").transform((value) => value === "true"),
|
|
4425
|
+
ELGORA_READINESS_TIMEOUT_MS: z5.coerce.number().int().min(1).max(READINESS_TIMEOUT_MS).default(READINESS_TIMEOUT_MS)
|
|
4516
4426
|
};
|
|
4517
|
-
var envSchema =
|
|
4518
|
-
var bountyPublicationEnvSchema =
|
|
4427
|
+
var envSchema = z5.object(envShape);
|
|
4428
|
+
var bountyPublicationEnvSchema = z5.object(publicationEnvShape);
|
|
4519
4429
|
|
|
4520
4430
|
// ../../packages/core/src/api/elgora-hub-error-catalog.ts
|
|
4521
4431
|
import { decodeErrorResult } from "viem";
|
|
@@ -4530,81 +4440,81 @@ var ELGORA_HUB_FEE_POLICY_ABI = [
|
|
|
4530
4440
|
];
|
|
4531
4441
|
|
|
4532
4442
|
// ../../packages/core/src/api/solver-submission-responses.ts
|
|
4533
|
-
import { isHex as
|
|
4534
|
-
import { z as
|
|
4535
|
-
var hexAddressSchema =
|
|
4536
|
-
var hexBytes32Schema =
|
|
4537
|
-
var hexDataSchema =
|
|
4538
|
-
var artifactUploadUrlResponseSchema =
|
|
4539
|
-
locator:
|
|
4540
|
-
upload_url:
|
|
4541
|
-
method:
|
|
4542
|
-
expires_at:
|
|
4443
|
+
import { isHex as isHex3 } from "viem";
|
|
4444
|
+
import { z as z6 } from "zod";
|
|
4445
|
+
var hexAddressSchema = z6.string().refine(isHexAddress, "Must be a hex-encoded address");
|
|
4446
|
+
var hexBytes32Schema = z6.string().refine(isHexBytes32, "Must be 32-byte hex");
|
|
4447
|
+
var hexDataSchema = z6.string().refine((value) => isHex3(value), "Must be hex-encoded calldata");
|
|
4448
|
+
var artifactUploadUrlResponseSchema = z6.object({
|
|
4449
|
+
locator: z6.string().min(1),
|
|
4450
|
+
upload_url: z6.string().min(1),
|
|
4451
|
+
method: z6.literal("PUT"),
|
|
4452
|
+
expires_at: z6.string().min(1)
|
|
4543
4453
|
});
|
|
4544
|
-
var solverSubmissionPrepareResponseSchema =
|
|
4545
|
-
content_record:
|
|
4546
|
-
content_kind:
|
|
4454
|
+
var solverSubmissionPrepareResponseSchema = z6.object({
|
|
4455
|
+
content_record: z6.object({
|
|
4456
|
+
content_kind: z6.literal(SOLVER_SUBMISSION_CONTENT_KIND),
|
|
4547
4457
|
submission_commitment: hexBytes32Schema,
|
|
4548
|
-
byte_length:
|
|
4549
|
-
created_at:
|
|
4458
|
+
byte_length: z6.number().int().nonnegative(),
|
|
4459
|
+
created_at: z6.string().min(1)
|
|
4550
4460
|
}),
|
|
4551
|
-
submit_transaction:
|
|
4552
|
-
chain_id:
|
|
4461
|
+
submit_transaction: z6.object({
|
|
4462
|
+
chain_id: z6.number().int().positive(),
|
|
4553
4463
|
to: hexAddressSchema,
|
|
4554
|
-
value:
|
|
4464
|
+
value: z6.literal("0"),
|
|
4555
4465
|
data: hexDataSchema,
|
|
4556
|
-
function_name:
|
|
4557
|
-
args:
|
|
4558
|
-
bounty_id:
|
|
4466
|
+
function_name: z6.literal("submit"),
|
|
4467
|
+
args: z6.object({
|
|
4468
|
+
bounty_id: z6.string().min(1),
|
|
4559
4469
|
submission_commitment: hexBytes32Schema,
|
|
4560
4470
|
guardian_roster_hash: hexBytes32Schema,
|
|
4561
|
-
extra_data:
|
|
4471
|
+
extra_data: z6.literal("0x")
|
|
4562
4472
|
})
|
|
4563
4473
|
})
|
|
4564
4474
|
});
|
|
4565
|
-
var solverSubmissionContentResponseSchema =
|
|
4566
|
-
content_record:
|
|
4567
|
-
bounty_id:
|
|
4568
|
-
canonical_json:
|
|
4475
|
+
var solverSubmissionContentResponseSchema = z6.object({
|
|
4476
|
+
content_record: z6.object({
|
|
4477
|
+
bounty_id: z6.string().min(1),
|
|
4478
|
+
canonical_json: z6.string().min(1)
|
|
4569
4479
|
}),
|
|
4570
|
-
ciphertext_download_url:
|
|
4571
|
-
expires_at:
|
|
4480
|
+
ciphertext_download_url: z6.string().min(1),
|
|
4481
|
+
expires_at: z6.string().min(1)
|
|
4572
4482
|
});
|
|
4573
|
-
var bountyGuardianRosterResponseSchema =
|
|
4574
|
-
bounty:
|
|
4483
|
+
var bountyGuardianRosterResponseSchema = z6.object({
|
|
4484
|
+
bounty: z6.object({
|
|
4575
4485
|
guardian_roster_hash: hexBytes32Schema,
|
|
4576
|
-
guardian_roster:
|
|
4577
|
-
|
|
4578
|
-
name:
|
|
4486
|
+
guardian_roster: z6.array(
|
|
4487
|
+
z6.object({
|
|
4488
|
+
name: z6.string(),
|
|
4579
4489
|
account: hexAddressSchema,
|
|
4580
|
-
encryption_public_key:
|
|
4490
|
+
encryption_public_key: z6.string().min(1)
|
|
4581
4491
|
})
|
|
4582
4492
|
).min(1)
|
|
4583
4493
|
})
|
|
4584
4494
|
});
|
|
4585
4495
|
|
|
4586
4496
|
// ../../packages/core/src/api/verification-records.ts
|
|
4587
|
-
import { z as
|
|
4588
|
-
var hexAddressSchema2 =
|
|
4589
|
-
var hexBytes32Schema2 =
|
|
4590
|
-
var integerStringSchema =
|
|
4591
|
-
var verdictEntrySchema =
|
|
4592
|
-
name:
|
|
4593
|
-
outcome:
|
|
4497
|
+
import { z as z7 } from "zod";
|
|
4498
|
+
var hexAddressSchema2 = z7.string().refine(isHexAddress, "Must be a hex-encoded address").transform((value) => value.toLowerCase());
|
|
4499
|
+
var hexBytes32Schema2 = z7.string().refine(isHexBytes32, "Must be 32-byte hex").transform((value) => value.toLowerCase());
|
|
4500
|
+
var integerStringSchema = z7.string().regex(/^(0|[1-9][0-9]*)$/);
|
|
4501
|
+
var verdictEntrySchema = z7.object({
|
|
4502
|
+
name: z7.string().min(1),
|
|
4503
|
+
outcome: z7.enum(["awarded", "no_valid_submission"]).nullable(),
|
|
4594
4504
|
winner: hexAddressSchema2.nullable(),
|
|
4595
4505
|
report_commitment: hexBytes32Schema2.nullable(),
|
|
4596
|
-
committed_at:
|
|
4597
|
-
supporting:
|
|
4506
|
+
committed_at: z7.string().datetime({ offset: true }).nullable(),
|
|
4507
|
+
supporting: z7.boolean()
|
|
4598
4508
|
}).strict();
|
|
4599
|
-
var formattedVerificationRecordSchema =
|
|
4600
|
-
chain_id:
|
|
4509
|
+
var formattedVerificationRecordSchema = z7.object({
|
|
4510
|
+
chain_id: z7.number().int().positive(),
|
|
4601
4511
|
hub_address: hexAddressSchema2,
|
|
4602
4512
|
bounty_id: integerStringSchema,
|
|
4603
|
-
status:
|
|
4513
|
+
status: z7.enum(["awarded", "no_valid_submission", "timed_out"]),
|
|
4604
4514
|
spec_commitment: hexBytes32Schema2,
|
|
4605
4515
|
winner: hexAddressSchema2.nullable(),
|
|
4606
|
-
verdicts:
|
|
4607
|
-
settlement:
|
|
4516
|
+
verdicts: z7.record(z7.string(), verdictEntrySchema),
|
|
4517
|
+
settlement: z7.object({
|
|
4608
4518
|
escrow_amount: integerStringSchema,
|
|
4609
4519
|
settlement_recipient: hexAddressSchema2,
|
|
4610
4520
|
settlement_amount: integerStringSchema,
|
|
@@ -4615,10 +4525,10 @@ var formattedVerificationRecordSchema = z8.object({
|
|
|
4615
4525
|
settled_tx_hash: hexBytes32Schema2,
|
|
4616
4526
|
settled_block_number: integerStringSchema
|
|
4617
4527
|
}).strict(),
|
|
4618
|
-
content_record:
|
|
4619
|
-
spec_content_byte_length:
|
|
4528
|
+
content_record: z7.object({
|
|
4529
|
+
spec_content_byte_length: z7.number().int().positive()
|
|
4620
4530
|
}).strict(),
|
|
4621
|
-
verified_at:
|
|
4531
|
+
verified_at: z7.string().datetime({ offset: true })
|
|
4622
4532
|
}).strict();
|
|
4623
4533
|
function parseBountyVerificationRecord(input, expected) {
|
|
4624
4534
|
const slice = input;
|
|
@@ -4640,79 +4550,79 @@ function parseBountyVerificationRecord(input, expected) {
|
|
|
4640
4550
|
}
|
|
4641
4551
|
|
|
4642
4552
|
// ../../packages/core/src/api/winning-solution-delivery.ts
|
|
4643
|
-
import { z as
|
|
4644
|
-
var hexBytes32Schema3 =
|
|
4645
|
-
var hexAddressSchema3 =
|
|
4646
|
-
var deliveryKeyIdSchema =
|
|
4647
|
-
var winningSolutionWrappedKeySchema =
|
|
4648
|
-
enc:
|
|
4649
|
-
ciphertext:
|
|
4553
|
+
import { z as z8 } from "zod";
|
|
4554
|
+
var hexBytes32Schema3 = z8.string().refine(isHexBytes32, "Must be 32-byte hex").refine((value) => value !== ZERO_BYTES32, "Must not be zero").transform((value) => value.toLowerCase());
|
|
4555
|
+
var hexAddressSchema3 = z8.string().refine((value) => /^0x[0-9a-fA-F]{40}$/.test(value), "Must be an address").transform((value) => value.toLowerCase());
|
|
4556
|
+
var deliveryKeyIdSchema = z8.string().min(1).max(128);
|
|
4557
|
+
var winningSolutionWrappedKeySchema = z8.strictObject({
|
|
4558
|
+
enc: z8.string().min(1),
|
|
4559
|
+
ciphertext: z8.string().min(1)
|
|
4650
4560
|
});
|
|
4651
|
-
var deliveryWrapRequestSchema =
|
|
4561
|
+
var deliveryWrapRequestSchema = z8.strictObject({
|
|
4652
4562
|
solver_address: hexAddressSchema3,
|
|
4653
4563
|
submission_commitment: hexBytes32Schema3,
|
|
4654
4564
|
wrapped_key: winningSolutionWrappedKeySchema
|
|
4655
4565
|
});
|
|
4656
|
-
var deliveryWrapRecordSchema =
|
|
4657
|
-
bounty_id:
|
|
4566
|
+
var deliveryWrapRecordSchema = z8.strictObject({
|
|
4567
|
+
bounty_id: z8.string().min(1),
|
|
4658
4568
|
guardian_address: hexAddressSchema3,
|
|
4659
4569
|
solver_address: hexAddressSchema3,
|
|
4660
4570
|
submission_commitment: hexBytes32Schema3,
|
|
4661
4571
|
delivery_key_id: deliveryKeyIdSchema,
|
|
4662
|
-
created_at:
|
|
4572
|
+
created_at: z8.string().min(1)
|
|
4663
4573
|
});
|
|
4664
|
-
var deliveryWrapResponseSchema =
|
|
4665
|
-
status:
|
|
4574
|
+
var deliveryWrapResponseSchema = z8.strictObject({
|
|
4575
|
+
status: z8.literal("stored"),
|
|
4666
4576
|
wrap: deliveryWrapRecordSchema
|
|
4667
4577
|
});
|
|
4668
|
-
var deliveryRetrieveRequestSchema =
|
|
4578
|
+
var deliveryRetrieveRequestSchema = z8.strictObject({
|
|
4669
4579
|
poster_ephemeral_public_key: x25519PublicKeySchema
|
|
4670
4580
|
});
|
|
4671
|
-
var deliveryRetrieveResponseSchema =
|
|
4581
|
+
var deliveryRetrieveResponseSchema = z8.strictObject({
|
|
4672
4582
|
submission_commitment: hexBytes32Schema3,
|
|
4673
4583
|
wrapped_key: winningSolutionWrappedKeySchema
|
|
4674
4584
|
});
|
|
4675
|
-
var deliveryStatusResponseSchema =
|
|
4676
|
-
exists:
|
|
4585
|
+
var deliveryStatusResponseSchema = z8.strictObject({
|
|
4586
|
+
exists: z8.boolean()
|
|
4677
4587
|
});
|
|
4678
|
-
var deliveryKeyConfigResponseSchema =
|
|
4588
|
+
var deliveryKeyConfigResponseSchema = z8.strictObject({
|
|
4679
4589
|
delivery_key_id: deliveryKeyIdSchema,
|
|
4680
|
-
public_key:
|
|
4590
|
+
public_key: z8.string().min(1)
|
|
4681
4591
|
});
|
|
4682
4592
|
|
|
4683
4593
|
// ../../packages/core/src/api/written-verdicts.ts
|
|
4684
4594
|
import { keccak256 as keccak2564, toBytes as toBytes3, zeroAddress as zeroAddress2 } from "viem";
|
|
4685
|
-
import { z as
|
|
4595
|
+
import { z as z9 } from "zod";
|
|
4686
4596
|
var WRITTEN_VERDICT_FORMAT_VERSION = 0;
|
|
4687
4597
|
var FRONTMATTER_DELIMITER2 = "---";
|
|
4688
|
-
var decimalSchema =
|
|
4689
|
-
var bountyIdSchema2 =
|
|
4690
|
-
var addressSchema2 =
|
|
4691
|
-
var
|
|
4598
|
+
var decimalSchema = z9.string().regex(/^[1-9][0-9]*$/, "Must be a positive integer").transform(Number).refine(Number.isSafeInteger, "Must be a safe integer");
|
|
4599
|
+
var bountyIdSchema2 = z9.string().regex(/^(0|[1-9][0-9]*)$/, "Must be a non-negative integer");
|
|
4600
|
+
var addressSchema2 = z9.string().refine(isHexAddress, "Must be a hex-encoded address").refine((value) => value === value.toLowerCase(), "Must use lowercase hex").transform((value) => value);
|
|
4601
|
+
var bytes32Schema3 = z9.string().refine(isHexBytes32, "Must be 32-byte hex").refine((value) => value === value.toLowerCase(), "Must use lowercase hex").transform((value) => value);
|
|
4692
4602
|
var commonFields = {
|
|
4693
|
-
format_version:
|
|
4603
|
+
format_version: z9.literal(WRITTEN_VERDICT_FORMAT_VERSION.toString()).transform(() => WRITTEN_VERDICT_FORMAT_VERSION),
|
|
4694
4604
|
chain_id: decimalSchema,
|
|
4695
4605
|
hub_address: addressSchema2,
|
|
4696
4606
|
bounty_id: bountyIdSchema2,
|
|
4697
|
-
verdict_body:
|
|
4607
|
+
verdict_body: z9.string().refine((value) => value.trim().length > 0, "Must not be empty")
|
|
4698
4608
|
};
|
|
4699
|
-
var writtenVerdictSchema =
|
|
4700
|
-
|
|
4609
|
+
var writtenVerdictSchema = z9.discriminatedUnion("outcome", [
|
|
4610
|
+
z9.object({
|
|
4701
4611
|
...commonFields,
|
|
4702
|
-
outcome:
|
|
4612
|
+
outcome: z9.literal("awarded"),
|
|
4703
4613
|
winner: addressSchema2.refine(
|
|
4704
4614
|
(value) => value !== zeroAddress2,
|
|
4705
4615
|
"Must not be the zero address"
|
|
4706
4616
|
),
|
|
4707
|
-
awarded_submission_commitment:
|
|
4617
|
+
awarded_submission_commitment: bytes32Schema3.refine(
|
|
4708
4618
|
(value) => value !== ZERO_BYTES32,
|
|
4709
4619
|
"Must not be zero bytes"
|
|
4710
4620
|
)
|
|
4711
4621
|
}).strict(),
|
|
4712
|
-
|
|
4622
|
+
z9.object({
|
|
4713
4623
|
...commonFields,
|
|
4714
|
-
outcome:
|
|
4715
|
-
winner:
|
|
4624
|
+
outcome: z9.literal("no_valid_submission"),
|
|
4625
|
+
winner: z9.literal(zeroAddress2)
|
|
4716
4626
|
}).strict()
|
|
4717
4627
|
]);
|
|
4718
4628
|
function buildWrittenVerdictMarkdown(input) {
|
|
@@ -4809,23 +4719,6 @@ import {
|
|
|
4809
4719
|
fallback,
|
|
4810
4720
|
http
|
|
4811
4721
|
} from "viem";
|
|
4812
|
-
|
|
4813
|
-
// ../../packages/core/src/auth/freshness.ts
|
|
4814
|
-
var API_REQUEST_APPROVAL_ANCHOR_LAG_SECONDS = 6;
|
|
4815
|
-
var FALLBACK_BLOCK_TIME_MS = 2e3;
|
|
4816
|
-
function blockTimeMsFor(chainId) {
|
|
4817
|
-
const chain = chainId === void 0 ? void 0 : SUPPORTED_CHAINS[chainId];
|
|
4818
|
-
return chain?.blockTime ?? FALLBACK_BLOCK_TIME_MS;
|
|
4819
|
-
}
|
|
4820
|
-
function blocksForSeconds(seconds, chainId) {
|
|
4821
|
-
const blocks = Math.ceil(seconds * 1e3 / blockTimeMsFor(chainId));
|
|
4822
|
-
return BigInt(Math.max(1, blocks));
|
|
4823
|
-
}
|
|
4824
|
-
function apiRequestApprovalAnchorLagBlocks(chainId) {
|
|
4825
|
-
return blocksForSeconds(API_REQUEST_APPROVAL_ANCHOR_LAG_SECONDS, chainId);
|
|
4826
|
-
}
|
|
4827
|
-
|
|
4828
|
-
// ../../packages/core/src/chain-client.ts
|
|
4829
4722
|
var RPC_RETRY_COUNT = 3;
|
|
4830
4723
|
function createChainTransport(chainId, rpcUrl) {
|
|
4831
4724
|
const publicRpcUrl = resolveSupportedChain(chainId).rpcUrls.default.http[0];
|
|
@@ -4859,13 +4752,6 @@ function assertChainId(actual, expected) {
|
|
|
4859
4752
|
throw new Error(`RPC returned chain_id ${actual}, expected ${expected}`);
|
|
4860
4753
|
}
|
|
4861
4754
|
}
|
|
4862
|
-
async function fetchSignableBlock(client) {
|
|
4863
|
-
const offset = apiRequestApprovalAnchorLagBlocks(client.chain?.id);
|
|
4864
|
-
const head = await client.getBlockNumber();
|
|
4865
|
-
const anchorNumber = head > offset ? head - offset : 0n;
|
|
4866
|
-
const anchor = await client.getBlock({ blockNumber: anchorNumber });
|
|
4867
|
-
return { number: anchor.number, hash: anchor.hash };
|
|
4868
|
-
}
|
|
4869
4755
|
async function assertHubDeployment(client, chainId, hubAddress) {
|
|
4870
4756
|
const [actualChainId, hubCode] = await Promise.all([
|
|
4871
4757
|
client.getChainId(),
|
|
@@ -5215,10 +5101,10 @@ var ApiRequestError = class extends Error {
|
|
|
5215
5101
|
this.retryAfterMs = input.retryAfterMs;
|
|
5216
5102
|
}
|
|
5217
5103
|
};
|
|
5218
|
-
async function postText(url, body, contentType, authorization
|
|
5104
|
+
async function postText(url, body, contentType, authorization) {
|
|
5219
5105
|
const response = await fetch(url, {
|
|
5220
5106
|
method: "POST",
|
|
5221
|
-
headers: {
|
|
5107
|
+
headers: { "content-type": contentType, authorization },
|
|
5222
5108
|
body
|
|
5223
5109
|
});
|
|
5224
5110
|
return parseJsonResponse(url, response);
|
|
@@ -5378,7 +5264,7 @@ function toArrayBuffer(bytes) {
|
|
|
5378
5264
|
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
5379
5265
|
|
|
5380
5266
|
// ../../packages/core/src/auth/authorization-header.ts
|
|
5381
|
-
import { isAddress as isAddress3, isHex as
|
|
5267
|
+
import { isAddress as isAddress3, isHex as isHex4 } from "viem";
|
|
5382
5268
|
var ELGORA_APPROVAL_AUTH_SCHEME = "Elgora-Approval";
|
|
5383
5269
|
var FIELD_SEPARATOR = "~";
|
|
5384
5270
|
function encodeApiRequestApprovalHeader(fields) {
|
|
@@ -5391,45 +5277,92 @@ function encodeApiRequestApprovalHeader(fields) {
|
|
|
5391
5277
|
return `${ELGORA_APPROVAL_AUTH_SCHEME} ${btoa(payload)}`;
|
|
5392
5278
|
}
|
|
5393
5279
|
|
|
5394
|
-
// ../../packages/core/src/auth/
|
|
5395
|
-
var
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5280
|
+
// ../../packages/core/src/auth/eip712.ts
|
|
5281
|
+
var API_REQUEST_APPROVAL_PRIMARY_TYPE = "ApiRequestApproval";
|
|
5282
|
+
var API_REQUEST_APPROVAL_TYPES = {
|
|
5283
|
+
ApiRequestApproval: [
|
|
5284
|
+
{ name: "endpointId", type: "string" },
|
|
5285
|
+
{ name: "audience", type: "string" },
|
|
5286
|
+
{ name: "bodyHash", type: "bytes32" },
|
|
5287
|
+
{ name: "query", type: "string" },
|
|
5288
|
+
{ name: "blockNumber", type: "uint256" },
|
|
5289
|
+
{ name: "blockHash", type: "bytes32" }
|
|
5290
|
+
]
|
|
5291
|
+
};
|
|
5292
|
+
function buildElgoraEip712Domain(params) {
|
|
5293
|
+
return {
|
|
5294
|
+
name: "Elgora",
|
|
5295
|
+
version: "1",
|
|
5296
|
+
chainId: params.chainId,
|
|
5297
|
+
verifyingContract: params.hubAddress
|
|
5298
|
+
};
|
|
5299
|
+
}
|
|
5300
|
+
function buildApiRequestApprovalTypedData(params) {
|
|
5301
|
+
return {
|
|
5302
|
+
domain: buildElgoraEip712Domain({
|
|
5303
|
+
chainId: params.chainId,
|
|
5304
|
+
hubAddress: params.hubAddress
|
|
5305
|
+
}),
|
|
5306
|
+
types: API_REQUEST_APPROVAL_TYPES,
|
|
5307
|
+
primaryType: API_REQUEST_APPROVAL_PRIMARY_TYPE,
|
|
5308
|
+
message: params.message
|
|
5309
|
+
};
|
|
5310
|
+
}
|
|
5311
|
+
function endpointIdFor(input) {
|
|
5312
|
+
return `${input.method.toUpperCase()} ${input.path}`;
|
|
5313
|
+
}
|
|
5314
|
+
function audienceFor(host) {
|
|
5315
|
+
return host.toLowerCase();
|
|
5316
|
+
}
|
|
5317
|
+
function queryFor(query) {
|
|
5318
|
+
return new URLSearchParams(query).toString();
|
|
5401
5319
|
}
|
|
5402
5320
|
|
|
5403
5321
|
// ../../packages/core/src/auth/request-approval.ts
|
|
5404
5322
|
import {
|
|
5405
5323
|
hashTypedData,
|
|
5406
|
-
isAddressEqual as
|
|
5324
|
+
isAddressEqual as isAddressEqual2,
|
|
5407
5325
|
keccak256 as keccak2565,
|
|
5408
5326
|
toBytes as toBytes4
|
|
5409
5327
|
} from "viem";
|
|
5410
5328
|
|
|
5411
5329
|
// ../../packages/core/src/auth/signature.ts
|
|
5412
5330
|
import {
|
|
5413
|
-
isAddressEqual
|
|
5414
|
-
recoverTypedDataAddress as
|
|
5331
|
+
isAddressEqual,
|
|
5332
|
+
recoverTypedDataAddress as recoverTypedDataAddress2
|
|
5415
5333
|
} from "viem";
|
|
5416
5334
|
|
|
5335
|
+
// ../../packages/core/src/auth/request-approval.ts
|
|
5336
|
+
function typedDataForRequest(request, block) {
|
|
5337
|
+
const bodyBytes = typeof request.body === "string" ? toBytes4(request.body) : request.body;
|
|
5338
|
+
return buildApiRequestApprovalTypedData({
|
|
5339
|
+
chainId: request.domain.chainId,
|
|
5340
|
+
hubAddress: request.domain.hubAddress,
|
|
5341
|
+
message: {
|
|
5342
|
+
endpointId: request.endpointId,
|
|
5343
|
+
audience: audienceFor(request.host),
|
|
5344
|
+
bodyHash: keccak2565(bodyBytes),
|
|
5345
|
+
query: queryFor(request.query),
|
|
5346
|
+
blockNumber: block.number,
|
|
5347
|
+
blockHash: block.hash
|
|
5348
|
+
}
|
|
5349
|
+
});
|
|
5350
|
+
}
|
|
5351
|
+
|
|
5417
5352
|
// ../../packages/core/src/auth/request-approval-header.ts
|
|
5418
|
-
import {
|
|
5353
|
+
import { z as z10 } from "zod";
|
|
5419
5354
|
async function buildAuthorizationHeader(params) {
|
|
5420
5355
|
const url = new URL(params.requestUrl);
|
|
5421
|
-
const typedData =
|
|
5422
|
-
|
|
5423
|
-
hubAddress: params.hubAddress,
|
|
5424
|
-
message: {
|
|
5356
|
+
const typedData = typedDataForRequest(
|
|
5357
|
+
{
|
|
5425
5358
|
endpointId: endpointIdFor({ method: params.method, path: url.pathname }),
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5359
|
+
host: url.host,
|
|
5360
|
+
query: url.search,
|
|
5361
|
+
body: params.body ?? "",
|
|
5362
|
+
domain: { chainId: params.chainId, hubAddress: params.hubAddress }
|
|
5363
|
+
},
|
|
5364
|
+
params.block
|
|
5365
|
+
);
|
|
5433
5366
|
const signature = await params.sign(typedData);
|
|
5434
5367
|
return encodeApiRequestApprovalHeader({
|
|
5435
5368
|
address: params.address,
|
|
@@ -5438,6 +5371,31 @@ async function buildAuthorizationHeader(params) {
|
|
|
5438
5371
|
blockHash: params.block.hash
|
|
5439
5372
|
});
|
|
5440
5373
|
}
|
|
5374
|
+
async function authorizeRequest(params) {
|
|
5375
|
+
return buildAuthorizationHeader({
|
|
5376
|
+
...params,
|
|
5377
|
+
block: await readChallengeBlock(params)
|
|
5378
|
+
});
|
|
5379
|
+
}
|
|
5380
|
+
var challengeBlockSchema = z10.object({
|
|
5381
|
+
error: z10.object({ block_number: z10.string(), block_hash: z10.string() })
|
|
5382
|
+
});
|
|
5383
|
+
async function readChallengeBlock(params) {
|
|
5384
|
+
const response = await fetch(params.requestUrl, {
|
|
5385
|
+
method: params.method,
|
|
5386
|
+
headers: params.contentType ? { "content-type": params.contentType } : {},
|
|
5387
|
+
body: params.method.toUpperCase() === "GET" ? null : params.body ?? ""
|
|
5388
|
+
});
|
|
5389
|
+
if (response.status !== 401) {
|
|
5390
|
+
throw new Error(
|
|
5391
|
+
`Expected an approval challenge (401) from ${params.requestUrl}, got ${response.status}.`
|
|
5392
|
+
);
|
|
5393
|
+
}
|
|
5394
|
+
const { block_number, block_hash } = challengeBlockSchema.parse(
|
|
5395
|
+
await response.json()
|
|
5396
|
+
).error;
|
|
5397
|
+
return { number: BigInt(block_number), hash: block_hash };
|
|
5398
|
+
}
|
|
5441
5399
|
|
|
5442
5400
|
// ../../packages/core/src/winning-solution-delivery.ts
|
|
5443
5401
|
async function wrapWinningSolutionKey(input) {
|
|
@@ -5446,14 +5404,13 @@ async function wrapWinningSolutionKey(input) {
|
|
|
5446
5404
|
apiBaseUrl: input.config.apiBaseUrl
|
|
5447
5405
|
});
|
|
5448
5406
|
const contentPathname = `/api/bounties/${input.bountyId}/submissions/${input.submissionCommitment}/content`;
|
|
5449
|
-
const contentAuthorization = await
|
|
5407
|
+
const contentAuthorization = await authorizeRequest({
|
|
5450
5408
|
requestUrl: new URL(contentPathname, input.config.apiBaseUrl).toString(),
|
|
5451
5409
|
method: "GET",
|
|
5452
5410
|
body: "",
|
|
5453
5411
|
chainId: input.config.chainId,
|
|
5454
5412
|
hubAddress: input.config.hubAddress,
|
|
5455
5413
|
address: input.owner.address,
|
|
5456
|
-
block: await fetchSignableBlock(input.publicClient),
|
|
5457
5414
|
sign: (typedData) => account.signTypedData(typedData)
|
|
5458
5415
|
});
|
|
5459
5416
|
const { content_record, ciphertext_download_url } = solverSubmissionContentResponseSchema.parse(
|
|
@@ -5505,14 +5462,14 @@ async function wrapWinningSolutionKey(input) {
|
|
|
5505
5462
|
submission_commitment: input.submissionCommitment,
|
|
5506
5463
|
wrapped_key: opened.wrapped_key
|
|
5507
5464
|
});
|
|
5508
|
-
const authorization = await
|
|
5465
|
+
const authorization = await authorizeRequest({
|
|
5509
5466
|
requestUrl: requestUrl.toString(),
|
|
5510
5467
|
method: "POST",
|
|
5468
|
+
contentType: "application/json",
|
|
5511
5469
|
body,
|
|
5512
5470
|
chainId: input.config.chainId,
|
|
5513
5471
|
hubAddress: input.config.hubAddress,
|
|
5514
5472
|
address: input.owner.address,
|
|
5515
|
-
block: await fetchSignableBlock(input.publicClient),
|
|
5516
5473
|
sign: (typedData) => account.signTypedData(typedData)
|
|
5517
5474
|
});
|
|
5518
5475
|
const responseBody = await postText(
|
|
@@ -5555,14 +5512,13 @@ async function main3(env = process.env, argv = process.argv.slice(2)) {
|
|
|
5555
5512
|
bountyId: args.bountyId,
|
|
5556
5513
|
submissionCommitment: args.submissionCommitment
|
|
5557
5514
|
});
|
|
5558
|
-
const authorization = await
|
|
5515
|
+
const authorization = await authorizeRequest({
|
|
5559
5516
|
requestUrl: new URL(pathname, config.apiBaseUrl).toString(),
|
|
5560
5517
|
method: "GET",
|
|
5561
5518
|
body: "",
|
|
5562
5519
|
chainId: config.chainId,
|
|
5563
5520
|
hubAddress: config.hubAddress,
|
|
5564
5521
|
address: account.address,
|
|
5565
|
-
block: await fetchSignableBlock(publicClient),
|
|
5566
5522
|
sign: (typedData) => account.signTypedData(typedData)
|
|
5567
5523
|
});
|
|
5568
5524
|
const { content_record, ciphertext_download_url } = await requestSubmissionContent({
|
|
@@ -5744,7 +5700,6 @@ async function main4(env = process.env, argv = process.argv.slice(2)) {
|
|
|
5744
5700
|
privateKey: guardianAccountPrivateKey,
|
|
5745
5701
|
address: account.address
|
|
5746
5702
|
},
|
|
5747
|
-
publicClient,
|
|
5748
5703
|
guardianPrivateKeys
|
|
5749
5704
|
});
|
|
5750
5705
|
console.log(
|
|
@@ -6905,14 +6860,13 @@ async function main7(env = process.env, argv = process.argv.slice(2)) {
|
|
|
6905
6860
|
}
|
|
6906
6861
|
if (args.outcome === "awarded") {
|
|
6907
6862
|
const contentPathname = `/api/bounties/${args.bountyId.toString()}/submissions/${args.awardedSubmissionCommitment}/content`;
|
|
6908
|
-
const contentAuthorization = await
|
|
6863
|
+
const contentAuthorization = await authorizeRequest({
|
|
6909
6864
|
requestUrl: new URL(contentPathname, config.apiBaseUrl).toString(),
|
|
6910
6865
|
method: "GET",
|
|
6911
6866
|
body: "",
|
|
6912
6867
|
chainId: config.chainId,
|
|
6913
6868
|
hubAddress: config.hubAddress,
|
|
6914
6869
|
address: account.address,
|
|
6915
|
-
block: await fetchSignableBlock(publicClient),
|
|
6916
6870
|
sign: (typedData) => account.signTypedData(typedData)
|
|
6917
6871
|
});
|
|
6918
6872
|
await assertCheckedSubmission({
|
|
@@ -6959,14 +6913,14 @@ async function main7(env = process.env, argv = process.argv.slice(2)) {
|
|
|
6959
6913
|
}
|
|
6960
6914
|
const pathname = `/api/written-verdicts/${reportCommitment}`;
|
|
6961
6915
|
const requestUrl = new URL(pathname, config.apiBaseUrl);
|
|
6962
|
-
const authorization = await
|
|
6916
|
+
const authorization = await authorizeRequest({
|
|
6963
6917
|
requestUrl: requestUrl.toString(),
|
|
6964
6918
|
method: "POST",
|
|
6919
|
+
contentType: MARKDOWN_CONTENT_TYPE,
|
|
6965
6920
|
body: markdown,
|
|
6966
6921
|
chainId: config.chainId,
|
|
6967
6922
|
hubAddress: config.hubAddress,
|
|
6968
6923
|
address: account.address,
|
|
6969
|
-
block: await fetchSignableBlock(publicClient),
|
|
6970
6924
|
sign: (typedData) => account.signTypedData(typedData)
|
|
6971
6925
|
});
|
|
6972
6926
|
await postText(requestUrl, markdown, MARKDOWN_CONTENT_TYPE, authorization);
|
|
@@ -7121,14 +7075,14 @@ var NETWORKS = [
|
|
|
7121
7075
|
{
|
|
7122
7076
|
name: "base-sepolia",
|
|
7123
7077
|
chainId: baseSepolia3.id,
|
|
7124
|
-
label: "Base Sepolia
|
|
7078
|
+
label: "Base Sepolia, test USDC"
|
|
7125
7079
|
},
|
|
7126
7080
|
{ name: "local", chainId: foundry3.id, label: "a local Anvil stack" }
|
|
7127
7081
|
];
|
|
7128
7082
|
var NETWORK_CHAIN_IDS = Object.fromEntries(
|
|
7129
7083
|
NETWORKS.map(({ name, chainId }) => [name, chainId])
|
|
7130
7084
|
);
|
|
7131
|
-
var
|
|
7085
|
+
var TESTNET_NETWORK = NETWORKS.find(
|
|
7132
7086
|
({ chainId }) => chainId === baseSepolia3.id
|
|
7133
7087
|
);
|
|
7134
7088
|
var NETWORK_NAMES_HINT = NETWORKS.map(
|
|
@@ -7138,15 +7092,15 @@ function describeChain(chainId) {
|
|
|
7138
7092
|
const network = NETWORKS.find((candidate) => candidate.chainId === chainId);
|
|
7139
7093
|
return network ? `${network.name} (${network.label})` : `chain ${chainId}`;
|
|
7140
7094
|
}
|
|
7141
|
-
var
|
|
7095
|
+
var TESTNET_HINT = `add ${NETWORK_FLAG} ${TESTNET_NETWORK.name} or set ELGORA_CHAIN_ID=${TESTNET_NETWORK.chainId}`;
|
|
7142
7096
|
var DEFAULT_NETWORK_HELP_LINES = [
|
|
7143
7097
|
`Default: ${describeChain(DEFAULT_CHAIN_ID)}.`,
|
|
7144
|
-
`
|
|
7145
|
-
` ${
|
|
7098
|
+
`Testnet: ${describeChain(TESTNET_NETWORK.chainId)};`,
|
|
7099
|
+
` ${TESTNET_HINT}.`
|
|
7146
7100
|
];
|
|
7147
7101
|
function defaultNetworkNotice(env) {
|
|
7148
7102
|
if (env.ELGORA_CHAIN_ID?.trim()) return void 0;
|
|
7149
|
-
return `elgora-cli: using the default network, ${describeChain(DEFAULT_CHAIN_ID)}. For
|
|
7103
|
+
return `elgora-cli: using the default network, ${describeChain(DEFAULT_CHAIN_ID)}. For testnet, ${TESTNET_HINT}.`;
|
|
7150
7104
|
}
|
|
7151
7105
|
function applyNetworkFlag(env, argv) {
|
|
7152
7106
|
const present = argv.some(
|
|
@@ -7173,7 +7127,7 @@ function resolveChainId(selector) {
|
|
|
7173
7127
|
}
|
|
7174
7128
|
|
|
7175
7129
|
// src/version.ts
|
|
7176
|
-
var CLI_VERSION = true ? "
|
|
7130
|
+
var CLI_VERSION = true ? "10.1.0" : "0.0.0-dev";
|
|
7177
7131
|
var CLI_NODE_ENGINES = true ? ">=24 <25" : ">=24 <25";
|
|
7178
7132
|
|
|
7179
7133
|
// src/node-engines.ts
|
|
@@ -7240,24 +7194,51 @@ function compareVersions(left, right) {
|
|
|
7240
7194
|
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
7241
7195
|
import path2 from "path";
|
|
7242
7196
|
import { privateKeyToAccount as privateKeyToAccount7 } from "viem/accounts";
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
const
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
);
|
|
7252
|
-
const
|
|
7253
|
-
|
|
7254
|
-
if (!posterPrivateKey || !isHexBytes32(posterPrivateKey)) {
|
|
7197
|
+
|
|
7198
|
+
// src/poster-request.ts
|
|
7199
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
7200
|
+
import { text as readStdinText3 } from "stream/consumers";
|
|
7201
|
+
function loadPosterConfig(env, apiBaseUrlOverride) {
|
|
7202
|
+
const defaults = withDeploymentDefaults(env);
|
|
7203
|
+
const clientConfig = loadClientDeploymentConfig(defaults, apiBaseUrlOverride);
|
|
7204
|
+
const rpcUrl = defaults.ELGORA_RPC_URL?.trim();
|
|
7205
|
+
if (!rpcUrl) throw new Error("ELGORA_RPC_URL is required");
|
|
7206
|
+
const privateKey = env.ELGORA_POSTER_PRIVATE_KEY?.trim();
|
|
7207
|
+
if (!privateKey || !isHexBytes32(privateKey)) {
|
|
7255
7208
|
throw new Error(
|
|
7256
7209
|
"ELGORA_POSTER_PRIVATE_KEY must be a 32-byte hex private key"
|
|
7257
7210
|
);
|
|
7258
7211
|
}
|
|
7259
|
-
|
|
7260
|
-
|
|
7212
|
+
return {
|
|
7213
|
+
...clientConfig,
|
|
7214
|
+
rpcUrl,
|
|
7215
|
+
posterPrivateKey: privateKey
|
|
7216
|
+
};
|
|
7217
|
+
}
|
|
7218
|
+
async function readBountyChallengeMarkdown2(path5) {
|
|
7219
|
+
return path5 === "-" ? readStdinText3(process.stdin) : readFile4(path5, "utf8");
|
|
7220
|
+
}
|
|
7221
|
+
async function signPosterRequest(input) {
|
|
7222
|
+
return authorizeRequest({
|
|
7223
|
+
requestUrl: input.requestUrl.toString(),
|
|
7224
|
+
method: "POST",
|
|
7225
|
+
contentType: "text/markdown",
|
|
7226
|
+
body: input.markdown,
|
|
7227
|
+
chainId: input.config.chainId,
|
|
7228
|
+
hubAddress: input.config.hubAddress,
|
|
7229
|
+
address: input.account.address,
|
|
7230
|
+
sign: (typedData) => input.account.signTypedData(typedData)
|
|
7231
|
+
});
|
|
7232
|
+
}
|
|
7233
|
+
|
|
7234
|
+
// src/poster-open-winning-submission.ts
|
|
7235
|
+
var DEFAULT_OUTPUT_ROOT2 = "./winning-submission";
|
|
7236
|
+
async function main8(env = process.env, argv = process.argv.slice(2)) {
|
|
7237
|
+
const { apiBaseUrl: apiBaseUrlOverride, argv: remainingArgv } = extractApiBaseUrlFlag(argv);
|
|
7238
|
+
const args = readPosterOpenWinningSubmissionArgs(remainingArgv);
|
|
7239
|
+
const config = loadPosterConfig(env, apiBaseUrlOverride);
|
|
7240
|
+
const account = privateKeyToAccount7(config.posterPrivateKey);
|
|
7241
|
+
const publicClient = createChainPublicClient(config.chainId, config.rpcUrl);
|
|
7261
7242
|
await assertHubDeployment(publicClient, config.chainId, config.hubAddress);
|
|
7262
7243
|
const ephemeral = await generateX25519KeyPair();
|
|
7263
7244
|
const retrieveUrl = new URL(
|
|
@@ -7267,14 +7248,14 @@ async function main8(env = process.env, argv = process.argv.slice(2)) {
|
|
|
7267
7248
|
const retrieveBody = JSON.stringify({
|
|
7268
7249
|
poster_ephemeral_public_key: ephemeral.public_key
|
|
7269
7250
|
});
|
|
7270
|
-
const retrieveAuthorization = await
|
|
7251
|
+
const retrieveAuthorization = await authorizeRequest({
|
|
7271
7252
|
requestUrl: retrieveUrl.toString(),
|
|
7272
7253
|
method: "POST",
|
|
7254
|
+
contentType: "application/json",
|
|
7273
7255
|
body: retrieveBody,
|
|
7274
7256
|
chainId: config.chainId,
|
|
7275
7257
|
hubAddress: config.hubAddress,
|
|
7276
7258
|
address: account.address,
|
|
7277
|
-
block: await fetchSignableBlock(publicClient),
|
|
7278
7259
|
sign: (typedData) => account.signTypedData(typedData)
|
|
7279
7260
|
});
|
|
7280
7261
|
const retrieved = deliveryRetrieveResponseSchema.parse(
|
|
@@ -7297,14 +7278,13 @@ async function main8(env = process.env, argv = process.argv.slice(2)) {
|
|
|
7297
7278
|
});
|
|
7298
7279
|
try {
|
|
7299
7280
|
const contentPathname = `/api/bounties/${args.bountyId}/submissions/${retrieved.submission_commitment}/content`;
|
|
7300
|
-
const contentAuthorization = await
|
|
7281
|
+
const contentAuthorization = await authorizeRequest({
|
|
7301
7282
|
requestUrl: new URL(contentPathname, config.apiBaseUrl).toString(),
|
|
7302
7283
|
method: "GET",
|
|
7303
7284
|
body: "",
|
|
7304
7285
|
chainId: config.chainId,
|
|
7305
7286
|
hubAddress: config.hubAddress,
|
|
7306
7287
|
address: account.address,
|
|
7307
|
-
block: await fetchSignableBlock(publicClient),
|
|
7308
7288
|
sign: (typedData) => account.signTypedData(typedData)
|
|
7309
7289
|
});
|
|
7310
7290
|
const { content_record, ciphertext_download_url } = solverSubmissionContentResponseSchema.parse(
|
|
@@ -7373,80 +7353,18 @@ function readPosterOpenWinningSubmissionArgs(argv) {
|
|
|
7373
7353
|
...outputDir ? { outputDir } : {}
|
|
7374
7354
|
};
|
|
7375
7355
|
}
|
|
7376
|
-
function required3(env, name) {
|
|
7377
|
-
const value = env[name]?.trim();
|
|
7378
|
-
if (!value) throw new Error(`${name} is required`);
|
|
7379
|
-
return value;
|
|
7380
|
-
}
|
|
7381
7356
|
|
|
7382
7357
|
// src/publish-fund.ts
|
|
7383
|
-
import { readFile as readFile5 } from "fs/promises";
|
|
7384
7358
|
import {
|
|
7385
7359
|
decodeFunctionData,
|
|
7386
|
-
|
|
7360
|
+
erc20Abi,
|
|
7387
7361
|
parseEventLogs
|
|
7388
7362
|
} from "viem";
|
|
7389
7363
|
import { privateKeyToAccount as privateKeyToAccount8 } from "viem/accounts";
|
|
7390
|
-
|
|
7391
|
-
// src/poster-request.ts
|
|
7392
|
-
import { readFile as readFile4 } from "fs/promises";
|
|
7393
|
-
import { text as readStdinText3 } from "stream/consumers";
|
|
7394
|
-
function loadPosterConfig(env, apiBaseUrlOverride) {
|
|
7395
|
-
const defaults = withDeploymentDefaults(env);
|
|
7396
|
-
const clientConfig = loadClientDeploymentConfig(defaults, apiBaseUrlOverride);
|
|
7397
|
-
const rpcUrl = defaults.ELGORA_RPC_URL?.trim();
|
|
7398
|
-
if (!rpcUrl) throw new Error("ELGORA_RPC_URL is required");
|
|
7399
|
-
const privateKey = env.ELGORA_POSTER_PRIVATE_KEY?.trim();
|
|
7400
|
-
if (!privateKey || !isHexBytes32(privateKey)) {
|
|
7401
|
-
throw new Error(
|
|
7402
|
-
"ELGORA_POSTER_PRIVATE_KEY must be a 32-byte hex private key"
|
|
7403
|
-
);
|
|
7404
|
-
}
|
|
7405
|
-
return {
|
|
7406
|
-
...clientConfig,
|
|
7407
|
-
rpcUrl,
|
|
7408
|
-
posterPrivateKey: privateKey
|
|
7409
|
-
};
|
|
7410
|
-
}
|
|
7411
|
-
function takeFlag(argv, flag, usage) {
|
|
7412
|
-
const uses = argv.filter(
|
|
7413
|
-
(arg) => arg === flag || arg.startsWith(`${flag}=`)
|
|
7414
|
-
).length;
|
|
7415
|
-
const extracted = extractFlagValue(argv, flag);
|
|
7416
|
-
if (uses > 1 || uses === 1 && (!extracted.value || extracted.value.startsWith("--")))
|
|
7417
|
-
throw new Error(usage);
|
|
7418
|
-
return extracted;
|
|
7419
|
-
}
|
|
7420
|
-
async function readBountyChallengeMarkdown2(path5) {
|
|
7421
|
-
return path5 === "-" ? readStdinText3(process.stdin) : readFile4(path5, "utf8");
|
|
7422
|
-
}
|
|
7423
|
-
async function signPosterRequest(input) {
|
|
7424
|
-
return buildAuthorizationHeader({
|
|
7425
|
-
requestUrl: input.requestUrl.toString(),
|
|
7426
|
-
method: "POST",
|
|
7427
|
-
body: input.markdown,
|
|
7428
|
-
chainId: input.config.chainId,
|
|
7429
|
-
hubAddress: input.config.hubAddress,
|
|
7430
|
-
address: input.account.address,
|
|
7431
|
-
block: await fetchSignableBlock(input.publicClient),
|
|
7432
|
-
sign: (typedData) => input.account.signTypedData(typedData)
|
|
7433
|
-
});
|
|
7434
|
-
}
|
|
7435
|
-
|
|
7436
|
-
// src/publish-fund.ts
|
|
7437
|
-
var PUBLISH_FUND_USAGE = "Usage: elgora-cli poster:publish-fund <bounty_challenge_md_path|-> --signoff <file>";
|
|
7438
|
-
var usdcAbi = parseAbi2([
|
|
7439
|
-
"function approve(address spender,uint256 value) returns (bool)",
|
|
7440
|
-
"function balanceOf(address account) view returns (uint256)"
|
|
7441
|
-
]);
|
|
7364
|
+
var PUBLISH_FUND_USAGE = "Usage: elgora-cli poster:publish-fund <bounty_challenge_md_path|->";
|
|
7442
7365
|
async function main9(env = process.env, argv = process.argv.slice(2)) {
|
|
7443
|
-
const { apiBaseUrl: apiBaseUrlOverride, argv:
|
|
7444
|
-
|
|
7445
|
-
afterApiBaseUrl,
|
|
7446
|
-
"--signoff",
|
|
7447
|
-
PUBLISH_FUND_USAGE
|
|
7448
|
-
);
|
|
7449
|
-
if (!signoffPath || remainingArgv.length !== 1 || !remainingArgv[0])
|
|
7366
|
+
const { apiBaseUrl: apiBaseUrlOverride, argv: remainingArgv } = extractApiBaseUrlFlag(argv);
|
|
7367
|
+
if (remainingArgv.length !== 1 || !remainingArgv[0])
|
|
7450
7368
|
throw new Error(PUBLISH_FUND_USAGE);
|
|
7451
7369
|
const config = loadPosterConfig(env, apiBaseUrlOverride);
|
|
7452
7370
|
const escrowTokenAddress = withDeploymentDefaults(env).ELGORA_ESCROW_TOKEN_ADDRESS?.trim();
|
|
@@ -7462,17 +7380,6 @@ async function main9(env = process.env, argv = process.argv.slice(2)) {
|
|
|
7462
7380
|
const localSpecCommitment = deriveBountyChallengeContentCommitment(
|
|
7463
7381
|
bountyChallengeMarkdown
|
|
7464
7382
|
);
|
|
7465
|
-
const signoff = readinessSignoffSchema.parse(
|
|
7466
|
-
JSON.parse(await readFile5(signoffPath, "utf8"))
|
|
7467
|
-
);
|
|
7468
|
-
if (signoff.spec_commitment.toLowerCase() !== localSpecCommitment) {
|
|
7469
|
-
throw new Error(
|
|
7470
|
-
"Readiness sign-off does not match the exact bounty_challenge.md bytes. Run poster:review again."
|
|
7471
|
-
);
|
|
7472
|
-
}
|
|
7473
|
-
if (signoff.expires_at <= Math.floor(Date.now() / 1e3)) {
|
|
7474
|
-
throw new Error("Readiness sign-off has expired. Run poster:review again.");
|
|
7475
|
-
}
|
|
7476
7383
|
const account = privateKeyToAccount8(config.posterPrivateKey);
|
|
7477
7384
|
const publicClient = createChainPublicClient(config.chainId, config.rpcUrl);
|
|
7478
7385
|
const walletClient = createChainWalletClient(
|
|
@@ -7490,14 +7397,12 @@ async function main9(env = process.env, argv = process.argv.slice(2)) {
|
|
|
7490
7397
|
requestUrl,
|
|
7491
7398
|
markdown: bountyChallengeMarkdown,
|
|
7492
7399
|
config,
|
|
7493
|
-
account
|
|
7494
|
-
publicClient
|
|
7400
|
+
account
|
|
7495
7401
|
});
|
|
7496
7402
|
const prepared = await requestPreparePublication({
|
|
7497
7403
|
requestUrl: requestUrl.toString(),
|
|
7498
7404
|
markdown: bountyChallengeMarkdown,
|
|
7499
|
-
authorization
|
|
7500
|
-
signoff: encodeReadinessSignoffHeader(signoff)
|
|
7405
|
+
authorization
|
|
7501
7406
|
});
|
|
7502
7407
|
if (prepared.content_record.spec_commitment !== localSpecCommitment) {
|
|
7503
7408
|
throw new Error(
|
|
@@ -7527,7 +7432,7 @@ async function main9(env = process.env, argv = process.argv.slice(2)) {
|
|
|
7527
7432
|
publicClient.getBalance({ address: account.address }),
|
|
7528
7433
|
publicClient.readContract({
|
|
7529
7434
|
address: tokenAddress,
|
|
7530
|
-
abi:
|
|
7435
|
+
abi: erc20Abi,
|
|
7531
7436
|
functionName: "balanceOf",
|
|
7532
7437
|
args: [account.address]
|
|
7533
7438
|
})
|
|
@@ -7564,7 +7469,7 @@ async function main9(env = process.env, argv = process.argv.slice(2)) {
|
|
|
7564
7469
|
} else {
|
|
7565
7470
|
const approveHash = await walletClient.writeContract({
|
|
7566
7471
|
address: tokenAddress,
|
|
7567
|
-
abi:
|
|
7472
|
+
abi: erc20Abi,
|
|
7568
7473
|
functionName: "approve",
|
|
7569
7474
|
args: [config.hubAddress, escrowAmount]
|
|
7570
7475
|
});
|
|
@@ -7637,40 +7542,39 @@ async function requestPreparePublication(input) {
|
|
|
7637
7542
|
new URL(input.requestUrl),
|
|
7638
7543
|
input.markdown,
|
|
7639
7544
|
"text/markdown",
|
|
7640
|
-
input.authorization
|
|
7641
|
-
{ [ELGORA_READINESS_SIGNOFF_HEADER]: input.signoff }
|
|
7545
|
+
input.authorization
|
|
7642
7546
|
);
|
|
7643
7547
|
return bountyPublicationResponseSchema.parse(body);
|
|
7644
7548
|
}
|
|
7645
7549
|
|
|
7646
7550
|
// src/required-env.ts
|
|
7647
|
-
function missingRequiredEnv(
|
|
7648
|
-
return
|
|
7551
|
+
function missingRequiredEnv(required3, env) {
|
|
7552
|
+
return required3.filter((envName) => !env[envName]?.trim());
|
|
7649
7553
|
}
|
|
7650
7554
|
|
|
7651
7555
|
// src/review.ts
|
|
7652
|
-
import { writeFile as writeFile3 } from "fs/promises";
|
|
7653
|
-
import { resolve } from "path";
|
|
7654
7556
|
import { privateKeyToAccount as privateKeyToAccount9 } from "viem/accounts";
|
|
7655
|
-
var USAGE2 = "Usage: elgora-cli poster:review <path|-> [--previous <commitment>]
|
|
7557
|
+
var USAGE2 = "Usage: elgora-cli poster:review <path|-> [--previous <commitment>]";
|
|
7558
|
+
function takeFlag(argv, flag, usage) {
|
|
7559
|
+
const uses = argv.filter(
|
|
7560
|
+
(arg) => arg === flag || arg.startsWith(`${flag}=`)
|
|
7561
|
+
).length;
|
|
7562
|
+
const extracted = extractFlagValue(argv, flag);
|
|
7563
|
+
if (uses > 1 || uses === 1 && (!extracted.value || extracted.value.startsWith("--")))
|
|
7564
|
+
throw new Error(usage);
|
|
7565
|
+
return extracted;
|
|
7566
|
+
}
|
|
7656
7567
|
async function main10(env = process.env, argv = process.argv.slice(2)) {
|
|
7657
7568
|
const { apiBaseUrl, argv: args } = extractApiBaseUrlFlag(argv);
|
|
7658
|
-
const { value: previous, argv:
|
|
7569
|
+
const { value: previous, argv: paths } = takeFlag(
|
|
7659
7570
|
args,
|
|
7660
7571
|
"--previous",
|
|
7661
7572
|
"--previous must be one bytes32 page commitment"
|
|
7662
7573
|
);
|
|
7663
7574
|
if (previous && !isHexBytes32(previous))
|
|
7664
7575
|
throw new Error("--previous must be one bytes32 page commitment");
|
|
7665
|
-
const { value: signoffOut, argv: paths } = takeFlag(
|
|
7666
|
-
afterPrevious,
|
|
7667
|
-
"--signoff-out",
|
|
7668
|
-
USAGE2
|
|
7669
|
-
);
|
|
7670
7576
|
if (paths.length !== 1 || !paths[0] || paths[0].startsWith("--"))
|
|
7671
7577
|
throw new Error(USAGE2);
|
|
7672
|
-
if (signoffOut && paths[0] !== "-" && resolve(signoffOut) === resolve(paths[0]))
|
|
7673
|
-
throw new Error("--signoff-out must not overwrite the bounty draft");
|
|
7674
7578
|
const config = loadPosterConfig(env, apiBaseUrl);
|
|
7675
7579
|
const markdown = await readBountyChallengeMarkdown2(paths[0]);
|
|
7676
7580
|
const commitment = deriveBountyChallengeContentCommitment(markdown);
|
|
@@ -7691,8 +7595,7 @@ async function main10(env = process.env, argv = process.argv.slice(2)) {
|
|
|
7691
7595
|
requestUrl,
|
|
7692
7596
|
markdown,
|
|
7693
7597
|
config,
|
|
7694
|
-
account
|
|
7695
|
-
publicClient
|
|
7598
|
+
account
|
|
7696
7599
|
});
|
|
7697
7600
|
let response;
|
|
7698
7601
|
try {
|
|
@@ -7719,18 +7622,12 @@ async function main10(env = process.env, argv = process.argv.slice(2)) {
|
|
|
7719
7622
|
"Elgora API returned a review for different bounty_challenge.md bytes"
|
|
7720
7623
|
);
|
|
7721
7624
|
}
|
|
7722
|
-
if (signoffOut)
|
|
7723
|
-
await writeFile3(
|
|
7724
|
-
signoffOut,
|
|
7725
|
-
`${JSON.stringify(response.readiness.signoff, null, 2)}
|
|
7726
|
-
`
|
|
7727
|
-
);
|
|
7728
7625
|
console.log(
|
|
7729
7626
|
JSON.stringify({
|
|
7730
7627
|
event: "review.ready",
|
|
7731
7628
|
spec_commitment: commitment,
|
|
7732
|
-
|
|
7733
|
-
warnings: response.readiness.warnings
|
|
7629
|
+
approved_until: response.readiness.approved_until,
|
|
7630
|
+
warnings: response.readiness.warnings,
|
|
7734
7631
|
prior_issues_resolved: response.readiness.prior_issues_resolved,
|
|
7735
7632
|
prior_issues_open: response.readiness.prior_issues_open
|
|
7736
7633
|
})
|
|
@@ -7960,8 +7857,8 @@ function usageError3() {
|
|
|
7960
7857
|
}
|
|
7961
7858
|
|
|
7962
7859
|
// src/roster-verify-guardian-proof.ts
|
|
7963
|
-
import { readFile as
|
|
7964
|
-
import { isAddress as isAddress6, isHex as
|
|
7860
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
7861
|
+
import { isAddress as isAddress6, isHex as isHex5, recoverMessageAddress } from "viem";
|
|
7965
7862
|
async function main13(_env = process.env, argv = process.argv.slice(2)) {
|
|
7966
7863
|
const [preparedPath, responsePath] = argv;
|
|
7967
7864
|
if (!preparedPath || !responsePath) {
|
|
@@ -7969,8 +7866,8 @@ async function main13(_env = process.env, argv = process.argv.slice(2)) {
|
|
|
7969
7866
|
"Usage: elgora-cli roster:verify-guardian-proof <prepared_json_path> <response_json_path>"
|
|
7970
7867
|
);
|
|
7971
7868
|
}
|
|
7972
|
-
const prepared = parsePrepared(await
|
|
7973
|
-
const response = parseResponse(await
|
|
7869
|
+
const prepared = parsePrepared(await readFile5(preparedPath, "utf8"));
|
|
7870
|
+
const response = parseResponse(await readFile5(responsePath, "utf8"));
|
|
7974
7871
|
const fixture = base64UrlToBytes(prepared.fixture);
|
|
7975
7872
|
const signedPayload = buildGuardianRosterKeyProofSignedPayload(
|
|
7976
7873
|
prepared.message,
|
|
@@ -8034,7 +7931,7 @@ function parseResponse(text) {
|
|
|
8034
7931
|
}
|
|
8035
7932
|
const guardianAccount = get(parsed, "guardian_account");
|
|
8036
7933
|
const signature = get(parsed, "signature");
|
|
8037
|
-
if (typeof guardianAccount !== "string" || !isAddress6(guardianAccount) || typeof signature !== "string" || !
|
|
7934
|
+
if (typeof guardianAccount !== "string" || !isAddress6(guardianAccount) || typeof signature !== "string" || !isHex5(signature) || signature.length !== 132) {
|
|
8038
7935
|
throw new Error(
|
|
8039
7936
|
"Guardian response JSON must be the unmodified stdout of guardian:prove-roster-key"
|
|
8040
7937
|
);
|
|
@@ -8052,7 +7949,7 @@ function get(value, key) {
|
|
|
8052
7949
|
}
|
|
8053
7950
|
|
|
8054
7951
|
// src/spec-commitment.ts
|
|
8055
|
-
import { readFile as
|
|
7952
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
8056
7953
|
import { text as readStdinText4 } from "stream/consumers";
|
|
8057
7954
|
var SPEC_COMMITMENT_USAGE = "Usage: elgora-cli spec-commitment <bounty_challenge_md_path>\n or: elgora-cli spec-commitment -";
|
|
8058
7955
|
async function main14(_env = process.env, argv = process.argv.slice(2)) {
|
|
@@ -8074,23 +7971,23 @@ async function readBountyChallengeMarkdown3(argv) {
|
|
|
8074
7971
|
if (path5 === "-") {
|
|
8075
7972
|
return readStdinText4(process.stdin);
|
|
8076
7973
|
}
|
|
8077
|
-
return
|
|
7974
|
+
return readFile6(path5, "utf8");
|
|
8078
7975
|
}
|
|
8079
7976
|
|
|
8080
7977
|
// src/submit.ts
|
|
8081
|
-
import { readdir, readFile as
|
|
7978
|
+
import { readdir, readFile as readFile7, stat } from "fs/promises";
|
|
8082
7979
|
import path3 from "path";
|
|
8083
7980
|
import { createInterface } from "readline";
|
|
8084
|
-
import { isAddress as isAddress7 } from "viem";
|
|
7981
|
+
import { getTypesForEIP712Domain, isAddress as isAddress7, stringify } from "viem";
|
|
8085
7982
|
import { privateKeyToAccount as privateKeyToAccount11 } from "viem/accounts";
|
|
8086
7983
|
|
|
8087
7984
|
// src/external-api-approval-signer.ts
|
|
8088
|
-
import { isHex as
|
|
7985
|
+
import { isHex as isHex6 } from "viem";
|
|
8089
7986
|
function createExternalApiApprovalSigner(input) {
|
|
8090
7987
|
return async (typedData) => {
|
|
8091
7988
|
input.writePrompt(input.renderPrompt(typedData));
|
|
8092
7989
|
const signature = (await input.readSignature())?.trim();
|
|
8093
|
-
if (!signature || signature === "0x" || !
|
|
7990
|
+
if (!signature || signature === "0x" || !isHex6(signature)) {
|
|
8094
7991
|
throw new Error(
|
|
8095
7992
|
"External signer must return one non-empty 0x-prefixed hex signature line on stdin"
|
|
8096
7993
|
);
|
|
@@ -8161,19 +8058,16 @@ async function main15(env = process.env, argv = process.argv.slice(2)) {
|
|
|
8161
8058
|
return next.done ? void 0 : next.value;
|
|
8162
8059
|
}
|
|
8163
8060
|
});
|
|
8164
|
-
const
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
sign: signApproval
|
|
8175
|
-
});
|
|
8176
|
-
};
|
|
8061
|
+
const authorizeSubmitRequest = (requestUrl, body) => authorizeRequest({
|
|
8062
|
+
requestUrl: requestUrl.toString(),
|
|
8063
|
+
method: "POST",
|
|
8064
|
+
body,
|
|
8065
|
+
contentType: "application/json",
|
|
8066
|
+
chainId: config.chainId,
|
|
8067
|
+
hubAddress: config.hubAddress,
|
|
8068
|
+
address: solver,
|
|
8069
|
+
sign: signApproval
|
|
8070
|
+
});
|
|
8177
8071
|
const rosterResponse = await requestBountyGuardianRoster({
|
|
8178
8072
|
apiBaseUrl: config.apiBaseUrl,
|
|
8179
8073
|
bountyId: bountyIdText
|
|
@@ -8220,7 +8114,7 @@ async function main15(env = process.env, argv = process.argv.slice(2)) {
|
|
|
8220
8114
|
solver,
|
|
8221
8115
|
ciphertextSha256: envelope.ciphertext_sha256,
|
|
8222
8116
|
ciphertextByteLength: ciphertext.byteLength,
|
|
8223
|
-
authorizeRequest
|
|
8117
|
+
authorizeRequest: authorizeSubmitRequest
|
|
8224
8118
|
});
|
|
8225
8119
|
if (uploadUrl.locator !== envelope.ciphertext_locator) {
|
|
8226
8120
|
throw new Error(
|
|
@@ -8241,7 +8135,7 @@ async function main15(env = process.env, argv = process.argv.slice(2)) {
|
|
|
8241
8135
|
bountyId: bountyIdText,
|
|
8242
8136
|
solver,
|
|
8243
8137
|
envelope,
|
|
8244
|
-
authorizeRequest
|
|
8138
|
+
authorizeRequest: authorizeSubmitRequest
|
|
8245
8139
|
});
|
|
8246
8140
|
} finally {
|
|
8247
8141
|
externalApprovalInput?.close();
|
|
@@ -8340,14 +8234,19 @@ async function main15(env = process.env, argv = process.argv.slice(2)) {
|
|
|
8340
8234
|
}
|
|
8341
8235
|
function createExternalApprovalSigner(input) {
|
|
8342
8236
|
return createExternalApiApprovalSigner({
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8237
|
+
// The eth_signTypedData_v4 shape: its types carry EIP712Domain, which
|
|
8238
|
+
// MetaMask-style signers need to hash the domain. The signed hash is the same.
|
|
8239
|
+
renderPrompt: (typedData) => stringify({
|
|
8240
|
+
event: "submit.approval_required",
|
|
8241
|
+
solver: input.solver.toLowerCase(),
|
|
8242
|
+
typed_data: {
|
|
8243
|
+
...typedData,
|
|
8244
|
+
types: {
|
|
8245
|
+
EIP712Domain: getTypesForEIP712Domain({ domain: typedData.domain }),
|
|
8246
|
+
...typedData.types
|
|
8247
|
+
}
|
|
8248
|
+
}
|
|
8249
|
+
}),
|
|
8351
8250
|
writePrompt: input.writePrompt,
|
|
8352
8251
|
readSignature: input.readSignature
|
|
8353
8252
|
});
|
|
@@ -8485,7 +8384,7 @@ function extractSolverAddressFlag(argv) {
|
|
|
8485
8384
|
for (let i = 0; i < argv.length; i++) {
|
|
8486
8385
|
const arg = argv[i];
|
|
8487
8386
|
if (arg === SOLVER_ADDRESS_FLAG) {
|
|
8488
|
-
solverAddress = argv[i + 1];
|
|
8387
|
+
solverAddress = argv[i + 1] ?? "";
|
|
8489
8388
|
i++;
|
|
8490
8389
|
continue;
|
|
8491
8390
|
}
|
|
@@ -8530,7 +8429,7 @@ async function readArtifactDirectory(artifactDir) {
|
|
|
8530
8429
|
}
|
|
8531
8430
|
return Promise.all(
|
|
8532
8431
|
entries.map(async (entry) => {
|
|
8533
|
-
const bytes = await
|
|
8432
|
+
const bytes = await readFile7(path3.join(artifactDir, entry.name));
|
|
8534
8433
|
return {
|
|
8535
8434
|
name: entry.name,
|
|
8536
8435
|
media_type: guessMediaType(entry.name),
|
|
@@ -8599,7 +8498,7 @@ async function requestPrepareSubmission(input) {
|
|
|
8599
8498
|
})
|
|
8600
8499
|
);
|
|
8601
8500
|
}
|
|
8602
|
-
await new Promise((
|
|
8501
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
8603
8502
|
}
|
|
8604
8503
|
}
|
|
8605
8504
|
}
|
|
@@ -8807,9 +8706,9 @@ var COMMAND_HELP = {
|
|
|
8807
8706
|
apiBaseUrlFlag: true
|
|
8808
8707
|
},
|
|
8809
8708
|
"poster:review": {
|
|
8810
|
-
usage: "elgora-cli poster:review <path|-> [--previous <commitment>]
|
|
8811
|
-
title: "Review a bounty page
|
|
8812
|
-
description: "
|
|
8709
|
+
usage: "elgora-cli poster:review <path|-> [--previous <commitment>]",
|
|
8710
|
+
title: "Review a bounty page before publishing it.",
|
|
8711
|
+
description: "Sign and send the exact Markdown for a readiness review. Ready prints\n review.ready; Elgora keeps the approval for these exact bytes.\n Not-ready prints all issues and exits 2; other failures exit 1.\n --previous sends the previous page commitment with the signed request.",
|
|
8813
8712
|
required: ["ELGORA_POSTER_PRIVATE_KEY"],
|
|
8814
8713
|
defaulted: [
|
|
8815
8714
|
"ELGORA_CHAIN_ID",
|
|
@@ -8820,9 +8719,9 @@ var COMMAND_HELP = {
|
|
|
8820
8719
|
apiBaseUrlFlag: true
|
|
8821
8720
|
},
|
|
8822
8721
|
"poster:publish-fund": {
|
|
8823
|
-
usage: "elgora-cli poster:publish-fund <bounty_challenge_md_path|->
|
|
8722
|
+
usage: "elgora-cli poster:publish-fund <bounty_challenge_md_path|->",
|
|
8824
8723
|
title: "Publish an approved challenge and fund its bounty.",
|
|
8825
|
-
description: "Read the exact approved bounty_challenge.md bytes
|
|
8724
|
+
description: "Read the exact approved bounty_challenge.md bytes. Publishing reuses\n their saved approval without another AI review, or reviews them first.\n Eligible wallets sign a USDC authorization, then send\n one funding transaction and pay gas. No new allowance is required;\n this authorization path does not revoke existing allowances.\n Unsupported accounts use approval then creation. Pass '-' to read stdin.",
|
|
8826
8725
|
required: ["ELGORA_POSTER_PRIVATE_KEY"],
|
|
8827
8726
|
defaulted: [
|
|
8828
8727
|
"ELGORA_CHAIN_ID",
|