Работа со структурами в Solidity и web3js [дубликат]

Я пытаюсь взаимодействовать с этим контрактом через web3.js.

Что-то вроде этого ответа кажется правильным путем, но я не могу понять, как реализовать эту логику в моем контракте.

Когда getAdopters()вызывается, я вижу следующую ошибку в консоли моего браузера:

invalid solidity type!: tuple[16]

Вот код, где getAdopters()вызывается:

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

В конечном счете, как я могу вернуть поля структуры как отдельные возвращаемые переменные, а затем получить к ним доступ с помощью web3.js ?

Ответы (1)

Ваш вопрос очень похож на этот:

Как вернуть массив структур (или массив деструктурированных структур) в Solidity

Просмотрите комментарии, особенно в отношении «экспериментальной прагмы ABIEncoderV2;»

Обновлено..

Основываясь на ваших комментариях, я думаю, что это то, что вы ищете. Значения из структур будут возвращены в web3 в виде массивов значений структур.

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

Некоторый тестовый код JS в сценарии 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()}`);
                }
            });
    });
};

Я тестировал с трюфелем

$ 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
Они говорят: «просто имейте в виду, что у любых веб-клиентов, использующих web3.js, будут проблемы». Я использую web3.js.
Есть и другие библиотеки, которые якобы его поддерживают. Оформить заказ на Ethers.. github.com/ethers-io/ethers.js . Является ли web3.js обязательным? Если это так, или вы хотите написать контракт, который будет работать с как можно большим количеством клиентов, то вам придется обойтись без возврата структур из общедоступного/внешнего метода.
Мой вопрос: «Как я могу вернуть поля структуры как отдельные возвращаемые переменные, а затем получить к ним доступ с помощью web3.js?».
функция getData(uint8 _index) возвращает внешнее представление (uint8,string) { return (data[_index].id, data[_index].name); } webjs получит это как массив.
как я могу изменить свою getAdopters()функцию, чтобы web3js получал ее как массив? если вы можете просто помочь мне с этим, я был бы рад принять ваш ответ
Смотрите мое обновление..
ах, это выглядит здорово! что мне нужно сделать с соответствующей markAdopted()функцией в моем файле js?
У меня нет удобной среды разработки, чтобы протестировать ее, но вы вызовете функцию контракта getAdopters и должны получить массив обратно, где элемент 0 — это массив владельцев, а элемент 1 — массив цен. Цены, скорее всего, вернутся в виде объектов BN, вы можете вызвать для них valueOf(), чтобы получить значения.
Спасибо за это. Кажется, что ownersон возвращается как пустой массив. В консоли вижу Cannot convert undefined or null to object. Я отредактировал свой вопрос с моим обновленным кодом js. Как вы думаете, что я делаю неправильно здесь?
Я добавил пример кода js в свой ответ. Надеюсь, это поможет.
без использования соглашений ES6, как это будет выглядеть в моей текущей markAdopted()функции?
Извините, но я думаю, что мы достигли конца пути на этом. Удачи вам.