Updating library to include snt controller functions

This commit is contained in:
Richard Ramos 2018-09-01 16:35:56 -04:00
parent 4b97ac8704
commit 16ed849c84
3 changed files with 350 additions and 150 deletions

View File

@ -1,4 +1,5 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import StatusGasRelayer, {Contracts} from '../status-gas-relayer';
import Button from '@material-ui/core/Button'; import Button from '@material-ui/core/Button';
import Card from '@material-ui/core/Card'; import Card from '@material-ui/core/Card';
import CardActions from '@material-ui/core/CardActions'; import CardActions from '@material-ui/core/CardActions';
@ -9,11 +10,11 @@ import MySnackbarContentWrapper from './snackbar';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import SNTController from 'Embark/contracts/SNTController'; import SNTController from 'Embark/contracts/SNTController';
import STT from 'Embark/contracts/STT'; import STT from 'Embark/contracts/STT';
import TestContract from 'Embark/contracts/TestContract';
import TextField from '@material-ui/core/TextField'; import TextField from '@material-ui/core/TextField';
import config from '../config'; import config from '../config';
import web3 from 'Embark/web3'; import web3 from 'Embark/web3';
import {withStyles} from '@material-ui/core/styles'; import {withStyles} from '@material-ui/core/styles';
import TestContract from 'Embark/contracts/TestContract';
const styles = theme => ({ const styles = theme => ({
root: { root: {
@ -55,7 +56,7 @@ class Execute extends Component {
}); });
}; };
sign = (event) => { sign = async (event) => {
if(event) event.preventDefault(); if(event) event.preventDefault();
this.setState({ this.setState({
@ -63,28 +64,16 @@ class Execute extends Component {
transactionError: '' transactionError: ''
}); });
SNTController.options.address = this.props.identityAddress;
try { try {
let message = ""; const accounts = await web3.eth.getAccounts();
SNTController.methods.getExecuteGasRelayedHash(
this.state.allowedContract, const s = new StatusGasRelayer.SNTController(SNTController.options.address, accounts[2])
this.state.data, .execute(this.state.allowedContract, this.state.data)
this.props.nonce, .setGas(this.state.gasPrice, this.state.gasMinimal);
this.state.gasPrice,
this.state.gasMinimal const signature = await s.sign(web3);
)
.call() this.setState({signature});
.then(result => {
message = result;
return web3.eth.getAccounts();
})
.then(accounts => {
return web3.eth.sign(message, accounts[2]);
})
.then(signature => {
this.setState({signature});
});
} catch(error){ } catch(error){
this.setState({transactionError: error.message}); this.setState({transactionError: error.message});
} }
@ -112,32 +101,18 @@ class Execute extends Component {
this.props.clearMessages(); this.props.clearMessages();
const accounts = await web3.eth.getAccounts();
try { try {
const sendOptions = { const accounts = await web3.eth.getAccounts();
ttl: 1000,
sig: kid, const s = new StatusGasRelayer.AvailableRelayers(Contracts.SNT, SNTController.options.address, accounts[2])
powTarget: 1, .setRelayersSymKeyID(skid)
powTime: 20, .setAsymmetricKeyID(kid)
topic: this.state.topic, .setGas(STT.options.address, this.state.gasPrice);
symKeyID: skid, await s.post(web3);
payload: web3.utils.toHex({
'contract': SNTController.options.address, console.log("Message sent");
'address': accounts[2], this.setState({submitting: false});
'action': 'availability',
'gasToken': STT.options.address,
'gasPrice': this.state.gasPrice
})
};
web3.shh.post(sendOptions)
.then(() => {
this.setState({submitting: false});
console.log("Message sent");
return true;
});
} catch(error){ } catch(error){
this.setState({messagingError: error.message, submitting: false}); this.setState({messagingError: error.message, submitting: false});
} }
@ -161,39 +136,19 @@ class Execute extends Component {
this.props.clearMessages(); this.props.clearMessages();
try { try {
let jsonAbi = SNTController._jsonInterface.filter(x => x.name == "executeGasRelayed")[0];
let funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
this.state.allowedContract,
this.state.data,
this.props.nonce,
this.state.gasPrice,
this.state.gasMinimal,
this.state.signature
]);
const accounts = await web3.eth.getAccounts(); const accounts = await web3.eth.getAccounts();
const sendOptions = { const s = new StatusGasRelayer.SNTController(SNTController.options.address, accounts[2])
ttl: 1000, .execute(this.state.allowedContract, this.state.data)
sig: kid, .setGas(this.state.gasPrice, this.state.gasMinimal)
powTarget: 1, .setRelayer(relayer)
powTime: 20, .setAsymmetricKeyID(kid);
topic: this.state.topic,
pubKey: relayer, await s.post(this.state.signature, web3);
payload: web3.utils.toHex({
'contract': SNTController.options.address, this.setState({submitting: false});
'address': accounts[2], console.log("Message sent");
'action': 'transaction',
'encodedFunctionCall': funCall
})
};
web3.shh.post(sendOptions)
.then(() => {
this.setState({submitting: false});
console.log("Message sent");
return true;
});
} catch(error){ } catch(error){
this.setState({messagingError: error.message, submitting: false}); this.setState({messagingError: error.message, submitting: false});
} }

View File

@ -1,4 +1,5 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import StatusGasRelayer, {Contracts} from '../status-gas-relayer';
import Button from '@material-ui/core/Button'; import Button from '@material-ui/core/Button';
import Card from '@material-ui/core/Card'; import Card from '@material-ui/core/Card';
import CardActions from '@material-ui/core/CardActions'; import CardActions from '@material-ui/core/CardActions';
@ -9,12 +10,12 @@ import MySnackbarContentWrapper from './snackbar';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import SNTController from 'Embark/contracts/SNTController'; import SNTController from 'Embark/contracts/SNTController';
import STT from 'Embark/contracts/STT'; import STT from 'Embark/contracts/STT';
import TestContract from 'Embark/contracts/TestContract'; import TestContract from 'Embark/contracts/TestContract';
import TextField from '@material-ui/core/TextField'; import TextField from '@material-ui/core/TextField';
import config from '../config'; import config from '../config';
import web3 from 'Embark/web3'; import web3 from 'Embark/web3';
import {withStyles} from '@material-ui/core/styles'; import {withStyles} from '@material-ui/core/styles';
const styles = theme => ({ const styles = theme => ({
root: { root: {
width: '100%', width: '100%',
@ -64,7 +65,7 @@ class TransferSNT extends Component {
}); });
} }
sign = (event) => { sign = async (event) => {
if(event) event.preventDefault(); if(event) event.preventDefault();
this.setState({ this.setState({
@ -72,27 +73,18 @@ class TransferSNT extends Component {
transactionError: '' transactionError: ''
}); });
SNTController.options.address = this.props.identityAddress;
try { try {
let message = ""; const accounts = await web3.eth.getAccounts();
SNTController.methods.getTransferSNTHash(
this.state.to, const s = new StatusGasRelayer.SNTController(SNTController.options.address, accounts[2])
this.state.amount, .transferSNT(this.state.to, this.state.amount)
this.props.nonce, .setGas(this.state.gasPrice);
this.state.gasPrice
) const signature = await s.sign(web3);
.call()
.then(result => { this.setState({signature});
message = result;
return web3.eth.getAccounts();
})
.then(accounts => {
return web3.eth.sign(message, accounts[2]);
})
.then(signature => {
this.setState({signature});
});
} catch(error){ } catch(error){
this.setState({transactionError: error.message}); this.setState({transactionError: error.message});
} }
@ -109,31 +101,19 @@ class TransferSNT extends Component {
}); });
this.props.clearMessages(); this.props.clearMessages();
const accounts = await web3.eth.getAccounts();
try { try {
const sendOptions = { const accounts = await web3.eth.getAccounts();
ttl: 1000,
sig: kid, const s = new StatusGasRelayer.AvailableRelayers(Contracts.SNT, SNTController.options.address, accounts[2])
powTarget: 1, .setRelayersSymKeyID(skid)
powTime: 20, .setAsymmetricKeyID(kid)
topic: this.state.topic, .setGas(STT.options.address, this.state.gasPrice);
symKeyID: skid, await s.post(web3);
payload: web3.utils.toHex({
'contract': SNTController.options.address, console.log("Message sent");
'address': accounts[2], this.setState({submitting: false});
'action': 'availability',
'gasToken': STT.options.address,
'gasPrice': this.state.gasPrice
})
};
web3.shh.post(sendOptions)
.then(() => {
this.setState({submitting: false});
console.log("Message sent");
return true;
});
} catch(error){ } catch(error){
this.setState({messagingError: error.message, submitting: false}); this.setState({messagingError: error.message, submitting: false});
} }
@ -156,38 +136,19 @@ class TransferSNT extends Component {
this.props.clearMessages(); this.props.clearMessages();
try { try {
let jsonAbi = SNTController._jsonInterface.filter(x => x.name == "transferSNT")[0];
let funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
this.state.to,
this.state.amount,
this.props.nonce,
this.state.gasPrice,
this.state.signature
]);
const accounts = await web3.eth.getAccounts(); const accounts = await web3.eth.getAccounts();
const sendOptions = { const s = new StatusGasRelayer.SNTController(SNTController.options.address, accounts[2])
ttl: 1000, .transferSNT(this.state.to, this.state.amount)
sig: kid, .setGas(this.state.gasPrice)
powTarget: 1, .setRelayer(relayer)
powTime: 20, .setAsymmetricKeyID(kid);
topic: this.state.topic,
pubKey: relayer, await s.post(this.state.signature, web3);
payload: web3.utils.toHex({
'contract': SNTController.options.address, this.setState({submitting: false});
'address': accounts[2], console.log("Message sent");
'action': 'transaction',
'encodedFunctionCall': funCall
})
};
web3.shh.post(sendOptions)
.then(() => {
this.setState({submitting: false});
console.log("Message sent");
return true;
});
} catch(error){ } catch(error){
this.setState({messagingError: error.message, submitting: false}); this.setState({messagingError: error.message, submitting: false});
} }

View File

@ -7,6 +7,10 @@ export const Functions = {
'Identity': { 'Identity': {
'call': 'callGasRelayed', 'call': 'callGasRelayed',
'approveAndCall': 'approveAndCallGasRelayed' 'approveAndCall': 'approveAndCallGasRelayed'
},
'SNT': {
'transfer': 'transferSNT',
'execute': 'executeGasRelayed'
} }
}; };
@ -90,7 +94,8 @@ class StatusGasRelayer {
validateBuild = (build) => { validateBuild = (build) => {
return (String(build.constructor) === String(StatusGasRelayer.AvailableRelayers) || return (String(build.constructor) === String(StatusGasRelayer.AvailableRelayers) ||
String(build.constructor) === String(StatusGasRelayer.Identity) String(build.constructor) === String(StatusGasRelayer.Identity) ||
String(build.constructor) === String(StatusGasRelayer.SNTController)
); );
} }
@ -101,6 +106,10 @@ class StatusGasRelayer {
static get Identity() { static get Identity() {
return IdentityGasRelayedAction; return IdentityGasRelayedAction;
} }
static get SNTController() {
return SNTControllerAction;
}
} }
class Action { class Action {
@ -259,6 +268,124 @@ class IdentityGasRelayedAction extends Action {
} }
} }
class SNTControllerAction extends Action {
constructor(contractAddress, accountAddress) {
super();
this.contractName = Contracts.SNT;
this.contractAddress = contractAddress;
this.accountAddress = accountAddress;
this.operation = Actions.Transaction;
return this;
}
transferSNT = (to, value) => {
this.to = to;
this.value = value;
this.contractFunction = Functions.SNT.transfer;
return this;
}
execute = (contract, data) => {
this.allowedContract = contract;
this.data = data;
this.contractFunction = Functions.SNT.execute;
return this;
}
_nonce = async(contract) => {
const nonce = await contract.methods.signNonce(this.accountAddress).call();
return nonce;
}
getNonce = async (web3) => {
const contract = new web3.eth.Contract(sntControllerABI, this.contractAddress);
const nonce = await this._nonce(contract);
return nonce;
}
setGas(price, minimal){
this.gasPrice = price;
this.gasMinimal = minimal;
return this;
}
sign = async web3 => {
const contract = new web3.eth.Contract(sntControllerABI, this.contractAddress);
const nonce = await this._nonce(contract);
let hashedMessage;
switch(this.contractFunction){
case Functions.SNT.execute:
hashedMessage = await contract.methods.getExecuteGasRelayedHash(
this.allowedContract,
this.data,
nonce,
this.gasPrice,
this.gasMinimal,
).call();
break;
case Functions.SNT.transfer:
hashedMessage = await contract.methods.getTransferSNTHash(
this.to,
this.value,
nonce,
this.gasPrice
).call();
break;
default:
throw new Error("Function not allowed");
}
const signedMessage = await web3.eth.sign(hashedMessage, this.accountAddress);
return signedMessage;
}
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 => {
let jsonAbi = sntControllerABI.find(x => x.name == this.contractFunction);
let funCall;
switch(this.contractFunction){
case Functions.SNT.execute:
funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
this.allowedContract,
this.data,
this.nonce,
this.gasPrice,
this.gasMinimal,
this.signature
]);
break;
case Functions.SNT.transfer:
funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
this.to,
this.value,
this.nonce,
this.gasPrice,
this.signature
]);
break;
default:
throw new Error("Function not allowed");
}
return {
'contract': this.contractAddress,
'address': this.accountAddress,
'action': Actions.Transaction,
'encodedFunctionCall': funCall
};
}
}
class AvailableRelayersAction extends Action { class AvailableRelayersAction extends Action {
constructor(contractName, contractAddress, accountAddress) { constructor(contractName, contractAddress, accountAddress) {
@ -288,6 +415,163 @@ class AvailableRelayersAction extends Action {
} }
} }
const sntControllerABI = [
{
"constant": true,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_amount",
"type": "uint256"
},
{
"name": "_nonce",
"type": "uint256"
},
{
"name": "_gasPrice",
"type": "uint256"
}
],
"name": "getTransferSNTHash",
"outputs": [
{
"name": "txHash",
"type": "bytes32"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0x0c1f1f25"
},
{
"constant": true,
"inputs": [
{
"name": "_allowedContract",
"type": "address"
},
{
"name": "_data",
"type": "bytes"
},
{
"name": "_nonce",
"type": "uint256"
},
{
"name": "_gasPrice",
"type": "uint256"
},
{
"name": "_gasMinimal",
"type": "uint256"
}
],
"name": "getExecuteGasRelayedHash",
"outputs": [
{
"name": "execHash",
"type": "bytes32"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0x31c128b1"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_amount",
"type": "uint256"
},
{
"name": "_nonce",
"type": "uint256"
},
{
"name": "_gasPrice",
"type": "uint256"
},
{
"name": "_signature",
"type": "bytes"
}
],
"name": "transferSNT",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function",
"signature": "0x916b6511"
},
{
"constant": false,
"inputs": [
{
"name": "_allowedContract",
"type": "address"
},
{
"name": "_data",
"type": "bytes"
},
{
"name": "_nonce",
"type": "uint256"
},
{
"name": "_gasPrice",
"type": "uint256"
},
{
"name": "_gasMinimal",
"type": "uint256"
},
{
"name": "_signature",
"type": "bytes"
}
],
"name": "executeGasRelayed",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function",
"signature": "0x754e6ab0"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "signNonce",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
"signature": "0x907920c7"
}
];
const identityGasRelayABI = [ const identityGasRelayABI = [
{ {
"constant": true, "constant": true,