Skip to content

DAO DAO Infrastructure

noah edited this page May 29, 2024 · 7 revisions

Introduction

DAO DAO is a blockchain application. What this means is that the DAO's existence and core logic (voting, managing money, etc.) are guaranteed by a blockchain. The data lives on the blockchain, and the data is updated by logic in smart contracts running on the blockchain. This replaces the traditional "backend" API server used by web2 applications.

In order to offer all features supported by the DAO DAO webapp, DAO DAO manages many services that do not live on the blockchain (also known as off-chain). DAO DAO's infrastructure is detailed below.

Blockchain

The smart contracts that run on a blockchain can be found in the dao-contracts repository. The code IDs of the deployed contracts can be found in each release on the releases page of that repo.

Next.js

The frontend is written using Next.js in TypeScript and hosted on Vercel. The code can be found in the repo you're currently viewing, or here if for some reason you're not.

The DAO DAO frontend is mostly served statically, but there are a few serverless API functions that handle:

  • retrieving data from the indexer (with a private token)
  • uploading images and NFT metadata to NFT.Storage (with a private token)
  • resetting the page cache for a DAO when a proposal is executed

Indexer

DAO DAO uses a custom-built CosmWasm indexer that indexes the state of smart contracts on the blockchain. It can be found here. The indexer is deployed on a https://www.digitalocean.com/ droplet.

Search

DAO search uses a Meilisearch instance hosted on a https://www.digitalocean.com/ droplet. The Meilisearch indexes are populated by the indexer.

Example code that uses the meilisearch npm package can be found here.

If the example code above is insufficient, the Meilisearch search docs are the best place to look for usage instructions.

value.contractAddress and value.proposalCount can be filtered, and blockHeight and value.proposalCount can be sorted.

Connection Info

Host: https://search.daodao.zone

API Key: 54ec0f5c2536c3126354852a7e45f383defaf112fd674de0c0dcf914fd7f55c8

Indexes:

  • DAOs for a given chain ID: <CHAIN ID>_daos
  • Proposals for a given chain ID: <CHAIN ID>_proposals

[Example] List 10 Neutron DAOs:

curl https://search.daodao.zone/indexes/neutron-1_daos/documents\?limit=10 -H 'Content-Type: application/json' -H 'Authorization: Bearer 54ec0f5c2536c3126354852a7e45f383defaf112fd674de0c0dcf914fd7f55c8'

Profiles

DAO DAO profiles, which simply map a name and NFT-owned image to a secp256k1 public key used by the Cosmos SDK, are managed by a Cloudflare Worker running pfpk. The repo's README contains API docs which explain how to retrieve a profile, update a profile, and search for profiles with a name prefix.

Payroll

DAO DAO supports various payroll structures, but only one requires an off-chain service: retroactive compensation. A Cloudflare Worker runs retroactive-compensation-cf-worker, which manages the survey cycle wherein submissions are accepted and then rated by DAO members before a proposal is proposed on-chain to the DAO. The frontend code that uses this API can be found here.

KVPK

Some features simply need access to a key-value store attached to a given wallet. An authenticated location to store tiny pieces of state to provide a seamless cross-browser experience for a given identity. DAO DAO uses a Cloudflare Worker running kvpk, which simply wraps the a Cloudflare KV Store to provide authenticated access. This works with a secp256k1 public key used by the Cosmos SDK.

Examples of data stored in this KV:

  • DAOs being followed by a wallet
  • Transaction presets on the Me page

Inbox

To maintain an event inbox for a wallet, DAO DAO uses a Cloudflare Worker running inbox-cf-worker. The indexer sends events to this worker that are relevant to show in the inbox. The user can then clear events from the inbox once they have read them.

Emailer

We use AWS SES for sending emails, which imposes a rate limit of emails per second. To ensure we remain below this limit while still allowing the indexer and inbox to queue emails as soon as events occur, we created a Cloudflare Worker running emailer-cf-worker that functions as a queue. It dequeues emails in batches and sends them, respecting the rate limit (which initially was set to 14 emails/second).

Notifier

We use a Cloudflare Worker running notifier-cf-worker that operates as the middleman between the indexer and the inbox. Sometimes, a single indexer event needs to send notifications to many wallets. The notifier's primary job is to locate everyone that should be notified, and then add the same notification to all of their inboxes. It typically does this by performing an additional query, either to the indexer or the KVPK service explained above.

For example, when a proposal is created, the indexer only triggers one event, but we need to notify everyone following that DAO. So, the indexer tells this notifier, and the notifier asks KVPK which wallets follow the DAO. Then, the notifier adds the proposal created notification to each inbox for every wallet. The inbox may also forward that notification to the emailer service explained above if on a per-wallet basis if they have email setup.

WebSockets

A Cloudflare Worker running websockets-cf-worker is responsible for receiving webhooks from the indexer and forwarding them to the UI to notify when events occur. This is used to refresh data on proposal state changes and votes.