¿Consulta cada estructura de una función de obtención de Mapping vs looping para el front-end?

Tengo un mapeo de estructuras y una variable de contador para realizar un seguimiento de cuántas estructuras se almacenan en el mapeo.

Para el desarrollo front-end, recomendaría consultar cada estructura utilizando el captador mymapping[mystruct_index] generado automáticamente. ¿O es mejor crear una función captadora específica para recorrer las estructuras X y recuperar estructuras en matrices de 50, por ejemplo? Además, si uso la función getter para obtener solo unas pocas filas de la estructura en lugar de la estructura completa, ¿conducirá a una mayor eficiencia que simplemente hacer una consulta para una estructura? ¿Tiene alguna experiencia con respecto a la interacción frontal con contratos inteligentes? ¿Cuál cree que es el mejor diseño para la eficiencia y la viabilidad a largo plazo del contrato inteligente? Atentamente

Respuestas (1)

Actualmente, Solidity no admite la devolución de una asignación o una lista de tamaño variable, por lo que deberá implementar una función getter como describió que toma un índice.

El enfoque que creo que está describiendo es mantener una segunda lista junto a la asignación y usarla para devolver la asignación en fragmentos como el código fuente a continuación.

contract SomeContract {

  mapping(address => uint256) public someMapping;
  address[] public addresses;

  function addValue(address _newAddress, uint256 _newValue) public {
    someMapping[_newAddress] = _newValue;
    addresses.push(_newAddress);
  }

  function getAddressCount() public view returns (uint256 _count) {
    return addresses.length;
  }

  function getValueByIndex(uint256 _index) public view returns (uint256 _val) {
    return someMapping[addresses[_index]];
  }

  // Get the values from mapping in chunks of size 10
  // This isn't a feasible solution in my opinion
  function getValuesChunk(uint256 _index) public view returns (uint256[10] memory _chunk) {
    uint256[10] memory vals;
    require(_index < 2^256 - 10, 'Index would wrap around unsafely');
    for (uint256 i = _index; i < _index+10; i++) {
        vals[i] = someMapping[addresses[i]];
    }
    return vals;
  }
}

Los viewmétodos son de solo lectura y no cuestan gasolina, por lo que técnicamente puede llamarlos tantas veces como desee para mostrar valores en su interfaz. Sin embargo, hay algunas razones para no hacerlo. * Seguiría necesitando potencia de CPU en su nodo Ethereum. Si es una lista lo suficientemente grande, su nodo podría considerarlo un ataque DoS y limitarlo o prohibirlo. Si ejecuta su propio nodo, eso es mucho trabajo o créditos de AWS para gastar en operaciones de cadena de bloques. * La asignación no cambiará mucho entre las llamadas a addValue. Estaría rehaciendo el trabajo de recuperar principalmente los mismos valores cada vez, incluso si realiza algo de almacenamiento en caché en su front-end.

En su lugar, recomendaría usar eventos de Solidity (registros de EVM), una función que le permite emitir un evento, que se recupera mediante una base de datos que permite que la indexación de un solo paso se lea varias veces fuera de la cadena, como Subgraph https:// thegraph .com/

Esto le permite mantener su código de solidez mínimo y limpio, sin gastar gasolina en un contrato complicado solo para admitir la funcionalidad de front-end que puede descargar fácilmente en sistemas diseñados para ello (GraphQL + React + Typescript)

contract SomeContract {

  event NewValue (
      address _address,
      uint256 _value
      );
  mapping(address => uint256) public someMapping;


  function addValue(address _newAddress, uint256 _newValue) public {
    someMapping[_newAddress] = _newValue;
    emit NewValue(_newAddress, _newValue);
  }

}

Espero que esto ayude.

Está bien, gracias. Simplemente no entiendo por qué creaste getValueByAddress getter ya que someMapping es público y debería poder hacer someMapping(adress) . Puedo hacerlo desde mi entorno de prueba de trufas, pero ¿estás diciendo que no es posible en mainet? Atentamente
@paul-ham Además, mi mapeo es ligeramente diferente: la clave es un índice uint vinculado al contador: mapeo (uint => struct) mymapping; uint contador de mapeo; // realiza un seguimiento de cuántas estructuras en el mapeo. Estaba pensando en hacer una función getter que devolvería una matriz creada en la memoria al recorrer las estructuras de mapeo
@KevinWad de nada. lol mi nombre es @paul-pham, no @paul-ham, ese es un desayuno diferente. Tiene razón, el mapeo público no necesita un captador separado, actualizaré mi respuesta para eliminarlo. Además, olvidé que su valor es una estructura, pero el principio general de mi respuesta aún se aplica. En lugar de regresar, uint256 _valuedevolvería su tipo de estructura.
Sí, mis disculpas. Vale, muchas gracias. Entonces, para reanudar, si confío en el captador de mapeo público sin una función de captador adicional, a medida que el mapeo se haga más grande, tendré que usar métodos fuera de la cadena porque, de lo contrario, enfrentaré problemas de Dos, ¿es correcto? ¿Y qué significa esto "Si ejecuta su propio nodo, eso es mucho trabajo o créditos de AWS para gastar en operaciones de cadena de bloques"? Atentamente
No hay problema. Llamar al captador público para el mapeo tiene un costo fijo para llamadas individuales. Si desea obtener todos los valores de mapeo cada vez, requerirá más y más llamadas a medida que el mapeo crece, como dijo. El resto de mi respuesta no encaja aquí, la moví a la esencia: gist.github.com/cryptogoth/edbacf61517bb9100b742b69ccd5fbc1 Espero que ayude