Bitcoin Forum
September 13, 2024, 06:20:15 PM *
News: Latest Bitcoin Core release: 27.1 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Problems Connecting to MtGox API 2 with Python  (Read 749 times)
chops228 (OP)
Newbie
*
Offline Offline

Activity: 2
Merit: 0


View Profile
April 28, 2013, 03:11:48 PM
 #1

Hey guys, I am writing a trading program that I need to connect to MtGox through the API v2. But I keep getting the following error:
URL: https://data.mtgox.com/api/2/BTCUSD/money/bitcoin/address
HTTP Error 403: Forbidden


I have contacted MtGox to make sure my account has the proper API access, and it does. I have created a couple different API keys, so I know I'm using the correct key + secret combination. The nonce is generated from the current time, so I know I have an ever increasing nonce. I'm relatively certain none of these items are an issue.

I got my python script from:
http://pastebin.com/aXQfULyq

I modified that code a little bit to fit Python 3.3. However, I had to create 'Rest-Sign' slightly different than in the above code. Here is what I have:
Code:
                    url = self.__url_parts + '2/' + path
                    api2postdatatohash = (path + chr(0) + post_data).encode('utf-8')          #new way to hash for API 2, includes path + NUL
                    ahmac = base64.b64encode(str(hmac.new(base64.b64decode(self.secret),api2postdatatohash,hashlib.sha512).digest()).encode('utf-8'))
               
                    # Create header for auth-requiring operations
                    header = {
                         "User-Agent": 'Arbitrater',
                         "Rest-Key": self.key,
                         "Rest-Sign": ahmac
                    }

For comparison, here is what the other guy had:
Code:
 
                    url = self.__url_parts + '2/' + path
                    api2postdatatohash = path + chr(0) + post_data          #new way to hash for API 2, includes path + NUL
                    ahmac = base64.b64encode(str(hmac.new(base64.b64decode(self.secret),api2postdatatohash,hashlib.sha512).digest()))
               
                    # Create header for auth-requiring operations
                    header = {
                         "User-Agent": 'genBTC-bot',
                          "Rest-Key": self.key,
                         "Rest-Sign": ahmac
                    }

Notice how on my code, I had I had to encode my string to utf-8? I'm wondering if that is what is causing me to get that forbidden error. I don't know how the other guy got away without changing to utf-8, because the script won't run if you try to pass a string to b64encode or hmac.

Does anyone see what I am doing wrong? Have any of you guys had the same problem? Any help is appreciated. Here is my full python script if it is helpful:
http://pastebin.com/9fY8Jv15
martinkou
Newbie
*
Offline Offline

Activity: 12
Merit: 0


View Profile
April 28, 2013, 07:20:54 PM
 #2

The other guy is most probably using Python 2.7 (or lower), where the str means byte string, not Unicode string as in Python 3.3.

If I were you I'd try changing the str() into a bytes() and remove the encode() at the end.

There're other parts of the auth logic that you haven't shown in your code though (and those might be wrong) - e.g. do you have a monotonically increasing nonce in the post message? Is the post message url-encoded?
chops228 (OP)
Newbie
*
Offline Offline

Activity: 2
Merit: 0


View Profile
April 28, 2013, 07:49:25 PM
 #3

I tried changing str() to bytes() and removing the encode at the end:

Code:
                    
                    url = self.__url_parts + '2/' + path
                    api2postdatatohash = (path + chr(0) + post_data).encode('utf-8')       #new way to hash for API 2, includes path + NUL
                   
                    ahmac = base64.b64encode(bytes(hmac.new(base64.b64decode(self.secret),api2postdatatohash,hashlib.sha512).digest()))

But no dice. That 'api2postdatatohash' is where I am putting in an increasing nonce, which is generated by:

Code:
                   nonce =  str(int(time.time()*1000)) + "000"
                   params += [(u'nonce',nonce)]                    #Note, params is empty at this point, so it just contains the nonce
                   post_data = urllib.parse.urlencode(params)

                   #So eventually that nonce makes its way to the 'api2postdatatohash'
                   #Path is the api page I am trying to connect to. In this case it is https://data.mtgox.com/api/2/BTCUSD/money/bitcoin/address
                   api2postdatatohash = (path + chr(0) + post_data).encode('utf-8')


So to answer your question, I'm pretty sure I am generated an ever increasing nonce and then url encoding it properly. Does that look right to you?
martinkou
Newbie
*
Offline Offline

Activity: 12
Merit: 0


View Profile
April 29, 2013, 01:35:45 AM
 #4

I can't spot any errors apart from that you seem to be mixing up Python 2.x with Python 3.x syntax (the u"" thing belongs to 2.x, all strings are automatically unicode in 3.x). The HMAC and the post data should be all correct. I thought the chr(0) might mess up Python's encode("utf-8") but it didn't.

What are you using to submit your request with? urllib.request.Request? Unlink Python 2.x, the urlopen() in Python 3.x doesn't submit your headers, you'd need to use the Request constructor instead. So if you're copying code from people using Python 2.x, you may end up not submitting your headers at all.
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!