BtcChinaApi
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