/// <summary>
        /// Gets a list of all tickers in a specific range provided by the "https://api.coinmarketcap.com/v2/ticker/" API endpoint. Performs an asynchronous call to the API.
        /// </summary>
        /// <param name="converter">An optional supported currency converter.</param>
        /// <returns>Returns a <see cref="Task{CmcResponse{Dictionary{string, CmcTicker}}}"/> with the result provided by the API, or any error occurred during the call.</returns>
        /// <seealso cref="SupportedFiatCurrencyConverters"/>.
        /// <seealso cref="SupportedCryptoCurrencyConverters"/>.
        public async Task <CmcResponse <Dictionary <string, CmcTicker> > > GetAllTickersAsync(string converter = null)
        {
            var cmcRequest = new CmcRequestSettings()
            {
                Endpoint          = CmcEndpoint.Ticker,
                CurrencyConverter = converter,
                StartPosition     = CmcRequestSettings.DefaultStartPosition,
                Limit             = CmcRequestSettings.DefaultLimit
            };

            var response = await ExecuteRequest <Dictionary <string, CmcTicker> >(cmcRequest);

            if (!response.Success)
            {
                return(response);
            }

            int totalCurrencyCount = response.Metadata.CryptocurrenciesCount;
            int currentCounter     = response.Data.Count;

            cmcRequest.StartPosition = 1; //set to one, so in the loop it can be incremented by LIMIT (100) => 101, 201, 301...
            var tempResponse = response;

            while (currentCounter < totalCurrencyCount && tempResponse.Success)
            {
                cmcRequest.StartPosition += cmcRequest.Limit;
                tempResponse              = await ExecuteRequest <Dictionary <string, CmcTicker> >(cmcRequest);

                if (!tempResponse.Success)
                {
                    return(tempResponse);
                }

                foreach (var item in tempResponse.Data)
                {
                    if (!response.Data.ContainsKey(item.Key))
                    {
                        response.Data.Add(item.Key, item.Value);
                    }
                }

                currentCounter = response.Data.Count;
            }

            return(response);
        }
        /// <summary>
        /// Executes a request to "https://api.coinmarketcap.com/" API using the specified settings.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="settings">The settings determining which endpoint will be called and if any parameter should be submitted to the endpoint.</param>
        /// <returns></returns>
        private async Task <CmcResponse <T> > ExecuteRequest <T>(CmcRequestSettings settings)
        {
            string content = String.Empty;

            try
            {
                using (var http = new HttpClient())
                {
                    var response = await http.GetAsync(settings.GetRelativeUrl());

                    content = await response.Content.ReadAsStringAsync();

                    if (!response.IsSuccessStatusCode)
                    {
                        var error = JsonConvert.DeserializeObject <CmcResponse <T> >(content);
                        error.Metadata.ErrorMessage = $"HTTP Response - Status code: {response.StatusCode}. Message: {error.Metadata.ErrorMessage}.";
                        return(error);
                    }

                    //Gets the result and sets success accordingly. Empty error message means success.
                    var result = JsonConvert.DeserializeObject <CmcResponse <T> >(content);
                    return(result);
                }
            }
            catch (JsonReaderException jre)
            {
                return(new CmcResponse <T>($"Exception: '{nameof(JsonSerializationException)}'." +
                                           $"{Environment.NewLine}" +
                                           $"Error occurred at Path: '{jre.Path}'; Line number: '{jre.LineNumber}', Line position: '{jre.LinePosition}'." +
                                           $"{Environment.NewLine}" +
                                           $"Received data: '{content}'."
                                           ));
            }
            catch (JsonSerializationException jse)
            {
                return(new CmcResponse <T>($"Exception: '{nameof(JsonSerializationException)}'." +
                                           $"{Environment.NewLine}" +
                                           $"Message: '{jse.Message}'." +
                                           $"{Environment.NewLine}" +
                                           $"Received data: '{content}'."
                                           ));
            }
            catch (CryptoMarketDataException cmde)
            {
                return(new CmcResponse <T>($"Exception: '{nameof(CryptoMarketDataException)}'" +
                                           $"{Environment.NewLine}" +
                                           $"Message: '{cmde.Message}'." +
                                           $"{Environment.NewLine}" +
                                           $"Inner exception: '{(cmde.InnerException != null ? cmde.InnerException.Message : String.Empty)}'."
                                           ));
            }
            catch (Exception e)
            {
                return(new CmcResponse <T>($"Exception: '{e.GetType()}'" +
                                           $"{Environment.NewLine}" +
                                           $"Message: '{e.Message}'." +
                                           $"{Environment.NewLine}" +
                                           $"Inner exception: '{(e.InnerException != null ? e.InnerException.Message : String.Empty)}'."
                                           ));
            }
        }