def api_query(self, command, req={}): if(command == 'returnTicker' or command == "return24Volume"): try: ret = requests.get(publicURL + command, timeout=REQ_TIMEOUT) except (ConnectionError, Timeout) as e: raise ExchangeError('poloniex', 'Could not complete request %r for reason %s %s' % (command, type(e), str(e))) return json.loads(ret.text) elif(command == "returnOrderBook" or command == "returnMarketTradeHistory"): try: ret = requests.get(publicURL + command + '¤cyPair=' + str(req['currencyPair']), timeout=REQ_TIMEOUT) except (ConnectionError, Timeout) as e: raise ExchangeError('poloniex', 'Could not complete request %r for reason %s %s' % (command, type(e), str(e))) return json.loads(ret.text) else: req['command'] = command req['nonce'] = int(time.time()*1000) post_data = urllib.urlencode(req) sign = hmac.new(self.Secret, post_data, hashlib.sha512).hexdigest() headers = { 'Sign': sign, 'Key': self.APIKey } try: ret = requests.post(url=tradeURL, data=req, headers=headers, timeout=REQ_TIMEOUT) except (ConnectionError, Timeout) as e: raise ExchangeError('poloniex', 'Could not complete request %r for reason %s %s' % (req, type(e), str(e))) return json.loads(ret.text)
def create_order(self, amount, price, otype='buy'): """ It returns the transactions history. parameter description it takes up the values pair pair btc_usd (example) type The transaction type buy or sell rate The rate to buy/sell numerical amount The amount which is necessary to buy/sell numerical """ if BLOCK_ORDERS: return "order blocked" if otype == 'bid': otype = 'buy' elif otype == 'ask': otype = 'sell' else: raise ExchangeError(exchange='btce', message="Unknown order type %r" % otype) params = { "method": "Trade", 'pair': 'btc_usd', 'type': otype, 'rate': float(price), 'amount': round(float(amount), 2) } resp = self._handle_response(self.send_btce(params)) if 'order_id' in resp: return str(resp['order_id']) raise ExchangeError( 'btce', 'unable to create %s %r at %r order' % (otype, amount, price))
def get_balance(self, btype='total'): """ :param str btype: The balance types to include """ try: stampbal = json.loads(self.submit_request('balance', {}, True)) if 'btc_balance' not in stampbal or 'usd_balance' not in stampbal: raise ExchangeError( exchange='bitstamp', message="Bitstamp balance information unavailable") except ValueError as e: raise ExchangeError( 'bitfinex', '%s %s while sending to bitfinex get_open_orders' % (type(e), str(e))) if btype == 'total': total = MultiMoney(Money(stampbal['btc_balance']), Money(stampbal['usd_balance'], currency='USD')) return total elif btype == 'available': available = MultiMoney( Money(stampbal['btc_available']), Money(stampbal['usd_available'], currency='USD')) return available else: total = MultiMoney(Money(stampbal['btc_balance']), Money(stampbal['usd_balance'], currency='USD')) # TODO this isn't correct available = MultiMoney( Money(stampbal['btc_available']), Money(stampbal['usd_available'], currency='USD')) return total, available
def _handle_response(self, resp): try: response = json.loads(resp) except (TypeError, ValueError): raise ExchangeError(exchange='btce', message="response was not valid json: %s" % str(resp)) if response and 'success' in response and response['success'] == 1: return response['return'] elif response and 'error' in response: raise ExchangeError(exchange='btce', message=response['error']) else: raise ExchangeError( exchange='btce', message="response not successful but also not erroneous... %s" % str(response))
def create_order(self, amount, price, otype): if BLOCK_ORDERS: return "order blocked" if otype == 'ask': otype = 'sell' elif otype == 'bid': otype = 'buy' if otype != 'buy' and otype != 'sell': raise ExchangeError( exchange='bitstamp', message="Only 'buy' and 'sell' are acceptable order types.") data = {'amount': round(float(amount), 2), 'price': round(price, 2)} response = json.loads(self.submit_request(otype, data, True)) if 'id' in response: return str(response['id']) raise ExchangeError('bitstamp', 'unable to create order %r' % data)
def get_market_depth(self, post_data=None): try: depth = requests.get('https://data.btcchina.com/data/orderbook', timeout=REQ_TIMEOUT) return depth.json() except (ConnectionError, Timeout, ValueError) as e: raise ExchangeError( 'btcchina', 'Could not get_market_depth using data %s for reason %s' % (post_data, e))
def send_shapeshift(path, values=None, pog='get'): """Send message to URL and return response contents Raises ExchangeError""" url = baseURL + path if pog == 'post': try: resp = requests.post(url, values).json() except (ConnectionError, Timeout, ValueError) as e: raise ExchangeError( 'shapeshift', '%s %s while sending %r' % (type(e), str(e), values)) else: try: resp = requests.get(url).json() except (ConnectionError, Timeout, ValueError) as e: raise ExchangeError( 'shapeshift', '%s %s while sending %r' % (type(e), str(e), values)) return resp
def get_order_book(cls, pair='ignored'): opath = 'order_book' try: jresp = cls.api_get(opath) response = json.loads(jresp) except (TypeError, ValueError): return None if response and 'bids' in response: return response elif response and 'error' in response: raise ExchangeError(exchange='bitstamp', message=response['error']) return None
def get_ticker(self, retry=0): try: resp = requests.get('https://data.btcchina.com/data/ticker', verify=False, timeout=REQ_TIMEOUT) except (ConnectionError, Timeout) as e: raise ExchangeError('btcchina', 'Could not get_ticker for reason %s' % e) try: return json.loads(resp.text) except ValueError: if retry < 5: self.get_ticker(retry=retry + 1)
def papi(cls, method): """ BTC-E public api interface """ url = publicUrl + method + '/' headers = {'Content-type': 'application/x-www-form-urlencoded'} try: response = requests.get(url, headers=headers, timeout=REQ_TIMEOUT) except (ConnectionError, Timeout) as e: raise ExchangeError( 'btce', '%s %s while sending %r to %s' % (type(e), e, method, url)) return response.text
def get_ticker(cls, pair='ignored'): try: rawtick = json.loads(cls.api_get('ticker')) except (ConnectionError, Timeout, ValueError) as e: raise ExchangeError( 'bitfinex', '%s %s while sending get_ticker to bitfinex' % (type(e), str(e))) return create_ticker(bid=rawtick['bid'], ask=rawtick['ask'], high=rawtick['high'], low=rawtick['low'], volume=rawtick['volume'], last=rawtick['last'], timestamp=rawtick['timestamp'], currency='USD')
def send_btce(self, params=None, sign=True, retry=0): """ Send request to BTCE. Parameters: path - The portion of the to use. params - The parameters to send with the request. sign - Flag indicating whether or not request needs to be signed. Default is True. """ if not params: params = {} url = tradeUrl params['nonce'] = self.next_nonce() post_string = urllib.urlencode(params) # Hash the params string to produce the Sign header value hash_parm = hmac.new(self.secret, digestmod=hashlib.sha512) hash_parm.update(post_string) headers = { "Content-type": "application/x-www-form-urlencoded", "Key": self.key, "Sign": hash_parm.hexdigest() } try: response = requests.post(url=url, data=params, headers=headers, timeout=REQ_TIMEOUT).text if "invalid nonce parameter" in response and retry < 3: return self.send_btce(params=params, sign=sign, retry=retry + 1) except (ConnectionError, Timeout) as e: raise ExchangeError( 'btce', '%s %s while sending to btce %r' % (type(e), str(e), params)) return response
def _private_request(self, post_data, retry=0): # 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 'id' not 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() try: response = requests.post(self.url + '/api_trade_v1.php', data=json.dumps(post_data), headers=headers, verify=False, timeout=REQ_TIMEOUT) except (ConnectionError, Timeout) as e: raise ExchangeError( 'btcchina', 'Could not complete request %r for reason %s' % (post_data, e)) # check response code, ID, and existence of 'result' or 'error' # before passing a dict of results # if response.status == 200: if response.status_code == 200: # this might fail if non-json data is returned # resp_dict = json.loads(response.read()) resp_dict = json.loads(response.text) # 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: ExchangeError( 'btcchina', 'error response for %r: %s' % (post_data, str(resp_dict['error']))) elif 'code' in resp_dict: ExchangeError( 'btcchina', 'error response for %r: %s' % (post_data, str(resp_dict['code']))) elif response.status_code == 401 and retry < 2: # possible nonce collision? self._private_request(post_data, retry=retry + 1) else: print "status:" + str(response.status_code) raise ExchangeError( 'btcchina', 'error response for %r: %s' % (post_data, str(response.status_code))) raise ExchangeError('btcchina', 'Invalid response for %r' % post_data)
def submit_request(self, path, params=None, private=False, timedelta=86400, retry=0): """ Send request to BitStamp. Parameters: path - The portion of the url path which follows the api version. Should begin with '/.' params - The parameters to send with the request. private - Boolean value weather or not the credentials need to be passed """ if not params: params = {} url = baseUrl + path + '/' if timedelta != 86400: url += '?timedelta=' + str(timedelta) if private: params['key'] = self.key params['nonce'] = int(time.time() * 100000) mess = str(params['nonce']) + self.clientid + self.key params['signature'] = hmac.new( self.secret, msg=mess, digestmod=hashlib.sha256).hexdigest().upper() headers = { 'Content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'newcpt' } if private: request = requests.post(url, data=params, headers=headers, verify=False, timeout=REQ_TIMEOUT) else: request = requests.post(url, headers=headers, verify=False, timeout=REQ_TIMEOUT) response = None try: response = request.text except request.exceptions.HTTPError as e: print e if request.status: print request.status if response: print response return None if response == '{"error": "Invalid nonce"}' and retry < 10: tosleep = round(1 - float(10 - retry) / 10, 2) time.sleep(tosleep) self.submit_request(path, params=params, private=private, timedelta=timedelta, retry=retry + 1) elif 'error' in response: raise ExchangeError('bitstamp', message=response) return response