-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathbtcchina.py
148 lines (124 loc) · 5.39 KB
/
btcchina.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author BTCChina.com - http://btcchina.org/api-trade-documentation-en
# updated to sellOrder2 and buyOrder2 API commands by Connor Smith
import time
import re
import hmac
import hashlib
import base64
import httplib
import json
class BTCChina():
def __init__(self,access=None,secret=None):
self.access_key=access
self.secret_key=secret
self.conn=httplib.HTTPSConnection("api.btcchina.com")
def _get_tonce(self):
return int(time.time()*1000000)
def _get_params_hash(self,pdict):
pstring=""
# The order of params is critical for calculating a correct hash
fields=['tonce','accesskey','requestmethod','id','method','params']
for f in fields:
if pdict[f]:
if f == 'params':
# Convert list to string, then strip brackets and spaces
# probably a cleaner way to do this
param_string=re.sub("[\[\] ]","",str(pdict[f]))
param_string=re.sub("'",'',param_string)
param_string=re.sub("True",'1',param_string)
param_string=re.sub("False",'',param_string)
pstring+=f+'='+param_string+'&'
else:
pstring+=f+'='+str(pdict[f])+'&'
else:
pstring+=f+'=&'
pstring=pstring.strip('&')
# now with correctly ordered param string, calculate hash
phash = hmac.new(self.secret_key, pstring, hashlib.sha1).hexdigest()
return phash
def _private_request(self,post_data):
#fill in common post_data parameters
tonce=self._get_tonce()
post_data['tonce']=tonce
post_data['accesskey']=self.access_key
post_data['requestmethod']='post'
# If ID is not passed as a key of post_data, just use tonce
if not 'id' in post_data:
post_data['id']=tonce
pd_hash=self._get_params_hash(post_data)
# must use b64 encode
auth_string='Basic '+base64.b64encode(self.access_key+':'+pd_hash)
headers={'Authorization':auth_string,'Json-Rpc-Tonce':tonce}
#post_data dictionary passed as JSON
self.conn.request("POST",'/api_trade_v1.php',json.dumps(post_data),headers)
response = self.conn.getresponse()
# check response code, ID, and existence of 'result' or 'error'
# before passing a dict of results
if response.status == 200:
# this might fail if non-json data is returned
resp_dict = json.loads(response.read())
# The id's may need to be used by the calling application,
# but for now, check and discard from the return dict
if str(resp_dict['id']) == str(post_data['id']):
if 'result' in resp_dict:
return resp_dict['result']
elif 'error' in resp_dict:
return resp_dict['error']
#else:
# not great error handling....
#print "status:",response.status
#print "reason:",response.reason
return None
def get_account_info(self,post_data={}):
post_data['method']='getAccountInfo'
post_data['params']=[]
return self._private_request(post_data)
def get_market_depth2(self,limit=10,post_data={}):
post_data['method']='getMarketDepth2'
post_data['params']=[limit]
return self._private_request(post_data)
def buy(self,price,amount,post_data={}):
post_data['method']='buyOrder2'
post_data['params']=[price,amount]
return self._private_request(post_data)
def sell(self,price,amount,post_data={}):
post_data['method']='sellOrder2'
post_data['params']=[price,amount]
return self._private_request(post_data)
def cancel(self,order_id,post_data={}):
post_data['method']='cancelOrder'
post_data['params']=[order_id]
return self._private_request(post_data)
def request_withdrawal(self,currency,amount,post_data={}):
post_data['method']='requestWithdrawal'
post_data['params']=[currency,amount]
return self._private_request(post_data)
def get_deposits(self,currency='BTC',pending=True,post_data={}):
post_data['method']='getDeposits'
post_data['params']=[currency,pending]
return self._private_request(post_data)
def get_orders(self,id=None,open_only=True,post_data={}):
# this combines getOrder and getOrders
if id is None:
post_data['method']='getOrders'
post_data['params']=[open_only]
else:
post_data['method']='getOrder'
post_data['params']=[id]
return self._private_request(post_data)
def get_withdrawals(self,id='BTC',pending=True,post_data={}):
# this combines getWithdrawal and getWithdrawals
try:
id = int(id)
post_data['method']='getWithdrawal'
post_data['params']=[id]
except:
post_data['method']='getWithdrawals'
post_data['params']=[id,pending]
return self._private_request(post_data)
def get_transactions(self,trans_type='all',limit=10,post_data={}):
post_data['method']='getTransactions'
post_data['params']=[trans_type,limit]
return self._private_request(post_data)