سؤال

I'm trying to authenticate with the MtGox.com WebSocket API and after a long while managed to complete the required "call" attribute of the JSON data. However, I realized that I was using Python 2 to run my codesample and the application the API is finally going to be implemented in is written in Python 3. When I tried to make it work in Python 3 I ran into a couple of problems I was unable to resolve despite several long attempts.

I also tried 2to3, but seems it doesn't have builtin fixers for these kinds of problems.

The API specification for authenticated API calls can be found here: https://en.bitcoin.it/wiki/MtGox/API/Streaming#Authenticated_commands

Here is the working Python 2 script I used for generating the JSON call which I then ran through a WebSocket console extension I found for Chrome.

import hashlib
import time
import hmac
import json
import base64
import binascii

apikey = ""
apisecret = ""

def _nonce():
    """produce a unique nonce that is guaranteed to be ever increasing"""
    microtime = int(time.time() * 1E6)
    return microtime

def _reqid(nonce):
    return hashlib.md5(str(nonce)).hexdigest()

def send_signed_call(api_endpoint, params):
    nonce = _nonce()
    reqid = _reqid(nonce)
    call = json.dumps({
        "id"       : reqid,
        "nonce"    : nonce,
        "call"     : api_endpoint,
        "params"   : params,
    })

    sign = hmac.new(base64.b64decode(apisecret), call, hashlib.sha512).digest()
    signedcall = apikey.replace("-", "").decode("hex") + sign + call

    return json.dumps({
        "op"      : "call",
        "call"    : base64.b64encode(signedcall),
        "id"      : reqid,
        "context" : "mtgox.com"
    })

msg = send_signed_call("private/info", {})
print(msg)

Some of the errors I ran into related to the no longer existing String.decode("hex"), I've had a few others but unfortunately I haven't kept track of all of them as I tried a great deal of different approaches. I also looked at codesamples of the same functionality in other languages but couldn't find any clue relating to the Python 3 problem. A lot seems to be having to do with changes made to bytes and strings encoding and decoding in Python 3.

Thanks a lot in advance!

هل كانت مفيدة؟

المحلول

Finally solved it!

Here is the working version of the send_signed_call function, enjoy:

def send_signed_call(api_endpoint, params):
    nonce = _nonce()
    reqid = _reqid(nonce)
    call = json.dumps({
        "id"       : reqid,
        "nonce"    : nonce,
        "call"     : api_endpoint,
        "params"   : params,
    })
    callByte = bytes(call, "utf-8")

    sign = hmac.new(base64.b64decode(api_secret), callByte, hashlib.sha512).digest()
    skey = bytes.fromhex(api_key.replace("-",""))

    signedcall = skey + sign + callByte
    return json.dumps({
        "op"      : "call",
        "call"    : base64.b64encode(signedcall).decode("utf-8"),
        "id"      : reqid,
        "context" : "mtgox.com"
    })

You guys have no idea how happy a panda I am right now!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top