Public
Edited
Dec 20, 2022
Insert cell
Insert cell
Insert cell
Plot.plot({
y: {
grid: true,
label: "Votes Bps"
},
x: {
label: "Proposal ID"
},
color: {
scheme: "rainbow"
},
marks: [
Plot.barY(governanceData, {x: "id", y: "votesAsBps", fill:"votesAsBps"})
]
})
Insert cell
Plot.plot({
y: {
grid: true,
label: "Votes Surplus Bps"
},
x: {
label: "Proposal ID"
},
color: {
scheme: "rainbow"
},
marks: [
Plot.barY(governanceData, {x: "id", y: "surplusAsBps", fill:"surplusAsBps"})
]
})
Insert cell
Insert cell
governanceData = R.pipe(
R.map(cleanProposal),
R.map(addVotesSum),
R.map(addQuorumSurplus),
R.map(addQuorumSurplusAsBps),
R.map(addSupplyAtStart),
R.map(addVotesAsBps),
)((await axios.post(subgraphUrl, {query: governanceQuery})).data.data.proposals)
Insert cell
addQuorumSurplusAsBps = proposal => ({...proposal, surplusAsBps: (proposal.quorumSurplus / supplyAtBlock(proposal.startBlock))* 10000})
Insert cell
addVotesAsBps = proposal => ({...proposal, votesAsBps: (proposal.votesSum / supplyAtBlock(proposal.startBlock) * 10000)})
Insert cell
addSupplyAtStart = proposal => ({...proposal, supplyAtStart: supplyAtBlock(proposal.startBlock)})
Insert cell
supplyAtBlock = block => (block - FIRST_NOUN_START_BLOCK) / BLOCKS_PER_NOUN
Insert cell
addQuorumSurplus = proposal => ({...proposal, quorumSurplus: proposal.votesSum - proposal.quorumVotes})
Insert cell
addVotesSum = proposal => ({...proposal, votesSum: computeVoteSum(proposal.votes)})
Insert cell
computeVoteSum = R.compose(R.sum, R.map(R.prop('votes')))
Insert cell
cleanProposal = rawProposal => ({
description: rawProposal.description,
endBlock: Number(rawProposal.endBlock),
executionETA: Number(rawProposal.executionETA),
id: Number(rawProposal.id),
proposalThreshold: Number(rawProposal.proposalThreshold),
quorumVotes: Number(rawProposal.quorumVotes),
startBlock: Number(rawProposal.startBlock),
proposer: rawProposal.proposer,
votes: R.map(cleanVote, rawProposal.votes)
})
Insert cell
cleanVote = vote => ({...vote, votes: Number(vote.votes)})
Insert cell
subgraphUrl = "https://api.thegraph.com/subgraphs/name/nounsdao/nouns-subgraph"
Insert cell
Insert cell
governanceData.filter(hadAgainstVote)
Insert cell
hadAgainstVote(lastFiveProposals[6])
Insert cell
hadAgainstVote = proposal => R.any(R.identity, R.map(vote => !vote.support, proposal.votes))
Insert cell
lastFiveProposals = governanceData.slice(0, 99)
Insert cell
Plot.plot({
x: {
label: "Number of Nouns Delegated"
},
y: {
label: "Number of Accounts"
},
color: {
scheme: "rainbow"
},
marks: [
Plot.barY(plottableFrequencyOfDelegatesVotedInN, {x: "delegationCount", y: "freq", fill:"freq"})
]
})
Insert cell
plottableFrequencyOfDelegatesVotedInN = Object.keys(frequencyOfAllDelegates).map(delegationCount => ({delegationCount: Number(delegationCount), freq: frequencyOfAllDelegates[delegationCount]}))
Insert cell
frequencyOfDelegatesVotedInLastFive = Object.keys(delegatesVotedInLastFive).reduce((acc, delegate) => {
if (!acc[delegates[delegate]]) acc[delegates[delegate]] = 0
acc[delegates[delegate]]++
return acc
},{})
Insert cell
frequencyOfAllDelegates = Object.keys(delegates).reduce((acc, delegate) => {
if (!acc[delegates[delegate]]) acc[delegates[delegate]] = 0
acc[delegates[delegate]]++
return acc
},{})
Insert cell
delegatesVotedInLastFive = Object.keys(delegates).filter(delegate => delegateVotedInAnyProposals(lastFiveProposals, delegate)).reduce((acc, delegate) => {
acc[delegate] = delegates[delegate]
return acc;
},{})
Insert cell
delegateVotedInAnyProposals = (proposals, delegate) => R.any(R.identity, R.map(p => delegateVotedInProposal(p, delegate), proposals))
Insert cell
delegateVotedInProposal = (proposal, delegate) => proposalVoters(proposal).includes(delegate)
Insert cell
proposalVoters = proposal => R.map(R.pipe(R.prop('id'), addr => addr.split('-')[0]), proposal.votes)
Insert cell
| Votes Delegated | Addresses |
|---|---|
${Object.keys(delegateSet).map(count => `|${count}|${delegateSet[count].join(', ')}\n`)}
Insert cell
delegateSet = delegateCounts.filter(deleg => deleg.count > 1).reduce((acc, delegation) => {
if(!acc[delegation.count]) acc[delegation.count] = [];
acc[delegation.count].push(delegation.addr)
return acc
}, {})
Insert cell
delegateCounts = Object.keys(delegates).map(addr => ({addr, count: delegates[addr]})).sort((a, b) => b.count - a.count)
Insert cell
Insert cell
nouns = R.pipe(
R.map(normalizeNoun)
)((await axios.post(subgraphUrl, {query: nounsQuery})).data.data.nouns).sort((a, b) => a.id - b.id)
Insert cell
Insert cell
Insert cell
Insert cell
normalizeSeed = (seed) => ({
accessory: Number(seed.accessory),
background: Number(seed.background),
body: Number(seed.body),
glasses: Number(seed.glasses),
head: Number(seed.head),
});
Insert cell
normalizeNoun = (noun) => ({
...noun,
id: Number(noun.id),
seed: normalizeSeed(noun.seed),
});

Insert cell
FIRST_NOUN_START_BLOCK=12985732
Insert cell
BLOCKS_PER_NOUN = (13700622 - FIRST_NOUN_START_BLOCK) / 123
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more