Completed callgasrelayed component
This commit is contained in:
parent
f61e98f75e
commit
d3d9710a02
|
@ -22,16 +22,6 @@ class AccountBalance extends React.Component {
|
|||
updateBalances(ev){
|
||||
if(ev) ev.preventDefault();
|
||||
|
||||
web3.eth.getBalance(this.props.address)
|
||||
.then(eth => {
|
||||
this.setState({eth});
|
||||
});
|
||||
|
||||
this.props.RND.methods.balanceOf(this.props.address)
|
||||
.call()
|
||||
.then(rnd => {
|
||||
this.setState({rnd});
|
||||
});
|
||||
}
|
||||
|
||||
sendEther(ev){
|
||||
|
@ -56,8 +46,8 @@ class AccountBalance extends React.Component {
|
|||
}
|
||||
|
||||
render(){
|
||||
const rnd = web3.utils.fromWei(this.state.rnd, "ether");
|
||||
const eth = web3.utils.fromWei(this.state.eth, "ether");
|
||||
const rnd = 1;
|
||||
const eth =2;
|
||||
|
||||
return <div>
|
||||
<h3>{this.props.name}</h3>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component, Fragment} from 'react';
|
||||
import CallGasRelayed from './callgasrelayed';
|
||||
import Divider from '@material-ui/core/Divider';
|
||||
import EmbarkJS from 'Embark/EmbarkJS';
|
||||
import IdentityFactory from 'Embark/contracts/IdentityFactory';
|
||||
|
@ -18,7 +19,8 @@ class Body extends Component {
|
|||
super(props);
|
||||
this.state = {
|
||||
tab: 0,
|
||||
identityAddress: null
|
||||
identityAddress: null,
|
||||
nonce: '0'
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -39,13 +41,18 @@ class Body extends Component {
|
|||
this.setState({tab});
|
||||
};
|
||||
|
||||
updateNonce = (newNonce) => {
|
||||
this.setState({nonce: newNonce});
|
||||
}
|
||||
|
||||
newIdentity = (cb) => {
|
||||
let toSend = IdentityFactory.methods['createIdentity()']();
|
||||
toSend.estimateGas()
|
||||
.then(estimatedGas => {
|
||||
return toSend.send({gas: estimatedGas + 100000});
|
||||
return toSend.send({gas: estimatedGas + 1000000});
|
||||
})
|
||||
.then((receipt) => {
|
||||
console.log(receipt);
|
||||
const instance = receipt.events.IdentityCreated.returnValues.instance;
|
||||
this.setState({identityAddress: instance});
|
||||
cb();
|
||||
|
@ -53,7 +60,7 @@ class Body extends Component {
|
|||
}
|
||||
|
||||
render(){
|
||||
const {tab, identityAddress} = this.state;
|
||||
const {tab, identityAddress, nonce} = this.state;
|
||||
|
||||
return <Fragment>
|
||||
<Tabs value={tab} onChange={this.handleChange}>
|
||||
|
@ -61,22 +68,24 @@ class Body extends Component {
|
|||
<Tab label="Approve and Call" />
|
||||
<Tab label="Deploy" />
|
||||
</Tabs>
|
||||
{tab === 0 && <TabContainer>One</TabContainer>}
|
||||
{tab === 1 && <TabContainer>Item Two</TabContainer>}
|
||||
{tab === 2 && <TabContainer>Item Three</TabContainer>}
|
||||
{tab === 0 && <Container><CallGasRelayed nonce={nonce} identityAddress={identityAddress} /></Container>}
|
||||
{tab === 1 && <Container>Item Two</Container>}
|
||||
{tab === 2 && <Container>Item Three</Container>}
|
||||
<Divider />
|
||||
<Status identityCreationFunction={this.newIdentity} identityAddress={identityAddress} />
|
||||
<Container>
|
||||
<Status identityCreationFunction={this.newIdentity} nonceUpdateFunction={this.updateNonce} nonce={nonce} identityAddress={identityAddress} />
|
||||
</Container>
|
||||
</Fragment>;
|
||||
}
|
||||
}
|
||||
|
||||
function TabContainer(props) {
|
||||
function Container(props) {
|
||||
return <Typography component="div" style={{padding: 8 * 3}}>
|
||||
{props.children}
|
||||
</Typography>;
|
||||
}
|
||||
|
||||
TabContainer.propTypes = {
|
||||
Container.propTypes = {
|
||||
children: PropTypes.node.isRequired
|
||||
};
|
||||
|
||||
|
|
|
@ -1,269 +1,392 @@
|
|||
import {Alert, Button, Col, ControlLabel, Form, FormControl, Grid, HelpBlock, InputGroup, Row} from 'react-bootstrap';
|
||||
import AccountBalance from './accountBalance';
|
||||
import React from 'react';
|
||||
import Web3 from 'web3';
|
||||
import React, {Component} from 'react';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActions from '@material-ui/core/CardActions';
|
||||
import CardContent from '@material-ui/core/CardContent';
|
||||
import CardHeader from '@material-ui/core/CardHeader';
|
||||
import EmbarkJS from 'Embark/EmbarkJS';
|
||||
import ErrorIcon from '@material-ui/icons/Error';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import IdentityGasRelay from 'Embark/contracts/IdentityGasRelay';
|
||||
import PropTypes from 'prop-types';
|
||||
import STT from 'Embark/contracts/STT';
|
||||
import SnackbarContent from '@material-ui/core/SnackbarContent';
|
||||
import TestContract from 'Embark/contracts/TestContract';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import classNames from 'classnames';
|
||||
import config from '../config';
|
||||
import web3 from 'Embark/web3';
|
||||
import {withStyles} from '@material-ui/core/styles';
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
backgroundColor: theme.palette.background.paper
|
||||
},
|
||||
card: {
|
||||
marginBottom: theme.spacing.unit * 3
|
||||
}
|
||||
});
|
||||
|
||||
class CallGasRelayed extends React.Component {
|
||||
window.TestContract = TestContract;
|
||||
class CallGasRelayed extends Component {
|
||||
|
||||
constructor(props) {
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
account: '',
|
||||
address: this.props.IdentityGasRelay.options.address,
|
||||
topic: '0x4964656e',
|
||||
to: '0x0000000000000000000000000000000000000000',
|
||||
value: 0,
|
||||
data: '0x00',
|
||||
nonce: 0,
|
||||
gasPrice: 0,
|
||||
gasLimit: 0,
|
||||
gasToken: "0x0000000000000000000000000000000000000000",
|
||||
signature: '',
|
||||
symKey: '0xd0d905c1c62b810b787141430417caf2b3f54cffadb395b7bb39fdeb8f17266b',
|
||||
kid: null,
|
||||
skid: null,
|
||||
msgSent: '',
|
||||
payload: '',
|
||||
messages: [],
|
||||
message: '',
|
||||
web3W: null,
|
||||
errorMessage: ''
|
||||
transactionError: '',
|
||||
messagingError: '',
|
||||
submitting: false
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
__embarkContext.execWhenReady(async () => {
|
||||
EmbarkJS.onReady(() => {
|
||||
web3.shh.addSymKey(config.relaySymKey)
|
||||
.then((skid) => {
|
||||
this.setState({skid});
|
||||
|
||||
let web3W = new Web3('ws://localhost:8546');
|
||||
const subsOptions = {
|
||||
topic: [this.state.topic],
|
||||
symKeyID: skid
|
||||
};
|
||||
|
||||
let accounts = await this.props.web3.eth.getAccounts();
|
||||
this.setState({
|
||||
account: accounts[0]
|
||||
});
|
||||
|
||||
let _skid = await web3W.shh.addSymKey(this.state.symKey);
|
||||
let _kid = await web3W.shh.newKeyPair();
|
||||
|
||||
this.setState({
|
||||
kid: _kid,
|
||||
skid: _skid,
|
||||
whisper: web3W
|
||||
});
|
||||
|
||||
web3W.shh.subscribe('messages', {
|
||||
"privateKeyID": _kid,
|
||||
"ttl": 20,
|
||||
"minPow": 0.8,
|
||||
"powTime": 1000
|
||||
}, (error, message, subscription) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
this.setState({errorMessage: error.message});
|
||||
EmbarkJS.Messages.listenTo(subsOptions, (error, message) => {
|
||||
if(error){
|
||||
console.error(error);
|
||||
} else {
|
||||
this.state.messages.push(this.props.web3.utils.hexToAscii(message.payload));
|
||||
this.setState({messages: this.state.messages});
|
||||
console.groupCollapsed("Message Sent");
|
||||
console.log(message);
|
||||
console.groupEnd();
|
||||
}
|
||||
this.setState({submitting: false});
|
||||
});
|
||||
|
||||
EmbarkJS.Messages.listenTo({usePrivateKey: true}, (error, message) => {
|
||||
if(error){
|
||||
console.error(error);
|
||||
} else {
|
||||
this.setState({message: JSON.stringify(message.data, null, " ")});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
handleChange(e, name){
|
||||
const newState = {};
|
||||
newState[name] = e.target.value;
|
||||
this.setState(newState);
|
||||
}
|
||||
handleChange = name => event => {
|
||||
this.setState({
|
||||
[name]: event.target.value
|
||||
});
|
||||
};
|
||||
|
||||
sendMessage(e){
|
||||
e.preventDefault();
|
||||
sign = (event) => {
|
||||
if(event) event.preventDefault();
|
||||
|
||||
this.setState({
|
||||
messages: [],
|
||||
errorMessage: ''
|
||||
msgSent: false,
|
||||
payload: '',
|
||||
message: '',
|
||||
transactionError: ''
|
||||
});
|
||||
|
||||
IdentityGasRelay.options.address = this.props.identityAddress;
|
||||
|
||||
try {
|
||||
IdentityGasRelay.methods.callGasRelayHash(
|
||||
this.state.to,
|
||||
this.state.value,
|
||||
web3.utils.soliditySha3({t: 'bytes', v: this.state.data}),
|
||||
this.props.nonce,
|
||||
this.state.gasPrice,
|
||||
this.state.gasLimit,
|
||||
this.state.gasToken
|
||||
)
|
||||
.call()
|
||||
.then(message => {
|
||||
return web3.eth.sign(message, web3.eth.defaultAccount);
|
||||
})
|
||||
.then(signature => {
|
||||
this.setState({signature});
|
||||
});
|
||||
} catch(error){
|
||||
this.setState({transactionError: error.message});
|
||||
}
|
||||
}
|
||||
|
||||
sendMessage = event => {
|
||||
event.preventDefault();
|
||||
|
||||
this.setState({
|
||||
message: '',
|
||||
messagingError: '',
|
||||
submitting: true
|
||||
});
|
||||
|
||||
try {
|
||||
let jsonAbi = this.props.IdentityGasRelay._jsonInterface.filter(x => x.name == "callGasRelayed")[0];
|
||||
let funCall = this.props.web3.eth.abi.encodeFunctionCall(jsonAbi, [
|
||||
let jsonAbi = IdentityGasRelay._jsonInterface.filter(x => x.name == "callGasRelayed")[0];
|
||||
let funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
|
||||
this.state.to,
|
||||
this.state.value,
|
||||
this.state.data,
|
||||
this.state.nonce,
|
||||
this.props.nonce,
|
||||
this.state.gasPrice,
|
||||
this.state.gasLimit,
|
||||
this.state.gasToken,
|
||||
this.state.signature
|
||||
]);
|
||||
let msgObj = {
|
||||
symKeyID: this.state.skid,
|
||||
sig: this.state.kid,
|
||||
const sendOptions = {
|
||||
ttl: 1000,
|
||||
powTarget: 1,
|
||||
powTime: 20,
|
||||
topic: this.state.topic,
|
||||
payload: this.props.web3.utils.toHex({
|
||||
'address': this.state.address,
|
||||
symKeyID: this.state.skid,
|
||||
data: {
|
||||
'address': this.props.identityAddress,
|
||||
'encodedFunctionCall': funCall
|
||||
})
|
||||
}
|
||||
};
|
||||
EmbarkJS.Messages.sendMessage(sendOptions);
|
||||
|
||||
console.log(msgObj);
|
||||
|
||||
this.props.web3.shh.post(msgObj)
|
||||
.then((err, result) => {
|
||||
console.log(result);
|
||||
console.log(err);
|
||||
this.setState({msgSent: result, payload: msgObj.payload});
|
||||
});
|
||||
} catch(error){
|
||||
console.error(error);
|
||||
this.setState({errorMessage: error.message});
|
||||
this.setState({messagingError: error.message, submitting: false});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async sign(ev){
|
||||
ev.preventDefault();
|
||||
|
||||
this.setState({
|
||||
msgSent: false,
|
||||
payload: '',
|
||||
messages: [],
|
||||
errorMessage: ''
|
||||
});
|
||||
|
||||
try {
|
||||
let message = await this.props.IdentityGasRelay.methods.callGasRelayHash(
|
||||
this.state.to,
|
||||
this.state.value,
|
||||
this.props.web3.utils.soliditySha3({t: 'bytes', v: this.state.data}),
|
||||
this.state.nonce,
|
||||
this.state.gasPrice,
|
||||
this.state.gasLimit,
|
||||
this.state.gasToken
|
||||
).call();
|
||||
|
||||
let accounts = await this.props.web3.eth.getAccounts();
|
||||
let _signature = await this.props.web3.eth.sign(message, accounts[0]);
|
||||
|
||||
this.setState({signature: _signature});
|
||||
} catch(error){
|
||||
console.error(error);
|
||||
this.setState({errorMessage: error.message});
|
||||
testContractDataSend = () => {
|
||||
let jsonAbi = TestContract._jsonInterface.filter(x => x.name == "test")[0];
|
||||
let funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, []);
|
||||
this.setState({data: funCall, to: TestContract.options.address});
|
||||
}
|
||||
|
||||
testContractDataCall = () => {
|
||||
TestContract.methods.val().call().then(value => this.setState({message: "TestContract.val(): " + value}));
|
||||
}
|
||||
|
||||
render(){
|
||||
return (<Grid>
|
||||
{
|
||||
this.state.errorMessage != '' && <React.Fragment><Alert bsStyle="danger">{this.state.errorMessage}</Alert></React.Fragment>
|
||||
}
|
||||
<Form>
|
||||
<Row>
|
||||
<Col md={3}>
|
||||
<AccountBalance name="Identity" address={this.state.address} web3={this.props.web3} RND={this.props.RND} />
|
||||
</Col>
|
||||
<Col md={3}>
|
||||
<AccountBalance name="To" address={this.state.to} web3={this.props.web3} RND={this.props.RND} />
|
||||
</Col>
|
||||
<Col md={3}>
|
||||
<AccountBalance name="Gas Relayer Node" address={this.state.account} web3={this.props.web3} RND={this.props.RND} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col md={9}>
|
||||
<ControlLabel>Identity Address</ControlLabel>
|
||||
<InputGroup>
|
||||
<InputGroup.Addon>0x</InputGroup.Addon>
|
||||
<FormControl type="text" placeholder="Address" defaultValue={this.state.address} onChange={(ev) => this.handleChange(ev, 'address')} />
|
||||
</InputGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col md={4}>
|
||||
<ControlLabel>To</ControlLabel>
|
||||
<InputGroup>
|
||||
<InputGroup.Addon>0x</InputGroup.Addon>
|
||||
<FormControl type="text" defaultValue={this.state.to} onChange={(ev) => this.handleChange(ev, 'to')} />
|
||||
</InputGroup>
|
||||
</Col>
|
||||
<Col md={1}>
|
||||
<ControlLabel>Value</ControlLabel>
|
||||
<FormControl type="string" defaultValue={this.state.value} onChange={(ev) => this.handleChange(ev, 'value')} />
|
||||
</Col>
|
||||
<Col md={4}>
|
||||
<ControlLabel>Data</ControlLabel>
|
||||
<InputGroup>
|
||||
<InputGroup.Addon>0x</InputGroup.Addon>
|
||||
<FormControl type="string" defaultValue={this.state.data} onChange={(ev) => this.handleChange(ev, 'data')} />
|
||||
</InputGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col md={1}>
|
||||
<ControlLabel>Nonce</ControlLabel>
|
||||
<FormControl type="string" defaultValue={this.state.nonce} onChange={(ev) => this.handleChange(ev, 'nonce')} />
|
||||
</Col>
|
||||
<Col md={1}>
|
||||
<ControlLabel>Gas Price in Tokens</ControlLabel>
|
||||
<FormControl type="string" defaultValue={this.state.gasPrice} onChange={(ev) => this.handleChange(ev, 'gasPrice')} />
|
||||
</Col>
|
||||
<Col md={1}>
|
||||
<ControlLabel>Gas Limit in Ether</ControlLabel>
|
||||
<FormControl type="string" defaultValue={this.state.gasLimit} onChange={(ev) => this.handleChange(ev, 'gasLimit')} />
|
||||
</Col>
|
||||
<Col md={6}>
|
||||
<ControlLabel>Gas Token</ControlLabel>
|
||||
<InputGroup>
|
||||
<InputGroup.Addon>0x</InputGroup.Addon>
|
||||
<FormControl type="text" defaultValue={this.state.gasToken} onChange={(ev) => this.handleChange(ev, 'gasToken')} />
|
||||
</InputGroup>
|
||||
<HelpBlock>RND: {this.props.RND.options.address}</HelpBlock>
|
||||
<HelpBlock>ETH: 0x0000000000000000000000000000000000000000</HelpBlock>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col md={4}>
|
||||
<Button bsStyle="primary" onClick={(ev) => this.sign(ev)}>1. Sign Message</Button>
|
||||
</Col>
|
||||
<Col md={5}>
|
||||
<b>Signature: </b>{this.state.signature}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col md={7}>
|
||||
<ControlLabel>Symmetric Key</ControlLabel>
|
||||
<InputGroup>
|
||||
<InputGroup.Addon>0x</InputGroup.Addon>
|
||||
<FormControl type="text" placeholder="Sym Key" defaultValue={this.state.symKey} />
|
||||
</InputGroup>
|
||||
</Col>
|
||||
<Col md={2}>
|
||||
<ControlLabel>Topic</ControlLabel>
|
||||
<InputGroup>
|
||||
<InputGroup.Addon>0x</InputGroup.Addon>
|
||||
<FormControl type="text" readOnly={true} defaultValue={this.state.topic} onChange={(ev) => this.handleChange(ev, 'topic')} />
|
||||
</InputGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col md={4}>
|
||||
<Button bsStyle="primary" disabled={this.state.signature == ""} onClick={(ev) => this.sendMessage(ev)}>2. Send via whisper</Button>
|
||||
</Col>
|
||||
<Col md={5}>
|
||||
{this.state.msgSent}
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<h3>Whisper Messages</h3>
|
||||
{
|
||||
this.state.messages.map((msg, i) => <p key={i}>{msg}</p>)
|
||||
}
|
||||
</Row>
|
||||
</Form>
|
||||
const {classes} = this.props;
|
||||
return <div>
|
||||
{ this.state.transactionError && <MySnackbarContentWrapper variant="error" message={this.state.transactionError} /> }
|
||||
<Card className={classes.card}>
|
||||
<CardHeader title="1. Transaction Data" />
|
||||
<CardContent>
|
||||
<form noValidate autoComplete="off">
|
||||
<Grid container spacing={24}>
|
||||
<Grid item xs={5}>
|
||||
<TextField
|
||||
id="to"
|
||||
label="To"
|
||||
value={this.state.to}
|
||||
onChange={this.handleChange('to')}
|
||||
margin="normal"
|
||||
fullWidth
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
}
|
||||
<Grid item xs={2}>
|
||||
<TextField
|
||||
id="value"
|
||||
label="Value"
|
||||
value={this.state.value}
|
||||
onChange={this.handleChange('value')}
|
||||
margin="normal"
|
||||
fullWidth
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={5}>
|
||||
<TextField
|
||||
id="data"
|
||||
label="Data"
|
||||
value={this.state.data}
|
||||
onChange={this.handleChange('data')}
|
||||
margin="normal"
|
||||
fullWidth
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={2}>
|
||||
<TextField
|
||||
id="nonce"
|
||||
label="Nonce"
|
||||
value={this.props.nonce}
|
||||
margin="normal"
|
||||
fullWidth
|
||||
InputProps={{
|
||||
readOnly: true
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<TextField
|
||||
id="gasToken"
|
||||
label="Gas Token"
|
||||
value={this.state.gasToken}
|
||||
onChange={this.handleChange('gasToken')}
|
||||
margin="normal"
|
||||
fullWidth
|
||||
select
|
||||
SelectProps={{
|
||||
native: true
|
||||
}}
|
||||
>
|
||||
<option key={STT.options.address} value={STT.options.address}>
|
||||
{STT.options.address} (STT)
|
||||
</option>
|
||||
<option key="0x0000000000000000000000000000000000000000" value="0x0000000000000000000000000000000000000000">
|
||||
0x0000000000000000000000000000000000000000 (ETH)
|
||||
</option>
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={2}>
|
||||
<TextField
|
||||
id="gasPrice"
|
||||
label="Gas Price"
|
||||
value={this.state.gasPrice}
|
||||
onChange={this.handleChange('gasPrice')}
|
||||
margin="normal"
|
||||
fullWidth
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={2}>
|
||||
<TextField
|
||||
id="gasLimit"
|
||||
label="Gas Limit"
|
||||
value={this.state.gasLimit}
|
||||
onChange={this.handleChange('gasLimit')}
|
||||
margin="normal"
|
||||
fullWidth
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</form>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button color="primary" onClick={this.sign}>
|
||||
Sign Message
|
||||
</Button>
|
||||
<Button size="small" onClick={this.testContractDataSend}>TestContract.methods.test().send()</Button>
|
||||
<Button size="small" onClick={this.testContractDataCall}>TestContract.methods.test().call()</Button>
|
||||
|
||||
export default CallGasRelayed;
|
||||
</CardActions>
|
||||
</Card>
|
||||
|
||||
{ this.state.messagingError && <MySnackbarContentWrapper variant="error" message={this.state.messagingError} /> }
|
||||
<Card className={classes.card}>
|
||||
<CardHeader title="2 Message" />
|
||||
<CardContent>
|
||||
<TextField
|
||||
id="signature"
|
||||
label="Signed Message"
|
||||
value={this.state.signature}
|
||||
margin="normal"
|
||||
fullWidth
|
||||
InputProps={{
|
||||
readOnly: true
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
id="symKey"
|
||||
label="Symmetric Key"
|
||||
value={config.relaySymKey}
|
||||
margin="normal"
|
||||
fullWidth
|
||||
InputProps={{
|
||||
readOnly: true
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
id="topic"
|
||||
label="Whisper Topic"
|
||||
value={this.state.topic}
|
||||
margin="normal"
|
||||
InputProps={{
|
||||
readOnly: true
|
||||
}}
|
||||
/>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button size="small" color="primary" onClick={this.sendMessage} disabled={this.state.submitting}>
|
||||
Send Message
|
||||
</Button>
|
||||
</CardActions>
|
||||
</Card>
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
<Typography>
|
||||
Message Received:
|
||||
</Typography>
|
||||
<pre>{this.state.message}</pre>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
CallGasRelayed.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
nonce: PropTypes.string.isRequired,
|
||||
identityAddress: PropTypes.string
|
||||
};
|
||||
|
||||
const variantIcon = {
|
||||
error: ErrorIcon
|
||||
};
|
||||
|
||||
const styles1 = theme => ({
|
||||
error: {
|
||||
backgroundColor: theme.palette.error.dark
|
||||
},
|
||||
icon: {
|
||||
fontSize: 20
|
||||
},
|
||||
iconVariant: {
|
||||
opacity: 0.9,
|
||||
marginRight: theme.spacing.unit
|
||||
},
|
||||
message: {
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
function MySnackbarContent(props) {
|
||||
const {classes, className, message, variant, ...other} = props;
|
||||
const Icon = variantIcon[variant];
|
||||
|
||||
return (
|
||||
<SnackbarContent
|
||||
className={classNames(classes[variant], className)}
|
||||
aria-describedby="client-snackbar"
|
||||
message={
|
||||
<span id="client-snackbar" className={classes.message}>
|
||||
<Icon className={classNames(classes.icon, classes.iconVariant)} />
|
||||
{message}
|
||||
</span>
|
||||
}
|
||||
{...other}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
MySnackbarContent.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
className: PropTypes.string,
|
||||
message: PropTypes.node,
|
||||
onClose: PropTypes.func,
|
||||
variant: PropTypes.oneOf(['success', 'warning', 'error', 'info']).isRequired
|
||||
};
|
||||
|
||||
const MySnackbarContentWrapper = withStyles(styles1)(MySnackbarContent);
|
||||
|
||||
export default withStyles(styles)(CallGasRelayed);
|
||||
|
|
|
@ -4,12 +4,14 @@ import BalanceIcon from '@material-ui/icons/AccountBalance';
|
|||
import Button from '@material-ui/core/Button';
|
||||
import CircularProgress from '@material-ui/core/CircularProgress';
|
||||
import EmbarkJS from 'Embark/EmbarkJS';
|
||||
import Identity from 'Embark/contracts/Identity';
|
||||
import KeyIcon from '@material-ui/icons/VpnKey';
|
||||
import LinearProgress from '@material-ui/core/LinearProgress';
|
||||
import List from '@material-ui/core/List';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||
import ListItemText from '@material-ui/core/ListItemText';
|
||||
import NumberIcon from '@material-ui/icons/ConfirmationNumber';
|
||||
import PropTypes from 'prop-types';
|
||||
import RefreshIcon from '@material-ui/icons/Refresh';
|
||||
import STT from 'Embark/contracts/STT';
|
||||
|
@ -17,7 +19,7 @@ import Typography from '@material-ui/core/Typography';
|
|||
import config from '../config';
|
||||
import web3 from 'Embark/web3';
|
||||
import {withStyles} from '@material-ui/core/styles';
|
||||
|
||||
window.Id = Identity;
|
||||
const styles = theme => ({
|
||||
button: {
|
||||
marginRight: theme.spacing.unit * 2
|
||||
|
@ -71,18 +73,21 @@ class Status extends Component {
|
|||
relayerAddress: config.relayAccount
|
||||
});
|
||||
|
||||
this.updateBalances();
|
||||
web3.eth.subscribe('newBlockHeaders')
|
||||
.on("data", (blockHeader) => {
|
||||
if(blockHeader.number){
|
||||
this.setState({block: blockHeader.number});
|
||||
this.updateBalances();
|
||||
}
|
||||
});
|
||||
setInterval(() => {
|
||||
this.getBlock();
|
||||
}, 5000);
|
||||
});
|
||||
}
|
||||
|
||||
updateBalances = () => {
|
||||
getBlock = () => {
|
||||
web3.eth.getBlock('latest')
|
||||
.then((block) => {
|
||||
this.setState({block: block.number});
|
||||
this.readChain();
|
||||
});
|
||||
}
|
||||
|
||||
readChain = () => {
|
||||
if(this.props.identityAddress){
|
||||
web3.eth.getBalance(this.props.identityAddress)
|
||||
.then(identityEthBalance => {
|
||||
|
@ -94,6 +99,13 @@ class Status extends Component {
|
|||
.then(identitySTTBalance => {
|
||||
this.setState({identitySTTBalance: web3.utils.fromWei(identitySTTBalance, 'ether')});
|
||||
});
|
||||
|
||||
Identity.options.address = this.props.identityAddress;
|
||||
Identity.methods.nonce()
|
||||
.call()
|
||||
.then((nonce) => {
|
||||
this.props.nonceUpdateFunction(nonce);
|
||||
});
|
||||
}
|
||||
|
||||
web3.eth.getBalance(this.state.relayerAddress)
|
||||
|
@ -115,7 +127,7 @@ class Status extends Component {
|
|||
submitState.generateSTT = true;
|
||||
this.setState({submitState});
|
||||
|
||||
let toSend = STT.methods.generateTokens(this.props.identityAddress, web3.utils.toWei(5000, 'ether'));
|
||||
let toSend = STT.methods.generateTokens(this.props.identityAddress, web3.utils.toWei('5000', 'ether'));
|
||||
toSend.estimateGas()
|
||||
.then(estimatedGas => {
|
||||
return toSend.send({gas: estimatedGas + 10000});
|
||||
|
@ -150,7 +162,7 @@ class Status extends Component {
|
|||
submitState.etherSend = true;
|
||||
this.setState({submitState});
|
||||
|
||||
web3.eth.sendTransaction({from: web3.eth.defaultAccount, to: this.state.relayerAddress, value: web3.utils.toWei(1, "ether")})
|
||||
web3.eth.sendTransaction({from: web3.eth.defaultAccount, to: this.state.relayerAddress, value: web3.utils.toWei('1', "ether")})
|
||||
.then((receipt) => {
|
||||
console.log(receipt);
|
||||
submitState = this.state.submitState;
|
||||
|
@ -160,7 +172,7 @@ class Status extends Component {
|
|||
}
|
||||
|
||||
render(){
|
||||
const {classes, identityAddress} = this.props;
|
||||
const {classes, identityAddress, nonce} = this.props;
|
||||
const {identityEthBalance, relayerAddress, relayerEthBalance, identitySTTBalance, relayerSTTBalance, submitState, block} = this.state;
|
||||
|
||||
return <div className={classes.container}>
|
||||
|
@ -190,6 +202,15 @@ class Status extends Component {
|
|||
secondary="Address"
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={classes.root}>
|
||||
<ListItemIcon>
|
||||
<NumberIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={nonce}
|
||||
secondary="Nonce"
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={classes.root}>
|
||||
<ListItemIcon>
|
||||
<BalanceIcon />
|
||||
|
@ -252,7 +273,9 @@ class Status extends Component {
|
|||
Status.propTypes = {
|
||||
classes: PropTypes.object.isRequired,
|
||||
identityAddress: PropTypes.string,
|
||||
identityCreationFunction: PropTypes.func.isRequired
|
||||
nonce: PropTypes.string.isRequired,
|
||||
identityCreationFunction: PropTypes.func.isRequired,
|
||||
nonceUpdateFunction: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default withStyles(styles)(Status);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const config = {
|
||||
"relayAccount": "0x3c72082cbd10a874d673f25e0d48b72d294b5368"
|
||||
"relayAccount": "0x91b3c570ace45716010e162cbbc1b27cd1a10b65",
|
||||
"relaySymKey": "0xd0d905c1c62b810b787141430417caf2b3f54cffadb395b7bb39fdeb8f17266b"
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
Loading…
Reference in New Issue