DAO Database - HausDAO/daohaus-monorepo-deprecated GitHub Wiki
Overview
Specification for a ridiculously simple DAO managed database utilizing Poster contracts and the daohaus v3 subgraph.
Features
1. Enable DAOs to own metadata
- stored in contract events and the daohaus subgraph and esily queried with other dao data
- only updated by DAO members
- validations levels: loot holder, share holder, ratified by proposal
2. Flexible and extendable db tables and fields
- this spec will define the schema for basic DAO profile metadata
3. Store a history of data updates
Specification
Writing data
Writing DAO data will be done through the post function in the poster contract on that DAOs network. Poster has been deployed at 0x000000000000cd17345801aa8147b8D3950260FF on most networks.
contract Poster {
event NewPost(address indexed user, string content, string indexed tag);
function post(string calldata content, string calldata tag) public {
emit NewPost(msg.sender, content, tag);
}
}
post function arguments
string calldata content
Json string with relevant key/values for the type of record.
DAO profile record:
{
"dao": "0x0",
"name": "kovan cco v2",
"description": "tester",
"longDescription": "some long description",
"purpose": "Products",
"avatarImg": {
content: "QmWLh8vCksEhmPQsyS6BgXtytkBAmtoJ68qpiTuJx47u22",
contentType: 'ipfs'
},
"links": {
"website": "",
"twitter": "",
"discord": "https://discord.gg/V4M4h5EX",
"telegram": "",
"medium": "",
"other": ""
},
"tags": ['some', 'tags'],
}
- 'dao' is a required field on all posts and will be used for lookup in the subgraph mappings
- all fields will be interpreted as strings unless indicated as an object with contentType
- ie) avatarImg should be a ipfs hash
- future types could include markdown, encoded hash, arweave hash
string calldata tag
String using dot notation that will aid subgraph indexing and parsing. These are emitted as indexed params so they are not human readable in events and subgraph mappings.
Format: <app: daohaus>.<pemission level>.<target table>
Permission levels:
- member: share or loot holder
- shares: share holder
- loot: loot holder
- proposal: post must be done in the execution action of a passed proposal
We will only have one target table at alpha stage used for DAO profile.
DAO profile record tag: daohaus.shares.daoProfile
Indexing data
The daohaus v3 subgraph will subscribe the the NewPost event and map valid data into Record entities.
type Record @entity {
id: ID!
createdAt: String!
createdBy: Bytes!
dao: Dao!
tag: Bytes!
table: String!
contentType: String!
content: String!
}
validation
- only defined tags will be indexed
- permission level validation performed in the mapping based on permission level in tag
- mapping will lookup share/loot holders or ensure the msg.sender is the daos safe address
- validate content string is json and has a dao property with a valid dao address
mapping
- ID: block timestamp + log index
- createdAt: block timestamp
- createdBy: msg.sender (event.params.address)
- dao: dao address (parsed from json and validated)
- tag: event.params.tag
- table: String (derived form tag)
- contentType:will always be json for these alpha records, but adding for future flexibility)
- content: json from post - event.params.content
Reading data
Record entities can be looked up by dao address + table. Sorting by the createdAt field, descending will return the most recent snapshot of the table's data.
example:
{
records(
where: {dao: '0x0', table: 'daoProfile'}
first: 1
orderBy: createdAt
orderDirection: desc
)
{id, content, table}
}