Example code for C# REST and WebSocket API
- •
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
Bash
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
// 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";
// string privateInputParameters = ""; //{"error":[]} IS SUCCESS, Means EMPTY BALANCE
// 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 publicWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"ticker\"}, \"pair\": [ \"XBT/EUR\",\"ETH/USD\" ]}";
// MORE PUBLIC WEBSOCKET EXAMPLES
// *
// string publicWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"interval\": 1440, \"name\": \"ohlc\"}, \"pair\": [ \"XBT/EUR\"]}";
// string publicWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"spread\"}, \"pair\": [ \"XBT/EUR\",\"ETH/USD\" ]}";
// *
await OpenAndStreamWebSocketSubscription(publicWebSocketURL, publicWebSocketSubscriptionMsg);
}
#endregion
#region Private WebSocket API Examples
if (1 == 0)
{
string privateWebSocketURL = "wss://ws-auth.kraken.com/";
// GET AND EXTRACT THE WEBSOCKET TOKEN FROM 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 OCCURRED :(");
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))
{
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
}
}
Introduction
Installation
C# Code