Trabajando con estructuras en Solidity y web3js [duplicado]

Estoy tratando de interactuar con este contrato a través de web3.js.

Algo como esta respuesta parece ser el camino correcto a seguir, pero no puedo encontrar la manera de implementar esa lógica en mi contrato.

Cuando getAdopters()se llama, veo el siguiente error en la consola de mi navegador:

invalid solidity type!: tuple[16]

Aquí está el código donde getAdopters()se llama:

  markAdopted: function(owners, account) {
    var adoptionInstance;

    App.contracts.Adoption.deployed().then(function(instance) {
      adoptionInstance = instance;

      return adoptionInstance.getAdopters.call();

    }).then(function(owners) {
      for (i = 0; i < owners.length; i++) {
        if (owners[i] !== '0x0000000000000000000000000000000000000000') {
            $('.panel-pet').eq(i).find('button').text('Success').attr('disabled', true);
            var loc = document.getElementById('owned-by');
            loc.innerHTML += owners[i];
            console.log(valueOf(owners[0]));

        }
      }
    }).catch(function(err) {
      console.log(err.message);
    });
  },

En última instancia, ¿cómo puedo devolver los campos de la estructura como variables de retorno separadas y luego acceder a ellas usando web3.js ?

Respuestas (1)

Tu pregunta es bastante similar a esta:

Cómo devolver una matriz de estructuras (o una matriz de estructuras desestructuradas) en Solidity

Revise los comentarios, particularmente con respecto a "pragma experimental ABIEncoderV2;"

Actualizado..

Según tus comentarios, creo que esto es lo que estás buscando. Los valores de las estructuras se devolverán a web3 como matrices de los valores de la estructura.

pragma solidity ^0.4.19;
contract Adoption {
    struct Pet {
        address owner;
        uint256 price;
    }

    Pet[16] data;

    function Adoption() public {
        for (uint i = 0; i < 16; i++) {
            data[i].owner = msg.sender;
            data[i].price = i;
        }
    }

    function getAdopters() external view returns (address[],uint256[]) {
        address[] memory owners = new address[](16);
        uint256[] memory prices =  new uint256[](16);
        for (uint i = 0; i < 16; i++) {
            owners[i] = (data[i].owner);
            prices[i] = (data[i].price);
        }
        return (owners,prices);
    }
}

Algunos códigos de prueba JS en el script test.js:

module.exports = () => {
    const Adoption = artifacts.require('Adoption');
    return Adoption.deployed().then(function(instance) {
        adoptionInstance = instance;

        return adoptionInstance.getAdopters.call()
            .then(adopters => {
                const [ owners, prices ] = adopters;
                for (let i = 0; i < owners.length; i++) {
                    console.log(`owner=${owners[i]}, price=${prices[i].valueOf()}`);
                }
            });
    });
};

Probé usando trufa

$ truffle exec --network ganache test.js 
Using network 'ganache'.

owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=0
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=1
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=2
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=3
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=4
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=5
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=6
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=7
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=8
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=9
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=10
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=11
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=12
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=13
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=14
owner=0x627306090abab3a6e1400e9345bc60c78a8bef57, price=15
Dicen "solo tenga en cuenta que cualquier cliente web que ejecute web3.js tendrá problemas". Estoy usando web3.js.
Hay otras bibliotecas que supuestamente lo admiten. Echa un vistazo a Ethers.. github.com/ethers-io/ethers.js . ¿Es web3.js imprescindible? Si es así, o si desea escribir un contrato que funcione con tantos clientes como sea posible, entonces tendrá que prescindir de la devolución de estructuras desde un método público/externo.
Mi pregunta es "¿cómo puedo devolver los campos de la estructura como variables de retorno separadas y luego acceder a ellos usando web3.js?".
función getData(uint8 _index) vista externa devuelve (uint8,string) { return (data[_index].id, data[_index].name); } webjs recibiría esto como una matriz.
¿Cómo puedo cambiar mi getAdopters()función para que web3js la reciba como una matriz? si me puede ayudar con eso, estaría encantado de aceptar su respuesta
Ver mi actualización..
ay, esto se ve genial! ¿Qué tendría que hacer con la markAdopted()función correspondiente en mi archivo js?
No tengo un entorno de desarrollo a mano para probarlo, pero llamaría a la función getAdopters del contrato y debería recibir una matriz donde el elemento 0 es la matriz de propietarios y el elemento 1 es la matriz de precios. Es probable que los precios regresen como objetos BN, puede llamar a valueOf() para obtener los valores.
gracias por eso. Parece que ownersse devuelve como una matriz vacía. En la consola, veo Cannot convert undefined or null to object. Edité mi pregunta con mi código js actualizado. ¿Qué crees que estoy haciendo mal aquí?
Agregué un código de muestra js a mi respuesta. Espero que ayude.
sin usar las convenciones de ES6, ¿cómo se vería eso dentro de mi markAdopted()función actual?
Lo siento, pero creo que hemos llegado al final del camino en este caso. La mejor de las suertes para ti.