The Quadratic Dollar Homepage is a spin on the Million Dollar Homepage. While it also features a space for images on a webpage, it allows users to vote on how much space each image takes up. Moreover, it employs a quadratic and collusion-resistant voting mechanism on Ethereum called Minimal Anti-Collusion Infrastructure (MACI) to prevent bribery and scale images quadratically.
DEMO: https://www.youtube.com/watch?v=b6VonnS8e1M
Clone this repo. Install dependencies by running yarn
or npm install
:
git clone https://github.com/appliedzkp/qdh
cd qdh
yarn # or `npm install`
Copy .env.sample
and name it .env
.
In .env
set values for all the missing variables, such as MONGO_URL
, AZURE_STORAGE_ACCOUNT_NAME
,
AZURE_CONTAINER_NAME
, AZURE_KEY
, AZURE_CONNECTION_STRING
. You can find detailed guides on setting up MongoDB and Azure Storage towards the end of this doc.
cp .env.sample .env
vim .env # set `MONGO_URL, AZURE_STORAGE_ACCOUNT_NAME, etc...`
Your .env
file should looks something like this:
NEXT_PUBLIC_MACI_ADDRESS=0x2C2B9C9a4a25e24B174f26114e8926a9f2128FE4
NEXT_PUBLIC_POAP_ADDRESS=0x22C1f6050E56d2876009903609a2cC3fEf83B415
NEXT_PUBLIC_STRAPI_URL=https://strapi-admin.quadratic.page
MONGO_URL=mongodb+srv://user:[email protected]/database...
AZURE_STORAGE_ACCOUNT_NAME=qdh
AZURE_CONTAINER_NAME=qdh-user-images
AZURE_KEY=24f234f234f+24f243f+24f243f/24f234f234f2f24f==...
AZURE_CONNECTION_STRING=DefaultEndpointsProtocol=https...
Now run yarn dev
(or npm run dev
)
If you are already running
yarn dev
(ornpm run dev
), make sure to kill the process and start it again. Next.js doesn't pick up.env
changes automatically. Hence you need to restart it manually.
On the output, you should see something like this:
Loaded env from /your-project-path/qdh/.env
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
Frontend is now accessible on http://localhost:3000
Now let's set up and deploy MACI on a local testnet.
In a separate terminal, clone MACI: https://github.com/appliedzkp/maci
Carefully follow everything in "Local development and testing": bootstrap MACI repo, install Rust, build zk-SNARKs, compile contracts... everything up to the "Demo" section.
Here is a summary of commands described in detail in the abovementioned guide:
git clone [email protected]:appliedzkp/maci.git
cd maci
npm i && npm run bootstrap && npm run build
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # to install Rust
cargo install zkutil --version 0.3.2 && zkutil --help
cd circuits
npm run buildBatchUpdateStateTreeSnark && npm run buildQuadVoteTallySnark
cd ../contracts
npm run compileSol
From the same directory (maci/contracts
) start a Ganache instance:
npm run ganache
In a separate terminal, go to maci/cli
directory and create a new MACI election:
node ./build/index.js create -d 0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3 \
-sk macisk.8715ab59a3e88a7ceec80f214ec24a95287ef2cb399a329b6964a87f85cf51c \
-e http://localhost:8545 \
-s 15 \
-o 60 \
-bm 4 \
-bv 4
Once you've deployed MACI and created an election, you should have an output like this:
MACI: 0x2C2B9C9a4a25e24B174f26114e8926a9f2128FE4
Now you have 15 seconds to go to the frontend http://localhost:3000 and sign up. Then you'll be able to start voting and interacting with MACI. If you didn't signup in time - restart ganache and redeploy MACI (steps above). Also, you can increase MACI signup deadline, by changing -s 15
to -s 30
seconds.
Don't forget to connect your Metamask to your local testnet locahost:8545
and import one of the test wallets into it.
You can find a detailed guide of this step and other MACI commands in the MACI Demonstration docs.
You can also watch & listen to these great in-depth presentations about MACI by Koh Wei Jie: Making Sense of MACI, ZKPodcast: MACI with Koh Wei Jie and Minimum Anti-Collusion Infrastructure (MACI)
The goal of the Admin Dashboard is to simplify moderation of uploaded images, supply basic initial configuration to the QDH frontend (e.g. MACI contract address on the mainnet) and upload tally.json
once the vote results are tallied.
Setting up and running Admin Dashboard is not mandatory, but recommended. We've based it on an open source headless CMS, called Strapi.
You'll be able to find detailed instructions on how to run it in the repo's README, but we'll make a short overview here as well.
Clone the repo https://github.com/appliedzkp/qdh-admin and install dependencies with yarn
(or npm install
)
git clone https://github.com/appliedzkp/qdh-admin
cd qdh-admin
yarn # or `npm install`
Copy .env.example
and name it .env
.
In .env
set values for all the missing variables, such as MONGO_URL
, AZURE_STORAGE_ACCOUNT_NAME
,
AZURE_CONTAINER_NAME
, AZURE_KEY
, AZURE_CONNECTION_STRING
with the same values as used above.
cp .env.example .env
vim .env # set `MONGO_URL`, `AZURE_STORAGE_ACCOUNT_NAME`, `AZURE_CONTAINER_NAME`, `AZURE_KEY`, `AZURE_CONNECTION_STRING`.
Run yarn develop
to start the server locally.
The api will be available at http://localhost:1337
and the admin panel at http://localhost:1337/admin
You might want to update NEXT_PUBLIC_STRAPI_URL=http://localhost:1337
in the .env
in qdh frontend, so that your local frontend talks to your locally run Strapi Admin api. Don't forget to manually kill and start the frontend server. (Next.js doesn't automatically pick up .env file changes.)
This repo is ready for Vercel, Heroku and Dokku deployments. Make sure to export enviromental variables from .env
to the platform you are deploying on.
Install Vercel CLI:
yarn global add vercel
# or
npm i -g vercel
Then from your qdh/
directory run vercel
to start the deployment process and follow the steps. Should work automagically:
vercel
You can also auto deploy to Vercel by importing your git repo: https://vercel.com/new
If you don't have heroku
cli installed yet, install it: brew tap heroku/brew && brew install heroku
on macOS or sudo snap install --classic heroku
on Ubuntu 16+. Then run heroku login
to link your Heroku CLI to your account.
Then from your qdh/
repo directory run the following:
heroku create qdh-frontend
heroku config:set $(cat .env | sed '/^$/d; /#[[:print:]]*$/d') --app qdh-frontend # this will pick up variables from .env and transport them to your heroku instance
heroku git:remote --app qdh-frontend
git push heroku master
If name qdh-frontend
is already taken, try the steps above with a different name.
Dokku is a Docker powered mini-Heroku.
Follow these instructions to install Dokku on your server. Make sure to add your pub ssh keys to the dokku deployment (not just to ~/.ssh/authorized_keys on your server). Once you do that, you should be able to run the following from your local machine:
ssh -t dokku@your-server-ip apps:create qdh-frontend
ssh -t dokku@your-server-ip config:set qdh-frontend $(cat .env | sed '/^$/d; /#[[:print:]]*$/d') # this will pick up variables from .env and transport them to your dokku instance
git remote add dokku dokku@your-server-ip:qdh-frontend
git push dokku master
- Create a Storage account. Give it a name. For example
qdh
- Go to Storage account > Overview
- Click on Containers. Create a new storage container. Let's name it
qdh-user-images
. Make sure that the "Public access level" is set to Blob (anonymous access for blobs only) - Click on Settings > Access keys. Copy paste Account Name, Key and Connection String from there.
- Tada! You now have
AZURE_STORAGE_ACCOUNT_NAME
,AZURE_CONTAINER_NAME
,AZURE_KEY
,AZURE_CONNECTION_STRING
:
AZURE_STORAGE_ACCOUNT_NAME='qdh'
AZURE_CONTAINER_NAME='qdh-user-images'
AZURE_KEY='24f234f234f+24f243f+24f243f/24f234f234f2f24f==...'
AZURE_CONNECTION_STRING='DefaultEndpointsProtocol=https...'
p.s. We'll eventually try to make this project cloud agnostic. Feel free to contribute!
- If you are are looking for a free & easy MongoDB hosting, try Mongo Atlas
- If you've used Dokku before, you can deploy mongo instance on it using dokku-mongo plugin.
- You can also deploy MongoDB on your IaaS or PaaS of choice.