contract MarketDataStorage is Ownable {
    // vars
    address[] supportedTokens;
    mapping (address => bool) public supportedTokensMapping; // same as supportedTokens just in a mapping for quicker lookup
    mapping (address => uint[]) public currentTokenMarketData; // represent the last token data
    mapping (bytes32 => bool) internal validIds; // for Oraclize callbacks
    address dataUpdater; // who is allowed to update data

    // modifiers
    modifier updaterOnly() {
        require(
            msg.sender == dataUpdater,
            "updater not allowed"
        );
        _;
    }

    modifier supportedTokenOnly(address token_address) {
        require(
            isTokenSupported(token_address),
            "Can't update a non supported token"
        );
        _;
    }

    constructor (address[] _supportedTokens, address _dataUpdater) Ownable() public {
        dataUpdater = _dataUpdater;

        // to populate supportedTokensMapping
        for (uint i=0; i<_supportedTokens.length; i++) {
            addSupportedToken(_supportedTokens[i]);
        }
    }

    function numberOfSupportedTokens() view public returns (uint) {
        return supportedTokens.length;
    }

    function getSupportedTokenByIndex(uint idx) view public returns (address token_address, bool supported_status) {
        address token = supportedTokens[idx];
        return (token, supportedTokensMapping[token]);
    }

    function getMarketDataByTokenIdx(uint idx) view public returns (address token_address, uint volume, uint depth, uint marketcap) {
        (address token, bool status) = getSupportedTokenByIndex(idx);

        (uint _volume, uint _depth, uint _marketcap) = getMarketData(token);

        return (token, _volume, _depth, _marketcap);
    }

    function getMarketData(address token_address) view public returns (uint volume, uint depth, uint marketcap) {
        // we do not throw an exception for non supported tokens, simply return 0,0,0
        if (!supportedTokensMapping[token_address]) {
            return (0,0,0);
        }

        uint[] memory data = currentTokenMarketData[token_address];
        return (data[0], data[1], data[2]);
    }

    function addSupportedToken(address token_address) public onlyOwner {
        require(
            isTokenSupported(token_address) == false,
            "Token already added"
        );

        supportedTokens.push(token_address);
        supportedTokensMapping[token_address] = true;

        currentTokenMarketData[token_address] = [0,0,0]; // until next update
    }

    function isTokenSupported(address token_address) view public returns (bool) {
        return supportedTokensMapping[token_address];
    }

    // update Data
    function updateMarketData(address token_address,
        uint volume,
        uint depth,
        uint marketcap)
    external
    updaterOnly
    supportedTokenOnly(token_address) {
        currentTokenMarketData[token_address] = [volume,depth,marketcap];
    }
}
function updateMarketData(address token_address,
    uint volume,
    uint depth,
    uint marketcap)
external
updaterOnly
supportedTokenOnly(token_address) {
    currentTokenMarketData[token_address] = [volume,depth,marketcap];
}

// update Data