@gzeoneth/gov-tracker 0.2.1-beta.b2eeb41 → 0.2.1-beta.d575294
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 +81 -2
- package/dist/abis.d.ts +3 -0
- package/dist/abis.d.ts.map +1 -1
- package/dist/abis.js +30 -2
- package/dist/abis.js.map +1 -1
- package/dist/cli/cli.js +265 -27
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/lib/cli.d.ts +48 -2
- package/dist/cli/lib/cli.d.ts.map +1 -1
- package/dist/cli/lib/cli.js +356 -63
- package/dist/cli/lib/cli.js.map +1 -1
- package/dist/cli/lib/json-state.d.ts +23 -0
- package/dist/cli/lib/json-state.d.ts.map +1 -1
- package/dist/cli/lib/json-state.js +51 -4
- package/dist/cli/lib/json-state.js.map +1 -1
- package/dist/constants.d.ts +39 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +47 -2
- package/dist/constants.js.map +1 -1
- package/dist/data/bundled-cache.json +11061 -1460
- package/dist/deduplication.d.ts +132 -0
- package/dist/deduplication.d.ts.map +1 -0
- package/dist/deduplication.js +270 -0
- package/dist/deduplication.js.map +1 -0
- package/dist/discovery/governor-discovery.d.ts.map +1 -1
- package/dist/discovery/governor-discovery.js +50 -35
- package/dist/discovery/governor-discovery.js.map +1 -1
- package/dist/discovery/timelock-discovery.d.ts +15 -6
- package/dist/discovery/timelock-discovery.d.ts.map +1 -1
- package/dist/discovery/timelock-discovery.js +27 -11
- package/dist/discovery/timelock-discovery.js.map +1 -1
- package/dist/election/contracts.d.ts +8 -0
- package/dist/election/contracts.d.ts.map +1 -0
- package/dist/election/contracts.js +28 -0
- package/dist/election/contracts.js.map +1 -0
- package/dist/election/details.d.ts +15 -0
- package/dist/election/details.d.ts.map +1 -0
- package/dist/election/details.js +157 -0
- package/dist/election/details.js.map +1 -0
- package/dist/election/index.d.ts +11 -0
- package/dist/election/index.d.ts.map +1 -0
- package/dist/election/index.js +48 -0
- package/dist/election/index.js.map +1 -0
- package/dist/election/params.d.ts +13 -0
- package/dist/election/params.d.ts.map +1 -0
- package/dist/election/params.js +93 -0
- package/dist/election/params.js.map +1 -0
- package/dist/election/participants.d.ts +6 -0
- package/dist/election/participants.d.ts.map +1 -0
- package/dist/election/participants.js +104 -0
- package/dist/election/participants.js.map +1 -0
- package/dist/election/prepare.d.ts +10 -0
- package/dist/election/prepare.d.ts.map +1 -0
- package/dist/election/prepare.js +52 -0
- package/dist/election/prepare.js.map +1 -0
- package/dist/election/proposal-ids.d.ts +18 -0
- package/dist/election/proposal-ids.d.ts.map +1 -0
- package/dist/election/proposal-ids.js +77 -0
- package/dist/election/proposal-ids.js.map +1 -0
- package/dist/election/status.d.ts +15 -0
- package/dist/election/status.d.ts.map +1 -0
- package/dist/election/status.js +102 -0
- package/dist/election/status.js.map +1 -0
- package/dist/election/tracking.d.ts +28 -0
- package/dist/election/tracking.d.ts.map +1 -0
- package/dist/election/tracking.js +412 -0
- package/dist/election/tracking.js.map +1 -0
- package/dist/index.d.ts +9 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +72 -8
- package/dist/index.js.map +1 -1
- package/dist/stages/builder.d.ts +4 -0
- package/dist/stages/builder.d.ts.map +1 -1
- package/dist/stages/builder.js +7 -0
- package/dist/stages/builder.js.map +1 -1
- package/dist/stages/l2-to-l1-message.d.ts +3 -1
- package/dist/stages/l2-to-l1-message.d.ts.map +1 -1
- package/dist/stages/l2-to-l1-message.js +6 -6
- package/dist/stages/l2-to-l1-message.js.map +1 -1
- package/dist/stages/proposal-created.d.ts +1 -0
- package/dist/stages/proposal-created.d.ts.map +1 -1
- package/dist/stages/proposal-created.js +1 -0
- package/dist/stages/proposal-created.js.map +1 -1
- package/dist/stages/proposal-queued.d.ts +1 -0
- package/dist/stages/proposal-queued.d.ts.map +1 -1
- package/dist/stages/proposal-queued.js +3 -1
- package/dist/stages/proposal-queued.js.map +1 -1
- package/dist/stages/retryables.js +2 -2
- package/dist/stages/retryables.js.map +1 -1
- package/dist/stages/timelock.d.ts +3 -1
- package/dist/stages/timelock.d.ts.map +1 -1
- package/dist/stages/timelock.js +12 -12
- package/dist/stages/timelock.js.map +1 -1
- package/dist/stages/utils.d.ts +5 -9
- package/dist/stages/utils.d.ts.map +1 -1
- package/dist/stages/utils.js +34 -29
- package/dist/stages/utils.js.map +1 -1
- package/dist/stages/voting.d.ts.map +1 -1
- package/dist/stages/voting.js +5 -4
- package/dist/stages/voting.js.map +1 -1
- package/dist/tracker/cache.d.ts +10 -6
- package/dist/tracker/cache.d.ts.map +1 -1
- package/dist/tracker/cache.js +36 -13
- package/dist/tracker/cache.js.map +1 -1
- package/dist/tracker/checkpoint-helpers.d.ts +81 -0
- package/dist/tracker/checkpoint-helpers.d.ts.map +1 -0
- package/dist/tracker/checkpoint-helpers.js +201 -0
- package/dist/tracker/checkpoint-helpers.js.map +1 -0
- package/dist/tracker/discovery.d.ts +40 -9
- package/dist/tracker/discovery.d.ts.map +1 -1
- package/dist/tracker/discovery.js +152 -15
- package/dist/tracker/discovery.js.map +1 -1
- package/dist/tracker/execute.d.ts.map +1 -1
- package/dist/tracker/execute.js +1 -25
- package/dist/tracker/execute.js.map +1 -1
- package/dist/tracker/pipeline.d.ts.map +1 -1
- package/dist/tracker/pipeline.js +26 -11
- package/dist/tracker/pipeline.js.map +1 -1
- package/dist/tracker/query.d.ts +1 -0
- package/dist/tracker/query.d.ts.map +1 -1
- package/dist/tracker/query.js +14 -61
- package/dist/tracker/query.js.map +1 -1
- package/dist/tracker/state.d.ts +0 -10
- package/dist/tracker/state.d.ts.map +1 -1
- package/dist/tracker/state.js +1 -28
- package/dist/tracker/state.js.map +1 -1
- package/dist/tracker.d.ts +100 -8
- package/dist/tracker.d.ts.map +1 -1
- package/dist/tracker.js +405 -42
- package/dist/tracker.js.map +1 -1
- package/dist/types/config.d.ts +49 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/core.d.ts +4 -2
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/election.d.ts +143 -0
- package/dist/types/election.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -7
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -3
- package/dist/types/index.js.map +1 -1
- package/dist/types/stages.d.ts +72 -7
- package/dist/types/stages.d.ts.map +1 -1
- package/dist/types/stages.js.map +1 -1
- package/dist/types/tracking.d.ts +34 -8
- package/dist/types/tracking.d.ts.map +1 -1
- package/dist/utils/block-cache.d.ts +50 -0
- package/dist/utils/block-cache.d.ts.map +1 -0
- package/dist/utils/block-cache.js +80 -0
- package/dist/utils/block-cache.js.map +1 -0
- package/dist/utils/formatters.d.ts +91 -0
- package/dist/utils/formatters.d.ts.map +1 -0
- package/dist/utils/formatters.js +327 -0
- package/dist/utils/formatters.js.map +1 -0
- package/dist/utils/multicall.d.ts +52 -0
- package/dist/utils/multicall.d.ts.map +1 -0
- package/dist/utils/multicall.js +75 -0
- package/dist/utils/multicall.js.map +1 -0
- package/dist/utils/rpc-utils.d.ts +7 -1
- package/dist/utils/rpc-utils.d.ts.map +1 -1
- package/dist/utils/rpc-utils.js +42 -29
- package/dist/utils/rpc-utils.js.map +1 -1
- package/dist/utils/salt-computation.d.ts.map +1 -1
- package/dist/utils/salt-computation.js +33 -7
- package/dist/utils/salt-computation.js.map +1 -1
- package/dist/utils/sanitize.d.ts.map +1 -1
- package/dist/utils/sanitize.js +3 -0
- package/dist/utils/sanitize.js.map +1 -1
- package/dist/utils/stage-metadata.d.ts +0 -20
- package/dist/utils/stage-metadata.d.ts.map +1 -1
- package/dist/utils/stage-metadata.js +29 -44
- package/dist/utils/stage-metadata.js.map +1 -1
- package/dist/utils/timing.d.ts +13 -0
- package/dist/utils/timing.d.ts.map +1 -1
- package/dist/utils/timing.js +37 -1
- package/dist/utils/timing.js.map +1 -1
- package/package.json +3 -2
- package/dist/election.d.ts +0 -172
- package/dist/election.d.ts.map +0 -1
- package/dist/election.js +0 -467
- package/dist/election.js.map +0 -1
- package/dist/types/cross-chain.d.ts +0 -24
- package/dist/types/cross-chain.d.ts.map +0 -1
- package/dist/types/cross-chain.js +0 -6
- package/dist/types/cross-chain.js.map +0 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://codecov.io/gh/gzeoneth/gov-tracker)
|
|
5
5
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
6
6
|
|
|
7
|
-
Track and execute Arbitrum DAO governance proposal lifecycle stages.
|
|
7
|
+
Track and execute Arbitrum DAO governance proposal lifecycle stages and Security Council elections.
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
@@ -80,12 +80,90 @@ npx @gzeoneth/gov-tracker track 0x... -w --private-key $PRIVATE_KEY
|
|
|
80
80
|
# Discover and track all proposals
|
|
81
81
|
npx @gzeoneth/gov-tracker run
|
|
82
82
|
|
|
83
|
+
# Selective tracking (only track specific types)
|
|
84
|
+
npx @gzeoneth/gov-tracker run --track-core # Constitutional proposals only
|
|
85
|
+
npx @gzeoneth/gov-tracker run --track-treasury # Non-constitutional proposals only
|
|
86
|
+
npx @gzeoneth/gov-tracker run --track-elections # Election governors only
|
|
87
|
+
npx @gzeoneth/gov-tracker run --track-timelocks # Direct timelock operations only
|
|
88
|
+
|
|
89
|
+
# Track with elections enabled in run loop
|
|
90
|
+
npx @gzeoneth/gov-tracker run --loop --election
|
|
91
|
+
|
|
83
92
|
# Disable caching
|
|
84
93
|
npx @gzeoneth/gov-tracker track 0x... --no-cache
|
|
94
|
+
|
|
95
|
+
# Interactive TUI (requires ink)
|
|
96
|
+
npx @gzeoneth/gov-tracker ui
|
|
97
|
+
|
|
98
|
+
# Track election creation tx (auto-switches to election view)
|
|
99
|
+
npx @gzeoneth/gov-tracker track 0x82a0baf3...
|
|
85
100
|
```
|
|
86
101
|
|
|
87
102
|
**Shorthands:** `-v` (verbose), `-p` (prepare), `-w` (write), `-i` (inspect)
|
|
88
103
|
|
|
104
|
+
### Interactive TUI
|
|
105
|
+
|
|
106
|
+
The `ui` command launches an interactive terminal interface for browsing proposals:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Browse bundled cache (no RPC required)
|
|
110
|
+
npx @gzeoneth/gov-tracker ui
|
|
111
|
+
|
|
112
|
+
# Enable live tracking with RPC
|
|
113
|
+
npx @gzeoneth/gov-tracker ui --l2-rpc $ARB1_RPC --l1-rpc $ETH_RPC
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Features:**
|
|
117
|
+
- Browse bundled proposals with filter tabs (All, Active, Complete, Timelocks, Elections)
|
|
118
|
+
- View proposal details, voting statistics, and stage progress
|
|
119
|
+
- Inspect decoded calldata with nested parameter display
|
|
120
|
+
- View simulation data for Tenderly/Foundry fork testing
|
|
121
|
+
- Monitor Security Council election status with detailed nominee/member info (requires RPC)
|
|
122
|
+
- Live tracking and discovery when RPC providers are configured
|
|
123
|
+
|
|
124
|
+
**Navigation:**
|
|
125
|
+
| Key | Action |
|
|
126
|
+
|-----|--------|
|
|
127
|
+
| `↑↓` | Navigate |
|
|
128
|
+
| `PgUp/Dn` | Page navigation |
|
|
129
|
+
| `Enter` | View details |
|
|
130
|
+
| `Tab` | Cycle filter |
|
|
131
|
+
| `c` | View calldata |
|
|
132
|
+
| `s` | View simulation |
|
|
133
|
+
| `d` | Discover proposals (with RPC) |
|
|
134
|
+
| `e` | Election status (with RPC) |
|
|
135
|
+
| `r` | Re-track (with RPC) |
|
|
136
|
+
| `b`/`Esc` | Go back |
|
|
137
|
+
| `q` | Quit |
|
|
138
|
+
|
|
139
|
+
**Note:** The TUI requires `ink` and `react` packages (installed as optional dependencies).
|
|
140
|
+
|
|
141
|
+
**Auto-Switch:** When tracking a `createElection` transaction, the CLI automatically displays election-specific status (phase, cohort, nominees) instead of proposal stages.
|
|
142
|
+
|
|
143
|
+
### Elections
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Check election status (next election, can create)
|
|
147
|
+
npx @gzeoneth/gov-tracker election
|
|
148
|
+
|
|
149
|
+
# List all elections with statuses
|
|
150
|
+
npx @gzeoneth/gov-tracker election --list
|
|
151
|
+
|
|
152
|
+
# Track specific election by index
|
|
153
|
+
npx @gzeoneth/gov-tracker election --track 0
|
|
154
|
+
|
|
155
|
+
# Track with detailed nominee/member info
|
|
156
|
+
npx @gzeoneth/gov-tracker election --track 0 --details -v
|
|
157
|
+
|
|
158
|
+
# Create election or execute phase transition
|
|
159
|
+
npx @gzeoneth/gov-tracker election --track 0 -w --private-key $PRIVATE_KEY
|
|
160
|
+
|
|
161
|
+
# Monitor elections in loop mode
|
|
162
|
+
npx @gzeoneth/gov-tracker election --loop --interval 300
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Election Phases:** `NOT_STARTED` → `NOMINEE_SELECTION` → `VETTING_PERIOD` → `MEMBER_ELECTION` → `PENDING_EXECUTION` → `COMPLETED`
|
|
166
|
+
|
|
89
167
|
**Bundled Cache**: The CLI includes a pre-built cache of completed proposals. On first run, this eliminates initial discovery RPC calls. SDK users can access via `getBundledCachePath()` or direct JSON import - see [Examples](./docs/EXAMPLES.md#bundled-cache-bootstrap).
|
|
90
168
|
|
|
91
169
|
## Environment
|
|
@@ -135,7 +213,8 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for development workflow.
|
|
|
135
213
|
|----------|-------------|
|
|
136
214
|
| Constitutional | Core proposals requiring L1 round-trip (8-day L2 timelock) |
|
|
137
215
|
| Non-Constitutional | Treasury proposals, L2-only execution (3-day L2 timelock) |
|
|
138
|
-
| Election | Security Council election
|
|
216
|
+
| Election | Security Council election with 6-phase lifecycle |
|
|
217
|
+
| Cohort | Security Council has two cohorts (0 and 1) that alternate elections |
|
|
139
218
|
|
|
140
219
|
See [Arbitrum governance docs](https://docs.arbitrum.foundation/concepts/lifecycle-anatomy-aip-proposal) for more details.
|
|
141
220
|
|
package/dist/abis.d.ts
CHANGED
|
@@ -44,4 +44,7 @@ export declare const upgradeExecutorInterface: ethers.utils.Interface;
|
|
|
44
44
|
export declare const memberSyncActionInterface: ethers.utils.Interface;
|
|
45
45
|
export declare const proposalCreatedInterface: ethers.utils.Interface;
|
|
46
46
|
export declare const proposalQueuedInterface: ethers.utils.Interface;
|
|
47
|
+
export declare const proposalExecutedInterface: ethers.utils.Interface;
|
|
48
|
+
export declare const nomineeElectionGovernorInterface: ethers.utils.Interface;
|
|
49
|
+
export declare const memberElectionGovernorInterface: ethers.utils.Interface;
|
|
47
50
|
//# sourceMappingURL=abis.d.ts.map
|
package/dist/abis.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abis.d.ts","sourceRoot":"","sources":["../src/abis.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC;;GAEG;AACH,eAAO,MAAM,YAAY,UAmBxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,UAIpC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,UAiBxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,4BAA4B,UAOxC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,UAErB,CAAC;AA0CF;;GAEG;AACH,eAAO,MAAM,6BAA6B,
|
|
1
|
+
{"version":3,"file":"abis.d.ts","sourceRoot":"","sources":["../src/abis.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC;;GAEG;AACH,eAAO,MAAM,YAAY,UAmBxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,UAIpC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,UAiBxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,4BAA4B,UAOxC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,UAErB,CAAC;AA0CF;;GAEG;AACH,eAAO,MAAM,6BAA6B,UAwBzC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,4BAA4B,UAcxC,CAAC;AAoBF,eAAO,MAAM,iBAAiB,wBAA2C,CAAC;AAC1E,eAAO,MAAM,iBAAiB,wBAA2C,CAAC;AAC1E,eAAO,MAAM,eAAe,wBAA0C,CAAC;AACvE,eAAO,MAAM,eAAe,wBAAyC,CAAC;AACtE,eAAO,MAAM,sBAAsB,wBAAiD,CAAC;AACrF,eAAO,MAAM,qBAAqB,wBAAmD,CAAC;AACtF,eAAO,MAAM,wBAAwB,wBAAmD,CAAC;AACzF,eAAO,MAAM,yBAAyB,wBAAqD,CAAC;AAC5F,eAAO,MAAM,wBAAwB,wBAAuD,CAAC;AAC7F,eAAO,MAAM,uBAAuB,wBAAsD,CAAC;AAC3F,eAAO,MAAM,yBAAyB,wBAAwD,CAAC;AAC/F,eAAO,MAAM,gCAAgC,wBAE5C,CAAC;AACF,eAAO,MAAM,+BAA+B,wBAE3C,CAAC"}
|
package/dist/abis.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* repeated interface creation throughout the codebase.
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.proposalQueuedInterface = exports.proposalCreatedInterface = exports.memberSyncActionInterface = exports.upgradeExecutorInterface = exports.arbRetryableInterface = exports.outboxExecuteInterface = exports.outboxInterface = exports.arbSysInterface = exports.timelockInterface = exports.governorInterface = exports.MEMBER_ELECTION_GOVERNOR_ABI = exports.NOMINEE_ELECTION_GOVERNOR_ABI = exports.INBOX_ABI = exports.SECURITY_COUNCIL_MANAGER_ABI = exports.TIMELOCK_ABI = exports.GOVERNOR_WITH_VETTER_ABI = exports.GOVERNOR_ABI = void 0;
|
|
10
|
+
exports.memberElectionGovernorInterface = exports.nomineeElectionGovernorInterface = exports.proposalExecutedInterface = exports.proposalQueuedInterface = exports.proposalCreatedInterface = exports.memberSyncActionInterface = exports.upgradeExecutorInterface = exports.arbRetryableInterface = exports.outboxExecuteInterface = exports.outboxInterface = exports.arbSysInterface = exports.timelockInterface = exports.governorInterface = exports.MEMBER_ELECTION_GOVERNOR_ABI = exports.NOMINEE_ELECTION_GOVERNOR_ABI = exports.INBOX_ABI = exports.SECURITY_COUNCIL_MANAGER_ABI = exports.TIMELOCK_ABI = exports.GOVERNOR_WITH_VETTER_ABI = exports.GOVERNOR_ABI = void 0;
|
|
11
11
|
const ethers_1 = require("ethers");
|
|
12
12
|
/**
|
|
13
13
|
* Governor contract ABI (minimal required interface)
|
|
@@ -128,6 +128,17 @@ exports.NOMINEE_ELECTION_GOVERNOR_ABI = [
|
|
|
128
128
|
"function state(uint256 proposalId) view returns (uint8)",
|
|
129
129
|
"function getProposeArgs(uint256 electionIndex) view returns (address[], uint256[], bytes[], string)",
|
|
130
130
|
"function hashProposal(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) view returns (bytes32)",
|
|
131
|
+
// Detailed nominee tracking
|
|
132
|
+
"function nominees(uint256 proposalId) view returns (address[])",
|
|
133
|
+
"function compliantNominees(uint256 proposalId) view returns (address[])",
|
|
134
|
+
"function votesReceived(uint256 proposalId, address contender) view returns (uint256)",
|
|
135
|
+
"function isExcluded(uint256 proposalId, address nominee) view returns (bool)",
|
|
136
|
+
"function quorum(uint256 blockNumber) view returns (uint256)",
|
|
137
|
+
// Events
|
|
138
|
+
"event ContenderAdded(uint256 indexed proposalId, address indexed contender)",
|
|
139
|
+
"event NewNominee(uint256 indexed proposalId, address indexed nominee)",
|
|
140
|
+
"event NomineeExcluded(uint256 indexed proposalId, address indexed nominee)",
|
|
141
|
+
"event VoteCastForContender(uint256 indexed proposalId, address indexed voter, address indexed contender, uint256 votes, uint256 totalUsedVotes, uint256 usableVotes)",
|
|
131
142
|
];
|
|
132
143
|
/**
|
|
133
144
|
* SecurityCouncilMemberElectionGovernor ABI
|
|
@@ -135,7 +146,17 @@ exports.NOMINEE_ELECTION_GOVERNOR_ABI = [
|
|
|
135
146
|
exports.MEMBER_ELECTION_GOVERNOR_ABI = [
|
|
136
147
|
"function state(uint256 proposalId) view returns (uint8)",
|
|
137
148
|
"function proposalDeadline(uint256 proposalId) view returns (uint256)",
|
|
138
|
-
"function
|
|
149
|
+
"function proposalSnapshot(uint256 proposalId) view returns (uint256)",
|
|
150
|
+
// From ElectionGovernor base - used to compute proposal ID
|
|
151
|
+
"function getProposeArgs(uint256 electionIndex) view returns (address[], uint256[], bytes[], string)",
|
|
152
|
+
"function hashProposal(address[] targets, uint256[] values, bytes[] calldatas, bytes32 descriptionHash) view returns (bytes32)",
|
|
153
|
+
// Detailed member election tracking
|
|
154
|
+
"function weightReceived(uint256 proposalId, address nominee) view returns (uint256)",
|
|
155
|
+
"function topNominees(uint256 proposalId) view returns (address[])",
|
|
156
|
+
"function fullWeightVotingDeadline(uint256 proposalId) view returns (uint256)",
|
|
157
|
+
"function fullWeightDuration() view returns (uint256)",
|
|
158
|
+
// Events
|
|
159
|
+
"event VoteCastForNominee(address indexed voter, uint256 indexed proposalId, address indexed nominee, uint256 votes, uint256 weight, uint256 totalUsedVotes, uint256 usableVotes, uint256 weightReceived)",
|
|
139
160
|
];
|
|
140
161
|
/**
|
|
141
162
|
* ProposalCreated event signature for parsing
|
|
@@ -145,6 +166,10 @@ const PROPOSAL_CREATED_EVENT = "event ProposalCreated(uint256 proposalId, addres
|
|
|
145
166
|
* ProposalQueued event signature for parsing
|
|
146
167
|
*/
|
|
147
168
|
const PROPOSAL_QUEUED_EVENT = "event ProposalQueued(uint256 proposalId, uint256 eta)";
|
|
169
|
+
/**
|
|
170
|
+
* ProposalExecuted event signature for parsing
|
|
171
|
+
*/
|
|
172
|
+
const PROPOSAL_EXECUTED_EVENT = "event ProposalExecuted(uint256 proposalId)";
|
|
148
173
|
// Pre-created Interface instances
|
|
149
174
|
exports.governorInterface = new ethers_1.ethers.utils.Interface(exports.GOVERNOR_ABI);
|
|
150
175
|
exports.timelockInterface = new ethers_1.ethers.utils.Interface(exports.TIMELOCK_ABI);
|
|
@@ -156,4 +181,7 @@ exports.upgradeExecutorInterface = new ethers_1.ethers.utils.Interface(UPGRADE_E
|
|
|
156
181
|
exports.memberSyncActionInterface = new ethers_1.ethers.utils.Interface(MEMBER_SYNC_ACTION_ABI);
|
|
157
182
|
exports.proposalCreatedInterface = new ethers_1.ethers.utils.Interface([PROPOSAL_CREATED_EVENT]);
|
|
158
183
|
exports.proposalQueuedInterface = new ethers_1.ethers.utils.Interface([PROPOSAL_QUEUED_EVENT]);
|
|
184
|
+
exports.proposalExecutedInterface = new ethers_1.ethers.utils.Interface([PROPOSAL_EXECUTED_EVENT]);
|
|
185
|
+
exports.nomineeElectionGovernorInterface = new ethers_1.ethers.utils.Interface(exports.NOMINEE_ELECTION_GOVERNOR_ABI);
|
|
186
|
+
exports.memberElectionGovernorInterface = new ethers_1.ethers.utils.Interface(exports.MEMBER_ELECTION_GOVERNOR_ABI);
|
|
159
187
|
//# sourceMappingURL=abis.js.map
|
package/dist/abis.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abis.js","sourceRoot":"","sources":["../src/abis.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,mCAAgC;AAEhC;;GAEG;AACU,QAAA,YAAY,GAAG;IAC1B,yDAAyD;IACzD,sEAAsE;IACtE,sEAAsE;IACtE,wHAAwH;IACxH,6DAA6D;IAC7D,iEAAiE;IACjE,gDAAgD;IAChD,+CAA+C;IAC/C,gDAAgD;IAChD,4CAA4C;IAC5C,qEAAqE;IACrE,iDAAiD;IACjD,6EAA6E;IAC7E,oCAAoC;IACpC,6EAA6E;IAC7E,8BAA8B;IAC9B,mHAAmH;IACnH,6HAA6H;CAC9H,CAAC;AAEF;;GAEG;AACU,QAAA,wBAAwB,GAAG;IACtC,6EAA6E;IAC7E,0CAA0C;IAC1C,2EAA2E;CAC5E,CAAC;AAEF;;GAEG;AACU,QAAA,YAAY,GAAG;IAC1B,sDAAsD;IACtD,6DAA6D;IAC7D,2DAA2D;IAC3D,0DAA0D;IAC1D,0DAA0D;IAC1D,+CAA+C;IAC/C,sIAAsI;IACtI,yKAAyK;IACzK,oHAAoH;IACpH,oJAAoJ;IACpJ,gHAAgH;IAChH,iIAAiI;IACjI,0DAA0D;IAC1D,yBAAyB;IACzB,+IAA+I;IAC/I,0GAA0G;CAC3G,CAAC;AAEF;;GAEG;AACU,QAAA,4BAA4B,GAAG;IAC1C,8CAA8C;IAC9C,6DAA6D;IAC7D,8DAA8D;IAC9D,+CAA+C;IAC/C,oFAAoF;IACpF,mFAAmF;CACpF,CAAC;AAEF;;GAEG;AACU,QAAA,SAAS,GAAG;IACvB,sGAAsG;CACvG,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,GAAG;IAClB,kDAAkD;IAClD,gFAAgF;IAChF,yMAAyM;CAC1M,CAAC;AAEF;;GAEG;AACH,MAAM,oBAAoB,GAAG,CAAC,+CAA+C,CAAC,CAAC;AAE/E;;GAEG;AACH,MAAM,sBAAsB,GAAG;IAC7B,4FAA4F;CAC7F,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,GAAG;IACjB,+HAA+H;CAChI,CAAC;AAEF;;GAEG;AACH,MAAM,oBAAoB,GAAG,CAAC,4CAA4C,CAAC,CAAC;AAE5E;;GAEG;AACH,MAAM,kBAAkB,GAAG;IACzB,wMAAwM;CACzM,CAAC;AAEF;;GAEG;AACU,QAAA,6BAA6B,GAAG;IAC3C,iDAAiD;IACjD,4EAA4E;IAC5E,4EAA4E;IAC5E,sDAAsD;IACtD,iDAAiD;IACjD,6EAA6E;IAC7E,2EAA2E;IAC3E,sEAAsE;IACtE,sEAAsE;IACtE,yDAAyD;IACzD,qGAAqG;IACrG,+HAA+H;
|
|
1
|
+
{"version":3,"file":"abis.js","sourceRoot":"","sources":["../src/abis.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/cli.js
CHANGED
|
@@ -76,12 +76,10 @@ const fs = __importStar(require("fs"));
|
|
|
76
76
|
const debug_1 = __importDefault(require("debug"));
|
|
77
77
|
// Check for required CLI dependencies (optional in package.json)
|
|
78
78
|
let Command;
|
|
79
|
-
let Option;
|
|
80
79
|
try {
|
|
81
80
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
82
81
|
const commander = require("commander");
|
|
83
82
|
Command = commander.Command;
|
|
84
|
-
Option = commander.Option;
|
|
85
83
|
}
|
|
86
84
|
catch {
|
|
87
85
|
console.error("Error: CLI requires 'commander' package.");
|
|
@@ -273,17 +271,23 @@ runCmd
|
|
|
273
271
|
.option("--json-output <path>", "Write JSON state for dashboard integration")
|
|
274
272
|
.option("--election", "Also check for Security Council elections each cycle")
|
|
275
273
|
.option("--concurrency <n>", "Number of concurrent tracking operations", "1")
|
|
274
|
+
.option("--track-core", "Track constitutional (core) governor proposals")
|
|
275
|
+
.option("--track-treasury", "Track non-constitutional (treasury) governor proposals")
|
|
276
|
+
.option("--track-timelocks", "Track L2 timelock operations (direct schedules)")
|
|
277
|
+
.option("--track-elections", "Track election governor proposals")
|
|
276
278
|
.action(async (opts) => {
|
|
277
279
|
if (opts.verbose)
|
|
278
280
|
debug_1.default.enable("gov-tracker:*");
|
|
281
|
+
(0, cli_1.validateCliOptions)(opts, "run");
|
|
279
282
|
(0, cli_1.requirePrivateKeyForWrite)(opts);
|
|
280
283
|
const providers = (0, cli_1.createProvidersFromOptions)(opts);
|
|
281
284
|
const chunkingConfig = (0, cli_1.parseChunkingConfig)(opts, index_1.CHUNK_SIZES.DELAY_MS);
|
|
282
|
-
// --no-cache disables cache entirely
|
|
285
|
+
// --no-cache disables cache entirely; use autoFlush: false for batch writes
|
|
283
286
|
const cachePath = opts.noCache ? undefined : opts.cache;
|
|
287
|
+
const cache = cachePath ? new index_1.FileCache(cachePath, { autoFlush: false }) : undefined;
|
|
284
288
|
const tracker = (0, index_1.createTracker)({
|
|
285
289
|
...providers,
|
|
286
|
-
|
|
290
|
+
cache,
|
|
287
291
|
chunkingConfig,
|
|
288
292
|
onProgress: createProgressCallback(),
|
|
289
293
|
});
|
|
@@ -299,6 +303,25 @@ runCmd
|
|
|
299
303
|
const intervalMs = parseInt(opts.interval, 10) * 1000;
|
|
300
304
|
const concurrency = parseInt(opts.concurrency, 10);
|
|
301
305
|
const gasSettings = (0, cli_1.parseGasSettings)(opts);
|
|
306
|
+
// Build discovery targets from --track-* flags
|
|
307
|
+
// If any --track-* flag is specified, only track those; otherwise track all
|
|
308
|
+
const hasTrackFlags = opts.trackCore || opts.trackTreasury || opts.trackTimelocks || opts.trackElections;
|
|
309
|
+
// Detect what types are being tracked
|
|
310
|
+
const trackingProposals = !hasTrackFlags || opts.trackCore || opts.trackTreasury;
|
|
311
|
+
const trackingTimelocks = !hasTrackFlags || opts.trackTimelocks;
|
|
312
|
+
const trackingElections = !hasTrackFlags || opts.trackElections;
|
|
313
|
+
// Detect elections-only mode (only --track-elections, no other --track-* flags)
|
|
314
|
+
const electionsOnly = opts.trackElections && !opts.trackCore && !opts.trackTreasury && !opts.trackTimelocks;
|
|
315
|
+
const discoveryTargets = hasTrackFlags
|
|
316
|
+
? {
|
|
317
|
+
constitutionalGovernor: opts.trackCore,
|
|
318
|
+
nonConstitutionalGovernor: opts.trackTreasury,
|
|
319
|
+
l2ConstitutionalTimelock: opts.trackTimelocks,
|
|
320
|
+
l2NonConstitutionalTimelock: opts.trackTimelocks,
|
|
321
|
+
electionNomineeGovernor: opts.trackElections,
|
|
322
|
+
electionMemberGovernor: opts.trackElections,
|
|
323
|
+
}
|
|
324
|
+
: (0, index_1.buildDefaultTargets)();
|
|
302
325
|
if (opts.verbose) {
|
|
303
326
|
if (startBlock !== undefined)
|
|
304
327
|
console.log(`Starting discovery from block ${startBlock}`);
|
|
@@ -307,6 +330,12 @@ runCmd
|
|
|
307
330
|
console.log(`Max consecutive errors before skip: ${cli_1.MAX_CONSECUTIVE_ERRORS}`);
|
|
308
331
|
if (concurrency > 1)
|
|
309
332
|
console.log(`Concurrency: ${concurrency}`);
|
|
333
|
+
if (hasTrackFlags) {
|
|
334
|
+
const enabled = Object.entries(discoveryTargets)
|
|
335
|
+
.filter(([, v]) => v)
|
|
336
|
+
.map(([k]) => k);
|
|
337
|
+
console.log(`Tracking targets: ${enabled.join(", ")}`);
|
|
338
|
+
}
|
|
310
339
|
console.log(`L2 gas: ${gasSettings.maxFeePerGas} gwei maxFee, ${gasSettings.maxPriorityFeePerGas} gwei priority`);
|
|
311
340
|
}
|
|
312
341
|
if (signer)
|
|
@@ -314,12 +343,17 @@ runCmd
|
|
|
314
343
|
// Track whether this is the first cycle (for startBlock override)
|
|
315
344
|
let isFirstCycle = true;
|
|
316
345
|
async function runCycle() {
|
|
317
|
-
|
|
346
|
+
if (electionsOnly) {
|
|
347
|
+
console.log("Tracking elections...\n");
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
console.log("Discovering proposals and operations...\n");
|
|
351
|
+
}
|
|
318
352
|
let electionsSkipped = 0;
|
|
319
353
|
// Only use startBlock on the first cycle; subsequent cycles resume from watermarks
|
|
320
354
|
const cycleStartBlock = isFirstCycle ? startBlock : undefined;
|
|
321
355
|
isFirstCycle = false;
|
|
322
|
-
const { result, proposals, timelockOps } = await (0, cli_1.runMonitorCycle)(tracker, providers, {
|
|
356
|
+
const { result, proposals, timelockOps, elections } = await (0, cli_1.runMonitorCycle)(tracker, providers, {
|
|
323
357
|
prepare: opts.prepare || opts.write || opts.prepareCompleted || opts.preparePending,
|
|
324
358
|
prepareCompleted: opts.prepareCompleted,
|
|
325
359
|
preparePending: opts.preparePending,
|
|
@@ -327,6 +361,9 @@ runCmd
|
|
|
327
361
|
blockLag,
|
|
328
362
|
maxAgeDays,
|
|
329
363
|
concurrency,
|
|
364
|
+
targets: discoveryTargets,
|
|
365
|
+
electionsOnly,
|
|
366
|
+
forceElections: opts.force,
|
|
330
367
|
onTrack: async (r) => {
|
|
331
368
|
// Skip showing complete elections
|
|
332
369
|
if (r.result?.isElection && r.result?.isComplete) {
|
|
@@ -335,7 +372,7 @@ runCmd
|
|
|
335
372
|
}
|
|
336
373
|
if (r.result) {
|
|
337
374
|
console.log(`\n[${r.key}]`);
|
|
338
|
-
|
|
375
|
+
(0, cli_1.displayTrackingResult)(r.result);
|
|
339
376
|
}
|
|
340
377
|
else if (r.error) {
|
|
341
378
|
console.log(`\n[${r.key}] ERROR: ${r.error}`);
|
|
@@ -367,14 +404,36 @@ runCmd
|
|
|
367
404
|
// Skip output if shutting down
|
|
368
405
|
if ((0, cli_1.isShuttingDown)())
|
|
369
406
|
return;
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
407
|
+
// Get checkpoints and calculate filtered stats based on enabled targets
|
|
408
|
+
const checkpoints = await tracker.getAllCheckpoints();
|
|
409
|
+
const stats = (0, cli_1.calculateFilteredStats)(checkpoints, discoveryTargets);
|
|
410
|
+
// Build summary based on what was tracked this run
|
|
411
|
+
if (electionsOnly) {
|
|
412
|
+
// Elections-only mode: count from tracked elections, not cache
|
|
413
|
+
const electionComplete = elections.filter((e) => e.phase === "COMPLETED").length;
|
|
414
|
+
console.log(`\nTracked ${elections.length} elections (${electionComplete}/${elections.length} complete)`);
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
// Discovery mode: show stats for tracked types only
|
|
418
|
+
const electionSummary = trackingElections && elections.length > 0
|
|
419
|
+
? `, ${elections.length} elections (${stats.elections.complete}/${stats.elections.total} complete)`
|
|
420
|
+
: "";
|
|
421
|
+
// Build incomplete stats for tracked types
|
|
422
|
+
const incompleteParts = [];
|
|
423
|
+
if (trackingProposals && stats.proposals.active > 0) {
|
|
424
|
+
incompleteParts.push(`${stats.proposals.active} proposals`);
|
|
425
|
+
}
|
|
426
|
+
if (trackingTimelocks && stats.timelocks.active > 0) {
|
|
427
|
+
incompleteParts.push(`${stats.timelocks.active} timelocks`);
|
|
428
|
+
}
|
|
429
|
+
const incompleteSummary = incompleteParts.length > 0 ? ` | Incomplete: ${incompleteParts.join(", ")}` : "";
|
|
430
|
+
console.log(`\nFound ${proposals.length} new proposals, ${timelockOps.length} new ops${electionSummary}${incompleteSummary} | ` +
|
|
431
|
+
`Tracked: ${result.tracked}, Prepared: ${result.prepared}` +
|
|
432
|
+
(electionsSkipped > 0 ? ` (${electionsSkipped} elections skipped)` : ""));
|
|
433
|
+
}
|
|
375
434
|
if (opts.jsonOutput) {
|
|
376
|
-
const
|
|
377
|
-
(0, json_state_1.writeDashboardState)((0, json_state_1.buildDashboardState)(
|
|
435
|
+
const filteredCheckpoints = (0, cli_1.filterCheckpointsByTargets)(checkpoints, discoveryTargets);
|
|
436
|
+
(0, json_state_1.writeDashboardState)((0, json_state_1.buildDashboardState)(filteredCheckpoints), opts.jsonOutput);
|
|
378
437
|
if (opts.verbose)
|
|
379
438
|
console.log(`JSON state written to ${opts.jsonOutput}`);
|
|
380
439
|
}
|
|
@@ -407,6 +466,8 @@ runCmd
|
|
|
407
466
|
intervalMs,
|
|
408
467
|
healthCheckUrl: opts.healthCheckUrl,
|
|
409
468
|
});
|
|
469
|
+
// Flush cache at end (single write instead of per-item)
|
|
470
|
+
await cache?.flush();
|
|
410
471
|
});
|
|
411
472
|
// ============================================================================
|
|
412
473
|
// Track Command
|
|
@@ -430,6 +491,7 @@ trackCmd
|
|
|
430
491
|
.action(async (txHash, opts) => {
|
|
431
492
|
if (opts.verbose)
|
|
432
493
|
debug_1.default.enable("gov-tracker:*");
|
|
494
|
+
(0, cli_1.validateCliOptions)(opts, "track");
|
|
433
495
|
(0, cli_1.requirePrivateKeyForWrite)(opts);
|
|
434
496
|
try {
|
|
435
497
|
const providers = (0, cli_1.createProvidersFromOptions)(opts);
|
|
@@ -443,14 +505,19 @@ trackCmd
|
|
|
443
505
|
if (opts.force)
|
|
444
506
|
console.log(`Force: ignoring cached data`);
|
|
445
507
|
}
|
|
446
|
-
// Use cache unless --
|
|
447
|
-
|
|
508
|
+
// Use cache unless --no-cache is specified
|
|
509
|
+
// --force clears the cache entry before tracking but still writes results
|
|
510
|
+
const cachePath = opts.noCache ? undefined : opts.cache;
|
|
448
511
|
const tracker = (0, index_1.createTracker)({
|
|
449
512
|
...providers,
|
|
450
513
|
cachePath,
|
|
451
514
|
chunkingConfig,
|
|
452
515
|
onProgress: opts.verbose ? createProgressCallback() : undefined,
|
|
453
516
|
});
|
|
517
|
+
// Clear all cache entries for this tx if --force to ensure fresh tracking
|
|
518
|
+
if (opts.force && cachePath) {
|
|
519
|
+
await tracker.clearTxCacheEntries(txHash);
|
|
520
|
+
}
|
|
454
521
|
let calldatas = [];
|
|
455
522
|
let targets = [];
|
|
456
523
|
let values = [];
|
|
@@ -483,11 +550,16 @@ trackCmd
|
|
|
483
550
|
prepareCompleted: opts.prepareCompleted,
|
|
484
551
|
preparePending: opts.preparePending,
|
|
485
552
|
}, providers);
|
|
553
|
+
if (results.length === 0) {
|
|
554
|
+
console.error("No proposal or timelock operation found in transaction");
|
|
555
|
+
process.exit(1);
|
|
556
|
+
}
|
|
486
557
|
// Format tracking output
|
|
487
|
-
results.
|
|
558
|
+
for (let i = 0; i < results.length; i++) {
|
|
559
|
+
const r = results[i];
|
|
488
560
|
const label = results.length > 1 ? `Operation ${i + 1}/${results.length}` : undefined;
|
|
489
|
-
|
|
490
|
-
}
|
|
561
|
+
(0, cli_1.displayTrackingResult)(r, label);
|
|
562
|
+
}
|
|
491
563
|
// Show all prepared transactions
|
|
492
564
|
if (preparedTransactions.length > 0) {
|
|
493
565
|
console.log(`\n${(0, cli_1.formatMultiplePreparedTransactions)(preparedTransactions)}`);
|
|
@@ -529,12 +601,13 @@ trackCmd
|
|
|
529
601
|
break;
|
|
530
602
|
console.log(`\nRe-tracking to find next stages...`);
|
|
531
603
|
const retracked = await (0, cli_1.trackAndPrepare)(tracker, txHash, { prepare: true }, providers);
|
|
532
|
-
retracked.results.
|
|
604
|
+
for (let i = 0; i < retracked.results.length; i++) {
|
|
605
|
+
const r = retracked.results[i];
|
|
533
606
|
const label = retracked.results.length > 1
|
|
534
607
|
? `Operation ${i + 1}/${retracked.results.length}`
|
|
535
608
|
: undefined;
|
|
536
|
-
|
|
537
|
-
}
|
|
609
|
+
(0, cli_1.displayTrackingResult)(r, label);
|
|
610
|
+
}
|
|
538
611
|
if (retracked.preparedTransactions.length > 0) {
|
|
539
612
|
console.log(`\n${(0, cli_1.formatMultiplePreparedTransactions)(retracked.preparedTransactions)}`);
|
|
540
613
|
}
|
|
@@ -590,16 +663,19 @@ program
|
|
|
590
663
|
.addOption(cli_1.cacheOptions.cache(DEFAULT_CACHE_PATH))
|
|
591
664
|
.option("--json", "Output as JSON")
|
|
592
665
|
.action(async (opts) => {
|
|
593
|
-
const { watermarks, checkpoints } = await index_1.ProposalStageTracker.readCacheStatus(opts.cache);
|
|
666
|
+
const { watermarks, checkpoints, elections } = await index_1.ProposalStageTracker.readCacheStatus(opts.cache);
|
|
594
667
|
if (opts.json) {
|
|
595
668
|
const checkpointsObj = {};
|
|
596
669
|
for (const [key, checkpoint] of checkpoints) {
|
|
597
670
|
checkpointsObj[key] = checkpoint;
|
|
598
671
|
}
|
|
672
|
+
for (const [index, checkpoint] of elections) {
|
|
673
|
+
checkpointsObj[`election:${index}`] = checkpoint;
|
|
674
|
+
}
|
|
599
675
|
console.log(JSON.stringify({ watermarks, checkpoints: checkpointsObj }, null, 2));
|
|
600
676
|
}
|
|
601
677
|
else {
|
|
602
|
-
console.log((0, cli_1.formatCacheStatus)(checkpoints));
|
|
678
|
+
console.log((0, cli_1.formatCacheStatus)(checkpoints, elections));
|
|
603
679
|
}
|
|
604
680
|
});
|
|
605
681
|
// ============================================================================
|
|
@@ -607,19 +683,181 @@ program
|
|
|
607
683
|
// ============================================================================
|
|
608
684
|
const electionCmd = program
|
|
609
685
|
.command("election")
|
|
610
|
-
.description("Check Security Council election status");
|
|
686
|
+
.description("Check Security Council election status and track elections");
|
|
611
687
|
(0, cli_1.addOptions)(electionCmd, cli_1.rpcOptions);
|
|
612
688
|
(0, cli_1.addOptions)(electionCmd, cli_1.loopOptions);
|
|
689
|
+
(0, cli_1.addOptions)(electionCmd, cli_1.executionOptions);
|
|
613
690
|
electionCmd
|
|
691
|
+
.addOption(cli_1.cacheOptions.cache(DEFAULT_CACHE_PATH))
|
|
692
|
+
.addOption(cli_1.cacheOptions.noCache)
|
|
693
|
+
.addOption(cli_1.cacheOptions.force)
|
|
614
694
|
.addOption(cli_1.verboseOption)
|
|
615
|
-
.option("--
|
|
616
|
-
.
|
|
695
|
+
.option("--list", "List all elections with their statuses")
|
|
696
|
+
.option("--track <index>", "Track a specific election by index")
|
|
697
|
+
.option("--details", "Show detailed nominee/member info (use with --track)")
|
|
617
698
|
.action(async (opts) => {
|
|
618
699
|
if (opts.verbose)
|
|
619
700
|
debug_1.default.enable("gov-tracker:*");
|
|
620
701
|
(0, cli_1.requirePrivateKeyForWrite)(opts);
|
|
621
702
|
const providers = (0, cli_1.createProvidersFromOptions)(opts);
|
|
622
703
|
const signer = opts.write ? (0, cli_1.createSigner)(opts.privateKey) : null;
|
|
704
|
+
// Create tracker with cache (unless --no-cache)
|
|
705
|
+
const cachePath = opts.noCache ? undefined : opts.cache;
|
|
706
|
+
const tracker = (0, index_1.createTracker)({
|
|
707
|
+
...providers,
|
|
708
|
+
cachePath,
|
|
709
|
+
});
|
|
710
|
+
// Import election tracking functions for detailed queries
|
|
711
|
+
const { getNomineeElectionDetails, getMemberElectionDetails, prepareMemberElectionTrigger, prepareMemberElectionExecution, } = await Promise.resolve().then(() => __importStar(require("../index")));
|
|
712
|
+
// --list: Show all elections (uses cached data for completed elections)
|
|
713
|
+
if (opts.list) {
|
|
714
|
+
console.log("Fetching all elections...\n");
|
|
715
|
+
// Use --force to bypass cache and re-track all elections
|
|
716
|
+
const elections = await tracker.trackAllElections({ force: opts.force });
|
|
717
|
+
if (elections.length === 0) {
|
|
718
|
+
console.log("No elections found.");
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
console.log(`=== Security Council Elections (${elections.length} total) ===\n`);
|
|
722
|
+
for (const election of elections) {
|
|
723
|
+
const cohortName = election.cohort === 0 ? "First" : "Second";
|
|
724
|
+
console.log(`Election #${election.electionIndex}`);
|
|
725
|
+
console.log(` Phase: ${election.phase}`);
|
|
726
|
+
console.log(` Cohort: ${cohortName} (${election.cohort})`);
|
|
727
|
+
console.log(` Compliant Nominees: ${election.compliantNomineeCount}/${election.targetNomineeCount}`);
|
|
728
|
+
if (election.nomineeProposalId) {
|
|
729
|
+
console.log(` Nominee Proposal: ${election.nomineeProposalState}`);
|
|
730
|
+
}
|
|
731
|
+
if (election.memberProposalId) {
|
|
732
|
+
console.log(` Member Proposal: ${election.memberProposalState}`);
|
|
733
|
+
}
|
|
734
|
+
if (election.canProceedToMemberPhase) {
|
|
735
|
+
console.log(` → Ready to trigger member election`);
|
|
736
|
+
}
|
|
737
|
+
if (election.canExecuteMember) {
|
|
738
|
+
console.log(` → Ready to execute member election`);
|
|
739
|
+
}
|
|
740
|
+
console.log("");
|
|
741
|
+
}
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
// --track <index>: Track specific election (uses cache unless --force)
|
|
745
|
+
if (opts.track !== undefined) {
|
|
746
|
+
const electionIndex = parseInt(opts.track, 10);
|
|
747
|
+
console.log(`Tracking election #${electionIndex}...\n`);
|
|
748
|
+
const election = await tracker.trackElection(electionIndex, { force: opts.force });
|
|
749
|
+
// Use shared formatter for consistent output with stages
|
|
750
|
+
console.log((0, cli_1.formatElectionResult)(election));
|
|
751
|
+
// Show detailed info if requested
|
|
752
|
+
if (opts.details) {
|
|
753
|
+
console.log(`\n--- Detailed Information ---`);
|
|
754
|
+
if (election.nomineeProposalId) {
|
|
755
|
+
const nomineeDetails = await getNomineeElectionDetails(electionIndex, providers.l2Provider);
|
|
756
|
+
if (nomineeDetails) {
|
|
757
|
+
console.log(`\nNominee Election Details:`);
|
|
758
|
+
console.log(` Contenders: ${nomineeDetails.contenders.length}`);
|
|
759
|
+
console.log(` Total Nominees: ${nomineeDetails.nominees.length}`);
|
|
760
|
+
console.log(` Compliant: ${nomineeDetails.compliantNominees.length}`);
|
|
761
|
+
console.log(` Excluded: ${nomineeDetails.excludedNominees.length}`);
|
|
762
|
+
console.log(` Quorum Threshold: ${nomineeDetails.quorumThreshold.toString()} votes`);
|
|
763
|
+
if (nomineeDetails.contenders.length > 0) {
|
|
764
|
+
console.log(`\n Registered Contenders (${nomineeDetails.contenders.length}):`);
|
|
765
|
+
for (const contender of nomineeDetails.contenders) {
|
|
766
|
+
const extra = opts.verbose ? ` (block ${contender.registeredAtBlock})` : "";
|
|
767
|
+
console.log(` ${contender.address}${extra}`);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
if (nomineeDetails.compliantNominees.length > 0) {
|
|
771
|
+
console.log(`\n Qualified Nominees (${nomineeDetails.compliantNominees.length}):`);
|
|
772
|
+
for (const nominee of nomineeDetails.compliantNominees) {
|
|
773
|
+
const extra = opts.verbose && nominee.nominatedAtBlock
|
|
774
|
+
? ` (block ${nominee.nominatedAtBlock})`
|
|
775
|
+
: "";
|
|
776
|
+
console.log(` ${nominee.address}: ${nominee.votesReceived.toString()} votes${extra}`);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
if (nomineeDetails.excludedNominees.length > 0) {
|
|
780
|
+
console.log(`\n Excluded Nominees (${nomineeDetails.excludedNominees.length}):`);
|
|
781
|
+
for (const nominee of nomineeDetails.excludedNominees) {
|
|
782
|
+
const extra = opts.verbose && nominee.excludedAtBlock
|
|
783
|
+
? ` (block ${nominee.excludedAtBlock})`
|
|
784
|
+
: "";
|
|
785
|
+
console.log(` ${nominee.address}: excluded${extra}`);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
if (election.memberProposalId) {
|
|
791
|
+
const memberDetails = await getMemberElectionDetails(electionIndex, providers.l2Provider);
|
|
792
|
+
if (memberDetails) {
|
|
793
|
+
console.log(`\nMember Election Details:`);
|
|
794
|
+
console.log(` Full Weight Deadline: block ${memberDetails.fullWeightDeadline}`);
|
|
795
|
+
console.log(` Proposal Deadline: block ${memberDetails.proposalDeadline}`);
|
|
796
|
+
if (memberDetails.nominees.length > 0) {
|
|
797
|
+
console.log(`\n Candidates by Weight (${memberDetails.nominees.length}):`);
|
|
798
|
+
for (const nominee of memberDetails.nominees) {
|
|
799
|
+
const winnerTag = nominee.isWinner ? " [WINNER]" : "";
|
|
800
|
+
console.log(` #${nominee.rank} ${nominee.address}: ${nominee.weightReceived.toString()}${winnerTag}`);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
if (memberDetails.winners.length > 0) {
|
|
804
|
+
console.log(`\n Elected Members (${memberDetails.winners.length}):`);
|
|
805
|
+
for (const winner of memberDetails.winners) {
|
|
806
|
+
console.log(` ${winner}`);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
function getActionStatus(isReady, isPending, isCompleted) {
|
|
813
|
+
if (isReady)
|
|
814
|
+
return "READY";
|
|
815
|
+
if (isCompleted)
|
|
816
|
+
return "COMPLETED";
|
|
817
|
+
if (isPending)
|
|
818
|
+
return "PENDING";
|
|
819
|
+
return "PENDING";
|
|
820
|
+
}
|
|
821
|
+
// Should we show/prepare this action based on flags?
|
|
822
|
+
function shouldShowAction(status) {
|
|
823
|
+
// Always show READY actions
|
|
824
|
+
if (status === "READY")
|
|
825
|
+
return true;
|
|
826
|
+
// Otherwise, only if --prepare* flags match the status
|
|
827
|
+
if (opts.preparePending && status === "PENDING")
|
|
828
|
+
return true;
|
|
829
|
+
if (opts.prepareCompleted && status === "COMPLETED")
|
|
830
|
+
return true;
|
|
831
|
+
return false;
|
|
832
|
+
}
|
|
833
|
+
// Helper to prepare and optionally execute an election action
|
|
834
|
+
async function handleElectionAction(actionName, prepareFunc, status) {
|
|
835
|
+
if (!shouldShowAction(status))
|
|
836
|
+
return;
|
|
837
|
+
console.log(`\n[ACTION] ${actionName} (${status})`);
|
|
838
|
+
const prepared = await prepareFunc();
|
|
839
|
+
if (!prepared)
|
|
840
|
+
return;
|
|
841
|
+
console.log((0, cli_1.formatDryRun)(prepared));
|
|
842
|
+
if (signer && opts.write && status === "READY") {
|
|
843
|
+
const execResult = await (0, cli_1.executeTransaction)(prepared, signer, providers);
|
|
844
|
+
if (execResult.success) {
|
|
845
|
+
console.log(`\n[EXECUTED] ${actionName} succeeded! Tx: ${execResult.txHash}`);
|
|
846
|
+
}
|
|
847
|
+
else {
|
|
848
|
+
console.error(`\n[ERROR] Execution failed: ${execResult.error}`);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
// Trigger member election
|
|
853
|
+
const triggerStatus = getActionStatus(election.canProceedToMemberPhase, election.phase === "VETTING_PERIOD" && !election.canProceedToMemberPhase, election.memberProposalId !== null);
|
|
854
|
+
await handleElectionAction("Trigger member election", () => prepareMemberElectionTrigger(election, providers.l2Provider), triggerStatus);
|
|
855
|
+
// Execute member election
|
|
856
|
+
const executeStatus = getActionStatus(election.canExecuteMember, election.phase === "MEMBER_ELECTION" && !election.canExecuteMember, election.phase === "COMPLETED");
|
|
857
|
+
await handleElectionAction("Execute member election - install new council", () => prepareMemberElectionExecution(election, providers.l2Provider), executeStatus);
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
// Default: Check election status (original behavior)
|
|
623
861
|
async function checkElection() {
|
|
624
862
|
try {
|
|
625
863
|
const result = await (0, election_check_1.checkAndExecuteElection)(providers, signer, {
|