diff --git a/package-lock.json b/package-lock.json index ee69ae18c8..1f3f00fd59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11644,9 +11644,9 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "typedarray-to-buffer": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.2.tgz", - "integrity": "sha1-EBezLZhP9VbroQD1AViauhrOLgQ=", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "requires": { "is-typedarray": "1.0.0" } @@ -12160,9 +12160,9 @@ } }, "web3": { - "version": "1.0.0-beta.33", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.0.0-beta.33.tgz", - "integrity": "sha1-xgIbV2mSdyY3HBhLhoRFMRsTkpU=", + "version": "1.0.0-beta.22", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.0.0-beta.22.tgz", + "integrity": "sha1-lu7zfn4BfUvu3u/5G6M0Por3qf8=", "requires": { "web3-bzz": "1.0.0-beta.33", "web3-core": "1.0.0-beta.33", @@ -12435,25 +12435,6 @@ "underscore": "1.8.3", "web3-core-helpers": "1.0.0-beta.33", "websocket": "git://github.com/frozeman/WebSocket-Node.git#7004c39c42ac98875ab61126e5b4a925430f592c" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "websocket": { - "version": "git://github.com/frozeman/WebSocket-Node.git#7004c39c42ac98875ab61126e5b4a925430f592c", - "requires": { - "debug": "2.6.9", - "nan": "2.9.2", - "typedarray-to-buffer": "3.1.2", - "yaeti": "0.0.6" - } - } } }, "web3-shh": { @@ -12883,6 +12864,25 @@ "source-map": "0.6.1" } }, + "websocket": { + "version": "git://github.com/frozeman/WebSocket-Node.git#7004c39c42ac98875ab61126e5b4a925430f592c", + "requires": { + "debug": "2.6.9", + "nan": "2.9.2", + "typedarray-to-buffer": "3.1.5", + "yaeti": "0.0.6" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, "websocket-driver": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", diff --git a/package.json b/package.json index 755fb51adf..aabd6b0a55 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "redux": "^3.7.2", "redux-subscriber": "^1.1.0", "redux-thunk": "^2.2.0", - "web3": "1.0.0-beta.33" + "web3": "1.0.0-beta.22" }, "scripts": { "start": "react-scripts start", diff --git a/src/App.js b/src/App.js index 9c021a5d5b..124f028a80 100644 --- a/src/App.js +++ b/src/App.js @@ -15,7 +15,8 @@ import About from './components/About'; import Links from './components/Links'; import SharePurchase from './components/SharePurchase'; import Transactions from './components/Transactions'; -// import SelectToken from './components/SelectToken' +// d3 +import Visualization from './components/Visualization'; // enter redux import { bindActionCreators } from 'redux' import { connect } from 'react-redux'; @@ -45,7 +46,6 @@ import { setInputBalance, import './App.css'; import cookie from 'react-cookies' import scrollToComponent from 'react-scroll-to-component'; -// import Candlesticks from './components/Candlesticks' var localweb3; // this isn't even in state @@ -455,6 +455,7 @@ class App extends Component { inputTokenValue={this.props.exchange.inputToken.value} exchangeFee={this.props.exchange.fee} /> + this.setState({data: data.data.data.Event})) .then(()=> this.visualizeData()) .catch(err => console.error(err)); diff --git a/src/components/Exchange.js b/src/components/Exchange.js index 877c7b5890..0830a7f95a 100644 --- a/src/components/Exchange.js +++ b/src/components/Exchange.js @@ -161,7 +161,7 @@ class Exchange extends Component {
-

{'<'}

+

{'<'}

) diff --git a/src/components/Visualization.js b/src/components/Visualization.js new file mode 100644 index 0000000000..a3db2c4bf4 --- /dev/null +++ b/src/components/Visualization.js @@ -0,0 +1,181 @@ +import React, { Component } from 'react'; +import ReactDOM from 'react-dom'; +import { connect } from 'react-redux'; +import { subscribe } from 'redux-subscriber' +import * as d3 from 'd3'; +import axios from 'axios'; + +class Visualization extends Component { + constructor(props) { + super(props); + this.state = { + data: null + } + } + // TODO: find a way to get this thing to listen for changes in the output token + componentDidMount() { + this.d3Graph = d3.select(ReactDOM.findDOMNode(this.refs.graph)); + + let inputToken = this.props.exchange.inputToken.value; + let outputToken = this.props.exchange.outputToken.value; + console.log(outputToken, 'output token'); + + let query = `{ + Event(input:"${outputToken}"){ + ethValueOfToken + createdAt + } + }`; + + console.log(query, 'query') + + axios.get('http://ec2-18-233-168-186.compute-1.amazonaws.com:3000/graphql', { params: {query: query } }) + .then(data => this.setState({data: data.data.data.Event })) + .then(() => this.createLineGraph()) + .catch(err => console.error(err)); + + this.outputTokenSubscriber(); + } + + outputTokenSubscriber() { + const outputTokenSubscriber = subscribe('exchange.outputToken', state => { + let outputToken = state.exchange.outputToken.value; + console.log('outputToken change deteced', outputToken) + + let query = `{ + Event(input:"${outputToken}"){ + ethValueOfToken + createdAt + } + }`; + + axios.get('http://ec2-18-233-168-186.compute-1.amazonaws.com:3000/graphql', { params: { query: query }}) + .then(data => this.setState({data: data.data.data.Event})) + .then(() => { + this.createNewLineGraph() + }) + .catch(err => console.error(err)); + }) + } + + createLineGraph() { + // TODO: as you change whether you want to see days or years, change the extent + // scales are wicked important + let width = 1039; + let height = 200; + let margin = {top: 20, bottom:20, left:20, right:20} + let svg = this.d3Graph + // first we want to see the min and max of our token prices + let ethValueOfTokenExtent = d3.extent(this.state.data, element => element.ethValueOfToken); + console.log('initial data visualized', this.state.data) + // create a y scale, for the eth value of the token + let yScale = d3.scaleLinear() + .domain(ethValueOfTokenExtent) + .range([margin.bottom, height - margin.top]); + + // now that we have the scale, we create the actual axis + let yAxis = d3.axisLeft() + .scale(yScale); + // time to put this y axis on the page + svg.append('g') + .attr('class', 'y axis') + .attr('transform', 'translate(50)') + .call(yAxis); + + // sanitize the data for the x-axis + this.state.data.map(e => e.createdAt = new Date(e.createdAt)); + // similarly, check the min and max of our times + let timeExtent = d3.extent(this.state.data, element => element.createdAt) + console.log('previous time extent', timeExtent) + // with this extent, create a scale for the x axis + // BIG NOTE: for timeScales, you need to create new Date objects from the date string + // also, domain needs to take in an array + let xScale = d3.scaleTime() + .domain(timeExtent) + .range([margin.left, width - margin.right]); + // we have a scale, lets create the axis + let xAxis = d3.axisBottom() + .scale(xScale); + // append the axis to the DOM, make sure it's positioned correctly + svg.append('g') + .attr('class', 'x axis') + .attr('transform', 'translate(30, 180)') + .call(xAxis); + + let line = d3.line() + .x(element => xScale(element.createdAt)) + .y(element => yScale(element.ethValueOfToken)) + + svg.append('path') + .datum(this.state.data) + .attr('d', line) + .attr('class', 'line') + .attr("fill", "none") + .attr("stroke", "steelblue") + .attr("stroke-linejoin", "round") + .attr("stroke-linecap", "round") + .attr("stroke-width", 1.5) + .attr('transform', 'translate(30)') + } + + createNewLineGraph(){ + let width = 1039; + let height = 200; + let margin = {top: 20, bottom:20, left:20, right:20} + this.state.data.map(e => e.createdAt = new Date(e.createdAt)); + console.log('data is being set correctly', this.state.data) + // we set the range of the data again + let yExtent = d3.extent(this.state.data, e => e.ethValueOfToken); + let xExtent = d3.extent(this.state.data, e => e.createdAt); + console.log('new yExtent', yExtent) + console.log('new xExtent', xExtent) + // we also redefine the scales for the new data + let yScale = d3.scaleLinear() + .domain(yExtent) + .range([margin.bottom, height - margin.top]); + let xScale = d3.scaleTime() + .domain(xExtent) + .range([margin.left, width - margin.right]); + // redefine the axes + let xAxis = d3.axisBottom() + .scale(xScale) + let yAxis = d3.axisLeft() + .scale(yScale) + + let svg = this.d3Graph.transition() + let line = d3.line() + .x(element => xScale(element.createdAt)) + .y(element => yScale(element.ethValueOfToken)) + + svg.select('.line') + .duration(750) + .attr('d', line(this.state.data)) + svg.select('.x.axis') + .duration(750) + .call(xAxis) + svg.select('.y.axis') + .duration(750) + .call(yAxis) + } + + render () { + const width = 1039; + const height = 200; + return ( + + + + ) + } +} + +const mapStateToProps = state => ({ + exchange: state.exchange +}) + +export default connect (mapStateToProps)(Visualization); + +// input and output tokens will have to be considered for this to work correctly +// we'll start by pulling the output token +// potential problem that these data points are not being written at the exact same time +// we will deal with that when we get there \ No newline at end of file diff --git a/src/store/initial-state.js b/src/store/initial-state.js index 7ada0db761..e55fc9c3af 100644 --- a/src/store/initial-state.js +++ b/src/store/initial-state.js @@ -37,7 +37,7 @@ export default { inputBalance: 0, outputBalance: 0, inputToken: { value: 'ETH', label: 'ETH', clearableValue: false }, - outputToken: { value: 'MKR', label: 'MKR', clearableValue: false }, + outputToken: { value: 'BAT', label: 'BAT', clearableValue: false }, investToken: { value: 'BAT', label: 'BAT', clearableValue: false }, invariant1: 0, invariant2: 0,