My use case is that I have to invoke a contract function when an API is called.
Now I have tried multiple ways, but I have issues with both. My function name is "transfer".
Method - I
In this method I first unlock the account of the user. Then invoke the contract function by contractInstance.methodName(). In the callback method, I lock the account again
Issue: The issue I see here is, when I get multiple calls to my api at the same time, it will cause an issue. As one call might lock the account just when one more thread is trying to invoke the function.
/ * Getting the contract Instance */
import Web3 from 'web3';
const tokenABI = require('../ContractABI.json');
if (typeof web3 !== 'undefined') {
var web3 = new Web3(web3.currentProvider)
} else {
var web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545'))
}
var TokenContract = web3.eth.contract(tokenABI.abi);
var tokenInstance = TokenContract.at(contractConfig.id);
/ * Getting the contract Instance */
router.post('/transferTokens',async (req,res,next)=>{
let senderAddress = req.param("sender");
let receiverAddress = req.param("receiver");
let transferAmount = req.param("amount");
let searchCriteria = {
address:senderAddress
}
try{
// Getting the private key of the user from DB.
let senderDetails = await MongoHelper.findOneByCriteria('accounts',searchCriteria);
console.log('senderDetails:',senderDetails);
let chk = web3.personal.unlockAccount(senderDetails.address, senderDetails.pwd, 95000);
// Unlocked the account and then invoke the transfer function with the necessary parameters.
tokenInstance.transfer(receiverAddress, transferAmount, { from: senderDetails.address })
.then(function (msg) {
res.data = msg;
let chk = web3.personal.lockAccount(senderDetails.address);
next();
}).catch(function (e) {
console.log('Error %%%%%%%%%%%%%%%%%',e);
let chk = web3.personal.lockAccount(senderDetails.address);
next(e)
});
}catch(err){
console.log(' Error err:',err);
next(err);
}
});
Method - II
**In this method, I am deriving the callData for my contract function. I am creating a Raw Transaction Object. I am signing it with the user's private key. Then I am using web3.eth.sendRawTransaction to send the transaction **
Issue: The issue i am facing is: I see a transaction is created. But it is not doing what it should do ideally. It is just a dummy transaction. The contract method is not getting invoked. I guess the call data is not proper or something.
I see the calldata something similar to below: 0xb7184b680000000000000000000000000000000000000000000000000000000000000578
router.post('/transferTokens2',async (req,res,next)=>{
let senderAddress = req.param("sender");
let receiverAddress = req.param("receiver");
let transferAmount = req.param("amount");
let searchCriteria = {
address:senderAddress
}
try{
let senderDetails = await MongoHelper.findOneByCriteria('accounts',searchCriteria);
let callData = tokenInstance.transfer.getData(receiverAddress,transferAmount);
let rawTx = {
from:senderAddress,
nonce: 93,
gasPrice: '0x4a817c800', // eth_estimateGas rpc result
gasLimit: '0x2fd618',
to:receiverAddress,
data:callData
}
var privateKey = new Buffer(senderDetails.key, 'hex')
var tx = new Tx(rawTx);
tx.sign(privateKey);
var serializedTx = tx.serialize();
web3.eth.sendRawTransaction('0x'+ serializedTx.toString('hex'), function(err, hash) {
if (!err) {
console.log('$$$$$:',hash);
res.data = hash;
next();
}else{
next(err);
}
});
}catch(err){
next(err);
}
});