diff --git a/bitfinex.py b/bitfinex.py index 79d5e13..86f2e5f 100644 --- a/bitfinex.py +++ b/bitfinex.py @@ -9,6 +9,7 @@ PATH_TICKER = "ticker/%s" PATH_TODAY = "today/%s" PATH_STATS = "stats/%s" +PATH_LENDBOOK = "lendbook/%s" class Client(object): """ @@ -23,16 +24,20 @@ def __initialize__(self): def server(self): return "%s://%s/%s" % (PROTOCOL, HOST, VERSION) - def url_for(self, path, parameters = ()): + def url_for(self, path, path_arg=None, parameters=None): # build the basic url url = "%s/%s" % (self.server(), path) - # If there are parameters, interpolate them into the URL. + # If there is a path_arh, interpolate it into the URL. # In this case the path that was provided will need to have string # interpolation characters in it, such as PATH_TICKER - if len(parameters) > 0: - url = url % parameters + if path_arg: + url = url % (path_arg) + + # Append any parameters to the URL. + if parameters: + url = "%s?%s" % (url, self._build_parameters(parameters)) return url @@ -98,6 +103,36 @@ def stats(self, symbol): return data + def lendbook(self, currency, parameters=None): + ''' + curl "https://api.bitfinex.com/v1/lendbook/btc" + + {"bids":[{"rate":"5.475","amount":"15.03894663","period":30,"timestamp":"1395112149.0","frr":"No"},{"rate":"2.409","amount":"14.5121868","period":7,"timestamp":"1395497599.0","frr":"No"}],"asks":[{"rate":"6.351","amount":"15.5180735","period":5,"timestamp":"1395549996.0","frr":"No"},{"rate":"6.3588","amount":"626.94808249","period":30,"timestamp":"1395400654.0","frr":"Yes"}]} + + Optional parameters + + limit_bids (int): Optional. Limit the number of bids (loan demands) returned. May be 0 in which case the array of bids is empty. Default is 50. + limit_asks (int): Optional. Limit the number of asks (loan offers) returned. May be 0 in which case the array of asks is empty. Default is 50. + + eg. https://api.bitfinex.com/v1/lendbook/btc?limit_bids=2&limit_asks=2 + ''' + data = self._get(self.url_for(PATH_LENDBOOK, path_arg=currency, parameters=parameters)) + + for lend_type in data.keys(): + + for lend in data[lend_type]: + + for key, value in lend.iteritems(): + if key in ['rate', 'amount', 'timestamp']: + new_value = float(value) + elif key == 'period': + new_value = int(value) + elif key == 'frr': + new_value = value == 'Yes' + + lend[key] = new_value + + return data def _convert_to_floats(self, data): """ @@ -109,6 +144,8 @@ def _convert_to_floats(self, data): return data def _get(self, url): - response = requests.get(url) + return json.loads(requests.get(url).content) + + def _build_parameters(self, parameters): + return '&'.join(["%s=%s" % (k, v) for k, v in parameters.iteritems()]) - return json.loads(response.content) diff --git a/test/bitfinex_test.py b/test/bitfinex_test.py index 0ee532f..8ceee45 100644 --- a/test/bitfinex_test.py +++ b/test/bitfinex_test.py @@ -19,9 +19,14 @@ def test_should_have_url_for_foo(self): expected = "https://api.bitfinex.com/v1/foo" self.assertEqual(expected, self.client.url_for("foo")) - def test_should_have_url_for_ticker_symbol(self): - expected = "https://api.bitfinex.com/v1/ticker/foo" - actual = self.client.url_for(bitfinex.PATH_TICKER, ("foo")) + def test_should_have_url_for_path_arg(self): + expected = "https://api.bitfinex.com/v1/foo/bar" + actual = self.client.url_for('foo/%s', path_arg="bar") + self.assertEqual(expected, actual) + + def test_should_have_url_with_parameters(self): + expected = "https://api.bitfinex.com/v1/foo?a=1&b=2" + actual = self.client.url_for('foo', parameters={'a': 1, 'b': 2}) self.assertEqual(expected, actual) def test_should_have_url_for_symbols(self): @@ -29,7 +34,7 @@ def test_should_have_url_for_symbols(self): self.assertEqual("https://api.bitfinex.com/v1/foo", expected) def test_should_have_ticker_for_symbol(self): - expected = self.client.url_for("foo/%s", ('bar')) + expected = self.client.url_for("foo/%s", path_arg='bar') self.assertEqual("https://api.bitfinex.com/v1/foo/bar", expected) @httpretty.activate @@ -46,7 +51,7 @@ def test_should_have_symbols(self): def test_should_have_ticker(self): # mock out the request mock_body = '{"mid":"562.56495","bid":"562.15","ask":"562.9799","last_price":"562.25","timestamp":"1395552658.339936691"}' - url = self.client.url_for(bitfinex.PATH_TICKER, ('btcusd')) + url = self.client.url_for(bitfinex.PATH_TICKER, path_arg='btcusd') httpretty.register_uri(httpretty.GET, url, body=mock_body, status=200) @@ -65,7 +70,7 @@ def test_should_have_ticker(self): def test_should_have_today(self): # mock out the request mock_body = '{"low":"550.09","high":"572.2398","volume":"7305.33119836"}' - url = self.client.url_for(bitfinex.PATH_TODAY, ('btcusd')) + url = self.client.url_for(bitfinex.PATH_TODAY, path_arg='btcusd') httpretty.register_uri(httpretty.GET, url, body=mock_body, status=200) @@ -82,7 +87,7 @@ def test_should_have_today(self): def test_should_have_stats(self): # mock out the request mock_body = '[{"period":1,"volume":"7410.27250155"},{"period":7,"volume":"52251.37118006"},{"period":30,"volume":"464505.07753251"}]' - url = self.client.url_for(bitfinex.PATH_STATS, ('btcusd')) + url = self.client.url_for(bitfinex.PATH_STATS, path_arg='btcusd') httpretty.register_uri(httpretty.GET, url, body=mock_body, status=200) @@ -94,3 +99,46 @@ def test_should_have_stats(self): ] self.assertEqual(expected, self.client.stats('btcusd')) + + @httpretty.activate + def test_should_have_lendbook(self): + # mock out the request + mock_body = '{"bids":[{"rate":"5.475","amount":"15.03894663","period":30,"timestamp":"1395112149.0","frr":"No"},{"rate":"2.409","amount":"14.5121868","period":7,"timestamp":"1395497599.0","frr":"No"}],"asks":[{"rate":"6.351","amount":"15.5180735","period":5,"timestamp":"1395549996.0","frr":"No"},{"rate":"6.3588","amount":"626.94808249","period":30,"timestamp":"1395400654.0","frr":"Yes"}]}' + url = self.client.url_for(bitfinex.PATH_LENDBOOK, path_arg='btc') + httpretty.register_uri(httpretty.GET, url, + body=mock_body, + status=200) + + expected = { + "bids":[ + {"rate": 5.475, "amount": 15.03894663, "period": 30, "timestamp": 1395112149.0, "frr": False}, + {"rate": 2.409, "amount": 14.5121868, "period": 7, "timestamp": 1395497599.0, "frr": False} + ], + "asks":[ + {"rate": 6.351, "amount": 15.5180735, "period": 5, "timestamp": 1395549996.0, "frr": False}, + {"rate": 6.3588, "amount": 626.94808249, "period": 30, "timestamp": 1395400654.0, "frr": True} + ] + } + + self.assertEqual(expected, self.client.lendbook('btc')) + + @httpretty.activate + def test_should_have_lendbook_with_parameters(self): + # mock out the request + mock_body = '{"bids":[{"rate":"5.475","amount":"15.03894663","period":30,"timestamp":"1395112149.0","frr":"No"},{"rate":"2.409","amount":"14.5121868","period":7,"timestamp":"1395497599.0","frr":"No"}],"asks":[]}' + parameters = {'limit_bids': 2, 'limit_asks': 0} + url = self.client.url_for(bitfinex.PATH_LENDBOOK, path_arg='btc', parameters=parameters) + httpretty.register_uri(httpretty.GET, url, + body=mock_body, + status=200) + + expected = { + "bids":[ + {"rate": 5.475, "amount": 15.03894663, "period": 30, "timestamp": 1395112149.0, "frr": False}, + {"rate": 2.409, "amount": 14.5121868, "period": 7, "timestamp": 1395497599.0, "frr": False} + ], + "asks":[ + ] + } + + self.assertEqual(expected, self.client.lendbook('btc', parameters))