def test_base_api_uri_used_instead_of_default(self): # Requests to the default BASE_API_URI will noticeably fail by raising an # AssertionError. Requests to the new URL will respond HTTP 200. new_base_api_uri = 'http://example.com/api/v1/' # If any error is raised by the server, the test suite will never exit when # using Python 3. This strange technique is used to raise the errors # outside of the mocked server environment. errors_in_server = [] def server_response(request, uri, headers): try: self.assertEqual(uri, new_base_api_uri) except AssertionError as e: errors_in_server.append(e) return (200, headers, "") hp.register_uri(hp.GET, Client.BASE_API_URI, body=server_response) hp.register_uri(hp.GET, new_base_api_uri, body=server_response) client2 = Client(api_key, api_secret, new_base_api_uri) self.assertEqual(client2._get().status_code, 200) client = Client(api_key, api_secret) with self.assertRaises(AssertionError): client._get() if errors_in_server: raise errors_in_server.pop()
def test_base_api_uri_used_instead_of_default(self): # Requests to the default BASE_API_URI will noticeably fail by raising an # AssertionError. Requests to the new URL will respond HTTP 200. new_base_api_uri = 'http://example.com/api/v1/' # If any error is raised by the server, the test suite will never exit when # using Python 3. This strange technique is used to raise the errors # outside of the mocked server environment. errors_in_server = [] def server_response(request, uri, headers): try: self.assertEqual(uri, new_base_api_uri) except AssertionError as e: errors_in_server.append(e) return (200, headers, "") hp.register_uri(hp.GET, Client.BASE_API_URI, body=server_response) hp.register_uri(hp.GET, new_base_api_uri, body=server_response) client2 = Client(api_key, api_secret, new_base_api_uri) self.assertEqual(client2._get().status_code, 200) client = Client(api_key, api_secret) with self.assertRaises(AssertionError): client._get() if errors_in_server: raise errors_in_server.pop()
def test_auth_succeeds_with_bytes_and_unicode(self): api_key = 'key' api_secret = 'secret' self.assertIsInstance(api_key, six.text_type) # Unicode self.assertIsInstance(api_secret, six.text_type) # Unicode client = Client(api_key, api_secret) self.assertEqual(client._get('test').status_code, 200) api_key = api_key.encode('utf-8') api_secret = api_secret.encode('utf-8') self.assertIsInstance(api_key, six.binary_type) # Bytes self.assertIsInstance(api_secret, six.binary_type) # Bytes client = Client(api_key, api_secret) self.assertEqual(client._get('test').status_code, 200)
def test_auth_succeeds_with_bytes_and_unicode(self): api_key = 'key' api_secret = 'secret' self.assertIsInstance(api_key, six.text_type) # Unicode self.assertIsInstance(api_secret, six.text_type) # Unicode client = Client(api_key, api_secret) self.assertEqual(client._get('test').status_code, 200) api_key = api_key.encode('utf-8') api_secret = api_secret.encode('utf-8') self.assertIsInstance(api_key, six.binary_type) # Bytes self.assertIsInstance(api_secret, six.binary_type) # Bytes client = Client(api_key, api_secret) self.assertEqual(client._get('test').status_code, 200)
def test_response_handling(self): client = Client(api_key, api_secret) # Check that 2XX responses always return the response error_response = { 'errors': [{ 'id': 'fakeid', 'message': 'some error message', }], 'data': mock_item, } error_str = json.dumps(error_response) for code in [200, 201, 204]: hp.register_uri( hp.GET, re.compile('.*' + str(code) + '$'), lambda r, u, h: (code, h, error_str)) response = client._get(str(code)) self.assertEqual(response.status_code, code) # Check that when the error data is in the response, that's what is used. import coinbase.wallet.error for eid, eclass in six.iteritems( coinbase.wallet.error._error_id_to_class): error_response = { 'errors': [{ 'id': eid, 'message': 'some message', }], 'data': mock_item, } error_str = json.dumps(error_response) hp.reset() hp.register_uri( hp.GET, re.compile('.*test$'), lambda r, u, h: (400, h, error_str)) with self.assertRaises(eclass): client._get('test') # Check that when the error data is missing, the status code is used # instead. error_response = {'data': mock_item} for code, eclass in six.iteritems( coinbase.wallet.error._status_code_to_class): hp.reset() hp.register_uri( hp.GET, re.compile('.*test$'), lambda r, u, h: (code, h, json.dumps(error_response))) with self.assertRaises(eclass): client._get('test') # Check that when the response code / error id is unrecognized, a generic # APIError is returned hp.reset() hp.register_uri(hp.GET, re.compile('.*test$'), lambda r, u, h: (418, h, '{}')) with self.assertRaises(APIError): client._get('test')
def test_response_handling(self): client = Client(api_key, api_secret) # Check that 2XX responses always return the response error_response = { 'errors': [{ 'id': 'fakeid', 'message': 'some error message', }], 'data': mock_item, } error_str = json.dumps(error_response) for code in [200, 201, 204]: hp.register_uri( hp.GET, re.compile('.*' + str(code) + '$'), lambda r, u, h: (code, h, error_str)) response = client._get(str(code)) self.assertEqual(response.status_code, code) # Check that when the error data is in the response, that's what is used. import coinbase.wallet.error for eid, eclass in six.iteritems( coinbase.wallet.error._error_id_to_class): error_response = { 'errors': [{ 'id': eid, 'message': 'some message', }], 'data': mock_item, } error_str = json.dumps(error_response) hp.reset() hp.register_uri( hp.GET, re.compile('.*test$'), lambda r, u, h: (400, h, error_str)) with self.assertRaises(eclass): client._get('test') # Check that when the error data is missing, the status code is used # instead. error_response = {'data': mock_item} for code, eclass in six.iteritems( coinbase.wallet.error._status_code_to_class): hp.reset() hp.register_uri( hp.GET, re.compile('.*test$'), lambda r, u, h: (code, h, json.dumps(error_response))) with self.assertRaises(eclass): client._get('test') # Check that when the response code / error id is unrecognized, a generic # APIError is returned hp.reset() hp.register_uri(hp.GET, re.compile('.*test$'), lambda r, u, h: (418, h, '{}')) with self.assertRaises(APIError): client._get('test')
def get_current_gains(user): api_key, api_secret = os.environ.get( f'API_KEY_{user.upper()}'), os.environ.get( f'API_SECRET_{user.upper()}') client = Client(api_key, api_secret) nat_curr = os.environ.get('NAT_CURRENCY', 'EUR') accounts = client.get_accounts() gains = [] for acc in accounts.data: # Getting general info id, curr, name = acc.id, acc.balance.currency, acc.name # Getting coin balance coin_balance = float(acc.balance.amount) # Getting market price if curr == 'EUR' or coin_balance == 0.0: continue sell_price = float( client._make_api_object( client._get('v2', 'prices', f'{curr.upper()}-{nat_curr}', 'sell'), APIObject).amount) buy_price = float( client._make_api_object( client._get('v2', 'prices', f'{curr.upper()}-{nat_curr}', 'buy'), APIObject).amount) # Getting fiat payments and balance fiat_balance = coin_balance * sell_price * (1 - SELL_FEE) fiat_buys = sum([ float(b['total']['amount']) for b in client.get_buys(id).data if b['status'] == 'completed' ]) gains.append({ 'currency': curr, 'name': name, 'fiat_buys': fiat_buys, 'fiat_balance': fiat_balance, 'coin_balance': coin_balance, 'buy_price': buy_price, 'sell_price': sell_price, }) return gains
def test_request_includes_auth_headers(self): client = Client(api_key, api_secret) def server_response(request, uri, response_headers): keys = [ 'CB-VERSION', 'CB-ACCESS-KEY', 'CB-ACCESS-SIGN', 'CB-ACCESS-TIMESTAMP', 'Accept', 'Content-Type', 'User-Agent'] for key in keys: self.assertIn(key, request.headers) self.assertNotEqual(request.headers[key], '') return 200, response_headers, '{}' hp.register_uri(hp.GET, re.compile('.*test$'), server_response) self.assertEqual(client._get('test').status_code, 200)
def test_request_includes_auth_headers(self): client = Client(api_key, api_secret) def server_response(request, uri, response_headers): keys = [ 'CB-VERSION', 'CB-ACCESS-KEY', 'CB-ACCESS-SIGN', 'CB-ACCESS-TIMESTAMP', 'Accept', 'Content-Type', 'User-Agent'] for key in keys: self.assertIn(key, request.headers) self.assertNotEqual(request.headers[key], '') return 200, response_headers, '{}' hp.register_uri(hp.GET, re.compile('.*test$'), server_response) self.assertEqual(client._get('test').status_code, 200)
def get_eth_price(self): client = Client(os.environ.get('COINBASE_KEY'), os.environ.get('COINBASE_SECRET'), api_version='2017-05-26') # rates = client.get_spot_price(currency_pair='ETH-USD') spot = client._make_api_object( client._get('v2', 'prices', 'ETH-USD', 'spot'), APIObject) current_time = datetime.datetime.utcnow().strftime( "%a %b %d %Y %H:%M:%S UTC") print('{} ETH price is {}'.format(current_time, spot.amount)) self.check_buy_price(spot.amount) return spot
class Coinbase: def __init__(self, api_key, api_secret, currency_pairs): self.client = Client(api_key, api_secret) self.currencyPair = currency_pairs self.startingBalUSD = 5000 self.startingBalETH = 0 self.balanceUSD = 5000 self.balanceBTC = 0 self.balanceETH = 0 self.balanceLTC = 0 self.profit = 0 self.buys = [] self.sells = [] self.coinbaseFee = 1.49 self.tempBuyPrice = self.GetBuyPrice() self.tempSellPrice = self.GetSellPrice() print 'Starting Balances: ETH %s USD %s Profit $%s' % ( self.startingBalETH, '{0:,.2f}'.format(self.startingBalUSD), '0') def GetBuyPrice(self): # Returns Buy Price including fees price = self.client._make_api_object( self.client._get('v2', 'prices', self.currencyPair, 'buy'), APIObject) return float(price["amount"]) + self.GetFee(float(price["amount"])) def GetSellPrice(self): # Returns Sell Price including fees price = self.client._make_api_object( self.client._get('v2', 'prices', self.currencyPair, 'sell'), APIObject) return float(price["amount"]) - self.GetFee(float(price["amount"])) def GetFee(self, price): # Calculates the fee for a given price fee = float((price / (100 / self.coinbaseFee))) return fee def Buy(self, amount): # Buy crypto total = self.GetBuyPrice() * amount if (self.balanceUSD - total) > 0: # If there is enough fiat in the account self.buys.append(total) self.balanceUSD -= total self.balanceETH += amount self.GetCurrentBalance() def Sell(self, amount): # Sell crypto total = self.GetSellPrice() * amount self.sells.append(total) self.profit = float((self.balanceUSD + total) - self.startingBalUSD) self.balanceUSD += total self.balanceETH -= amount self.GetCurrentBalance() def GetCurrentBalance(self): print 'Current Balances: ETH %s USD %s Profit $%s' % ( self.balanceETH, '{0:,.2f}'.format(self.balanceUSD), self.profit) def GetSpread(self): if self.tempBuyPrice != self.GetBuyPrice() or \ self.tempSellPrice != self.GetSellPrice(): # Print spread if Buy or Sell price has changed self.tempBuyPrice = self.GetBuyPrice() self.tempSellPrice = self.GetSellPrice() print ' Buy: $%s Sell: $%s' % (self.GetBuyPrice(), self.GetSellPrice())