Siento que debo estar perdiendo algo trivial aquí. Tengo un contrato inteligente que completa una serie de estructuras que se muestran a continuación. Cuando intenta llamar addNewQuestion('0x12345')
o getQuestionListSize()
parece que nunca agrega una nueva estructura de pregunta a questionList
. Al llamar getQuestionListSize()
, debería devolver el contador que nombré questionId
, pero siempre solo devuelve "1". Cualquier ayuda muy apreciada.
Contrato:
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;
}
}
NodoJS:
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);
});
Probé su contrato y encontré un par de problemas:
ethUpVotingContract.methods.addNewQuestion('foo')
.send(ethOptions, (err, resp) => {
fallará con
throw new Error('El parámetro dado no son bytes: "'+ valor + '"');
Error: el parámetro dado no es bytes: "foo" en SolidityTypeBytes.formatInputBytes [como _inputFormatter]
La conversión a bytes hará que funcione
const question = web3.utils.asciiToHex('foo');
ethUpVotingContract.methods.addNewQuestion(question)
.send(options, (err, hash) => {
El otro problema es que ahora send
ya call
devuelve una promesa. ¿Lo que está sucediendo? Si la call
promesa comienza a ejecutarse antes de send
que finalice, mostrará los datos anteriores como si send
nunca hubiera tenido éxito.
Para corregir eso, debe hacer que el call
interior sea la cláusula luego del send
para asegurarse de que haya terminado
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');
eterquimista
MannfromReno
ismael
eterquimista
ismael
MannfromReno
http
proveedor, los mismos síntomas.