Documentation for Gas Relayer pt1

This commit is contained in:
Richard Ramos 2018-08-27 11:58:52 -04:00
parent 4dd1004c4e
commit 00a203896f
6 changed files with 93 additions and 4 deletions

View File

@ -1,5 +1,14 @@
/**
* Message Processor to analyze and execute strategies based on input objects
*/
class MessageProcessor {
/**
* @param {object} config Configuration object obtained from `./config/config.js`
* @param {object} settings Settings obtained from parsing the configuration object
* @param {object} web3 Web3 object already configured
* @param {object} events Event emitter
*/
constructor(config, settings, web3, events){
this.config = config;
this.settings = settings;
@ -7,6 +16,12 @@ class MessageProcessor {
this.events = events;
}
/**
* Validate input message content
* @param {object} contract Contract object obtained from the settings based on the message topic
* @param {object} input Input object obtained from a message.
* @returns {object} State of validation
*/
async _validateInput(contract, input){
console.info("Processing '%s' request to contract: %s", input.action, input.contract);
@ -37,6 +52,14 @@ class MessageProcessor {
return {success: true};
}
/**
* Process strategy and return validation result
* @param {object} contract Contract object obtained from the settings based on the message topic
* @param {object} input Input object obtained from a message.
* @param {function} reply Reply function to return message
* @param {object} strategy Strategy to apply. If undefined, it will use a strategy based on the contract
* @returns {object} State of validation
*/
async processStrategy(contract, input, reply, strategy){
const inputValidation = await this._validateInput(contract, input);
if(!inputValidation.success){
@ -62,6 +85,13 @@ class MessageProcessor {
}
}
/**
* Process strategy and based on its result, send a transaction to the blockchain
* @param {object} contract Contract object obtained from the settings based on the message topic
* @param {object} input Input object obtained from a message.
* @param {function} reply Reply function to return message
* @returns {undefined}
*/
async processTransaction(contract, input, reply){
const validationResult = await this.processStrategy(contract, input, reply);
@ -89,7 +119,7 @@ class MessageProcessor {
try {
const receipt = await this.web3.eth.sendTransaction(p);
// TODO: parse events
return reply("Transaction mined", receipt);
reply("Transaction mined", receipt);
} catch(err){
reply("Couldn't mine transaction: " + err.message);
// TODO log this?

View File

@ -1,13 +1,22 @@
const Strategy = require('./BaseStrategy');
/**
* Class representing a strategy to validate an 'availability' request.
* @extends Strategy
*/
class AvailabilityStrategy extends Strategy {
async execute(input){
/**
* Process availability strategy
* @param {object} input Input object obtained from an 'availability' request. It expects an object with this structure `{contract, address, action, gasToken, gasPrice}`
* @returns {object} Status of validation, and minimum price
*/
execute(input){
// Verifying if token is allowed
const token = this.settings.getToken(input.gasToken);
if(token == undefined) return {success: false, message: "Token not allowed"};
// TODO Validate gasPrice, and return the minPrice accepted
// TODO: Validate gasPrice, and return the minPrice accepted
const minPrice = 0.00;
return {

View File

@ -2,7 +2,17 @@ const ganache = require("ganache-cli");
const Web3 = require('web3');
const erc20ABI = require('../../abi/ERC20Token.json');
/**
* Abstract class used for validation strategies
*/
class BaseStrategy {
/**
* @param {object} web3 Web3 object already configured
* @param {object} config Configuration object obtained from `./config/config.js`
* @param {object} settings Settings obtained from parsing the configuration object
* @param {object} contract Contract object obtained from the settings based on the message topic
*/
constructor(web3, config, settings, contract){
this.web3 = web3;
this.settings = settings;
@ -10,6 +20,12 @@ class BaseStrategy {
this.config = config;
}
/**
* Obtain the balance in tokens or ETH from an address
* @param {string} address ETH address to obtain the balance from
* @param {object} token Token obtained from `settings.getToken(tokenSymbol)`
* @returns {web3.utils.BN} Balance
*/
async getBalance(address, token){
// Determining balances of token used
if(token.symbol == "ETH"){
@ -21,6 +37,11 @@ class BaseStrategy {
}
}
/**
* Build Parameters Function
* @param {object} input Input object obtained from an `transaction` request.
* @returns {function} Function that simplifies accessing contract functions' parameters
*/
_obtainParametersFunc(input){
const parameterList = this.web3.eth.abi.decodeParameters(this.contract.allowedFunctions[input.functionName].inputs, input.functionParameters);
return function(parameterName){
@ -28,6 +49,11 @@ class BaseStrategy {
};
}
/**
* Estimate gas using web3
* @param {object} input Input object obtained from an `transaction` request.
* @returns {web3.utils.toBN} Estimated gas fees
*/
async _estimateGas(input){
let p = {
from: this.config.node.blockchain.account,
@ -40,6 +66,8 @@ class BaseStrategy {
/**
* Simulate transaction using ganache. Useful for obtaining events
* @param {object} input Input object obtained from an `transaction` request.
* @returns {object} Simulated transaction receipt
*/
async _simulateTransaction(input){
let web3Sim = new Web3(ganache.provider({

View File

@ -1,8 +1,17 @@
const Strategy = require('./BaseStrategy');
const erc20ABI = require('../../abi/ERC20Token.json');
/**
* Class representing a strategy to validate a `transaction` request when the topic is related to Identities.
* @extends Strategy
*/
class IdentityStrategy extends Strategy {
/**
* Validates if the contract being invoked represents an Identity instance
* @param {object} input Input object obtained from a `transaction` request.
* @returns {bool} Valid instance or not
*/
async _validateInstance(input){
const instanceCodeHash = this.web3.utils.soliditySha3(await this.web3.eth.getCode(input.contract));
const kernelVerifSignature = this.web3.utils.soliditySha3(this.contract.kernelVerification).slice(0, 10);
@ -15,6 +24,11 @@ class IdentityStrategy extends Strategy {
return this.web3.eth.abi.decodeParameter('bool', verificationResult);
}
/**
* Process Identity strategy
* @param {object} input Input object obtained from an 'transaction' request. It expects an object with this structure `{contract, address, action, functionName, functionParameters, payload}`
* @returns {object} Status of validation and estimated gas
*/
async execute(input){
if(this.contract.isIdentity){
let validInstance = await this._validateInstance(input);

View File

@ -3,9 +3,17 @@ const Strategy = require('./BaseStrategy');
const TransferSNT = "0x916b6511";
const ExecuteGasRelayed = "0x754e6ab0";
/**
* Class representing a strategy to validate a `transaction` request when the topic is related to SNTController.
* @extends Strategy
*/
class SNTStrategy extends Strategy {
/**
* Process SNTController strategy
* @param {object} input Input object obtained from an 'transaction' request. It expects an object with this structure `{contract, address, action, functionName, functionParameters, payload}`
* @returns {object} Status of validation and estimated gas
*/
async execute(input){
const params = this._obtainParametersFunc(input);