C# KrakenApi writing like "Invalid Key" but key is valid

101 Views Asked by At

[enter image description here][1]Help to correct it please C# KrakenApi writing like "Invalid Key" but key is valid. I just have no idea how to fix it, but I need it so much.

MAIN: Create a URL for the Kraken Balance API

        var url = "https://api.kraken.com/0/private/Balance";

Create a request object

        var request = (HttpWebRequest)WebRequest.Create(url);
        request.Method = "POST";

Add the API key header

        string apiKey = "API KEY";
        request.Headers.Add("API-Key", apiKey);

Add the secret key header

        string secret = "API SIGN";
        var nonce = GenerateNonce();
        var postData = $"nonce={nonce}";
        var apiSign = ComputeSignature(url, nonce, postData, secret);
        request.Headers.Add("API-Sign", apiSign);

Write the POST data to the request body

        byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        request.ContentLength = byteArray.Length;
        using (Stream dataStream = request.GetRequestStream())
        {
            dataStream.Write(byteArray, 0, byteArray.Length);
        }

Get the response from the API

        try
        {
            using (var response = (HttpWebResponse)request.GetResponse())
            {
                // Read the response stream
                using (var reader = new StreamReader(response.GetResponseStream()))
                {
                    // Convert the response to a string
                    var responseString = reader.ReadToEnd();

                    // Print the response
                    Console.WriteLine(responseString);
                }
            }
        }
        catch (WebException ex)
        {

If an error occurred, print the error message

            using (var errorResponse = (HttpWebResponse)ex.Response)
            {
                using (var reader = new StreamReader(errorResponse.GetResponseStream()))
                {
                    var error = reader.ReadToEnd();
                    Console.WriteLine(error);
                }
            }
        }

methods:

    static string ComputeSignature(string url, string nonce, string postData, string secret)
    {
        var path = new Uri(url).AbsolutePath;
        var data = Encoding.UTF8.GetBytes(nonce + postData);
        using (var hmac = new HMACSHA512(Convert.FromBase64String(secret)))
        {
            var pathBytes = Encoding.UTF8.GetBytes(path);
            hmac.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0);
            hmac.TransformFinalBlock(data, 0, data.Length);
            var hash = hmac.Hash;
            var signature = Convert.ToBase64String(hash);
            return signature;
        }
    }

    static string GenerateNonce()
    {
        var nonce = DateTime.UtcNow.Ticks;
        return nonce.ToString();
    }

I tried get my balance in Kraken.com with API

tried some, but -, may be u can advice some from nuget packages

      public static byte[] ComputeSha256Hash(string nonce, string inputParams)
    {
        string combinedString = nonce + inputParams;
        byte[] data = Encoding.UTF8.GetBytes(combinedString);

        using (SHA256 sha256Hash = SHA256.Create())
        {
            byte[] hashBytes = sha256Hash.ComputeHash(data);
            return hashBytes;
        }
    }

    public static byte[] ComputeSha512Hash(byte[] sha256Hash, string endpointName)
    {
        byte[] endpointBytes = Encoding.UTF8.GetBytes(endpointName);
        byte[] combinedBytes = new byte[sha256Hash.Length + endpointBytes.Length];

        Buffer.BlockCopy(sha256Hash, 0, combinedBytes, 0, sha256Hash.Length);
        Buffer.BlockCopy(endpointBytes, 0, combinedBytes, sha256Hash.Length, endpointBytes.Length);

        using (SHA512 sha512Hash = SHA512.Create())
        {
            byte[] hashBytes = sha512Hash.ComputeHash(combinedBytes);
            return hashBytes;
        }
    }
1

There are 1 best solutions below

6
derloopkat On BEST ANSWER

In my console application I have a GetAccountBalance() method. When I want to get my bitcoin balance, I am calling: decimal volume = GetAccountBalance(asset: "BTC").Value;.

Broker.cs

private decimal? GetAccountBalance(string asset)
{
    var response = GetAccountBalances();
    var balance = response["result"][asset]?.Value;
    var errors = response.error.ToObject<string[]>();
    Display.PrintErrors(errors);
    return decimal.Parse(balance);
}

public virtual dynamic GetAccountBalances()
{
    var json = KrakenApi.QueryPrivateEndpoint("Balance", null).Result;
    var response = JsonConvert.DeserializeObject<dynamic>(json);
    return response;
}

KrakenApi.cs

private const string BaseDomain = "https://api.kraken.com";
private const string PrivatePath = "/0/private/";
private static long LastUsedNonce;

public static async Task<string> QueryPrivateEndpoint(string endpointName, string inputParameters)
{           
    string apiEndpointFullURL = BaseDomain + PrivatePath + endpointName;
    string nonce = GetNextNonce();
    if (string.IsNullOrWhiteSpace(inputParameters) == false)
    {
        inputParameters = "&" + inputParameters;
    }
    string apiPostBodyData = "nonce=" + nonce + inputParameters;
    string signature = CreateAuthenticationSignature(endpointName, nonce, inputParameters);
    string jsonData;
    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Clear();
        client.DefaultRequestHeaders.Add("API-Key", ApiPublicKey);
        client.DefaultRequestHeaders.Add("API-Sign", signature);
        client.DefaultRequestHeaders.Add("User-Agent", "KrakenDotNet Client");
        StringContent data = new StringContent(apiPostBodyData, Encoding.UTF8, "application/x-www-form-urlencoded");
        HttpResponseMessage response = await client.PostAsync(apiEndpointFullURL, data);
        jsonData = response.Content.ReadAsStringAsync().Result;
    }
    Logger.AddEntry($"apiPostBodyData: {apiPostBodyData}");
    return jsonData;
}

public static string CreateAuthenticationSignature(string endpointName, string nonce, string inputParams)
{
    byte[] sha256Hash = ComputeSha256Hash(nonce, inputParams);
    byte[] sha512Hash = ComputeSha512Hash(sha256Hash, endpointName);
    return Convert.ToBase64String(sha512Hash);
}

private static string GetNextNonce()
{
    var nonce = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
    if (nonce == LastUsedNonce) nonce += 1;
    LastUsedNonce = nonce;
    return nonce.ToString();
}

private static byte[] ComputeSha256Hash(string nonce, string inputParams)
{
    byte[] sha256Hash;
    string sha256HashData = nonce.ToString() + "nonce=" + nonce.ToString() + inputParams;
    using (var sha = SHA256.Create())
    {
        sha256Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(sha256HashData));
    }
    return sha256Hash;
}

private static byte[] ComputeSha512Hash(byte[] sha256Hash, string endpointName)
{
    string apiEndpointPath = PrivatePath + endpointName;
    byte[] apiEndpointPathBytes = Encoding.UTF8.GetBytes(apiEndpointPath);
    byte[] sha512HashData = apiEndpointPathBytes.Concat(sha256Hash).ToArray();
    HMACSHA512 encryptor = new HMACSHA512(Convert.FromBase64String(ApiPrivateKey));
    byte[] sha512Hash = encryptor.ComputeHash(sha512HashData);
    return sha512Hash;
}

I use a different nonce number every time. Check out Kraken documentation for the details. Note QueryPrivateEndpoint() can also handle parameters in the query string. Finally you need to grant your api key with permission to retrieve your balance at the Kraken web site.