Merge pull request #2 from status-im/feat/fix
refactoring and additional UI functionality for improved UX
This commit is contained in:
commit
c9db6abd18
|
@ -3,3 +3,4 @@ node_modules/
|
||||||
dist/
|
dist/
|
||||||
config/production/password
|
config/production/password
|
||||||
config/livenet/password
|
config/livenet/password
|
||||||
|
chains.json
|
||||||
|
|
|
@ -0,0 +1,284 @@
|
||||||
|
/*global web3*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import {Button, Grid, Row, Col, Alert } from 'react-bootstrap';
|
||||||
|
import * as NumericInput from 'react-numeric-input';
|
||||||
|
import Select from 'react-select';
|
||||||
|
|
||||||
|
import EmbarkJS from 'Embark/EmbarkJS';
|
||||||
|
|
||||||
|
import Meritocracy from 'Embark/contracts/Meritocracy';
|
||||||
|
|
||||||
|
// import './css/dapp.css';
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
- list praise for contributor
|
||||||
|
- listen to events to update UI, (initially on page load but within function calls)
|
||||||
|
*/
|
||||||
|
|
||||||
|
const MAINNET = 1;
|
||||||
|
const TESTNET = 3;
|
||||||
|
|
||||||
|
// Todo Resolve ENS entries
|
||||||
|
import contributors from "./contributors";
|
||||||
|
let options = contributors;
|
||||||
|
|
||||||
|
class App extends React.Component {
|
||||||
|
|
||||||
|
state = {
|
||||||
|
error: null,
|
||||||
|
errorMsg: null,
|
||||||
|
busy: true,
|
||||||
|
selectedContributors: [],
|
||||||
|
contributorList: [],
|
||||||
|
currentContributor: {
|
||||||
|
allocation: 0,
|
||||||
|
totalForfeited: 0,
|
||||||
|
totalReceived: 0,
|
||||||
|
received: 0,
|
||||||
|
status: []
|
||||||
|
},
|
||||||
|
award: 0,
|
||||||
|
praise: '',
|
||||||
|
networkName: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleContributorSelection = this.handleContributorSelection.bind(this);
|
||||||
|
this.handleAwardChange = this.handleAwardChange.bind(this);
|
||||||
|
this.handlePraiseChange = this.handlePraiseChange.bind(this);
|
||||||
|
this.awardTokens = this.awardTokens.bind(this);
|
||||||
|
this.withdrawTokens = this.withdrawTokens.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
EmbarkJS.onReady(async (err) => {
|
||||||
|
if (err) {
|
||||||
|
return this.setState({error: err.message || err});
|
||||||
|
}
|
||||||
|
|
||||||
|
const netId = await web3.eth.net.getId();
|
||||||
|
if (EmbarkJS.environment === 'testnet' && netId !== TESTNET) {
|
||||||
|
this.setState({ error: 'Please connect to Ropsten' });
|
||||||
|
return;
|
||||||
|
} else if (EmbarkJS.environment === 'livenet' && netId !== MAINNET) {
|
||||||
|
this.setState({ error: 'Please connect to Mainnet' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({busy: false});
|
||||||
|
|
||||||
|
options = options.map(prepareOptions);
|
||||||
|
|
||||||
|
await this.getContributors();
|
||||||
|
|
||||||
|
this.getCurrentContributorData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleContributorSelection(_selectedContributors) {
|
||||||
|
this.setState({ selectedContributors: _selectedContributors });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAwardChange(_amount) {
|
||||||
|
const { currentContributor: {allocation}, selectedContributors} = this.state;
|
||||||
|
|
||||||
|
const maxAllocation = allocation / selectedContributors.length;
|
||||||
|
const award = (_amount <= maxAllocation ? _amount : maxAllocation );
|
||||||
|
this.setState({award});
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePraiseChange(e) {
|
||||||
|
this.setState({ praise: e.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
resetUIFields(){
|
||||||
|
this.setState({
|
||||||
|
praise: '',
|
||||||
|
selectedContributors: [],
|
||||||
|
error: '',
|
||||||
|
errorMsg: '',
|
||||||
|
award: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCurrentContributorData(){
|
||||||
|
const currentContributor = await this.getContributor(web3.eth.defaultAccount);
|
||||||
|
|
||||||
|
let praises = [];
|
||||||
|
for(let i = 0; i < currentContributor.praiseNum; i++){
|
||||||
|
praises.push(Meritocracy.methods.getStatus(web3.eth.defaultAccount, i).call());
|
||||||
|
}
|
||||||
|
|
||||||
|
const contribData = options.find(x => x.value === web3.eth.defaultAccount);
|
||||||
|
if(contribData) currentContributor.name = contribData.label;
|
||||||
|
|
||||||
|
currentContributor.praises = await Promise.all(praises);
|
||||||
|
currentContributor.allocation = web3.utils.fromWei(currentContributor.allocation, "ether");
|
||||||
|
currentContributor.totalForfeited = web3.utils.fromWei(currentContributor.totalForfeited, "ether");
|
||||||
|
currentContributor.totalReceived = web3.utils.fromWei(currentContributor.totalReceived, "ether");
|
||||||
|
currentContributor.received = web3.utils.fromWei(currentContributor.received, "ether");
|
||||||
|
|
||||||
|
this.setState({currentContributor});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getContributor(_address) {
|
||||||
|
const contributor = await Meritocracy.methods.contributors(_address).call();
|
||||||
|
contributor.praiseNum = await Meritocracy.methods.getStatusLength(_address).call();
|
||||||
|
return contributor;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getContributors() {
|
||||||
|
const registry = await Meritocracy.methods.getRegistry().call();
|
||||||
|
const contributorList = options.filter(x => registry.includes(x.value) && x.value !== web3.eth.defaultAccount);
|
||||||
|
this.setState({contributorList});
|
||||||
|
}
|
||||||
|
|
||||||
|
async awardTokens(e) {
|
||||||
|
const {award, selectedContributors, praise} = this.state;
|
||||||
|
|
||||||
|
// TODO some sanity checks
|
||||||
|
if(award <= 0) {
|
||||||
|
this.setState({errorMsg: 'amount must be more than 0'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let addresses = selectedContributors.map(a => a.value);
|
||||||
|
|
||||||
|
const sntAmount = web3.utils.toWei(award.toString(), "ether");
|
||||||
|
|
||||||
|
let toSend;
|
||||||
|
switch(addresses.length) {
|
||||||
|
case 0:
|
||||||
|
this.setState({errorMsg: 'No Contributor Selected'});
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
toSend = Meritocracy.methods.award(addresses[0], sntAmount, praise);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
toSend = Meritocracy.methods.awardContributors(addresses, sntAmount, praise);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.setState({busy: true});
|
||||||
|
|
||||||
|
const estimatedGas = await toSend.estimateGas({from: web3.eth.defaultAccount});
|
||||||
|
const receipt = await toSend.send({from: web3.eth.defaultAccount, gas: estimatedGas + 1000});
|
||||||
|
this.resetUIFields();
|
||||||
|
this.getCurrentContributorData();
|
||||||
|
} catch(e) {
|
||||||
|
this.setState({errorMsg: 'tx failed? got enough tokens to award?'});
|
||||||
|
console.error(e);
|
||||||
|
} finally {
|
||||||
|
this.setState({busy: false});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async withdrawTokens(e) {
|
||||||
|
const {currentContributor} = this.state;
|
||||||
|
|
||||||
|
if (currentContributor.received == 0) {
|
||||||
|
this.setState({errorMsg: 'can only call withdraw when you have tokens'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( currentContributor.allocation > 0 ) {
|
||||||
|
this.setState({errorMsg: 'you must allocate all your tokens'});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const toSend = Meritocracy.methods.withdraw();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.setState({busy: true});
|
||||||
|
|
||||||
|
const estimatedGas = await toSend.estimateGas({from: web3.eth.defaultAccount});
|
||||||
|
const receipt = await toSend.send({from: web3.eth.defaultAccount, gas: estimatedGas + 1000});
|
||||||
|
|
||||||
|
this.getCurrentContributorData();
|
||||||
|
} catch(e) {
|
||||||
|
this.setState({errorMsg: 'tx failed? Did you allocate all your tokens first?'});
|
||||||
|
console.error(e);
|
||||||
|
} finally {
|
||||||
|
this.setState({busy: false});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { selectedContributors, contributorList, award, currentContributor, praise, busy, error, errorMsg } = this.state;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (<div>
|
||||||
|
<div>Something went wrong connecting to ethereum. Please make sure you have a node running or are using metamask to connect to the ethereum network:</div>
|
||||||
|
<div>{error}</div>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxAllocation = selectedContributors.length ? currentContributor.allocation / selectedContributors.length : 0;
|
||||||
|
|
||||||
|
return (<div>
|
||||||
|
<h3>Status Meritocracy</h3>
|
||||||
|
|
||||||
|
{errorMsg && <Alert bsStyle="danger">{errorMsg}</Alert>}
|
||||||
|
|
||||||
|
{currentContributor.name && <h2>Hello, {currentContributor.name} !</h2>}
|
||||||
|
<span>Your Total Received Kudos: { currentContributor.totalReceived || 0} SNT</span> <br/>
|
||||||
|
<span>Your Total Forfeited Kudos: { currentContributor.totalForfeited || 0} SNT</span> <br/>
|
||||||
|
|
||||||
|
<h4>Award Kudos</h4>
|
||||||
|
<Select
|
||||||
|
isMulti
|
||||||
|
value={selectedContributors}
|
||||||
|
onChange={this.handleContributorSelection}
|
||||||
|
options={contributorList}
|
||||||
|
placeholder="Choose Contributor(s)..."
|
||||||
|
isDisabled={busy}
|
||||||
|
/>
|
||||||
|
<span>Your Allocatable Kudos: { currentContributor.allocation } SNT</span> <br/>
|
||||||
|
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<NumericInput mobile step={5} min={0} max={maxAllocation} onChange={this.handleAwardChange} value={award} disabled={busy} /> <br/>
|
||||||
|
|
||||||
|
<input disabled={busy} placeholder="Enter your praise..." onChange={this.handlePraiseChange} value={praise} /> <br/>
|
||||||
|
<span> Total Awarding: {award * selectedContributors.length} SNT </span> <br/>
|
||||||
|
<Button disabled={busy} variant="outline-primary" onClick={this.awardTokens}>Award</Button>
|
||||||
|
|
||||||
|
|
||||||
|
<h4>Your Kudos History</h4>
|
||||||
|
<span>Your Received Kudos: <b>{ currentContributor.received } SNT</b> <Button variant="outline-primary" onClick={this.withdrawTokens} disabled={busy}>Withdraw</Button></span> <br/>
|
||||||
|
<Grid>
|
||||||
|
<Row>
|
||||||
|
{currentContributor.praises && currentContributor.praises.map((item, i) => {
|
||||||
|
const name = options.find(x => x.value === item.author);
|
||||||
|
return <Col key={i}>{(name && name.label) || item.author} has sent you {web3.utils.fromWei(item.amount, "ether")} SNT {item.praise && "\"" + item.praise + "\""}</Col>;
|
||||||
|
})}
|
||||||
|
</Row>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// === Utils ===============================================
|
||||||
|
|
||||||
|
const prepareOptions = option => {
|
||||||
|
if(option.value.match(/^0x[0-9A-Za-z]{40}$/)){ // Address
|
||||||
|
option.value = web3.utils.toChecksumAddress(option.value);
|
||||||
|
} else { // ENS Name
|
||||||
|
// TODO: resolve ENS names
|
||||||
|
// EmbarkJS.Names.resolve("ethereum.eth").then(address => {
|
||||||
|
// console.log("the address for ethereum.eth is: " + address);
|
||||||
|
//
|
||||||
|
}
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
|
@ -0,0 +1,47 @@
|
||||||
|
const contributors = [
|
||||||
|
{ 'label' : 'Jarrad (Test)', 'value' : '0x061b0227116e76025D5573cFbb1Ac854916286Fe' },
|
||||||
|
{ 'label' : 'Andreas S.', 'value' : '0x4923121411e884a4af66ec025712eba600a782d3' },
|
||||||
|
{ 'label' : 'andrey.dev', 'value' : '0xA4EcA293cb578a68b190e3e07c2B170dc753fe44' },
|
||||||
|
{ 'label' : 'barry', 'value' : '0xa46b0546481a04b7de049a8a20f8a9b2b2c5cc05' },
|
||||||
|
{ 'label' : 'BrianXV', 'value' : '0x03b832b3fa819d7a4b6c819e4df1e60a173e739a' },
|
||||||
|
{ 'label' : 'ceri', 'value' : '0x68f47e153e1aa7d6529e078feff86eada87ddee3' },
|
||||||
|
{ 'label' : 'Dani', 'value' : '0x89c010bc7085eb150b66582f13681f9e36904bea' },
|
||||||
|
{ 'label' : 'dmitryn', 'value' : '0x6b0d7ba67aa3d84122749dc7906b8e7f25ed1af8' },
|
||||||
|
{ 'label' : 'gravityblast', 'value' : '0xb5a2c17c7fd72070fcf078bb8458f2f595441066' },
|
||||||
|
{ 'label' : 'guylouis.stateofus.eth', 'value' : '0x6913f3bdbb7c303977d6244c0e0071b4ebc6f359' },
|
||||||
|
{ 'label' : 'Hester', 'value' : '0x8c4f71b3cf6a76de2cc239a6fa84e1a80e589598' },
|
||||||
|
{ 'label' : 'Hutch', 'value' : '0x34a4b73100d11815ee4bb0ebcc86ba5824b12134' },
|
||||||
|
{ 'label' : 'igor.stateofus.eth', 'value' : '0x6a069D627BAA9a627D79D2097EC979E2c58F1984' },
|
||||||
|
{ 'label' : 'jakubgs.eth', 'value' : '0x9b64770c9485A5188D238C305E53627A67C05D7D'},
|
||||||
|
{ 'label' : 'Jinho', 'value' : '0x7407bF49004ee99d9B2caA2fb90B476bfF2DbCaf' },
|
||||||
|
{ 'label' : 'Jonathan Barker', 'value' : '0xf23d05F375A8367b150f7Ad1A37DFd9E3c35eE56' },
|
||||||
|
{ 'label' : 'Jonathan Rainville', 'value' : '0x9ce0056c5fc6bb9459a4dcfa35eaad8c1fee5ce9' },
|
||||||
|
{ 'label' : 'Jonny Z', 'value' : '0xa40b07ac80d1f89b233b74e78d254c90906c33ee' },
|
||||||
|
{ 'label' : 'Julien', 'value' : '0x6c618ddbf53aa9540c279e3670d4d26fb367fd4e' },
|
||||||
|
{ 'label' : 'Maciej', 'value' : '0x227612e69b1d06250e7035c1c12840561ebf3c56' },
|
||||||
|
{ 'label' : 'michele', 'value' : '0x658a1d2c105b35d9aaad38480dbbfe47b9054962' },
|
||||||
|
{ 'label' : 'Nabil', 'value' : '0x528c9e62bb0e7083f4b42802297b38ba237776a0' },
|
||||||
|
{ 'label' : 'Oskar', 'value' : '0x3fd6e2dfa535ce8b1e7eb7116a009eba3890b6bd' },
|
||||||
|
{ 'label' : 'PascalPrecht', 'value' : '0x6f490165DdD8d604b52dB9D9BF9b63aE997DC11C' },
|
||||||
|
{ 'label' : 'pedro.stateofus.eth', 'value' : '0x78EA50b13de394671474314aA261556717bF9185' },
|
||||||
|
{ 'label' : 'Rachel', 'value' : '0x4b9ba5B0dEE90f5B84Bcbfbf921cF02e1C8da113' },
|
||||||
|
{ 'label' : 'Rajanie', 'value' : '0x8af0d6fabc4a90ea0b95f80ab62beb816ed32a69' },
|
||||||
|
{ 'label' : 'Ricardo Schmidt <3esmit>', 'value' : '0x3D597789ea16054a084ac84ce87F50df9198F415' },
|
||||||
|
{ 'label' : 'Sergey', 'value' : '0xb9f914fe1c6edae2351fb42276868470083a3cd2' },
|
||||||
|
{ 'label' : 'shemnon', 'value' : '0x82ad1b2419fd71dfe2d5db9b3c832c60ec96c53b' },
|
||||||
|
{ 'label' : 'sonja.stateofus.eth', 'value' : '0xCF03738e9605C0B38cEAa7349bF6926463f01A25' },
|
||||||
|
{ 'label' : 'Swader', 'value' : '0x9702797d92e2a06070b446e49a594a943686e28f' },
|
||||||
|
{ 'label' : 'yenda', 'value' : '0xe829f7947175fe6a338344e70aa770a8c134372c' },
|
||||||
|
{ 'label' : 'petty', 'value' : '0x2942577508e060ea092c0CD7802ae42c1CEA2BAe' },
|
||||||
|
{ 'label' : 'chu', 'value' : '0xd21DB0e43048AcB94f428eD61dC244c82f1ff2a8' },
|
||||||
|
{ 'label' : 'Yessin', 'value' : '0xbaba92b7822a56c05554ab5d1bc1d0b7e212499d' },
|
||||||
|
{ 'label' : 'michaelb', 'value' : '0xdba0bade45727776bbb0d93176ee1ddba830f319' },
|
||||||
|
{ 'label' : 'cryptowanderer', 'value' : '0x406abd306b633b6460666b4092784a3330370c7b' },
|
||||||
|
{ 'label' : 'adam.stateofus.eth', 'value' : '0x074032269ca1775896c92304d45f80b5a67a5bcb' },
|
||||||
|
{ 'label' : 'André Medeiros', 'value' : '0xf062E478870B17B55d1dC64888914B82aD9808B4' },
|
||||||
|
{ 'label' : 'rramos', 'value' : '0xc379330ae48716b81d7411813c3250cd89271788' },
|
||||||
|
{ 'label' : 'emizzle', 'value' : '0x91Ef8ef20Adf13E42757a3Ed6Ff2b1249bE15544' },
|
||||||
|
{ 'label' : 'jason.stateofus.eth', 'value' : '0x4636fb2F6D1DC335EA655795064c2092c89148aB' }
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = contributors;
|
279
app/js/index.js
279
app/js/index.js
|
@ -1,281 +1,6 @@
|
||||||
/*global web3*/
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import {Tabs, Tab, Button, Grid, Row, Col } from 'react-bootstrap';
|
|
||||||
import * as NumericInput from 'react-numeric-input';
|
|
||||||
import Select from 'react-select';
|
|
||||||
|
|
||||||
import EmbarkJS from 'Embark/EmbarkJS';
|
import App from './app';
|
||||||
// import Blockchain from './components/blockchain';
|
|
||||||
|
|
||||||
import Meritocracy from 'Embark/contracts/Meritocracy';
|
ReactDOM.render(<App />, document.getElementById('app'));
|
||||||
|
|
||||||
// import './css/dapp.css';
|
|
||||||
|
|
||||||
/*
|
|
||||||
TODO:
|
|
||||||
- list praise for contributor
|
|
||||||
- listen to events to update UI, (initially on page load but within function calls)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Todo Resolve ENS entries
|
|
||||||
const options = [
|
|
||||||
{ 'label' : 'Jarrad (Test)', 'value' : '0x061b0227116e76025D5573cFbb1Ac854916286Fe' },
|
|
||||||
{ 'label' : 'Andreas S.', 'value' : '0x4923121411e884a4af66ec025712eba600a782d3' },
|
|
||||||
{ 'label' : 'andrey.dev', 'value' : '0xA4EcA293cb578a68b190e3e07c2B170dc753fe44' },
|
|
||||||
{ 'label' : 'barry', 'value' : '0xa46b0546481a04b7de049a8a20f8a9b2b2c5cc05' },
|
|
||||||
{ 'label' : 'BrianXV', 'value' : '0x03b832b3fa819d7a4b6c819e4df1e60a173e739a' },
|
|
||||||
{ 'label' : 'ceri', 'value' : '0x68f47e153e1aa7d6529e078feff86eada87ddee3' },
|
|
||||||
{ 'label' : 'Dani', 'value' : '0x89c010bc7085eb150b66582f13681f9e36904bea' },
|
|
||||||
{ 'label' : 'dmitryn', 'value' : '0x6b0d7ba67aa3d84122749dc7906b8e7f25ed1af8' },
|
|
||||||
{ 'label' : 'gravityblast', 'value' : '0xb5a2c17c7fd72070fcf078bb8458f2f595441066' },
|
|
||||||
{ 'label' : 'guylouis.stateofus.eth', 'value' : '0x6913f3bdbb7c303977d6244c0e0071b4ebc6f359' },
|
|
||||||
{ 'label' : 'Hester', 'value' : '0x8c4f71b3cf6a76de2cc239a6fa84e1a80e589598' },
|
|
||||||
{ 'label' : 'Hutch', 'value' : '0x34a4b73100d11815ee4bb0ebcc86ba5824b12134' },
|
|
||||||
{ 'label' : 'igor.stateofus.eth', 'value' : '0x6a069D627BAA9a627D79D2097EC979E2c58F1984' },
|
|
||||||
{ 'label' : 'jakubgs.eth', 'value' : 'jakubgs.eth'},
|
|
||||||
{ 'label' : 'Jinho', 'value' : '0x7407bF49004ee99d9B2caA2fb90B476bfF2DbCaf' },
|
|
||||||
{ 'label' : 'Jonathan Barker', 'value' : '0xf23d05F375A8367b150f7Ad1A37DFd9E3c35eE56' },
|
|
||||||
{ 'label' : 'Jonathan Rainville', 'value' : '0x9ce0056c5fc6bb9459a4dcfa35eaad8c1fee5ce9' },
|
|
||||||
{ 'label' : 'Jonny Z', 'value' : '0xa40b07ac80d1f89b233b74e78d254c90906c33ee' },
|
|
||||||
{ 'label' : 'Julien', 'value' : '0x6c618ddbf53aa9540c279e3670d4d26fb367fd4e' },
|
|
||||||
{ 'label' : 'Maciej', 'value' : '0x227612e69b1d06250e7035c1c12840561ebf3c56' },
|
|
||||||
{ 'label' : 'michele', 'value' : '0x658a1d2c105b35d9aaad38480dbbfe47b9054962' },
|
|
||||||
{ 'label' : 'Nabil', 'value' : '0x528c9e62bb0e7083f4b42802297b38ba237776a0' },
|
|
||||||
{ 'label' : 'Oskar', 'value' : '0x3fd6e2dfa535ce8b1e7eb7116a009eba3890b6bd' },
|
|
||||||
{ 'label' : 'PascalPrecht', 'value' : '0x6f490165DdD8d604b52dB9D9BF9b63aE997DC11C' },
|
|
||||||
{ 'label' : 'pedro.stateofus.eth', 'value' : '0x78EA50b13de394671474314aA261556717bF9185' },
|
|
||||||
{ 'label' : 'Rachel', 'value' : '0x4b9ba5B0dEE90f5B84Bcbfbf921cF02e1C8da113' },
|
|
||||||
{ 'label' : 'Rajanie', 'value' : '0x8af0d6fabc4a90ea0b95f80ab62beb816ed32a69' },
|
|
||||||
{ 'label' : 'Ricardo Schmidt <3esmit>', 'value' : '0x3D597789ea16054a084ac84ce87F50df9198F415' },
|
|
||||||
{ 'label' : 'Sergey', 'value' : '0xb9f914fe1c6edae2351fb42276868470083a3cd2' },
|
|
||||||
{ 'label' : 'shemnon', 'value' : '0x82ad1b2419fd71dfe2d5db9b3c832c60ec96c53b' },
|
|
||||||
{ 'label' : 'sonja.stateofus.eth', 'value' : '0xCF03738e9605C0B38cEAa7349bF6926463f01A25' },
|
|
||||||
{ 'label' : 'Swader', 'value' : '0x9702797d92e2a06070b446e49a594a943686e28f' },
|
|
||||||
{ 'label' : 'yenda', 'value' : '0xe829f7947175fe6a338344e70aa770a8c134372c' },
|
|
||||||
{ 'label' : 'petty', 'value' : '0x2942577508e060ea092c0CD7802ae42c1CEA2BAe' },
|
|
||||||
{ 'label' : 'chu', 'value' : '0xd21DB0e43048AcB94f428eD61dC244c82f1ff2a8' },
|
|
||||||
{ 'label' : 'Yessin', 'value' : '0xbaba92b7822a56c05554ab5d1bc1d0b7e212499d' },
|
|
||||||
{ 'label' : 'michaelb', 'value' : '0xdba0bade45727776bbb0d93176ee1ddba830f319' },
|
|
||||||
{ 'label' : 'cryptowanderer', 'value' : '0x406abd306b633b6460666b4092784a3330370c7b' },
|
|
||||||
{ 'label' : 'adam.stateofus.eth', 'value' : '0x074032269ca1775896c92304d45f80b5a67a5bcb' },
|
|
||||||
{ 'label' : 'André Medeiros', 'value' : 'andre medeiros.eth' },
|
|
||||||
{ 'label' : 'rramos / rramos.stateofus.eth', 'value' : '0xc379330ae48716b81d7411813c3250cd89271788' },
|
|
||||||
{ 'label' : 'emizzle', 'value' : '0x91Ef8ef20Adf13E42757a3Ed6Ff2b1249bE15544' },
|
|
||||||
{ 'label' : 'jason.stateofus.eth', 'value' : '0x4636fb2F6D1DC335EA655795064c2092c89148aB' }
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
class App extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.handleContributorSelection = this.handleContributorSelection.bind(this);
|
|
||||||
this.handleAwardChange = this.handleAwardChange.bind(this);
|
|
||||||
this.handlePraiseChange = this.handlePraiseChange.bind(this);
|
|
||||||
this.awardTokens = this.awardTokens.bind(this);
|
|
||||||
this.withdrawTokens = this.withdrawTokens.bind(this);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
error: null,
|
|
||||||
activeTab: 1,
|
|
||||||
whisperEnabled: false,
|
|
||||||
storageEnabled: false,
|
|
||||||
blockchainEnabled: false,
|
|
||||||
|
|
||||||
selectedContributors: [],
|
|
||||||
contributorList: [], // TODO: Merge these data structures?
|
|
||||||
contributorData: {},
|
|
||||||
award: 0,
|
|
||||||
praise: ''
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
EmbarkJS.onReady((err) => {
|
|
||||||
this.setState({blockchainEnabled: true});
|
|
||||||
if (err) {
|
|
||||||
return this.setState({error: err.message || err});
|
|
||||||
}
|
|
||||||
|
|
||||||
// console.log(web3.eth.defaultAccount);
|
|
||||||
var contributorData = {};
|
|
||||||
contributorData[web3.eth.defaultAccount] = {
|
|
||||||
allocation: 0,
|
|
||||||
totalForfeited: 0,
|
|
||||||
totalReceived: 0,
|
|
||||||
received: 0,
|
|
||||||
status: []
|
|
||||||
};
|
|
||||||
this.setState({contributorData: contributorData, defaultAccount : web3.eth.defaultAccount });
|
|
||||||
|
|
||||||
this.getContributors();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleContributorSelection(_selectedContributors) {
|
|
||||||
this.setState({ selectedContributors: _selectedContributors });
|
|
||||||
console.log(`selectedContributors:`, selectedContributors);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleAwardChange(_amount) {
|
|
||||||
let maxAllocation = this.state.allocation / this.state.selectedContributors.length;
|
|
||||||
amount = (_amount <= maxAllocation ? _amount : maxAllocation );
|
|
||||||
this.setState({ award: amount });
|
|
||||||
console.log(`handleAwardChange:`, amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePraiseChange(e) {
|
|
||||||
this.setState({ praise: e.target.value });
|
|
||||||
}
|
|
||||||
|
|
||||||
getContributor(_address) {
|
|
||||||
console.log('getContributor', _address);
|
|
||||||
Meritocracy.methods.contributors(_address).call().then(_contributor => {
|
|
||||||
var contributorData = this.state.contributorData;
|
|
||||||
contributorData[_contributor.addr.toLowerCase()] = _contributor; // Lowercase here incase we use keys for <Select />
|
|
||||||
console.log(_contributor);
|
|
||||||
this.setState({ contributorData : contributorData });
|
|
||||||
this.forceUpdate() // ...
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getContributors() {
|
|
||||||
console.log('getContributors');
|
|
||||||
Meritocracy.methods.getRegistry().call().then(_registry => {
|
|
||||||
console.log('got return', _registry); // TODO why is this empty with metamask??
|
|
||||||
// This block is probably not needed if can use contributorData keys in <Select />
|
|
||||||
let registry = _registry.map(Function.prototype.call, String.prototype.toLowerCase);
|
|
||||||
let contributorList = options.filter(_e => {
|
|
||||||
if (registry.includes(_e.value.toLowerCase())) return _e;
|
|
||||||
// TODO resolve ENS names
|
|
||||||
// EmbarkJS.Names.resolve("ethereum.eth").then(address => {
|
|
||||||
// console.log("the address for ethereum.eth is: " + address);
|
|
||||||
// })
|
|
||||||
});
|
|
||||||
this.setState({ contributorList : contributorList });
|
|
||||||
|
|
||||||
// Get Individual Contributor Data
|
|
||||||
for(var i=0; i<_registry.length;i++) {
|
|
||||||
this.getContributor(_registry[i]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
awardTokens(e) {
|
|
||||||
let currentContributor = this.state.contributorData[this.state.defaultAccount];
|
|
||||||
|
|
||||||
// TODO some sanity checks
|
|
||||||
if(this.state.award <= 0) {
|
|
||||||
console.log('amount must be more than 0');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let addresses = this.state.selectedContributors.map(a => a.value);
|
|
||||||
|
|
||||||
switch(addresses.length) {
|
|
||||||
case 0:
|
|
||||||
console.log('No Contributor Selected');
|
|
||||||
return;
|
|
||||||
case 1:
|
|
||||||
// use award
|
|
||||||
console.log('use award');
|
|
||||||
|
|
||||||
try {
|
|
||||||
Meritocracy.methods.award(addresses[0], this.state.award, this.state.praise).send().then(_contributor => {
|
|
||||||
getContributor(this.state.defaultAccount);
|
|
||||||
});
|
|
||||||
} catch(e) {
|
|
||||||
console.log('tx failed? got enough tokens to award?');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// use awardContributors
|
|
||||||
console.log('using awardContributors');
|
|
||||||
|
|
||||||
try {
|
|
||||||
Meritocracy.methods.awardContributors(addresses, this.state.award, this.state.praise).send().then(_contributor => {
|
|
||||||
getContributor(this.state.defaultAccount);
|
|
||||||
});
|
|
||||||
} catch(e) {
|
|
||||||
console.log('tx failed? got enough tokens to award?');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
withdrawTokens(e) {
|
|
||||||
|
|
||||||
console.log('withdrawTokens');
|
|
||||||
let currentContributor = this.state.contributorData[this.state.defaultAccount];
|
|
||||||
|
|
||||||
if (currentContributor.received == 0) {
|
|
||||||
console.log('can only call withdraw when you have tokens');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( currentContributor.allocation > 0 ) {
|
|
||||||
console.log('you must allocate all your tokens');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Meritocracy.methods.withdraw().send().then(_contributor => {
|
|
||||||
getContributor(this.state.defaultAccount);
|
|
||||||
});
|
|
||||||
} catch(e) {
|
|
||||||
console.log('tx failed? Did you allocate all your tokens first?');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { selectedContributors, contributorList, award, contributorData, defaultAccount } = this.state;
|
|
||||||
if (this.state.error) {
|
|
||||||
return (<div>
|
|
||||||
<div>Something went wrong connecting to ethereum. Please make sure you have a node running or are using metamask to connect to the ethereum network:</div>
|
|
||||||
<div>{this.state.error}</div>
|
|
||||||
</div>);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!defaultAccount) return (<div>Cannot Find web3.eth.defaultAccount</div>);
|
|
||||||
const currentContributor = contributorData[defaultAccount];
|
|
||||||
console.log('currentContributor.allocation', defaultAccount, currentContributor.allocation);
|
|
||||||
return (<div>
|
|
||||||
<h3>Status Meritocracy</h3>
|
|
||||||
|
|
||||||
<span>Your Total Received Kudos: { currentContributor.totalReceived } SNT</span> <br/>
|
|
||||||
<span>Your Total Forfeited Kudos: { currentContributor.totalForfeited } SNT</span> <br/>
|
|
||||||
|
|
||||||
<h4>Award Kudos</h4>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
isMulti
|
|
||||||
defaultValue={selectedContributors}
|
|
||||||
onChange={this.handleContributorSelection}
|
|
||||||
options={contributorList}
|
|
||||||
placeholder="Choose Contributor(s)..."
|
|
||||||
/> <br/>
|
|
||||||
|
|
||||||
<span>Your Allocatable Kudos: { currentContributor.allocation } SNT</span> <br/>
|
|
||||||
|
|
||||||
<NumericInput mobile step={5} min={0} max={currentContributor.allocation / selectedContributors.length } onChange={this.handleAwardChange} defaultValue={award} /> <br/>
|
|
||||||
|
|
||||||
<input placeholder="Enter your praise..." onChange={this.handlePraiseChange}/> <br/>
|
|
||||||
<span> Total Awarding: {award * selectedContributors.length} SNT </span> <br/>
|
|
||||||
<Button variant="outline-primary" onClick={this.awardTokens}>Award</Button>
|
|
||||||
|
|
||||||
<h4>Your Kudos History</h4>
|
|
||||||
|
|
||||||
<span>Your Received Kudos: { currentContributor.received } SNT <Button variant="outline-primary" onClick={this.withdrawTokens}>Withdraw</Button></span> <br/>
|
|
||||||
<Grid>
|
|
||||||
<Row>
|
|
||||||
<Col>0x00 has sent you 500 SNT "keep up the good work"</Col>
|
|
||||||
</Row>
|
|
||||||
</Grid>
|
|
||||||
</div>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReactDOM.render(<App></App>, document.getElementById('app'));
|
|
||||||
|
|
|
@ -1,49 +1,4 @@
|
||||||
// this is also defined in index.js
|
const options = require("../app/js/contributors");
|
||||||
const options = [
|
|
||||||
{ 'label' : 'Jarrad (Test)', 'value' : '0x061b0227116e76025D5573cFbb1Ac854916286Fe' },
|
|
||||||
{ 'label' : 'Andreas S.', 'value' : '0x4923121411e884a4af66ec025712eba600a782d3' }, // commented because I already added to blockchain
|
|
||||||
{ 'label' : 'andrey.dev', 'value' : '0xA4EcA293cb578a68b190e3e07c2B170dc753fe44' },
|
|
||||||
{ 'label' : 'barry', 'value' : '0xa46b0546481a04b7de049a8a20f8a9b2b2c5cc05' },
|
|
||||||
{ 'label' : 'BrianXV', 'value' : '0x03b832b3fa819d7a4b6c819e4df1e60a173e739a' },
|
|
||||||
{ 'label' : 'ceri', 'value' : '0x68f47e153e1aa7d6529e078feff86eada87ddee3' },
|
|
||||||
{ 'label' : 'Dani', 'value' : '0x89c010bc7085eb150b66582f13681f9e36904bea' },
|
|
||||||
{ 'label' : 'dmitryn', 'value' : '0x6b0d7ba67aa3d84122749dc7906b8e7f25ed1af8' },
|
|
||||||
{ 'label' : 'gravityblast', 'value' : '0xb5a2c17c7fd72070fcf078bb8458f2f595441066' },
|
|
||||||
{ 'label' : 'guylouis.stateofus.eth', 'value' : '0x6913f3bdbb7c303977d6244c0e0071b4ebc6f359' },
|
|
||||||
{ 'label' : 'Hester', 'value' : '0x8c4f71b3cf6a76de2cc239a6fa84e1a80e589598' },
|
|
||||||
{ 'label' : 'Hutch', 'value' : '0x34a4b73100d11815ee4bb0ebcc86ba5824b12134' },
|
|
||||||
{ 'label' : 'igor.stateofus.eth', 'value' : '0x6a069D627BAA9a627D79D2097EC979E2c58F1984' },
|
|
||||||
// { 'label' : 'jakubgs.eth', 'value' : 'jakubgs.eth'}, // commented because ens resolving
|
|
||||||
{ 'label' : 'Jinho', 'value' : '0x7407bF49004ee99d9B2caA2fb90B476bfF2DbCaf' },
|
|
||||||
{ 'label' : 'Jonathan Barker', 'value' : '0xf23d05F375A8367b150f7Ad1A37DFd9E3c35eE56' },
|
|
||||||
{ 'label' : 'Jonathan Rainville', 'value' : '0x9ce0056c5fc6bb9459a4dcfa35eaad8c1fee5ce9' },
|
|
||||||
{ 'label' : 'Jonny Z', 'value' : '0xa40b07ac80d1f89b233b74e78d254c90906c33ee' },
|
|
||||||
{ 'label' : 'Julien', 'value' : '0x6c618ddbf53aa9540c279e3670d4d26fb367fd4e' },
|
|
||||||
{ 'label' : 'Maciej', 'value' : '0x227612e69b1d06250e7035c1c12840561ebf3c56' },
|
|
||||||
{ 'label' : 'michele', 'value' : '0x658a1d2c105b35d9aaad38480dbbfe47b9054962' },
|
|
||||||
{ 'label' : 'Nabil', 'value' : '0x528c9e62bb0e7083f4b42802297b38ba237776a0' },
|
|
||||||
{ 'label' : 'Oskar', 'value' : '0x3fd6e2dfa535ce8b1e7eb7116a009eba3890b6bd' },
|
|
||||||
{ 'label' : 'PascalPrecht', 'value' : '0x6f490165DdD8d604b52dB9D9BF9b63aE997DC11C' },
|
|
||||||
{ 'label' : 'pedro.stateofus.eth', 'value' : '0x78EA50b13de394671474314aA261556717bF9185' },
|
|
||||||
{ 'label' : 'Rachel', 'value' : '0x4b9ba5B0dEE90f5B84Bcbfbf921cF02e1C8da113' },
|
|
||||||
{ 'label' : 'Rajanie', 'value' : '0x8af0d6fabc4a90ea0b95f80ab62beb816ed32a69' },
|
|
||||||
{ 'label' : 'Ricardo Schmidt <3esmit>', 'value' : '0x3D597789ea16054a084ac84ce87F50df9198F415' },
|
|
||||||
{ 'label' : 'Sergey', 'value' : '0xb9f914fe1c6edae2351fb42276868470083a3cd2' },
|
|
||||||
{ 'label' : 'shemnon', 'value' : '0x82ad1b2419fd71dfe2d5db9b3c832c60ec96c53b' },
|
|
||||||
{ 'label' : 'sonja.stateofus.eth', 'value' : '0xCF03738e9605C0B38cEAa7349bF6926463f01A25' },
|
|
||||||
{ 'label' : 'Swader', 'value' : '0x9702797d92e2a06070b446e49a594a943686e28f' },
|
|
||||||
{ 'label' : 'yenda', 'value' : '0xe829f7947175fe6a338344e70aa770a8c134372c' },
|
|
||||||
{ 'label' : 'petty', 'value' : '0x2942577508e060ea092c0CD7802ae42c1CEA2BAe' },
|
|
||||||
{ 'label' : 'chu', 'value' : '0xd21DB0e43048AcB94f428eD61dC244c82f1ff2a8' },
|
|
||||||
{ 'label' : 'Yessin', 'value' : '0xbaba92b7822a56c05554ab5d1bc1d0b7e212499d' },
|
|
||||||
{ 'label' : 'michaelb', 'value' : '0xdba0bade45727776bbb0d93176ee1ddba830f319' },
|
|
||||||
{ 'label' : 'cryptowanderer', 'value' : '0x406abd306b633b6460666b4092784a3330370c7b' },
|
|
||||||
{ 'label' : 'adam.stateofus.eth', 'value' : '0x074032269ca1775896c92304d45f80b5a67a5bcb' },
|
|
||||||
// { 'label' : 'André Medeiros', 'value' : 'andre medeiros.eth' },
|
|
||||||
{ 'label' : 'rramos / rramos.stateofus.eth', 'value' : '0xc379330ae48716b81d7411813c3250cd89271788' },
|
|
||||||
{ 'label' : 'emizzle', 'value' : '0x91Ef8ef20Adf13E42757a3Ed6Ff2b1249bE15544' },
|
|
||||||
{ 'label' : 'jason.stateofus.eth', 'value' : '0x4636fb2F6D1DC335EA655795064c2092c89148aB' }
|
|
||||||
];
|
|
||||||
|
|
||||||
function getContributors () {
|
function getContributors () {
|
||||||
var addresses = options.map(a => "'"+ a.value + "'");
|
var addresses = options.map(a => "'"+ a.value + "'");
|
||||||
|
@ -107,6 +62,8 @@ module.exports = {
|
||||||
// contracts section.
|
// contracts section.
|
||||||
//strategy: 'implicit',
|
//strategy: 'implicit',
|
||||||
|
|
||||||
|
strategy: 'explicit',
|
||||||
|
|
||||||
contracts: {
|
contracts: {
|
||||||
"MiniMeToken": { "deploy": false },
|
"MiniMeToken": { "deploy": false },
|
||||||
"MiniMeTokenFactory": {
|
"MiniMeTokenFactory": {
|
||||||
|
@ -125,7 +82,6 @@ module.exports = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Meritocracy": {
|
"Meritocracy": {
|
||||||
"fromIndex": 0,
|
|
||||||
"args": [ "$SNT", 66]
|
"args": [ "$SNT", 66]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,13 +110,12 @@ module.exports = {
|
||||||
},
|
},
|
||||||
"afterDeploy": [
|
"afterDeploy": [
|
||||||
// Give Tokens to Meritocracy Owner
|
// Give Tokens to Meritocracy Owner
|
||||||
"SNT.methods.generateTokens('$accounts[0]', '100000000000000000000').send()",
|
"SNT.methods.generateTokens('$accounts[0]', '1000000000000000000000').send()",
|
||||||
// Add All Contributors
|
// Add All Contributors
|
||||||
"Meritocracy.methods.addContributors([" + getContributors().toString() + "]).send()",
|
"Meritocracy.methods.addContributors([" + getContributors().toString() + "]).send()",
|
||||||
// Allocate Owner Tokens
|
// Allocate Owner Tokens
|
||||||
"SNT.methods.approve('$Meritocracy', 10000).send()",
|
"SNT.methods.approve('$Meritocracy', '1000000000000000000000').send()",
|
||||||
"Meritocracy.methods.allocate(10000).send()"
|
"Meritocracy.methods.allocate('1000000000000000000000').send()",
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
},
|
},
|
||||||
|
@ -173,6 +128,28 @@ module.exports = {
|
||||||
// merges with the settings in default
|
// merges with the settings in default
|
||||||
// used with "embark run testnet"
|
// used with "embark run testnet"
|
||||||
testnet: {
|
testnet: {
|
||||||
|
contracts: {
|
||||||
|
"MiniMeToken": { "deploy": false },
|
||||||
|
"MiniMeTokenFactory": {
|
||||||
|
"address": "0x6bfa86a71a7dbc68566d5c741f416e3009804279"
|
||||||
|
},
|
||||||
|
"SNT": {
|
||||||
|
"address": "0xc55cF4B03948D7EBc8b9E8BAD92643703811d162"
|
||||||
|
},
|
||||||
|
"Meritocracy": {
|
||||||
|
"args": [ "$SNT", 66]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deployment: {
|
||||||
|
accounts: [{
|
||||||
|
mnemonic: "your ropsten mnemonic here",
|
||||||
|
numAddresses: "10"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"afterDeploy": [
|
||||||
|
// Add All Contributors
|
||||||
|
"Meritocracy.methods.addContributors([" + getContributors().toString() + "]).send()",
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
// merges with the settings in default
|
// merges with the settings in default
|
||||||
|
|
|
@ -88,14 +88,20 @@ contract Meritocracy {
|
||||||
// Split amount over each contributor in registry, any contributor can allocate? TODO maybe relax this restriction, so anyone can allocate tokens
|
// Split amount over each contributor in registry, any contributor can allocate? TODO maybe relax this restriction, so anyone can allocate tokens
|
||||||
function allocate(uint256 _amount) external {
|
function allocate(uint256 _amount) external {
|
||||||
// Locals
|
// Locals
|
||||||
uint256 individualAmount;
|
|
||||||
// Contributor memory cAllocator = contributors[msg.sender];
|
// Contributor memory cAllocator = contributors[msg.sender];
|
||||||
// Requirements
|
// Requirements
|
||||||
// require(cAllocator.addr != address(0)); // is sender a Contributor? TODO maybe relax this restriction.
|
// require(cAllocator.addr != address(0)); // is sender a Contributor? TODO maybe relax this restriction.
|
||||||
require(token.transferFrom(msg.sender, address(this), _amount));
|
uint256 individualAmount = _amount / registry.length;
|
||||||
|
|
||||||
|
// removing decimals
|
||||||
|
individualAmount = (individualAmount / 1000000000000000000 * 1000000000000000000);
|
||||||
|
|
||||||
|
uint amount = individualAmount * registry.length;
|
||||||
|
|
||||||
|
require(token.transferFrom(msg.sender, address(this), amount));
|
||||||
// Body
|
// Body
|
||||||
// cAllocator.inPot = true;
|
// cAllocator.inPot = true;
|
||||||
individualAmount = _amount / registry.length;
|
|
||||||
for (uint256 i = 0; i < registry.length; i++) {
|
for (uint256 i = 0; i < registry.length; i++) {
|
||||||
contributors[registry[i]].allocation += individualAmount;
|
contributors[registry[i]].allocation += individualAmount;
|
||||||
}
|
}
|
||||||
|
@ -151,6 +157,22 @@ contract Meritocracy {
|
||||||
emit ContributorTransaction(cSender.addr, cReceiver.addr);
|
emit ContributorTransaction(cSender.addr, cReceiver.addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getStatusLength(address _contributor) public view returns (uint) {
|
||||||
|
return contributors[_contributor].status.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatus(address _contributor, uint _index) public view returns (
|
||||||
|
address author,
|
||||||
|
string memory praise,
|
||||||
|
uint256 amount,
|
||||||
|
uint256 time
|
||||||
|
) {
|
||||||
|
author = contributors[_contributor].status[_index].author;
|
||||||
|
praise = contributors[_contributor].status[_index].praise;
|
||||||
|
amount = contributors[_contributor].status[_index].amount;
|
||||||
|
time = contributors[_contributor].status[_index].time;
|
||||||
|
}
|
||||||
|
|
||||||
// Allow Contributor to award multiple Contributors
|
// Allow Contributor to award multiple Contributors
|
||||||
function awardContributors(address[] calldata _contributors, uint256 _amountEach, string calldata _praise) external {
|
function awardContributors(address[] calldata _contributors, uint256 _amountEach, string calldata _praise) external {
|
||||||
// Locals
|
// Locals
|
||||||
|
|
Loading…
Reference in New Issue