In meinem Vertrag habe ich so ein Mappingmapping(uint => myStruct)
Ich habe eine check
Funktion, wo ich eine gebe und ich möchte alle Informationen in der Struktur (es gibt Strings, Adressen, uints, ...) mit einer Funktion in meinem truffle uint id
erhalten .call
app.js
Was ist der beste Weg, das zu tun? Kann ich jedes Feld in eine Zeichenfolge konvertieren und ein Array von Zeichenfolgen senden? Sollte ich für jedes Feld einen separaten Getter erstellen und so viele Funktionen verwenden call
?
Im Moment gebe ich nur struct zurück und ich bekommeinvalid solidity type!: tuple
Sie benötigen keine zusätzliche Solidity-Funktion, um die Informationen aus einer Struktur zu erhalten. Sie können die Struktur direkt mit web3 aufrufen.
Es ist hilfreich, wenn Sie eine Funktion im Vertrag haben, um die Anzahl der Token zu erhalten, da Sie sonst möglicherweise mit while anstelle von for stecken bleiben. Nehmen wir an, Sie haben eine Funktion, die Ihnen struct.length gibt
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);
}
Anscheinend wurde meine Frage falsch verstanden, aber ich habe das Problem mit Hilfe von Mikko Ohtamaa in den Kommentaren gelöst.
Aus irgendeinem Grund war mir nicht klar, dass ich mehrere Variablen (und von verschiedenen Typen!) Zurückgeben kann. Sobald Sie wissen, dass Sie dies tun können, gibt es wirklich kein Problem. Javascript kommt damit sehr gut zurecht.
Meine Lösung sieht in etwa so aus:
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);
}
/.../
}
Und in der entsprechenden Trüffel call
wird ein Array mit den Variablen der Rückgabe in der angegebenen Reihenfolge zurückgegeben:
myContractInstance.getOwnableInfo.call(ownableId).then((resultArray => {
name = resultArray[0];
creator = resultArray[1];
currentOwner = resultArray[2];
/.../
});
Anmerkungen:
Ownable o = Ownables[OwnableId];
, ich habe das gemacht, um die Lesbarkeit zu verbessern, ich denke nicht, dass es nützlich oder überhaupt eine gute Sache ist.resultArray[4].toNumber()
damit JavaScript damit umgehen kann.Der beste Weg, um etwas in eine Struktur einzufügen und alle Datensätze zu erhalten, ist:
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;
}
}
und verwenden Sie in Ihrer Benutzeroberfläche diesen Code:
Verwenden Sie zuerst let len = await test.methods.recordsArrayLength().call()
das length
Array of Records und rufen Sie es ab, und drücken Sie dann diesen Code:
let records = []
for(let i=0;i<len;i++){
records.push(await test.methods.records(i))
}
und jetzt haben Sie alle struct
Es ist tangential zu Ihrer Frage, aber eine der besten Möglichkeiten, Daten zu organisieren, ist eine zugeordnete Struktur mit einem Index von Schlüsseln. Dadurch ist es möglich, auf einen bestimmten Datensatz zuzugreifen oder seine Existenz zu überprüfen, ohne zu wissen, in welcher Zeile er sich befindet, und ohne eine Liste durchsuchen zu müssen. Der Index ist eine ungeordnete Liste von Schlüsseln, die es ermöglicht, die Schlüssel zu zählen und die vorhandenen Schlüssel aufzuzählen.
mapping(bytes32 => RecordStruct) public recordStructs;
bytes32 public recordKeys;
Werfen Sie hier einen Blick auf einige Varianten, Implementierungsdetails und Diskussionen über Einschränkungen und Vorteile verschiedener Ansätze.
Gibt es gut gelöste und einfache Speichermuster für Solidity?
Auch, obwohl in den Beispielen nicht gezeigt, können Ereignis-Emitter den Speicherzustand für Software-Clients sichtbar machen. Mit umfassenden Ereignisprotokollen kann man den Vertrag mit der Annahme schreiben, dass Kunden jederzeit über den vollständigen Zustand informiert sind. Dies reduziert Bedenken in der Kette erheblich.
Ich hoffe es hilft.
mapping(uint => myStruct)
haben Strukturen, die nach Nummer gespeichert sind, und die Frage betrifft die Migration zu einem Array (auch nach Nummer). Ich möchte per Schlüssel (z. B. "ORD002" oder "0x123...") abrufen und nicht suchen. Ich möchte auch eine Liste und eine Zählung.call
um all diese Informationen zu erhalten.
Kaki Meister der Zeit
return ( struct.member1,struct.member2)
Mikko Ohtamaa
Ziege teleportieren