For fun (and to teach myself some C#) I've been integrating someone's C# socket.io class with MtGox's API. I can currently recieve and parse all the public information (trades, depth, ticker, lag). That's all peachy. My issue is with authenticated requests. I've been trying to follow along and convert the code example listed at
https://en.bitcoin.it/wiki/MtGox/API/Streaming. Here's the part I'm interested in replicating:
$nonce = explode(' ', microtime(false));
$nonce = $nonce[1].substr($nonce[0], 2, 6);
$id = md5($nonce); // id can be anything to recognize this call
$query = array('call' => $call, 'params' => $params, 'item' => $item, 'currency' => $currency, 'id' => $id, 'nonce' => $nonce);
$query = json_encode($query);
// generate signature
$sign = hash_hmac('sha512', $query, base64_decode($apiSecret), true);
// prefix signature to query
$query = pack('H*', str_replace('-','',$apiKey)).$sign.$query;
// send query
$call = array('op' => 'call', 'call' => base64_encode($query), 'id' => $id, 'context' => 'mtgox.com');
// $call can now be pushed out to the websocket
Essentially what happens is once I try to make the authenticated call, my socket immediately drops connection. I do have try/catch all over the place (including some added to the socket.io and websocket classes I aquired) but it doesn't seem to be causing any errors, and no op:remark comes back from the server. It just dies. Poof. gonzo. Dead as a doornail.
So now in order to try and reclaim what little sanity I may have left, I'm asking for some advice. Yes, I do realize I could just flip to another language and all is good, but I'm trying to pick up C# for my day-job.
I believe that my JSON is well-formed, but I think my issue with the code lies within the encoding/hashing algorithms.
The call I'm specifically trying to make is to "private/info". Here is what I have for each encoded/decoded/hashed value:
$ID:
string nonce = DateTime.Now.Ticks.ToString();
string id = Encoding.UTF8.GetString(md5Hash.ComputeHash(Encoding.UTF8.GetBytes(nonce)))
$SIGN:
protected string EncodeSign(string query)
{
var hmacsha512 = new HMACSHA512(Convert.FromBase64String(this.apiSecret));
var byteArray = hmacsha512.ComputeHash( Encoding.UTF8.GetBytes(query));
return Encoding.UTF8.GetString(byteArray);
}
$KEY:
string key = HexToString(apiKey.Replace("-", ""));
protected string HexToString(string hex)
{
var buffer = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length; i += 2)
{
string hexdec = hex.Substring(i, 2);
buffer[i / 2] = byte.Parse(hexdec, NumberStyles.HexNumber);
}
return Encoding.UTF8.GetString(buffer);
}
$QUERY (the pack() line, not the json_encode line)
encQuery = key + encQuery + sb.ToString(); //sb is a StringBuilder object containing the inner query (equivalent of the $query = json_encode($query); line in the PHP example)
System.Convert.ToBase64String(Encoding.UTF8.GetBytes(encQuery)) //This is used in the same way as "base64_encode($query)" in the last line of the PHP example).
Does anyone see an issue with my encoding off the top of their head? Any help is appreciated.