Search code examples
c#restsharpcrypto.com-exchange-api

crypto.com exchange C# API - How to


crypto.com exchange API has close to no documentation available, at least for C#. I am trying to get as little as the account summary, and failing miserably. Can we try to have the right functions here for everybody to use?

Here is the doc link

Basically only 2 functions as per below, classes removed for simplification:

using Newtonsoft.Json;
using RestSharp;
using System.Security.Cryptography;
using System.Text;

namespace Crypto.Account
{
    internal class AccountSummary
    {
        private readonly string apiKey = "xxxxxx";
        private readonly string apiSecret = "xxxxx";
        private readonly string apiUrl = "https://api.crypto.com/v2/private/get-account-summary";        

        public AccountResponse GetAccountSummary()
        {
            var client = new RestClient();
            var request = new RestRequest(apiUrl, Method.Post);

            long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

            string sign = GetSignature(timestamp);

            var requestBody = new
            {
                id = 1,
                method = "private/get-account-summary",
                @params = new { },
                nonce = timestamp,
                api_key = apiKey,
                sig = sign
            };

            request.AddJsonBody(requestBody);

            var response = client.Execute(request);

            if (response.IsSuccessful)
            {
                //return JsonConvert.DeserializeObject<AccountResponse>(response.Content);
                return "hooray";
            }
            else
            {
                throw new Exception($"Error: {response.StatusCode}, {response.Content}");
            }
        }

        private string GetSignature(long timestamp)
        {
            string sigPayload = $"{apiKey}{timestamp}private/get-account-summary";
            using (var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(apiSecret)))
            {
                var hash = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(sigPayload));
                return BitConverter.ToString(hash).Replace("-", "").ToLower();
            }
        }

    }
}

I am getting either this:
10002 401 UNAUTHORIZED Not authenticated, or key/signature incorrect
or this
10003 401 IP_ILLEGAL IP address not whitelisted

What needs to be corrected? Any suggestions?


Solution

  • Here is the basic code to get a summary of your account from the Crypto.com exchange API. This serves as a foundation for expanding functionalities and should help get started.

    Class:

    using Newtonsoft.Json;
    using RestSharp;
    using System.Security.Cryptography;
    using System.Text;
    
    namespace Crypto.Account
    {
        internal class AccountSummary
        {
            private const string apiKey = "yourAPIkey";
            private const string apiSecret = "yourAPIsecret";
            private readonly string apiUrl = "https://api.crypto.com/v2/private/get-account-summary";
    
            public class AccountResponse
            {
                public int Id { get; set; }
                public string Method { get; set; } = string.Empty;
                public int Code { get; set; }
                public AccountResult? Result { get; set; }
            }
    
            public class AccountResult
            {
                public List<AccountBalance>? Accounts { get; set; }
            }
    
            public class AccountBalance
            {
                public decimal Available { get; set; }
                public decimal TotalBalance { get; set; }
                public string Currency { get; set; } = string.Empty;
            }
    
            public AccountResponse GetAccountSummary()
            {
                var client = new RestClient();
                var request = new RestRequest(apiUrl, Method.Post);
    
                long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                int id = 1;
    
                var requestBody = new
                {
                    id,
                    method = "private/get-account-summary",
                    @params = new { },
                    nonce = timestamp,
                    api_key = apiKey
                };
    
                string sign = GetSign(requestBody.method, id, timestamp);
                request.AddJsonBody(new
                {
                    requestBody.id,
                    requestBody.method,
                    requestBody.@params,
                    requestBody.nonce,
                    requestBody.api_key,
                    sig = sign
                });
    
                var response = client.Execute(request);
    
                if (response.IsSuccessful)
                {
                    var accountResponse = JsonConvert.DeserializeObject<AccountResponse>(response.Content);
                    if (accountResponse != null && accountResponse.Code == 0)
                    {
                        return accountResponse;
                    }
                    else
                    {
                        throw new Exception(accountResponse?.Method ?? "Unknown error occurred.");
                    }
                }
                else
                {
                    throw new Exception($"Error: {response.StatusCode}, {response.Content}");
                }
            }
    
            private string GetSign(string method, int id, long nonce)
            {
                string sigPayload = $"{method}{id}{apiKey}{nonce}";
                using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(apiSecret)))
                {
                    var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(sigPayload));
                    return BitConverter.ToString(hash).Replace("-", "").ToLower();
                }
            }
        }
    }
    
    

    MainWindow:

    <Window x:Class="Crypto.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:Crypto"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
        <Grid>
            <TextBlock x:Name="totalAssetTextBlock" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" FontSize="16"/>
            <DataGrid x:Name="balancesDataGrid" AutoGenerateColumns="False" HorizontalAlignment="Left" Margin="10,50,0,0" VerticalAlignment="Top" Height="500" Width="600">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Currency" Binding="{Binding Currency}" Width="*"/>
                    <DataGridTextColumn Header="Available" Binding="{Binding Available}" Width="*"/>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </Window>
    
    

    Code behind:

    using Crypto.Account;
    using System.Windows;
    
    namespace Crypto
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                LoadAccountSummaryAsync();
            }
    
            private async void LoadAccountSummaryAsync()
            {
                try
                {
                    AccountSummary accountSummary = new AccountSummary();
                    var summary = await Task.Run(() => accountSummary.GetAccountSummary());
    
                    if (summary != null && summary.Result != null)
                    {
                        balancesDataGrid.ItemsSource = summary.Result.Accounts;
                    }
                    else
                    {
                        MessageBox.Show("No data returned from the API.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
    }
    
    

    Feel free to add any improvements.