Problema al intentar recuperar datos del contrato usando Web3 1.0

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);
});
¿Por qué usa ethUpVotingContract.methods? no solo ethUpVotingContract
Solo estaba siguiendo la documentación: web3js.readthedocs.io/en/1.0/…
En una versión anterior, el proveedor 'ws' no funcionaba, probaría con 'http' y/o 'ipc' para verificar si funcionan, web3 v1.0 todavía está en versión beta, por lo que algunas cosas no funcionarán y otras tienen errores.
@Ismael, ¿entonces esto de los métodos es parte de web3js 1.0 como nuevas características?
@Etherkimist Sí, web3 v1.0 es una refactorización del antiguo v0.20 estable. Diría que aprenda web3 v1.0 porque está más preparado para el futuro, pero si necesita algo listo para la producción, me quedaría con v0.20 por el momento. Esperemos que v1.0 sea lanzado pronto.
Intenté usar el httpproveedor, los mismos síntomas.

Respuestas (1)

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 sendya calldevuelve una promesa. ¿Lo que está sucediendo? Si la callpromesa comienza a ejecutarse antes de sendque finalice, mostrará los datos anteriores como si sendnunca hubiera tenido éxito.

Para corregir eso, debe hacer que el callinterior sea la cláusula luego del sendpara 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');
Gracias por tomarse el tiempo para encontrar el error y explicar todo, muy útil.