diff --git a/.gitignore b/.gitignore index 13dd958..6a74080 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules/ dist/ config/production/password config/livenet/password +chains.json diff --git a/app/js/app.js b/app/js/app.js new file mode 100644 index 0000000..2397157 --- /dev/null +++ b/app/js/app.js @@ -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 (
+
Something went wrong connecting to ethereum. Please make sure you have a node running or are using metamask to connect to the ethereum network:
+
{error}
+
); + } + + const maxAllocation = selectedContributors.length ? currentContributor.allocation / selectedContributors.length : 0; + + return (
+

Status Meritocracy

+ + {errorMsg && {errorMsg}} + + {currentContributor.name &&

Hello, {currentContributor.name} !

} + Your Total Received Kudos: { currentContributor.totalReceived || 0} SNT
+ Your Total Forfeited Kudos: { currentContributor.totalForfeited || 0} SNT
+ +

Award Kudos

+
+ Total Awarding: {award * selectedContributors.length} SNT
+ + + +

Your Kudos History

+ Your Received Kudos: { currentContributor.received } SNT
+ + + {currentContributor.praises && currentContributor.praises.map((item, i) => { + const name = options.find(x => x.value === item.author); + return {(name && name.label) || item.author} has sent you {web3.utils.fromWei(item.amount, "ether")} SNT {item.praise && "\"" + item.praise + "\""}; + })} + + + +
); + } +} + + +// === 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; diff --git a/app/js/contributors.js b/app/js/contributors.js new file mode 100644 index 0000000..742fca5 --- /dev/null +++ b/app/js/contributors.js @@ -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; diff --git a/app/js/index.js b/app/js/index.js index cc70f63..78ec1a4 100644 --- a/app/js/index.js +++ b/app/js/index.js @@ -1,281 +1,6 @@ -/*global web3*/ import React from 'react'; 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 Blockchain from './components/blockchain'; +import App from './app'; -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) -*/ - -// 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 - 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 (
-
Something went wrong connecting to ethereum. Please make sure you have a node running or are using metamask to connect to the ethereum network:
-
{this.state.error}
-
); - } - - if(!defaultAccount) return (
Cannot Find web3.eth.defaultAccount
); - const currentContributor = contributorData[defaultAccount]; - console.log('currentContributor.allocation', defaultAccount, currentContributor.allocation); - return (
-

Status Meritocracy

- - Your Total Received Kudos: { currentContributor.totalReceived } SNT
- Your Total Forfeited Kudos: { currentContributor.totalForfeited } SNT
- -

Award Kudos

- -
- Total Awarding: {award * selectedContributors.length} SNT
- - -

Your Kudos History

- - Your Received Kudos: { currentContributor.received } SNT
- - - 0x00 has sent you 500 SNT "keep up the good work" - - -
); - } -} - -ReactDOM.render(, document.getElementById('app')); +ReactDOM.render(, document.getElementById('app')); diff --git a/config/contracts.js b/config/contracts.js index 304aea7..1eaf82f 100644 --- a/config/contracts.js +++ b/config/contracts.js @@ -1,49 +1,4 @@ -// this is also defined in index.js -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' } -]; +const options = require("../app/js/contributors"); function getContributors () { var addresses = options.map(a => "'"+ a.value + "'"); @@ -107,6 +62,8 @@ module.exports = { // contracts section. //strategy: 'implicit', + strategy: 'explicit', + contracts: { "MiniMeToken": { "deploy": false }, "MiniMeTokenFactory": { @@ -125,7 +82,6 @@ module.exports = { ] }, "Meritocracy": { - "fromIndex": 0, "args": [ "$SNT", 66] } } @@ -154,13 +110,12 @@ module.exports = { }, "afterDeploy": [ // Give Tokens to Meritocracy Owner - "SNT.methods.generateTokens('$accounts[0]', '100000000000000000000').send()", + "SNT.methods.generateTokens('$accounts[0]', '1000000000000000000000').send()", // Add All Contributors "Meritocracy.methods.addContributors([" + getContributors().toString() + "]).send()", // Allocate Owner Tokens - "SNT.methods.approve('$Meritocracy', 10000).send()", - "Meritocracy.methods.allocate(10000).send()" - + "SNT.methods.approve('$Meritocracy', '1000000000000000000000').send()", + "Meritocracy.methods.allocate('1000000000000000000000').send()", ] }, @@ -173,6 +128,28 @@ module.exports = { // merges with the settings in default // used with "embark run 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 diff --git a/contracts/Meritocracy.sol b/contracts/Meritocracy.sol index 7b63aa8..ccf7712 100644 --- a/contracts/Meritocracy.sol +++ b/contracts/Meritocracy.sol @@ -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 function allocate(uint256 _amount) external { // Locals - uint256 individualAmount; + // Contributor memory cAllocator = contributors[msg.sender]; // Requirements // 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 // cAllocator.inPot = true; - individualAmount = _amount / registry.length; for (uint256 i = 0; i < registry.length; i++) { contributors[registry[i]].allocation += individualAmount; } @@ -151,6 +157,22 @@ contract Meritocracy { 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 function awardContributors(address[] calldata _contributors, uint256 _amountEach, string calldata _praise) external { // Locals