Bitcoin Forum
April 19, 2024, 11:08:24 PM *
News: Latest Bitcoin Core release: 26.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: 1 2 [All]
  Print  
Author Topic: Req: Python MtGox auth example  (Read 14495 times)
osmosis (OP)
Sr. Member
****
Offline Offline

Activity: 300
Merit: 250



View Profile
October 25, 2011, 06:37:56 AM
 #1

The wiki has a mtgox authentication example in PHP. Anyone out there have an example they can provide for python?  I have been trying to get goxsh.py to work with no luck.

https://en.bitcoin.it/wiki/MtGox/API
1713568104
Hero Member
*
Offline Offline

Posts: 1713568104

View Profile Personal Message (Offline)

Ignore
1713568104
Reply with quote  #2

1713568104
Report to moderator
"This isn't the kind of software where we can leave so many unresolved bugs that we need a tracker for them." -- Satoshi
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
kokjo
Legendary
*
Offline Offline

Activity: 1050
Merit: 1000

You are WRONG!


View Profile
October 25, 2011, 06:52:50 AM
 #2

Code:
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"] = "GoxApi"
        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)

"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
osmosis (OP)
Sr. Member
****
Offline Offline

Activity: 300
Merit: 250



View Profile
October 26, 2011, 05:36:27 AM
 #3

THANKS!
kokjo
Legendary
*
Offline Offline

Activity: 1050
Merit: 1000

You are WRONG!


View Profile
October 26, 2011, 07:42:56 AM
 #4

THANKS!
please consider to donate, so i am motivated to helping more people. Smiley

"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
molecular
Donator
Legendary
*
Offline Offline

Activity: 2772
Merit: 1019



View Profile
January 10, 2012, 07:01:17 PM
 #5

Code:
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"] = "GoxApi"
        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)

cool, this helped speed things up, thanks.

Donation address?

PGP key molecular F9B70769 fingerprint 9CDD C0D3 20F8 279F 6BE0  3F39 FC49 2362 F9B7 0769
kokjo
Legendary
*
Offline Offline

Activity: 1050
Merit: 1000

You are WRONG!


View Profile
January 10, 2012, 07:22:37 PM
 #6

cool, this helped speed things up, thanks.

Donation address?
1JpsKmkim7REYq2EWE5aEXG8YN4zJTTX16

thanks Smiley

"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
osmosis (OP)
Sr. Member
****
Offline Offline

Activity: 300
Merit: 250



View Profile
January 10, 2012, 07:27:13 PM
 #7

THANKS!
please consider to donate, so i am motivated to helping more people. Smiley

thx kokjo
kokjo
Legendary
*
Offline Offline

Activity: 1050
Merit: 1000

You are WRONG!


View Profile
January 10, 2012, 07:34:28 PM
 #8

im amazed it actually works. it was something i wrote up, in like 10 min.

"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
molecular
Donator
Legendary
*
Offline Offline

Activity: 2772
Merit: 1019



View Profile
January 11, 2012, 02:51:52 AM
 #9

I'm also amazed.

looked at goxsh python impl a while back and I couldn't even figure out wtf was going on...

your solution: drop 2 functions into my sources, change 2-3 lines => switched from user/pass to api key auth.

thanks kokjo, sent a nickle

PGP key molecular F9B70769 fingerprint 9CDD C0D3 20F8 279F 6BE0  3F39 FC49 2362 F9B7 0769
finway
Hero Member
*****
Offline Offline

Activity: 714
Merit: 500


View Profile
January 11, 2012, 05:58:22 AM
 #10

mark.

Ente
Legendary
*
Offline Offline

Activity: 2126
Merit: 1001



View Profile
January 28, 2012, 12:20:40 PM
 #11

Code:
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"] = "GoxApi"
        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)

Thank you a lot for posting this!

Uh, python newbie question:
How to use that class?
I tried:

Quote
key = "12345"
secret = "1234567890"
path = "info.php"
args = "123"

tuer = requester(key,secret)
tuer.perform(path,args)
(key and secret replaced)

Dropped error:
Quote
Traceback (most recent call last):
  File "./auth.py", line 48, in <module>
    tuer.perform(path,args)
  File "./auth.py", line 33, in perform
    data, headers = self.build_query(args)
  File "./auth.py", line 24, in build_query
    req["nonce"] = get_nonce()
TypeError: 'str' object does not support item assignment

By the way, what goes in the "args" when none are needed, like when fetching "info"?

Ah, success comes in tiny, bloody steps..

Ente
kokjo
Legendary
*
Offline Offline

Activity: 1050
Merit: 1000

You are WRONG!


View Profile
January 28, 2012, 12:44:58 PM
 #12

Code:
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"] = "GoxApi"
        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)

Thank you a lot for posting this!

Uh, python newbie question:
How to use that class?
I tried:

Quote
key = "12345"
secret = "1234567890"
path = "info.php"
args = "123"

tuer = requester(key,secret)
tuer.perform(path,args)
(key and secret replaced)

Dropped error:
Quote
Traceback (most recent call last):
  File "./auth.py", line 48, in <module>
    tuer.perform(path,args)
  File "./auth.py", line 33, in perform
    data, headers = self.build_query(args)
  File "./auth.py", line 24, in build_query
    req["nonce"] = get_nonce()
TypeError: 'str' object does not support item assignment

By the way, what goes in the "args" when none are needed, like when fetching "info"?

Ah, success comes in tiny, bloody steps..

Ente
args is a dict. args = {"someparameter": "value of the parameter"}, thats why it does not work.

"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
Ente
Legendary
*
Offline Offline

Activity: 2126
Merit: 1001



View Profile
January 28, 2012, 01:31:37 PM
 #13

args is a dict. args = {"someparameter": "value of the parameter"}, thats why it does not work.

Haha I really an a noob! :-)
Thank you, kokjo!

*flips a coin in your direction*

Ente
kokjo
Legendary
*
Offline Offline

Activity: 1050
Merit: 1000

You are WRONG!


View Profile
January 28, 2012, 01:33:03 PM
 #14

args is a dict. args = {"someparameter": "value of the parameter"}, thats why it does not work.

Haha I really an a noob! :-)
Thank you, kokjo!

*flips a coin in your direction*

Ente
thank you.

"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
molecular
Donator
Legendary
*
Offline Offline

Activity: 2772
Merit: 1019



View Profile
January 28, 2012, 09:01:14 PM
 #15

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.

PGP key molecular F9B70769 fingerprint 9CDD C0D3 20F8 279F 6BE0  3F39 FC49 2362 F9B7 0769
Ente
Legendary
*
Offline Offline

Activity: 2126
Merit: 1001



View Profile
January 31, 2012, 01:46:42 PM
 #16

ah, here comes my next stumbling block:
(still Python, still with the code kokjo was so nice to post)

How do I cancel an order?
I only found old-api-examples (the apt where you POST your credentials directly).
Is it even possible with the newer api?

It expects:
#POST data: oid=#&type=#
#oid: Order ID
#type: 1 for sell order or 2 for buy order

For example:
OID=123asd-123-etz-1542-12947
Type=1

123asd-123-etz-1542-12947=1

How do I pass this string into the "args" variable?

Stupid.. everything else (get info, get orders, buy, sell) works as simple as passing the arguments as a JSON to the .php.
Do I have to rewrite it all just for this single "cancel" order? Or is it only possible with the old API altogether, which will be deactivated in some weeks?


..being noobish again:

Ente

edit:
I would expect something as easy as this to work:

Code:
path_cancel = "0/cancelOrder.php"
oid = "123-124-124-124"
typ = "1"
args_cancel = {oid: typ}
kokjo
Legendary
*
Offline Offline

Activity: 1050
Merit: 1000

You are WRONG!


View Profile
January 31, 2012, 02:03:03 PM
 #17

Code:
args = {"oid": "123-456-bla-bla", "type":"1"}

notice the "" around the 1, AFAIK does urlencode not take numbers, only strings.

"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
Ente
Legendary
*
Offline Offline

Activity: 2126
Merit: 1001



View Profile
January 31, 2012, 02:12:38 PM
 #18

Yea, works, great! :-)
Actually I had the "1" in "", my mistake was even more silly.

I did:
Code:
{"123-456-bla-bla": "1"}

expected is:
Code:
{"oid": "123-456-bla-bla", "type":"1"}

Thanks mate, again!

Ente

edit:
wiki says
Code:
oid=#&type=# 
.
I just read that wrong. This is the moment where I really sense the value in programming languages. What the speaker says is what the listener will understand. Without two "but I meant.." in between!
DBordello
Sr. Member
****
Offline Offline

Activity: 349
Merit: 250


BTCPak.com - Exchange your Bitcoins for MP!


View Profile WWW
February 10, 2012, 01:25:19 AM
 #19

I am having difficulty getting this to work.  Here is the code I am using.  Any thoughts?

I am getting not logged in errors.



Code:
def test():
key = 'x'
secret = 'x'
path = "info.php"
args = {}

tuer = requester(key,secret)
r = tuer.perform(path,args)
print r

#### MT Gox Code ####
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"] = "GoxApi"
        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)

www.BTCPak.com - Exchange your bitcoins for MP: Secure, Anonymous and Easy!
Waam
Newbie
*
Offline Offline

Activity: 21
Merit: 0


View Profile
February 19, 2012, 05:17:06 AM
 #20

I am having difficulty getting this to work.  Here is the code I am using.  Any thoughts?

I am getting not logged in errors.



Code:
def test():
key = 'x'
secret = 'x'
path = "info.php"
args = {}

tuer = requester(key,secret)
r = tuer.perform(path,args)
print r

#### MT Gox Code ####
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"] = "GoxApi"
        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)

key =, etc are variables -- They need to be declared outside of a function. imports/froms should be before any other syntax.

Let me know if you need any more help and I can post my working script (up to Authentication, I wouldn't want to do the work for ya.) Wink
rokj
Newbie
*
Offline Offline

Activity: 26
Merit: 0


View Profile
February 19, 2012, 03:45:36 PM
Last edit: April 17, 2012, 08:26:21 AM by rokj
 #21

https://github.com/rokj/bitcoin_dealer/blob/master/exchange/exchange/mtgox.py

Here it is how I am doing, but it supports older API.

Will implement support for newer API in few days.

UPDATE: Here is for APIv1 https://github.com/rokj/bitcoin_dealer/blob/master/exchange/exchange/mtgox1.py
rokj
Newbie
*
Offline Offline

Activity: 26
Merit: 0


View Profile
February 22, 2012, 11:24:37 AM
Last edit: February 22, 2012, 05:22:18 PM by rokj
 #22

Following seems to work.

Code:
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 Offline

Activity: 105
Merit: 10



View Profile
March 29, 2012, 01:18:13 AM
 #23

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.
Code:
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
Hero Member
*****
Offline Offline

Activity: 742
Merit: 500



View Profile WWW
April 01, 2012, 07:17:09 AM
Last edit: April 01, 2012, 07:28:07 AM by Red Emerald
 #24

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 Python

Also, cython does allow setting types.

Takkun
Newbie
*
Offline Offline

Activity: 12
Merit: 0


View Profile
April 03, 2012, 08:07:57 PM
 #25

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].

Code:
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
Hero Member
*****
Offline Offline

Activity: 900
Merit: 1000


Crypto Geek


View Profile WWW
April 12, 2012, 03:27:45 AM
 #26

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
Sr. Member
****
Offline Offline

Activity: 274
Merit: 250



View Profile
April 13, 2012, 08:40:14 PM
 #27

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 Offline

Activity: 1050
Merit: 1000

You are WRONG!


View Profile
April 13, 2012, 08:45:45 PM
 #28

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 Offline

Activity: 24
Merit: 0



View Profile
April 17, 2012, 08:07:53 AM
 #29

Thanks for the code.

However, when I try it, I always get the not logon error like below:
Code:
{u'error': u'Must be logged in'}

The code is like below:
Code:
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
Code:
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

Code:
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:
Code:
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

Code:

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=1

I 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 Smiley

Any help is appreciate!
rokj
Newbie
*
Offline Offline

Activity: 26
Merit: 0


View Profile
April 17, 2012, 08:27:43 AM
 #30

Thanks for the code.

However, when I try it, I always get the not logon error like below:
Code:
{u'error': u'Must be logged in'}

The code is like below:
Code:
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
Code:
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

Code:
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:
Code:
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

Code:

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=1

I 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 Smiley

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 Offline

Activity: 24
Merit: 0



View Profile
April 17, 2012, 10:05:54 AM
 #31

I just tried it. However, the result is same:  Huh
Code:
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...
rokj
Newbie
*
Offline Offline

Activity: 26
Merit: 0


View Profile
April 17, 2012, 10:12:20 AM
 #32

I just tried it. However, the result is same:  Huh
Code:
url = "https://mtgox.com/api/0/info.php"

Try APIv1.

https://mtgox.com/api/1/BTCUSD/public/ticker using GET or https://mtgox.com/api/1/generic/private/orders using POST.
029xue
Newbie
*
Offline Offline

Activity: 24
Merit: 0



View Profile
April 17, 2012, 11:56:47 AM
 #33

I just tried it. However, the result is same:  Huh
Code:
url = "https://mtgox.com/api/0/info.php"

Try APIv1.

https://mtgox.com/api/1/BTCUSD/public/ticker using GET or https://mtgox.com/api/1/generic/private/orders using POST.


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 Offline

Activity: 26
Merit: 0


View Profile
April 17, 2012, 02:16:07 PM
 #34

I just tried it. However, the result is same:  Huh
Code:
url = "https://mtgox.com/api/0/info.php"

Try APIv1.

https://mtgox.com/api/1/BTCUSD/public/ticker using GET or https://mtgox.com/api/1/generic/private/orders using POST.


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 Offline

Activity: 24
Merit: 0



View Profile
April 20, 2012, 01:10:56 PM
 #35

Thanks for your help. Your code is working and I finally find out the reason Smiley

My .NET code generate nonce like this:
Code:
string parameters = "nonce=" + DateTime.Now.Ticks.ToString();
it'll generate a 18 length value like 634705522019762907

In Python code, it generate nonce like this:
Code:
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 Smiley
rokj
Newbie
*
Offline Offline

Activity: 26
Merit: 0


View Profile
April 20, 2012, 08:25:09 PM
 #36

Thanks for your help. Your code is working and I finally find out the reason Smiley

My .NET code generate nonce like this:
Code:
string parameters = "nonce=" + DateTime.Now.Ticks.ToString();
it'll generate a 18 length value like 634705522019762907

In Python code, it generate nonce like this:
Code:
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 Smiley

No problem!  Wink

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.  Smiley

Pages: 1 2 [All]
  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!