Added account options
This commit is contained in:
parent
47c449c035
commit
a27d230c4c
|
@ -11,7 +11,13 @@ module.exports = {
|
|||
"port": 8545
|
||||
},
|
||||
"blockchain": {
|
||||
"account": "0xb8d851486d1c953e31a44374aca11151d49b8bb3"
|
||||
// privateKey: "your_private_key",
|
||||
|
||||
// privateKeyFile: "path/to/file"
|
||||
|
||||
// mnemonic: "12 word mnemonic",
|
||||
// addressIndex: "0", // Optionnal. The index to start getting the address
|
||||
// hdpath: "m/44'/60'/0'/0/" // Optionnal. HD derivation path
|
||||
},
|
||||
"whisper": {
|
||||
"symKey": "0xd0d905c1c62b810b787141430417caf2b3f54cffadb395b7bb39fdeb8f17266b",
|
||||
|
|
|
@ -22,8 +22,10 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.18.0",
|
||||
"bip39": "^2.5.0",
|
||||
"consola": "^1.4.3",
|
||||
"daemonize2": "^0.4.2",
|
||||
"ethereumjs-wallet": "^0.6.2",
|
||||
"ganache-cli": "^6.1.0",
|
||||
"jsum": "^0.1.4",
|
||||
"memory-cache": "^0.2.0",
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
const bip39 = require("bip39");
|
||||
const hdkey = require('ethereumjs-wallet/hdkey');
|
||||
const ethereumjsWallet = require('ethereumjs-wallet');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
|
||||
class AccountParser {
|
||||
static get(accountConfig, web3) {
|
||||
if (accountConfig.privateKey) {
|
||||
if (!accountConfig.privateKey.startsWith('0x')) {
|
||||
accountConfig.privateKey = '0x' + accountConfig.privateKey;
|
||||
}
|
||||
if (!web3.utils.isHexStrict(accountConfig.privateKey)) {
|
||||
console.error(`Private key ending with ${accountConfig.privateKey.substr(accountConfig.privateKey.length - 5)} is not a HEX string`);
|
||||
return null;
|
||||
}
|
||||
return web3.eth.accounts.privateKeyToAccount(accountConfig.privateKey);
|
||||
}
|
||||
|
||||
|
||||
if (accountConfig.privateKeyFile) {
|
||||
let privateKeyFile = path.resolve(accountConfig.privateKeyFile);
|
||||
let fileContent = fs.readFileSync(privateKeyFile).toString();
|
||||
if (accountConfig.password) {
|
||||
try {
|
||||
fileContent = JSON.parse(fileContent);
|
||||
if (!ethereumjsWallet['fromV' + fileContent.version]) {
|
||||
console.error(`Key file ${accountConfig.privateKeyFile} is not a valid keystore file`);
|
||||
return null;
|
||||
}
|
||||
const wallet = ethereumjsWallet['fromV' + fileContent.version](fileContent, accountConfig.password);
|
||||
return web3.eth.accounts.privateKeyToAccount('0x' + wallet.getPrivateKey().toString('hex'));
|
||||
} catch (e) {
|
||||
console.error('Private key file is not a keystore JSON file but a password was provided');
|
||||
console.error(e.message || e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
fileContent = fileContent.trim().split(/[,;]/);
|
||||
return fileContent.map((key, index) => {
|
||||
if (!key.startsWith('0x')) {
|
||||
key = '0x' + key;
|
||||
}
|
||||
if (!web3.utils.isHexStrict(key)) {
|
||||
console.error(`Private key is not a HEX string in file ${accountConfig.privateKeyFile} at index ${index}`);
|
||||
return null;
|
||||
}
|
||||
return web3.eth.accounts.privateKeyToAccount(key);
|
||||
});
|
||||
}
|
||||
|
||||
if (accountConfig.mnemonic) {
|
||||
const hdwallet = hdkey.fromMasterSeed(bip39.mnemonicToSeed(accountConfig.mnemonic.trim()));
|
||||
const addressIndex = accountConfig.addressIndex || 0;
|
||||
const wallet_hdpath = accountConfig.hdpath || "m/44'/60'/0'/0/";
|
||||
const wallet = hdwallet.derivePath(wallet_hdpath + addressIndex).getWallet();
|
||||
return web3.eth.accounts.privateKeyToAccount('0x' + wallet.getPrivateKey().toString('hex'));
|
||||
}
|
||||
|
||||
console.error('Unsupported account configuration: ' + JSON.stringify(accountConfig));
|
||||
console.error('Try using one of those: ' +
|
||||
'{ "privateKey": "your-private-key", "privateKeyFile": "path/to/file/containing/key", "mnemonic": "12 word mnemonic" }');
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AccountParser;
|
|
@ -92,29 +92,37 @@ class MessageProcessor {
|
|||
* @param {function} reply - function to reply a message
|
||||
* @returns {undefined}
|
||||
*/
|
||||
async processTransaction(contract, input, reply, cb){
|
||||
async processTransaction(contract, input, reply, account, cb){
|
||||
const validationResult = await this.processStrategy(contract, input, reply);
|
||||
|
||||
const {toHex} = this.web3.utils;
|
||||
|
||||
if(!validationResult.success) return;
|
||||
|
||||
const {toBN} = this.web3.utils;
|
||||
|
||||
const gasPrice = toBN(await this.web3.eth.getGasPrice()).add(toBN(this.config.gasPrice.modifier)).toString();
|
||||
|
||||
let p = {
|
||||
from: this.config.node.blockchain.account,
|
||||
to: input.contract,
|
||||
value: 0,
|
||||
data: input.payload,
|
||||
gasPrice
|
||||
};
|
||||
const nonce = await this.web3.eth.getTransactionCount(this.config.node.blockchain.account.address);
|
||||
|
||||
if(!validationResult.estimatedGas){
|
||||
validationResult.estimatedGas = await this.web3.eth.estimateGas(p);
|
||||
}
|
||||
|
||||
p.gas = Math.floor(parseInt(validationResult.estimatedGas, 10)); // Tune this
|
||||
const estimatedGas = parseInt(validationResult.estimatedGas, 10);
|
||||
|
||||
const nodeBalance = await this.web3.eth.getBalance(this.config.node.blockchain.account);
|
||||
let p = {
|
||||
from: this.config.node.blockchain.account.address,
|
||||
to: input.contract,
|
||||
value: "0x00",
|
||||
data: input.payload,
|
||||
nonce: toHex(nonce),
|
||||
gasPrice: toHex(parseInt(gasPrice, 10)),
|
||||
gasLimit: toHex(estimatedGas) // Tune this,
|
||||
};
|
||||
|
||||
|
||||
const nodeBalance = await this.web3.eth.getBalance(this.config.node.blockchain.account.address);
|
||||
|
||||
if(nodeBalance < p.gas){
|
||||
reply("Relayer unavailable");
|
||||
|
@ -122,14 +130,16 @@ class MessageProcessor {
|
|||
this.events.emit('exit');
|
||||
} else {
|
||||
try {
|
||||
this.web3.eth.sendTransaction(p)
|
||||
.on('transactionHash', function(hash){
|
||||
reply("Transaction broadcasted: " + hash);
|
||||
cb();
|
||||
})
|
||||
.on('receipt', function(receipt){
|
||||
reply("Transaction mined", receipt);
|
||||
});
|
||||
const signedTrx = await account.signTransaction(p);
|
||||
|
||||
this.web3.eth.sendSignedTransaction(signedTrx.rawTransaction)
|
||||
.on('transactionHash', function(hash){
|
||||
reply("Transaction broadcasted: " + hash);
|
||||
cb();
|
||||
})
|
||||
.on('receipt', function(receipt){
|
||||
reply("Transaction mined", receipt);
|
||||
});
|
||||
|
||||
} catch(err){
|
||||
reply("Couldn't mine transaction: " + err.message);
|
||||
|
|
|
@ -6,7 +6,8 @@ const MessageProcessor = require('./message-processor');
|
|||
const JSum = require('jsum');
|
||||
const logger = require('consola');
|
||||
const winston = require('winston');
|
||||
var cache = require('memory-cache');
|
||||
const cache = require('memory-cache');
|
||||
const accountParser = require('./account-parser');
|
||||
|
||||
// Setting up logging
|
||||
const wLogger = winston.createLogger({
|
||||
|
@ -28,6 +29,8 @@ const events = new EventEmitter();
|
|||
const connectionURL = `${config.node.local.protocol}://${config.node.local.host}:${config.node.local.port}`;
|
||||
const wsProvider = new Web3.providers.WebsocketProvider(connectionURL, {headers: {Origin: "gas-relayer"}});
|
||||
const web3 = new Web3(wsProvider);
|
||||
let account;
|
||||
|
||||
|
||||
web3.eth.net.isListening()
|
||||
.then(() => events.emit('web3:connected', connectionURL))
|
||||
|
@ -39,6 +42,15 @@ web3.eth.net.isListening()
|
|||
|
||||
events.on('web3:connected', connURL => {
|
||||
logger.info("Connected to '" + connURL + "'");
|
||||
|
||||
|
||||
account = accountParser.get(config.node.blockchain, web3);
|
||||
if(!account) {
|
||||
process.exit(1);
|
||||
} else {
|
||||
config.node.blockchain.account = account;
|
||||
}
|
||||
|
||||
let settings = new ContractSettings(config, web3, events, logger);
|
||||
settings.process();
|
||||
});
|
||||
|
@ -50,10 +62,10 @@ const shhOptions = {
|
|||
};
|
||||
|
||||
const verifyBalance = async (exitSubs) => {
|
||||
const nodeBalance = await web3.eth.getBalance(config.node.blockchain.account);
|
||||
const nodeBalance = await web3.eth.getBalance(config.node.blockchain.account.address);
|
||||
if(web3.utils.toBN(nodeBalance).lte(web3.utils.toBN(100000))){ // TODO: tune minimum amount required for transactions
|
||||
logger.info("Not enough balance available for processing transactions");
|
||||
logger.info("> Account: " + config.node.blockchain.account);
|
||||
logger.info("> Account: " + config.node.blockchain.account.address);
|
||||
logger.info("> Balance: " + nodeBalance);
|
||||
|
||||
if(exitSubs){
|
||||
|
@ -171,6 +183,7 @@ events.on('server:listen', (shhOptions, settings) => {
|
|||
processor.processTransaction(settings.getContractByTopic(message.topic),
|
||||
input,
|
||||
reply,
|
||||
account,
|
||||
() => {
|
||||
cache.put(inputCheckSum, (new Date().getTime()), 3600000);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ class AvailabilityStrategy extends Strategy {
|
|||
success: true,
|
||||
message: {
|
||||
message: "Available",
|
||||
address: this.config.node.blockchain.account,
|
||||
address: this.config.node.blockchain.account.address,
|
||||
minGasPrice: gasPrices.inTokens.toString(),
|
||||
gasPriceETH: gasPrices.inEther.add(toBN(this.config.gasPrice.modifier)).toString()
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ class BaseStrategy {
|
|||
*/
|
||||
async _estimateGas(input){
|
||||
let p = {
|
||||
from: this.config.node.blockchain.account,
|
||||
from: this.config.node.blockchain.account.address,
|
||||
to: input.contract,
|
||||
data: input.payload
|
||||
};
|
||||
|
|
|
@ -82,7 +82,7 @@ class IdentityStrategy extends Strategy {
|
|||
if(exc.message.indexOf("revert") > -1) return {success: false, message: "Transaction will revert"};
|
||||
else {
|
||||
console.error(exc);
|
||||
return {success: false, message: "Couldn't process transaction"};
|
||||
return {success: false, message: "Transaction will fail"};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,11 +23,20 @@ class SNTStrategy extends Strategy {
|
|||
|
||||
const balance = await this.getBalance(input.address, token);
|
||||
|
||||
const estimatedGas = await this.web3.eth.estimateGas({
|
||||
data: input.payload,
|
||||
from: this.config.node.blockchain.account,
|
||||
to: input.contract
|
||||
});
|
||||
let estimatedGas;
|
||||
try {
|
||||
estimatedGas = await this.web3.eth.estimateGas({
|
||||
data: input.payload,
|
||||
from: this.config.node.blockchain.account.address,
|
||||
to: input.contract
|
||||
});
|
||||
} catch(exc){
|
||||
if(exc.message.indexOf("revert") > -1) return {success: false, message: "Transaction will revert"};
|
||||
else {
|
||||
console.error(exc);
|
||||
return {success: false, message: "Transaction will fail"};
|
||||
}
|
||||
}
|
||||
|
||||
let tokenRate = await this.getTokenRate(token, cache);
|
||||
if(!tokenRate){
|
||||
|
|
Loading…
Reference in New Issue