For information on changes for our US clients, please visit our Support Center article.

Поиск
Example code for C# REST and WebSocket API

Introduction

Below is a C# example script that can be referenced for both the REST and WebSocket Implementation of the Kraken API.

It demo's the following functionality:
  • Public REST API Endpoints
  • Private REST API Endpoints
  • Public WebSocket API Subscriptions
  • Private WebSocket API Subscriptions

Installation

To run locally, you can copy/paste the code below.

Note that setting the if statement of 1 == 0 to 1 == 1 will execute the specific block of code.

Before running the script, you need to update the script with your Public and Private API Keys.

You can download this file here.

C# Code

using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.WebSockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace KrakenCSharpExampleConsole
{
class Program
{
static async Task Main(string[] args)
{
//TODO: UPDATE WITH YOUR KEYS :)
string apiPublicKey = "YOUR_PUBLIC_KEY";
string apiPrivateKey = "YOUR_PRIVATE_KEY";

try
{
System.Console.WriteLine("|=========================================|");
System.Console.WriteLine("| KRAKEN.COM C# TEST APP |");
System.Console.WriteLine("|=========================================|");
System.Console.WriteLine();

#region Public REST API Examples

if(1 == 0)
{
string publicResponse = "";

string publicEndpoint = "SystemStatus";
string publicInputParameters = "";

//MORE PUBLIC REST EXAMPLES
//*

//string publicEndpoint = "AssetPairs";
//string publicInputParameters = "pair=ethusd,xbtusd";

//string publicEndpoint = "Ticker";
//string publicInputParameters = "pair=ethusd";

//string publicEndpoint = "Trades";
//string publicInputParameters = "pair=ethusd&since=0";

//*

publicResponse = await QueryPublicEndpoint(publicEndpoint, publicInputParameters);
System.Console.WriteLine(publicResponse);

}

#endregion

#region Private REST API Examples

if(1 == 0)
{
string privateResponse = "";

string privateEndpoint = "Balance";
string privateInputParameters = "";

//MORE PRIVATE REST EXAMPLES
//*

//string privateEndpoint = "AddOrder";
//string privateInputParameters = "pair=xbteur&type=buy&ordertype=limit&price=1.00&volume=1";

//string privateEndpoint = "AddOrder"
//string privateInputParameters = "pair=xdgeur&type=sell&ordertype=limit&volume=3000&price=%2b10.0%" //Positive Percentage Example (%2 represtes +, which is a reseved character in HTTP)

//string privateEndpoint = "AddOrder"
//string privateInputParameters = "pair=xdgeur&type=sell&ordertype=limit&volume=3000&price=-10.0%" //Negative Percentage Example

//string privateEndpoint = "AddOrder"
//string privateInputParameters = "pair=xdgeur&type=buy&ordertype=market&volume=3000&userref=789" //Userref Example

//string privateEndpoint = "Balance" //{"error":[]} IS SUCCESS, Means EMPTY BALANCE
//string privateInputParameters = ""

//string privateEndpoint = "QueryOrders"
//string privateInputParameters = "txid=OFUSL6-GXIIT-KZ2JDJ"

//string privateEndpoint = "AddOrder"
//string privateInputParameters = "pair=xdgusd&type=buy&ordertype=market&volume=5000"

//string privateEndpoint = "DepositAddresses"
//string privateInputParameters = "asset=xbt&method=Bitcoin"

//string privateEndpoint = "DepositMethods"
//string privateInputParameters = "asset=eth"

//string privateEndpoint = "WalletTransfer"
//string privateInputParameters = "asset=xbt&to=Futures Wallet&from=Spot Wallet&amount=0.0045"

//string privateEndpoint = "TradesHistory"
//string privateInputParameters = "start=1577836800&end=1609459200"

//string privateEndpoint = "GetWebSocketsToken"
//string privateInputParameters = ""

//*


privateResponse = await QueryPrivateEndpoint(privateEndpoint,
privateInputParameters,
apiPublicKey,
apiPrivateKey);
System.Console.WriteLine(privateResponse);

}

#endregion

#region Public WebSocket API Examples

if(1 == 0)
{
string publicWebSocketURL = "wss://ws.kraken.com/";
string pulbicWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"ticker\"}, \"pair\": [ \"XBT/EUR\",\"ETH/USD\" ]}";

//MORE PRUBLIC WEBSOCKET EXAMPLES
//*

//string pulbicWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"interval\": 1440, \"name\": \"ohlc\"}, \"pair\": [ \"XBT/EUR\"]}";

//string pulbicWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"spread\"}, \"pair\": [ \"XBT/EUR\",\"ETH/USD\" ]}";

//*

await OpenAndStreamWebSocketSubscription(publicWebSocketURL, pulbicWebSocketSubscriptionMsg);

}

#endregion

#region Private WebSocket API Examples

if(1 == 0)
{
string privateWebSocketURL = "wss://ws-auth.kraken.com/";

//GET AND EXTRACT THE WEBSOCKET TOKEN FORM THE JSON RESPONSE
string webSocketRestResponseJSON = await QueryPrivateEndpoint("GetWebSocketsToken", "", apiPublicKey, apiPrivateKey);

var splits = webSocketRestResponseJSON.Split( new string[] { "\"token\":\"", "\"}}" }, StringSplitOptions.None );
string webSocketToken = splits[1];

string privateWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"ownTrades\", \"token\": \"#TOKEN#\"}}";

//MORE PRIVATE WEBSOCKET EXAMPLES
//*

//#TOKEN# IS A PLACEHOLDER

//string privateWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"openOrders\", \"token\": \"#TOKEN#\"}}";

//string privateWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"balances\", \"token\": \"#TOKEN#\"}}";

//string addOrderExample = "{\"event\":\"addOrder\",\"reqid\":1234,\"ordertype\":\"limit\",\"pair\":\"XBT/EUR\",\"token\":\"#TOKEN#\",\"type\":\"buy\",\"volume\":\"1\", \"price\":\"1.00\"}";

//*

//REPLACE PLACEHOLDER WITH TOKEN
privateWebSocketSubscriptionMsg = privateWebSocketSubscriptionMsg.Replace("#TOKEN#", webSocketToken);
await OpenAndStreamWebSocketSubscription(privateWebSocketURL, privateWebSocketSubscriptionMsg);

}

#endregion

System.Console.WriteLine();
System.Console.WriteLine("|=========================================|");
System.Console.WriteLine("| END OF PROGRAM, HAVE A NICE DAY :) |");
System.Console.WriteLine("|=========================================|");
System.Console.WriteLine();
}
catch(Exception e)
{
System.Console.WriteLine();
System.Console.WriteLine("AN EXCEPTION OCCURED :(");
System.Console.WriteLine(e.ToString());
}

}

#region Public REST API Endpoints

private static async Task<string> QueryPublicEndpoint(string endpointName, string inputParameters)
{
string jsonData;
string baseDomain = "https://api.kraken.com";
string publicPath = "/0/public/";
string apiEndpointFullURL = baseDomain + publicPath + endpointName + "?" + inputParameters;
using(HttpClient client = new HttpClient())
{
jsonData = await client.GetStringAsync(apiEndpointFullURL);
}
return jsonData;
}

#endregion

#region Private REST API Endpoints

private static async Task<string> QueryPrivateEndpoint(string endpointName,
string inputParameters,
string apiPublicKey,
string apiPrivateKey)
{
string baseDomain = "https://api.kraken.com";
string privatePath = "/0/private/";

string apiEndpointFullURL = baseDomain + privatePath + endpointName;
string nonce = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
if(string.IsNullOrWhiteSpace(inputParameters) == false)
{
inputParameters = "&" + inputParameters;
}
string apiPostBodyData = "nonce=" + nonce + inputParameters;
string signature = CreateAuthenticationSignature(apiPrivateKey,
privatePath,
endpointName,
nonce,
inputParameters);
string jsonData;
using(HttpClient 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;
}

return jsonData;
}

#endregion

#region Authentication Algorithm

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

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(string apiPrivateKey,
byte[] sha256Hash,
string apiPath,
string endpointName,
string nonce,
string inputParams)
{

string apiEndpointPath = apiPath + 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;
}

#endregion

#region WebSocket API

private static async Task OpenAndStreamWebSocketSubscription(string connectionURL, string webSocketSubscription)
{
try
{
ClientWebSocket webSocketClient = new ClientWebSocket();
CancellationTokenSource stoppingToken = new CancellationTokenSource();

//OPEN CONNECTION
await webSocketClient.ConnectAsync(new Uri(connectionURL), CancellationToken.None);
System.Console.WriteLine("WEBSOCKET CONNECTION OPEN!");

//SEND SUBSCRIPTION MESSAGE
System.Console.WriteLine("WEBSOCKET SUBSCRIPTION MESSAGE:");
System.Console.WriteLine(webSocketSubscription);
if (webSocketClient.State == WebSocketState.Open)
{
await webSocketClient.SendAsync(Encoding.UTF8.GetBytes(webSocketSubscription),
WebSocketMessageType.Text,
true,
stoppingToken.Token);
}

//RECEIVE AND PRINT MESSAGE
do
{
await ReceiveMessage(webSocketClient, stoppingToken.Token);
} while(webSocketClient.State == WebSocketState.Open);

//CLOSE CONNECTION
await webSocketClient.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "", stoppingToken.Token);
}
catch (OperationCanceledException)
{
//DO NOTHING - ASSUME WAS REQUESTED
}
catch(Exception ex)
{
throw ex;
}
}

private static async Task ReceiveMessage(ClientWebSocket socket, CancellationToken stoppingToken)
{
var buffer = new ArraySegment<byte>(new byte[2048]);
while (!stoppingToken.IsCancellationRequested)
{

WebSocketReceiveResult result;
using (var ms = new MemoryStream())
{
do
{
result = await socket.ReceiveAsync(buffer, stoppingToken);
ms.Write(buffer.Array, buffer.Offset, result.Count);
} while (!result.EndOfMessage);

if (result.MessageType == WebSocketMessageType.Close)
{
break;
}

string wsMsg = "";
ms.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(ms, Encoding.UTF8))
{
wsMsg = await reader.ReadToEndAsync();
}
string msgTime = DateTime.Now.ToString("dd-MMM-yyyy HH:mm:ss") + ": ";
System.Console.WriteLine(msgTime + wsMsg);
}
};
}

#endregion

}
}