The Governance Registry
The Registry is the single entry point to æternity governance. It keeps the index of every
poll ever registered, and it holds the global delegation map. It does not hold votes
(those live on each individual Poll contract), and it does not compute results, which happens
off-chain in the governance backend.
One registry per network, deployed once, with no admin entrypoint and no upgrade path.
Addresses
| Network | Registry address |
|---|---|
| Mainnet | ct_ouZib4wT9cNwgRA1pxgA63XEUd8eQRrG8PcePDEYogBc1VYTq |
| Testnet | ct_2nritSnqW6zooEL4g2SMW5pf12GUbrNyZ17osTLrap7wXiSSjf |
The Superhero app ships these as GOVERNANCE_CONTRACT_ADDRESS. The agent skill's CLI defaults
to the mainnet address and accepts an override through the AE_GOVERNANCE_REGISTRY
environment variable, which is how you point it at testnet.
State
Registry.state = { polls : map(int, Registry.poll_data)
, seq_id : int
, delegations : map(address, address)
, created_height : int }
Registry.poll_data = { poll : Poll
, is_listed : bool
, title : string
, close_height : option(int) }poll_data caches the title and close height, which also live on the poll contract, so a
client can render a full poll list from one contract call instead of one call per poll, which
is what the app and the CLI do.
delegations is a plain address-to-address map, which is why an account can have at most
one outgoing delegation and any number of incoming ones. See
Delegation.
seq_id is the counter behind poll ids: add_poll assigns the next one, so ids are dense,
sequential and permanent. created_height records when the registry was deployed; the
governance backend starts scanning for Delegation and RevokeDelegation events from that
height when it reconstructs a historic delegation graph.
Entrypoints
| Entrypoint | Signature | Purpose |
|---|---|---|
init | () | No parameters. The registry is deployed empty. |
add_poll | (poll: Poll, is_listed: bool) : int | Register a deployed poll; returns its id. Stateful. |
polls | () : map(int, poll_data) | Every poll, listed and unlisted |
poll | (poll_id: int) : poll_data | One poll's summary |
delegate | (delegatee: address) | Set or replace your delegation. Stateful. |
revoke_delegation | () | Remove your delegation. Stateful. |
delegations | () : map(address, address) | The complete delegation map |
delegatee | (account: address) : option(address) | Who that account delegates to |
delegators | (account: address) : map(address, address) | Direct delegators to that account |
created_height | () : int | Deployment height |
version | () : int | Contract version |
The complete list of state-changing entrypoints is add_poll, delegate and
revoke_delegation. There is no way to remove a poll, change its is_listed flag, or edit its
cached title, and there is no owner, admin, pause or migration hook.
add_poll can be called by any account for any deployed poll, including one the caller did
not author, and the caller chooses is_listed. The call reverts if the argument cannot answer
title() and close_height(). The same poll can be registered more than once under different
ids. A registration is permanent; listing decisions happen in clients.
polls() returns everything, unlisted included, because is_listed is a display hint rather
than an access control. See Polls.
Contract versions
| Source | version() | Notes |
|---|---|---|
Registry.aes | 1 | Builds with aesophia up to 5.0.0 |
Registry_Compiler_v6.aes | 2 | @compiler >= 6; contract interface Poll and main contract Registry syntax. Builds 6.0.0 through 8.0.0 |
The two have the same state, entrypoints and events, so the ACI is the same either way. Read
version() on the address you are calling if you need to know which build a network runs.
Events
| Event | Fields |
|---|---|
AddPoll | the poll contract, its id |
Delegation | delegator, delegatee |
RevokeDelegation | delegator |
These three are the registry's whole activity stream. AddPoll lets an indexer discover new
polls without re-reading polls(); the delegation events let it maintain the delegation graph
incrementally.
Vote and RevokeVote are emitted by each Poll contract, not by the registry, so an
indexer subscribes per poll, discovering polls through AddPoll first and then following
them individually. See Contract events.
Call it
From the agent skill's CLI, which initialises the registry for you:
node scripts/superhero-governance.mjs list # Registry.polls(), listed only
node scripts/superhero-governance.mjs list 50 --all # include unlisted
node scripts/superhero-governance.mjs info-by-id 42 # Registry.poll(42), then the poll itself
node scripts/superhero-governance.mjs delegatee # Registry.delegatee(you)
node scripts/superhero-governance.mjs delegators # Registry.delegators(you)To point any of them at testnet, override both the node and the registry:
export AE_NODE_URL=https://testnet.aeternity.io
export AE_GOVERNANCE_REGISTRY=ct_2nritSnqW6zooEL4g2SMW5pf12GUbrNyZ17osTLrap7wXiSSjfFrom your own client, initialise a contract instance against the registry ACI and the address
for your network. The agent skill ships the ACI as RegistryWithEventsACI.json; the event
variant declared in it is what lets a client decode AddPoll, Delegation and
RevokeDelegation without a separate schema.
The governance API
The registry gives you structure; the backend gives you weighted results.
| Network | Governance API base URL |
|---|---|
| Mainnet | https://governance-server-mainnet.prd.service.aepps.com/ |
| Testnet | https://governance-server-testnet.prd.service.aepps.com/ |
| Endpoint | Returns |
|---|---|
GET version | Backend version |
GET pollOrdering?closed=true,false | Poll ordering with per-poll totals, vote counts and a score |
GET pollOverview/:pollAddress | Full poll state, per-account stakes at height, per-option stakes |
GET votesState/:address | The same overview shape; the source of the official result |
GET delegatedPower/:address?poll=:pollAddress | Delegated power and delegation tree, optionally scoped to one poll |
GET accountPollVoterAuthor/:address | Polls an account voted in, authored, or was represented in by its delegatee |
POST contractEvent | Nudge the backend to re-index, with a topic and an optional poll address |
The Superhero app combines the two sources for its poll list: it reads titles from
Registry.polls() and ordering, stake totals and vote counts from pollOrdering, then merges
them by poll id.
The agent skill's CLI defaults to https://governance-server-mainnet.prd.aepps.com for
mainnet, overridable with AE_GOVERNANCE_BACKEND_URL. If one host does not answer, try the
other.
Superhero's own backend also indexes governance transactions at
/api/governance/votes and /api/governance/delegations. They are useful for history rather than for
live results. See Polls.
Related
- Polls: what
poll_datasummarises, and how the backend turns votes into results. - Delegation: the delegation entrypoints in context, with the transitivity rules.
- Creating a Poll:
add_pollas the second half of poll creation. - Registry and Poll contract reference: the full signature tables.
- Contract addresses: every deployed address across both networks in one place.