diff --git a/test-dapp/app/components/callgasrelayed.js b/test-dapp/app/components/callgasrelayed.js index f508042..fef747e 100644 --- a/test-dapp/app/components/callgasrelayed.js +++ b/test-dapp/app/components/callgasrelayed.js @@ -1,4 +1,5 @@ import React, {Component} from 'react'; +import StatusGasRelayer, {Contracts} from '../status-gas-relayer'; import Button from '@material-ui/core/Button'; import Card from '@material-ui/core/Card'; import CardActions from '@material-ui/core/CardActions'; @@ -6,7 +7,6 @@ import CardContent from '@material-ui/core/CardContent'; import CardHeader from '@material-ui/core/CardHeader'; import EmbarkJS from 'Embark/EmbarkJS'; import Grid from '@material-ui/core/Grid'; -import IdentityGasRelay from 'Embark/contracts/IdentityGasRelay'; import MySnackbarContentWrapper from './snackbar'; import PropTypes from 'prop-types'; import STT from 'Embark/contracts/STT'; @@ -16,9 +16,6 @@ import config from '../config'; import web3 from 'Embark/web3'; import {withStyles} from '@material-ui/core/styles'; -import StatusGasRelayer, {Contracts} from '../status-gas-relayer'; - - const styles = theme => ({ root: { width: '100%', @@ -83,7 +80,7 @@ class CallGasRelayed extends Component { const s = new StatusGasRelayer.Identity(this.props.identityAddress, web3.eth.defaultAccount) .setTransaction(this.state.to, this.state.value, this.state.data) .setGas(this.state.gasToken, this.state.gasPrice, this.state.gasLimit); - + const signature = await s.sign(web3); this.setState({signature}); @@ -118,7 +115,7 @@ class CallGasRelayed extends Component { } } - sendTransaction = event => { + sendTransaction = async event => { event.preventDefault(); const {web3, kid} = this.props; @@ -135,38 +132,16 @@ class CallGasRelayed extends Component { this.props.clearMessages(); try { - 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.props.nonce, - this.state.gasPrice, - this.state.gasLimit, - this.state.gasToken, - this.state.signature - ]); - const sendOptions = { - ttl: 1000, - sig: kid, - powTarget: 1, - powTime: 20, - topic: this.state.topic, - pubKey: relayer, - payload: web3.utils.toHex({ - 'contract': this.props.identityAddress, - 'address': web3.eth.defaultAccount, - 'action': 'transaction', - 'encodedFunctionCall': funCall - }) - }; - - web3.shh.post(sendOptions) - .then(() => { - this.setState({submitting: false}); - console.log("Message sent"); - return true; - }); + const s = new StatusGasRelayer.Identity(this.props.identityAddress, web3.eth.defaultAccount) + .setTransaction(this.state.to, this.state.value, this.state.data) + .setGas(this.state.gasToken, this.state.gasPrice, this.state.gasLimit) + .setRelayer(relayer) + .setAsymmetricKeyID(kid); + + await s.post(this.state.signature, web3); + + this.setState({submitting: false}); + console.log("Message sent"); } catch(error){ this.setState({messagingError: error.message, submitting: false}); } diff --git a/test-dapp/app/status-gas-relayer.js b/test-dapp/app/status-gas-relayer.js index 7dac953..f1049e1 100644 --- a/test-dapp/app/status-gas-relayer.js +++ b/test-dapp/app/status-gas-relayer.js @@ -19,21 +19,34 @@ const relayerSymmmetricKeyID = "0xd0d905c1c62b810b787141430417caf2b3f54cffadb395 class StatusGasRelayer { constructor(build, web3) { + if (arguments.length !== 2 || !this.validateBuild(build)) throw new Error("Invalid build"); + this.web3 = web3; - if (arguments.length === 2 && this.validateBuild(build)) { + + Object.defineProperties(this, { + message: { + value: build._getMessage(web3), + writable: false + }, + topic: { + value: web3.utils.toHex(build.contractName).slice(0, 10), + writable: false + }, + kid: { + value: build.kid, + writable: false + } + }); + + if(build.operation === Actions.Transaction){ Object.defineProperties(this, { - message: { - value: build._getMessage(web3), + pubKey: { + value: build.relayer, writable: false - }, - topic: { - value: web3.utils.toHex(build.contractName).slice(0, 10), - writable: false - }, - kid: { - value: build.kid, - writable: false - }, + } + }); + } else { + Object.defineProperties(this, { skid: { value: build.skid, writable: false @@ -45,10 +58,8 @@ class StatusGasRelayer { post = async (options) => { options = options || {}; + let pubKey = options.pubKey || this.pubKey; let skid = options.skid || this.skid; - if(!skid){ - skid = await this.web3.shh.addSymKey(relayerSymmmetricKeyID); - } let kid = options.kid || this.kid; if(!kid){ @@ -61,10 +72,18 @@ class StatusGasRelayer { powTarget: options.powTarget || 1, powTime: options.powTime || 20, topic: this.topic, - symKeyID: skid, payload: this.web3.utils.toHex(this.message) }; + if(pubKey){ + sendOptions.pubKey = pubKey; + } else { + if(!skid){ + skid = await this.web3.shh.addSymKey(relayerSymmmetricKeyID); + } + sendOptions.symKeyID = skid; + } + const msgId = await this.web3.shh.post(sendOptions); return msgId; } @@ -97,6 +116,11 @@ class Action { return this; } + setRelayer(relayer){ + this.relayer = relayer; + return this; + } + setRelayersSymKeyID = (skid) => { this.skid = skid; return this; @@ -138,7 +162,7 @@ class IdentityGasRelayedAction extends Action { return nonce; } - sign = async (web3) => { + sign = async web3 => { const contract = new web3.eth.Contract(identityGasRelayABI, this.contractAddress); const nonce = await this._nonce(contract); @@ -153,14 +177,38 @@ class IdentityGasRelayedAction extends Action { this.gasToken ).call(); - const signature = await web3.eth.sign(hashedMessage, this.accountAddress); + const signedMessage = await web3.eth.sign(hashedMessage, this.accountAddress); - return signature; + return signedMessage; } - _getMessage = async web3 => { - return { + post = async (signature, web3, options) => { + this.nonce = await this.getNonce(web3); + this.signature = signature; + + const s = new StatusGasRelayer(this, web3); + return s.post(options); + } + _getMessage = web3 => { + // TODO: this depends on the operation to execute + let jsonAbi = identityGasRelayABI.find(x => x.name == "callGasRelayed"); + let funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [ + this.to, + this.value, + this.data, + this.nonce, + this.gasPrice, + this.gasLimit, + this.gasToken, + this.signature + ]); + + return { + 'contract': this.contractAddress, + 'address': this.accountAddress, + 'action': Actions.Transaction, + 'encodedFunctionCall': funCall }; } } @@ -253,7 +301,55 @@ const identityGasRelayABI = [ "stateMutability": "view", "type": "function", "signature": "0xaffed0e0" - } + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + }, + { + "name": "_data", + "type": "bytes" + }, + { + "name": "_nonce", + "type": "uint256" + }, + { + "name": "_gasPrice", + "type": "uint256" + }, + { + "name": "_gasLimit", + "type": "uint256" + }, + { + "name": "_gasToken", + "type": "address" + }, + { + "name": "_messageSignatures", + "type": "bytes" + } + ], + "name": "callGasRelayed", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfd0dded5" + } ]; export default StatusGasRelayer;