private async Task <TResult> Request <TResult>(string query, CancellationToken cancellationToken)
        {
            var relativeUri = $"gql?token={_accessToken}";

            var requestStart = DateTimeOffset.UtcNow;

            HttpResponseMessage response;

            try
            {
                response = await _httpClient.PostAsync(relativeUri, JsonContent(new { query }), cancellationToken);
            }
            catch (Exception exception)
            {
                throw new TibberApiHttpException(new Uri(_httpClient.BaseAddress, relativeUri), HttpMethod.Post, DateTimeOffset.Now - requestStart, exception.Message, exception);
            }

            if (!response.IsSuccessStatusCode)
            {
                throw await TibberApiHttpException.Create(new Uri(new Uri(BaseUrl), relativeUri), HttpMethod.Post, response, DateTimeOffset.Now - requestStart).ConfigureAwait(false);
            }

            using var stream = await response.Content.ReadAsStreamAsync();

            using var streamReader = new StreamReader(stream);
            using var jsonReader   = new JsonTextReader(streamReader);
            return(Serializer.Deserialize <TResult>(jsonReader));
        }
        internal static async Task <TibberApiHttpException> Create(Uri uri, HttpMethod httpMethod, HttpResponseMessage response, TimeSpan duration, string message = null)
        {
            var exception =
                new TibberApiHttpException(
                    uri,
                    httpMethod,
                    response.StatusCode,
                    response.ReasonPhrase,
                    response.RequestMessage.Headers,
                    response.Headers,
                    duration,
                    message ?? $"HTTP '{httpMethod} {uri}' call failed with status '{response.ReasonPhrase}' ({(int)response.StatusCode})");

            if (response.RequestMessage.Content != null)
            {
                exception.RequestContentHeaders = response.RequestMessage.Content.Headers;

                try
                {
                    exception.RequestContent = await response.RequestMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
                }
                catch
                {
                    exception.RequestContent = "<unavailable>";
                }

                response.RequestMessage.Content.Dispose();
            }

            if (response.Content != null)
            {
                exception.ResponseContentHeaders = response.Content.Headers;

                try
                {
                    exception.ResponseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                }
                catch
                {
                    exception.RequestContent = "<unavailable>";
                }

                response.Content.Dispose();
            }

            response.Dispose();

            return(exception);
        }