@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.
Files changed (3) hide show
  1. package/README.md +16 -12
  2. package/dist/cli.js +422 -523
  3. 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 isHex3 } from "viem";
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
- // ../../packages/core/src/auth/eip712.ts
400
- var API_REQUEST_APPROVAL_PRIMARY_TYPE = "ApiRequestApproval";
401
- var API_REQUEST_APPROVAL_TYPES = {
402
- ApiRequestApproval: [
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
- reviewer_hash: bytes32Schema,
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: z3.string().datetime({ offset: true })
399
+ created_at: z2.string().datetime({ offset: true })
468
400
  }).strict();
469
- var bountyPublicationResponseSchema = z3.object({
401
+ var bountyPublicationResponseSchema = z2.object({
470
402
  content_record: bountyChallengeContentRecordSchema,
471
- create_bounty_transaction: z3.object({
472
- chain_id: z3.number().int().positive(),
403
+ create_bounty_transaction: z2.object({
404
+ chain_id: z2.number().int().positive(),
473
405
  to: addressSchema,
474
- value: z3.literal("0"),
406
+ value: z2.literal("0"),
475
407
  data: hexBytesSchema,
476
- function_name: z3.literal("create_bounty"),
477
- args: z3.object({
478
- spec_commitment: bytes32Schema2,
479
- escrow_amount: z3.string().refine(isPositiveInteger),
480
- submission_deadline: z3.number().int().positive()
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: z3.object({
415
+ protocol_fee_policy: z2.object({
484
416
  treasury_recipient: addressSchema,
485
- treasury_fee_bps: z3.number().int().min(0).max(1e4),
417
+ treasury_fee_bps: z2.number().int().min(0).max(1e4),
486
418
  guardian_fee_recipient: addressSchema,
487
- guardian_fee_bps: z3.number().int().min(0).max(1e4)
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 = z3.object({
499
- issue_index: z3.number().int().nonnegative(),
500
- message: z3.string().trim().min(1).max(1500)
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: z3.enum(["resolved", "open"])
435
+ status: z2.enum(["resolved", "open"])
504
436
  }).strict();
505
- var readinessFindingSchema = z3.object({
506
- path: z3.string().trim().min(1).max(120),
507
- message: z3.string().trim().min(1).max(1500),
508
- code: z3.string().min(1).optional(),
509
- anchor: z3.string().trim().min(1).max(120).optional(),
510
- hazard: z3.boolean().optional()
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 = z3.object({
514
- content_record: bountyChallengeContentRecordSchema,
515
- readiness: z3.object({
516
- decision: z3.literal("ready"),
517
- signoff: readinessSignoffSchema,
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
- // Optional because servers before three-pass review do not send it.
520
- warnings: z3.array(readinessFindingSchema).max(MAX_READINESS_FINDINGS).optional(),
521
- prior_issues_resolved: z3.array(priorIssueSchema),
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 z4 } from "zod";
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 = z4.string().regex(BASE64URL_RE);
649
- var lowerAddressSchema = z4.string().refine(isLowercaseHexAddress);
650
- var bytes32Schema3 = z4.string().refine(isLowercaseBytes32);
651
- var sha256HexSchema = z4.string().refine(isSha256Hex);
652
- var keyIdSchema = z4.string().min(1).max(128).regex(KEY_ID_RE);
653
- var artifactNameSchema = z4.string().max(
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 = z4.string().regex(MEDIA_TYPE_RE);
658
- var bountyIdSchema = z4.string().refine(isBountyId);
659
- var chainIdSchema = z4.number().int().positive().lte(Number.MAX_SAFE_INTEGER);
660
- var privateArtifactContextSchema = z4.strictObject({
661
- type: z4.literal("solver_submission"),
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 = z4.strictObject({
585
+ var guardianRecipientSchema = z3.strictObject({
668
586
  key_id: keyIdSchema,
669
- suite: z4.literal(PRIVATE_ARTIFACT_HPKE_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 = z4.strictObject({
593
+ var guardianRecipientPrivateKeySchema = z3.strictObject({
676
594
  key_id: keyIdSchema,
677
- suite: z4.literal(PRIVATE_ARTIFACT_HPKE_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 = z4.array(guardianRecipientSchema).min(1).superRefine((recipients, ctx) => {
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 = z4.array(guardianRecipientPrivateKeySchema).min(1);
697
- var artifactManifestEntrySchema = z4.strictObject({
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: z4.number().int().nonnegative().lte(Number.MAX_SAFE_INTEGER),
618
+ size_bytes: z3.number().int().nonnegative().lte(Number.MAX_SAFE_INTEGER),
701
619
  sha256: sha256HexSchema
702
620
  });
703
- var privateArtifactPublicManifestSchema = z4.strictObject({
704
- kind: z4.literal(PRIVATE_ARTIFACT_PUBLIC_MANIFEST_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 = z4.strictObject({
711
- kind: z4.literal(PRIVATE_ARTIFACT_ENCRYPTED_BUNDLE_KIND),
628
+ var privateArtifactEncryptedBundleSchema = z3.strictObject({
629
+ kind: z3.literal(PRIVATE_ARTIFACT_ENCRYPTED_BUNDLE_KIND),
712
630
  context: privateArtifactContextSchema,
713
- artifacts: z4.array(encryptedBundleArtifactSchema).min(1).max(
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 = z4.strictObject({
722
- kind: z4.literal(PRIVATE_ARTIFACT_REVEAL_POLICY_KIND),
723
- network: z4.string().min(1),
724
- chain_hash: z4.string().min(1),
725
- round: z4.string().refine(isPositiveInteger),
726
- not_before: z4.number().int().nonnegative().lte(Number.MAX_SAFE_INTEGER)
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 = z4.strictObject({
646
+ var wrappedRecipientKeySchema = z3.strictObject({
729
647
  key_id: keyIdSchema,
730
- suite: z4.literal(PRIVATE_ARTIFACT_HPKE_SUITE),
648
+ suite: z3.literal(PRIVATE_ARTIFACT_HPKE_SUITE),
731
649
  enc: base64UrlSchema,
732
650
  ciphertext: base64UrlSchema
733
651
  });
734
- var wrappedKeyBagSchema = z4.strictObject({
735
- kind: z4.literal(PRIVATE_ARTIFACT_WRAPPED_KEY_BAG_KIND),
736
- keys: z4.array(wrappedRecipientKeySchema).min(1)
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 = z4.strictObject({
739
- kind: z4.literal(PRIVATE_ARTIFACT_ENVELOPE_KIND),
740
- alg: z4.literal(SUBMISSION_ENCRYPTION_TYPE),
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: bytes32Schema3,
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: z4.string().min(1)
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 = z4.strictObject({
731
+ var winningSolutionDeliveryContextSchema = z3.strictObject({
814
732
  chain_id: chainIdSchema,
815
733
  hub_address: lowerAddressSchema,
816
734
  bounty_id: bountyIdSchema,
817
- submission_commitment: bytes32Schema3
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 = z4.strictObject({
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 = z4.array(wrappedRecipientKeySchema).parse(input.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://staging.elgora.ai",
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 z5 } from "zod";
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 as recoverTypedDataAddress2
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 recoverTypedDataAddress2({ ...authorization, signature })).toLowerCase() !== poster.toLowerCase()) {
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 = z5.object({
4428
- ciphertext_sha256: z5.string().refine(isSha256Hex),
4429
- ciphertext_byte_length: z5.number().int().positive().max(MAX_SOLVER_SUBMISSION_CIPHERTEXT_BYTES)
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 z6 } from "zod";
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 = z6.coerce.number().int().positive().refine((chainId) => SUPPORTED_CHAINS[chainId] !== void 0, {
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 = z6.string().refine(isHexAddress, "ELGORA_HUB_ADDRESS must be a 20-byte EVM address").transform((value) => value.toLowerCase());
4459
- var publicDeploymentEnvSchema = z6.object({
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: z6.string().refine(
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: z6.coerce.number().int().nonnegative().default(DEFAULT_TIMELOCK_REVEAL_DELAY_SECONDS),
4480
- ELGORA_RPC_URL: z6.string().min(1, "ELGORA_RPC_URL is required"),
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: z6.string().refine(
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: z6.string().min(1, "ELGORA_DATABASE_URL is required"),
4491
- ELGORA_SUBGRAPH_ENDPOINT: z6.string().min(1, "ELGORA_SUBGRAPH_ENDPOINT is required"),
4492
- ELGORA_ARTIFACT_STORAGE_ENDPOINT: z6.string().min(1, "ELGORA_ARTIFACT_STORAGE_ENDPOINT is required"),
4493
- ELGORA_ARTIFACT_STORAGE_REGION: z6.string().min(1, "ELGORA_ARTIFACT_STORAGE_REGION is required"),
4494
- ELGORA_ARTIFACT_STORAGE_BUCKET: z6.string().min(1, "ELGORA_ARTIFACT_STORAGE_BUCKET is required"),
4495
- ELGORA_ARTIFACT_STORAGE_ACCESS_KEY_ID: z6.string().min(1, "ELGORA_ARTIFACT_STORAGE_ACCESS_KEY_ID is required"),
4496
- ELGORA_ARTIFACT_STORAGE_SECRET_ACCESS_KEY: z6.string().min(1, "ELGORA_ARTIFACT_STORAGE_SECRET_ACCESS_KEY is required"),
4497
- ELGORA_DELIVERY_PUBLIC_KEY: z6.string().min(1, "ELGORA_DELIVERY_PUBLIC_KEY is required"),
4498
- ELGORA_DELIVERY_PRIVATE_KEY: z6.string().min(1, "ELGORA_DELIVERY_PRIVATE_KEY is required")
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: z6.string().trim().toLowerCase().pipe(z6.enum(["true", "false"])).default("true").transform((value) => value === "true"),
4515
- ELGORA_READINESS_TIMEOUT_MS: z6.coerce.number().int().min(1).max(12e4).default(12e4)
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 = z6.object(envShape);
4518
- var bountyPublicationEnvSchema = z6.object(publicationEnvShape);
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 isHex4 } from "viem";
4534
- import { z as z7 } from "zod";
4535
- var hexAddressSchema = z7.string().refine(isHexAddress, "Must be a hex-encoded address");
4536
- var hexBytes32Schema = z7.string().refine(isHexBytes32, "Must be 32-byte hex");
4537
- var hexDataSchema = z7.string().refine((value) => isHex4(value), "Must be hex-encoded calldata");
4538
- var artifactUploadUrlResponseSchema = z7.object({
4539
- locator: z7.string().min(1),
4540
- upload_url: z7.string().min(1),
4541
- method: z7.literal("PUT"),
4542
- expires_at: z7.string().min(1)
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 = z7.object({
4545
- content_record: z7.object({
4546
- content_kind: z7.literal(SOLVER_SUBMISSION_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: z7.number().int().nonnegative(),
4549
- created_at: z7.string().min(1)
4458
+ byte_length: z6.number().int().nonnegative(),
4459
+ created_at: z6.string().min(1)
4550
4460
  }),
4551
- submit_transaction: z7.object({
4552
- chain_id: z7.number().int().positive(),
4461
+ submit_transaction: z6.object({
4462
+ chain_id: z6.number().int().positive(),
4553
4463
  to: hexAddressSchema,
4554
- value: z7.literal("0"),
4464
+ value: z6.literal("0"),
4555
4465
  data: hexDataSchema,
4556
- function_name: z7.literal("submit"),
4557
- args: z7.object({
4558
- bounty_id: z7.string().min(1),
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: z7.literal("0x")
4471
+ extra_data: z6.literal("0x")
4562
4472
  })
4563
4473
  })
4564
4474
  });
4565
- var solverSubmissionContentResponseSchema = z7.object({
4566
- content_record: z7.object({
4567
- bounty_id: z7.string().min(1),
4568
- canonical_json: z7.string().min(1)
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: z7.string().min(1),
4571
- expires_at: z7.string().min(1)
4480
+ ciphertext_download_url: z6.string().min(1),
4481
+ expires_at: z6.string().min(1)
4572
4482
  });
4573
- var bountyGuardianRosterResponseSchema = z7.object({
4574
- bounty: z7.object({
4483
+ var bountyGuardianRosterResponseSchema = z6.object({
4484
+ bounty: z6.object({
4575
4485
  guardian_roster_hash: hexBytes32Schema,
4576
- guardian_roster: z7.array(
4577
- z7.object({
4578
- name: z7.string(),
4486
+ guardian_roster: z6.array(
4487
+ z6.object({
4488
+ name: z6.string(),
4579
4489
  account: hexAddressSchema,
4580
- encryption_public_key: z7.string().min(1)
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 z8 } from "zod";
4588
- var hexAddressSchema2 = z8.string().refine(isHexAddress, "Must be a hex-encoded address").transform((value) => value.toLowerCase());
4589
- var hexBytes32Schema2 = z8.string().refine(isHexBytes32, "Must be 32-byte hex").transform((value) => value.toLowerCase());
4590
- var integerStringSchema = z8.string().regex(/^(0|[1-9][0-9]*)$/);
4591
- var verdictEntrySchema = z8.object({
4592
- name: z8.string().min(1),
4593
- outcome: z8.enum(["awarded", "no_valid_submission"]).nullable(),
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: z8.string().datetime({ offset: true }).nullable(),
4597
- supporting: z8.boolean()
4506
+ committed_at: z7.string().datetime({ offset: true }).nullable(),
4507
+ supporting: z7.boolean()
4598
4508
  }).strict();
4599
- var formattedVerificationRecordSchema = z8.object({
4600
- chain_id: z8.number().int().positive(),
4509
+ var formattedVerificationRecordSchema = z7.object({
4510
+ chain_id: z7.number().int().positive(),
4601
4511
  hub_address: hexAddressSchema2,
4602
4512
  bounty_id: integerStringSchema,
4603
- status: z8.enum(["awarded", "no_valid_submission", "timed_out"]),
4513
+ status: z7.enum(["awarded", "no_valid_submission", "timed_out"]),
4604
4514
  spec_commitment: hexBytes32Schema2,
4605
4515
  winner: hexAddressSchema2.nullable(),
4606
- verdicts: z8.record(z8.string(), verdictEntrySchema),
4607
- settlement: z8.object({
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: z8.object({
4619
- spec_content_byte_length: z8.number().int().positive()
4528
+ content_record: z7.object({
4529
+ spec_content_byte_length: z7.number().int().positive()
4620
4530
  }).strict(),
4621
- verified_at: z8.string().datetime({ offset: true })
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 z9 } from "zod";
4644
- var hexBytes32Schema3 = z9.string().refine(isHexBytes32, "Must be 32-byte hex").refine((value) => value !== ZERO_BYTES32, "Must not be zero").transform((value) => value.toLowerCase());
4645
- var hexAddressSchema3 = z9.string().refine((value) => /^0x[0-9a-fA-F]{40}$/.test(value), "Must be an address").transform((value) => value.toLowerCase());
4646
- var deliveryKeyIdSchema = z9.string().min(1).max(128);
4647
- var winningSolutionWrappedKeySchema = z9.strictObject({
4648
- enc: z9.string().min(1),
4649
- ciphertext: z9.string().min(1)
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 = z9.strictObject({
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 = z9.strictObject({
4657
- bounty_id: z9.string().min(1),
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: z9.string().min(1)
4572
+ created_at: z8.string().min(1)
4663
4573
  });
4664
- var deliveryWrapResponseSchema = z9.strictObject({
4665
- status: z9.literal("stored"),
4574
+ var deliveryWrapResponseSchema = z8.strictObject({
4575
+ status: z8.literal("stored"),
4666
4576
  wrap: deliveryWrapRecordSchema
4667
4577
  });
4668
- var deliveryRetrieveRequestSchema = z9.strictObject({
4578
+ var deliveryRetrieveRequestSchema = z8.strictObject({
4669
4579
  poster_ephemeral_public_key: x25519PublicKeySchema
4670
4580
  });
4671
- var deliveryRetrieveResponseSchema = z9.strictObject({
4581
+ var deliveryRetrieveResponseSchema = z8.strictObject({
4672
4582
  submission_commitment: hexBytes32Schema3,
4673
4583
  wrapped_key: winningSolutionWrappedKeySchema
4674
4584
  });
4675
- var deliveryStatusResponseSchema = z9.strictObject({
4676
- exists: z9.boolean()
4585
+ var deliveryStatusResponseSchema = z8.strictObject({
4586
+ exists: z8.boolean()
4677
4587
  });
4678
- var deliveryKeyConfigResponseSchema = z9.strictObject({
4588
+ var deliveryKeyConfigResponseSchema = z8.strictObject({
4679
4589
  delivery_key_id: deliveryKeyIdSchema,
4680
- public_key: z9.string().min(1)
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 z10 } from "zod";
4595
+ import { z as z9 } from "zod";
4686
4596
  var WRITTEN_VERDICT_FORMAT_VERSION = 0;
4687
4597
  var FRONTMATTER_DELIMITER2 = "---";
4688
- var decimalSchema = z10.string().regex(/^[1-9][0-9]*$/, "Must be a positive integer").transform(Number).refine(Number.isSafeInteger, "Must be a safe integer");
4689
- var bountyIdSchema2 = z10.string().regex(/^(0|[1-9][0-9]*)$/, "Must be a non-negative integer");
4690
- var addressSchema2 = z10.string().refine(isHexAddress, "Must be a hex-encoded address").refine((value) => value === value.toLowerCase(), "Must use lowercase hex").transform((value) => value);
4691
- var bytes32Schema4 = z10.string().refine(isHexBytes32, "Must be 32-byte hex").refine((value) => value === value.toLowerCase(), "Must use lowercase hex").transform((value) => value);
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: z10.literal(WRITTEN_VERDICT_FORMAT_VERSION.toString()).transform(() => WRITTEN_VERDICT_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: z10.string().refine((value) => value.trim().length > 0, "Must not be empty")
4607
+ verdict_body: z9.string().refine((value) => value.trim().length > 0, "Must not be empty")
4698
4608
  };
4699
- var writtenVerdictSchema = z10.discriminatedUnion("outcome", [
4700
- z10.object({
4609
+ var writtenVerdictSchema = z9.discriminatedUnion("outcome", [
4610
+ z9.object({
4701
4611
  ...commonFields,
4702
- outcome: z10.literal("awarded"),
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: bytes32Schema4.refine(
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
- z10.object({
4622
+ z9.object({
4713
4623
  ...commonFields,
4714
- outcome: z10.literal("no_valid_submission"),
4715
- winner: z10.literal(zeroAddress2)
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, headers = {}) {
5104
+ async function postText(url, body, contentType, authorization) {
5219
5105
  const response = await fetch(url, {
5220
5106
  method: "POST",
5221
- headers: { ...headers, "content-type": contentType, authorization },
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 isHex5 } from "viem";
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/readiness-signoff-header.ts
5395
- var ELGORA_READINESS_SIGNOFF_HEADER = "Elgora-Readiness-Signoff";
5396
- function encodeReadinessSignoffHeader(signoff) {
5397
- const bytes = new TextEncoder().encode(
5398
- JSON.stringify(readinessSignoffSchema.parse(signoff))
5399
- );
5400
- return btoa(String.fromCharCode(...bytes));
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 isAddressEqual3,
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 as isAddressEqual2,
5414
- recoverTypedDataAddress as recoverTypedDataAddress3
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 { keccak256 as keccak2566, toBytes as toBytes5 } from "viem";
5353
+ import { z as z10 } from "zod";
5419
5354
  async function buildAuthorizationHeader(params) {
5420
5355
  const url = new URL(params.requestUrl);
5421
- const typedData = buildApiRequestApprovalTypedData({
5422
- chainId: params.chainId,
5423
- hubAddress: params.hubAddress,
5424
- message: {
5356
+ const typedData = typedDataForRequest(
5357
+ {
5425
5358
  endpointId: endpointIdFor({ method: params.method, path: url.pathname }),
5426
- audience: audienceFor(url.host),
5427
- bodyHash: keccak2566(toBytes5(params.body ?? "")),
5428
- query: queryFor(url.search),
5429
- blockNumber: params.block.number,
5430
- blockHash: params.block.hash
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 buildAuthorizationHeader({
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 buildAuthorizationHeader({
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 buildAuthorizationHeader({
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 buildAuthorizationHeader({
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 buildAuthorizationHeader({
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 testnet, Elgora's staging deployment"
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 STAGING_NETWORK = NETWORKS.find(
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 STAGING_HINT = `add ${NETWORK_FLAG} ${STAGING_NETWORK.name} or set ELGORA_CHAIN_ID=${STAGING_NETWORK.chainId}`;
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
- `Staging: ${describeChain(STAGING_NETWORK.chainId)};`,
7145
- ` ${STAGING_HINT}.`
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 staging, ${STAGING_HINT}.`;
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 ? "9.1.0" : "0.0.0-dev";
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
- var DEFAULT_OUTPUT_ROOT2 = "./winning-submission";
7244
- async function main8(env = process.env, argv = process.argv.slice(2)) {
7245
- const { apiBaseUrl: apiBaseUrlOverride, argv: remainingArgv } = extractApiBaseUrlFlag(argv);
7246
- const args = readPosterOpenWinningSubmissionArgs(remainingArgv);
7247
- const envWithDefaults = withDeploymentDefaults(env);
7248
- const config = loadClientDeploymentConfig(
7249
- envWithDefaults,
7250
- apiBaseUrlOverride
7251
- );
7252
- const rpcUrl = required3(envWithDefaults, "ELGORA_RPC_URL");
7253
- const posterPrivateKey = envWithDefaults.ELGORA_POSTER_PRIVATE_KEY?.trim();
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
- const account = privateKeyToAccount7(posterPrivateKey.toLowerCase());
7260
- const publicClient = createChainPublicClient(config.chainId, rpcUrl);
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 buildAuthorizationHeader({
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 buildAuthorizationHeader({
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
- parseAbi as parseAbi2,
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: afterApiBaseUrl } = extractApiBaseUrlFlag(argv);
7444
- const { value: signoffPath, argv: remainingArgv } = takeFlag(
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: usdcAbi,
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: usdcAbi,
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(required4, env) {
7648
- return required4.filter((envName) => !env[envName]?.trim());
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>] [--signoff-out <file>]";
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: afterPrevious } = takeFlag(
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
- signoff: response.readiness.signoff,
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 readFile6 } from "fs/promises";
7964
- import { isAddress as isAddress6, isHex as isHex6, recoverMessageAddress } from "viem";
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 readFile6(preparedPath, "utf8"));
7973
- const response = parseResponse(await readFile6(responsePath, "utf8"));
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" || !isHex6(signature) || signature.length !== 132) {
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 readFile7 } from "fs/promises";
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 readFile7(path5, "utf8");
7974
+ return readFile6(path5, "utf8");
8078
7975
  }
8079
7976
 
8080
7977
  // src/submit.ts
8081
- import { readdir, readFile as readFile8, stat } from "fs/promises";
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 isHex7 } from "viem";
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" || !isHex7(signature)) {
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 authorizeRequest = async (requestUrl, body) => {
8165
- const block = await fetchSignableBlock(publicClient);
8166
- return buildAuthorizationHeader({
8167
- requestUrl: requestUrl.toString(),
8168
- method: "POST",
8169
- body,
8170
- chainId: config.chainId,
8171
- hubAddress: config.hubAddress,
8172
- address: solver,
8173
- block,
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
- renderPrompt: (typedData) => JSON.stringify(
8344
- {
8345
- event: "submit.approval_required",
8346
- solver: input.solver.toLowerCase(),
8347
- typed_data: typedData
8348
- },
8349
- (_key, value) => typeof value === "bigint" ? value.toString() : value
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 readFile8(path3.join(artifactDir, entry.name));
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((resolve2) => setTimeout(resolve2, retryDelay));
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>] [--signoff-out <file>]",
8811
- title: "Review a bounty page and save its readiness certificate.",
8812
- description: "Send the exact Markdown for a signed readiness review. Ready prints\n review.ready; --signoff-out saves the certificate for publication.\n Not-ready prints all issues and exits 2; other failures exit 1.\n --previous sends the previous page commitment with the signed request.",
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|-> --signoff <file>",
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 and its saved certificate.\n Publishing checks the certificate and never runs another AI review.\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.",
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",