0

I'm trying to interact with this contract via web3.js.

Something like this answer seems to be the right path to take, but I can't figure out how to implement that logic in my contract.

When getAdopters() is called, I see the following error in my browser's console:

invalid solidity type!: tuple[16]

Here's the code where getAdopters() is called:

  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);
    });
  },

Ultimately, how can I return the fields of the struct as separate return variables, and then access them using web3.js?

1

Your question is pretty similar to this one:

How to return an array of structs (or an array of destructured structs) in Solidity

Look over the comments, particularly with regards to "pragma experimental ABIEncoderV2;"

Updated..

Based on your comments, I think this is what you're looking for. The values from the structs will be returned to web3 as arrays of the struct values.

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);
    }
}

Some JS test code in test.js script:

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()}`);
                }
            });
    });
};

I tested using truffle

$ 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
| improve this answer | |
  • They say "just be aware that any web clients running web3.js will have issues". I'm using web3.js. – rustyshackleford Feb 17 '18 at 18:05
  • There are other libraries that supposedly support it. Checkout out Ethers.. github.com/ethers-io/ethers.js . Is web3.js a must? If it is, or you want to write a contract that would work with as many clients as possible, then returning structs from a public/external method is something you'll have to do without. – Howard Feb 17 '18 at 19:31
  • My question is "how can I return the fields of the struct as separate return variables, and then access them using web3.js?". – rustyshackleford Feb 17 '18 at 22:07
  • function getData(uint8 _index) external view returns (uint8,string) { return (data[_index].id, data[_index].name); } webjs would receive this as an array. – Howard Feb 17 '18 at 22:31
  • how can I change my getAdopters() function such that web3js receives it as an array? if you can just help me with that, I'd be glad to accept your answer – rustyshackleford Feb 17 '18 at 23:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.