@spectratools/assembly-cli 0.12.0 → 0.14.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/dist/cli.js +1404 -788
  2. package/dist/index.js +1404 -788
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -7,9 +7,9 @@ import { fileURLToPath } from "url";
7
7
  import {
8
8
  initTelemetry,
9
9
  shutdownTelemetry,
10
- withCommandSpan
10
+ withCommandSpan as withCommandSpan2
11
11
  } from "@spectratools/cli-shared/telemetry";
12
- import { Cli as Cli6, z as z8 } from "incur";
12
+ import { Cli as Cli7, z as z10 } from "incur";
13
13
 
14
14
  // src/commands/_common.ts
15
15
  import { checksumAddress, weiToEth } from "@spectratools/cli-shared";
@@ -4358,8 +4358,8 @@ var writeOptions = z.object({
4358
4358
  "max-fee": z.string().optional().describe("Max fee per gas override in wei (EIP-1559)"),
4359
4359
  nonce: z.number().optional().describe("Nonce override")
4360
4360
  });
4361
- function resolveAccount(env6) {
4362
- const signer = createPrivateKeySigner(env6.PRIVATE_KEY);
4361
+ function resolveAccount(env7) {
4362
+ const signer = createPrivateKeySigner(env7.PRIVATE_KEY);
4363
4363
  return signer.account;
4364
4364
  }
4365
4365
  function formatTxResult(result) {
@@ -4381,10 +4381,10 @@ function formatTxResult(result) {
4381
4381
  };
4382
4382
  }
4383
4383
  async function assemblyWriteTx(opts) {
4384
- const { env: env6, options, address, abi, functionName, args, value } = opts;
4385
- const account = resolveAccount(env6);
4386
- const publicClient = createAssemblyPublicClient(env6.ABSTRACT_RPC_URL);
4387
- const walletClient = createAssemblyWalletClient(account, env6.ABSTRACT_RPC_URL);
4384
+ const { env: env7, options, address, abi, functionName, args, value } = opts;
4385
+ const account = resolveAccount(env7);
4386
+ const publicClient = createAssemblyPublicClient(env7.ABSTRACT_RPC_URL);
4387
+ const walletClient = createAssemblyWalletClient(account, env7.ABSTRACT_RPC_URL);
4388
4388
  const result = await executeTx({
4389
4389
  publicClient,
4390
4390
  walletClient,
@@ -4459,9 +4459,9 @@ council.command("seats", {
4459
4459
  args: [id]
4460
4460
  }))
4461
4461
  }) : [];
4462
- const seats = seatTuples.map(decodeSeat);
4462
+ const seats2 = seatTuples.map(decodeSeat);
4463
4463
  return c.ok(
4464
- seats.map((seat, idx) => ({
4464
+ seats2.map((seat, idx) => ({
4465
4465
  id: idx,
4466
4466
  owner: toChecksum(seat.owner),
4467
4467
  startAt: timeValue(seat.startAt, c.format),
@@ -4546,10 +4546,10 @@ council.command("members", {
4546
4546
  args: [id]
4547
4547
  }))
4548
4548
  }) : [];
4549
- const seats = seatTuples.map(decodeSeat);
4549
+ const seats2 = seatTuples.map(decodeSeat);
4550
4550
  const activeOwners = [
4551
4551
  ...new Set(
4552
- seats.filter((x) => !x.forfeited && asNum(x.endAt) > Math.floor(Date.now() / 1e3)).map((x) => x.owner)
4552
+ seats2.filter((x) => !x.forfeited && asNum(x.endAt) > Math.floor(Date.now() / 1e3)).map((x) => x.owner)
4553
4553
  )
4554
4554
  ];
4555
4555
  const powers = activeOwners.length ? await client.multicall({
@@ -5246,9 +5246,9 @@ council.command("withdraw-refund", {
5246
5246
  }
5247
5247
  });
5248
5248
 
5249
- // src/commands/forum.ts
5250
- import { TxError } from "@spectratools/tx-shared";
5251
- import { Cli as Cli2, z as z3 } from "incur";
5249
+ // src/commands/digest.ts
5250
+ import { withCommandSpan } from "@spectratools/cli-shared/telemetry";
5251
+ import { z as z4 } from "incur";
5252
5252
 
5253
5253
  // src/services/forum.ts
5254
5254
  function decodeThread(value) {
@@ -5376,51 +5376,912 @@ async function fetchForumStats(client) {
5376
5376
  address: ABSTRACT_MAINNET_ADDRESSES.forum,
5377
5377
  functionName: "petitionCount"
5378
5378
  }),
5379
- client.readContract({
5380
- abi: forumAbi,
5381
- address: ABSTRACT_MAINNET_ADDRESSES.forum,
5382
- functionName: "petitionThresholdBps"
5383
- })
5384
- ]);
5385
- return {
5386
- threadCount: asNum(threadCount),
5387
- commentCount: asNum(commentCount),
5388
- petitionCount: asNum(petitionCount),
5389
- petitionThresholdBps: asNum(petitionThresholdBps)
5390
- };
5379
+ client.readContract({
5380
+ abi: forumAbi,
5381
+ address: ABSTRACT_MAINNET_ADDRESSES.forum,
5382
+ functionName: "petitionThresholdBps"
5383
+ })
5384
+ ]);
5385
+ return {
5386
+ threadCount: asNum(threadCount),
5387
+ commentCount: asNum(commentCount),
5388
+ petitionCount: asNum(petitionCount),
5389
+ petitionThresholdBps: asNum(petitionThresholdBps)
5390
+ };
5391
+ }
5392
+ async function fetchHasSignedBatch(client, address, petitionIds) {
5393
+ if (petitionIds.length === 0) return /* @__PURE__ */ new Map();
5394
+ const results = await client.multicall({
5395
+ allowFailure: false,
5396
+ contracts: petitionIds.map((id) => ({
5397
+ abi: forumAbi,
5398
+ address: ABSTRACT_MAINNET_ADDRESSES.forum,
5399
+ functionName: "hasSignedPetition",
5400
+ args: [BigInt(id), address]
5401
+ }))
5402
+ });
5403
+ const map = /* @__PURE__ */ new Map();
5404
+ for (let i = 0; i < petitionIds.length; i++) {
5405
+ map.set(petitionIds[i], results[i]);
5406
+ }
5407
+ return map;
5408
+ }
5409
+
5410
+ // src/services/governance.ts
5411
+ var proposalStatusLabels = {
5412
+ 0: "pending",
5413
+ 1: "active",
5414
+ 2: "passed",
5415
+ 3: "executed",
5416
+ 4: "defeated",
5417
+ 5: "cancelled"
5418
+ };
5419
+ function proposalStatus(status) {
5420
+ const statusCode = asNum(status);
5421
+ return {
5422
+ status: proposalStatusLabels[statusCode] ?? `unknown-${statusCode}`,
5423
+ statusCode
5424
+ };
5425
+ }
5426
+ function decodeProposal(value) {
5427
+ const [
5428
+ kind,
5429
+ configRiskTier,
5430
+ origin,
5431
+ status,
5432
+ proposer,
5433
+ threadId,
5434
+ petitionId,
5435
+ createdAt,
5436
+ deliberationEndsAt,
5437
+ voteStartAt,
5438
+ voteEndAt,
5439
+ timelockEndsAt,
5440
+ activeSeatsSnapshot,
5441
+ forVotes,
5442
+ againstVotes,
5443
+ abstainVotes,
5444
+ amount,
5445
+ snapshotAssetBalance,
5446
+ transferIntent,
5447
+ intentDeadline,
5448
+ intentMaxRiskTier,
5449
+ title,
5450
+ description
5451
+ ] = value;
5452
+ return {
5453
+ kind,
5454
+ configRiskTier,
5455
+ origin,
5456
+ status,
5457
+ proposer: toChecksum(proposer),
5458
+ threadId,
5459
+ petitionId,
5460
+ createdAt,
5461
+ deliberationEndsAt,
5462
+ voteStartAt,
5463
+ voteEndAt,
5464
+ timelockEndsAt,
5465
+ activeSeatsSnapshot,
5466
+ forVotes,
5467
+ againstVotes,
5468
+ abstainVotes,
5469
+ amount,
5470
+ snapshotAssetBalance,
5471
+ transferIntent,
5472
+ intentDeadline,
5473
+ intentMaxRiskTier,
5474
+ title,
5475
+ description
5476
+ };
5477
+ }
5478
+ function serializeProposal(proposal) {
5479
+ const status = proposalStatus(proposal.status);
5480
+ return {
5481
+ kind: asNum(proposal.kind),
5482
+ configRiskTier: asNum(proposal.configRiskTier),
5483
+ origin: asNum(proposal.origin),
5484
+ status: status.status,
5485
+ statusCode: status.statusCode,
5486
+ proposer: proposal.proposer,
5487
+ threadId: asNum(proposal.threadId),
5488
+ petitionId: asNum(proposal.petitionId),
5489
+ createdAt: asNum(proposal.createdAt),
5490
+ deliberationEndsAt: asNum(proposal.deliberationEndsAt),
5491
+ voteStartAt: asNum(proposal.voteStartAt),
5492
+ voteEndAt: asNum(proposal.voteEndAt),
5493
+ timelockEndsAt: asNum(proposal.timelockEndsAt),
5494
+ activeSeatsSnapshot: asNum(proposal.activeSeatsSnapshot),
5495
+ forVotes: proposal.forVotes.toString(),
5496
+ againstVotes: proposal.againstVotes.toString(),
5497
+ abstainVotes: proposal.abstainVotes.toString(),
5498
+ amount: proposal.amount.toString(),
5499
+ snapshotAssetBalance: proposal.snapshotAssetBalance.toString(),
5500
+ transferIntent: proposal.transferIntent,
5501
+ intentDeadline: asNum(proposal.intentDeadline),
5502
+ intentMaxRiskTier: asNum(proposal.intentMaxRiskTier),
5503
+ title: proposal.title,
5504
+ description: proposal.description
5505
+ };
5506
+ }
5507
+ async function fetchProposalCount(client) {
5508
+ return await client.readContract({
5509
+ abi: governanceAbi,
5510
+ address: ABSTRACT_MAINNET_ADDRESSES.governance,
5511
+ functionName: "proposalCount"
5512
+ });
5513
+ }
5514
+ async function fetchProposalById(client, id) {
5515
+ return decodeProposal(
5516
+ await client.readContract({
5517
+ abi: governanceAbi,
5518
+ address: ABSTRACT_MAINNET_ADDRESSES.governance,
5519
+ functionName: "proposals",
5520
+ args: [BigInt(id)]
5521
+ })
5522
+ );
5523
+ }
5524
+ async function fetchAllProposals(client) {
5525
+ const count = await fetchProposalCount(client);
5526
+ const ids = Array.from({ length: Number(count) }, (_, i) => BigInt(i + 1));
5527
+ if (ids.length === 0) return [];
5528
+ const proposalTuples = await client.multicall({
5529
+ allowFailure: false,
5530
+ contracts: ids.map((id) => ({
5531
+ abi: governanceAbi,
5532
+ address: ABSTRACT_MAINNET_ADDRESSES.governance,
5533
+ functionName: "proposals",
5534
+ args: [id]
5535
+ }))
5536
+ });
5537
+ return proposalTuples.map(decodeProposal);
5538
+ }
5539
+ async function fetchHasVotedBatch(client, address, proposalIds) {
5540
+ if (proposalIds.length === 0) return /* @__PURE__ */ new Map();
5541
+ const results = await client.multicall({
5542
+ allowFailure: false,
5543
+ contracts: proposalIds.map((id) => ({
5544
+ abi: governanceAbi,
5545
+ address: ABSTRACT_MAINNET_ADDRESSES.governance,
5546
+ functionName: "hasVoted",
5547
+ args: [BigInt(id), address]
5548
+ }))
5549
+ });
5550
+ const map = /* @__PURE__ */ new Map();
5551
+ for (let i = 0; i < proposalIds.length; i++) {
5552
+ map.set(proposalIds[i], results[i]);
5553
+ }
5554
+ return map;
5555
+ }
5556
+
5557
+ // src/services/members.ts
5558
+ import { z as z3 } from "incur";
5559
+ var DEFAULT_MEMBER_SNAPSHOT_URL = "https://www.theaiassembly.org/api/indexer/members";
5560
+ var REGISTERED_EVENT_SCAN_STEP = 100000n;
5561
+ var REGISTERED_EVENT_SCAN_TIMEOUT_MS = 2e4;
5562
+ var memberSnapshotEntrySchema = z3.union([
5563
+ z3.string(),
5564
+ z3.object({
5565
+ address: z3.string(),
5566
+ ens: z3.string().optional(),
5567
+ name: z3.string().optional()
5568
+ })
5569
+ ]);
5570
+ var memberSnapshotSchema = z3.array(memberSnapshotEntrySchema);
5571
+ var AssemblyApiValidationError = class extends Error {
5572
+ constructor(details) {
5573
+ super("Assembly API response validation failed");
5574
+ this.details = details;
5575
+ this.name = "AssemblyApiValidationError";
5576
+ }
5577
+ };
5578
+ var AssemblyIndexerUnavailableError = class extends Error {
5579
+ constructor(details) {
5580
+ super("Assembly indexer unavailable");
5581
+ this.details = details;
5582
+ this.name = "AssemblyIndexerUnavailableError";
5583
+ }
5584
+ };
5585
+ function memberSnapshotEntryToIdentity(entry) {
5586
+ if (typeof entry === "string") return { address: entry };
5587
+ const identity = { address: entry.address };
5588
+ if (entry.ens !== void 0) identity.ens = entry.ens;
5589
+ if (entry.name !== void 0) identity.name = entry.name;
5590
+ return identity;
5591
+ }
5592
+ function mergeMemberIdentities(entries) {
5593
+ const byAddress = /* @__PURE__ */ new Map();
5594
+ for (const entry of entries) {
5595
+ const key = entry.address.toLowerCase();
5596
+ const existing = byAddress.get(key);
5597
+ if (!existing) {
5598
+ byAddress.set(key, entry);
5599
+ continue;
5600
+ }
5601
+ const merged = { address: existing.address };
5602
+ const ens = existing.ens ?? entry.ens;
5603
+ const name = existing.name ?? entry.name;
5604
+ if (ens !== void 0) merged.ens = ens;
5605
+ if (name !== void 0) merged.name = name;
5606
+ byAddress.set(key, merged);
5607
+ }
5608
+ return [...byAddress.values()];
5609
+ }
5610
+ async function memberSnapshot(url) {
5611
+ let res;
5612
+ try {
5613
+ res = await fetch(url);
5614
+ } catch (error) {
5615
+ throw new AssemblyIndexerUnavailableError({
5616
+ code: "ASSEMBLY_INDEXER_UNAVAILABLE",
5617
+ url,
5618
+ reason: error instanceof Error ? error.message : String(error)
5619
+ });
5620
+ }
5621
+ if (!res.ok) {
5622
+ throw new AssemblyIndexerUnavailableError({
5623
+ code: "ASSEMBLY_INDEXER_UNAVAILABLE",
5624
+ url,
5625
+ status: res.status,
5626
+ statusText: res.statusText
5627
+ });
5628
+ }
5629
+ const json = await res.json();
5630
+ const parsed = memberSnapshotSchema.safeParse(json);
5631
+ if (parsed.success) {
5632
+ return mergeMemberIdentities(parsed.data.map(memberSnapshotEntryToIdentity));
5633
+ }
5634
+ throw new AssemblyApiValidationError({
5635
+ code: "INVALID_ASSEMBLY_API_RESPONSE",
5636
+ url,
5637
+ issues: parsed.error.issues,
5638
+ response: json
5639
+ });
5640
+ }
5641
+ async function withTimeout(promise, timeoutMs, timeoutMessage) {
5642
+ let timer;
5643
+ try {
5644
+ return await Promise.race([
5645
+ promise,
5646
+ new Promise((_, reject) => {
5647
+ timer = setTimeout(() => {
5648
+ reject(new Error(timeoutMessage));
5649
+ }, timeoutMs);
5650
+ })
5651
+ ]);
5652
+ } finally {
5653
+ if (timer) clearTimeout(timer);
5654
+ }
5655
+ }
5656
+ async function membersFromRegisteredEvents(client) {
5657
+ const latestBlock = await client.getBlockNumber();
5658
+ const addresses = /* @__PURE__ */ new Set();
5659
+ for (let fromBlock = ABSTRACT_MAINNET_DEPLOYMENT_BLOCKS.registry; fromBlock <= latestBlock; fromBlock += REGISTERED_EVENT_SCAN_STEP) {
5660
+ const toBlock = fromBlock + REGISTERED_EVENT_SCAN_STEP - 1n > latestBlock ? latestBlock : fromBlock + REGISTERED_EVENT_SCAN_STEP - 1n;
5661
+ const events = await client.getContractEvents({
5662
+ abi: registryAbi,
5663
+ address: ABSTRACT_MAINNET_ADDRESSES.registry,
5664
+ eventName: "Registered",
5665
+ fromBlock,
5666
+ toBlock,
5667
+ strict: true
5668
+ });
5669
+ for (const event of events) {
5670
+ const member = event.args.member;
5671
+ if (typeof member === "string") {
5672
+ addresses.add(member);
5673
+ }
5674
+ }
5675
+ }
5676
+ return [...addresses].map((address) => ({ address }));
5677
+ }
5678
+ async function fetchMemberList(client, snapshotUrl) {
5679
+ const url = snapshotUrl ?? DEFAULT_MEMBER_SNAPSHOT_URL;
5680
+ try {
5681
+ return { members: await memberSnapshot(url) };
5682
+ } catch (error) {
5683
+ if (error instanceof AssemblyApiValidationError) {
5684
+ throw error;
5685
+ }
5686
+ if (!(error instanceof AssemblyIndexerUnavailableError)) {
5687
+ throw error;
5688
+ }
5689
+ const fallbackMembers = await withTimeout(
5690
+ membersFromRegisteredEvents(client),
5691
+ REGISTERED_EVENT_SCAN_TIMEOUT_MS,
5692
+ `Registered event fallback scan timed out after ${REGISTERED_EVENT_SCAN_TIMEOUT_MS}ms`
5693
+ );
5694
+ return {
5695
+ members: mergeMemberIdentities(fallbackMembers),
5696
+ fallbackReason: error.details
5697
+ };
5698
+ }
5699
+ }
5700
+ async function fetchMemberOnchainState(client, addresses) {
5701
+ if (addresses.length === 0) return [];
5702
+ const calls = addresses.flatMap((address) => [
5703
+ {
5704
+ abi: registryAbi,
5705
+ address: ABSTRACT_MAINNET_ADDRESSES.registry,
5706
+ functionName: "isActive",
5707
+ args: [address]
5708
+ },
5709
+ {
5710
+ abi: registryAbi,
5711
+ address: ABSTRACT_MAINNET_ADDRESSES.registry,
5712
+ functionName: "members",
5713
+ args: [address]
5714
+ }
5715
+ ]);
5716
+ const values = await client.multicall({ allowFailure: false, contracts: calls });
5717
+ return addresses.map((address, i) => {
5718
+ const active = values[i * 2];
5719
+ const info = values[i * 2 + 1];
5720
+ return {
5721
+ address: toChecksum(address),
5722
+ active,
5723
+ registered: info.registered,
5724
+ activeUntil: info.activeUntil,
5725
+ lastHeartbeatAt: info.lastHeartbeatAt
5726
+ };
5727
+ });
5728
+ }
5729
+
5730
+ // src/commands/digest.ts
5731
+ var digestEnv = z4.object({
5732
+ ABSTRACT_RPC_URL: z4.string().optional().describe("Abstract RPC URL override"),
5733
+ ASSEMBLY_INDEXER_URL: z4.string().optional().describe("Optional members snapshot endpoint (default: theaiassembly.org indexer)")
5734
+ });
5735
+ var memberItemSchema = z4.object({
5736
+ address: z4.string(),
5737
+ active: z4.boolean(),
5738
+ registered: z4.boolean(),
5739
+ activeUntil: z4.string(),
5740
+ lastHeartbeatAt: z4.string()
5741
+ });
5742
+ var proposalDigestSchema = z4.object({
5743
+ id: z4.number(),
5744
+ kind: z4.number(),
5745
+ configRiskTier: z4.number(),
5746
+ origin: z4.number(),
5747
+ status: z4.string(),
5748
+ statusCode: z4.number(),
5749
+ proposer: z4.string(),
5750
+ threadId: z4.number(),
5751
+ petitionId: z4.number(),
5752
+ createdAt: z4.number(),
5753
+ deliberationEndsAt: z4.number(),
5754
+ voteStartAt: z4.number(),
5755
+ voteEndAt: z4.number(),
5756
+ timelockEndsAt: z4.number(),
5757
+ activeSeatsSnapshot: z4.number(),
5758
+ forVotes: z4.string(),
5759
+ againstVotes: z4.string(),
5760
+ abstainVotes: z4.string(),
5761
+ amount: z4.string(),
5762
+ snapshotAssetBalance: z4.string(),
5763
+ transferIntent: z4.boolean(),
5764
+ intentDeadline: z4.number(),
5765
+ intentMaxRiskTier: z4.number(),
5766
+ title: z4.string(),
5767
+ description: z4.string(),
5768
+ hasVoted: z4.boolean().optional()
5769
+ });
5770
+ var threadDigestSchema = z4.object({
5771
+ id: z4.number(),
5772
+ kind: z4.number(),
5773
+ author: z4.string(),
5774
+ createdAt: z4.number(),
5775
+ category: z4.string(),
5776
+ title: z4.string(),
5777
+ proposalId: z4.number(),
5778
+ petitionId: z4.number()
5779
+ });
5780
+ var commentDigestSchema = z4.object({
5781
+ id: z4.number(),
5782
+ threadId: z4.number(),
5783
+ parentId: z4.number(),
5784
+ author: z4.string(),
5785
+ createdAt: z4.number(),
5786
+ body: z4.string()
5787
+ });
5788
+ var petitionDigestSchema = z4.object({
5789
+ id: z4.number(),
5790
+ proposer: z4.string(),
5791
+ createdAt: z4.number(),
5792
+ category: z4.string(),
5793
+ title: z4.string(),
5794
+ body: z4.string(),
5795
+ signatures: z4.number(),
5796
+ promoted: z4.boolean(),
5797
+ threadId: z4.number(),
5798
+ hasSigned: z4.boolean().optional()
5799
+ });
5800
+ var proposalSummarySchema = z4.object({
5801
+ id: z4.number(),
5802
+ title: z4.string(),
5803
+ status: z4.string(),
5804
+ statusCode: z4.number(),
5805
+ createdAt: z4.number(),
5806
+ hasVoted: z4.boolean().optional()
5807
+ });
5808
+ var threadSummarySchema = z4.object({
5809
+ id: z4.number(),
5810
+ title: z4.string(),
5811
+ category: z4.string(),
5812
+ createdAt: z4.number()
5813
+ });
5814
+ var commentSummarySchema = z4.object({
5815
+ id: z4.number(),
5816
+ threadId: z4.number(),
5817
+ author: z4.string(),
5818
+ createdAt: z4.number()
5819
+ });
5820
+ var petitionSummarySchema = z4.object({
5821
+ id: z4.number(),
5822
+ title: z4.string(),
5823
+ category: z4.string(),
5824
+ signatures: z4.number(),
5825
+ promoted: z4.boolean(),
5826
+ createdAt: z4.number(),
5827
+ hasSigned: z4.boolean().optional()
5828
+ });
5829
+ var filtersMetaSchema = z4.object({
5830
+ since: z4.string().optional(),
5831
+ until: z4.string().optional(),
5832
+ omitComments: z4.boolean().optional(),
5833
+ omitMembers: z4.boolean().optional(),
5834
+ omitPetitions: z4.boolean().optional(),
5835
+ proposalsLimit: z4.number().optional(),
5836
+ threadsLimit: z4.number().optional(),
5837
+ commentsLimit: z4.number().optional(),
5838
+ petitionsLimit: z4.number().optional(),
5839
+ summaryOnly: z4.boolean().optional(),
5840
+ proposalStatus: z4.string().optional()
5841
+ });
5842
+ var digestOutputSchema = z4.object({
5843
+ meta: z4.object({
5844
+ chainId: z4.number(),
5845
+ fetchedAt: z4.string(),
5846
+ address: z4.string().optional(),
5847
+ filters: filtersMetaSchema.optional()
5848
+ }),
5849
+ proposals: z4.array(z4.union([proposalDigestSchema, proposalSummarySchema])),
5850
+ threads: z4.array(z4.union([threadDigestSchema, threadSummarySchema])),
5851
+ comments: z4.array(z4.union([commentDigestSchema, commentSummarySchema])).optional(),
5852
+ petitions: z4.array(z4.union([petitionDigestSchema, petitionSummarySchema])).optional(),
5853
+ members: z4.object({
5854
+ count: z4.number(),
5855
+ items: z4.array(memberItemSchema)
5856
+ }).optional(),
5857
+ errors: z4.array(z4.string())
5858
+ });
5859
+ function parseDuration(value) {
5860
+ const match = value.match(/^(\d+(?:\.\d+)?)\s*(m|h|d)$/i);
5861
+ if (!match) return null;
5862
+ const amount = Number.parseFloat(match[1]);
5863
+ const unit = match[2].toLowerCase();
5864
+ switch (unit) {
5865
+ case "m":
5866
+ return amount * 60 * 1e3;
5867
+ case "h":
5868
+ return amount * 3600 * 1e3;
5869
+ case "d":
5870
+ return amount * 86400 * 1e3;
5871
+ default:
5872
+ return null;
5873
+ }
5874
+ }
5875
+ var validProposalStatuses = new Set(Object.values(proposalStatusLabels));
5876
+ function registerDigestCommand(cli2) {
5877
+ cli2.command("digest", {
5878
+ description: "Aggregate proposals, threads, comments, petitions, and members into a single governance snapshot.",
5879
+ options: z4.object({
5880
+ address: z4.string().optional().describe("Wallet address to enrich proposals (hasVoted) and petitions (hasSigned)"),
5881
+ since: z4.string().optional().describe("Only items created/updated after this ISO-8601 timestamp"),
5882
+ last: z4.string().optional().describe("Duration shorthand (e.g. 24h, 7d, 30m) \u2014 converted to --since"),
5883
+ until: z4.string().optional().describe("Only items created/updated before this ISO-8601 timestamp"),
5884
+ "omit-comments": z4.boolean().optional().describe("Exclude comments from output"),
5885
+ "omit-members": z4.boolean().optional().describe("Exclude members from output"),
5886
+ "omit-petitions": z4.boolean().optional().describe("Exclude petitions from output"),
5887
+ "proposals-limit": z4.number().optional().describe("Return only the most recent N proposals"),
5888
+ "threads-limit": z4.number().optional().describe("Return only the most recent N threads"),
5889
+ "comments-limit": z4.number().optional().describe("Return only the most recent N comments"),
5890
+ "petitions-limit": z4.number().optional().describe("Return only the most recent N petitions"),
5891
+ "summary-only": z4.boolean().optional().describe("Return only counts/metadata per section (no full bodies)"),
5892
+ "proposal-status": z4.string().optional().describe("Filter proposals by status (pending/active/passed/executed/defeated/cancelled)")
5893
+ }),
5894
+ env: digestEnv,
5895
+ output: digestOutputSchema,
5896
+ examples: [
5897
+ { description: "Fetch a full governance digest" },
5898
+ {
5899
+ options: { address: "0x230Ccc765765d729fFb1897D538f773b92005Aa2" },
5900
+ description: "Fetch digest with wallet-relative enrichment"
5901
+ },
5902
+ {
5903
+ options: { last: "24h" },
5904
+ description: "Fetch digest for the last 24 hours"
5905
+ },
5906
+ {
5907
+ options: { "summary-only": true },
5908
+ description: "Fetch digest with only summary metadata"
5909
+ },
5910
+ {
5911
+ options: { "proposal-status": "active", "omit-comments": true },
5912
+ description: "Fetch only active proposals, omitting comments"
5913
+ }
5914
+ ],
5915
+ async run(c) {
5916
+ return withCommandSpan("assembly digest", { address: c.options.address }, async () => {
5917
+ const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
5918
+ const errors = [];
5919
+ const address = c.options.address ? toChecksum(c.options.address) : void 0;
5920
+ let sinceTs;
5921
+ let untilTs;
5922
+ if (c.options.last && c.options.since) {
5923
+ return c.error({
5924
+ code: "INVALID_OPTIONS",
5925
+ message: "Cannot specify both --since and --last",
5926
+ retryable: false
5927
+ });
5928
+ }
5929
+ if (c.options.last) {
5930
+ const durationMs = parseDuration(c.options.last);
5931
+ if (durationMs === null) {
5932
+ return c.error({
5933
+ code: "INVALID_DURATION",
5934
+ message: `Invalid duration format: "${c.options.last}". Use e.g. 24h, 7d, 30m`,
5935
+ retryable: false
5936
+ });
5937
+ }
5938
+ sinceTs = Math.floor((Date.now() - durationMs) / 1e3);
5939
+ } else if (c.options.since) {
5940
+ const parsed = Date.parse(c.options.since);
5941
+ if (Number.isNaN(parsed)) {
5942
+ return c.error({
5943
+ code: "INVALID_TIMESTAMP",
5944
+ message: `Invalid --since timestamp: "${c.options.since}"`,
5945
+ retryable: false
5946
+ });
5947
+ }
5948
+ sinceTs = Math.floor(parsed / 1e3);
5949
+ }
5950
+ if (c.options.until) {
5951
+ const parsed = Date.parse(c.options.until);
5952
+ if (Number.isNaN(parsed)) {
5953
+ return c.error({
5954
+ code: "INVALID_TIMESTAMP",
5955
+ message: `Invalid --until timestamp: "${c.options.until}"`,
5956
+ retryable: false
5957
+ });
5958
+ }
5959
+ untilTs = Math.floor(parsed / 1e3);
5960
+ }
5961
+ const proposalStatusFilter = c.options["proposal-status"];
5962
+ if (proposalStatusFilter && !validProposalStatuses.has(proposalStatusFilter)) {
5963
+ return c.error({
5964
+ code: "INVALID_STATUS",
5965
+ message: `Invalid --proposal-status: "${proposalStatusFilter}". Valid: ${[...validProposalStatuses].join(", ")}`,
5966
+ retryable: false
5967
+ });
5968
+ }
5969
+ const omitComments = c.options["omit-comments"] ?? false;
5970
+ const omitMembers = c.options["omit-members"] ?? false;
5971
+ const omitPetitions = c.options["omit-petitions"] ?? false;
5972
+ const summaryOnly = c.options["summary-only"] ?? false;
5973
+ const proposalsLimit = c.options["proposals-limit"];
5974
+ const threadsLimit = c.options["threads-limit"];
5975
+ const commentsLimit = c.options["comments-limit"];
5976
+ const petitionsLimit = c.options["petitions-limit"];
5977
+ const [proposalsResult, threadsResult, commentsResult, petitionsResult, membersResult] = await Promise.allSettled([
5978
+ fetchAllProposals(client),
5979
+ fetchAllThreads(client),
5980
+ omitComments ? Promise.resolve([]) : fetchAllComments(client),
5981
+ omitPetitions ? Promise.resolve([]) : fetchAllPetitions(client),
5982
+ omitMembers ? Promise.resolve({ members: [], fallbackReason: void 0 }) : fetchMemberList(client, c.env.ASSEMBLY_INDEXER_URL)
5983
+ ]);
5984
+ let proposals = [];
5985
+ if (proposalsResult.status === "fulfilled") {
5986
+ proposals = proposalsResult.value;
5987
+ } else {
5988
+ errors.push(`proposals: ${proposalsResult.reason}`);
5989
+ }
5990
+ let threads = [];
5991
+ if (threadsResult.status === "fulfilled") {
5992
+ threads = threadsResult.value;
5993
+ } else {
5994
+ errors.push(`threads: ${threadsResult.reason}`);
5995
+ }
5996
+ let comments = [];
5997
+ if (!omitComments) {
5998
+ if (commentsResult.status === "fulfilled") {
5999
+ comments = commentsResult.value;
6000
+ } else {
6001
+ errors.push(`comments: ${commentsResult.reason}`);
6002
+ }
6003
+ }
6004
+ let petitions = [];
6005
+ if (!omitPetitions) {
6006
+ if (petitionsResult.status === "fulfilled") {
6007
+ petitions = petitionsResult.value;
6008
+ } else {
6009
+ errors.push(`petitions: ${petitionsResult.reason}`);
6010
+ }
6011
+ }
6012
+ let memberIdentities = [];
6013
+ if (!omitMembers) {
6014
+ if (membersResult.status === "fulfilled") {
6015
+ const loaded = membersResult.value;
6016
+ memberIdentities = loaded.members;
6017
+ if (loaded.fallbackReason) {
6018
+ process.stderr.write(
6019
+ `${JSON.stringify({
6020
+ level: "warn",
6021
+ code: loaded.fallbackReason.code,
6022
+ message: "Member snapshot indexer is unavailable. Falling back to on-chain Registered events.",
6023
+ url: loaded.fallbackReason.url
6024
+ })}
6025
+ `
6026
+ );
6027
+ }
6028
+ } else {
6029
+ const err = membersResult.reason;
6030
+ if (err instanceof AssemblyApiValidationError) {
6031
+ errors.push(`members: ${err.details.code}`);
6032
+ } else {
6033
+ errors.push(`members: ${err}`);
6034
+ }
6035
+ }
6036
+ }
6037
+ if (sinceTs !== void 0) {
6038
+ proposals = proposals.filter((p) => Number(p.createdAt) >= sinceTs);
6039
+ threads = threads.filter((t) => t.createdAt >= sinceTs);
6040
+ comments = comments.filter((cm) => cm.createdAt >= sinceTs);
6041
+ petitions = petitions.filter((p) => p.createdAt >= sinceTs);
6042
+ }
6043
+ if (untilTs !== void 0) {
6044
+ proposals = proposals.filter((p) => Number(p.createdAt) <= untilTs);
6045
+ threads = threads.filter((t) => t.createdAt <= untilTs);
6046
+ comments = comments.filter((cm) => cm.createdAt <= untilTs);
6047
+ petitions = petitions.filter((p) => p.createdAt <= untilTs);
6048
+ }
6049
+ if (proposalStatusFilter) {
6050
+ const statusLabelToCode = /* @__PURE__ */ new Map();
6051
+ for (const [code, label] of Object.entries(proposalStatusLabels)) {
6052
+ statusLabelToCode.set(label, Number(code));
6053
+ }
6054
+ const targetCode = statusLabelToCode.get(proposalStatusFilter);
6055
+ if (targetCode !== void 0) {
6056
+ proposals = proposals.filter((p) => Number(p.status) === targetCode);
6057
+ }
6058
+ }
6059
+ proposals.sort((a, b) => Number(b.createdAt) - Number(a.createdAt));
6060
+ threads.sort((a, b) => b.createdAt - a.createdAt);
6061
+ comments.sort((a, b) => b.createdAt - a.createdAt);
6062
+ petitions.sort((a, b) => b.createdAt - a.createdAt);
6063
+ if (proposalsLimit !== void 0) {
6064
+ proposals = proposals.slice(0, proposalsLimit);
6065
+ }
6066
+ if (threadsLimit !== void 0) {
6067
+ threads = threads.slice(0, threadsLimit);
6068
+ }
6069
+ if (commentsLimit !== void 0) {
6070
+ comments = comments.slice(0, commentsLimit);
6071
+ }
6072
+ if (petitionsLimit !== void 0) {
6073
+ petitions = petitions.slice(0, petitionsLimit);
6074
+ }
6075
+ let memberItems = [];
6076
+ if (!omitMembers && memberIdentities.length > 0) {
6077
+ try {
6078
+ const onchainStates = await fetchMemberOnchainState(
6079
+ client,
6080
+ memberIdentities.map((m) => m.address)
6081
+ );
6082
+ memberItems = onchainStates.map((s) => ({
6083
+ address: s.address,
6084
+ active: s.active,
6085
+ registered: s.registered,
6086
+ activeUntil: isoTime(s.activeUntil),
6087
+ lastHeartbeatAt: isoTime(s.lastHeartbeatAt)
6088
+ }));
6089
+ } catch (err) {
6090
+ errors.push(`members onchain state: ${err}`);
6091
+ }
6092
+ }
6093
+ let hasVotedMap = /* @__PURE__ */ new Map();
6094
+ let hasSignedMap = /* @__PURE__ */ new Map();
6095
+ if (address) {
6096
+ const proposalIds = proposals.map((_, i) => i + 1);
6097
+ const petitionIds = petitions.map((p) => p.id);
6098
+ const [votedResult, signedResult] = await Promise.allSettled([
6099
+ fetchHasVotedBatch(client, address, proposalIds),
6100
+ omitPetitions ? Promise.resolve(/* @__PURE__ */ new Map()) : fetchHasSignedBatch(client, address, petitionIds)
6101
+ ]);
6102
+ if (votedResult.status === "fulfilled") {
6103
+ hasVotedMap = votedResult.value;
6104
+ } else {
6105
+ errors.push(`hasVoted enrichment: ${votedResult.reason}`);
6106
+ }
6107
+ if (signedResult.status === "fulfilled") {
6108
+ hasSignedMap = signedResult.value;
6109
+ } else {
6110
+ errors.push(`hasSigned enrichment: ${signedResult.reason}`);
6111
+ }
6112
+ }
6113
+ let serializedProposals;
6114
+ if (summaryOnly) {
6115
+ serializedProposals = proposals.map((p, i) => {
6116
+ const { status, statusCode } = serializeProposal(p);
6117
+ const entry = {
6118
+ id: i + 1,
6119
+ title: p.title,
6120
+ status,
6121
+ statusCode,
6122
+ createdAt: Number(p.createdAt)
6123
+ };
6124
+ if (address) {
6125
+ entry.hasVoted = hasVotedMap.get(i + 1) ?? false;
6126
+ }
6127
+ return entry;
6128
+ });
6129
+ } else {
6130
+ serializedProposals = proposals.map((p, i) => {
6131
+ const serialized = serializeProposal(p);
6132
+ const entry = {
6133
+ id: i + 1,
6134
+ ...serialized
6135
+ };
6136
+ if (address) {
6137
+ entry.hasVoted = hasVotedMap.get(i + 1) ?? false;
6138
+ }
6139
+ return entry;
6140
+ });
6141
+ }
6142
+ let serializedThreads;
6143
+ if (summaryOnly) {
6144
+ serializedThreads = threads.map((t) => ({
6145
+ id: t.id,
6146
+ title: t.title,
6147
+ category: t.category,
6148
+ createdAt: t.createdAt
6149
+ }));
6150
+ } else {
6151
+ serializedThreads = threads.map((t) => ({
6152
+ id: t.id,
6153
+ kind: t.kind,
6154
+ author: t.author,
6155
+ createdAt: t.createdAt,
6156
+ category: t.category,
6157
+ title: t.title,
6158
+ proposalId: t.proposalId,
6159
+ petitionId: t.petitionId
6160
+ }));
6161
+ }
6162
+ let serializedComments;
6163
+ if (!omitComments) {
6164
+ if (summaryOnly) {
6165
+ serializedComments = comments.map((cm) => ({
6166
+ id: cm.id,
6167
+ threadId: cm.threadId,
6168
+ author: cm.author,
6169
+ createdAt: cm.createdAt
6170
+ }));
6171
+ } else {
6172
+ serializedComments = comments.map((cm) => ({
6173
+ id: cm.id,
6174
+ threadId: cm.threadId,
6175
+ parentId: cm.parentId,
6176
+ author: cm.author,
6177
+ createdAt: cm.createdAt,
6178
+ body: cm.body
6179
+ }));
6180
+ }
6181
+ }
6182
+ let serializedPetitions;
6183
+ if (!omitPetitions) {
6184
+ if (summaryOnly) {
6185
+ serializedPetitions = petitions.map((p) => {
6186
+ const entry = {
6187
+ id: p.id,
6188
+ title: p.title,
6189
+ category: p.category,
6190
+ signatures: p.signatures,
6191
+ promoted: p.promoted,
6192
+ createdAt: p.createdAt
6193
+ };
6194
+ if (address) {
6195
+ entry.hasSigned = hasSignedMap.get(p.id) ?? false;
6196
+ }
6197
+ return entry;
6198
+ });
6199
+ } else {
6200
+ serializedPetitions = petitions.map((p) => {
6201
+ const entry = {
6202
+ id: p.id,
6203
+ proposer: p.proposer,
6204
+ createdAt: p.createdAt,
6205
+ category: p.category,
6206
+ title: p.title,
6207
+ body: p.body,
6208
+ signatures: p.signatures,
6209
+ promoted: p.promoted,
6210
+ threadId: p.threadId
6211
+ };
6212
+ if (address) {
6213
+ entry.hasSigned = hasSignedMap.get(p.id) ?? false;
6214
+ }
6215
+ return entry;
6216
+ });
6217
+ }
6218
+ }
6219
+ const filtersMeta = {};
6220
+ if (sinceTs !== void 0) filtersMeta.since = isoTime(sinceTs);
6221
+ if (untilTs !== void 0) filtersMeta.until = isoTime(untilTs);
6222
+ if (omitComments) filtersMeta.omitComments = true;
6223
+ if (omitMembers) filtersMeta.omitMembers = true;
6224
+ if (omitPetitions) filtersMeta.omitPetitions = true;
6225
+ if (proposalsLimit !== void 0) filtersMeta.proposalsLimit = proposalsLimit;
6226
+ if (threadsLimit !== void 0) filtersMeta.threadsLimit = threadsLimit;
6227
+ if (commentsLimit !== void 0) filtersMeta.commentsLimit = commentsLimit;
6228
+ if (petitionsLimit !== void 0) filtersMeta.petitionsLimit = petitionsLimit;
6229
+ if (summaryOnly) filtersMeta.summaryOnly = true;
6230
+ if (proposalStatusFilter) filtersMeta.proposalStatus = proposalStatusFilter;
6231
+ const hasFilters = Object.keys(filtersMeta).length > 0;
6232
+ const output = {
6233
+ meta: {
6234
+ chainId: 2741,
6235
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString().replace(".000Z", "Z"),
6236
+ ...address ? { address } : {},
6237
+ ...hasFilters ? { filters: filtersMeta } : {}
6238
+ },
6239
+ proposals: serializedProposals,
6240
+ threads: serializedThreads,
6241
+ ...omitComments ? {} : { comments: serializedComments },
6242
+ ...omitPetitions ? {} : { petitions: serializedPetitions },
6243
+ ...omitMembers ? {} : { members: { count: memberItems.length, items: memberItems } },
6244
+ errors
6245
+ };
6246
+ return c.ok(output);
6247
+ });
6248
+ }
6249
+ });
5391
6250
  }
5392
6251
 
5393
6252
  // src/commands/forum.ts
5394
- var env2 = z3.object({
5395
- ABSTRACT_RPC_URL: z3.string().optional().describe("Abstract RPC URL override")
6253
+ import { TxError } from "@spectratools/tx-shared";
6254
+ import { Cli as Cli2, z as z5 } from "incur";
6255
+ var env2 = z5.object({
6256
+ ABSTRACT_RPC_URL: z5.string().optional().describe("Abstract RPC URL override")
5396
6257
  });
5397
6258
  var commentEnv = env2.extend({
5398
- PRIVATE_KEY: z3.string().optional().describe("Private key (required only when posting a comment via --body)")
6259
+ PRIVATE_KEY: z5.string().optional().describe("Private key (required only when posting a comment via --body)")
5399
6260
  });
5400
- var timestampOutput2 = z3.union([z3.number(), z3.string()]);
5401
- var txResultOutput2 = z3.union([
5402
- z3.object({
5403
- status: z3.literal("success"),
5404
- hash: z3.string(),
5405
- blockNumber: z3.number(),
5406
- gasUsed: z3.string(),
5407
- from: z3.string(),
5408
- to: z3.string().nullable(),
5409
- effectiveGasPrice: z3.string().optional()
6261
+ var timestampOutput2 = z5.union([z5.number(), z5.string()]);
6262
+ var txResultOutput2 = z5.union([
6263
+ z5.object({
6264
+ status: z5.literal("success"),
6265
+ hash: z5.string(),
6266
+ blockNumber: z5.number(),
6267
+ gasUsed: z5.string(),
6268
+ from: z5.string(),
6269
+ to: z5.string().nullable(),
6270
+ effectiveGasPrice: z5.string().optional()
5410
6271
  }),
5411
- z3.object({
5412
- status: z3.literal("reverted"),
5413
- hash: z3.string(),
5414
- blockNumber: z3.number(),
5415
- gasUsed: z3.string(),
5416
- from: z3.string(),
5417
- to: z3.string().nullable(),
5418
- effectiveGasPrice: z3.string().optional()
6272
+ z5.object({
6273
+ status: z5.literal("reverted"),
6274
+ hash: z5.string(),
6275
+ blockNumber: z5.number(),
6276
+ gasUsed: z5.string(),
6277
+ from: z5.string(),
6278
+ to: z5.string().nullable(),
6279
+ effectiveGasPrice: z5.string().optional()
5419
6280
  }),
5420
- z3.object({
5421
- status: z3.literal("dry-run"),
5422
- estimatedGas: z3.string(),
5423
- simulationResult: z3.unknown()
6281
+ z5.object({
6282
+ status: z5.literal("dry-run"),
6283
+ estimatedGas: z5.string(),
6284
+ simulationResult: z5.unknown()
5424
6285
  })
5425
6286
  ]);
5426
6287
  var forum = Cli2.create("forum", {
@@ -5429,19 +6290,19 @@ var forum = Cli2.create("forum", {
5429
6290
  forum.command("threads", {
5430
6291
  description: "List forum threads with author and creation metadata.",
5431
6292
  env: env2,
5432
- output: z3.object({
5433
- threads: z3.array(
5434
- z3.object({
5435
- id: z3.number(),
5436
- kind: z3.number(),
5437
- author: z3.string(),
6293
+ output: z5.object({
6294
+ threads: z5.array(
6295
+ z5.object({
6296
+ id: z5.number(),
6297
+ kind: z5.number(),
6298
+ author: z5.string(),
5438
6299
  createdAt: timestampOutput2,
5439
- createdAtRelative: z3.string(),
5440
- category: z3.string().nullable().optional(),
5441
- title: z3.string().nullable().optional()
6300
+ createdAtRelative: z5.string(),
6301
+ category: z5.string().nullable().optional(),
6302
+ title: z5.string().nullable().optional()
5442
6303
  })
5443
6304
  ),
5444
- count: z3.number()
6305
+ count: z5.number()
5445
6306
  }),
5446
6307
  examples: [{ description: "List all forum threads" }],
5447
6308
  async run(c) {
@@ -5475,13 +6336,13 @@ forum.command("threads", {
5475
6336
  });
5476
6337
  forum.command("thread", {
5477
6338
  description: "Get one thread and all comments associated with it.",
5478
- args: z3.object({
5479
- id: z3.coerce.number().int().positive().describe("Thread id (1-indexed)")
6339
+ args: z5.object({
6340
+ id: z5.coerce.number().int().positive().describe("Thread id (1-indexed)")
5480
6341
  }),
5481
6342
  env: env2,
5482
- output: z3.object({
5483
- thread: z3.record(z3.string(), z3.unknown()),
5484
- comments: z3.array(z3.record(z3.string(), z3.unknown()))
6343
+ output: z5.object({
6344
+ thread: z5.record(z5.string(), z5.unknown()),
6345
+ comments: z5.array(z5.record(z5.string(), z5.unknown()))
5485
6346
  }),
5486
6347
  examples: [{ args: { id: 1 }, description: "Fetch thread #1 and its comments" }],
5487
6348
  async run(c) {
@@ -5514,11 +6375,11 @@ forum.command("thread", {
5514
6375
  });
5515
6376
  forum.command("comments", {
5516
6377
  description: "List comments for a thread id.",
5517
- args: z3.object({
5518
- threadId: z3.coerce.number().int().positive().describe("Thread id to filter comments by")
6378
+ args: z5.object({
6379
+ threadId: z5.coerce.number().int().positive().describe("Thread id to filter comments by")
5519
6380
  }),
5520
6381
  env: env2,
5521
- output: z3.array(z3.record(z3.string(), z3.unknown())),
6382
+ output: z5.array(z5.record(z5.string(), z5.unknown())),
5522
6383
  examples: [{ args: { threadId: 1 }, description: "List comments for thread #1" }],
5523
6384
  async run(c) {
5524
6385
  const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
@@ -5530,15 +6391,15 @@ forum.command("comments", {
5530
6391
  });
5531
6392
  forum.command("comment", {
5532
6393
  description: "Get one comment by id, or post to a thread when --body is provided.",
5533
- args: z3.object({
5534
- id: z3.coerce.number().int().positive().describe("Comment id (read) or thread id (write)")
6394
+ args: z5.object({
6395
+ id: z5.coerce.number().int().positive().describe("Comment id (read) or thread id (write)")
5535
6396
  }),
5536
6397
  options: writeOptions.extend({
5537
- body: z3.string().min(1).optional().describe("Comment body (write mode)"),
5538
- "parent-id": z3.coerce.number().int().nonnegative().default(0).describe("Optional parent comment id for threaded replies (write mode)")
6398
+ body: z5.string().min(1).optional().describe("Comment body (write mode)"),
6399
+ "parent-id": z5.coerce.number().int().nonnegative().default(0).describe("Optional parent comment id for threaded replies (write mode)")
5539
6400
  }),
5540
6401
  env: commentEnv,
5541
- output: z3.record(z3.string(), z3.unknown()),
6402
+ output: z5.record(z5.string(), z5.unknown()),
5542
6403
  examples: [
5543
6404
  { args: { id: 1 }, description: "Fetch comment #1" },
5544
6405
  {
@@ -5653,16 +6514,16 @@ forum.command("post", {
5653
6514
  description: "Create a new discussion thread in the forum.",
5654
6515
  hint: "Requires PRIVATE_KEY environment variable for signing.",
5655
6516
  options: writeOptions.extend({
5656
- category: z3.string().min(1).describe("Thread category label (e.g., general, governance)"),
5657
- title: z3.string().min(1).describe("Thread title"),
5658
- body: z3.string().min(1).describe("Thread body")
6517
+ category: z5.string().min(1).describe("Thread category label (e.g., general, governance)"),
6518
+ title: z5.string().min(1).describe("Thread title"),
6519
+ body: z5.string().min(1).describe("Thread body")
5659
6520
  }),
5660
6521
  env: writeEnv,
5661
- output: z3.object({
5662
- author: z3.string(),
5663
- category: z3.string(),
5664
- title: z3.string(),
5665
- expectedThreadId: z3.number(),
6522
+ output: z5.object({
6523
+ author: z5.string(),
6524
+ category: z5.string(),
6525
+ title: z5.string(),
6526
+ expectedThreadId: z5.number(),
5666
6527
  tx: txResultOutput2
5667
6528
  }),
5668
6529
  examples: [
@@ -5730,19 +6591,19 @@ forum.command("post", {
5730
6591
  forum.command("post-comment", {
5731
6592
  description: "Post a comment to a forum thread.",
5732
6593
  hint: "Requires PRIVATE_KEY environment variable for signing.",
5733
- args: z3.object({
5734
- threadId: z3.coerce.number().int().positive().describe("Thread id to comment on")
6594
+ args: z5.object({
6595
+ threadId: z5.coerce.number().int().positive().describe("Thread id to comment on")
5735
6596
  }),
5736
6597
  options: writeOptions.extend({
5737
- body: z3.string().min(1).describe("Comment body"),
5738
- "parent-id": z3.coerce.number().int().nonnegative().default(0).describe("Optional parent comment id for threaded replies")
6598
+ body: z5.string().min(1).describe("Comment body"),
6599
+ "parent-id": z5.coerce.number().int().nonnegative().default(0).describe("Optional parent comment id for threaded replies")
5739
6600
  }),
5740
6601
  env: writeEnv,
5741
- output: z3.object({
5742
- author: z3.string(),
5743
- threadId: z3.number(),
5744
- parentId: z3.number(),
5745
- expectedCommentId: z3.number(),
6602
+ output: z5.object({
6603
+ author: z5.string(),
6604
+ threadId: z5.number(),
6605
+ parentId: z5.number(),
6606
+ expectedCommentId: z5.number(),
5746
6607
  tx: txResultOutput2
5747
6608
  }),
5748
6609
  examples: [
@@ -5829,20 +6690,20 @@ forum.command("create-petition", {
5829
6690
  description: "Create a new petition for community-initiated proposals.",
5830
6691
  hint: "Requires PRIVATE_KEY environment variable for signing.",
5831
6692
  options: writeOptions.extend({
5832
- title: z3.string().min(1).describe("Petition title"),
5833
- description: z3.string().min(1).describe("Petition description"),
5834
- kind: z3.coerce.number().int().nonnegative().max(255).describe("Proposal kind enum value"),
5835
- category: z3.string().default("governance").describe("Forum category label for the petition")
6693
+ title: z5.string().min(1).describe("Petition title"),
6694
+ description: z5.string().min(1).describe("Petition description"),
6695
+ kind: z5.coerce.number().int().nonnegative().max(255).describe("Proposal kind enum value"),
6696
+ category: z5.string().default("governance").describe("Forum category label for the petition")
5836
6697
  }),
5837
6698
  env: writeEnv,
5838
- output: z3.object({
5839
- proposer: z3.string(),
5840
- category: z3.string(),
5841
- kind: z3.number(),
5842
- title: z3.string(),
5843
- description: z3.string(),
5844
- expectedPetitionId: z3.number(),
5845
- expectedThreadId: z3.number(),
6699
+ output: z5.object({
6700
+ proposer: z5.string(),
6701
+ category: z5.string(),
6702
+ kind: z5.number(),
6703
+ title: z5.string(),
6704
+ description: z5.string(),
6705
+ expectedPetitionId: z5.number(),
6706
+ expectedThreadId: z5.number(),
5846
6707
  tx: txResultOutput2
5847
6708
  }),
5848
6709
  examples: [
@@ -5945,15 +6806,15 @@ forum.command("create-petition", {
5945
6806
  forum.command("sign-petition", {
5946
6807
  description: "Sign an existing petition as an active member.",
5947
6808
  hint: "Requires PRIVATE_KEY environment variable for signing.",
5948
- args: z3.object({
5949
- petitionId: z3.coerce.number().int().positive().describe("Petition id (1-indexed)")
6809
+ args: z5.object({
6810
+ petitionId: z5.coerce.number().int().positive().describe("Petition id (1-indexed)")
5950
6811
  }),
5951
6812
  options: writeOptions,
5952
6813
  env: writeEnv,
5953
- output: z3.object({
5954
- signer: z3.string(),
5955
- petitionId: z3.number(),
5956
- expectedSignatures: z3.number(),
6814
+ output: z5.object({
6815
+ signer: z5.string(),
6816
+ petitionId: z5.number(),
6817
+ expectedSignatures: z5.number(),
5957
6818
  tx: txResultOutput2
5958
6819
  }),
5959
6820
  examples: [{ args: { petitionId: 1 }, description: "Sign petition #1" }],
@@ -6040,7 +6901,7 @@ forum.command("sign-petition", {
6040
6901
  forum.command("petitions", {
6041
6902
  description: "List petitions submitted in the forum contract.",
6042
6903
  env: env2,
6043
- output: z3.array(z3.record(z3.string(), z3.unknown())),
6904
+ output: z5.array(z5.record(z5.string(), z5.unknown())),
6044
6905
  examples: [{ description: "List all petitions" }],
6045
6906
  async run(c) {
6046
6907
  const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
@@ -6050,11 +6911,11 @@ forum.command("petitions", {
6050
6911
  });
6051
6912
  forum.command("petition", {
6052
6913
  description: "Get one petition plus whether proposer already signed it.",
6053
- args: z3.object({
6054
- id: z3.coerce.number().int().positive().describe("Petition id (1-indexed)")
6914
+ args: z5.object({
6915
+ id: z5.coerce.number().int().positive().describe("Petition id (1-indexed)")
6055
6916
  }),
6056
6917
  env: env2,
6057
- output: z3.object({ proposerSigned: z3.boolean() }).passthrough(),
6918
+ output: z5.object({ proposerSigned: z5.boolean() }).passthrough(),
6058
6919
  examples: [{ args: { id: 1 }, description: "Fetch petition #1" }],
6059
6920
  async run(c) {
6060
6921
  const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
@@ -6089,15 +6950,15 @@ forum.command("petition", {
6089
6950
  });
6090
6951
  forum.command("has-signed", {
6091
6952
  description: "Check whether an address signed a petition.",
6092
- args: z3.object({
6093
- petitionId: z3.coerce.number().int().positive().describe("Petition id (1-indexed)"),
6094
- address: z3.string().describe("Signer address to check")
6953
+ args: z5.object({
6954
+ petitionId: z5.coerce.number().int().positive().describe("Petition id (1-indexed)"),
6955
+ address: z5.string().describe("Signer address to check")
6095
6956
  }),
6096
6957
  env: env2,
6097
- output: z3.object({
6098
- petitionId: z3.number(),
6099
- address: z3.string(),
6100
- hasSigned: z3.boolean()
6958
+ output: z5.object({
6959
+ petitionId: z5.number(),
6960
+ address: z5.string(),
6961
+ hasSigned: z5.boolean()
6101
6962
  }),
6102
6963
  examples: [
6103
6964
  {
@@ -6122,11 +6983,11 @@ forum.command("has-signed", {
6122
6983
  forum.command("stats", {
6123
6984
  description: "Read top-level forum counters and petition threshold.",
6124
6985
  env: env2,
6125
- output: z3.object({
6126
- threadCount: z3.number(),
6127
- commentCount: z3.number(),
6128
- petitionCount: z3.number(),
6129
- petitionThresholdBps: z3.number()
6986
+ output: z5.object({
6987
+ threadCount: z5.number(),
6988
+ commentCount: z5.number(),
6989
+ petitionCount: z5.number(),
6990
+ petitionThresholdBps: z5.number()
6130
6991
  }),
6131
6992
  examples: [{ description: "Get forum counts and petition threshold" }],
6132
6993
  async run(c) {
@@ -6137,176 +6998,44 @@ forum.command("stats", {
6137
6998
 
6138
6999
  // src/commands/governance.ts
6139
7000
  import { TxError as TxError2 } from "@spectratools/tx-shared";
6140
- import { Cli as Cli3, z as z4 } from "incur";
6141
-
6142
- // src/services/governance.ts
6143
- var proposalStatusLabels = {
6144
- 0: "pending",
6145
- 1: "active",
6146
- 2: "passed",
6147
- 3: "executed",
6148
- 4: "defeated",
6149
- 5: "cancelled"
6150
- };
6151
- function proposalStatus(status) {
6152
- const statusCode = asNum(status);
6153
- return {
6154
- status: proposalStatusLabels[statusCode] ?? `unknown-${statusCode}`,
6155
- statusCode
6156
- };
6157
- }
6158
- function decodeProposal(value) {
6159
- const [
6160
- kind,
6161
- configRiskTier,
6162
- origin,
6163
- status,
6164
- proposer,
6165
- threadId,
6166
- petitionId,
6167
- createdAt,
6168
- deliberationEndsAt,
6169
- voteStartAt,
6170
- voteEndAt,
6171
- timelockEndsAt,
6172
- activeSeatsSnapshot,
6173
- forVotes,
6174
- againstVotes,
6175
- abstainVotes,
6176
- amount,
6177
- snapshotAssetBalance,
6178
- transferIntent,
6179
- intentDeadline,
6180
- intentMaxRiskTier,
6181
- title,
6182
- description
6183
- ] = value;
6184
- return {
6185
- kind,
6186
- configRiskTier,
6187
- origin,
6188
- status,
6189
- proposer: toChecksum(proposer),
6190
- threadId,
6191
- petitionId,
6192
- createdAt,
6193
- deliberationEndsAt,
6194
- voteStartAt,
6195
- voteEndAt,
6196
- timelockEndsAt,
6197
- activeSeatsSnapshot,
6198
- forVotes,
6199
- againstVotes,
6200
- abstainVotes,
6201
- amount,
6202
- snapshotAssetBalance,
6203
- transferIntent,
6204
- intentDeadline,
6205
- intentMaxRiskTier,
6206
- title,
6207
- description
6208
- };
6209
- }
6210
- function serializeProposal(proposal) {
6211
- const status = proposalStatus(proposal.status);
6212
- return {
6213
- kind: asNum(proposal.kind),
6214
- configRiskTier: asNum(proposal.configRiskTier),
6215
- origin: asNum(proposal.origin),
6216
- status: status.status,
6217
- statusCode: status.statusCode,
6218
- proposer: proposal.proposer,
6219
- threadId: asNum(proposal.threadId),
6220
- petitionId: asNum(proposal.petitionId),
6221
- createdAt: asNum(proposal.createdAt),
6222
- deliberationEndsAt: asNum(proposal.deliberationEndsAt),
6223
- voteStartAt: asNum(proposal.voteStartAt),
6224
- voteEndAt: asNum(proposal.voteEndAt),
6225
- timelockEndsAt: asNum(proposal.timelockEndsAt),
6226
- activeSeatsSnapshot: asNum(proposal.activeSeatsSnapshot),
6227
- forVotes: proposal.forVotes.toString(),
6228
- againstVotes: proposal.againstVotes.toString(),
6229
- abstainVotes: proposal.abstainVotes.toString(),
6230
- amount: proposal.amount.toString(),
6231
- snapshotAssetBalance: proposal.snapshotAssetBalance.toString(),
6232
- transferIntent: proposal.transferIntent,
6233
- intentDeadline: asNum(proposal.intentDeadline),
6234
- intentMaxRiskTier: asNum(proposal.intentMaxRiskTier),
6235
- title: proposal.title,
6236
- description: proposal.description
6237
- };
6238
- }
6239
- async function fetchProposalCount(client) {
6240
- return await client.readContract({
6241
- abi: governanceAbi,
6242
- address: ABSTRACT_MAINNET_ADDRESSES.governance,
6243
- functionName: "proposalCount"
6244
- });
6245
- }
6246
- async function fetchProposalById(client, id) {
6247
- return decodeProposal(
6248
- await client.readContract({
6249
- abi: governanceAbi,
6250
- address: ABSTRACT_MAINNET_ADDRESSES.governance,
6251
- functionName: "proposals",
6252
- args: [BigInt(id)]
6253
- })
6254
- );
6255
- }
6256
- async function fetchAllProposals(client) {
6257
- const count = await fetchProposalCount(client);
6258
- const ids = Array.from({ length: Number(count) }, (_, i) => BigInt(i + 1));
6259
- if (ids.length === 0) return [];
6260
- const proposalTuples = await client.multicall({
6261
- allowFailure: false,
6262
- contracts: ids.map((id) => ({
6263
- abi: governanceAbi,
6264
- address: ABSTRACT_MAINNET_ADDRESSES.governance,
6265
- functionName: "proposals",
6266
- args: [id]
6267
- }))
6268
- });
6269
- return proposalTuples.map(decodeProposal);
6270
- }
6271
-
6272
- // src/commands/governance.ts
6273
- var env3 = z4.object({
6274
- ABSTRACT_RPC_URL: z4.string().optional().describe("Abstract RPC URL override")
7001
+ import { Cli as Cli3, z as z6 } from "incur";
7002
+ var env3 = z6.object({
7003
+ ABSTRACT_RPC_URL: z6.string().optional().describe("Abstract RPC URL override")
6275
7004
  });
6276
- var timestampOutput3 = z4.union([z4.number(), z4.string()]);
7005
+ var timestampOutput3 = z6.union([z6.number(), z6.string()]);
6277
7006
  var PROPOSAL_STATUS_PENDING = 0;
6278
- var PROPOSAL_STATUS_ACTIVE = 1;
6279
- var PROPOSAL_STATUS_PASSED = 2;
6280
- var supportChoiceToValue = {
6281
- against: 0,
6282
- for: 1,
6283
- abstain: 2
6284
- };
6285
- var proposalOutputSchema = z4.object({
6286
- kind: z4.number(),
6287
- configRiskTier: z4.number(),
6288
- origin: z4.number(),
6289
- status: z4.string(),
6290
- statusCode: z4.number(),
6291
- proposer: z4.string(),
6292
- threadId: z4.number(),
6293
- petitionId: z4.number(),
6294
- createdAt: z4.number(),
6295
- deliberationEndsAt: z4.number(),
6296
- voteStartAt: z4.number(),
6297
- voteEndAt: z4.number(),
6298
- timelockEndsAt: z4.number(),
6299
- activeSeatsSnapshot: z4.number(),
6300
- forVotes: z4.string(),
6301
- againstVotes: z4.string(),
6302
- abstainVotes: z4.string(),
6303
- amount: z4.string(),
6304
- snapshotAssetBalance: z4.string(),
6305
- transferIntent: z4.boolean(),
6306
- intentDeadline: z4.number(),
6307
- intentMaxRiskTier: z4.number(),
6308
- title: z4.string(),
6309
- description: z4.string()
7007
+ var PROPOSAL_STATUS_ACTIVE = 1;
7008
+ var PROPOSAL_STATUS_PASSED = 2;
7009
+ var supportChoiceToValue = {
7010
+ against: 0,
7011
+ for: 1,
7012
+ abstain: 2
7013
+ };
7014
+ var proposalOutputSchema = z6.object({
7015
+ kind: z6.number(),
7016
+ configRiskTier: z6.number(),
7017
+ origin: z6.number(),
7018
+ status: z6.string(),
7019
+ statusCode: z6.number(),
7020
+ proposer: z6.string(),
7021
+ threadId: z6.number(),
7022
+ petitionId: z6.number(),
7023
+ createdAt: z6.number(),
7024
+ deliberationEndsAt: z6.number(),
7025
+ voteStartAt: z6.number(),
7026
+ voteEndAt: z6.number(),
7027
+ timelockEndsAt: z6.number(),
7028
+ activeSeatsSnapshot: z6.number(),
7029
+ forVotes: z6.string(),
7030
+ againstVotes: z6.string(),
7031
+ abstainVotes: z6.string(),
7032
+ amount: z6.string(),
7033
+ snapshotAssetBalance: z6.string(),
7034
+ transferIntent: z6.boolean(),
7035
+ intentDeadline: z6.number(),
7036
+ intentMaxRiskTier: z6.number(),
7037
+ title: z6.string(),
7038
+ description: z6.string()
6310
7039
  });
6311
7040
  var governance = Cli3.create("governance", {
6312
7041
  description: "Inspect Assembly governance proposals, votes, and parameters."
@@ -6314,19 +7043,19 @@ var governance = Cli3.create("governance", {
6314
7043
  governance.command("proposals", {
6315
7044
  description: "List governance proposals with status and vote end time.",
6316
7045
  env: env3,
6317
- output: z4.object({
6318
- proposals: z4.array(
6319
- z4.object({
6320
- id: z4.number(),
6321
- kind: z4.number(),
6322
- status: z4.string(),
6323
- statusCode: z4.number(),
6324
- title: z4.string().nullable().optional(),
7046
+ output: z6.object({
7047
+ proposals: z6.array(
7048
+ z6.object({
7049
+ id: z6.number(),
7050
+ kind: z6.number(),
7051
+ status: z6.string(),
7052
+ statusCode: z6.number(),
7053
+ title: z6.string().nullable().optional(),
6325
7054
  voteEndAt: timestampOutput3,
6326
- voteEndRelative: z4.string()
7055
+ voteEndRelative: z6.string()
6327
7056
  })
6328
7057
  ),
6329
- count: z4.number()
7058
+ count: z6.number()
6330
7059
  }),
6331
7060
  examples: [{ description: "List all proposals" }],
6332
7061
  async run(c) {
@@ -6362,8 +7091,8 @@ governance.command("proposals", {
6362
7091
  });
6363
7092
  governance.command("proposal", {
6364
7093
  description: "Get full raw proposal details by proposal id.",
6365
- args: z4.object({
6366
- id: z4.coerce.number().int().positive().describe("Proposal id (1-indexed)")
7094
+ args: z6.object({
7095
+ id: z6.coerce.number().int().positive().describe("Proposal id (1-indexed)")
6367
7096
  }),
6368
7097
  env: env3,
6369
7098
  output: proposalOutputSchema,
@@ -6384,15 +7113,15 @@ governance.command("proposal", {
6384
7113
  });
6385
7114
  governance.command("has-voted", {
6386
7115
  description: "Check if an address has voted on a proposal.",
6387
- args: z4.object({
6388
- proposalId: z4.coerce.number().int().positive().describe("Proposal id (1-indexed)"),
6389
- address: z4.string().describe("Voter address")
7116
+ args: z6.object({
7117
+ proposalId: z6.coerce.number().int().positive().describe("Proposal id (1-indexed)"),
7118
+ address: z6.string().describe("Voter address")
6390
7119
  }),
6391
7120
  env: env3,
6392
- output: z4.object({
6393
- proposalId: z4.number(),
6394
- address: z4.string(),
6395
- hasVoted: z4.boolean()
7121
+ output: z6.object({
7122
+ proposalId: z6.number(),
7123
+ address: z6.string(),
7124
+ hasVoted: z6.boolean()
6396
7125
  }),
6397
7126
  examples: [
6398
7127
  {
@@ -6421,19 +7150,19 @@ governance.command("has-voted", {
6421
7150
  governance.command("params", {
6422
7151
  description: "Read governance threshold and timing parameters.",
6423
7152
  env: env3,
6424
- output: z4.object({
6425
- deliberationPeriod: z4.number(),
6426
- votePeriod: z4.number(),
6427
- quorumBps: z4.number(),
6428
- constitutionalDeliberationPeriod: z4.number(),
6429
- constitutionalVotePeriod: z4.number(),
6430
- constitutionalPassBps: z4.number(),
6431
- majorPassBps: z4.number(),
6432
- parameterPassBps: z4.number(),
6433
- significantPassBps: z4.number(),
6434
- significantThresholdBps: z4.number(),
6435
- routineThresholdBps: z4.number(),
6436
- timelockPeriod: z4.number()
7153
+ output: z6.object({
7154
+ deliberationPeriod: z6.number(),
7155
+ votePeriod: z6.number(),
7156
+ quorumBps: z6.number(),
7157
+ constitutionalDeliberationPeriod: z6.number(),
7158
+ constitutionalVotePeriod: z6.number(),
7159
+ constitutionalPassBps: z6.number(),
7160
+ majorPassBps: z6.number(),
7161
+ parameterPassBps: z6.number(),
7162
+ significantPassBps: z6.number(),
7163
+ significantThresholdBps: z6.number(),
7164
+ routineThresholdBps: z6.number(),
7165
+ timelockPeriod: z6.number()
6437
7166
  }),
6438
7167
  examples: [{ description: "Inspect governance timing and pass thresholds" }],
6439
7168
  async run(c) {
@@ -6476,36 +7205,36 @@ governance.command("params", {
6476
7205
  });
6477
7206
  }
6478
7207
  });
6479
- var txResultOutput3 = z4.union([
6480
- z4.object({
6481
- status: z4.enum(["success", "reverted"]),
6482
- hash: z4.string(),
6483
- blockNumber: z4.number(),
6484
- gasUsed: z4.string(),
6485
- from: z4.string(),
6486
- to: z4.string().nullable(),
6487
- effectiveGasPrice: z4.string().optional()
7208
+ var txResultOutput3 = z6.union([
7209
+ z6.object({
7210
+ status: z6.enum(["success", "reverted"]),
7211
+ hash: z6.string(),
7212
+ blockNumber: z6.number(),
7213
+ gasUsed: z6.string(),
7214
+ from: z6.string(),
7215
+ to: z6.string().nullable(),
7216
+ effectiveGasPrice: z6.string().optional()
6488
7217
  }),
6489
- z4.object({
6490
- status: z4.literal("dry-run"),
6491
- estimatedGas: z4.string(),
6492
- simulationResult: z4.unknown()
7218
+ z6.object({
7219
+ status: z6.literal("dry-run"),
7220
+ estimatedGas: z6.string(),
7221
+ simulationResult: z6.unknown()
6493
7222
  })
6494
7223
  ]);
6495
7224
  governance.command("vote", {
6496
7225
  description: "Cast a governance vote on a proposal.",
6497
7226
  hint: "Requires PRIVATE_KEY environment variable for signing.",
6498
- args: z4.object({
6499
- proposalId: z4.coerce.number().int().positive().describe("Proposal id (1-indexed)"),
6500
- support: z4.enum(["for", "against", "abstain"]).describe("Vote support: for, against, or abstain")
7227
+ args: z6.object({
7228
+ proposalId: z6.coerce.number().int().positive().describe("Proposal id (1-indexed)"),
7229
+ support: z6.enum(["for", "against", "abstain"]).describe("Vote support: for, against, or abstain")
6501
7230
  }),
6502
7231
  options: writeOptions,
6503
7232
  env: writeEnv,
6504
- output: z4.object({
6505
- proposalId: z4.number(),
6506
- proposalTitle: z4.string(),
6507
- support: z4.enum(["for", "against", "abstain"]),
6508
- supportValue: z4.number(),
7233
+ output: z6.object({
7234
+ proposalId: z6.number(),
7235
+ proposalTitle: z6.string(),
7236
+ support: z6.enum(["for", "against", "abstain"]),
7237
+ supportValue: z6.number(),
6509
7238
  tx: txResultOutput3
6510
7239
  }),
6511
7240
  examples: [
@@ -6585,22 +7314,22 @@ governance.command("propose", {
6585
7314
  description: "Create a new council-originated governance proposal.",
6586
7315
  hint: "Requires PRIVATE_KEY environment variable for signing.",
6587
7316
  options: writeOptions.extend({
6588
- title: z4.string().min(1).describe("Proposal title"),
6589
- description: z4.string().min(1).describe("Proposal description"),
6590
- kind: z4.coerce.number().int().nonnegative().max(255).describe("Proposal kind enum value"),
6591
- category: z4.string().default("governance").describe("Forum category label for the proposal"),
6592
- "risk-tier": z4.coerce.number().int().nonnegative().max(255).optional().describe("Optional max allowed intent risk tier (default: 0)"),
6593
- amount: z4.string().optional().describe("Optional treasury amount hint (currently unsupported for intent encoding)"),
6594
- recipient: z4.string().optional().describe("Optional treasury recipient hint (currently unsupported for intent encoding)")
7317
+ title: z6.string().min(1).describe("Proposal title"),
7318
+ description: z6.string().min(1).describe("Proposal description"),
7319
+ kind: z6.coerce.number().int().nonnegative().max(255).describe("Proposal kind enum value"),
7320
+ category: z6.string().default("governance").describe("Forum category label for the proposal"),
7321
+ "risk-tier": z6.coerce.number().int().nonnegative().max(255).optional().describe("Optional max allowed intent risk tier (default: 0)"),
7322
+ amount: z6.string().optional().describe("Optional treasury amount hint (currently unsupported for intent encoding)"),
7323
+ recipient: z6.string().optional().describe("Optional treasury recipient hint (currently unsupported for intent encoding)")
6595
7324
  }),
6596
7325
  env: writeEnv,
6597
- output: z4.object({
6598
- proposer: z4.string(),
6599
- category: z4.string(),
6600
- kind: z4.number(),
6601
- title: z4.string(),
6602
- description: z4.string(),
6603
- expectedProposalId: z4.number(),
7326
+ output: z6.object({
7327
+ proposer: z6.string(),
7328
+ category: z6.string(),
7329
+ kind: z6.number(),
7330
+ title: z6.string(),
7331
+ description: z6.string(),
7332
+ expectedProposalId: z6.number(),
6604
7333
  tx: txResultOutput3
6605
7334
  }),
6606
7335
  examples: [
@@ -6689,15 +7418,15 @@ governance.command("propose", {
6689
7418
  governance.command("queue", {
6690
7419
  description: "Finalize voting and queue an eligible proposal into timelock.",
6691
7420
  hint: "Requires PRIVATE_KEY environment variable for signing.",
6692
- args: z4.object({
6693
- proposalId: z4.coerce.number().int().positive().describe("Proposal id (1-indexed)")
7421
+ args: z6.object({
7422
+ proposalId: z6.coerce.number().int().positive().describe("Proposal id (1-indexed)")
6694
7423
  }),
6695
7424
  options: writeOptions,
6696
7425
  env: writeEnv,
6697
- output: z4.object({
6698
- proposalId: z4.number(),
6699
- proposalTitle: z4.string(),
6700
- statusBefore: z4.string(),
7426
+ output: z6.object({
7427
+ proposalId: z6.number(),
7428
+ proposalTitle: z6.string(),
7429
+ statusBefore: z6.string(),
6701
7430
  tx: txResultOutput3
6702
7431
  }),
6703
7432
  examples: [
@@ -6732,308 +7461,133 @@ governance.command("queue", {
6732
7461
  retryable: false
6733
7462
  });
6734
7463
  }
6735
- if (status.statusCode !== PROPOSAL_STATUS_ACTIVE) {
6736
- return c.error({
6737
- code: "PROPOSAL_NOT_QUEUEABLE",
6738
- message: `Proposal ${c.args.proposalId} is ${status.status} and cannot be queued.`,
6739
- retryable: false
6740
- });
6741
- }
6742
- const latestBlock = await client.getBlock({ blockTag: "latest" });
6743
- if (latestBlock.timestamp < proposal.voteEndAt) {
6744
- return c.error({
6745
- code: "VOTING_STILL_ACTIVE",
6746
- message: `Proposal ${c.args.proposalId} voting window is still open (ends ${relTime(proposal.voteEndAt)}).`,
6747
- retryable: false
6748
- });
6749
- }
6750
- try {
6751
- const txResult = await assemblyWriteTx({
6752
- env: c.env,
6753
- options: c.options,
6754
- address: ABSTRACT_MAINNET_ADDRESSES.governance,
6755
- abi: governanceAbi,
6756
- functionName: "finalizeVote",
6757
- args: [BigInt(c.args.proposalId)]
6758
- });
6759
- return c.ok({
6760
- proposalId: c.args.proposalId,
6761
- proposalTitle: proposal.title,
6762
- statusBefore: status.status,
6763
- tx: txResult
6764
- });
6765
- } catch (error) {
6766
- if (error instanceof TxError2) {
6767
- return c.error({
6768
- code: error.code,
6769
- message: error.message,
6770
- retryable: error.code === "NONCE_CONFLICT"
6771
- });
6772
- }
6773
- throw error;
6774
- }
6775
- }
6776
- });
6777
- governance.command("execute", {
6778
- description: "Execute a queued governance proposal after timelock expiry.",
6779
- hint: "Requires PRIVATE_KEY environment variable for signing.",
6780
- args: z4.object({
6781
- proposalId: z4.coerce.number().int().positive().describe("Proposal id (1-indexed)")
6782
- }),
6783
- options: writeOptions,
6784
- env: writeEnv,
6785
- output: z4.object({
6786
- proposalId: z4.number(),
6787
- proposalTitle: z4.string(),
6788
- timelockEndsAt: timestampOutput3,
6789
- tx: txResultOutput3
6790
- }),
6791
- examples: [
6792
- {
6793
- args: { proposalId: 1 },
6794
- description: "Execute proposal #1 after timelock has expired"
6795
- }
6796
- ],
6797
- async run(c) {
6798
- const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
6799
- const proposalCount = await fetchProposalCount(client);
6800
- if (c.args.proposalId > Number(proposalCount)) {
6801
- return c.error({
6802
- code: "OUT_OF_RANGE",
6803
- message: `Proposal id ${c.args.proposalId} does not exist (proposalCount: ${proposalCount})`,
6804
- retryable: false
6805
- });
6806
- }
6807
- const proposal = await fetchProposalById(client, c.args.proposalId);
6808
- const status = proposalStatus(proposal.status);
6809
- if (status.statusCode !== PROPOSAL_STATUS_PASSED) {
6810
- return c.error({
6811
- code: "PROPOSAL_NOT_EXECUTABLE",
6812
- message: `Proposal ${c.args.proposalId} is ${status.status} and cannot be executed.`,
6813
- retryable: false
6814
- });
6815
- }
6816
- const latestBlock = await client.getBlock({ blockTag: "latest" });
6817
- if (latestBlock.timestamp < proposal.timelockEndsAt) {
6818
- return c.error({
6819
- code: "TIMELOCK_ACTIVE",
6820
- message: `Proposal ${c.args.proposalId} timelock has not expired yet (ends ${relTime(proposal.timelockEndsAt)}).`,
6821
- retryable: false
6822
- });
6823
- }
6824
- try {
6825
- const txResult = await assemblyWriteTx({
6826
- env: c.env,
6827
- options: c.options,
6828
- address: ABSTRACT_MAINNET_ADDRESSES.governance,
6829
- abi: governanceAbi,
6830
- functionName: "executeProposal",
6831
- args: [BigInt(c.args.proposalId)]
6832
- });
6833
- return c.ok({
6834
- proposalId: c.args.proposalId,
6835
- proposalTitle: proposal.title,
6836
- timelockEndsAt: timeValue(proposal.timelockEndsAt, c.format),
6837
- tx: txResult
6838
- });
6839
- } catch (error) {
6840
- if (error instanceof TxError2) {
6841
- return c.error({
6842
- code: error.code,
6843
- message: error.message,
6844
- retryable: error.code === "NONCE_CONFLICT"
6845
- });
6846
- }
6847
- throw error;
6848
- }
6849
- }
6850
- });
6851
-
6852
- // src/commands/members.ts
6853
- import { TxError as TxError3 } from "@spectratools/tx-shared";
6854
- import { Cli as Cli4, z as z6 } from "incur";
6855
-
6856
- // src/services/members.ts
6857
- import { z as z5 } from "incur";
6858
- var DEFAULT_MEMBER_SNAPSHOT_URL = "https://www.theaiassembly.org/api/indexer/members";
6859
- var REGISTERED_EVENT_SCAN_STEP = 100000n;
6860
- var REGISTERED_EVENT_SCAN_TIMEOUT_MS = 2e4;
6861
- var memberSnapshotEntrySchema = z5.union([
6862
- z5.string(),
6863
- z5.object({
6864
- address: z5.string(),
6865
- ens: z5.string().optional(),
6866
- name: z5.string().optional()
6867
- })
6868
- ]);
6869
- var memberSnapshotSchema = z5.array(memberSnapshotEntrySchema);
6870
- var AssemblyApiValidationError = class extends Error {
6871
- constructor(details) {
6872
- super("Assembly API response validation failed");
6873
- this.details = details;
6874
- this.name = "AssemblyApiValidationError";
6875
- }
6876
- };
6877
- var AssemblyIndexerUnavailableError = class extends Error {
6878
- constructor(details) {
6879
- super("Assembly indexer unavailable");
6880
- this.details = details;
6881
- this.name = "AssemblyIndexerUnavailableError";
6882
- }
6883
- };
6884
- function memberSnapshotEntryToIdentity(entry) {
6885
- if (typeof entry === "string") return { address: entry };
6886
- const identity = { address: entry.address };
6887
- if (entry.ens !== void 0) identity.ens = entry.ens;
6888
- if (entry.name !== void 0) identity.name = entry.name;
6889
- return identity;
6890
- }
6891
- function mergeMemberIdentities(entries) {
6892
- const byAddress = /* @__PURE__ */ new Map();
6893
- for (const entry of entries) {
6894
- const key = entry.address.toLowerCase();
6895
- const existing = byAddress.get(key);
6896
- if (!existing) {
6897
- byAddress.set(key, entry);
6898
- continue;
6899
- }
6900
- const merged = { address: existing.address };
6901
- const ens = existing.ens ?? entry.ens;
6902
- const name = existing.name ?? entry.name;
6903
- if (ens !== void 0) merged.ens = ens;
6904
- if (name !== void 0) merged.name = name;
6905
- byAddress.set(key, merged);
6906
- }
6907
- return [...byAddress.values()];
6908
- }
6909
- async function memberSnapshot(url) {
6910
- let res;
6911
- try {
6912
- res = await fetch(url);
6913
- } catch (error) {
6914
- throw new AssemblyIndexerUnavailableError({
6915
- code: "ASSEMBLY_INDEXER_UNAVAILABLE",
6916
- url,
6917
- reason: error instanceof Error ? error.message : String(error)
6918
- });
6919
- }
6920
- if (!res.ok) {
6921
- throw new AssemblyIndexerUnavailableError({
6922
- code: "ASSEMBLY_INDEXER_UNAVAILABLE",
6923
- url,
6924
- status: res.status,
6925
- statusText: res.statusText
6926
- });
6927
- }
6928
- const json = await res.json();
6929
- const parsed = memberSnapshotSchema.safeParse(json);
6930
- if (parsed.success) {
6931
- return mergeMemberIdentities(parsed.data.map(memberSnapshotEntryToIdentity));
6932
- }
6933
- throw new AssemblyApiValidationError({
6934
- code: "INVALID_ASSEMBLY_API_RESPONSE",
6935
- url,
6936
- issues: parsed.error.issues,
6937
- response: json
6938
- });
6939
- }
6940
- async function withTimeout(promise, timeoutMs, timeoutMessage) {
6941
- let timer;
6942
- try {
6943
- return await Promise.race([
6944
- promise,
6945
- new Promise((_, reject) => {
6946
- timer = setTimeout(() => {
6947
- reject(new Error(timeoutMessage));
6948
- }, timeoutMs);
6949
- })
6950
- ]);
6951
- } finally {
6952
- if (timer) clearTimeout(timer);
6953
- }
6954
- }
6955
- async function membersFromRegisteredEvents(client) {
6956
- const latestBlock = await client.getBlockNumber();
6957
- const addresses = /* @__PURE__ */ new Set();
6958
- for (let fromBlock = ABSTRACT_MAINNET_DEPLOYMENT_BLOCKS.registry; fromBlock <= latestBlock; fromBlock += REGISTERED_EVENT_SCAN_STEP) {
6959
- const toBlock = fromBlock + REGISTERED_EVENT_SCAN_STEP - 1n > latestBlock ? latestBlock : fromBlock + REGISTERED_EVENT_SCAN_STEP - 1n;
6960
- const events = await client.getContractEvents({
6961
- abi: registryAbi,
6962
- address: ABSTRACT_MAINNET_ADDRESSES.registry,
6963
- eventName: "Registered",
6964
- fromBlock,
6965
- toBlock,
6966
- strict: true
6967
- });
6968
- for (const event of events) {
6969
- const member = event.args.member;
6970
- if (typeof member === "string") {
6971
- addresses.add(member);
6972
- }
7464
+ if (status.statusCode !== PROPOSAL_STATUS_ACTIVE) {
7465
+ return c.error({
7466
+ code: "PROPOSAL_NOT_QUEUEABLE",
7467
+ message: `Proposal ${c.args.proposalId} is ${status.status} and cannot be queued.`,
7468
+ retryable: false
7469
+ });
6973
7470
  }
6974
- }
6975
- return [...addresses].map((address) => ({ address }));
6976
- }
6977
- async function fetchMemberList(client, snapshotUrl) {
6978
- const url = snapshotUrl ?? DEFAULT_MEMBER_SNAPSHOT_URL;
6979
- try {
6980
- return { members: await memberSnapshot(url) };
6981
- } catch (error) {
6982
- if (error instanceof AssemblyApiValidationError) {
6983
- throw error;
7471
+ const latestBlock = await client.getBlock({ blockTag: "latest" });
7472
+ if (latestBlock.timestamp < proposal.voteEndAt) {
7473
+ return c.error({
7474
+ code: "VOTING_STILL_ACTIVE",
7475
+ message: `Proposal ${c.args.proposalId} voting window is still open (ends ${relTime(proposal.voteEndAt)}).`,
7476
+ retryable: false
7477
+ });
6984
7478
  }
6985
- if (!(error instanceof AssemblyIndexerUnavailableError)) {
7479
+ try {
7480
+ const txResult = await assemblyWriteTx({
7481
+ env: c.env,
7482
+ options: c.options,
7483
+ address: ABSTRACT_MAINNET_ADDRESSES.governance,
7484
+ abi: governanceAbi,
7485
+ functionName: "finalizeVote",
7486
+ args: [BigInt(c.args.proposalId)]
7487
+ });
7488
+ return c.ok({
7489
+ proposalId: c.args.proposalId,
7490
+ proposalTitle: proposal.title,
7491
+ statusBefore: status.status,
7492
+ tx: txResult
7493
+ });
7494
+ } catch (error) {
7495
+ if (error instanceof TxError2) {
7496
+ return c.error({
7497
+ code: error.code,
7498
+ message: error.message,
7499
+ retryable: error.code === "NONCE_CONFLICT"
7500
+ });
7501
+ }
6986
7502
  throw error;
6987
7503
  }
6988
- const fallbackMembers = await withTimeout(
6989
- membersFromRegisteredEvents(client),
6990
- REGISTERED_EVENT_SCAN_TIMEOUT_MS,
6991
- `Registered event fallback scan timed out after ${REGISTERED_EVENT_SCAN_TIMEOUT_MS}ms`
6992
- );
6993
- return {
6994
- members: mergeMemberIdentities(fallbackMembers),
6995
- fallbackReason: error.details
6996
- };
6997
7504
  }
6998
- }
6999
- async function fetchMemberOnchainState(client, addresses) {
7000
- if (addresses.length === 0) return [];
7001
- const calls = addresses.flatMap((address) => [
7002
- {
7003
- abi: registryAbi,
7004
- address: ABSTRACT_MAINNET_ADDRESSES.registry,
7005
- functionName: "isActive",
7006
- args: [address]
7007
- },
7505
+ });
7506
+ governance.command("execute", {
7507
+ description: "Execute a queued governance proposal after timelock expiry.",
7508
+ hint: "Requires PRIVATE_KEY environment variable for signing.",
7509
+ args: z6.object({
7510
+ proposalId: z6.coerce.number().int().positive().describe("Proposal id (1-indexed)")
7511
+ }),
7512
+ options: writeOptions,
7513
+ env: writeEnv,
7514
+ output: z6.object({
7515
+ proposalId: z6.number(),
7516
+ proposalTitle: z6.string(),
7517
+ timelockEndsAt: timestampOutput3,
7518
+ tx: txResultOutput3
7519
+ }),
7520
+ examples: [
7008
7521
  {
7009
- abi: registryAbi,
7010
- address: ABSTRACT_MAINNET_ADDRESSES.registry,
7011
- functionName: "members",
7012
- args: [address]
7522
+ args: { proposalId: 1 },
7523
+ description: "Execute proposal #1 after timelock has expired"
7013
7524
  }
7014
- ]);
7015
- const values = await client.multicall({ allowFailure: false, contracts: calls });
7016
- return addresses.map((address, i) => {
7017
- const active = values[i * 2];
7018
- const info = values[i * 2 + 1];
7019
- return {
7020
- address: toChecksum(address),
7021
- active,
7022
- registered: info.registered,
7023
- activeUntil: info.activeUntil,
7024
- lastHeartbeatAt: info.lastHeartbeatAt
7025
- };
7026
- });
7027
- }
7525
+ ],
7526
+ async run(c) {
7527
+ const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
7528
+ const proposalCount = await fetchProposalCount(client);
7529
+ if (c.args.proposalId > Number(proposalCount)) {
7530
+ return c.error({
7531
+ code: "OUT_OF_RANGE",
7532
+ message: `Proposal id ${c.args.proposalId} does not exist (proposalCount: ${proposalCount})`,
7533
+ retryable: false
7534
+ });
7535
+ }
7536
+ const proposal = await fetchProposalById(client, c.args.proposalId);
7537
+ const status = proposalStatus(proposal.status);
7538
+ if (status.statusCode !== PROPOSAL_STATUS_PASSED) {
7539
+ return c.error({
7540
+ code: "PROPOSAL_NOT_EXECUTABLE",
7541
+ message: `Proposal ${c.args.proposalId} is ${status.status} and cannot be executed.`,
7542
+ retryable: false
7543
+ });
7544
+ }
7545
+ const latestBlock = await client.getBlock({ blockTag: "latest" });
7546
+ if (latestBlock.timestamp < proposal.timelockEndsAt) {
7547
+ return c.error({
7548
+ code: "TIMELOCK_ACTIVE",
7549
+ message: `Proposal ${c.args.proposalId} timelock has not expired yet (ends ${relTime(proposal.timelockEndsAt)}).`,
7550
+ retryable: false
7551
+ });
7552
+ }
7553
+ try {
7554
+ const txResult = await assemblyWriteTx({
7555
+ env: c.env,
7556
+ options: c.options,
7557
+ address: ABSTRACT_MAINNET_ADDRESSES.governance,
7558
+ abi: governanceAbi,
7559
+ functionName: "executeProposal",
7560
+ args: [BigInt(c.args.proposalId)]
7561
+ });
7562
+ return c.ok({
7563
+ proposalId: c.args.proposalId,
7564
+ proposalTitle: proposal.title,
7565
+ timelockEndsAt: timeValue(proposal.timelockEndsAt, c.format),
7566
+ tx: txResult
7567
+ });
7568
+ } catch (error) {
7569
+ if (error instanceof TxError2) {
7570
+ return c.error({
7571
+ code: error.code,
7572
+ message: error.message,
7573
+ retryable: error.code === "NONCE_CONFLICT"
7574
+ });
7575
+ }
7576
+ throw error;
7577
+ }
7578
+ }
7579
+ });
7028
7580
 
7029
7581
  // src/commands/members.ts
7582
+ import { TxError as TxError3 } from "@spectratools/tx-shared";
7583
+ import { Cli as Cli4, z as z7 } from "incur";
7030
7584
  var DEFAULT_MEMBER_SNAPSHOT_URL2 = "https://www.theaiassembly.org/api/indexer/members";
7031
7585
  var MAX_MEMBER_LOOKUP_SUGGESTIONS = 5;
7032
- var env4 = z6.object({
7033
- ABSTRACT_RPC_URL: z6.string().optional().describe("Abstract RPC URL override"),
7034
- ASSEMBLY_INDEXER_URL: z6.string().optional().describe("Optional members snapshot endpoint (default: theaiassembly.org indexer)")
7586
+ var env4 = z7.object({
7587
+ ABSTRACT_RPC_URL: z7.string().optional().describe("Abstract RPC URL override"),
7588
+ ASSEMBLY_INDEXER_URL: z7.string().optional().describe("Optional members snapshot endpoint (default: theaiassembly.org indexer)")
7035
7589
  });
7036
- var timestampOutput4 = z6.union([z6.number(), z6.string()]);
7590
+ var timestampOutput4 = z7.union([z7.number(), z7.string()]);
7037
7591
  function matchableAddressInput(query) {
7038
7592
  return query.startsWith("0x") && query.length === 42;
7039
7593
  }
@@ -7079,19 +7633,19 @@ var members = Cli4.create("members", {
7079
7633
  members.command("list", {
7080
7634
  description: "List members from an indexer snapshot (or Registered event fallback) plus on-chain active state.",
7081
7635
  env: env4,
7082
- output: z6.object({
7083
- members: z6.array(
7084
- z6.object({
7085
- address: z6.string(),
7086
- active: z6.boolean(),
7087
- registered: z6.boolean(),
7636
+ output: z7.object({
7637
+ members: z7.array(
7638
+ z7.object({
7639
+ address: z7.string(),
7640
+ active: z7.boolean(),
7641
+ registered: z7.boolean(),
7088
7642
  activeUntil: timestampOutput4,
7089
- activeUntilRelative: z6.string(),
7643
+ activeUntilRelative: z7.string(),
7090
7644
  lastHeartbeatAt: timestampOutput4,
7091
- lastHeartbeatRelative: z6.string()
7645
+ lastHeartbeatRelative: z7.string()
7092
7646
  })
7093
7647
  ),
7094
- count: z6.number()
7648
+ count: z7.number()
7095
7649
  }),
7096
7650
  examples: [
7097
7651
  { description: "List members using default indexer snapshot" },
@@ -7145,17 +7699,17 @@ members.command("list", {
7145
7699
  });
7146
7700
  members.command("info", {
7147
7701
  description: "Get member registry record and active status by full address, partial address, ENS, or name.",
7148
- args: z6.object({
7149
- address: z6.string().describe("Member lookup query (full/partial address, ENS, or name metadata)")
7702
+ args: z7.object({
7703
+ address: z7.string().describe("Member lookup query (full/partial address, ENS, or name metadata)")
7150
7704
  }),
7151
7705
  env: env4,
7152
- output: z6.object({
7153
- address: z6.string(),
7154
- active: z6.boolean(),
7706
+ output: z7.object({
7707
+ address: z7.string(),
7708
+ active: z7.boolean(),
7155
7709
  activeUntil: timestampOutput4,
7156
7710
  lastHeartbeatAt: timestampOutput4,
7157
- activeUntilRelative: z6.string(),
7158
- lastHeartbeatRelative: z6.string()
7711
+ activeUntilRelative: z7.string(),
7712
+ lastHeartbeatRelative: z7.string()
7159
7713
  }),
7160
7714
  examples: [
7161
7715
  {
@@ -7240,9 +7794,9 @@ members.command("info", {
7240
7794
  members.command("count", {
7241
7795
  description: "Get active and total-known member counts from Registry.",
7242
7796
  env: env4,
7243
- output: z6.object({
7244
- active: z6.number(),
7245
- total: z6.number()
7797
+ output: z7.object({
7798
+ active: z7.number(),
7799
+ total: z7.number()
7246
7800
  }),
7247
7801
  examples: [{ description: "Count active and known members" }],
7248
7802
  async run(c) {
@@ -7265,12 +7819,12 @@ members.command("count", {
7265
7819
  members.command("fees", {
7266
7820
  description: "Get registration and heartbeat fee settings.",
7267
7821
  env: env4,
7268
- output: z6.object({
7269
- registrationFeeWei: z6.string(),
7270
- registrationFee: z6.string(),
7271
- heartbeatFeeWei: z6.string(),
7272
- heartbeatFee: z6.string(),
7273
- heartbeatGracePeriodSeconds: z6.number()
7822
+ output: z7.object({
7823
+ registrationFeeWei: z7.string(),
7824
+ registrationFee: z7.string(),
7825
+ heartbeatFeeWei: z7.string(),
7826
+ heartbeatFee: z7.string(),
7827
+ heartbeatGracePeriodSeconds: z7.number()
7274
7828
  }),
7275
7829
  examples: [{ description: "Inspect current registry fee configuration" }],
7276
7830
  async run(c) {
@@ -7301,24 +7855,24 @@ members.command("fees", {
7301
7855
  });
7302
7856
  }
7303
7857
  });
7304
- var txOutputSchema = z6.union([
7305
- z6.object({
7306
- status: z6.enum(["success", "reverted"]),
7307
- hash: z6.string(),
7308
- blockNumber: z6.number(),
7309
- gasUsed: z6.string(),
7310
- from: z6.string(),
7311
- to: z6.string().nullable(),
7312
- effectiveGasPrice: z6.string().optional(),
7313
- fee: z6.string(),
7314
- feeEth: z6.string()
7858
+ var txOutputSchema = z7.union([
7859
+ z7.object({
7860
+ status: z7.enum(["success", "reverted"]),
7861
+ hash: z7.string(),
7862
+ blockNumber: z7.number(),
7863
+ gasUsed: z7.string(),
7864
+ from: z7.string(),
7865
+ to: z7.string().nullable(),
7866
+ effectiveGasPrice: z7.string().optional(),
7867
+ fee: z7.string(),
7868
+ feeEth: z7.string()
7315
7869
  }),
7316
- z6.object({
7317
- status: z6.literal("dry-run"),
7318
- estimatedGas: z6.string(),
7319
- simulationResult: z6.unknown(),
7320
- fee: z6.string(),
7321
- feeEth: z6.string()
7870
+ z7.object({
7871
+ status: z7.literal("dry-run"),
7872
+ estimatedGas: z7.string(),
7873
+ simulationResult: z7.unknown(),
7874
+ fee: z7.string(),
7875
+ feeEth: z7.string()
7322
7876
  })
7323
7877
  ]);
7324
7878
  members.command("register", {
@@ -7475,49 +8029,109 @@ members.command("renew", {
7475
8029
  }
7476
8030
  });
7477
8031
 
8032
+ // src/commands/seats.ts
8033
+ import { Cli as Cli5, z as z8 } from "incur";
8034
+ var env5 = z8.object({
8035
+ ABSTRACT_RPC_URL: z8.string().optional().describe("Abstract RPC URL override")
8036
+ });
8037
+ var timestampOutput5 = z8.union([z8.number(), z8.string()]);
8038
+ function decodeSeat2(value) {
8039
+ const [owner, startAt, endAt, forfeited] = value;
8040
+ return { owner, startAt, endAt, forfeited };
8041
+ }
8042
+ var seats = Cli5.create("seats", {
8043
+ description: "Council seat aliases (compatibility shim for council seats)."
8044
+ });
8045
+ seats.command("list", {
8046
+ description: "List all council seats and their occupancy windows (alias for council seats).",
8047
+ env: env5,
8048
+ output: z8.array(
8049
+ z8.object({
8050
+ id: z8.number(),
8051
+ owner: z8.string(),
8052
+ startAt: timestampOutput5,
8053
+ startAtRelative: z8.string(),
8054
+ endAt: timestampOutput5,
8055
+ endAtRelative: z8.string(),
8056
+ forfeited: z8.boolean()
8057
+ })
8058
+ ),
8059
+ examples: [{ description: "List all council seats" }],
8060
+ async run(c) {
8061
+ const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
8062
+ const count = await client.readContract({
8063
+ abi: councilSeatsAbi,
8064
+ address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
8065
+ functionName: "seatCount"
8066
+ });
8067
+ const ids = Array.from({ length: Number(count) }, (_, i) => BigInt(i));
8068
+ const seatTuples = ids.length ? await client.multicall({
8069
+ allowFailure: false,
8070
+ contracts: ids.map((id) => ({
8071
+ abi: councilSeatsAbi,
8072
+ address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
8073
+ functionName: "seats",
8074
+ args: [id]
8075
+ }))
8076
+ }) : [];
8077
+ const seatList = seatTuples.map(decodeSeat2);
8078
+ return c.ok(
8079
+ seatList.map((seat, idx) => ({
8080
+ id: idx,
8081
+ owner: toChecksum(seat.owner),
8082
+ startAt: timeValue(seat.startAt, c.format),
8083
+ startAtRelative: relTime(seat.startAt),
8084
+ endAt: timeValue(seat.endAt, c.format),
8085
+ endAtRelative: relTime(seat.endAt),
8086
+ forfeited: seat.forfeited
8087
+ }))
8088
+ );
8089
+ }
8090
+ });
8091
+
7478
8092
  // src/commands/treasury.ts
7479
8093
  import { TxError as TxError4 } from "@spectratools/tx-shared";
7480
- import { Cli as Cli5, z as z7 } from "incur";
8094
+ import { Cli as Cli6, z as z9 } from "incur";
7481
8095
  import { encodeAbiParameters, parseUnits, zeroAddress } from "viem";
7482
- var env5 = z7.object({
7483
- ABSTRACT_RPC_URL: z7.string().optional().describe("Abstract RPC URL override")
8096
+ var env6 = z9.object({
8097
+ ABSTRACT_RPC_URL: z9.string().optional().describe("Abstract RPC URL override")
7484
8098
  });
7485
- var timestampOutput5 = z7.union([z7.number(), z7.string()]);
7486
- var txResultOutput4 = z7.union([
7487
- z7.object({
7488
- status: z7.literal("success"),
7489
- hash: z7.string(),
7490
- blockNumber: z7.number(),
7491
- gasUsed: z7.string(),
7492
- from: z7.string(),
7493
- to: z7.string().nullable(),
7494
- effectiveGasPrice: z7.string().optional()
8099
+ var timestampOutput6 = z9.union([z9.number(), z9.string()]);
8100
+ var txResultOutput4 = z9.union([
8101
+ z9.object({
8102
+ status: z9.literal("success"),
8103
+ hash: z9.string(),
8104
+ blockNumber: z9.number(),
8105
+ gasUsed: z9.string(),
8106
+ from: z9.string(),
8107
+ to: z9.string().nullable(),
8108
+ effectiveGasPrice: z9.string().optional()
7495
8109
  }),
7496
- z7.object({
7497
- status: z7.literal("reverted"),
7498
- hash: z7.string(),
7499
- blockNumber: z7.number(),
7500
- gasUsed: z7.string(),
7501
- from: z7.string(),
7502
- to: z7.string().nullable(),
7503
- effectiveGasPrice: z7.string().optional()
8110
+ z9.object({
8111
+ status: z9.literal("reverted"),
8112
+ hash: z9.string(),
8113
+ blockNumber: z9.number(),
8114
+ gasUsed: z9.string(),
8115
+ from: z9.string(),
8116
+ to: z9.string().nullable(),
8117
+ effectiveGasPrice: z9.string().optional()
7504
8118
  }),
7505
- z7.object({
7506
- status: z7.literal("dry-run"),
7507
- estimatedGas: z7.string(),
7508
- simulationResult: z7.unknown()
8119
+ z9.object({
8120
+ status: z9.literal("dry-run"),
8121
+ estimatedGas: z9.string(),
8122
+ simulationResult: z9.unknown()
7509
8123
  })
7510
8124
  ]);
7511
- var treasury = Cli5.create("treasury", {
8125
+ var treasury = Cli6.create("treasury", {
7512
8126
  description: "Inspect treasury balances, execution status, and spend controls."
7513
8127
  });
7514
8128
  treasury.command("balance", {
7515
8129
  description: "Get current native token balance for the treasury contract.",
7516
- env: env5,
7517
- output: z7.object({
7518
- address: z7.string(),
7519
- balanceWei: z7.string(),
7520
- balance: z7.string()
8130
+ env: env6,
8131
+ output: z9.object({
8132
+ address: z9.string(),
8133
+ balanceWei: z9.string(),
8134
+ balance: z9.string()
7521
8135
  }),
7522
8136
  examples: [{ description: "Check treasury balance" }],
7523
8137
  async run(c) {
@@ -7532,13 +8146,13 @@ treasury.command("balance", {
7532
8146
  });
7533
8147
  treasury.command("whitelist", {
7534
8148
  description: "Check whether an asset address is treasury-whitelisted.",
7535
- args: z7.object({
7536
- asset: z7.string().describe("Token/asset contract address")
8149
+ args: z9.object({
8150
+ asset: z9.string().describe("Token/asset contract address")
7537
8151
  }),
7538
- env: env5,
7539
- output: z7.object({
7540
- asset: z7.string(),
7541
- whitelisted: z7.boolean()
8152
+ env: env6,
8153
+ output: z9.object({
8154
+ asset: z9.string(),
8155
+ whitelisted: z9.boolean()
7542
8156
  }),
7543
8157
  examples: [
7544
8158
  {
@@ -7559,12 +8173,12 @@ treasury.command("whitelist", {
7559
8173
  });
7560
8174
  treasury.command("major-spend-status", {
7561
8175
  description: "Read major-spend cooldown status for the treasury contract.",
7562
- env: env5,
7563
- output: z7.object({
7564
- majorSpendCooldownSeconds: z7.number(),
7565
- lastMajorSpendAt: timestampOutput5,
7566
- lastMajorSpendRelative: z7.string(),
7567
- isMajorSpendAllowed: z7.boolean()
8176
+ env: env6,
8177
+ output: z9.object({
8178
+ majorSpendCooldownSeconds: z9.number(),
8179
+ lastMajorSpendAt: timestampOutput6,
8180
+ lastMajorSpendRelative: z9.string(),
8181
+ isMajorSpendAllowed: z9.boolean()
7568
8182
  }),
7569
8183
  examples: [{ description: "Inspect treasury major-spend guardrails" }],
7570
8184
  async run(c) {
@@ -7598,13 +8212,13 @@ treasury.command("major-spend-status", {
7598
8212
  });
7599
8213
  treasury.command("executed", {
7600
8214
  description: "Check whether a treasury action for a proposal has executed.",
7601
- args: z7.object({
7602
- proposalId: z7.coerce.number().int().positive().describe("Governance proposal id")
8215
+ args: z9.object({
8216
+ proposalId: z9.coerce.number().int().positive().describe("Governance proposal id")
7603
8217
  }),
7604
- env: env5,
7605
- output: z7.object({
7606
- proposalId: z7.number(),
7607
- executed: z7.boolean()
8218
+ env: env6,
8219
+ output: z9.object({
8220
+ proposalId: z9.number(),
8221
+ executed: z9.boolean()
7608
8222
  }),
7609
8223
  examples: [{ args: { proposalId: 1 }, description: "Check execution status for proposal #1" }],
7610
8224
  async run(c) {
@@ -7634,25 +8248,25 @@ treasury.command("propose-spend", {
7634
8248
  description: "Create a council proposal that spends treasury funds via TreasuryTransferIntentModule.",
7635
8249
  hint: "Requires PRIVATE_KEY environment variable for signing.",
7636
8250
  options: writeOptions.extend({
7637
- token: z7.string().describe("Token address to spend (use 0x0000000000000000000000000000000000000000 for ETH)"),
7638
- recipient: z7.string().describe("Recipient address"),
7639
- amount: z7.string().describe("Token amount as decimal string (human units)"),
7640
- decimals: z7.coerce.number().int().min(0).max(36).default(18).describe("Token decimals used to parse --amount (default: 18)"),
7641
- title: z7.string().min(1).describe("Proposal title"),
7642
- description: z7.string().min(1).describe("Proposal description"),
7643
- category: z7.string().default("treasury").describe("Forum category label for this proposal"),
7644
- "risk-tier": z7.coerce.number().int().min(0).max(3).default(3).describe("Max allowed risk tier in intent constraints (0-3, default: 3)")
8251
+ token: z9.string().describe("Token address to spend (use 0x0000000000000000000000000000000000000000 for ETH)"),
8252
+ recipient: z9.string().describe("Recipient address"),
8253
+ amount: z9.string().describe("Token amount as decimal string (human units)"),
8254
+ decimals: z9.coerce.number().int().min(0).max(36).default(18).describe("Token decimals used to parse --amount (default: 18)"),
8255
+ title: z9.string().min(1).describe("Proposal title"),
8256
+ description: z9.string().min(1).describe("Proposal description"),
8257
+ category: z9.string().default("treasury").describe("Forum category label for this proposal"),
8258
+ "risk-tier": z9.coerce.number().int().min(0).max(3).default(3).describe("Max allowed risk tier in intent constraints (0-3, default: 3)")
7645
8259
  }),
7646
8260
  env: writeEnv,
7647
- output: z7.object({
7648
- proposer: z7.string(),
7649
- category: z7.string(),
7650
- token: z7.string(),
7651
- recipient: z7.string(),
7652
- amount: z7.string(),
7653
- amountWei: z7.string(),
7654
- expectedProposalId: z7.number(),
7655
- expectedThreadId: z7.number(),
8261
+ output: z9.object({
8262
+ proposer: z9.string(),
8263
+ category: z9.string(),
8264
+ token: z9.string(),
8265
+ recipient: z9.string(),
8266
+ amount: z9.string(),
8267
+ amountWei: z9.string(),
8268
+ expectedProposalId: z9.number(),
8269
+ expectedThreadId: z9.number(),
7656
8270
  tx: txResultOutput4
7657
8271
  }),
7658
8272
  examples: [
@@ -7947,33 +8561,35 @@ function applyFriendlyErrorHandling(cli2) {
7947
8561
  // src/cli.ts
7948
8562
  var __dirname = dirname(fileURLToPath(import.meta.url));
7949
8563
  var pkg = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf8"));
7950
- var cli = Cli6.create("assembly", {
8564
+ var cli = Cli7.create("assembly", {
7951
8565
  version: pkg.version,
7952
8566
  description: "Assembly governance CLI for Abstract chain."
7953
8567
  });
7954
8568
  cli.command(members);
7955
8569
  cli.command(council);
8570
+ cli.command(seats);
7956
8571
  cli.command(forum);
7957
8572
  cli.command(governance);
7958
8573
  cli.command(treasury);
7959
- var rootEnv = z8.object({
7960
- ABSTRACT_RPC_URL: z8.string().optional().describe("Abstract RPC URL override")
8574
+ registerDigestCommand(cli);
8575
+ var rootEnv = z10.object({
8576
+ ABSTRACT_RPC_URL: z10.string().optional().describe("Abstract RPC URL override")
7961
8577
  });
7962
- var timestampOutput6 = z8.union([z8.number(), z8.string()]);
8578
+ var timestampOutput7 = z10.union([z10.number(), z10.string()]);
7963
8579
  cli.command("status", {
7964
8580
  description: "Get a cross-contract Assembly snapshot (members, council, governance, treasury).",
7965
8581
  env: rootEnv,
7966
- output: z8.object({
7967
- activeMemberCount: z8.number(),
7968
- seatCount: z8.number(),
7969
- proposalCount: z8.number(),
7970
- currentAuctionDay: z8.number(),
7971
- currentAuctionSlot: z8.number(),
7972
- treasuryBalance: z8.string()
8582
+ output: z10.object({
8583
+ activeMemberCount: z10.number(),
8584
+ seatCount: z10.number(),
8585
+ proposalCount: z10.number(),
8586
+ currentAuctionDay: z10.number(),
8587
+ currentAuctionSlot: z10.number(),
8588
+ treasuryBalance: z10.string()
7973
8589
  }),
7974
8590
  examples: [{ description: "Fetch the current Assembly system status" }],
7975
8591
  async run(c) {
7976
- return withCommandSpan("assembly status", {}, async () => {
8592
+ return withCommandSpan2("assembly status", {}, async () => {
7977
8593
  const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
7978
8594
  const [
7979
8595
  activeMemberCount,
@@ -8023,18 +8639,18 @@ cli.command("status", {
8023
8639
  });
8024
8640
  cli.command("health", {
8025
8641
  description: "Check cross-contract health for one address (membership, council, refunds, power).",
8026
- args: z8.object({
8027
- address: z8.string().describe("Member or wallet address to inspect")
8642
+ args: z10.object({
8643
+ address: z10.string().describe("Member or wallet address to inspect")
8028
8644
  }),
8029
8645
  env: rootEnv,
8030
- output: z8.object({
8031
- address: z8.string(),
8032
- isActive: z8.boolean(),
8033
- activeUntil: timestampOutput6,
8034
- activeUntilRelative: z8.string(),
8035
- isCouncilMember: z8.boolean(),
8036
- pendingReturnsWei: z8.string(),
8037
- votingPower: z8.number()
8646
+ output: z10.object({
8647
+ address: z10.string(),
8648
+ isActive: z10.boolean(),
8649
+ activeUntil: timestampOutput7,
8650
+ activeUntilRelative: z10.string(),
8651
+ isCouncilMember: z10.boolean(),
8652
+ pendingReturnsWei: z10.string(),
8653
+ votingPower: z10.number()
8038
8654
  }),
8039
8655
  examples: [
8040
8656
  {
@@ -8043,7 +8659,7 @@ cli.command("health", {
8043
8659
  }
8044
8660
  ],
8045
8661
  async run(c) {
8046
- return withCommandSpan("assembly health", { address: c.args.address }, async () => {
8662
+ return withCommandSpan2("assembly health", { address: c.args.address }, async () => {
8047
8663
  const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
8048
8664
  const [isActive, member, isCouncilMember, pendingReturns, votingPower] = await Promise.all([
8049
8665
  client.readContract({