Asignación de direcciones a unidades multidimensionales

Estoy tratando de crear una matriz que contenga direcciones que pertenezcan a una ID de transacción en particular.

Estructura de matriz:

transactions[0x12345][0] = 123456
transactions[0x12345][1] = 789101
transactions[0x12345][2] = 865436

Salida esperada al llamar a getAccountTransactions():

[0] = 123456
[1] = 789101
[2] = 865436

Código:

mapping (address => mapping(uint => uint)) public transactions;

function getAccountTransactions() public returns (uint[] tx) {

    return transactions[msg.sender];

}

El compilador devuelve el error:

TypeError: la asignación de tipo de argumento de retorno (uint256 => uint256) no se puede convertir implícitamente al tipo esperado (tipo de la primera variable de retorno) memoria uint256[].

Respuestas (1)

El principal problema con su código es que está tratando de devolver un uint[]que es un array, sin embargo, definió su variable como un mapeo de mapeos, y mappingson arrayde diferentes tipos.

Podrías hacer que tu código se compile así:

pragma solidity ^0.4.24;

contract test {

    mapping (address => uint[]) public transactions;

    constructor() public {
        transactions[msg.sender].push(123456);
        transactions[msg.sender].push(789101);
        transactions[msg.sender].push(865436);
    }

    function getTransactions() public view returns (uint[]) {

        return transactions[msg.sender];

    }
}

Sin embargo, en general, no recomendaría una sola función que devuelva todos los valores. Si bien esto puede usarse en un front-end web, no se escalará como una función de contrato normal, ya que eventualmente alcanzará una cantidad de objetos en la matriz donde el costo del gas para devolverlos será demasiado alto para el evm.

En su lugar, le sugiero que lo divida en dos funciones:

pragma solidity ^0.4.24;

contract test {

    mapping (address => uint[]) public transactions;

    constructor() public {
        transactions[msg.sender].push(123456);
        transactions[msg.sender].push(789101);
        transactions[msg.sender].push(865436);
    }

    function getTransactionsLength() public view returns (uint) {

        return transactions[msg.sender].length;

    }

    function getTransactionsValue(uint index) public view returns (uint) {

        return transactions[msg.sender][index];

    }
}

Uno es getTransactionsLength(), y el otro es getTransactionsValue(). Ambas funciones devuelven un solo uint, lo que significa que tendrá un tamaño de salida y costos de gas predecibles, lo que significa que puede usarse en otras partes de su contrato.

Además, también creará mejores experiencias de usuario al controlar la cantidad de valores que muestra. Si necesita mostrar todos los valores, primero puede obtener el length, y luego repetir la llamada de valor desde 0 to length-1.

Pero aún mejor, es posible que solo desee mostrar las últimas 10 transacciones en la interfaz de usuario, desde donde puede realizar un bucle length-1 to length-11. Estos pueden parecer complejos al principio, pero en realidad serán simplificaciones para su dApp a medida que crezca; cosas que realmente llegarás a apreciar de los programas inmutables :)

No puedo votar pero muchas gracias por la rápida respuesta. Su ejemplo me trae algunas ideas nuevas que voy a implementar en mi contrato :)
Ningún problema. Si esto responde a su pregunta, debería poder marcar la respuesta como correcta, ¡lo que hará que el foro sepa que el problema está resuelto! Buena suerte :)
Claro, mensaje marcado :)