Skip to content

Commit

Permalink
Check social member, #1034
Browse files Browse the repository at this point in the history
  • Loading branch information
hyifeng committed Sep 3, 2024
1 parent e5f1d6b commit 92c7e4e
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const config = {
{
network: networks.kusama,
ss58Format: 2,
whoCanVote: "societyMember",
assets: [
{
symbol: "KSM",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { NODE_API_ENDPOINT } = require("../../env");
const { fetchApi } = require("../../utils/fech.api");

async function getSocietyMembers(network, height) {
const url = `${NODE_API_ENDPOINT}/${network}/society/members/height/${height}`;
return await fetchApi(url);
}

module.exports = {
getSocietyMembers,
};
97 changes: 69 additions & 28 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,7 @@ const { getBeenDelegated } = require("../node.service/getBeenDelegated");
const { adaptBalance } = require("../../utils/balance");
const { getDemocracyDelegated } = require("../node.service/getDelegated");
const { findDelegationStrategies } = require("../../utils/delegation");
const { getSocietyMembers } = require("../node.service/getSocietyMembers");

async function getDelegatorBalances({
proposal,
Expand Down Expand Up @@ -134,6 +135,57 @@ async function addDelegatedVotes(
}
}

async function checkVoterDelegation({
proposal,
voterNetwork,
address,
realVoter,
}) {
const snapshotHeight = proposal.snapshotHeights?.[voterNetwork];
const voter = realVoter || address;

if (realVoter && realVoter !== address) {
await checkDelegation(voterNetwork, address, realVoter, snapshotHeight);
}

const delegationStrategies = findDelegationStrategies(
proposal.networksConfig,
voterNetwork,
);
if (delegationStrategies.includes("democracy")) {
const delegation = await getDemocracyDelegated(
voterNetwork,
snapshotHeight,
voter,
);
if (!isEmpty(delegation)) {
throw new HttpError(
400,
"You can't vote because you have delegated your votes",
);
}
}
}

async function checkWhoCanVote({ proposal, voterNetwork, address, realVoter }) {
const snapshotHeight = proposal.snapshotHeights?.[voterNetwork];
const voter = realVoter || address;

const networkCfg = proposal.networksConfig.networks?.find(
(networkCfg) => networkCfg.network === voterNetwork,
);
if (networkCfg && networkCfg.whoCanVote === "societyMember") {
const societyMembers = await getSocietyMembers(
voterNetwork,
snapshotHeight,
);
const item = societyMembers.find((item) => item.address === voter);
if (!item) {
throw new HttpError(400, "Cannot vote");
}
}
}

async function vote(
proposalCid,
choices,
Expand Down Expand Up @@ -181,30 +233,17 @@ async function vote(
throw new HttpError(400, "Voter network is not supported by this proposal");
}

const snapshotHeight = proposal.snapshotHeights?.[voterNetwork];
if (realVoter && realVoter !== address) {
await checkDelegation(voterNetwork, address, realVoter, snapshotHeight);
}
await checkVoterDelegation({
proposal,
voterNetwork,
address,
realVoter,
});

const snapshotHeight = proposal.snapshotHeights?.[voterNetwork];
const voter = realVoter || address;

const delegationStrategies = findDelegationStrategies(
proposal.networksConfig,
voterNetwork,
);
if (delegationStrategies.includes("democracy")) {
const delegation = await getDemocracyDelegated(
voterNetwork,
snapshotHeight,
voter,
);
if (!isEmpty(delegation)) {
throw new HttpError(
400,
"You can't vote because you have delegated your votes",
);
}
}
await checkWhoCanVote({ proposal, voterNetwork, address, realVoter });

const networkBalance = await getBalanceFromNetwork({
networksConfig: proposal.networksConfig,
Expand All @@ -229,14 +268,16 @@ async function vote(
const networkConfig = networksConfig?.networks?.find(
(item) => item.network === voterNetwork,
);
const passThreshold = networkConfig?.assets?.some((item) =>
networkBalanceDetails?.some((balance) =>
new BigNumber(item.votingThreshold || 0).lte(balance.balance),
),
);
if (networkConfig?.assets) {
const passThreshold = networkConfig?.assets?.some((item) =>
networkBalanceDetails?.some((balance) =>
new BigNumber(item.votingThreshold || 0).lte(balance.balance),
),
);

if (!passThreshold) {
throw new HttpError(400, "You don't have enough balance to vote");
if (!passThreshold) {
throw new HttpError(400, "You don't have enough balance to vote");
}
}

const delegators = await getDelegatorBalances({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const { getApis, getBlockApi } = require("@osn/polkadot-api-container");
const { chains } = require("../../constants");

async function getSocietyMembersFromOneApi(api, blockHashOrHeight) {
let blockApi = await getBlockApi(api, blockHashOrHeight);
const societyMembers = await blockApi.query.society.members.entries();

return societyMembers.map(([key, value]) => {
const {
args: [id],
} = key;
const address = id.toJSON();
const data = value.toJSON();
return { address, ...data };
});
}

async function getSocietyMembersFromApis(apis, blockHashOrHeight) {
const promises = [];
for (const api of apis) {
promises.push(getSocietyMembersFromOneApi(api, blockHashOrHeight));
}

return await Promise.any(promises);
}

async function getSocietyMembers(ctx) {
const { chain } = ctx.params;
const { block: blockHashOrHeight } = ctx.query;
if (![chains.kusama].includes(chain)) {
ctx.throw(400, `Not support chain ${chain}`);
}

const apis = getApis(chain);
ctx.body = await getSocietyMembersFromApis(apis, blockHashOrHeight);
}

module.exports = {
getSocietyMembers,
};
7 changes: 7 additions & 0 deletions backend/packages/node-api/src/features/society/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const Router = require("koa-router");
const { getSocietyMembers } = require("./getSocietyMembers");

const router = new Router();
router.get("/society/members/height/:blockHashOrHeight?", getSocietyMembers);

module.exports = router;
7 changes: 7 additions & 0 deletions backend/packages/node-api/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const tokenMetaRoutes = require("./features/tokenMeta/routes");
const evmRoutes = require("./features/evm/routes");
const issuanceRoutes = require("./features/issuance/routes");
const stafiRoutes = require("./features/stafi/routes");
const societyRoutes = require("./features/society/routes");
const { evmChains } = require("./constants");
const { chains } = require("./constants");

Expand All @@ -38,6 +39,12 @@ module.exports = (app) => {
stafiRoutes.allowedMethods({ throw: true }),
);

router.use(
"/:chain(kusama)",
societyRoutes.routes(),
societyRoutes.allowedMethods({ throw: true }),
);

router.use(
"/:chain",
tokenMetaRoutes.routes(),
Expand Down

0 comments on commit 92c7e4e

Please sign in to comment.