Cómo ver estructuras con trufa

En mi contrato tengo un mapeo como estemapping(uint => myStruct)

Tengo una checkfunción donde doy un uint idy quiero obtener toda la información en la estructura (hay cadenas, direcciones, uints, ...) con una callfunción en mi truffle app.js.

¿Cuál es la mejor manera de hacer eso? ¿Puedo convertir cada campo en una cadena y enviar una matriz de cadenas? ¿Debo hacer un getter separado para cada campo y usar tantas callfunciones?

Por ahora solo devuelvo struct y obtengoinvalid solidity type!: tuple

No puede devolver una estructura en solidez, al menos para la versión actual. por lo que debe devolver cada valor por sí solo. algo como:return ( struct.member1,struct.member2)
Tenga en cuenta que hay trabajo en curso para que Solidity admita la serialización de tipos complejos blog.ricmoo.com/…
@MedMansour ¿Puede devolver cada valor por separado en una sola devolución? ¡Eso cambia todo si js puede manejarlo!

Respuestas (4)

No necesita una función de solidez adicional para obtener la información de una estructura. Puede llamar a la estructura directamente usando web3.

Ayuda si tiene una función en el contrato para obtener la cantidad de tokens; de lo contrario, podría quedarse atrapado usando while en lugar de for. Supongamos que tiene una función para darle 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);
}

Aparentemente se malinterpretó mi pregunta, pero resolví el problema con la ayuda de Mikko Ohtamaa en los comentarios.

Por alguna razón, no me di cuenta de que podía devolver múltiples variables (¡y de diferentes tipos!). Una vez que sabes que puedes hacer esto, no hay ningún problema. Javascript lo maneja muy bien.

Mi solución se ve algo así:

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

  /.../
}

Y en la trufa correspondiente, calldevolverá un array con las variables de la devolución en orden:

myContractInstance.getOwnableInfo.call(ownableId).then((resultArray => {
  name = resultArray[0];
  creator = resultArray[1];
  currentOwner = resultArray[2];
  /.../
});

Notas:

  • No mires demasiado en el Ownable o = Ownables[OwnableId];, lo hice para aumentar la legibilidad, no creo que sea útil o algo bueno en absoluto.
  • Si uno de los datos es un número grande (generalmente un precio wei), lo convierto usando números grandes resultArray[4].toNumber()para que JavaScript pueda manejarlo.

la mejor manera de agregar algo a una estructura y obtener todos los registros es:

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

}

y en tu ui usa este código:

primero use let len = await test.methods.recordsArrayLength().call()y obtenga la lengthmatriz de registros y luego presione este código:

let records = []

for(let i=0;i<len;i++){
    records.push(await test.methods.records(i))
}

y ahora tienes toda la estructura

Entonces, en lugar de devolver la estructura, ¿devuelve una matriz con una estructura dentro?
si eso es correcto
No estoy seguro de cómo entendiste eso, pero no quiero agregar algo a una estructura, solo quiero obtener toda la información dentro de ella.

Es tangencial a su pregunta, pero una de las mejores formas de organizar los datos es una estructura asignada con un índice de claves. Esto hace posible acceder a un registro en particular o verificar su existencia sin saber en qué fila está y sin buscar en una lista. El índice es una lista desordenada de claves que permite contar las claves y enumerar las claves que existen.

mapping(bytes32 => RecordStruct) public recordStructs;
bytes32 public recordKeys;

Eche un vistazo aquí para ver algunas variantes, detalles de implementación y discusión de las limitaciones y ventajas de varios enfoques.

¿Existen patrones de almacenamiento sencillos y bien resueltos para Solidity?

Además, aunque no se muestra en los ejemplos, los emisores de eventos pueden hacer que el estado de almacenamiento sea evidente para los clientes de software. Con registros de eventos completos, se puede redactar el contrato asumiendo que los clientes conocen el estado completo en todo momento. Esto reduce considerablemente las preocupaciones en la cadena.

Espero eso ayude.

¿Qué quieres decir con " sin saber en qué fila está "? Su respuesta parece interesante, pero no estoy seguro de lo que está tratando de lograr.
Tiene mapping(uint => myStruct)estructuras almacenadas por número y la pregunta es sobre migrar a una matriz (también por número). Quiero recuperar por clave (por ejemplo, "ORD002" o "0x123...") y no quiero buscar. También quiero una lista y un conteo.
Creo que entendiste mal mi pregunta. No quiero migrar, tengo una estructura con varios datos de varios tipos y quiero escribir una función callcon truffle para obtener toda esa información.
Escribí una respuesta sobre cómo resolví mi problema, tal vez entiendas mejor lo que quise decir.