Census3 is an API service to create censuses for elections with holders of a single token or a combination of a some of them. The service creates a list of holder addresses and balances and keeps it updated in realtime, for every registered token. Then, allows to create a merkle tree census (compatible with Vocdoni) with these holders, using its balances as vote weight.
The service suports the following list of token types:
- ERC20
- ERC721
- ERC1155 (coming soon)
- ERC777
- Nation3 (veNation)
- wANT
- The censuses are published on IPFS after its creation.
- Census3 uses go.vocdoni.io/dvote/tree/arbo to build the censuses merkle trees.
- The censuses can be created with the holders of just one token or a combination of tokens, using complex strategies (coming soon).
- The censuses are zk-friendly and can be used also for anonymous voting.
A strategy is a definition of a group of previously created tokens and how their scanned holders must be combined to create a census.
- Must support combinations of tokens which contains:
- A operator, which is a function associated with a tag (e.g.
AND
) that are used to combine token holders and define how to combine them. - Two token symbols (e.g.
BTC
), that identifies the token holders to combine. - Must have the following format:
<token_symbol> <operator> <token_symbol>
, e.g.BTC OR ETH
.
- A operator, which is a function associated with a tag (e.g.
- Must support groups of combinations, e.g.
USDC AND (ETH OR (BTC AND DAI))
- Build the project:
go build -o census3 ./cmd/census3
- Run the CLI:
./census3 --help
Usage of ./census3:
--connectKey string connect group key for IPFS connect
--dataDir string data directory for persistent storage (default "<$HOME>/.census3")
--logLevel string log level (debug, info, warn, error) (default "info")
--port int HTTP port for the API (default 7788)
--web3Providers string the list of URL's of available web3 providers (separated with commas)
Example:
./census3 --web3Providers https://goerli.rpcendpoint.io/,https://mainnet.rpcendpoint.io/ --logLevel debug
# or just:
# go run ./cmd/census3 --web3Providers https://goerli.rpcendpoint.io/,https://mainnet.rpcendpoint.io/ --logLevel debug
- Create your config file using the
.env
file as a template and save it the root.
# A web3 endpoint provider
WEB3_PROVIDERS=https://rpc-endoint.example1.com,https://rpc-endoint.example2.com
# Internal port for the service (80 and 443 are used by traefik)
PORT=7788
# Domain name for TLS
# DOMAIN=your.own.domain.xyz
DOMAIN=localhost
# Log level (info, debug, warning, error)
LOGLEVEL=debug
# IPFS connect key for discovering nodes
CONNECT_KEY=yourIPFSConnectKey
- Run the services with
docker compose
:
docker compose up -d
- Starts the API service on
localhost:7788
with a web3 provider formainnet
- Register a new
erc20
token frommainnet (chainId: 1)
by its contract address:
curl -X POST \
--json '{"ID": "0xFE67A4450907459c3e1FFf623aA927dD4e28c67a", "type": "erc20", "chainID": 1}' \
http:https://localhost:7788/api/tokens
- Wait to that the API service completes the token sync. It could take up to 10-20 minutes, even more, based on the number of holders and transactions. You can check the token sync status getting the token info:
curl -X GET \
http:https://localhost:7788/api/tokens/0xFE67A4450907459c3e1FFf623aA927dD4e28c67a
- When the API ends, and the token reaches
synced
status (token.status.synced = true
), its time to create a new census based on the default token strategy. This strategy is created during the token registration and just contains the holders of this token. To create the census with token holders, you need to know thetoken.defaultStrategy
(from token info endpoint):
curl -X POST \
--json '{"strategyID": <strategyId>, "anonymous": true}" \
http:https://localhost:7788/api/censuses
- The last request will return a
queueId
which identifies the census creation and publication processes on the API queue. It will be completed in background. We can check if the task is done, it raised an error or was succesfully completed:
curl -X GET \
http:https://localhost:7788/censuses/queue/<queueId>
You can check and run the example using the example.sh
file:
sh ./example.sh
-> creating token...
Ok
-> created, waiting 4m to token scan
-> getting token info...
{"id":"0xFE67A4450907459c3e1FFf623aA927dD4e28c67a","type":"erc20","decimals":18,"startBlock":16976695,"symbol":"NEXT","totalSupply":"1000000000000000000000000000","name":"Connext","status":{"atBlock":18092468,"synced":true,"progress":100},"size":644,"defaultStrategy":1,"chainID":1}
-> enter the strategyId:
1
-> creating census...
{"queueId":"cd234ba75988e04e1e7a3234e48ff4033633142f"}
-> waiting 1m to census publication
-> enter the enqueue census:
cd234ba75988e04e1e7a3234e48ff4033633142f
{"done":true,"error":null,"census":{"censusId":1,"strategyId":1,"merkleRoot":"73368af290f4d0dfcb25b12060184bb3e5ad4147c5e5949de6729800c3629509","uri":"ipfs:https://bafybeiehspu3xrpshzjcvexl52u756cwfjobcwjz7ol4as44zfpvnlchsu","size":644,"weight":"5180125781955736442164650279357953853238828163172892166520872906800","anonymous":true}}
Check out the API endpoints definitions, accepted requests and expected responses in the ./api
folder.