Мой вариант использования заключается в том, что мне нужно вызывать функцию контракта при вызове API.
Теперь я пробовал несколько способов, но у меня есть проблемы с обоими. Имя моей функции — «передача» .
Метод - я
В этом методе я сначала разблокирую учетную запись пользователя. Затем вызовите функцию контракта с помощью contractInstance.methodName(). В методе обратного вызова я снова блокирую учетную запись
Проблема: проблема, которую я вижу здесь, заключается в том, что когда я получаю несколько вызовов своего API одновременно, это вызывает проблему. Поскольку один вызов может заблокировать учетную запись, когда еще один поток пытается вызвать функцию.
/ * 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);
}
});
Метод - II
**В этом методе я получаю callData для своей контрактной функции. Я создаю необработанный объект транзакции. Я подписываю его закрытым ключом пользователя. Затем я использую web3.eth.sendRawTransaction для отправки транзакции **
Проблема: проблема, с которой я столкнулся: я вижу, что транзакция создана. Но он не делает того, что должен делать в идеале. Это просто фиктивная сделка. Метод контракта не вызывается. Я предполагаю, что данные вызова не являются правильными или что-то в этом роде.
Я вижу calldata примерно так, как показано ниже:
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);
}
});
Для метода 1) вам необходимо сериализовать доступ к разблокировке/блокировке учетной записи. Вы можете использовать семафор для ограничения одной операции в любое время.
Для метода 2) вы жестко запрограммировали одноразовый номер. Вы должны рассчитывать перед каждой сделкой var nonce = web3.eth.getTransactionCount(<address>)
. Имейте в виду, что nonce — это последовательные числа без повторений. Вы также должны гарантировать, что каждый одноразовый номер используется только один раз.