diff --git a/package-lock.json b/package-lock.json index 0813c91..819fa02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8009,9 +8009,9 @@ } }, "react": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.2.0.tgz", - "integrity": "sha512-ZmIomM7EE1DvPEnSFAHZn9Vs9zJl5A9H7el0EGTE6ZbW9FKe/14IYAlPbC8iH25YarEQxZL+E8VW7Mi7kfQrDQ==", + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/react/-/react-16.3.2.tgz", + "integrity": "sha512-o5GPdkhciQ3cEph6qgvYB7LTOHw/GB0qRI6ZFNugj49qJCFfgHwVNjZ5u+b7nif4vOeMIOuYj3CeYe2IBD74lg==", "requires": { "fbjs": "0.8.16", "loose-envify": "1.3.1", @@ -8045,9 +8045,9 @@ } }, "react-dom": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.2.0.tgz", - "integrity": "sha512-zpGAdwHVn9K0091d+hr+R0qrjoJ84cIBFL2uU60KvWBPfZ7LPSrfqviTxGHWN0sjPZb2hxWzMexwrvJdKePvjg==", + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.3.2.tgz", + "integrity": "sha512-MMPko3zYncNrz/7gG17wJWUREZDvskZHXOwbttzl0F0L3wDmToyuETuo/r8Y5yvDejwYcRyWI1lvVBjLJWFwKA==", "requires": { "fbjs": "0.8.16", "loose-envify": "1.3.1", diff --git a/package.json b/package.json index fd36b56..7a6a14c 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "version": "0.1.0", "private": true, "dependencies": { - "react": "^16.2.0", - "react-dom": "^16.2.0", + "react": "^16.3.2", + "react-dom": "^16.3.2", "react-scripts": "1.0.17" }, "scripts": { @@ -13,4 +13,4 @@ "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" } -} \ No newline at end of file +} diff --git a/src/App.js b/src/App.js index 0e368dc..3f92a3f 100644 --- a/src/App.js +++ b/src/App.js @@ -64,40 +64,83 @@ class App extends Component this.waitForConfirmations = this.waitForConfirmations.bind(this); this.handleInputChange = this.handleInputChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); - this.getGovernanceInfo = this.getGovernanceInfo.bind(this); + this.getSuperblockInfo = this.getSuperblockInfo.bind(this); this.getBestBlock = this.getBestBlock.bind(this); this.updateNetwork = this.updateNetwork.bind(this); this.initializeEpochs = this.initializeEpochs.bind(this); } - getGovernanceInfo() + getSuperblockInfo() { - return fetch(this.explorerAPI + 'getgovernanceinfo') - .then((resp) => { - if (resp.ok) { + var getGovernanceInfo = function() + { + return fetch(this.explorerAPI + 'getgovernanceinfo') + .then((resp) => { + if (resp.ok) { + return resp.json() + .then((responseData) => { + this.setState({governanceInfo: responseData}, + function() + { + getSuperblockBudget(); + } + ); + return responseData; + }); + } return resp.json() - .then((responseData) => { - this.setState({governanceInfo: responseData}, - function() - { - this.apiSyncState++; - if (this.apiSyncState == 2) this.initializeEpochs(); - } - ); - return responseData; + .then((error) => { + return Promise.reject(error); }); - } - return resp.json() - .then((error) => { - return Promise.reject(error); - }); - }) - .catch(err => {this.setError("Unable to fetch current blockchain information. Please try again later. " + err.toString())}); + }) + .catch(err => {this.setError("Unable to fetch current blockchain information. Please try again later. " + err.toString())}); + } + + var getSuperblockBudget = function(depth = 0) + { + const maxDepth = 52; + const superblockNumber = this.state.governanceInfo.nextsuperblock + (depth * this.state.governanceInfo.superblockcycle); + return fetch(this.explorerAPI + 'getsuperblockbudget/' + superblockNumber) + .then((resp) => { + if (resp.ok) { + return resp.json() + .then((responseData) => { + var superblockBudgets = this.state.superblockBudgets || []; + superblockBudgets[depth] = responseData; + this.setState({superblockBudgets: superblockBudgets}, + function() + { + if (depth === (maxDepth - 1)) + { + this.apiSyncState++; + if (this.apiSyncState === 2) this.initializeEpochs(); + } + else + { + getSuperblockBudget(depth + 1); + } + } + ); + return responseData; + }); + } + return resp.json() + .then((error) => { + return Promise.reject(error); + }); + }) + .catch(err => {this.setError("Unable to fetch current blockchain information. Please try again later. " + err.toString())}); + } + + getGovernanceInfo = getGovernanceInfo.bind(this); + getSuperblockBudget = getSuperblockBudget.bind(this); + + getGovernanceInfo(); } getBestBlock() { - function getBlock(hash) + var getBlock = function(hash) { return fetch(this.explorerAPI + 'getblock?hash=' + hash) .then((resp) => { @@ -108,7 +151,7 @@ class App extends Component function() { this.apiSyncState++; - if (this.apiSyncState == 2) this.initializeEpochs(); + if (this.apiSyncState === 2) this.initializeEpochs(); } ); return responseData; @@ -122,7 +165,7 @@ class App extends Component .catch(err => {this.setError("Unable to fetch current blockchain information. Please try again later. " + err.toString())}); } - function getHash(height) + var getHash = function(height) { return fetch(this.explorerAPI + 'getblockhash?index=' + Number(height).toString()) .then((resp) => { @@ -141,7 +184,7 @@ class App extends Component .catch(err => {this.setError("Unable to fetch current blockchain information. Please try again later. " + err.toString())}); } - function getHeight() + var getHeight = function() { return fetch(this.explorerAPI + 'getblockcount') .then((resp) => { @@ -167,9 +210,9 @@ class App extends Component updateNetwork(networkName) { - function fetchBlockchainInfo() + var fetchBlockchainInfo = function() { - this.getGovernanceInfo(); + this.getSuperblockInfo(); this.getBestBlock(); } @@ -178,8 +221,8 @@ class App extends Component this.setState({network: networkName}, function() { if (this.state.network === 'main') this.explorerAPI = 'https://explore.energi.network/api/'; - else if (this.state.network == 'test') this.explorerAPI = 'http://explore.test.energi.network/api/'; - else if (this.state.network === 'test60x') this.explorerAPI = 'http://explore.test60x.energi.network/api/'; + else if (this.state.network === 'test') this.explorerAPI = 'https://explore.test.energi.network/api/'; + //else if (this.state.network === 'test60x') this.explorerAPI = 'https://explore.test60x.energi.network/api/'; else this.setError("Invalid network"); fetchBlockchainInfo(); @@ -193,9 +236,9 @@ class App extends Component return new Promise(resolve => setTimeout(resolve, ms)); } - async function waitForSync() + var waitForSync = async function() { - while (this.apiSyncState != 2) await sleep(100); + while (this.apiSyncState !== 2) await sleep(100); } waitForSync = waitForSync.bind(this); @@ -207,14 +250,14 @@ class App extends Component let new_gobj = this.state.gobj; new_gobj[0][1].start_epoch = initial_epoch; new_gobj[0][1].end_epoch = initial_epoch + (gov.superblockcycle * 60); - this.setState({gobj: new_gobj}, this.validateNewState()); + this.setState({gobj: new_gobj}, this.validateNewState); } componentDidMount() { document.title = "Energi Proposal Creator"; - this.updateNetwork('test60x'); + this.updateNetwork('main'); } setError(errStr) @@ -315,11 +358,15 @@ class App extends Component function validateProposalAmount(setError, state) { - const maximumBudgetAmount = state.governanceInfo.lastsuperblock === 0 ? 4000000 : 184000; + const nextSuperblockTime = ((state.governanceInfo.nextsuperblock - state.bestBlock.height) * 60) + state.bestBlock.time; + const superblockIndex = (state.gobj[0][1].start_epoch - nextSuperblockTime) / 60 / state.governanceInfo.superblockcycle; + let needed_budgets = state.superblockBudgets.slice(superblockIndex, superblockIndex + state.payment_cycles); + const maximumBudgetAmount = Math.min(...needed_budgets); + const payment_amount = state.gobj[0][1].payment_amount; if (payment_amount > maximumBudgetAmount) { - setError("Payment amount exceeds maximum budget of " + maximumBudgetAmount.toString() + " EGI"); + setError("Payment amount exceeds maximum budget of " + maximumBudgetAmount.toString() + " NRG"); return false; } if (payment_amount <= 0) @@ -350,11 +397,12 @@ class App extends Component result = result && validateProposalAddress(this.setError, this.state); result = result && validateProposalAmount(this.setError, this.state); result = result && validateProposalType(this.setError, this.state); + return result; } waitForConfirmations() { - function fetchConfirmations() + var fetchConfirmations = function() { return fetch(this.explorerAPI + 'getrawtransaction?txid=' + this.state.collateral_txhash + '&decrypt=1') .then((resp) => { @@ -379,7 +427,7 @@ class App extends Component return new Promise(resolve => setTimeout(resolve, ms)); } - async function checkConfirmations() + var checkConfirmations = async function() { while (this.state.confirmations < 6) { @@ -404,6 +452,10 @@ class App extends Component { this.setState({collateral_txhash: value}, this.waitForConfirmations); } + else if (name === 'networkSelector') + { + this.updateNetwork(target.value); + } else { // make sure numbers are numbers @@ -428,7 +480,7 @@ class App extends Component new_state.gobj[0][1].end_epoch = new_state.gobj[0][1].start_epoch + (new_state.payment_cycles * this.state.governanceInfo.superblockcycle * 60); } - this.setState(new_state, this.validateNewState()); + this.setState(new_state, this.validateNewState); } } @@ -436,7 +488,7 @@ class App extends Component { const dateTime = new Date().getTime(); const timestamp = Math.floor(dateTime / 1000); - this.setState({submitted: true, proposalTime: timestamp}, this.validateNewState()); + this.setState({submitted: true, proposalTime: timestamp}, this.validateNewState); } render() diff --git a/src/DisplayTotal.js b/src/DisplayTotal.js index 7c503b8..282e79a 100644 --- a/src/DisplayTotal.js +++ b/src/DisplayTotal.js @@ -49,7 +49,7 @@ class DisplayTotal extends Component const start_epoch = this.props.gobj[0][1].start_epoch; const end_epoch = this.props.gobj[0][1].end_epoch; - if (this.props.payment_cycles == 1) + if (this.props.payment_cycles === 1) { return "at " + format_date(start_epoch); } @@ -59,13 +59,11 @@ class DisplayTotal extends Component render() { - let props = this.props; - if (this.props.gobj[0][1].payment_amount <= 0) return null; return (
- Total: {this.get_total()} EGI {this.get_date_str()} + Total: {this.get_total()} NRG {this.get_date_str()}
); } diff --git a/src/PrepareForm.js b/src/PrepareForm.js index 7fccd4a..ed4f8c6 100644 --- a/src/PrepareForm.js +++ b/src/PrepareForm.js @@ -24,6 +24,7 @@ import React, { Component } from 'react'; import TextInputField from './TextInputField.js'; import SelectFirstPayment from './SelectFirstPayment.js'; import SelectPaymentCycles from './SelectPaymentCycles.js'; +import SelectNetwork from './SelectNetwork.js'; import DisplayTotal from './DisplayTotal.js'; import ValidationError from './ValidationError.js'; import PreparedProposal from './PreparedProposal.js'; @@ -59,6 +60,7 @@ class PrepareForm extends Component + diff --git a/src/PreparedProposal.js b/src/PreparedProposal.js index b8c058f..b80977a 100644 --- a/src/PreparedProposal.js +++ b/src/PreparedProposal.js @@ -43,8 +43,6 @@ class PreparedProposal extends Component render() { - let props = this.props; - if (!this.props.submitted || (this.props.validationError !== '')) return null; return ( diff --git a/src/SelectNetwork.js b/src/SelectNetwork.js new file mode 100644 index 0000000..ba3a38f --- /dev/null +++ b/src/SelectNetwork.js @@ -0,0 +1,33 @@ +/* Energi Proposal Creator +*/ + +import React, { Component } from 'react'; + +class SelectNetwork extends Component +{ + getNetworks() + { + let htmlOptionTags = []; + htmlOptionTags.push(); + //htmlOptionTags.push(); + htmlOptionTags.push(); + return htmlOptionTags; + } + + render() + { + let props = this.props; + return ( +
+ +
+ ); + } +} + +export default SelectNetwork; diff --git a/src/SubmitProposalForm.js b/src/SubmitProposalForm.js index 68548f2..5501dfc 100644 --- a/src/SubmitProposalForm.js +++ b/src/SubmitProposalForm.js @@ -42,8 +42,6 @@ class SubmitProposalForm extends Component render() { - let props = this.props; - if (this.props.confirmations < 6) return null; return (