csharp/aabiryukov/CryptoMarketApi/Api/BtcChinaApi/BTCChinaAPI.cs

BTCChinaAPI.cs
using System;
using System.Globalization;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.IO;
//using System.Runtime.Serialization.Json;//for NET 3.5, astembly System.ServiceModel.Web; for NET 4.0+, astembly System.Runtime.Serialization
//using System.Security.Cryptography.X509Certificates;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;


namespace BTCChina
{
    public sealed clast BTCChinaAPI
    {
		private static clast WebApi
		{
			private static readonly HttpClient st_client = new HttpClient{ Timeout = TimeSpan.FromSeconds(4) };

			static HttpClient Client { get { return st_client; } }

			public static string Query(string url)
			{
				var resultString = Client.GetStringAsync(url).Result;
				return resultString;
			}
		}

        private readonly string accessKey;
	    private readonly string secretKey;
	    //constants
        private const int BTCChinaConnectionLimit = 1;

		private const string apiHost = "api.btcc.com";
		private const string url = "https://" + apiHost + "/api_trade_v1.php";
        //for cheap access to jParams
        private const string pTonce = "tonce";
        private const string pAccessKey = "accesskey";
        private const string pRequestMethod = "requestmethod";
        private const string pId = "id";
        private const string pMethod = "method";
        private const string pParams = "params";

        private static readonly DateTime genesis = new DateTime(1970, 1, 1);
        // private static readonly Object methodLock = new Object();//protect DoMethod()
        private static readonly Random jsonRequestID = new Random();
		private readonly object m_tonceLock = new object();

        //attributes-like enums for static stringcollection eunmerate
        public enum MarketType { BTCCNY = 0, LTCCNY, LTCBTC, ALL };
        public enum CurrencyType { BTC = 0, LTC };
        public enum TransactionType { all = 0, fundbtc, withdrawbtc, fundmoney, withdrawmoney, refundmoney, buybtc, sellbtc, buyltc, sellltc, tradefee, rebate };


		public static Ticker GetTicker()
		{
			const string queryStr = "https://" + apiHost + "/data/ticker?market=btccny";
			var response = WebApi.Query(queryStr);
			var jobj = JObject.Parse( response );
			return Ticker.ReadFromJObject(jobj["ticker"]);
		}

		public static List GetTrades()
		{
			const string queryStr = "https://" + apiHost + "/data/trades";
			var json = WebApi.Query(queryStr);
			var list = JsonConvert.DeserializeObject(json);
			return list;
		}

		public static List GetTradeHistory(int limit)
		{
			var queryStr = string.Format(CultureInfo.InvariantCulture, "https://" + apiHost + "/data/historydata?limit={0}", limit);
			var json = WebApi.Query(queryStr);
			var list = JsonConvert.DeserializeObject(json);
			return list;
		}

	    public static OrderBook GetOrderBook()
	    {
		    return GetOrderBook(20);
	    }

		public static OrderBook GetOrderBook(int limit)
		{
			var queryStr = string.Format(CultureInfo.InvariantCulture, "https://" + apiHost + "/data/orderbook?limit={0}", limit);
			var json = WebApi.Query(queryStr);
			var book = JsonConvert.DeserializeObject(json);
			return book;
		}

        /// 
        /// Unique ctor sets access key and secret key, which cannot be changed later.
        /// 
        /// Your Access Key
        /// Your Secret Key
        public BTCChinaAPI(string access_key, string secret_key)
        {
            accessKey = access_key;
            secretKey = secret_key;
            // HttpWebRequest setups
            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; //for https
            ServicePointManager.DefaultConnectionLimit = BTCChinaConnectionLimit; //one concurrent connection is allowed for this server atm.
            //ServicePointManager.UseNagleAlgorithm = false;
        }

        /// 
        /// Place a buy/sell order.
        /// 
        /// The price in quote currency to buy 1 base currency. Negative value to buy/sell at market price
        /// The amount of LTC/BTC to buy/sell. Negative value to sell, while positive value to buy
        /// Default is "BTCCNY". [ BTCCNY | LTCCNY | LTCBTC ]
        /// Order id.
        public int PlaceOrder(double price, double amount, MarketType market)
        {
            string regPrice = "", regAmount = "", method = "", mParams = "";
            switch (market)
            {
                case MarketType.BTCCNY:
					regPrice = price.ToString("F2", CultureInfo.InvariantCulture);
					regAmount = amount.ToString("F4", CultureInfo.InvariantCulture);
                    break;
                case MarketType.LTCCNY:
					regPrice = price.ToString("F2", CultureInfo.InvariantCulture);
					regAmount = amount.ToString("F3", CultureInfo.InvariantCulture);
                    break;
                case MarketType.LTCBTC:
					regPrice = price.ToString("F4", CultureInfo.InvariantCulture);
					regAmount = amount.ToString("F3", CultureInfo.InvariantCulture);
                    break;
                default://"ALL" is not supported
                    throw new BTCChinaException("PlaceOrder", "N/A", "Market not supported.");
            }
            if (regPrice.StartsWith("-", StringComparison.Ordinal))
                regPrice = "null";
			if (regAmount.StartsWith("-", StringComparison.Ordinal))
            {
                regAmount = regAmount.TrimStart('-');
                method = "sellOrder2";
            }
            else
            {
                method = "buyOrder2";
            }

//          mParams = regPrice + "," + regAmount;
            mParams = "\"" + regPrice + "\",\"" + regAmount + "\"";
            //not default market
            if (market != MarketType.BTCCNY)
                mParams += ",\"" + System.Enum.GetName(typeof(MarketType), market) + "\"";

            var response = DoMethod(BuildParams(method, mParams));
	        var jsonObject = JObject.Parse(response);
	        var orderId = jsonObject.Value("result");

	        return orderId;
        }

        /// 
        /// Cancel an active order if the status is 'open'.
        /// 
        /// The order id to cancel.
        /// Default is "BTCCNY". [ BTCCNY | LTCCNY | LTCBTC ]
        /// true or false depending on the result of cancellation.
        public bool cancelOrder(int orderID, MarketType market=MarketType.BTCCNY)
        {
            const string method = "cancelOrder";
            string mParams = orderID.ToString(CultureInfo.InvariantCulture);
            //all is not supported
            if (market == MarketType.ALL)
                throw new BTCChinaException(method, "N/A", "Market:ALL is not supported.");
            //not default market
            if (market != MarketType.BTCCNY)
                mParams += ",\"" + System.Enum.GetName(typeof(MarketType), market) + "\"";

            var response = DoMethod(BuildParams(method, mParams));
			var jsonObject = JObject.Parse(response);
			var success = jsonObject.Value("result");

	        return success;
        }


// ReSharper disable once ClastNeverInstantiated.Local
		private clast GetAccountInfoResult
		{
			[JsonProperty("result", Required = Required.Always)]
			public AccountInfo Result { get; private set; }
		}

        /// 
        /// Get stored account information and user balance.
        /// 
        /// objects profile, balance and frozen in JSON
        public AccountInfo getAccountInfo()
        {
            const string method = "getAccountInfo";
            var response = DoMethod(BuildParams(method, ""));
			var obj = JsonConvert.DeserializeObject(response);
	        return obj.Result;
        }

        /// 
        /// Get all user deposits.
        /// 
        /// [ BTC | LTC ]
        /// Default is 'true'. Only open(pending) deposits are returned.
        /// JSON-string of deposit or withdrawal objects
        public string getDeposits(CurrencyType currency, bool pendingonly = true)
        {
            const string method = "getDeposits";
            string mParams = "\"" + System.Enum.GetName(typeof(CurrencyType), currency) + "\"";
            if (!pendingonly)
                mParams += "," + pendingonly.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
            return DoMethod(BuildParams(method, mParams));
        }

		/// 
        /// Get all user withdrawals.
        /// 
        /// [ BTC | LTC ]
        /// Default is 'true'. Only open(pending) deposits are returned.
        /// JSON-string of deposit or withdrawal objects
        public string getWithdrawals(CurrencyType currency, bool pendingonly = true)
        {
            const string method = "getWithdrawals";
            string mParams = "\"" + System.Enum.GetName(typeof(CurrencyType), currency) + "\"";
            if (!pendingonly)
				mParams += "," + pendingonly.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
            return DoMethod(BuildParams(method, mParams));
        }

        /// 
        /// Get the complete market depth. 
        /// 
        /// Number of orders returned. Default is 10 per side
        /// Default to “BTCCNY”. [ BTCCNY | LTCCNY | LTCBTC | ALL]
        /// All open bid and ask orders.
        public string getMarketDepth(uint limit = 10, MarketType markets = MarketType.BTCCNY)
        {
            const string method = "getMarketDepth2";
            string mParams = "";
			if (limit != 10) mParams = limit.ToString(CultureInfo.InvariantCulture);
            if (markets != MarketType.BTCCNY)
                mParams += ",\"" + System.Enum.GetName(typeof(MarketType), markets) + "\"";
            return DoMethod(BuildParams(method, mParams));
        }

        /// 
        /// Get withdrawal status.
        /// 
        /// The withdrawal id.
        /// Default is “BTC”. Can be [ BTC | LTC ]
        /// JSON-string of withdrawal object
        public string getWithdrawal(int withdrawalID, CurrencyType currency = CurrencyType.BTC)
        {
            const string method = "getWithdrawal";
			string mParams = withdrawalID.ToString(CultureInfo.InvariantCulture);
            if (currency != CurrencyType.BTC)
                mParams += ",\"" + System.Enum.GetName(typeof(CurrencyType), currency) + "\"";//should be "LTC" but for further implmentations
            return DoMethod(BuildParams(method, mParams));
        }

        /// 
        /// Make a withdrawal request. BTC withdrawals will pick last used withdrawal address from user profile.
        /// 
        /// Currency short code, [BTC | LTC ].
        /// Amount to withdraw.
        /// Returns the withdrawal id
        public string requestWithdrawal(CurrencyType currency, double amount)
        {
            if (amount