@spectratools/assembly-cli 0.6.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/cli.js +1009 -283
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { readFileSync, realpathSync } from "fs";
|
|
5
5
|
import { dirname, resolve } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
|
-
import { Cli as Cli6, z as
|
|
7
|
+
import { Cli as Cli6, z as z7 } from "incur";
|
|
8
8
|
|
|
9
9
|
// src/commands/_common.ts
|
|
10
10
|
import { checksumAddress, weiToEth } from "@spectratools/cli-shared";
|
|
@@ -59,7 +59,8 @@ function jsonSafe(value) {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// src/commands/council.ts
|
|
62
|
-
import { Cli, z } from "incur";
|
|
62
|
+
import { Cli, z as z2 } from "incur";
|
|
63
|
+
import { parseEther } from "viem";
|
|
63
64
|
|
|
64
65
|
// src/contracts/CouncilSeats.abi.json
|
|
65
66
|
var CouncilSeats_abi_default = [
|
|
@@ -4328,12 +4329,79 @@ function createAssemblyPublicClient(rpcUrl) {
|
|
|
4328
4329
|
transport: http(rpcUrl ?? process.env.ABSTRACT_RPC_URL ?? "https://api.mainnet.abs.xyz")
|
|
4329
4330
|
});
|
|
4330
4331
|
}
|
|
4332
|
+
function createAssemblyWalletClient(account, rpcUrl) {
|
|
4333
|
+
return createWalletClient({
|
|
4334
|
+
account,
|
|
4335
|
+
chain: abstractMainnet,
|
|
4336
|
+
transport: http(rpcUrl ?? process.env.ABSTRACT_RPC_URL ?? "https://api.mainnet.abs.xyz")
|
|
4337
|
+
});
|
|
4338
|
+
}
|
|
4331
4339
|
|
|
4332
|
-
// src/commands/
|
|
4333
|
-
|
|
4340
|
+
// src/commands/_write-utils.ts
|
|
4341
|
+
import {
|
|
4342
|
+
createPrivateKeySigner,
|
|
4343
|
+
executeTx
|
|
4344
|
+
} from "@spectratools/tx-shared";
|
|
4345
|
+
import { z } from "incur";
|
|
4346
|
+
var writeEnv = z.object({
|
|
4347
|
+
PRIVATE_KEY: z.string().describe("Private key (0x-prefixed 32-byte hex) for signing transactions"),
|
|
4334
4348
|
ABSTRACT_RPC_URL: z.string().optional().describe("Abstract RPC URL override")
|
|
4335
4349
|
});
|
|
4336
|
-
var
|
|
4350
|
+
var writeOptions = z.object({
|
|
4351
|
+
"dry-run": z.boolean().default(false).describe("Simulate the transaction without broadcasting"),
|
|
4352
|
+
"gas-limit": z.string().optional().describe("Gas limit override (in gas units)"),
|
|
4353
|
+
"max-fee": z.string().optional().describe("Max fee per gas override in wei (EIP-1559)"),
|
|
4354
|
+
nonce: z.number().optional().describe("Nonce override")
|
|
4355
|
+
});
|
|
4356
|
+
function resolveAccount(env6) {
|
|
4357
|
+
const signer = createPrivateKeySigner(env6.PRIVATE_KEY);
|
|
4358
|
+
return signer.account;
|
|
4359
|
+
}
|
|
4360
|
+
function formatTxResult(result) {
|
|
4361
|
+
if (result.status === "dry-run") {
|
|
4362
|
+
return {
|
|
4363
|
+
status: "dry-run",
|
|
4364
|
+
estimatedGas: result.estimatedGas.toString(),
|
|
4365
|
+
simulationResult: jsonSafe(result.simulationResult)
|
|
4366
|
+
};
|
|
4367
|
+
}
|
|
4368
|
+
return {
|
|
4369
|
+
status: result.status,
|
|
4370
|
+
hash: result.hash,
|
|
4371
|
+
blockNumber: Number(result.blockNumber),
|
|
4372
|
+
gasUsed: result.gasUsed.toString(),
|
|
4373
|
+
from: result.from,
|
|
4374
|
+
to: result.to,
|
|
4375
|
+
...result.effectiveGasPrice !== void 0 ? { effectiveGasPrice: result.effectiveGasPrice.toString() } : {}
|
|
4376
|
+
};
|
|
4377
|
+
}
|
|
4378
|
+
async function assemblyWriteTx(opts) {
|
|
4379
|
+
const { env: env6, options, address, abi, functionName, args, value } = opts;
|
|
4380
|
+
const account = resolveAccount(env6);
|
|
4381
|
+
const publicClient = createAssemblyPublicClient(env6.ABSTRACT_RPC_URL);
|
|
4382
|
+
const walletClient = createAssemblyWalletClient(account, env6.ABSTRACT_RPC_URL);
|
|
4383
|
+
const result = await executeTx({
|
|
4384
|
+
publicClient,
|
|
4385
|
+
walletClient,
|
|
4386
|
+
account,
|
|
4387
|
+
address,
|
|
4388
|
+
abi,
|
|
4389
|
+
functionName,
|
|
4390
|
+
...args !== void 0 ? { args } : {},
|
|
4391
|
+
...value !== void 0 ? { value } : {},
|
|
4392
|
+
dryRun: options["dry-run"],
|
|
4393
|
+
...options["gas-limit"] ? { gasLimit: BigInt(options["gas-limit"]) } : {},
|
|
4394
|
+
...options["max-fee"] ? { maxFeePerGas: BigInt(options["max-fee"]) } : {},
|
|
4395
|
+
...options.nonce !== void 0 ? { nonce: options.nonce } : {}
|
|
4396
|
+
});
|
|
4397
|
+
return formatTxResult(result);
|
|
4398
|
+
}
|
|
4399
|
+
|
|
4400
|
+
// src/commands/council.ts
|
|
4401
|
+
var env = z2.object({
|
|
4402
|
+
ABSTRACT_RPC_URL: z2.string().optional().describe("Abstract RPC URL override")
|
|
4403
|
+
});
|
|
4404
|
+
var timestampOutput = z2.union([z2.number(), z2.string()]);
|
|
4337
4405
|
function decodeSeat(value) {
|
|
4338
4406
|
const [owner, startAt, endAt, forfeited] = value;
|
|
4339
4407
|
return { owner, startAt, endAt, forfeited };
|
|
@@ -4342,10 +4410,14 @@ function decodeAuction(value) {
|
|
|
4342
4410
|
const [highestBidder, highestBid, settled] = value;
|
|
4343
4411
|
return { highestBidder, highestBid, settled };
|
|
4344
4412
|
}
|
|
4345
|
-
function
|
|
4346
|
-
if (params.settled) return "settled";
|
|
4347
|
-
|
|
4348
|
-
|
|
4413
|
+
function deriveAuctionExecutionState(params) {
|
|
4414
|
+
if (params.settled) return { executionStatus: "settled", bidExecutableNow: false };
|
|
4415
|
+
const isCurrentAuctionSlot = params.day === Number(params.currentAuctionDay) && params.slot === Number(params.currentAuctionSlot);
|
|
4416
|
+
if (params.currentTimestamp < params.windowEnd) {
|
|
4417
|
+
if (isCurrentAuctionSlot) return { executionStatus: "open_now", bidExecutableNow: true };
|
|
4418
|
+
return { executionStatus: "upcoming", bidExecutableNow: false };
|
|
4419
|
+
}
|
|
4420
|
+
return { executionStatus: "closed_unsettled", bidExecutableNow: false };
|
|
4349
4421
|
}
|
|
4350
4422
|
var council = Cli.create("council", {
|
|
4351
4423
|
description: "Inspect council seats, members, auctions, and seat parameters."
|
|
@@ -4353,15 +4425,15 @@ var council = Cli.create("council", {
|
|
|
4353
4425
|
council.command("seats", {
|
|
4354
4426
|
description: "List all council seats and their occupancy windows.",
|
|
4355
4427
|
env,
|
|
4356
|
-
output:
|
|
4357
|
-
|
|
4358
|
-
id:
|
|
4359
|
-
owner:
|
|
4428
|
+
output: z2.array(
|
|
4429
|
+
z2.object({
|
|
4430
|
+
id: z2.number(),
|
|
4431
|
+
owner: z2.string(),
|
|
4360
4432
|
startAt: timestampOutput,
|
|
4361
|
-
startAtRelative:
|
|
4433
|
+
startAtRelative: z2.string(),
|
|
4362
4434
|
endAt: timestampOutput,
|
|
4363
|
-
endAtRelative:
|
|
4364
|
-
forfeited:
|
|
4435
|
+
endAtRelative: z2.string(),
|
|
4436
|
+
forfeited: z2.boolean()
|
|
4365
4437
|
})
|
|
4366
4438
|
),
|
|
4367
4439
|
examples: [{ description: "List all council seats" }],
|
|
@@ -4398,17 +4470,17 @@ council.command("seats", {
|
|
|
4398
4470
|
});
|
|
4399
4471
|
council.command("seat", {
|
|
4400
4472
|
description: "Get detailed seat information for a specific seat id.",
|
|
4401
|
-
args:
|
|
4402
|
-
id:
|
|
4473
|
+
args: z2.object({
|
|
4474
|
+
id: z2.coerce.number().int().nonnegative().describe("Seat id (0-indexed)")
|
|
4403
4475
|
}),
|
|
4404
4476
|
env,
|
|
4405
|
-
output:
|
|
4406
|
-
id:
|
|
4407
|
-
owner:
|
|
4477
|
+
output: z2.object({
|
|
4478
|
+
id: z2.number(),
|
|
4479
|
+
owner: z2.string(),
|
|
4408
4480
|
startAt: timestampOutput,
|
|
4409
4481
|
endAt: timestampOutput,
|
|
4410
|
-
forfeited:
|
|
4411
|
-
endAtRelative:
|
|
4482
|
+
forfeited: z2.boolean(),
|
|
4483
|
+
endAtRelative: z2.string()
|
|
4412
4484
|
}),
|
|
4413
4485
|
examples: [{ args: { id: 0 }, description: "Inspect seat #0" }],
|
|
4414
4486
|
async run(c) {
|
|
@@ -4445,10 +4517,10 @@ council.command("seat", {
|
|
|
4445
4517
|
council.command("members", {
|
|
4446
4518
|
description: "List currently active council members and voting power.",
|
|
4447
4519
|
env,
|
|
4448
|
-
output:
|
|
4449
|
-
|
|
4450
|
-
address:
|
|
4451
|
-
votingPower:
|
|
4520
|
+
output: z2.array(
|
|
4521
|
+
z2.object({
|
|
4522
|
+
address: z2.string(),
|
|
4523
|
+
votingPower: z2.number()
|
|
4452
4524
|
})
|
|
4453
4525
|
),
|
|
4454
4526
|
examples: [{ description: "List active council members" }],
|
|
@@ -4494,13 +4566,13 @@ council.command("members", {
|
|
|
4494
4566
|
});
|
|
4495
4567
|
council.command("is-member", {
|
|
4496
4568
|
description: "Check whether an address is currently a council member.",
|
|
4497
|
-
args:
|
|
4498
|
-
address:
|
|
4569
|
+
args: z2.object({
|
|
4570
|
+
address: z2.string().describe("Address to check")
|
|
4499
4571
|
}),
|
|
4500
4572
|
env,
|
|
4501
|
-
output:
|
|
4502
|
-
address:
|
|
4503
|
-
isMember:
|
|
4573
|
+
output: z2.object({
|
|
4574
|
+
address: z2.string(),
|
|
4575
|
+
isMember: z2.boolean()
|
|
4504
4576
|
}),
|
|
4505
4577
|
examples: [
|
|
4506
4578
|
{
|
|
@@ -4521,13 +4593,13 @@ council.command("is-member", {
|
|
|
4521
4593
|
});
|
|
4522
4594
|
council.command("voting-power", {
|
|
4523
4595
|
description: "Get the current voting power for an address.",
|
|
4524
|
-
args:
|
|
4525
|
-
address:
|
|
4596
|
+
args: z2.object({
|
|
4597
|
+
address: z2.string().describe("Address to inspect")
|
|
4526
4598
|
}),
|
|
4527
4599
|
env,
|
|
4528
|
-
output:
|
|
4529
|
-
address:
|
|
4530
|
-
votingPower:
|
|
4600
|
+
output: z2.object({
|
|
4601
|
+
address: z2.string(),
|
|
4602
|
+
votingPower: z2.number()
|
|
4531
4603
|
}),
|
|
4532
4604
|
examples: [
|
|
4533
4605
|
{
|
|
@@ -4549,19 +4621,21 @@ council.command("voting-power", {
|
|
|
4549
4621
|
council.command("auctions", {
|
|
4550
4622
|
description: "List recent and current council auction slots and leading bids.",
|
|
4551
4623
|
env,
|
|
4552
|
-
output:
|
|
4553
|
-
currentDay:
|
|
4554
|
-
currentSlot:
|
|
4555
|
-
auctions:
|
|
4556
|
-
|
|
4557
|
-
day:
|
|
4558
|
-
slot:
|
|
4559
|
-
highestBidder:
|
|
4560
|
-
highestBid:
|
|
4561
|
-
settled:
|
|
4624
|
+
output: z2.object({
|
|
4625
|
+
currentDay: z2.number(),
|
|
4626
|
+
currentSlot: z2.number(),
|
|
4627
|
+
auctions: z2.array(
|
|
4628
|
+
z2.object({
|
|
4629
|
+
day: z2.number(),
|
|
4630
|
+
slot: z2.number(),
|
|
4631
|
+
highestBidder: z2.string(),
|
|
4632
|
+
highestBid: z2.string(),
|
|
4633
|
+
settled: z2.boolean(),
|
|
4562
4634
|
windowEnd: timestampOutput,
|
|
4563
|
-
windowEndRelative:
|
|
4564
|
-
|
|
4635
|
+
windowEndRelative: z2.string(),
|
|
4636
|
+
bidExecutableNow: z2.boolean(),
|
|
4637
|
+
executionStatus: z2.enum(["open_now", "upcoming", "closed_unsettled", "settled"]),
|
|
4638
|
+
status: z2.enum(["open_now", "upcoming", "closed_unsettled", "settled"])
|
|
4565
4639
|
})
|
|
4566
4640
|
)
|
|
4567
4641
|
}),
|
|
@@ -4619,19 +4693,27 @@ council.command("auctions", {
|
|
|
4619
4693
|
currentSlot: asNum(slot),
|
|
4620
4694
|
auctions: recent.map((x, i) => {
|
|
4621
4695
|
const windowEnd = windowEnds[i];
|
|
4696
|
+
const dayValue = Number(x.day);
|
|
4697
|
+
const execution = deriveAuctionExecutionState({
|
|
4698
|
+
day: dayValue,
|
|
4699
|
+
slot: x.slot,
|
|
4700
|
+
currentAuctionDay: day,
|
|
4701
|
+
currentAuctionSlot: slot,
|
|
4702
|
+
settled: auctions[i].settled,
|
|
4703
|
+
windowEnd,
|
|
4704
|
+
currentTimestamp
|
|
4705
|
+
});
|
|
4622
4706
|
return {
|
|
4623
|
-
day:
|
|
4707
|
+
day: dayValue,
|
|
4624
4708
|
slot: x.slot,
|
|
4625
4709
|
highestBidder: toChecksum(auctions[i].highestBidder),
|
|
4626
4710
|
highestBid: eth(auctions[i].highestBid),
|
|
4627
4711
|
settled: auctions[i].settled,
|
|
4628
4712
|
windowEnd: timeValue(windowEnd, c.format),
|
|
4629
4713
|
windowEndRelative: relTime(windowEnd),
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
currentTimestamp
|
|
4634
|
-
})
|
|
4714
|
+
bidExecutableNow: execution.bidExecutableNow,
|
|
4715
|
+
executionStatus: execution.executionStatus,
|
|
4716
|
+
status: execution.executionStatus
|
|
4635
4717
|
};
|
|
4636
4718
|
})
|
|
4637
4719
|
},
|
|
@@ -4649,20 +4731,22 @@ council.command("auctions", {
|
|
|
4649
4731
|
});
|
|
4650
4732
|
council.command("auction", {
|
|
4651
4733
|
description: "Get one auction slot by day + slot.",
|
|
4652
|
-
args:
|
|
4653
|
-
day:
|
|
4654
|
-
slot:
|
|
4734
|
+
args: z2.object({
|
|
4735
|
+
day: z2.coerce.number().int().nonnegative().describe("Auction day index"),
|
|
4736
|
+
slot: z2.coerce.number().int().nonnegative().describe("Slot index within day")
|
|
4655
4737
|
}),
|
|
4656
4738
|
env,
|
|
4657
|
-
output:
|
|
4658
|
-
day:
|
|
4659
|
-
slot:
|
|
4660
|
-
highestBidder:
|
|
4661
|
-
highestBid:
|
|
4662
|
-
settled:
|
|
4739
|
+
output: z2.object({
|
|
4740
|
+
day: z2.number(),
|
|
4741
|
+
slot: z2.number(),
|
|
4742
|
+
highestBidder: z2.string(),
|
|
4743
|
+
highestBid: z2.string(),
|
|
4744
|
+
settled: z2.boolean(),
|
|
4663
4745
|
windowEnd: timestampOutput,
|
|
4664
|
-
windowEndRelative:
|
|
4665
|
-
|
|
4746
|
+
windowEndRelative: z2.string(),
|
|
4747
|
+
bidExecutableNow: z2.boolean(),
|
|
4748
|
+
executionStatus: z2.enum(["open_now", "upcoming", "closed_unsettled", "settled"]),
|
|
4749
|
+
status: z2.enum(["open_now", "upcoming", "closed_unsettled", "settled"])
|
|
4666
4750
|
}),
|
|
4667
4751
|
examples: [{ args: { day: 0, slot: 0 }, description: "Inspect day 0, slot 0 auction" }],
|
|
4668
4752
|
async run(c) {
|
|
@@ -4679,7 +4763,7 @@ council.command("auction", {
|
|
|
4679
4763
|
retryable: false
|
|
4680
4764
|
});
|
|
4681
4765
|
}
|
|
4682
|
-
const [auctionTuple, windowEnd, latestBlock] = await Promise.all([
|
|
4766
|
+
const [auctionTuple, windowEnd, latestBlock, currentAuctionDay, currentAuctionSlot] = await Promise.all([
|
|
4683
4767
|
client.readContract({
|
|
4684
4768
|
abi: councilSeatsAbi,
|
|
4685
4769
|
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
@@ -4692,11 +4776,30 @@ council.command("auction", {
|
|
|
4692
4776
|
functionName: "auctionWindowEnd",
|
|
4693
4777
|
args: [BigInt(c.args.day), c.args.slot]
|
|
4694
4778
|
}),
|
|
4695
|
-
client.getBlock({ blockTag: "latest" })
|
|
4779
|
+
client.getBlock({ blockTag: "latest" }),
|
|
4780
|
+
client.readContract({
|
|
4781
|
+
abi: councilSeatsAbi,
|
|
4782
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
4783
|
+
functionName: "currentAuctionDay"
|
|
4784
|
+
}),
|
|
4785
|
+
client.readContract({
|
|
4786
|
+
abi: councilSeatsAbi,
|
|
4787
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
4788
|
+
functionName: "currentAuctionSlot"
|
|
4789
|
+
})
|
|
4696
4790
|
]);
|
|
4697
4791
|
const auction = decodeAuction(auctionTuple);
|
|
4698
4792
|
const windowEndTimestamp = windowEnd;
|
|
4699
4793
|
const currentTimestamp = latestBlock.timestamp;
|
|
4794
|
+
const execution = deriveAuctionExecutionState({
|
|
4795
|
+
day: c.args.day,
|
|
4796
|
+
slot: c.args.slot,
|
|
4797
|
+
currentAuctionDay,
|
|
4798
|
+
currentAuctionSlot,
|
|
4799
|
+
settled: auction.settled,
|
|
4800
|
+
windowEnd: windowEndTimestamp,
|
|
4801
|
+
currentTimestamp
|
|
4802
|
+
});
|
|
4700
4803
|
return c.ok({
|
|
4701
4804
|
day: c.args.day,
|
|
4702
4805
|
slot: c.args.slot,
|
|
@@ -4705,24 +4808,22 @@ council.command("auction", {
|
|
|
4705
4808
|
settled: auction.settled,
|
|
4706
4809
|
windowEnd: timeValue(windowEndTimestamp, c.format),
|
|
4707
4810
|
windowEndRelative: relTime(windowEndTimestamp),
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
currentTimestamp
|
|
4712
|
-
})
|
|
4811
|
+
bidExecutableNow: execution.bidExecutableNow,
|
|
4812
|
+
executionStatus: execution.executionStatus,
|
|
4813
|
+
status: execution.executionStatus
|
|
4713
4814
|
});
|
|
4714
4815
|
}
|
|
4715
4816
|
});
|
|
4716
4817
|
council.command("pending-refund", {
|
|
4717
4818
|
description: "Get pending refundable bid amount for an address.",
|
|
4718
|
-
args:
|
|
4719
|
-
address:
|
|
4819
|
+
args: z2.object({
|
|
4820
|
+
address: z2.string().describe("Bidder address")
|
|
4720
4821
|
}),
|
|
4721
4822
|
env,
|
|
4722
|
-
output:
|
|
4723
|
-
address:
|
|
4724
|
-
pendingRefund:
|
|
4725
|
-
pendingRefundWei:
|
|
4823
|
+
output: z2.object({
|
|
4824
|
+
address: z2.string(),
|
|
4825
|
+
pendingRefund: z2.string(),
|
|
4826
|
+
pendingRefundWei: z2.string()
|
|
4726
4827
|
}),
|
|
4727
4828
|
examples: [
|
|
4728
4829
|
{
|
|
@@ -4748,13 +4849,13 @@ council.command("pending-refund", {
|
|
|
4748
4849
|
council.command("params", {
|
|
4749
4850
|
description: "Read council seat term and auction scheduling parameters.",
|
|
4750
4851
|
env,
|
|
4751
|
-
output:
|
|
4752
|
-
SEAT_TERM:
|
|
4753
|
-
AUCTION_SLOT_DURATION:
|
|
4754
|
-
AUCTION_SLOTS_PER_DAY:
|
|
4755
|
-
auctionEpochStart:
|
|
4756
|
-
auctionWindowStart:
|
|
4757
|
-
auctionWindowEnd:
|
|
4852
|
+
output: z2.object({
|
|
4853
|
+
SEAT_TERM: z2.number(),
|
|
4854
|
+
AUCTION_SLOT_DURATION: z2.number(),
|
|
4855
|
+
AUCTION_SLOTS_PER_DAY: z2.number(),
|
|
4856
|
+
auctionEpochStart: z2.number(),
|
|
4857
|
+
auctionWindowStart: z2.number(),
|
|
4858
|
+
auctionWindowEnd: z2.number()
|
|
4758
4859
|
}),
|
|
4759
4860
|
examples: [{ description: "Inspect council seat + auction timing constants" }],
|
|
4760
4861
|
async run(c) {
|
|
@@ -4805,13 +4906,347 @@ council.command("params", {
|
|
|
4805
4906
|
});
|
|
4806
4907
|
}
|
|
4807
4908
|
});
|
|
4909
|
+
var txResultOutput = z2.union([
|
|
4910
|
+
z2.object({
|
|
4911
|
+
status: z2.enum(["success", "reverted"]),
|
|
4912
|
+
hash: z2.string(),
|
|
4913
|
+
blockNumber: z2.number(),
|
|
4914
|
+
gasUsed: z2.string(),
|
|
4915
|
+
from: z2.string(),
|
|
4916
|
+
to: z2.string().nullable(),
|
|
4917
|
+
effectiveGasPrice: z2.string().optional()
|
|
4918
|
+
}),
|
|
4919
|
+
z2.object({
|
|
4920
|
+
status: z2.literal("dry-run"),
|
|
4921
|
+
estimatedGas: z2.string(),
|
|
4922
|
+
simulationResult: z2.unknown()
|
|
4923
|
+
})
|
|
4924
|
+
]);
|
|
4925
|
+
council.command("bid", {
|
|
4926
|
+
description: "Place a bid on a council seat auction (payable).",
|
|
4927
|
+
hint: "Requires PRIVATE_KEY environment variable for signing.",
|
|
4928
|
+
args: z2.object({
|
|
4929
|
+
day: z2.coerce.number().int().nonnegative().describe("Auction day index"),
|
|
4930
|
+
slot: z2.coerce.number().int().nonnegative().describe("Slot index within day")
|
|
4931
|
+
}),
|
|
4932
|
+
options: writeOptions.extend({
|
|
4933
|
+
amount: z2.string().describe('ETH amount to bid (e.g. "0.1")')
|
|
4934
|
+
}),
|
|
4935
|
+
env: writeEnv,
|
|
4936
|
+
output: z2.object({
|
|
4937
|
+
day: z2.number(),
|
|
4938
|
+
slot: z2.number(),
|
|
4939
|
+
bidAmount: z2.string(),
|
|
4940
|
+
tx: txResultOutput
|
|
4941
|
+
}),
|
|
4942
|
+
examples: [
|
|
4943
|
+
{
|
|
4944
|
+
args: { day: 0, slot: 0 },
|
|
4945
|
+
options: { amount: "0.1" },
|
|
4946
|
+
description: "Bid 0.1 ETH on day 0, slot 0"
|
|
4947
|
+
}
|
|
4948
|
+
],
|
|
4949
|
+
async run(c) {
|
|
4950
|
+
const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
4951
|
+
let amountWei;
|
|
4952
|
+
try {
|
|
4953
|
+
amountWei = parseEther(c.options.amount);
|
|
4954
|
+
} catch {
|
|
4955
|
+
return c.error({
|
|
4956
|
+
code: "INVALID_AMOUNT",
|
|
4957
|
+
message: `Invalid ETH amount: "${c.options.amount}". Provide a decimal number (e.g. "0.1").`,
|
|
4958
|
+
retryable: false
|
|
4959
|
+
});
|
|
4960
|
+
}
|
|
4961
|
+
if (amountWei <= 0n) {
|
|
4962
|
+
return c.error({
|
|
4963
|
+
code: "INVALID_AMOUNT",
|
|
4964
|
+
message: "Bid amount must be greater than zero.",
|
|
4965
|
+
retryable: false
|
|
4966
|
+
});
|
|
4967
|
+
}
|
|
4968
|
+
const slotsPerDay = await client.readContract({
|
|
4969
|
+
abi: councilSeatsAbi,
|
|
4970
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
4971
|
+
functionName: "AUCTION_SLOTS_PER_DAY"
|
|
4972
|
+
});
|
|
4973
|
+
if (c.args.slot >= Number(slotsPerDay)) {
|
|
4974
|
+
return c.error({
|
|
4975
|
+
code: "OUT_OF_RANGE",
|
|
4976
|
+
message: `Slot ${c.args.slot} does not exist (max: ${Number(slotsPerDay) - 1})`,
|
|
4977
|
+
retryable: false
|
|
4978
|
+
});
|
|
4979
|
+
}
|
|
4980
|
+
const [auctionTuple, windowEnd, latestBlock, currentAuctionDay, currentAuctionSlot] = await Promise.all([
|
|
4981
|
+
client.readContract({
|
|
4982
|
+
abi: councilSeatsAbi,
|
|
4983
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
4984
|
+
functionName: "auctions",
|
|
4985
|
+
args: [BigInt(c.args.day), c.args.slot]
|
|
4986
|
+
}),
|
|
4987
|
+
client.readContract({
|
|
4988
|
+
abi: councilSeatsAbi,
|
|
4989
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
4990
|
+
functionName: "auctionWindowEnd",
|
|
4991
|
+
args: [BigInt(c.args.day), c.args.slot]
|
|
4992
|
+
}),
|
|
4993
|
+
client.getBlock({ blockTag: "latest" }),
|
|
4994
|
+
client.readContract({
|
|
4995
|
+
abi: councilSeatsAbi,
|
|
4996
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
4997
|
+
functionName: "currentAuctionDay"
|
|
4998
|
+
}),
|
|
4999
|
+
client.readContract({
|
|
5000
|
+
abi: councilSeatsAbi,
|
|
5001
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
5002
|
+
functionName: "currentAuctionSlot"
|
|
5003
|
+
})
|
|
5004
|
+
]);
|
|
5005
|
+
const auction = decodeAuction(auctionTuple);
|
|
5006
|
+
const windowEndTimestamp = windowEnd;
|
|
5007
|
+
const currentTimestamp = latestBlock.timestamp;
|
|
5008
|
+
const execution = deriveAuctionExecutionState({
|
|
5009
|
+
day: c.args.day,
|
|
5010
|
+
slot: c.args.slot,
|
|
5011
|
+
currentAuctionDay,
|
|
5012
|
+
currentAuctionSlot,
|
|
5013
|
+
settled: auction.settled,
|
|
5014
|
+
windowEnd: windowEndTimestamp,
|
|
5015
|
+
currentTimestamp
|
|
5016
|
+
});
|
|
5017
|
+
if (execution.executionStatus === "settled") {
|
|
5018
|
+
return c.error({
|
|
5019
|
+
code: "AUCTION_SETTLED",
|
|
5020
|
+
message: `Auction (day=${c.args.day}, slot=${c.args.slot}) is already settled. Winner: ${toChecksum(auction.highestBidder)}.`,
|
|
5021
|
+
retryable: false
|
|
5022
|
+
});
|
|
5023
|
+
}
|
|
5024
|
+
if (execution.executionStatus === "upcoming") {
|
|
5025
|
+
return c.error({
|
|
5026
|
+
code: "AUCTION_NOT_ACTIVE",
|
|
5027
|
+
message: `Auction (day=${c.args.day}, slot=${c.args.slot}) is not the currently active slot. Current bid-executable slot is day=${Number(currentAuctionDay)}, slot=${Number(currentAuctionSlot)}.`,
|
|
5028
|
+
retryable: false
|
|
5029
|
+
});
|
|
5030
|
+
}
|
|
5031
|
+
if (execution.executionStatus === "closed_unsettled") {
|
|
5032
|
+
return c.error({
|
|
5033
|
+
code: "AUCTION_CLOSED",
|
|
5034
|
+
message: `Auction (day=${c.args.day}, slot=${c.args.slot}) bidding window has ended. Use "council settle" instead.`,
|
|
5035
|
+
retryable: false
|
|
5036
|
+
});
|
|
5037
|
+
}
|
|
5038
|
+
if (auction.highestBid >= amountWei) {
|
|
5039
|
+
return c.error({
|
|
5040
|
+
code: "BID_TOO_LOW",
|
|
5041
|
+
message: `Bid of ${c.options.amount} ETH is not higher than current highest bid of ${eth(auction.highestBid)}. Increase your bid amount.`,
|
|
5042
|
+
retryable: false
|
|
5043
|
+
});
|
|
5044
|
+
}
|
|
5045
|
+
const txResult = await assemblyWriteTx({
|
|
5046
|
+
env: c.env,
|
|
5047
|
+
options: c.options,
|
|
5048
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
5049
|
+
abi: councilSeatsAbi,
|
|
5050
|
+
functionName: "bid",
|
|
5051
|
+
args: [BigInt(c.args.day), c.args.slot],
|
|
5052
|
+
value: amountWei
|
|
5053
|
+
});
|
|
5054
|
+
return c.ok(
|
|
5055
|
+
{
|
|
5056
|
+
day: c.args.day,
|
|
5057
|
+
slot: c.args.slot,
|
|
5058
|
+
bidAmount: `${c.options.amount} ETH`,
|
|
5059
|
+
tx: txResult
|
|
5060
|
+
},
|
|
5061
|
+
c.format === "json" || c.format === "jsonl" ? void 0 : {
|
|
5062
|
+
cta: {
|
|
5063
|
+
description: "Next steps:",
|
|
5064
|
+
commands: [
|
|
5065
|
+
{
|
|
5066
|
+
command: "council auction",
|
|
5067
|
+
args: { day: String(c.args.day), slot: String(c.args.slot) },
|
|
5068
|
+
description: "Check auction status"
|
|
5069
|
+
}
|
|
5070
|
+
]
|
|
5071
|
+
}
|
|
5072
|
+
}
|
|
5073
|
+
);
|
|
5074
|
+
}
|
|
5075
|
+
});
|
|
5076
|
+
council.command("settle", {
|
|
5077
|
+
description: "Settle a completed council seat auction.",
|
|
5078
|
+
hint: "Requires PRIVATE_KEY environment variable for signing.",
|
|
5079
|
+
args: z2.object({
|
|
5080
|
+
day: z2.coerce.number().int().nonnegative().describe("Auction day index"),
|
|
5081
|
+
slot: z2.coerce.number().int().nonnegative().describe("Slot index within day")
|
|
5082
|
+
}),
|
|
5083
|
+
options: writeOptions,
|
|
5084
|
+
env: writeEnv,
|
|
5085
|
+
output: z2.object({
|
|
5086
|
+
day: z2.number(),
|
|
5087
|
+
slot: z2.number(),
|
|
5088
|
+
highestBidder: z2.string(),
|
|
5089
|
+
highestBid: z2.string(),
|
|
5090
|
+
tx: txResultOutput
|
|
5091
|
+
}),
|
|
5092
|
+
examples: [
|
|
5093
|
+
{
|
|
5094
|
+
args: { day: 0, slot: 0 },
|
|
5095
|
+
description: "Settle the auction for day 0, slot 0"
|
|
5096
|
+
}
|
|
5097
|
+
],
|
|
5098
|
+
async run(c) {
|
|
5099
|
+
const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
5100
|
+
const slotsPerDay = await client.readContract({
|
|
5101
|
+
abi: councilSeatsAbi,
|
|
5102
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
5103
|
+
functionName: "AUCTION_SLOTS_PER_DAY"
|
|
5104
|
+
});
|
|
5105
|
+
if (c.args.slot >= Number(slotsPerDay)) {
|
|
5106
|
+
return c.error({
|
|
5107
|
+
code: "OUT_OF_RANGE",
|
|
5108
|
+
message: `Slot ${c.args.slot} does not exist (max: ${Number(slotsPerDay) - 1})`,
|
|
5109
|
+
retryable: false
|
|
5110
|
+
});
|
|
5111
|
+
}
|
|
5112
|
+
const [auctionTuple, windowEnd, latestBlock, currentAuctionDay, currentAuctionSlot] = await Promise.all([
|
|
5113
|
+
client.readContract({
|
|
5114
|
+
abi: councilSeatsAbi,
|
|
5115
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
5116
|
+
functionName: "auctions",
|
|
5117
|
+
args: [BigInt(c.args.day), c.args.slot]
|
|
5118
|
+
}),
|
|
5119
|
+
client.readContract({
|
|
5120
|
+
abi: councilSeatsAbi,
|
|
5121
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
5122
|
+
functionName: "auctionWindowEnd",
|
|
5123
|
+
args: [BigInt(c.args.day), c.args.slot]
|
|
5124
|
+
}),
|
|
5125
|
+
client.getBlock({ blockTag: "latest" }),
|
|
5126
|
+
client.readContract({
|
|
5127
|
+
abi: councilSeatsAbi,
|
|
5128
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
5129
|
+
functionName: "currentAuctionDay"
|
|
5130
|
+
}),
|
|
5131
|
+
client.readContract({
|
|
5132
|
+
abi: councilSeatsAbi,
|
|
5133
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
5134
|
+
functionName: "currentAuctionSlot"
|
|
5135
|
+
})
|
|
5136
|
+
]);
|
|
5137
|
+
const auction = decodeAuction(auctionTuple);
|
|
5138
|
+
const windowEndTimestamp = windowEnd;
|
|
5139
|
+
const currentTimestamp = latestBlock.timestamp;
|
|
5140
|
+
const execution = deriveAuctionExecutionState({
|
|
5141
|
+
day: c.args.day,
|
|
5142
|
+
slot: c.args.slot,
|
|
5143
|
+
currentAuctionDay,
|
|
5144
|
+
currentAuctionSlot,
|
|
5145
|
+
settled: auction.settled,
|
|
5146
|
+
windowEnd: windowEndTimestamp,
|
|
5147
|
+
currentTimestamp
|
|
5148
|
+
});
|
|
5149
|
+
if (execution.executionStatus === "settled") {
|
|
5150
|
+
return c.error({
|
|
5151
|
+
code: "ALREADY_SETTLED",
|
|
5152
|
+
message: `Auction (day=${c.args.day}, slot=${c.args.slot}) is already settled.`,
|
|
5153
|
+
retryable: false
|
|
5154
|
+
});
|
|
5155
|
+
}
|
|
5156
|
+
if (execution.executionStatus === "open_now") {
|
|
5157
|
+
return c.error({
|
|
5158
|
+
code: "AUCTION_STILL_ACTIVE",
|
|
5159
|
+
message: `Auction (day=${c.args.day}, slot=${c.args.slot}) is still accepting bids. Window ends ${relTime(windowEndTimestamp)}.`,
|
|
5160
|
+
retryable: false
|
|
5161
|
+
});
|
|
5162
|
+
}
|
|
5163
|
+
if (execution.executionStatus === "upcoming") {
|
|
5164
|
+
return c.error({
|
|
5165
|
+
code: "AUCTION_STILL_ACTIVE",
|
|
5166
|
+
message: `Auction (day=${c.args.day}, slot=${c.args.slot}) is not yet the active slot. Current slot is day=${Number(currentAuctionDay)}, slot=${Number(currentAuctionSlot)}.`,
|
|
5167
|
+
retryable: false
|
|
5168
|
+
});
|
|
5169
|
+
}
|
|
5170
|
+
const txResult = await assemblyWriteTx({
|
|
5171
|
+
env: c.env,
|
|
5172
|
+
options: c.options,
|
|
5173
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
5174
|
+
abi: councilSeatsAbi,
|
|
5175
|
+
functionName: "settleAuction",
|
|
5176
|
+
args: [BigInt(c.args.day), c.args.slot]
|
|
5177
|
+
});
|
|
5178
|
+
return c.ok(
|
|
5179
|
+
{
|
|
5180
|
+
day: c.args.day,
|
|
5181
|
+
slot: c.args.slot,
|
|
5182
|
+
highestBidder: toChecksum(auction.highestBidder),
|
|
5183
|
+
highestBid: eth(auction.highestBid),
|
|
5184
|
+
tx: txResult
|
|
5185
|
+
},
|
|
5186
|
+
c.format === "json" || c.format === "jsonl" ? void 0 : {
|
|
5187
|
+
cta: {
|
|
5188
|
+
description: "Next steps:",
|
|
5189
|
+
commands: [
|
|
5190
|
+
{
|
|
5191
|
+
command: "council seats",
|
|
5192
|
+
description: "View updated council seats"
|
|
5193
|
+
}
|
|
5194
|
+
]
|
|
5195
|
+
}
|
|
5196
|
+
}
|
|
5197
|
+
);
|
|
5198
|
+
}
|
|
5199
|
+
});
|
|
5200
|
+
council.command("withdraw-refund", {
|
|
5201
|
+
description: "Withdraw pending bid refunds for the signer address.",
|
|
5202
|
+
hint: "Requires PRIVATE_KEY environment variable for signing.",
|
|
5203
|
+
options: writeOptions,
|
|
5204
|
+
env: writeEnv,
|
|
5205
|
+
output: z2.object({
|
|
5206
|
+
address: z2.string(),
|
|
5207
|
+
refundAmount: z2.string(),
|
|
5208
|
+
refundAmountWei: z2.string(),
|
|
5209
|
+
tx: txResultOutput.optional()
|
|
5210
|
+
}),
|
|
5211
|
+
examples: [{ description: "Withdraw all pending bid refunds" }],
|
|
5212
|
+
async run(c) {
|
|
5213
|
+
const account = resolveAccount(c.env);
|
|
5214
|
+
const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
5215
|
+
const pendingAmount = await client.readContract({
|
|
5216
|
+
abi: councilSeatsAbi,
|
|
5217
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
5218
|
+
functionName: "pendingReturns",
|
|
5219
|
+
args: [account.address]
|
|
5220
|
+
});
|
|
5221
|
+
if (pendingAmount === 0n) {
|
|
5222
|
+
return c.ok({
|
|
5223
|
+
address: toChecksum(account.address),
|
|
5224
|
+
refundAmount: "0 ETH",
|
|
5225
|
+
refundAmountWei: "0"
|
|
5226
|
+
});
|
|
5227
|
+
}
|
|
5228
|
+
const txResult = await assemblyWriteTx({
|
|
5229
|
+
env: c.env,
|
|
5230
|
+
options: c.options,
|
|
5231
|
+
address: ABSTRACT_MAINNET_ADDRESSES.councilSeats,
|
|
5232
|
+
abi: councilSeatsAbi,
|
|
5233
|
+
functionName: "withdrawRefund"
|
|
5234
|
+
});
|
|
5235
|
+
return c.ok({
|
|
5236
|
+
address: toChecksum(account.address),
|
|
5237
|
+
refundAmount: eth(pendingAmount),
|
|
5238
|
+
refundAmountWei: pendingAmount.toString(),
|
|
5239
|
+
tx: txResult
|
|
5240
|
+
});
|
|
5241
|
+
}
|
|
5242
|
+
});
|
|
4808
5243
|
|
|
4809
5244
|
// src/commands/forum.ts
|
|
4810
|
-
import { Cli as Cli2, z as
|
|
4811
|
-
var env2 =
|
|
4812
|
-
ABSTRACT_RPC_URL:
|
|
5245
|
+
import { Cli as Cli2, z as z3 } from "incur";
|
|
5246
|
+
var env2 = z3.object({
|
|
5247
|
+
ABSTRACT_RPC_URL: z3.string().optional().describe("Abstract RPC URL override")
|
|
4813
5248
|
});
|
|
4814
|
-
var timestampOutput2 =
|
|
5249
|
+
var timestampOutput2 = z3.union([z3.number(), z3.string()]);
|
|
4815
5250
|
function decodeThread(value) {
|
|
4816
5251
|
const [id, kind, author, createdAt, category, title, body, proposalId, petitionId] = value;
|
|
4817
5252
|
return {
|
|
@@ -4869,19 +5304,19 @@ var forum = Cli2.create("forum", {
|
|
|
4869
5304
|
forum.command("threads", {
|
|
4870
5305
|
description: "List forum threads with author and creation metadata.",
|
|
4871
5306
|
env: env2,
|
|
4872
|
-
output:
|
|
4873
|
-
threads:
|
|
4874
|
-
|
|
4875
|
-
id:
|
|
4876
|
-
kind:
|
|
4877
|
-
author:
|
|
5307
|
+
output: z3.object({
|
|
5308
|
+
threads: z3.array(
|
|
5309
|
+
z3.object({
|
|
5310
|
+
id: z3.number(),
|
|
5311
|
+
kind: z3.number(),
|
|
5312
|
+
author: z3.string(),
|
|
4878
5313
|
createdAt: timestampOutput2,
|
|
4879
|
-
createdAtRelative:
|
|
4880
|
-
category:
|
|
4881
|
-
title:
|
|
5314
|
+
createdAtRelative: z3.string(),
|
|
5315
|
+
category: z3.string().nullable().optional(),
|
|
5316
|
+
title: z3.string().nullable().optional()
|
|
4882
5317
|
})
|
|
4883
5318
|
),
|
|
4884
|
-
count:
|
|
5319
|
+
count: z3.number()
|
|
4885
5320
|
}),
|
|
4886
5321
|
examples: [{ description: "List all forum threads" }],
|
|
4887
5322
|
async run(c) {
|
|
@@ -4930,13 +5365,13 @@ forum.command("threads", {
|
|
|
4930
5365
|
});
|
|
4931
5366
|
forum.command("thread", {
|
|
4932
5367
|
description: "Get one thread and all comments associated with it.",
|
|
4933
|
-
args:
|
|
4934
|
-
id:
|
|
5368
|
+
args: z3.object({
|
|
5369
|
+
id: z3.coerce.number().int().positive().describe("Thread id (1-indexed)")
|
|
4935
5370
|
}),
|
|
4936
5371
|
env: env2,
|
|
4937
|
-
output:
|
|
4938
|
-
thread:
|
|
4939
|
-
comments:
|
|
5372
|
+
output: z3.object({
|
|
5373
|
+
thread: z3.record(z3.string(), z3.unknown()),
|
|
5374
|
+
comments: z3.array(z3.record(z3.string(), z3.unknown()))
|
|
4940
5375
|
}),
|
|
4941
5376
|
examples: [{ args: { id: 1 }, description: "Fetch thread #1 and its comments" }],
|
|
4942
5377
|
async run(c) {
|
|
@@ -4986,11 +5421,11 @@ forum.command("thread", {
|
|
|
4986
5421
|
});
|
|
4987
5422
|
forum.command("comments", {
|
|
4988
5423
|
description: "List comments for a thread id.",
|
|
4989
|
-
args:
|
|
4990
|
-
threadId:
|
|
5424
|
+
args: z3.object({
|
|
5425
|
+
threadId: z3.coerce.number().int().positive().describe("Thread id to filter comments by")
|
|
4991
5426
|
}),
|
|
4992
5427
|
env: env2,
|
|
4993
|
-
output:
|
|
5428
|
+
output: z3.array(z3.record(z3.string(), z3.unknown())),
|
|
4994
5429
|
examples: [{ args: { threadId: 1 }, description: "List comments for thread #1" }],
|
|
4995
5430
|
async run(c) {
|
|
4996
5431
|
const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
@@ -5017,11 +5452,11 @@ forum.command("comments", {
|
|
|
5017
5452
|
});
|
|
5018
5453
|
forum.command("comment", {
|
|
5019
5454
|
description: "Get one comment by comment id.",
|
|
5020
|
-
args:
|
|
5021
|
-
id:
|
|
5455
|
+
args: z3.object({
|
|
5456
|
+
id: z3.coerce.number().int().positive().describe("Comment id (1-indexed)")
|
|
5022
5457
|
}),
|
|
5023
5458
|
env: env2,
|
|
5024
|
-
output:
|
|
5459
|
+
output: z3.record(z3.string(), z3.unknown()),
|
|
5025
5460
|
examples: [{ args: { id: 1 }, description: "Fetch comment #1" }],
|
|
5026
5461
|
async run(c) {
|
|
5027
5462
|
const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
@@ -5049,7 +5484,7 @@ forum.command("comment", {
|
|
|
5049
5484
|
forum.command("petitions", {
|
|
5050
5485
|
description: "List petitions submitted in the forum contract.",
|
|
5051
5486
|
env: env2,
|
|
5052
|
-
output:
|
|
5487
|
+
output: z3.array(z3.record(z3.string(), z3.unknown())),
|
|
5053
5488
|
examples: [{ description: "List all petitions" }],
|
|
5054
5489
|
async run(c) {
|
|
5055
5490
|
const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
@@ -5074,11 +5509,11 @@ forum.command("petitions", {
|
|
|
5074
5509
|
});
|
|
5075
5510
|
forum.command("petition", {
|
|
5076
5511
|
description: "Get one petition plus whether proposer already signed it.",
|
|
5077
|
-
args:
|
|
5078
|
-
id:
|
|
5512
|
+
args: z3.object({
|
|
5513
|
+
id: z3.coerce.number().int().positive().describe("Petition id (1-indexed)")
|
|
5079
5514
|
}),
|
|
5080
5515
|
env: env2,
|
|
5081
|
-
output:
|
|
5516
|
+
output: z3.object({ proposerSigned: z3.boolean() }).passthrough(),
|
|
5082
5517
|
examples: [{ args: { id: 1 }, description: "Fetch petition #1" }],
|
|
5083
5518
|
async run(c) {
|
|
5084
5519
|
const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
@@ -5113,15 +5548,15 @@ forum.command("petition", {
|
|
|
5113
5548
|
});
|
|
5114
5549
|
forum.command("has-signed", {
|
|
5115
5550
|
description: "Check whether an address signed a petition.",
|
|
5116
|
-
args:
|
|
5117
|
-
petitionId:
|
|
5118
|
-
address:
|
|
5551
|
+
args: z3.object({
|
|
5552
|
+
petitionId: z3.coerce.number().int().positive().describe("Petition id (1-indexed)"),
|
|
5553
|
+
address: z3.string().describe("Signer address to check")
|
|
5119
5554
|
}),
|
|
5120
5555
|
env: env2,
|
|
5121
|
-
output:
|
|
5122
|
-
petitionId:
|
|
5123
|
-
address:
|
|
5124
|
-
hasSigned:
|
|
5556
|
+
output: z3.object({
|
|
5557
|
+
petitionId: z3.number(),
|
|
5558
|
+
address: z3.string(),
|
|
5559
|
+
hasSigned: z3.boolean()
|
|
5125
5560
|
}),
|
|
5126
5561
|
examples: [
|
|
5127
5562
|
{
|
|
@@ -5146,11 +5581,11 @@ forum.command("has-signed", {
|
|
|
5146
5581
|
forum.command("stats", {
|
|
5147
5582
|
description: "Read top-level forum counters and petition threshold.",
|
|
5148
5583
|
env: env2,
|
|
5149
|
-
output:
|
|
5150
|
-
threadCount:
|
|
5151
|
-
commentCount:
|
|
5152
|
-
petitionCount:
|
|
5153
|
-
petitionThresholdBps:
|
|
5584
|
+
output: z3.object({
|
|
5585
|
+
threadCount: z3.number(),
|
|
5586
|
+
commentCount: z3.number(),
|
|
5587
|
+
petitionCount: z3.number(),
|
|
5588
|
+
petitionThresholdBps: z3.number()
|
|
5154
5589
|
}),
|
|
5155
5590
|
examples: [{ description: "Get forum counts and petition threshold" }],
|
|
5156
5591
|
async run(c) {
|
|
@@ -5187,11 +5622,11 @@ forum.command("stats", {
|
|
|
5187
5622
|
});
|
|
5188
5623
|
|
|
5189
5624
|
// src/commands/governance.ts
|
|
5190
|
-
import { Cli as Cli3, z as
|
|
5191
|
-
var env3 =
|
|
5192
|
-
ABSTRACT_RPC_URL:
|
|
5625
|
+
import { Cli as Cli3, z as z4 } from "incur";
|
|
5626
|
+
var env3 = z4.object({
|
|
5627
|
+
ABSTRACT_RPC_URL: z4.string().optional().describe("Abstract RPC URL override")
|
|
5193
5628
|
});
|
|
5194
|
-
var timestampOutput3 =
|
|
5629
|
+
var timestampOutput3 = z4.union([z4.number(), z4.string()]);
|
|
5195
5630
|
var proposalStatusLabels = {
|
|
5196
5631
|
0: "pending",
|
|
5197
5632
|
1: "active",
|
|
@@ -5207,31 +5642,31 @@ function proposalStatus(status) {
|
|
|
5207
5642
|
statusCode
|
|
5208
5643
|
};
|
|
5209
5644
|
}
|
|
5210
|
-
var proposalOutputSchema =
|
|
5211
|
-
kind:
|
|
5212
|
-
configRiskTier:
|
|
5213
|
-
origin:
|
|
5214
|
-
status:
|
|
5215
|
-
statusCode:
|
|
5216
|
-
proposer:
|
|
5217
|
-
threadId:
|
|
5218
|
-
petitionId:
|
|
5219
|
-
createdAt:
|
|
5220
|
-
deliberationEndsAt:
|
|
5221
|
-
voteStartAt:
|
|
5222
|
-
voteEndAt:
|
|
5223
|
-
timelockEndsAt:
|
|
5224
|
-
activeSeatsSnapshot:
|
|
5225
|
-
forVotes:
|
|
5226
|
-
againstVotes:
|
|
5227
|
-
abstainVotes:
|
|
5228
|
-
amount:
|
|
5229
|
-
snapshotAssetBalance:
|
|
5230
|
-
transferIntent:
|
|
5231
|
-
intentDeadline:
|
|
5232
|
-
intentMaxRiskTier:
|
|
5233
|
-
title:
|
|
5234
|
-
description:
|
|
5645
|
+
var proposalOutputSchema = z4.object({
|
|
5646
|
+
kind: z4.number(),
|
|
5647
|
+
configRiskTier: z4.number(),
|
|
5648
|
+
origin: z4.number(),
|
|
5649
|
+
status: z4.string(),
|
|
5650
|
+
statusCode: z4.number(),
|
|
5651
|
+
proposer: z4.string(),
|
|
5652
|
+
threadId: z4.number(),
|
|
5653
|
+
petitionId: z4.number(),
|
|
5654
|
+
createdAt: z4.number(),
|
|
5655
|
+
deliberationEndsAt: z4.number(),
|
|
5656
|
+
voteStartAt: z4.number(),
|
|
5657
|
+
voteEndAt: z4.number(),
|
|
5658
|
+
timelockEndsAt: z4.number(),
|
|
5659
|
+
activeSeatsSnapshot: z4.number(),
|
|
5660
|
+
forVotes: z4.string(),
|
|
5661
|
+
againstVotes: z4.string(),
|
|
5662
|
+
abstainVotes: z4.string(),
|
|
5663
|
+
amount: z4.string(),
|
|
5664
|
+
snapshotAssetBalance: z4.string(),
|
|
5665
|
+
transferIntent: z4.boolean(),
|
|
5666
|
+
intentDeadline: z4.number(),
|
|
5667
|
+
intentMaxRiskTier: z4.number(),
|
|
5668
|
+
title: z4.string(),
|
|
5669
|
+
description: z4.string()
|
|
5235
5670
|
});
|
|
5236
5671
|
function decodeProposal(value) {
|
|
5237
5672
|
const [
|
|
@@ -5320,19 +5755,19 @@ var governance = Cli3.create("governance", {
|
|
|
5320
5755
|
governance.command("proposals", {
|
|
5321
5756
|
description: "List governance proposals with status and vote end time.",
|
|
5322
5757
|
env: env3,
|
|
5323
|
-
output:
|
|
5324
|
-
proposals:
|
|
5325
|
-
|
|
5326
|
-
id:
|
|
5327
|
-
kind:
|
|
5328
|
-
status:
|
|
5329
|
-
statusCode:
|
|
5330
|
-
title:
|
|
5758
|
+
output: z4.object({
|
|
5759
|
+
proposals: z4.array(
|
|
5760
|
+
z4.object({
|
|
5761
|
+
id: z4.number(),
|
|
5762
|
+
kind: z4.number(),
|
|
5763
|
+
status: z4.string(),
|
|
5764
|
+
statusCode: z4.number(),
|
|
5765
|
+
title: z4.string().nullable().optional(),
|
|
5331
5766
|
voteEndAt: timestampOutput3,
|
|
5332
|
-
voteEndRelative:
|
|
5767
|
+
voteEndRelative: z4.string()
|
|
5333
5768
|
})
|
|
5334
5769
|
),
|
|
5335
|
-
count:
|
|
5770
|
+
count: z4.number()
|
|
5336
5771
|
}),
|
|
5337
5772
|
examples: [{ description: "List all proposals" }],
|
|
5338
5773
|
async run(c) {
|
|
@@ -5380,8 +5815,8 @@ governance.command("proposals", {
|
|
|
5380
5815
|
});
|
|
5381
5816
|
governance.command("proposal", {
|
|
5382
5817
|
description: "Get full raw proposal details by proposal id.",
|
|
5383
|
-
args:
|
|
5384
|
-
id:
|
|
5818
|
+
args: z4.object({
|
|
5819
|
+
id: z4.coerce.number().int().positive().describe("Proposal id (1-indexed)")
|
|
5385
5820
|
}),
|
|
5386
5821
|
env: env3,
|
|
5387
5822
|
output: proposalOutputSchema,
|
|
@@ -5413,15 +5848,15 @@ governance.command("proposal", {
|
|
|
5413
5848
|
});
|
|
5414
5849
|
governance.command("has-voted", {
|
|
5415
5850
|
description: "Check if an address has voted on a proposal.",
|
|
5416
|
-
args:
|
|
5417
|
-
proposalId:
|
|
5418
|
-
address:
|
|
5851
|
+
args: z4.object({
|
|
5852
|
+
proposalId: z4.coerce.number().int().positive().describe("Proposal id (1-indexed)"),
|
|
5853
|
+
address: z4.string().describe("Voter address")
|
|
5419
5854
|
}),
|
|
5420
5855
|
env: env3,
|
|
5421
|
-
output:
|
|
5422
|
-
proposalId:
|
|
5423
|
-
address:
|
|
5424
|
-
hasVoted:
|
|
5856
|
+
output: z4.object({
|
|
5857
|
+
proposalId: z4.number(),
|
|
5858
|
+
address: z4.string(),
|
|
5859
|
+
hasVoted: z4.boolean()
|
|
5425
5860
|
}),
|
|
5426
5861
|
examples: [
|
|
5427
5862
|
{
|
|
@@ -5450,19 +5885,19 @@ governance.command("has-voted", {
|
|
|
5450
5885
|
governance.command("params", {
|
|
5451
5886
|
description: "Read governance threshold and timing parameters.",
|
|
5452
5887
|
env: env3,
|
|
5453
|
-
output:
|
|
5454
|
-
deliberationPeriod:
|
|
5455
|
-
votePeriod:
|
|
5456
|
-
quorumBps:
|
|
5457
|
-
constitutionalDeliberationPeriod:
|
|
5458
|
-
constitutionalVotePeriod:
|
|
5459
|
-
constitutionalPassBps:
|
|
5460
|
-
majorPassBps:
|
|
5461
|
-
parameterPassBps:
|
|
5462
|
-
significantPassBps:
|
|
5463
|
-
significantThresholdBps:
|
|
5464
|
-
routineThresholdBps:
|
|
5465
|
-
timelockPeriod:
|
|
5888
|
+
output: z4.object({
|
|
5889
|
+
deliberationPeriod: z4.number(),
|
|
5890
|
+
votePeriod: z4.number(),
|
|
5891
|
+
quorumBps: z4.number(),
|
|
5892
|
+
constitutionalDeliberationPeriod: z4.number(),
|
|
5893
|
+
constitutionalVotePeriod: z4.number(),
|
|
5894
|
+
constitutionalPassBps: z4.number(),
|
|
5895
|
+
majorPassBps: z4.number(),
|
|
5896
|
+
parameterPassBps: z4.number(),
|
|
5897
|
+
significantPassBps: z4.number(),
|
|
5898
|
+
significantThresholdBps: z4.number(),
|
|
5899
|
+
routineThresholdBps: z4.number(),
|
|
5900
|
+
timelockPeriod: z4.number()
|
|
5466
5901
|
}),
|
|
5467
5902
|
examples: [{ description: "Inspect governance timing and pass thresholds" }],
|
|
5468
5903
|
async run(c) {
|
|
@@ -5507,16 +5942,26 @@ governance.command("params", {
|
|
|
5507
5942
|
});
|
|
5508
5943
|
|
|
5509
5944
|
// src/commands/members.ts
|
|
5510
|
-
import {
|
|
5945
|
+
import { TxError } from "@spectratools/tx-shared";
|
|
5946
|
+
import { Cli as Cli4, z as z5 } from "incur";
|
|
5511
5947
|
var DEFAULT_MEMBER_SNAPSHOT_URL = "https://www.theaiassembly.org/api/indexer/members";
|
|
5512
5948
|
var REGISTERED_EVENT_SCAN_STEP = 100000n;
|
|
5513
5949
|
var REGISTERED_EVENT_SCAN_TIMEOUT_MS = 2e4;
|
|
5514
|
-
var
|
|
5515
|
-
|
|
5516
|
-
|
|
5950
|
+
var MAX_MEMBER_LOOKUP_SUGGESTIONS = 5;
|
|
5951
|
+
var env4 = z5.object({
|
|
5952
|
+
ABSTRACT_RPC_URL: z5.string().optional().describe("Abstract RPC URL override"),
|
|
5953
|
+
ASSEMBLY_INDEXER_URL: z5.string().optional().describe("Optional members snapshot endpoint (default: theaiassembly.org indexer)")
|
|
5517
5954
|
});
|
|
5518
|
-
var timestampOutput4 =
|
|
5519
|
-
var
|
|
5955
|
+
var timestampOutput4 = z5.union([z5.number(), z5.string()]);
|
|
5956
|
+
var memberSnapshotEntrySchema = z5.union([
|
|
5957
|
+
z5.string(),
|
|
5958
|
+
z5.object({
|
|
5959
|
+
address: z5.string(),
|
|
5960
|
+
ens: z5.string().optional(),
|
|
5961
|
+
name: z5.string().optional()
|
|
5962
|
+
})
|
|
5963
|
+
]);
|
|
5964
|
+
var memberSnapshotSchema = z5.array(memberSnapshotEntrySchema);
|
|
5520
5965
|
var AssemblyApiValidationError = class extends Error {
|
|
5521
5966
|
constructor(details) {
|
|
5522
5967
|
super("Assembly API response validation failed");
|
|
@@ -5531,6 +5976,45 @@ var AssemblyIndexerUnavailableError = class extends Error {
|
|
|
5531
5976
|
this.name = "AssemblyIndexerUnavailableError";
|
|
5532
5977
|
}
|
|
5533
5978
|
};
|
|
5979
|
+
function mergeMemberIdentities(entries) {
|
|
5980
|
+
const byAddress = /* @__PURE__ */ new Map();
|
|
5981
|
+
for (const entry of entries) {
|
|
5982
|
+
const key = entry.address.toLowerCase();
|
|
5983
|
+
const existing = byAddress.get(key);
|
|
5984
|
+
if (!existing) {
|
|
5985
|
+
byAddress.set(key, entry);
|
|
5986
|
+
continue;
|
|
5987
|
+
}
|
|
5988
|
+
const merged = { address: existing.address };
|
|
5989
|
+
const ens = existing.ens ?? entry.ens;
|
|
5990
|
+
const name = existing.name ?? entry.name;
|
|
5991
|
+
if (ens !== void 0) merged.ens = ens;
|
|
5992
|
+
if (name !== void 0) merged.name = name;
|
|
5993
|
+
byAddress.set(key, merged);
|
|
5994
|
+
}
|
|
5995
|
+
return [...byAddress.values()];
|
|
5996
|
+
}
|
|
5997
|
+
function memberSnapshotEntryToIdentity(entry) {
|
|
5998
|
+
if (typeof entry === "string") return { address: entry };
|
|
5999
|
+
const identity = { address: entry.address };
|
|
6000
|
+
if (entry.ens !== void 0) identity.ens = entry.ens;
|
|
6001
|
+
if (entry.name !== void 0) identity.name = entry.name;
|
|
6002
|
+
return identity;
|
|
6003
|
+
}
|
|
6004
|
+
function matchableAddressInput(query) {
|
|
6005
|
+
return query.startsWith("0x") && query.length === 42;
|
|
6006
|
+
}
|
|
6007
|
+
function searchMemberIdentities(query, members2) {
|
|
6008
|
+
const needle = query.trim().toLowerCase();
|
|
6009
|
+
if (needle.length === 0) return [];
|
|
6010
|
+
const exactMatches = members2.filter((member) => {
|
|
6011
|
+
return member.address.toLowerCase() === needle || member.ens?.toLowerCase() === needle || member.name?.toLowerCase() === needle;
|
|
6012
|
+
});
|
|
6013
|
+
if (exactMatches.length > 0) return exactMatches;
|
|
6014
|
+
return members2.filter((member) => {
|
|
6015
|
+
return member.address.toLowerCase().includes(needle) || member.ens?.toLowerCase().includes(needle) || member.name?.toLowerCase().includes(needle);
|
|
6016
|
+
});
|
|
6017
|
+
}
|
|
5534
6018
|
async function memberSnapshot(url) {
|
|
5535
6019
|
let res;
|
|
5536
6020
|
try {
|
|
@@ -5553,7 +6037,7 @@ async function memberSnapshot(url) {
|
|
|
5553
6037
|
const json = await res.json();
|
|
5554
6038
|
const parsed = memberSnapshotSchema.safeParse(json);
|
|
5555
6039
|
if (parsed.success) {
|
|
5556
|
-
return parsed.data;
|
|
6040
|
+
return mergeMemberIdentities(parsed.data.map(memberSnapshotEntryToIdentity));
|
|
5557
6041
|
}
|
|
5558
6042
|
throw new AssemblyApiValidationError({
|
|
5559
6043
|
code: "INVALID_ASSEMBLY_API_RESPONSE",
|
|
@@ -5597,7 +6081,28 @@ async function membersFromRegisteredEvents(client) {
|
|
|
5597
6081
|
}
|
|
5598
6082
|
}
|
|
5599
6083
|
}
|
|
5600
|
-
return [...addresses];
|
|
6084
|
+
return [...addresses].map((address) => ({ address }));
|
|
6085
|
+
}
|
|
6086
|
+
async function loadMemberIdentities(client, snapshotUrl) {
|
|
6087
|
+
try {
|
|
6088
|
+
return { members: await memberSnapshot(snapshotUrl) };
|
|
6089
|
+
} catch (error) {
|
|
6090
|
+
if (error instanceof AssemblyApiValidationError) {
|
|
6091
|
+
throw error;
|
|
6092
|
+
}
|
|
6093
|
+
if (!(error instanceof AssemblyIndexerUnavailableError)) {
|
|
6094
|
+
throw error;
|
|
6095
|
+
}
|
|
6096
|
+
const fallbackMembers = await withTimeout(
|
|
6097
|
+
membersFromRegisteredEvents(client),
|
|
6098
|
+
REGISTERED_EVENT_SCAN_TIMEOUT_MS,
|
|
6099
|
+
`Registered event fallback scan timed out after ${REGISTERED_EVENT_SCAN_TIMEOUT_MS}ms`
|
|
6100
|
+
);
|
|
6101
|
+
return {
|
|
6102
|
+
members: mergeMemberIdentities(fallbackMembers),
|
|
6103
|
+
fallbackReason: error.details
|
|
6104
|
+
};
|
|
6105
|
+
}
|
|
5601
6106
|
}
|
|
5602
6107
|
function indexerIssue(details) {
|
|
5603
6108
|
if (typeof details.status === "number") {
|
|
@@ -5618,25 +6123,31 @@ function emitIndexerFallbackWarning(details) {
|
|
|
5618
6123
|
`
|
|
5619
6124
|
);
|
|
5620
6125
|
}
|
|
6126
|
+
function describeMember(member) {
|
|
6127
|
+
const parts = [toChecksum(member.address)];
|
|
6128
|
+
if (member.ens) parts.push(`ens=${member.ens}`);
|
|
6129
|
+
if (member.name) parts.push(`name=${member.name}`);
|
|
6130
|
+
return parts.join(" ");
|
|
6131
|
+
}
|
|
5621
6132
|
var members = Cli4.create("members", {
|
|
5622
6133
|
description: "Inspect Assembly membership and registry fee state."
|
|
5623
6134
|
});
|
|
5624
6135
|
members.command("list", {
|
|
5625
6136
|
description: "List members from an indexer snapshot (or Registered event fallback) plus on-chain active state.",
|
|
5626
6137
|
env: env4,
|
|
5627
|
-
output:
|
|
5628
|
-
members:
|
|
5629
|
-
|
|
5630
|
-
address:
|
|
5631
|
-
active:
|
|
5632
|
-
registered:
|
|
6138
|
+
output: z5.object({
|
|
6139
|
+
members: z5.array(
|
|
6140
|
+
z5.object({
|
|
6141
|
+
address: z5.string(),
|
|
6142
|
+
active: z5.boolean(),
|
|
6143
|
+
registered: z5.boolean(),
|
|
5633
6144
|
activeUntil: timestampOutput4,
|
|
5634
|
-
activeUntilRelative:
|
|
6145
|
+
activeUntilRelative: z5.string(),
|
|
5635
6146
|
lastHeartbeatAt: timestampOutput4,
|
|
5636
|
-
lastHeartbeatRelative:
|
|
6147
|
+
lastHeartbeatRelative: z5.string()
|
|
5637
6148
|
})
|
|
5638
6149
|
),
|
|
5639
|
-
count:
|
|
6150
|
+
count: z5.number()
|
|
5640
6151
|
}),
|
|
5641
6152
|
examples: [
|
|
5642
6153
|
{ description: "List members using default indexer snapshot" },
|
|
@@ -5645,10 +6156,12 @@ members.command("list", {
|
|
|
5645
6156
|
async run(c) {
|
|
5646
6157
|
const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
5647
6158
|
const snapshotUrl = c.env.ASSEMBLY_INDEXER_URL ?? DEFAULT_MEMBER_SNAPSHOT_URL;
|
|
5648
|
-
let
|
|
6159
|
+
let memberIdentities;
|
|
5649
6160
|
let fallbackReason;
|
|
5650
6161
|
try {
|
|
5651
|
-
|
|
6162
|
+
const loaded = await loadMemberIdentities(client, snapshotUrl);
|
|
6163
|
+
memberIdentities = loaded.members;
|
|
6164
|
+
fallbackReason = loaded.fallbackReason;
|
|
5652
6165
|
} catch (error) {
|
|
5653
6166
|
if (error instanceof AssemblyApiValidationError) {
|
|
5654
6167
|
return c.error({
|
|
@@ -5657,27 +6170,19 @@ members.command("list", {
|
|
|
5657
6170
|
retryable: false
|
|
5658
6171
|
});
|
|
5659
6172
|
}
|
|
5660
|
-
if (!(error instanceof
|
|
6173
|
+
if (!(error instanceof Error)) {
|
|
5661
6174
|
throw error;
|
|
5662
6175
|
}
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
`Registered event fallback scan timed out after ${REGISTERED_EVENT_SCAN_TIMEOUT_MS}ms`
|
|
5669
|
-
);
|
|
5670
|
-
} catch (fallbackError) {
|
|
5671
|
-
return c.error({
|
|
5672
|
-
code: "MEMBER_LIST_SOURCE_UNAVAILABLE",
|
|
5673
|
-
message: `Member indexer unavailable (${indexerIssue(error.details)} at ${error.details.url}) and on-chain Registered event fallback failed: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`,
|
|
5674
|
-
retryable: true
|
|
5675
|
-
});
|
|
5676
|
-
}
|
|
6176
|
+
return c.error({
|
|
6177
|
+
code: "MEMBER_LIST_SOURCE_UNAVAILABLE",
|
|
6178
|
+
message: `Unable to load member list from indexer (${snapshotUrl}) or on-chain fallback: ${error.message}`,
|
|
6179
|
+
retryable: true
|
|
6180
|
+
});
|
|
5677
6181
|
}
|
|
5678
6182
|
if (fallbackReason) {
|
|
5679
6183
|
emitIndexerFallbackWarning(fallbackReason);
|
|
5680
6184
|
}
|
|
6185
|
+
const addresses = memberIdentities.map((member) => member.address);
|
|
5681
6186
|
const calls = addresses.flatMap((address) => [
|
|
5682
6187
|
{
|
|
5683
6188
|
abi: registryAbi,
|
|
@@ -5713,43 +6218,91 @@ members.command("list", {
|
|
|
5713
6218
|
}
|
|
5714
6219
|
});
|
|
5715
6220
|
members.command("info", {
|
|
5716
|
-
description: "Get registry record and active status
|
|
5717
|
-
args:
|
|
5718
|
-
address:
|
|
6221
|
+
description: "Get member registry record and active status by full address, partial address, ENS, or name.",
|
|
6222
|
+
args: z5.object({
|
|
6223
|
+
address: z5.string().describe("Member lookup query (full/partial address, ENS, or name metadata)")
|
|
5719
6224
|
}),
|
|
5720
6225
|
env: env4,
|
|
5721
|
-
output:
|
|
5722
|
-
address:
|
|
5723
|
-
active:
|
|
6226
|
+
output: z5.object({
|
|
6227
|
+
address: z5.string(),
|
|
6228
|
+
active: z5.boolean(),
|
|
5724
6229
|
activeUntil: timestampOutput4,
|
|
5725
6230
|
lastHeartbeatAt: timestampOutput4,
|
|
5726
|
-
activeUntilRelative:
|
|
5727
|
-
lastHeartbeatRelative:
|
|
6231
|
+
activeUntilRelative: z5.string(),
|
|
6232
|
+
lastHeartbeatRelative: z5.string()
|
|
5728
6233
|
}),
|
|
5729
6234
|
examples: [
|
|
5730
6235
|
{
|
|
5731
6236
|
args: { address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" },
|
|
5732
6237
|
description: "Inspect one member address"
|
|
6238
|
+
},
|
|
6239
|
+
{
|
|
6240
|
+
args: { address: "a96045" },
|
|
6241
|
+
description: "Lookup a member by partial address"
|
|
5733
6242
|
}
|
|
5734
6243
|
],
|
|
5735
6244
|
async run(c) {
|
|
5736
6245
|
const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
6246
|
+
const snapshotUrl = c.env.ASSEMBLY_INDEXER_URL ?? DEFAULT_MEMBER_SNAPSHOT_URL;
|
|
6247
|
+
let lookupAddress = c.args.address;
|
|
6248
|
+
if (!matchableAddressInput(c.args.address)) {
|
|
6249
|
+
let loadedMembers;
|
|
6250
|
+
let fallbackReason;
|
|
6251
|
+
try {
|
|
6252
|
+
const loaded = await loadMemberIdentities(client, snapshotUrl);
|
|
6253
|
+
loadedMembers = loaded.members;
|
|
6254
|
+
fallbackReason = loaded.fallbackReason;
|
|
6255
|
+
} catch (error) {
|
|
6256
|
+
if (error instanceof AssemblyApiValidationError) {
|
|
6257
|
+
return c.error({
|
|
6258
|
+
code: error.details.code,
|
|
6259
|
+
message: `Member snapshot response failed validation. url=${error.details.url}; issues=${JSON.stringify(error.details.issues)}; response=${JSON.stringify(error.details.response)}`,
|
|
6260
|
+
retryable: false
|
|
6261
|
+
});
|
|
6262
|
+
}
|
|
6263
|
+
return c.error({
|
|
6264
|
+
code: "MEMBER_LOOKUP_SOURCE_UNAVAILABLE",
|
|
6265
|
+
message: error instanceof Error ? `Unable to resolve member query from indexer (${snapshotUrl}) or on-chain fallback: ${error.message}` : `Unable to resolve member query from indexer (${snapshotUrl}) or on-chain fallback.`,
|
|
6266
|
+
retryable: true
|
|
6267
|
+
});
|
|
6268
|
+
}
|
|
6269
|
+
if (fallbackReason) {
|
|
6270
|
+
emitIndexerFallbackWarning(fallbackReason);
|
|
6271
|
+
}
|
|
6272
|
+
const matches = searchMemberIdentities(c.args.address, loadedMembers);
|
|
6273
|
+
if (matches.length === 0) {
|
|
6274
|
+
return c.error({
|
|
6275
|
+
code: "MEMBER_NOT_FOUND",
|
|
6276
|
+
message: `No Assembly member matched "${c.args.address}". Try a longer query or run \`assembly members list\` first.`,
|
|
6277
|
+
retryable: false
|
|
6278
|
+
});
|
|
6279
|
+
}
|
|
6280
|
+
if (matches.length > 1) {
|
|
6281
|
+
const suggestions = matches.slice(0, MAX_MEMBER_LOOKUP_SUGGESTIONS).map(describeMember).join("; ");
|
|
6282
|
+
return c.error({
|
|
6283
|
+
code: "AMBIGUOUS_MEMBER_QUERY",
|
|
6284
|
+
message: `Member query "${c.args.address}" matched ${matches.length} members. Be more specific. Matches: ${suggestions}`,
|
|
6285
|
+
retryable: false
|
|
6286
|
+
});
|
|
6287
|
+
}
|
|
6288
|
+
lookupAddress = matches[0].address;
|
|
6289
|
+
}
|
|
5737
6290
|
const [member, active] = await Promise.all([
|
|
5738
6291
|
client.readContract({
|
|
5739
6292
|
abi: registryAbi,
|
|
5740
6293
|
address: ABSTRACT_MAINNET_ADDRESSES.registry,
|
|
5741
6294
|
functionName: "members",
|
|
5742
|
-
args: [
|
|
6295
|
+
args: [lookupAddress]
|
|
5743
6296
|
}),
|
|
5744
6297
|
client.readContract({
|
|
5745
6298
|
abi: registryAbi,
|
|
5746
6299
|
address: ABSTRACT_MAINNET_ADDRESSES.registry,
|
|
5747
6300
|
functionName: "isActive",
|
|
5748
|
-
args: [
|
|
6301
|
+
args: [lookupAddress]
|
|
5749
6302
|
})
|
|
5750
6303
|
]);
|
|
5751
6304
|
return c.ok({
|
|
5752
|
-
address: toChecksum(
|
|
6305
|
+
address: toChecksum(lookupAddress),
|
|
5753
6306
|
active,
|
|
5754
6307
|
activeUntil: timeValue(member.activeUntil, c.format),
|
|
5755
6308
|
lastHeartbeatAt: timeValue(member.lastHeartbeatAt, c.format),
|
|
@@ -5761,9 +6314,9 @@ members.command("info", {
|
|
|
5761
6314
|
members.command("count", {
|
|
5762
6315
|
description: "Get active and total-known member counts from Registry.",
|
|
5763
6316
|
env: env4,
|
|
5764
|
-
output:
|
|
5765
|
-
active:
|
|
5766
|
-
total:
|
|
6317
|
+
output: z5.object({
|
|
6318
|
+
active: z5.number(),
|
|
6319
|
+
total: z5.number()
|
|
5767
6320
|
}),
|
|
5768
6321
|
examples: [{ description: "Count active and known members" }],
|
|
5769
6322
|
async run(c) {
|
|
@@ -5786,12 +6339,12 @@ members.command("count", {
|
|
|
5786
6339
|
members.command("fees", {
|
|
5787
6340
|
description: "Get registration and heartbeat fee settings.",
|
|
5788
6341
|
env: env4,
|
|
5789
|
-
output:
|
|
5790
|
-
registrationFeeWei:
|
|
5791
|
-
registrationFee:
|
|
5792
|
-
heartbeatFeeWei:
|
|
5793
|
-
heartbeatFee:
|
|
5794
|
-
heartbeatGracePeriodSeconds:
|
|
6342
|
+
output: z5.object({
|
|
6343
|
+
registrationFeeWei: z5.string(),
|
|
6344
|
+
registrationFee: z5.string(),
|
|
6345
|
+
heartbeatFeeWei: z5.string(),
|
|
6346
|
+
heartbeatFee: z5.string(),
|
|
6347
|
+
heartbeatGracePeriodSeconds: z5.number()
|
|
5795
6348
|
}),
|
|
5796
6349
|
examples: [{ description: "Inspect current registry fee configuration" }],
|
|
5797
6350
|
async run(c) {
|
|
@@ -5822,23 +6375,196 @@ members.command("fees", {
|
|
|
5822
6375
|
});
|
|
5823
6376
|
}
|
|
5824
6377
|
});
|
|
6378
|
+
var txOutputSchema = z5.union([
|
|
6379
|
+
z5.object({
|
|
6380
|
+
status: z5.enum(["success", "reverted"]),
|
|
6381
|
+
hash: z5.string(),
|
|
6382
|
+
blockNumber: z5.number(),
|
|
6383
|
+
gasUsed: z5.string(),
|
|
6384
|
+
from: z5.string(),
|
|
6385
|
+
to: z5.string().nullable(),
|
|
6386
|
+
effectiveGasPrice: z5.string().optional(),
|
|
6387
|
+
fee: z5.string(),
|
|
6388
|
+
feeEth: z5.string()
|
|
6389
|
+
}),
|
|
6390
|
+
z5.object({
|
|
6391
|
+
status: z5.literal("dry-run"),
|
|
6392
|
+
estimatedGas: z5.string(),
|
|
6393
|
+
simulationResult: z5.unknown(),
|
|
6394
|
+
fee: z5.string(),
|
|
6395
|
+
feeEth: z5.string()
|
|
6396
|
+
})
|
|
6397
|
+
]);
|
|
6398
|
+
members.command("register", {
|
|
6399
|
+
description: "Register as a new Assembly member (pays the registration fee).",
|
|
6400
|
+
hint: "Requires PRIVATE_KEY environment variable for signing.",
|
|
6401
|
+
env: writeEnv,
|
|
6402
|
+
options: writeOptions,
|
|
6403
|
+
output: txOutputSchema,
|
|
6404
|
+
examples: [
|
|
6405
|
+
{ description: "Register as a member" },
|
|
6406
|
+
{ options: { "dry-run": true }, description: "Simulate registration without broadcasting" }
|
|
6407
|
+
],
|
|
6408
|
+
async run(c) {
|
|
6409
|
+
const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
6410
|
+
const fee = await client.readContract({
|
|
6411
|
+
abi: registryAbi,
|
|
6412
|
+
address: ABSTRACT_MAINNET_ADDRESSES.registry,
|
|
6413
|
+
functionName: "registrationFee"
|
|
6414
|
+
});
|
|
6415
|
+
process.stderr.write(
|
|
6416
|
+
`${JSON.stringify({ level: "info", message: `Registration fee: ${eth(fee)} (${fee} wei)` })}
|
|
6417
|
+
`
|
|
6418
|
+
);
|
|
6419
|
+
try {
|
|
6420
|
+
const result = await assemblyWriteTx({
|
|
6421
|
+
env: c.env,
|
|
6422
|
+
options: c.options,
|
|
6423
|
+
address: ABSTRACT_MAINNET_ADDRESSES.registry,
|
|
6424
|
+
abi: registryAbi,
|
|
6425
|
+
functionName: "register",
|
|
6426
|
+
value: fee
|
|
6427
|
+
});
|
|
6428
|
+
return c.ok(
|
|
6429
|
+
{ ...result, fee: fee.toString(), feeEth: eth(fee) },
|
|
6430
|
+
result.status === "success" ? {
|
|
6431
|
+
cta: {
|
|
6432
|
+
description: "Check your membership:",
|
|
6433
|
+
commands: [{ command: "members info", args: { address: result.from } }]
|
|
6434
|
+
}
|
|
6435
|
+
} : void 0
|
|
6436
|
+
);
|
|
6437
|
+
} catch (error) {
|
|
6438
|
+
if (error instanceof TxError && error.code === "INSUFFICIENT_FUNDS") {
|
|
6439
|
+
return c.error({
|
|
6440
|
+
code: "INSUFFICIENT_FUNDS",
|
|
6441
|
+
message: `Insufficient funds to register. Required fee: ${eth(fee)} (${fee} wei). ${error.message}`,
|
|
6442
|
+
retryable: false
|
|
6443
|
+
});
|
|
6444
|
+
}
|
|
6445
|
+
throw error;
|
|
6446
|
+
}
|
|
6447
|
+
}
|
|
6448
|
+
});
|
|
6449
|
+
members.command("heartbeat", {
|
|
6450
|
+
description: "Send a heartbeat to extend active membership (pays the heartbeat fee).",
|
|
6451
|
+
hint: "Requires PRIVATE_KEY environment variable for signing.",
|
|
6452
|
+
env: writeEnv,
|
|
6453
|
+
options: writeOptions,
|
|
6454
|
+
output: txOutputSchema,
|
|
6455
|
+
examples: [
|
|
6456
|
+
{ description: "Send a heartbeat" },
|
|
6457
|
+
{ options: { "dry-run": true }, description: "Simulate heartbeat without broadcasting" }
|
|
6458
|
+
],
|
|
6459
|
+
async run(c) {
|
|
6460
|
+
const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
6461
|
+
const fee = await client.readContract({
|
|
6462
|
+
abi: registryAbi,
|
|
6463
|
+
address: ABSTRACT_MAINNET_ADDRESSES.registry,
|
|
6464
|
+
functionName: "heartbeatFee"
|
|
6465
|
+
});
|
|
6466
|
+
process.stderr.write(
|
|
6467
|
+
`${JSON.stringify({ level: "info", message: `Heartbeat fee: ${eth(fee)} (${fee} wei)` })}
|
|
6468
|
+
`
|
|
6469
|
+
);
|
|
6470
|
+
try {
|
|
6471
|
+
const result = await assemblyWriteTx({
|
|
6472
|
+
env: c.env,
|
|
6473
|
+
options: c.options,
|
|
6474
|
+
address: ABSTRACT_MAINNET_ADDRESSES.registry,
|
|
6475
|
+
abi: registryAbi,
|
|
6476
|
+
functionName: "heartbeat",
|
|
6477
|
+
value: fee
|
|
6478
|
+
});
|
|
6479
|
+
return c.ok(
|
|
6480
|
+
{ ...result, fee: fee.toString(), feeEth: eth(fee) },
|
|
6481
|
+
result.status === "success" ? {
|
|
6482
|
+
cta: {
|
|
6483
|
+
description: "Check your membership:",
|
|
6484
|
+
commands: [{ command: "members info", args: { address: result.from } }]
|
|
6485
|
+
}
|
|
6486
|
+
} : void 0
|
|
6487
|
+
);
|
|
6488
|
+
} catch (error) {
|
|
6489
|
+
if (error instanceof TxError && error.code === "INSUFFICIENT_FUNDS") {
|
|
6490
|
+
return c.error({
|
|
6491
|
+
code: "INSUFFICIENT_FUNDS",
|
|
6492
|
+
message: `Insufficient funds for heartbeat. Required fee: ${eth(fee)} (${fee} wei). ${error.message}`,
|
|
6493
|
+
retryable: false
|
|
6494
|
+
});
|
|
6495
|
+
}
|
|
6496
|
+
throw error;
|
|
6497
|
+
}
|
|
6498
|
+
}
|
|
6499
|
+
});
|
|
6500
|
+
members.command("renew", {
|
|
6501
|
+
description: "Renew an expired membership (pays the registration fee).",
|
|
6502
|
+
hint: "Requires PRIVATE_KEY environment variable for signing. Calls register() to re-activate expired membership.",
|
|
6503
|
+
env: writeEnv,
|
|
6504
|
+
options: writeOptions,
|
|
6505
|
+
output: txOutputSchema,
|
|
6506
|
+
examples: [
|
|
6507
|
+
{ description: "Renew expired membership" },
|
|
6508
|
+
{ options: { "dry-run": true }, description: "Simulate renewal without broadcasting" }
|
|
6509
|
+
],
|
|
6510
|
+
async run(c) {
|
|
6511
|
+
const client = createAssemblyPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
6512
|
+
const fee = await client.readContract({
|
|
6513
|
+
abi: registryAbi,
|
|
6514
|
+
address: ABSTRACT_MAINNET_ADDRESSES.registry,
|
|
6515
|
+
functionName: "registrationFee"
|
|
6516
|
+
});
|
|
6517
|
+
process.stderr.write(
|
|
6518
|
+
`${JSON.stringify({ level: "info", message: `Renewal fee: ${eth(fee)} (${fee} wei)` })}
|
|
6519
|
+
`
|
|
6520
|
+
);
|
|
6521
|
+
try {
|
|
6522
|
+
const result = await assemblyWriteTx({
|
|
6523
|
+
env: c.env,
|
|
6524
|
+
options: c.options,
|
|
6525
|
+
address: ABSTRACT_MAINNET_ADDRESSES.registry,
|
|
6526
|
+
abi: registryAbi,
|
|
6527
|
+
functionName: "register",
|
|
6528
|
+
value: fee
|
|
6529
|
+
});
|
|
6530
|
+
return c.ok(
|
|
6531
|
+
{ ...result, fee: fee.toString(), feeEth: eth(fee) },
|
|
6532
|
+
result.status === "success" ? {
|
|
6533
|
+
cta: {
|
|
6534
|
+
description: "Check your membership:",
|
|
6535
|
+
commands: [{ command: "members info", args: { address: result.from } }]
|
|
6536
|
+
}
|
|
6537
|
+
} : void 0
|
|
6538
|
+
);
|
|
6539
|
+
} catch (error) {
|
|
6540
|
+
if (error instanceof TxError && error.code === "INSUFFICIENT_FUNDS") {
|
|
6541
|
+
return c.error({
|
|
6542
|
+
code: "INSUFFICIENT_FUNDS",
|
|
6543
|
+
message: `Insufficient funds to renew. Required fee: ${eth(fee)} (${fee} wei). ${error.message}`,
|
|
6544
|
+
retryable: false
|
|
6545
|
+
});
|
|
6546
|
+
}
|
|
6547
|
+
throw error;
|
|
6548
|
+
}
|
|
6549
|
+
}
|
|
6550
|
+
});
|
|
5825
6551
|
|
|
5826
6552
|
// src/commands/treasury.ts
|
|
5827
|
-
import { Cli as Cli5, z as
|
|
5828
|
-
var env5 =
|
|
5829
|
-
ABSTRACT_RPC_URL:
|
|
6553
|
+
import { Cli as Cli5, z as z6 } from "incur";
|
|
6554
|
+
var env5 = z6.object({
|
|
6555
|
+
ABSTRACT_RPC_URL: z6.string().optional().describe("Abstract RPC URL override")
|
|
5830
6556
|
});
|
|
5831
|
-
var timestampOutput5 =
|
|
6557
|
+
var timestampOutput5 = z6.union([z6.number(), z6.string()]);
|
|
5832
6558
|
var treasury = Cli5.create("treasury", {
|
|
5833
6559
|
description: "Inspect treasury balances, execution status, and spend controls."
|
|
5834
6560
|
});
|
|
5835
6561
|
treasury.command("balance", {
|
|
5836
6562
|
description: "Get current native token balance for the treasury contract.",
|
|
5837
6563
|
env: env5,
|
|
5838
|
-
output:
|
|
5839
|
-
address:
|
|
5840
|
-
balanceWei:
|
|
5841
|
-
balance:
|
|
6564
|
+
output: z6.object({
|
|
6565
|
+
address: z6.string(),
|
|
6566
|
+
balanceWei: z6.string(),
|
|
6567
|
+
balance: z6.string()
|
|
5842
6568
|
}),
|
|
5843
6569
|
examples: [{ description: "Check treasury balance" }],
|
|
5844
6570
|
async run(c) {
|
|
@@ -5853,13 +6579,13 @@ treasury.command("balance", {
|
|
|
5853
6579
|
});
|
|
5854
6580
|
treasury.command("whitelist", {
|
|
5855
6581
|
description: "Check whether an asset address is treasury-whitelisted.",
|
|
5856
|
-
args:
|
|
5857
|
-
asset:
|
|
6582
|
+
args: z6.object({
|
|
6583
|
+
asset: z6.string().describe("Token/asset contract address")
|
|
5858
6584
|
}),
|
|
5859
6585
|
env: env5,
|
|
5860
|
-
output:
|
|
5861
|
-
asset:
|
|
5862
|
-
whitelisted:
|
|
6586
|
+
output: z6.object({
|
|
6587
|
+
asset: z6.string(),
|
|
6588
|
+
whitelisted: z6.boolean()
|
|
5863
6589
|
}),
|
|
5864
6590
|
examples: [
|
|
5865
6591
|
{
|
|
@@ -5881,11 +6607,11 @@ treasury.command("whitelist", {
|
|
|
5881
6607
|
treasury.command("major-spend-status", {
|
|
5882
6608
|
description: "Read major-spend cooldown status for the treasury contract.",
|
|
5883
6609
|
env: env5,
|
|
5884
|
-
output:
|
|
5885
|
-
majorSpendCooldownSeconds:
|
|
6610
|
+
output: z6.object({
|
|
6611
|
+
majorSpendCooldownSeconds: z6.number(),
|
|
5886
6612
|
lastMajorSpendAt: timestampOutput5,
|
|
5887
|
-
lastMajorSpendRelative:
|
|
5888
|
-
isMajorSpendAllowed:
|
|
6613
|
+
lastMajorSpendRelative: z6.string(),
|
|
6614
|
+
isMajorSpendAllowed: z6.boolean()
|
|
5889
6615
|
}),
|
|
5890
6616
|
examples: [{ description: "Inspect treasury major-spend guardrails" }],
|
|
5891
6617
|
async run(c) {
|
|
@@ -5919,13 +6645,13 @@ treasury.command("major-spend-status", {
|
|
|
5919
6645
|
});
|
|
5920
6646
|
treasury.command("executed", {
|
|
5921
6647
|
description: "Check whether a treasury action for a proposal has executed.",
|
|
5922
|
-
args:
|
|
5923
|
-
proposalId:
|
|
6648
|
+
args: z6.object({
|
|
6649
|
+
proposalId: z6.coerce.number().int().positive().describe("Governance proposal id")
|
|
5924
6650
|
}),
|
|
5925
6651
|
env: env5,
|
|
5926
|
-
output:
|
|
5927
|
-
proposalId:
|
|
5928
|
-
executed:
|
|
6652
|
+
output: z6.object({
|
|
6653
|
+
proposalId: z6.number(),
|
|
6654
|
+
executed: z6.boolean()
|
|
5929
6655
|
}),
|
|
5930
6656
|
examples: [{ args: { proposalId: 1 }, description: "Check execution status for proposal #1" }],
|
|
5931
6657
|
async run(c) {
|
|
@@ -6091,20 +6817,20 @@ cli.command(council);
|
|
|
6091
6817
|
cli.command(forum);
|
|
6092
6818
|
cli.command(governance);
|
|
6093
6819
|
cli.command(treasury);
|
|
6094
|
-
var rootEnv =
|
|
6095
|
-
ABSTRACT_RPC_URL:
|
|
6820
|
+
var rootEnv = z7.object({
|
|
6821
|
+
ABSTRACT_RPC_URL: z7.string().optional().describe("Abstract RPC URL override")
|
|
6096
6822
|
});
|
|
6097
|
-
var timestampOutput6 =
|
|
6823
|
+
var timestampOutput6 = z7.union([z7.number(), z7.string()]);
|
|
6098
6824
|
cli.command("status", {
|
|
6099
6825
|
description: "Get a cross-contract Assembly snapshot (members, council, governance, treasury).",
|
|
6100
6826
|
env: rootEnv,
|
|
6101
|
-
output:
|
|
6102
|
-
activeMemberCount:
|
|
6103
|
-
seatCount:
|
|
6104
|
-
proposalCount:
|
|
6105
|
-
currentAuctionDay:
|
|
6106
|
-
currentAuctionSlot:
|
|
6107
|
-
treasuryBalance:
|
|
6827
|
+
output: z7.object({
|
|
6828
|
+
activeMemberCount: z7.number(),
|
|
6829
|
+
seatCount: z7.number(),
|
|
6830
|
+
proposalCount: z7.number(),
|
|
6831
|
+
currentAuctionDay: z7.number(),
|
|
6832
|
+
currentAuctionSlot: z7.number(),
|
|
6833
|
+
treasuryBalance: z7.string()
|
|
6108
6834
|
}),
|
|
6109
6835
|
examples: [{ description: "Fetch the current Assembly system status" }],
|
|
6110
6836
|
async run(c) {
|
|
@@ -6156,18 +6882,18 @@ cli.command("status", {
|
|
|
6156
6882
|
});
|
|
6157
6883
|
cli.command("health", {
|
|
6158
6884
|
description: "Check cross-contract health for one address (membership, council, refunds, power).",
|
|
6159
|
-
args:
|
|
6160
|
-
address:
|
|
6885
|
+
args: z7.object({
|
|
6886
|
+
address: z7.string().describe("Member or wallet address to inspect")
|
|
6161
6887
|
}),
|
|
6162
6888
|
env: rootEnv,
|
|
6163
|
-
output:
|
|
6164
|
-
address:
|
|
6165
|
-
isActive:
|
|
6889
|
+
output: z7.object({
|
|
6890
|
+
address: z7.string(),
|
|
6891
|
+
isActive: z7.boolean(),
|
|
6166
6892
|
activeUntil: timestampOutput6,
|
|
6167
|
-
activeUntilRelative:
|
|
6168
|
-
isCouncilMember:
|
|
6169
|
-
pendingReturnsWei:
|
|
6170
|
-
votingPower:
|
|
6893
|
+
activeUntilRelative: z7.string(),
|
|
6894
|
+
isCouncilMember: z7.boolean(),
|
|
6895
|
+
pendingReturnsWei: z7.string(),
|
|
6896
|
+
votingPower: z7.number()
|
|
6171
6897
|
}),
|
|
6172
6898
|
examples: [
|
|
6173
6899
|
{
|