commit
994933f9a2
50
package-lock.json
generated
50
package-lock.json
generated
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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}
|
||||
/>
|
||||
<Visualization />
|
||||
<Purchase
|
||||
symbolToExchangeContract={this.symbolToExchangeContract}
|
||||
symbolToTokenAddress={this.symbolToTokenAddress}
|
||||
|
@ -10,7 +10,6 @@ class Candlesticks extends Component {
|
||||
}
|
||||
this.visualizeData.bind(this)
|
||||
}
|
||||
|
||||
// note, this url is being used for development
|
||||
// the actual url will be wherever the API is hosted
|
||||
componentDidMount() {
|
||||
@ -21,7 +20,7 @@ class Candlesticks extends Component {
|
||||
}
|
||||
}`;
|
||||
|
||||
axios.get('http://localhost:3000/graphql', { params: { 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.visualizeData())
|
||||
.catch(err => console.error(err));
|
||||
|
@ -161,7 +161,7 @@ class Exchange extends Component {
|
||||
<div className="value border pa2">
|
||||
<input type="number" readOnly={true} value={(this.props.exchange.outputValue/10**18).toFixed(6)} placeholder="0"/>
|
||||
<SelectToken token={this.props.exchange.outputToken} onSelectToken={this.onSelectToken} type="output"/>
|
||||
<p className="dropdown">{'<'}</p>
|
||||
<p className="dropdown">{'<'}</p>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
181
src/components/Visualization.js
Normal file
181
src/components/Visualization.js
Normal file
@ -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 (
|
||||
<svg width={width} height={height}>
|
||||
<g ref="graph"/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user