Skip to content

Commit

Permalink
Implement new society strategy, #1034
Browse files Browse the repository at this point in the history
  • Loading branch information
hyifeng committed Sep 5, 2024
1 parent 9a42f10 commit fa45492
Show file tree
Hide file tree
Showing 19 changed files with 213 additions and 41 deletions.
1 change: 1 addition & 0 deletions backend/packages/backend/src/consts/voting.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const strategies = Object.freeze({
quorumQuadraticBalanceOf: "quorum-quadratic-balance-of",
biasedVoting: "biased-voting",
onePersonOneVote: "one-person-one-vote",
society: "society",
});

module.exports = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const config = {
],
},
],
weightStrategy: [strategies.onePersonOneVote],
weightStrategy: [strategies.society],
version: "4",
spaceIcon: "kusamasociety.png",
seoImage: "QmYB3YVU3Sa27EfqTk3cGZ9S3GhiH6Z2ANpQdHKETpRrEZ",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ async function getSocietyMember(network, address, height) {
if (isTestAccount(address)) {
return {
data: {
rank: 0,
rank: 1,
strikes: 10,
vouching: null,
index: 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const calcWeights = (vote, decimals) => {
vote.weights.balanceOf?.toString(),
decimals,
),
societyVote: vote.weights.societyVote?.toString(),
details: vote.weights.details,
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,30 @@ async function getProposalById(proposalId) {

const votes = await voteCol.find({ proposal: proposal._id }).toArray();
const calculatedVotes = votes.map((v) => calcWeights(v, decimals));

const votedWeights = {};

for (const vote of calculatedVotes) {
votedWeights.balanceOf = new BigNumber(votedWeights.balanceOf || 0)
.plus(vote.weights.balanceOf)
.plus(vote.weights.balanceOf || 0)
.toString();
votedWeights.quadraticBalanceOf = new BigNumber(
votedWeights.quadraticBalanceOf || 0,
)
.plus(vote.weights.quadraticBalanceOf)
.plus(vote.weights.quadraticBalanceOf || 0)
.toString();

votedWeights.onePersonOneVote = new BigNumber(
votedWeights.onePersonOneVote || 0,
)
.plus(1)
.toString();

votedWeights.societyVote = new BigNumber(votedWeights.societyVote || 0)
.plus(vote.weights.societyVote || 0)
.toString();
}

proposal.votesCount = votesCount;
proposal.votedWeights = votedWeights;

Expand Down
12 changes: 10 additions & 2 deletions backend/packages/backend/src/services/proposal.service/getStats.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ async function getStats(proposalCid) {
const calculatedVotes = votes.map((v) =>
calcWeights(v, spaceService.decimals),
);

const stats = Object.fromEntries(
proposal.choices.map((choice) => [
choice,
{
choice,
balanceOf: "0",
quadraticBalanceOf: "0",
societyVote: "0",
onePersonOneVote: "0",
votesCount: 0,
},
Expand All @@ -33,14 +35,20 @@ async function getStats(proposalCid) {
for (const vote of calculatedVotes) {
for (const choice of vote.choices) {
const weights = (stats[choice] = stats[choice] || { choice });

weights.balanceOf = new BigNumber(weights.balanceOf || 0)
.plus(vote.weights.balanceOf)
.plus(vote.weights.balanceOf || 0)
.toString();
weights.quadraticBalanceOf = new BigNumber(
weights.quadraticBalanceOf || 0,
)
.plus(vote.weights.quadraticBalanceOf)
.plus(vote.weights.quadraticBalanceOf || 0)
.toString();

weights.societyVote = new BigNumber(weights.societyVote || 0)
.plus(vote.weights.societyVote || 0)
.toString();

weights.onePersonOneVote = new BigNumber(weights.onePersonOneVote || 0)
.plus(1)
.toString();
Expand Down
58 changes: 45 additions & 13 deletions backend/packages/backend/src/services/proposal.service/vote.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ const { getDemocracyDelegated } = require("../node.service/getDelegated");
const { findDelegationStrategies } = require("../../utils/delegation");
const { getSocietyMember } = require("../node.service/getSocietyMember");
const { Accessibility } = require("../../consts/space");
const {
hasBalanceStrategy,
hasSocietyStrategy,
} = require("../../utils/strategy");

async function getDelegatorBalances({
proposal,
Expand Down Expand Up @@ -220,6 +224,22 @@ async function checkSocietyVote({
}
}

async function getSocietyVote({ voterNetwork, voter, snapshotHeight }) {
const societyMember = await getSocietyMember(
voterNetwork,
voter,
snapshotHeight,
);
if (societyMember.data) {
const rank = societyMember.data.rank;
if (rank === 1) {
return 4;
}
return 1;
}
return 0;
}

async function vote(
proposalCid,
choices,
Expand Down Expand Up @@ -255,17 +275,32 @@ async function vote(
const snapshotHeight = proposal.snapshotHeights?.[voterNetwork];
const voter = realVoter || address;

const networkBalance = await getBalanceFromNetwork({
networksConfig: proposal.networksConfig,
networkName: voterNetwork,
address: voter,
blockHeight: snapshotHeight,
});
const weights = {};

const balanceOf = networkBalance?.balanceOf;
const networkBalanceDetails = networkBalance?.details;
if (hasBalanceStrategy(proposal)) {
const networkBalance = await getBalanceFromNetwork({
networksConfig: proposal.networksConfig,
networkName: voterNetwork,
address: voter,
blockHeight: snapshotHeight,
});

const balanceOf = networkBalance?.balanceOf;
const networkBalanceDetails = networkBalance?.details;

await checkVoteThreshold({ networkBalanceDetails, proposal, voterNetwork });

await checkVoteThreshold({ networkBalanceDetails, proposal, voterNetwork });
weights.balanceOf = toDecimal128(balanceOf);
weights.details = networkBalanceDetails;
}

if (hasSocietyStrategy(proposal)) {
weights.societyVote = await getSocietyVote({
voterNetwork,
voter,
snapshotHeight,
});
}

const delegators = await getDelegatorBalances({
proposal,
Expand Down Expand Up @@ -301,10 +336,7 @@ async function vote(
updatedAt: now,
cid,
pinHash,
weights: {
balanceOf: toDecimal128(balanceOf),
details: networkBalanceDetails,
},
weights,
// Version 2: multiple network space support
// Version 3: multiple choices support
// Version 4: multi-assets network
Expand Down
3 changes: 3 additions & 0 deletions backend/packages/backend/src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ function toSymbolUnit(value, decimals) {
}

function enhancedSqrtOfBalance(balance, decimals) {
if (!balance) {
return balance;
}
return new BigNumber(balance)
.div(Math.pow(10, decimals))
.sqrt()
Expand Down
25 changes: 25 additions & 0 deletions backend/packages/backend/src/utils/strategy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const { strategies } = require("../consts/voting");

function hasBalanceStrategy(proposal) {
return [
strategies.balanceOf,
strategies.quorumBalanceOf,
strategies.quadraticBalanceOf,
strategies.quorumQuadraticBalanceOf,
strategies.biasedVoting,
].some((strategy) => proposal.weightStrategy.includes(strategy));
}

function hasSocietyStrategy(proposal) {
return proposal.weightStrategy.includes(strategies.society);
}

function hasOnePersonOneVoteStrategy(proposal) {
return proposal.weightStrategy.includes(strategies.onePersonOneVote);
}

module.exports = {
hasBalanceStrategy,
hasSocietyStrategy,
hasOnePersonOneVoteStrategy,
};
4 changes: 2 additions & 2 deletions next/components/listInfo/details.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Flex, FlexBetween } from "@osn/common-ui";
import uniq from "lodash.uniq";
import { getSpaceAssets } from "frontedUtils/getSpaceAssets";
import AssetList from "../assetList";
import { isOnePersonOnVoteOnly } from "frontedUtils/strategy";
import { hasBalanceStrategy } from "frontedUtils/strategy";

const Wrapper = styled.div``;

Expand Down Expand Up @@ -117,7 +117,7 @@ export default function Details({ space }) {
</div>
</DetailsItem>

{!isOnePersonOnVoteOnly(space?.weightStrategy) && (
{hasBalanceStrategy(space?.weightStrategy) && (
<DetailsItem>
<DetailsLabel>Assets({assets.length})</DetailsLabel>
<AssetList assets={assets} />
Expand Down
4 changes: 2 additions & 2 deletions next/components/postCreate/information.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
proxyBalanceLoadingSelector,
} from "../../store/reducers/statusSlice";
import BalanceRow from "@/components/postCreate/BalanceRow";
import { isOnePersonOnVoteOnly } from "frontedUtils/strategy";
import { hasBalanceStrategy } from "frontedUtils/strategy";
import SocietyMemberHit from "./societyMemberHit";

const Hint = styled.div`
Expand Down Expand Up @@ -94,7 +94,7 @@ export default function Information({ space }) {

return (
<>
{!isOnePersonOnVoteOnly(weightStrategy) && (
{hasBalanceStrategy(weightStrategy) && (
<BalanceRow
balance={balance}
isLoading={useProxy ? proxyBalanceLoading : balanceLoading}
Expand Down
4 changes: 2 additions & 2 deletions next/components/postDetail/postInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Panel from "@/components/postDetail/panel";
import SideSectionTitle from "@/components/sideBar/sideSectionTitle";
import AssetList from "../assetList";
import { getSpaceAssets } from "frontedUtils/getSpaceAssets";
import { isOnePersonOnVoteOnly } from "frontedUtils/strategy";
import { hasBalanceStrategy } from "frontedUtils/strategy";

const Wrapper = styled(Panel)`
> :not(:first-child) {
Expand Down Expand Up @@ -116,7 +116,7 @@ export default function PostInfo({ data, space }) {
)}
</div>
</div>
{!isOnePersonOnVoteOnly(space?.weightStrategy) && (
{hasBalanceStrategy(space?.weightStrategy) && (
<div>
<SideSectionTitle
title={`Assets(${assets.length})`}
Expand Down
16 changes: 14 additions & 2 deletions next/components/postDetail/postResults.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { VoteItem } from "./strategyResult/common/styled";
import QuorumBalanceOfResult from "./strategyResult/quorumBalanceOfResult";
import QuorumQuadraticBalanceOfResult from "./strategyResult/quorumQuadraticBalanceOfResult";
import OnePersonOneVoteResult from "./strategyResult/onePersonOneVoteResult";
import { isOnePersonOnVoteOnly } from "frontedUtils/strategy";
import { hasBalanceStrategy } from "frontedUtils/strategy";
import SocietyVoteResult from "./strategyResult/societyVoteResult";

export default function PostResult({ data, voteStatus, space }) {
const votedAmount = data?.votedWeights?.balanceOf || 0;
Expand Down Expand Up @@ -70,6 +71,17 @@ export default function PostResult({ data, voteStatus, space }) {
);
}

if (strategy === "society") {
return (
<SocietyVoteResult
key={strategy}
proposal={data}
space={space}
voteStatus={voteStatus}
/>
);
}

return null;
});

Expand All @@ -82,7 +94,7 @@ export default function PostResult({ data, voteStatus, space }) {
<SideSectionTitle title="Results" img="/imgs/icons/strategy.svg" />
<Divider />
<div>
{!isOnePersonOnVoteOnly(data?.weightStrategy) && (
{hasBalanceStrategy(data?.weightStrategy) && (
<VoteItem>
<div>Voted</div>
<div>
Expand Down
4 changes: 2 additions & 2 deletions next/components/postDetail/postVote.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { useTerminate } from "./terminate";
import { Tooltip } from "@osn/common-ui";
import VoteBalanceDetail from "./VoteBalanceDetail";
import DelegationInfo from "./delegationInfo";
import { isOnePersonOnVoteOnly } from "frontedUtils/strategy";
import { hasBalanceStrategy } from "frontedUtils/strategy";
import SocietyMemberHit from "../postCreate/societyMemberHit";
import SocietyMemberButton from "../societyMemberButton";

Expand Down Expand Up @@ -265,7 +265,7 @@ export default function PostVote({ proposal }) {
if (!proposalClosed) {
let balanceInfo = null;

if (!isOnePersonOnVoteOnly(proposal?.weightStrategy)) {
if (hasBalanceStrategy(proposal?.weightStrategy)) {
if (voteDelegation) {
balanceInfo = (
<DelegationInfo
Expand Down
4 changes: 2 additions & 2 deletions next/components/postDetail/postVotesItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Voter from "@/components/role/voter";
import { Tooltip } from "@osn/common-ui";
import VoteBalanceDetail from "./VoteBalanceDetail";
import { isZero } from "frontedUtils";
import { isOnePersonOnVoteOnly } from "frontedUtils/strategy";
import { hasBalanceStrategy } from "frontedUtils/strategy";

const Item = styled.div`
padding: 20px 0;
Expand Down Expand Up @@ -191,7 +191,7 @@ export default function PostVotesItem({
</EqualWrapper>
<EqualWrapper>
<BalanceWrapper>
{!isOnePersonOnVoteOnly(space.strategies) && (
{hasBalanceStrategy(space.strategies) && (
<ValueDisplay
value={data.weights?.balanceOf}
space={space}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ import {
} from "./styled";
import { toPrecision } from "@osn/common";

export default function OnePersonOneVoteOptionList({
optionList,
strategy,
space,
}) {
export default function VoteCountOptionList({ optionList, strategy, space }) {
const symbol = space?.symbol;

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import BigNumber from "bignumber.js";
import { Tooltip } from "@osn/common-ui";
import { SystemFail, SystemPass } from "@osn/icons/opensquare";
import OnePersonOneVoteOptionList from "./common/onePersonOneVoteOptionList";
import VoteCountOptionList from "./common/voteCountOptionList";

export default function OnePersonOneVoteResult({
proposal,
Expand Down Expand Up @@ -74,7 +74,7 @@ export default function OnePersonOneVoteResult({
});

return (
<OnePersonOneVoteOptionList
<VoteCountOptionList
strategy="one-person-one-vote"
optionList={optionList}
space={space}
Expand Down
Loading

0 comments on commit fa45492

Please sign in to comment.