@spectratools/assembly-cli 0.13.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 +506 -195
  2. package/dist/index.js +506 -195
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  shutdownTelemetry,
10
10
  withCommandSpan as withCommandSpan2
11
11
  } from "@spectratools/cli-shared/telemetry";
12
- import { Cli as Cli6, z as z9 } 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({
@@ -5797,27 +5797,99 @@ var petitionDigestSchema = z4.object({
5797
5797
  threadId: z4.number(),
5798
5798
  hasSigned: z4.boolean().optional()
5799
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
+ });
5800
5842
  var digestOutputSchema = z4.object({
5801
5843
  meta: z4.object({
5802
5844
  chainId: z4.number(),
5803
5845
  fetchedAt: z4.string(),
5804
- address: z4.string().optional()
5846
+ address: z4.string().optional(),
5847
+ filters: filtersMetaSchema.optional()
5805
5848
  }),
5806
- proposals: z4.array(proposalDigestSchema),
5807
- threads: z4.array(threadDigestSchema),
5808
- comments: z4.array(commentDigestSchema),
5809
- petitions: z4.array(petitionDigestSchema),
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(),
5810
5853
  members: z4.object({
5811
5854
  count: z4.number(),
5812
5855
  items: z4.array(memberItemSchema)
5813
- }),
5856
+ }).optional(),
5814
5857
  errors: z4.array(z4.string())
5815
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));
5816
5876
  function registerDigestCommand(cli2) {
5817
5877
  cli2.command("digest", {
5818
5878
  description: "Aggregate proposals, threads, comments, petitions, and members into a single governance snapshot.",
5819
5879
  options: z4.object({
5820
- address: z4.string().optional().describe("Wallet address to enrich proposals (hasVoted) and petitions (hasSigned)")
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)")
5821
5893
  }),
5822
5894
  env: digestEnv,
5823
5895
  output: digestOutputSchema,
@@ -5826,6 +5898,18 @@ function registerDigestCommand(cli2) {
5826
5898
  {
5827
5899
  options: { address: "0x230Ccc765765d729fFb1897D538f773b92005Aa2" },
5828
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"
5829
5913
  }
5830
5914
  ],
5831
5915
  async run(c) {
@@ -5833,12 +5917,69 @@ function registerDigestCommand(cli2) {
5833
5917
  const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
5834
5918
  const errors = [];
5835
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"];
5836
5977
  const [proposalsResult, threadsResult, commentsResult, petitionsResult, membersResult] = await Promise.allSettled([
5837
5978
  fetchAllProposals(client),
5838
5979
  fetchAllThreads(client),
5839
- fetchAllComments(client),
5840
- fetchAllPetitions(client),
5841
- fetchMemberList(client, c.env.ASSEMBLY_INDEXER_URL)
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)
5842
5983
  ]);
5843
5984
  let proposals = [];
5844
5985
  if (proposalsResult.status === "fulfilled") {
@@ -5853,42 +5994,86 @@ function registerDigestCommand(cli2) {
5853
5994
  errors.push(`threads: ${threadsResult.reason}`);
5854
5995
  }
5855
5996
  let comments = [];
5856
- if (commentsResult.status === "fulfilled") {
5857
- comments = commentsResult.value;
5858
- } else {
5859
- errors.push(`comments: ${commentsResult.reason}`);
5997
+ if (!omitComments) {
5998
+ if (commentsResult.status === "fulfilled") {
5999
+ comments = commentsResult.value;
6000
+ } else {
6001
+ errors.push(`comments: ${commentsResult.reason}`);
6002
+ }
5860
6003
  }
5861
6004
  let petitions = [];
5862
- if (petitionsResult.status === "fulfilled") {
5863
- petitions = petitionsResult.value;
5864
- } else {
5865
- errors.push(`petitions: ${petitionsResult.reason}`);
6005
+ if (!omitPetitions) {
6006
+ if (petitionsResult.status === "fulfilled") {
6007
+ petitions = petitionsResult.value;
6008
+ } else {
6009
+ errors.push(`petitions: ${petitionsResult.reason}`);
6010
+ }
5866
6011
  }
5867
6012
  let memberIdentities = [];
5868
- if (membersResult.status === "fulfilled") {
5869
- const loaded = membersResult.value;
5870
- memberIdentities = loaded.members;
5871
- if (loaded.fallbackReason) {
5872
- process.stderr.write(
5873
- `${JSON.stringify({
5874
- level: "warn",
5875
- code: loaded.fallbackReason.code,
5876
- message: "Member snapshot indexer is unavailable. Falling back to on-chain Registered events.",
5877
- url: loaded.fallbackReason.url
5878
- })}
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
+ })}
5879
6025
  `
5880
- );
5881
- }
5882
- } else {
5883
- const err = membersResult.reason;
5884
- if (err instanceof AssemblyApiValidationError) {
5885
- errors.push(`members: ${err.details.code}`);
6026
+ );
6027
+ }
5886
6028
  } else {
5887
- errors.push(`members: ${err}`);
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
+ }
5888
6035
  }
5889
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
+ }
5890
6075
  let memberItems = [];
5891
- if (memberIdentities.length > 0) {
6076
+ if (!omitMembers && memberIdentities.length > 0) {
5892
6077
  try {
5893
6078
  const onchainStates = await fetchMemberOnchainState(
5894
6079
  client,
@@ -5908,17 +6093,11 @@ function registerDigestCommand(cli2) {
5908
6093
  let hasVotedMap = /* @__PURE__ */ new Map();
5909
6094
  let hasSignedMap = /* @__PURE__ */ new Map();
5910
6095
  if (address) {
6096
+ const proposalIds = proposals.map((_, i) => i + 1);
6097
+ const petitionIds = petitions.map((p) => p.id);
5911
6098
  const [votedResult, signedResult] = await Promise.allSettled([
5912
- fetchHasVotedBatch(
5913
- client,
5914
- address,
5915
- proposals.map((_, i) => i + 1)
5916
- ),
5917
- fetchHasSignedBatch(
5918
- client,
5919
- address,
5920
- petitions.map((p) => p.id)
5921
- )
6099
+ fetchHasVotedBatch(client, address, proposalIds),
6100
+ omitPetitions ? Promise.resolve(/* @__PURE__ */ new Map()) : fetchHasSignedBatch(client, address, petitionIds)
5922
6101
  ]);
5923
6102
  if (votedResult.status === "fulfilled") {
5924
6103
  hasVotedMap = votedResult.value;
@@ -5931,66 +6110,137 @@ function registerDigestCommand(cli2) {
5931
6110
  errors.push(`hasSigned enrichment: ${signedResult.reason}`);
5932
6111
  }
5933
6112
  }
5934
- const serializedProposals = proposals.map((p, i) => {
5935
- const serialized = serializeProposal(p);
5936
- const entry = {
5937
- id: i + 1,
5938
- ...serialized
5939
- };
5940
- if (address) {
5941
- entry.hasVoted = hasVotedMap.get(i + 1) ?? false;
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
+ }));
5942
6180
  }
5943
- return entry;
5944
- });
5945
- const serializedThreads = threads.map((t) => ({
5946
- id: t.id,
5947
- kind: t.kind,
5948
- author: t.author,
5949
- createdAt: t.createdAt,
5950
- category: t.category,
5951
- title: t.title,
5952
- proposalId: t.proposalId,
5953
- petitionId: t.petitionId
5954
- }));
5955
- const serializedComments = comments.map((cm) => ({
5956
- id: cm.id,
5957
- threadId: cm.threadId,
5958
- parentId: cm.parentId,
5959
- author: cm.author,
5960
- createdAt: cm.createdAt,
5961
- body: cm.body
5962
- }));
5963
- const serializedPetitions = petitions.map((p) => {
5964
- const entry = {
5965
- id: p.id,
5966
- proposer: p.proposer,
5967
- createdAt: p.createdAt,
5968
- category: p.category,
5969
- title: p.title,
5970
- body: p.body,
5971
- signatures: p.signatures,
5972
- promoted: p.promoted,
5973
- threadId: p.threadId
5974
- };
5975
- if (address) {
5976
- entry.hasSigned = hasSignedMap.get(p.id) ?? false;
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
+ });
5977
6217
  }
5978
- return entry;
5979
- });
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;
5980
6232
  const output = {
5981
6233
  meta: {
5982
6234
  chainId: 2741,
5983
6235
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString().replace(".000Z", "Z"),
5984
- ...address ? { address } : {}
6236
+ ...address ? { address } : {},
6237
+ ...hasFilters ? { filters: filtersMeta } : {}
5985
6238
  },
5986
6239
  proposals: serializedProposals,
5987
6240
  threads: serializedThreads,
5988
- comments: serializedComments,
5989
- petitions: serializedPetitions,
5990
- members: {
5991
- count: memberItems.length,
5992
- items: memberItems
5993
- },
6241
+ ...omitComments ? {} : { comments: serializedComments },
6242
+ ...omitPetitions ? {} : { petitions: serializedPetitions },
6243
+ ...omitMembers ? {} : { members: { count: memberItems.length, items: memberItems } },
5994
6244
  errors
5995
6245
  };
5996
6246
  return c.ok(output);
@@ -7779,49 +8029,109 @@ members.command("renew", {
7779
8029
  }
7780
8030
  });
7781
8031
 
7782
- // src/commands/treasury.ts
7783
- import { TxError as TxError4 } from "@spectratools/tx-shared";
8032
+ // src/commands/seats.ts
7784
8033
  import { Cli as Cli5, z as z8 } from "incur";
7785
- import { encodeAbiParameters, parseUnits, zeroAddress } from "viem";
7786
8034
  var env5 = z8.object({
7787
8035
  ABSTRACT_RPC_URL: z8.string().optional().describe("Abstract RPC URL override")
7788
8036
  });
7789
8037
  var timestampOutput5 = z8.union([z8.number(), z8.string()]);
7790
- var txResultOutput4 = z8.union([
7791
- z8.object({
7792
- status: z8.literal("success"),
7793
- hash: z8.string(),
7794
- blockNumber: z8.number(),
7795
- gasUsed: z8.string(),
7796
- from: z8.string(),
7797
- to: z8.string().nullable(),
7798
- effectiveGasPrice: z8.string().optional()
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
+
8092
+ // src/commands/treasury.ts
8093
+ import { TxError as TxError4 } from "@spectratools/tx-shared";
8094
+ import { Cli as Cli6, z as z9 } from "incur";
8095
+ import { encodeAbiParameters, parseUnits, zeroAddress } from "viem";
8096
+ var env6 = z9.object({
8097
+ ABSTRACT_RPC_URL: z9.string().optional().describe("Abstract RPC URL override")
8098
+ });
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()
7799
8109
  }),
7800
- z8.object({
7801
- status: z8.literal("reverted"),
7802
- hash: z8.string(),
7803
- blockNumber: z8.number(),
7804
- gasUsed: z8.string(),
7805
- from: z8.string(),
7806
- to: z8.string().nullable(),
7807
- effectiveGasPrice: z8.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()
7808
8118
  }),
7809
- z8.object({
7810
- status: z8.literal("dry-run"),
7811
- estimatedGas: z8.string(),
7812
- simulationResult: z8.unknown()
8119
+ z9.object({
8120
+ status: z9.literal("dry-run"),
8121
+ estimatedGas: z9.string(),
8122
+ simulationResult: z9.unknown()
7813
8123
  })
7814
8124
  ]);
7815
- var treasury = Cli5.create("treasury", {
8125
+ var treasury = Cli6.create("treasury", {
7816
8126
  description: "Inspect treasury balances, execution status, and spend controls."
7817
8127
  });
7818
8128
  treasury.command("balance", {
7819
8129
  description: "Get current native token balance for the treasury contract.",
7820
- env: env5,
7821
- output: z8.object({
7822
- address: z8.string(),
7823
- balanceWei: z8.string(),
7824
- balance: z8.string()
8130
+ env: env6,
8131
+ output: z9.object({
8132
+ address: z9.string(),
8133
+ balanceWei: z9.string(),
8134
+ balance: z9.string()
7825
8135
  }),
7826
8136
  examples: [{ description: "Check treasury balance" }],
7827
8137
  async run(c) {
@@ -7836,13 +8146,13 @@ treasury.command("balance", {
7836
8146
  });
7837
8147
  treasury.command("whitelist", {
7838
8148
  description: "Check whether an asset address is treasury-whitelisted.",
7839
- args: z8.object({
7840
- asset: z8.string().describe("Token/asset contract address")
8149
+ args: z9.object({
8150
+ asset: z9.string().describe("Token/asset contract address")
7841
8151
  }),
7842
- env: env5,
7843
- output: z8.object({
7844
- asset: z8.string(),
7845
- whitelisted: z8.boolean()
8152
+ env: env6,
8153
+ output: z9.object({
8154
+ asset: z9.string(),
8155
+ whitelisted: z9.boolean()
7846
8156
  }),
7847
8157
  examples: [
7848
8158
  {
@@ -7863,12 +8173,12 @@ treasury.command("whitelist", {
7863
8173
  });
7864
8174
  treasury.command("major-spend-status", {
7865
8175
  description: "Read major-spend cooldown status for the treasury contract.",
7866
- env: env5,
7867
- output: z8.object({
7868
- majorSpendCooldownSeconds: z8.number(),
7869
- lastMajorSpendAt: timestampOutput5,
7870
- lastMajorSpendRelative: z8.string(),
7871
- isMajorSpendAllowed: z8.boolean()
8176
+ env: env6,
8177
+ output: z9.object({
8178
+ majorSpendCooldownSeconds: z9.number(),
8179
+ lastMajorSpendAt: timestampOutput6,
8180
+ lastMajorSpendRelative: z9.string(),
8181
+ isMajorSpendAllowed: z9.boolean()
7872
8182
  }),
7873
8183
  examples: [{ description: "Inspect treasury major-spend guardrails" }],
7874
8184
  async run(c) {
@@ -7902,13 +8212,13 @@ treasury.command("major-spend-status", {
7902
8212
  });
7903
8213
  treasury.command("executed", {
7904
8214
  description: "Check whether a treasury action for a proposal has executed.",
7905
- args: z8.object({
7906
- proposalId: z8.coerce.number().int().positive().describe("Governance proposal id")
8215
+ args: z9.object({
8216
+ proposalId: z9.coerce.number().int().positive().describe("Governance proposal id")
7907
8217
  }),
7908
- env: env5,
7909
- output: z8.object({
7910
- proposalId: z8.number(),
7911
- executed: z8.boolean()
8218
+ env: env6,
8219
+ output: z9.object({
8220
+ proposalId: z9.number(),
8221
+ executed: z9.boolean()
7912
8222
  }),
7913
8223
  examples: [{ args: { proposalId: 1 }, description: "Check execution status for proposal #1" }],
7914
8224
  async run(c) {
@@ -7938,25 +8248,25 @@ treasury.command("propose-spend", {
7938
8248
  description: "Create a council proposal that spends treasury funds via TreasuryTransferIntentModule.",
7939
8249
  hint: "Requires PRIVATE_KEY environment variable for signing.",
7940
8250
  options: writeOptions.extend({
7941
- token: z8.string().describe("Token address to spend (use 0x0000000000000000000000000000000000000000 for ETH)"),
7942
- recipient: z8.string().describe("Recipient address"),
7943
- amount: z8.string().describe("Token amount as decimal string (human units)"),
7944
- decimals: z8.coerce.number().int().min(0).max(36).default(18).describe("Token decimals used to parse --amount (default: 18)"),
7945
- title: z8.string().min(1).describe("Proposal title"),
7946
- description: z8.string().min(1).describe("Proposal description"),
7947
- category: z8.string().default("treasury").describe("Forum category label for this proposal"),
7948
- "risk-tier": z8.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)")
7949
8259
  }),
7950
8260
  env: writeEnv,
7951
- output: z8.object({
7952
- proposer: z8.string(),
7953
- category: z8.string(),
7954
- token: z8.string(),
7955
- recipient: z8.string(),
7956
- amount: z8.string(),
7957
- amountWei: z8.string(),
7958
- expectedProposalId: z8.number(),
7959
- expectedThreadId: z8.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(),
7960
8270
  tx: txResultOutput4
7961
8271
  }),
7962
8272
  examples: [
@@ -8251,30 +8561,31 @@ function applyFriendlyErrorHandling(cli2) {
8251
8561
  // src/cli.ts
8252
8562
  var __dirname = dirname(fileURLToPath(import.meta.url));
8253
8563
  var pkg = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf8"));
8254
- var cli = Cli6.create("assembly", {
8564
+ var cli = Cli7.create("assembly", {
8255
8565
  version: pkg.version,
8256
8566
  description: "Assembly governance CLI for Abstract chain."
8257
8567
  });
8258
8568
  cli.command(members);
8259
8569
  cli.command(council);
8570
+ cli.command(seats);
8260
8571
  cli.command(forum);
8261
8572
  cli.command(governance);
8262
8573
  cli.command(treasury);
8263
8574
  registerDigestCommand(cli);
8264
- var rootEnv = z9.object({
8265
- ABSTRACT_RPC_URL: z9.string().optional().describe("Abstract RPC URL override")
8575
+ var rootEnv = z10.object({
8576
+ ABSTRACT_RPC_URL: z10.string().optional().describe("Abstract RPC URL override")
8266
8577
  });
8267
- var timestampOutput6 = z9.union([z9.number(), z9.string()]);
8578
+ var timestampOutput7 = z10.union([z10.number(), z10.string()]);
8268
8579
  cli.command("status", {
8269
8580
  description: "Get a cross-contract Assembly snapshot (members, council, governance, treasury).",
8270
8581
  env: rootEnv,
8271
- output: z9.object({
8272
- activeMemberCount: z9.number(),
8273
- seatCount: z9.number(),
8274
- proposalCount: z9.number(),
8275
- currentAuctionDay: z9.number(),
8276
- currentAuctionSlot: z9.number(),
8277
- treasuryBalance: z9.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()
8278
8589
  }),
8279
8590
  examples: [{ description: "Fetch the current Assembly system status" }],
8280
8591
  async run(c) {
@@ -8328,18 +8639,18 @@ cli.command("status", {
8328
8639
  });
8329
8640
  cli.command("health", {
8330
8641
  description: "Check cross-contract health for one address (membership, council, refunds, power).",
8331
- args: z9.object({
8332
- address: z9.string().describe("Member or wallet address to inspect")
8642
+ args: z10.object({
8643
+ address: z10.string().describe("Member or wallet address to inspect")
8333
8644
  }),
8334
8645
  env: rootEnv,
8335
- output: z9.object({
8336
- address: z9.string(),
8337
- isActive: z9.boolean(),
8338
- activeUntil: timestampOutput6,
8339
- activeUntilRelative: z9.string(),
8340
- isCouncilMember: z9.boolean(),
8341
- pendingReturnsWei: z9.string(),
8342
- votingPower: z9.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()
8343
8654
  }),
8344
8655
  examples: [
8345
8656
  {