В моем контракте у меня есть такое отображениеmapping(uint => myStruct)
У меня есть check
функция, в которой я даю, uint id
и я хочу получить всю информацию в структуре (есть строки, адреса, uints,...) с помощью функции call
в моем трюфеле app.js
.
Как лучше всего это сделать? Могу ли я преобразовать каждое поле в строку и отправить массив строк? Должен ли я сделать отдельный геттер для каждого поля и использовать как можно больше call
функций?
Пока я просто возвращаю структуру и получаюinvalid solidity type!: tuple
Вам не нужна дополнительная функция Solidity, чтобы получить информацию из структуры. Вы можете вызвать структуру напрямую, используя web3.
Это помогает, если у вас есть функция в контракте для получения количества токенов, иначе вы можете застрять, используя while вместо for. Предположим, у вас есть функция, которая дает вам struct.length
var OwnableList = [];
//to get one struct entry you do this.
function getStructData(tokenId) {
myContract.Ownables(tokenId, function(error, details) {
if(details == undefined) {
return false;
} else {
var name = details[0];
var creator = details[1];
var currentOwner = details[2];
var isDestructible = details[3];
var price = parseInt(details[4]);
OwnableList.push({name: name, creator: creator, currentOwner: currentOwner, isDestructible: isDestructible, price: price});
})
return true;
}
}
//to get all struct entrys you do this
function dumpStructData() {
myContract.totalOwnables(function(error, total) {
for(i=0; i<parseInt(total); i++) {
getStructData(i);
}
}
}
//now you can just read the struct
function showStruct() {
console.log(JSON.stringify(OwnableList);
}
Видимо мой вопрос был неправильно понят, но я решил проблему с помощью Mikko Ohtamaa в комментариях.
По какой-то причине я не понял, что могу вернуть несколько переменных (и разных типов!). Если вы знаете, что можете это сделать, на самом деле нет проблем. Javascript справляется с этим очень хорошо.
Мое решение выглядит примерно так:
contract myContract {
struct Ownable {
string name;
address creator;
address currentOwner;
bool isDestructible;
uint price;
}
mapping (uint => Ownable) public Ownables;
function getOwnableInfo(uint OwnableId) public view returns (string, address, address, bool, uint){
Ownable o = Ownables[OwnableId];
return (o.name, o.creator, o.currentOwner, o.isDestructible, o.price);
}
/.../
}
И в соответствующем трюфеле call
вернет массив с переменными возврата по порядку:
myContractInstance.getOwnableInfo.call(ownableId).then((resultArray => {
name = resultArray[0];
creator = resultArray[1];
currentOwner = resultArray[2];
/.../
});
Примечания:
Ownable o = Ownables[OwnableId];
, я сделал это, чтобы улучшить читаемость, я не думаю, что это полезно или вообще хорошо.resultArray[4].toNumber()
чтобы JavaScript мог его обработать.лучший способ добавить что-то в структуру и получить все записи:
pragma solidity ^0.4.17;
contract test {
struct Record {
string name;
string homeAddress;
}
Record[] public records;
function AddRecord(string Address , string Name) public {
Record memory newRec = Record({
name : Name,
homeAddress : Address
});
records.push(newRec);
}
function recordsArrayLength() public view returns(uint256){
return records.length;
}
}
и в вашем пользовательском интерфейсе используйте этот код:
сначала используйте let len = await test.methods.recordsArrayLength().call()
и получите length
массив записей, а затем нажмите этот код:
let records = []
for(let i=0;i<len;i++){
records.push(await test.methods.records(i))
}
и теперь у вас есть вся структура
Это не имеет отношения к вашему вопросу, но один из лучших способов организации данных - это сопоставленная структура с индексом ключей. Это позволяет получить доступ к определенной записи или проверить ее существование, не зная, в какой строке она находится, и без поиска в списке. Индекс представляет собой неупорядоченный список ключей, который позволяет подсчитывать ключи и перечислять существующие ключи.
mapping(bytes32 => RecordStruct) public recordStructs;
bytes32 public recordKeys;
Посмотрите здесь некоторые варианты, детали реализации и обсуждение ограничений и преимуществ различных подходов.
Существуют ли хорошо решенные и простые шаблоны хранения для Solidity?
Кроме того, хотя это и не показано в примерах, генераторы событий могут сделать состояние хранилища очевидным для программных клиентов. С полными журналами событий можно написать контракт, предполагая, что клиенты всегда осведомлены о полном состоянии. Это значительно снижает проблемы в сети.
Надеюсь, поможет.
mapping(uint => myStruct)
есть структуры, хранящиеся по номеру, и вопрос касается перехода к массиву (также по номеру). Я хочу получить по ключу (например, "ORD002" или "0x123...") и не хочу искать. Я также хочу список и количество.call
трюфелем, чтобы получить всю эту информацию.
Каки Мастер Времени
return ( struct.member1,struct.member2)
Микко Отамаа
Телепортирующаяся коза