Skip to content

Commit

Permalink
Merge pull request #492 from DemocracyEarth/daoverse
Browse files Browse the repository at this point in the history
Supports MolochDAO on-chain votes.
  • Loading branch information
santisiri authored Jan 10, 2020
2 parents 3dc71a0 + a1f453c commit 5073c33
Show file tree
Hide file tree
Showing 14 changed files with 280 additions and 90 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
Create and participate in Digital Autonomous Organizations (DAOs).

[![Join the chat at https://gitter.im/DemocracyEarth/sovereign](https://badges.gitter.im/DemocracyEarth/sovereign.svg)](https://gitter.im/DemocracyEarth/sovereign?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Slack Status](http://chat.democracy.earth/badge.svg)](http://chat.democracy.earth)
[![Build Status](http://ci.comunes.org/buildStatus/icon?job=sovereign)](http://ci.comunes.org/job/sovereign/)

Read our 📃 [white paper](https://github.com/DemocracyEarth/paper) and check our presentations in [Paris 🇫🇷 2016](https://youtube.com/watch?v=UajbQTHnTfM), [New York 🇺🇸 2019](https://www.youtube.com/watch?v=o2u0g0-hjgk) and [Berlin 🇩🇪 2019](https://www.youtube.com/watch?v=JJBDcG2EqwE).
Expand All @@ -26,7 +25,7 @@ Read our 📃 [white paper](https://github.com/DemocracyEarth/paper) and check o

**Release:**

* Currently [`version 0.7.0`](https://github.com/DemocracyEarth/sovereign/releases)
* Currently [`version 0.7`](https://github.com/DemocracyEarth/sovereign/releases)
* This [User Agreement](https://github.com/DemocracyEarth/sovereign/blob/master/UserAgreement.md) governs access to and use of the Democracy Earth platform.

## Setup
Expand Down
10 changes: 7 additions & 3 deletions i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@
"close": "Close",
"metamask-denied-signature": "Transaction signature was denied.",
"metamask-invalid-address": "Address mismatch.<br>Verify wallet account is the same used to sign in.",
"metamask-invalid-argument": "An invalid argument was passed to the contact.",
"blockchain-address": "Blockchain Address",
"blockchain-address-placeholder": "Your account if none specified.",
"cost-per-vote": "Tokens required per vote",
Expand Down Expand Up @@ -727,15 +728,15 @@
"poll-never-ends": "This poll never ends (always on).",
"height-compressed": "blocks",
"height-singular": "block",
"poll-is-closed": "This poll is no longer open for voting.",
"poll-is-closed": "This poll is not open for voting.",
"feeds": "Feeds",
"poll-hypothetical": "Poll will end in {{days}} {{hours}} {{minutes}} {{seconds}} (in {{blocks}})",
"coinvote-signature": "A total of {{quantity}} {{ticker}} will be tallied in support of {{choice}} in the proposal available on {{url}}. No tokens will be spent.",
"metamask-confirm-tally": "Sign vote with your private key.<br>To be included on Delegate list:",
"transaction-tally": "{{token}} Signature verified, account balance tallied.",
"transaction-tally-denied": "{{token}} Signature denied, no votes tallied.",
"already-voted": "Already Voted",
"already-voted-detail": "Your account balance has already been tallied on this decision.",
"already-voted-detail": "Your vote has already been tallied on this proposal.",
"election-rule-onchain": "On-chain vote.",
"voting-editor-onchain-tooltip": "Governance for this decision is tallied on the blockchain.",
"election-rule-webvote": "Web Vote",
Expand Down Expand Up @@ -817,7 +818,10 @@
"moloch-contract-ragequit-tooltip": "A member has burned shares to withdraw funds from this DAO.",
"not-synced": "Not synced ",
"not-synced-message": "The application is not synced with the corresponding blockchain for this transaction.",
"dao-confirm-tally": "Confirm vote in your blockchain wallet.<br>This will be a vote for <strong>{{voteValue}}</strong>.",
"not-connected": "Not connected",
"not-connected-message": "The application is not connected to a server.",
"dao-confirm-tally": "You are voting for <strong>{{voteValue}}</strong> on:<br><em>{{proposalName}}</em><br><br>Confirm vote in your blockchain wallet.<br>",
"dao-default-tally": "You are voting on<br><em>{{proposalName}}</em><br><br>Confirm vote in your blockchain wallet.<br>",
"moloch-guild": "Guild.",
"guild-total-shares": "Total Shares",
"guild-total-assets": "Total Assets",
Expand Down
30 changes: 19 additions & 11 deletions imports/api/blockchain/Blockchain.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,42 +97,50 @@ Schema.ContractMap = new SimpleSchema({
},
});

Schema.Map = new SimpleSchema({
eventName: {
Schema.Parameter = new SimpleSchema({
name: {
type: String,
optional: true,
},
collectionType: {
type: {
type: String,
optional: true,
},
contract: {
type: Schema.ContractMap,
value: {
type: String,
optional: true,
},
script: {
length: {
type: String,
optional: true,
},
});

Schema.Parameter = new SimpleSchema({
name: {
Schema.Map = new SimpleSchema({
eventName: {
type: String,
optional: true,
},
type: {
methodName: {
type: String,
optional: true,
},
value: {
collectionType: {
type: String,
optional: true,
},
length: {
contract: {
type: Schema.ContractMap,
optional: true,
},
script: {
type: String,
optional: true,
},
parameter: {
type: [Schema.Parameter],
optional: true,
},
});

Schema.Blockchain = new SimpleSchema({
Expand Down
154 changes: 139 additions & 15 deletions imports/startup/both/modules/metamask.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { Transactions } from '/imports/api/transactions/Transactions';
import { sync } from '/imports/ui/templates/layout/sync';
import { defaults } from '/lib/const';
import { Collectives } from '/imports/api/collectives/Collectives';
import { getShares, setTransaction } from '/lib/web3';
import { getTransactionObject } from '/lib/interpreter';

import { BigNumber } from 'bignumber.js';

Expand Down Expand Up @@ -234,14 +236,14 @@ const _delegate = (sourceId, targetId, contractId, hash, value) => {
* @param {object} smartContracts from collective map
* @param {string} functionName to identify abi from contract context
*/
const _getMap = (smartContracts, functionName) => {
const _getMethodMap = (smartContracts, functionName) => {
let myself;
let index;
let found = false;
if (smartContracts) {
for (let i = 0; i < smartContracts.length; i += 1) {
myself = _.findWhere(smartContracts[i].map, { eventName: functionName });
if (myself.eventName === functionName) {
myself = _.findWhere(smartContracts[i].map, { methodName: functionName });
if (myself.methodName === functionName) {
found = true;
index = i;
break;
Expand All @@ -254,17 +256,142 @@ const _getMap = (smartContracts, functionName) => {
return undefined;
};

/**
* @summary adds a temporary pending transaction on server db
* @param {string} voterAddress is coming from
* @param {string} hash from transaction
* @param {object} contract being voted on
* @param {object} choice contract being voted for
*/
const _pendingTransaction = (voterAddress, hash, contract, choice) => {
const voter = Meteor.user();
if (voter) {
const shares = getShares(voter, defaults.TOKEN);
const ticket = {
shares,
timestamp: new Date(),
contract: {
_id: contract._id,
},
poll: {
_id: choice._id,
},
address: contract.keyword,
blockchain: {
tickets: [
{
hash,
status: 'PENDING',
value: shares.toNumber(),
},
],
coin: {
code: defaults.TOKEN,
},
publicAddress: voterAddress.toLowerCase(),
score: {
totalConfirmed: '0',
totalPending: shares.toString(),
totalFail: '0',
finalConfirmed: 0,
finalPending: shares.toNumber(),
finalFail: 0,
value: 0,
},
},
};
const transactionObject = getTransactionObject(voter, ticket);
transactionObject.status = 'PENDING';
setTransaction(voter._id, choice._id, transactionObject);
}
};

/**
* @summary call a method from a dao using a collective map
* @param {string} methodName to call from contract
* @param {array} parameterList with parameter values to include in the call
* @param {string} collectiveId to look for required contract
* @param {string} walletMetho either 'call' or 'send' initially.
* @param {object} walletParameters from the signing user
*/
const _callDAOMethod = async (methodName, parameterList, collectiveId, walletMethod, walletParameters) => {
let response;
if (_web3(true)) {
const collective = Collectives.findOne({ _id: collectiveId });
if (collective) {
const smartContracts = collective.profile.blockchain.smartContracts;
const map = _getMethodMap(smartContracts, methodName);
const contractABI = JSON.parse(map.abi);

const dao = await new web3.eth.Contract(contractABI, map.publicAddress);

await dao.methods[`${methodName}`](...parameterList)[walletMethod](walletParameters, (err, res) => {
if (err) {
let message;
switch (err.code) {
case -32602:
message = TAPi18n.__('metamask-invalid-argument');
break;
case -32603:
message = TAPi18n.__('metamask-invalid-address');
break;
case 4001:
message = TAPi18n.__('metamask-denied-signature');
break;
default:
message = err.message;
}
displayModal(
true,
{
icon: Meteor.settings.public.app.logo,
title: TAPi18n.__('wallet'),
message,
cancel: TAPi18n.__('close'),
alertMode: true,
}
);
return err;
}
response = res;
return res;
});
}
}
return response;
};

/**
* @summary submit vote to moloch dao
* @param {number} proposalIndex uint256
* @param {number} uintVote uint8
* @param {object} contract from parent of poll
* @param {object} choice poll contract with choice voted
*/
const _submitVote = async (proposalIndex, uintVote, collectiveId) => {
if (_web3(true)) {
const collective = Collectives.findOne({ _id: collectiveId });
const _hasRightToVote = async (memberAddress, proposalIndex, collectiveId) => {
const memberVotes = await _callDAOMethod('getMemberProposalVote', [memberAddress, proposalIndex], collectiveId, 'call', {});
return (memberVotes === 0);
};

/**
* @summary submit vote to moloch dao
* @param {number} proposalIndex uint256
* @param {number} uintVote uint8
* @param {object} contract from parent of poll
* @param {object} choice poll contract with choice voted
*/
const _submitVote = async (proposalIndex, uintVote, contract, choice) => {
const res = await _callDAOMethod('submitVote', [proposalIndex, uintVote], choice.collectiveId, 'send', { from: Meteor.user().username });
if (res) {
_pendingTransaction(Meteor.user().username, res, contract, choice);
displayModal(false, modal);
}

/**
const collective = Collectives.findOne({ _id: choice.collectiveId });
const smartContracts = collective.profile.blockchain.smartContracts;
const map = _getMap(smartContracts, 'SubmitVote');
const map = _getMethodMap(smartContracts, 'submitVote');
const contractABI = JSON.parse(map.abi);
const dao = await new web3.eth.Contract(contractABI, map.publicAddress);
Expand All @@ -290,16 +417,12 @@ const _submitVote = async (proposalIndex, uintVote, collectiveId) => {
alertMode: true,
},
);
return err;
}
_pendingTransaction(Meteor.user().username, res, contract, choice);
displayModal(false, modal);
return res;
});

console.log(`dao: ${dao}`);
// const dao = await new web3.eth.Contract(abi, smartContract.publicAddress);
console.log('submitting vote....');
console.log(`proposalIndex: ${proposalIndex}`);
console.log(`uintVote: ${uintVote}`);
}
});*/
};

/**
Expand Down Expand Up @@ -807,3 +930,4 @@ export const getBlockHeight = _getBlockHeight;
export const getLastTimestamp = _getLastTimestamp;
export const verifyCoinVote = _verifyCoinVote;
export const submitVote = _submitVote;
export const hasRightToVote = _hasRightToVote;
4 changes: 2 additions & 2 deletions imports/ui/css/earth.css
Original file line number Diff line number Diff line change
Expand Up @@ -6274,12 +6274,12 @@ blockquote {
.token-pending {
display: inline-block;
margin: -1px -3px -1px 5px;
padding: 3px 3px 1px;
padding: 2px 3px 3px;
float: right;
border-radius: 3px;
background-color: #f9d55b;
color: #8f6e00;
font-size: 8px;
font-size: 0.65em;
line-height: 8px;
text-transform: uppercase;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template name="guild">
<div id="non-editable-feed" class="ledger">
<div class="vote vote-delegation vote-feed vote-search w-clearfix">
<div class="vote vote-delegation vote-feed vote-search guild-block">
{{#if ready}}
<div class="guild">
<div class="guild-row">
Expand Down
7 changes: 4 additions & 3 deletions imports/ui/templates/components/decision/balance/balance.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
<div class="token-pending">
{{pending}}
</div>
{{else}}
<div class="token-score">
{{balance}}
</div>
{{/if}}
<div class="token-score">
{{balance}}
</div>
</div>
{{#unless disableStake}}
<div class="token-stake">
Expand Down
Loading

0 comments on commit 5073c33

Please sign in to comment.