rokj
Newbie
Offline
Activity: 26
Merit: 0
|
|
February 19, 2012, 03:45:36 PM Last edit: April 17, 2012, 08:26:21 AM by rokj |
|
|
|
|
|
rokj
Newbie
Offline
Activity: 26
Merit: 0
|
|
February 22, 2012, 11:24:37 AM Last edit: February 22, 2012, 05:22:18 PM by rokj |
|
Following seems to work. params = [(u"nonce", self._create_nonce())] headers = {'Rest-Key': key, 'Rest-Sign': base64.b64encode(str(hmac.new(base64.b64decode(secret), urllib.urlencode(params), hashlib.sha512).digest())), 'Content-type': 'application/x-www-form-urlencoded', 'Accept': 'application/json, text/javascript, */*; q=0.01', 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'} http_pool = urllib3.connection_from_url(url) response = http_pool.urlopen('POST', url, body=urllib.urlencode(params), headers=headers)
print response.status, response.data
For some reason I could not get it working with MtGox APIv1 with other than with urllib3:
|
|
|
|
TheStig
Member
Offline
Activity: 105
Merit: 10
|
|
March 29, 2012, 01:18:13 AM |
|
A newbie wanted to post this https://bitcointalk.org/index.php?topic=74530.0 I found this thread to be extremely helpful, so I'm returning the favor by posting an improved and simplified version of the code. Unfortunately, my forum account is limited to the Newbie section. Mods, please move this post to the thread above. from hashlib import sha512 from hmac import HMAC from base64 import b64decode, b64encode from urllib import urlencode
from time import time
import requests
class MTGox: def __init__(self, key, secret, base): self.key = key self.secret = b64decode(secret) self.base = base
def query(self, path, args={}): args['nonce'] = int(time()*100000) headers = { 'User-Agent': 'BitcoinTalk', 'Rest-Key': self.key, 'Rest-Sign': b64encode(str(HMAC(self.secret, urlencode(args), sha512).digest())) } r = requests.post(self.base + path, data=args, headers=headers) print r.text
|
|
|
|
Red Emerald
|
|
April 01, 2012, 07:17:09 AM Last edit: April 01, 2012, 07:28:07 AM by Red Emerald |
|
args is a dict. args = {"someparameter": "value of the parameter"}, thats why it does not work.
As much as I like python, but one has to admit that languages that use static typing do have certain advantages. A simple if check or catch TypeError would be all that is needed to make a nice error message. Static typing isn't needed for that. And also, Adding Optional Static Typing to PythonAlso, cython does allow setting types.
|
|
|
|
Takkun
Newbie
Offline
Activity: 12
Merit: 0
|
|
April 03, 2012, 08:07:57 PM |
|
Here is a full API v0 example using the authentication code posted earlier, if anyone is interested... It's only missing withdraw, btcAddress, and history_[CUR]. from urllib import urlencode import urllib2 import time from hashlib import sha512 from hmac import HMAC import base64 import json from pprint import pprint
class MtGox: def __init__(self): self.key = 'x' self.secret = 'x' self.auth = Authenticate(self.key,self.secret)
def getTrades(self, since): path = "getTrades.php" args = {'since': since} return self.auth.run(path,args) def getDepth(self): path = "data/getDepth.php" args = {'Currency': 'USD'} return self.auth.run(path,args) def getFunds(self): path = "getFunds.php" args = {} return self.auth.run(path,args) def buyBTC(self, amount, price): path = "buyBTC.php" args = {'amount': amount, 'price': price, 'Currency':'USD'} return self.auth.run(path,args) def sellBTC(self, amount, price): path = "sellBTC.php" args = {'amount': amount, 'price': price, 'Currency':'USD'} return self.auth.run(path,args) def getOrders(self): path = "getOrders.php" args = {} return self.auth.run(path,args) def cancelOrder(self, oid, type): path = "cancelOrder.php" args = {'oid': oid, 'type': type} return self.auth.run(path,args) def redeemCode(self, code): path = "redeemCode.php" args = {'code': code} return self.auth.run(path,args) def getInfo(self): path = "info.php" args = {} return self.auth.run(path,args) def getTicker(self): path = "data/ticker.php" args = {} return self.auth.run(path,args) def printDic(self, dic): pprint(dic) #MtGox End
def get_nonce(): return int(time.time()*100000)
def sign_data(secret, data): return base64.b64encode(str(HMAC(secret, data, sha512).digest())) class Authenticate: def __init__(self, auth_key, auth_secret): self.auth_key = auth_key self.auth_secret = base64.b64decode(auth_secret) def build_query(self, req={}): req["nonce"] = get_nonce() post_data = urlencode(req) headers = {} headers["User-Agent"] = "GoxApi" headers["Rest-Key"] = self.auth_key headers["Rest-Sign"] = sign_data(self.auth_secret, post_data) return (post_data, headers) def run(self, path, args): data, headers = self.build_query(args) req = urllib2.Request("https://mtgox.com/api/0/"+path, data, headers) res = urllib2.urlopen(req, data) return json.load(res) #Authenticate End
|
|
|
|
jago25_98
|
|
April 12, 2012, 03:27:45 AM |
|
appreciated. I'm actually a user looking for a command line method to do withdrawal codes,or at least a way to interact with arumxchange.
|
Bitcoiner since the early days. Crypto YouTube Channel: Trading Nomads | Analyst | News Reporter | Bitcoin Hodler | Support Freedom of Speech!
|
|
|
Nyx
|
|
April 13, 2012, 08:40:14 PM |
|
some newbie questions:
a) Why there is an API 0 and API 1. Will API 0 soon be deprecated?
b) Is there a bug in the getTrades-Function? The parameter "since" seems to be ignored... Or is there an error in the code of Takkun?
Thank you
|
- Einfach sicherer und schneller BTC-Handel über Bitcoin.de
|
|
|
kokjo
Legendary
Offline
Activity: 1050
Merit: 1000
You are WRONG!
|
|
April 13, 2012, 08:45:45 PM |
|
a) Why there is an API 0 and API 1. Will API 0 soon be deprecated?
i think so.
|
"The whole problem with the world is that fools and fanatics are always so certain of themselves and wiser people so full of doubts." -Bertrand Russell
|
|
|
029xue
Newbie
Offline
Activity: 24
Merit: 0
|
|
April 17, 2012, 08:07:53 AM |
|
Thanks for the code. However, when I try it, I always get the not logon error like below: {u'error': u'Must be logged in'} The code is like below: from urllib import urlencode import urllib2 import time from hashlib import sha512 from hmac import HMAC import base64 import json def get_nonce(): return int(time.time()*100000)
def sign_data(secret, data): return base64.b64encode(str(HMAC(secret, data, sha512).digest())) class requester: def __init__(self, auth_key, auth_secret): self.auth_key = auth_key self.auth_secret = base64.b64decode(auth_secret) def build_query(self, req={}): req["nonce"] = get_nonce() post_data = urlencode(req) headers = {} headers["User-Agent"] = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)" headers["Accept"] = "application/json" headers["Rest-Key"] = self.auth_key headers["Rest-Sign"] = sign_data(self.auth_secret, post_data) return (post_data, headers) def perform(self, path, args): data, headers = self.build_query(args) req = urllib2.Request("https://mtgox.com/api/0/"+path, data, headers) res = urllib2.urlopen(req, data) return json.load(res)
m = requester(auth_key=mykey, auth_secret = mysecret) print m.perform("info.php", {}) The wired thing is, when I using the C# code to communicate, it all works well. I checked the http headers and found there're a little difference: .NET header CONNECT mtgox.com:443 HTTP/1.1 Host: mtgox.com Connection: Keep-Alive
HTTP/1.1 200 Connection Established FiddlerGateway: Direct StartTime: 15:34:07.861 Connection: close
POST /api/0/info.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) Accept: application/json Rest-Key: fbbb66ba-5740-449d-a078-3d55752d82ed Rest-Sign: BE3pmUGjOPh4069XH4j28tw3RKd0HEZWIWoJ+gahIXR5Qn4T+rc+E2aN2L0WfUcx4ptzmfuhe9lqKtkJHE+nGQ== Host: mtgox.com Content-Length: 24 Expect: 100-continue Connection: Keep-Alive
HTTP/1.0 200 OK Date: Tue, 17 Apr 2012 07:34:09 GMT Server: Apache X-Powered-By: PHP/5.3.10 Set-Cookie: SESSION_ID=ff7f7d011f6321a87b6cdd93d27fb7e5; expires=Thu, 19-Apr-2012 07:34:09 GMT; path=/; domain=.mtgox.com; HttpOnly Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Strict-Transport-Security: max-age=1209600 Content-Length: 1253 nnCoection: close Content-Type: application/json Connection: Keep-Alive
Python header: CONNECT mtgox.com:443 HTTP/1.0 Host: mtgox.com:443
HTTP/1.0 200 Connection Established FiddlerGateway: Direct StartTime: 15:34:20.718 Connection: close
POST /api/0/info.php HTTP/1.1 Accept-Encoding: identity Rest-Sign: KV6aRCWoOSJbXMwY/c5hhlZ9GLsqxYfPMzvFWRV7KmrGCnL6dmp3mPAMNO3JCWDWfEFwAbMiCeUoUap7FIdewg== Content-Length: 21 Rest-Key: fbbb66ba-5740-449d-a078-3d55752d82ed Connection: close Accept: application/json User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) Host: mtgox.com Content-Type: application/x-www-form-urlencoded
HTTP/1.0 200 OK Date: Tue, 17 Apr 2012 07:34:23 GMT Server: Apache X-Powered-By: PHP/5.3.10 Set-Cookie: SESSION_ID=3e8b54b2e889b2516c87639d02252daf; expires=Thu, 19-Apr-2012 07:34:23 GMT; path=/; domain=.mtgox.com; HttpOnly Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Strict-Transport-Security: max-age=1209600 Content-Length: 29 Connection: close Content-Type: application/json
The only difference is that:https://public.sn2.livefilestore.com/y1pvy4eqYCVgTia_7dDcpCIVy4wQ9-xxLR-VcM-NBvt1cGxzqiv7V2ijeAgimnTpXKXykAjrJlHo9Oz8DMasUL23g/123.png?psid=1I guess it may related with the connection type, but I'm new to Python and have no idea how to control it... (why there're dozens of http lib exist in Python Any help is appreciate!
|
|
|
|
rokj
Newbie
Offline
Activity: 26
Merit: 0
|
|
April 17, 2012, 08:27:43 AM |
|
Thanks for the code. However, when I try it, I always get the not logon error like below: {u'error': u'Must be logged in'} The code is like below: from urllib import urlencode import urllib2 import time from hashlib import sha512 from hmac import HMAC import base64 import json def get_nonce(): return int(time.time()*100000)
def sign_data(secret, data): return base64.b64encode(str(HMAC(secret, data, sha512).digest())) class requester: def __init__(self, auth_key, auth_secret): self.auth_key = auth_key self.auth_secret = base64.b64decode(auth_secret) def build_query(self, req={}): req["nonce"] = get_nonce() post_data = urlencode(req) headers = {} headers["User-Agent"] = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)" headers["Accept"] = "application/json" headers["Rest-Key"] = self.auth_key headers["Rest-Sign"] = sign_data(self.auth_secret, post_data) return (post_data, headers) def perform(self, path, args): data, headers = self.build_query(args) req = urllib2.Request("https://mtgox.com/api/0/"+path, data, headers) res = urllib2.urlopen(req, data) return json.load(res)
m = requester(auth_key=mykey, auth_secret = mysecret) print m.perform("info.php", {}) The wired thing is, when I using the C# code to communicate, it all works well. I checked the http headers and found there're a little difference: .NET header CONNECT mtgox.com:443 HTTP/1.1 Host: mtgox.com Connection: Keep-Alive
HTTP/1.1 200 Connection Established FiddlerGateway: Direct StartTime: 15:34:07.861 Connection: close
POST /api/0/info.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) Accept: application/json Rest-Key: fbbb66ba-5740-449d-a078-3d55752d82ed Rest-Sign: BE3pmUGjOPh4069XH4j28tw3RKd0HEZWIWoJ+gahIXR5Qn4T+rc+E2aN2L0WfUcx4ptzmfuhe9lqKtkJHE+nGQ== Host: mtgox.com Content-Length: 24 Expect: 100-continue Connection: Keep-Alive
HTTP/1.0 200 OK Date: Tue, 17 Apr 2012 07:34:09 GMT Server: Apache X-Powered-By: PHP/5.3.10 Set-Cookie: SESSION_ID=ff7f7d011f6321a87b6cdd93d27fb7e5; expires=Thu, 19-Apr-2012 07:34:09 GMT; path=/; domain=.mtgox.com; HttpOnly Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Strict-Transport-Security: max-age=1209600 Content-Length: 1253 nnCoection: close Content-Type: application/json Connection: Keep-Alive
Python header: CONNECT mtgox.com:443 HTTP/1.0 Host: mtgox.com:443
HTTP/1.0 200 Connection Established FiddlerGateway: Direct StartTime: 15:34:20.718 Connection: close
POST /api/0/info.php HTTP/1.1 Accept-Encoding: identity Rest-Sign: KV6aRCWoOSJbXMwY/c5hhlZ9GLsqxYfPMzvFWRV7KmrGCnL6dmp3mPAMNO3JCWDWfEFwAbMiCeUoUap7FIdewg== Content-Length: 21 Rest-Key: fbbb66ba-5740-449d-a078-3d55752d82ed Connection: close Accept: application/json User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) Host: mtgox.com Content-Type: application/x-www-form-urlencoded
HTTP/1.0 200 OK Date: Tue, 17 Apr 2012 07:34:23 GMT Server: Apache X-Powered-By: PHP/5.3.10 Set-Cookie: SESSION_ID=3e8b54b2e889b2516c87639d02252daf; expires=Thu, 19-Apr-2012 07:34:23 GMT; path=/; domain=.mtgox.com; HttpOnly Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Strict-Transport-Security: max-age=1209600 Content-Length: 29 Connection: close Content-Type: application/json
The only difference is that:https://public.sn2.livefilestore.com/y1pvy4eqYCVgTia_7dDcpCIVy4wQ9-xxLR-VcM-NBvt1cGxzqiv7V2ijeAgimnTpXKXykAjrJlHo9Oz8DMasUL23g/123.png?psid=1I guess it may related with the connection type, but I'm new to Python and have no idea how to control it... (why there're dozens of http lib exist in Python Any help is appreciate! Had "similar" problems. First, use APIv1 and for some reason I got it working only with urllib3. See: https://bitcointalk.org/index.php?topic=49789.msg762709#msg762709.
|
|
|
|
029xue
Newbie
Offline
Activity: 24
Merit: 0
|
|
April 17, 2012, 10:05:54 AM |
|
I just tried it. However, the result is same: import urllib, time, hashlib, hmac, base64, urllib3
def _create_nonce(): return int(time.time()*100000)
url = "https://mtgox.com/api/0/info.php" params = [(u"nonce", _create_nonce())] headers = {'Rest-Key': key, 'Rest-Sign': base64.b64encode(str(hmac.new(base64.b64decode(secret), urllib.urlencode(params), hashlib.sha512).digest())), 'Content-type': 'application/x-www-form-urlencoded', 'Accept': 'application/json, text/javascript, */*; q=0.01', 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'} http_pool = urllib3.connection_from_url(url) response = http_pool.urlopen('POST', url, body=urllib.urlencode(params), headers=headers)
print response.status, response.data
200 {"error":"Must be logged in"}
May be because I'm under in proxy, but why .NET code work well? It's all in same machine...
|
|
|
|
|
029xue
Newbie
Offline
Activity: 24
Merit: 0
|
|
April 17, 2012, 11:56:47 AM |
|
Dose the code work on you side? If so, I may need start investigate my network problem instead of code... I got this "403 {"result":"error","error":"Identification required to access private API","token":"login_required"}" when try https://mtgox.com/api/1/generic/private/orders using POST. Thanks very much!
|
|
|
|
rokj
Newbie
Offline
Activity: 26
Merit: 0
|
|
April 17, 2012, 02:16:07 PM |
|
Dose the code work on you side? If so, I may need start investigate my network problem instead of code... I got this "403 {"result":"error","error":"Identification required to access private API","token":"login_required"}" when try https://mtgox.com/api/1/generic/private/orders using POST. Thanks very much! Yes, I am using https://github.com/rokj/bitcoin_dealer/, you probably copied wrong key or missed something out.
|
|
|
|
029xue
Newbie
Offline
Activity: 24
Merit: 0
|
|
April 20, 2012, 01:10:56 PM |
|
Thanks for your help. Your code is working and I finally find out the reason My .NET code generate nonce like this: string parameters = "nonce=" + DateTime.Now.Ticks.ToString(); it'll generate a 18 length value like 634705522019762907 In Python code, it generate nonce like this: string parameters = "nonce=" + DateTime.Now.Ticks.ToString(); which will generate 16 length value like 133492738213800 In like case, as it always smaller than the last .NET nonce in one account, then MtGox regards it as invalid and can't get authorization. I simply added more zero to " int(time.time()*1000000000)" and it then works. (or If I using one account for Python only, then it have no such problem also.) Again, thanks for your code
|
|
|
|
rokj
Newbie
Offline
Activity: 26
Merit: 0
|
|
April 20, 2012, 08:25:09 PM |
|
Thanks for your help. Your code is working and I finally find out the reason My .NET code generate nonce like this: string parameters = "nonce=" + DateTime.Now.Ticks.ToString(); it'll generate a 18 length value like 634705522019762907 In Python code, it generate nonce like this: string parameters = "nonce=" + DateTime.Now.Ticks.ToString(); which will generate 16 length value like 133492738213800 In like case, as it always smaller than the last .NET nonce in one account, then MtGox regards it as invalid and can't get authorization. I simply added more zero to " int(time.time()*1000000000)" and it then works. (or If I using one account for Python only, then it have no such problem also.) Again, thanks for your code No problem! Argh ... and totally forgot to write this frustration with nonce also (have had same problems when doing it in PHP and then in Python). Bold your message or something, I am sure someone else will also have the same experience in the future.
|
|
|
|
|