No se puede obtener valor al llamar a la función constante con web3js y Metamask

Tengo un contrato extremadamente básico implementado en Ropsten:

pragma solidity ^0.4.16;

contract hypergrowth {
  uint256 public someNumber = 5;

  function hypergrowth() public {}

  function changeNumber(uint256 number) public {
    someNumber = number;
  }

  function getNumber() public constant returns (uint256 someNumber) {
    return someNumber;
  }
}

Uso web3js y Metamask para interactuar con el contrato implementado.

Puedo inicializar web3. Puedo obtener la cuenta principal de Metamask. Pero siempre obtengo 0 cuando llamo a getNumber(). Aquí están las funciones que uso con web3:

function getNumberFromContract(contract) {
  contract.getNumber( (err, res) => {
    console.log(res.toNumber());
  });
}

function setNumberFromContract(contract) {
  contract.changeNumber(10, function(err,res){
    console.log("done");
  });
}

No entiendo por qué recibo 0... ni siquiera puedo ver si setNumber() funciona.

¿Qué hago mal?

ACTUALIZAR:

Uso este código para esperar a que se ejecute la función getNumber:

var deferred = new $.Deferred();
  setTimeout(function () {
    deferred.resolve(getNumberFromContract(hyperContract));
  }, 5000);

Y todavía obtener 0.

ACTUALIZACIÓN 2:

Así es como obtengo el contrato:

var address = '0xbabd1c95906d4ebec8977a7d0f32410ecba1103f';
var abi = [
  {
    "constant": true,
    "inputs": [],
    "name": "getNumber",
    "outputs": [
      {
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "name": "number",
        "type": "uint256"
      }
    ],
    "name": "changeNumber",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "constructor"
  }
];
var hyperContract = getContract(abi, web3.eth.accounts[0], web3);

La getContractfuncion es esta:

function getContract(ABI, address, web3) {
  return web3.eth.contract(ABI).at(address);
}

Respuestas (3)

¡Me parece que invocas tu función "getContract" con una dirección EOA y no la dirección del contrato!

cambiar :

var hyperContract = getContract(abi, web3.eth.accounts[0], web3);

por :

var hyperContract = getContract(abi, address, web3); // (As address var is defined above)

Debe esperar a que se extraiga la transacción.

Esta línea:

console.log("done");

debería leer con mayor precisión:

console.log("sent");

Puede generar el recibo de la transacción para risitas ( res). El siguiente paso es verificar periódicamente si la transacción está minada. Una vez que se extrae/confirma, puede continuar con su captador y, con solo observar el código, parece que funcionará.

Aquí hay una idea general que muestra una forma de esperar la confirmación antes de continuar con el siguiente paso.

https://gist.github.com/xavierlepretre/88682e871f4ad07be4534ae560692ee6

Espero eso ayude.

Probé con un objeto diferido y esperé 5 segundos. Todavía no funciona. Actualicé mi pregunta con el código.

Otro problema con su función es que la variable de retorno someNumberoculta la variable global con el mismo nombre someNumber.

uint256 public someNumber = 5;

// ..

function getNumber() public constant returns (uint256 someNumber) {
    return someNumber;    //   <---  Here someNumber is 0
}