Я чувствую, что я должен пропустить что-то тривиальное здесь. У меня есть смарт-контракт, который заполняет массив структур, показанных ниже. При попытке вызова addNewQuestion('0x12345')
или getQuestionListSize()
кажется, что он никогда не добавляет новую структуру Вопроса в questionList
. При вызове getQuestionListSize()
он должен возвращать счетчик, который я назвал questionId
, но он всегда просто возвращает «1». Любая помощь очень ценится.
Договор:
pragma solidity ^0.4.11;
contract EthUpVoting {
struct Question {
bytes32 ipfsHash;
uint upvotes;
address user;
}
uint private questionId;
mapping (uint => Question) public questionList;
event AddedQuestion(bytes32 ipfs_hash, uint qId);
function EthUpVoting() public {
questionId = 1;
questionList[questionId] = Question({
ipfsHash: "Hello, World!",
upvotes: 0,
user: msg.sender
});
}
function addNewQuestion(bytes32 questionHash) public {
questionId += 1;
questionList[questionId] = Question({
ipfsHash: questionHash,
upvotes: 0,
user: msg.sender
});
AddedQuestion(questionHash, questionId);
}
function voteForQuestion(uint qId) public {
questionList[qId].upvotes += 1;
questionId += 1;
}
function getQuestionTextAtIndex(uint qId) public constant returns (bytes32 ipfsHashReturn) {
return questionList[qId].ipfsHash;
}
function getQuestionListSize() public constant returns (uint size) {
return questionId;
}
}
NodeJS:
const web3 = new Web3(Web3.givenProvider || "ws://127.0.0.1:8546")
const ethUpVotingContract = new web3.eth.Contract(config.eth.abi, config.eth.contractAddr);
ethUpVotingContract.methods.addNewQuestion('foo').send(ethOptions, (err, resp) => {
if (err) {
console.log(err)
} else {
// successfully returns transaction hash
console.log(resp);
}
}).then(resp => {
// successfully returns transaction receipt
console.log(resp);
});
ethUpVotingContract.methods.getQuestionListSize().call().then(function (resp) {
// this always returns "1"
console.log(resp);
});
Я попробовал ваш контракт и обнаружил пару проблем:
ethUpVotingContract.methods.addNewQuestion('foo')
.send(ethOptions, (err, resp) => {
потерпит неудачу с
throw new Error('Данный параметр не является байтом: "'+ значение + '"');
Ошибка: данный параметр не является байтом: «foo» в SolidityTypeBytes.formatInputBytes [как _inputFormatter]
Преобразование в байты заставит его работать
const question = web3.utils.asciiToHex('foo');
ethUpVotingContract.methods.addNewQuestion(question)
.send(options, (err, hash) => {
Другая проблема заключается в том, что теперь send
и call
вернуть обещание. Что случилось? Если call
обещание начнет выполняться до send
завершения, оно отобразит предыдущие данные, как будто send
они никогда не выполнялись.
Чтобы исправить это, вы должны сделать call
внутри предложение then, send
чтобы убедиться, что оно завершено.
const message = web3.utils.asciiToHex('foo');
ethUpVotingContract.methods.addNewQuestion(message)
.send(options, (err, hash) => {
if (err) {
console.log(err);
}
console.log(`TxHash: ${hash}`);
})
.then((result) => {
console.log('Send has completed');
// Here we are guarantee `send` has finished
// and we can query the data
ethUpVotingContract.methods.getQuestionListSize().call()
.then((result) => {
console.log('Call has returned');
console.log(result);
});
});
// If we call here perhaps `send` didn't finish yet
console.log('Send was called');
Этеркимист
MannfromReno
Исмаэль
Этеркимист
Исмаэль
MannfromReno
http
провайдера, те же симптомы.