diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b99b59e --- /dev/null +++ b/.gitignore @@ -0,0 +1,94 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# IPython Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# dotenv +.env + +# virtualenv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject + +# Project +*~ +*.swp + diff --git a/README.md b/README.md index 67b3d02..67f9d99 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,6 @@ You can find each client reference implementation in: * [NodeJs](examples/nodejs/) * [Java](examples/java/) * [Go](examples/go/) +* [Python 2](examples/python/) +* [Python 3](examples/python3/) [doc](examples/python3/README.md) + diff --git a/examples/python3/README.md b/examples/python3/README.md new file mode 100644 index 0000000..f546df6 --- /dev/null +++ b/examples/python3/README.md @@ -0,0 +1,25 @@ +Unofficial Python 3 Bl3p client exchange api +=== + +## Install +``` +$ git clone https://github.com/joosthoeks/bl3p-api.git +$ cd bl3p-api/examples/python3 +$ [sudo] pip3 install -e . +``` + +## Update +``` +$ cd bl3p-api +$ git pull +``` + +## Test +``` +$ cd examples/python3/ +``` +modify public_key and secret_key in example.py then run: +``` +$ python3 example.py +``` + diff --git a/examples/python3/bl3p/__init__.py b/examples/python3/bl3p/__init__.py new file mode 100644 index 0000000..973a698 --- /dev/null +++ b/examples/python3/bl3p/__init__.py @@ -0,0 +1,2 @@ +from .api import * + diff --git a/examples/python3/bl3p/api/__init__.py b/examples/python3/bl3p/api/__init__.py new file mode 100644 index 0000000..973a698 --- /dev/null +++ b/examples/python3/bl3p/api/__init__.py @@ -0,0 +1,2 @@ +from .api import * + diff --git a/examples/python3/bl3p/api/api.py b/examples/python3/bl3p/api/api.py new file mode 100755 index 0000000..4f3f450 --- /dev/null +++ b/examples/python3/bl3p/api/api.py @@ -0,0 +1,144 @@ +# Unofficial Python 3 Bl3p client exchange api + + +import base64 +import hashlib +import hmac +import json +import requests +import urllib.parse + + +class Bl3pApi: + url = None + pubKey = None + secKey = None + verbose = False + + def __init__(self, u, pk, sk): + self.url = u + self.pubKey = pk + self.secKey = sk + + def apiCall(self, path, params): + post_data = urllib.parse.urlencode(params) + + body = ('%s%c%s' % (path, 0x00, post_data)).encode() + + privkey_bin = base64.b64decode(self.secKey) + + signature_bin = hmac.new(privkey_bin, body, hashlib.sha512) + + signature = base64.b64encode(signature_bin.digest()).decode() + + fullpath = '%s%s' % (self.url, path) + + headers = { + 'Rest-Key': self.pubKey, + 'Rest-Sign': signature + } + + r = requests.get(fullpath, headers=headers, data=post_data) + + response_code = r.status_code + if response_code != 200: + raise Exception('unexpected response code: %d' % response_code) + + return r.json() + + # multiply the btc value (e.g 1.3BTC) with this and round-up/down + def getBtcMultiplier(self): + return 100000000 + + def getEurMultiplier(self): + return 100000 + + # Add order to your account. + # @method addOrder + # @param market 'EUR' + # @param order_type 'bid' or 'ask' + # bid: used if you want to buy bitcoins + # ask: if you want to sell bitcoins + # @param order_amount Amount to order *1e8 (so 1 bitcoin is 100000000) + # @param order_price Price of order *1e5 (1 euro is 100000) + # @return Result of the add order call + def addOrder(self, market, order_type, order_amount, order_price): + params = { + 'type' : order_type, + 'amount_int' : order_amount, + 'price_int' : order_price, + 'fee_currency' : 'BTC' + } + return self.apiCall('%sEUR/money/order/add' % market, params) + + # Cancel a specific order. + # @method cancelOrder + # @param market 'EUR' + # @param order_id Id of the order + # @return Direct resulf of the '/money/order/cancel' call + def cancelOrder(self, market, order_id): + params = { 'order_id' : order_id } + return self.apiCall("%sEUR/money/order/cancel" % market, params) + + # Fetch information about an specific order + # @method orderInfo + # @param market 'EUR' + # @param order_id Id of the order + # @return Direct resulf of the '/money/order/result' call + def orderInfo(self, market, order_id): + params = { 'order_id' : order_id } + return self.apiCall("%sEUR/money/order/result" % market, params) + + # Fetch complete orderbook + # @method fullDepth + # @param market 'EUR' + # @return Direct resulf of the '/money/depth/full' call + def fullDepth(self, market): + return self.apiCall("%sEUR/money/depth/full" % market, { }) + + # Get new deposit address. + # @method getNewDepositAddress + # @param market 'EUR' + # @return new deposit address + def getNewDepositAddress(self, market): + return self.apiCall("%sEUR/money/new_deposit_address" % market, { }) + + # Get the most recent generated deposit address + # @method getLastDepositAddress + # @param market 'EUR' + # @return most recent generated deposit address + def getLastDepositAddress(self, market): + return self.apiCall("%sEUR/money/deposit_address" % market, { }) + + # Get the last 1000 trades that where executed before an specific trade_id + # @method fetchTrades + # @param market 'EUR' + # @param trade_id id of the trade + # @return array of last 1000 executed trades. + def fetchLast1000Trades(self, market, trade_id): + params = { 'trade_id' : trade_id } + return self.apiCall("%sEUR/money/trades/fetch" % market, params) + + # Get the transaction history + # @method walletHistory + # @param currency currency which currency + # @param n how many to retrieve + # @return array json structure with the transaction history + def walletHistory(self, currency, n): + params = { 'currency' : currency, 'recs_per_page' : n } + return self.apiCall('GENMKT/money/wallet/history', params) + + # Get all open orders. + # @method getAllActiveOrders + # @param market 'EUR' + # @return array of open orders + def getAllActiveOrders(self, market): + return self.apiCall("%sEUR/money/orders" % market, { }); + + # Get the balances + # @method getBalances + # @return array json structure with the wallet balances + def getBalances(self): + params = { } + return self.apiCall('GENMKT/money/info', params) + diff --git a/examples/python3/example-py.txt b/examples/python3/example-py.txt new file mode 100644 index 0000000..1fd2089 --- /dev/null +++ b/examples/python3/example-py.txt @@ -0,0 +1,100 @@ +Examples +======== + +invalid public/secret key: +------------------------- +{ + "data": { + "code": "KEY_MISSING", + "message": "Rest-Key missing" + }, + "result": "error" +} + + +invalid market: +-------------- +{ + "data": { + "code": "UNKNOWN_MARKETPLACE", + "message": "Unknown marketplace" + }, + "result": "error" +} + + +price too low: +------------- +{ + "data": { + "code": "PRICE_LESS_THAN_MINIMUM", + "message": "Price '1' less than marketplace minimum '1000'" + }, + "result": "error" +} + + +insufficient funds: +------------------ +{ + "data": { + "code": "INSUFFICIENT_FUNDS", + "message": "Insufficient available funds, available = 0 order value = 10000000" + }, + "result": "error" +} + + +market unavailable: +------------------ +{ + "data": { + "code": "ERR_TEMPORARILY_UNAVAILABLE", + "message": "Error creating address" + }, + "result": "error" +} + + +walletHistory(): +------------- +{ + "data": { + "max_page": 1, + "page": 1, + "records": 1, + "transactions": [ + { + "amount": { + "currency": "BTC", + "display": "0.01000000 BTC", + "display_short": "0.01 BTC", + "value": "0.01000000", + "value_int": "1000000" + }, + "balance": { + "currency": "BTC", + "display": "0.01000000 BTC", + "display_short": "0.01 BTC", + "value": "0.01000000", + "value_int": "1000000" + }, + "date": 1450353480, + "debit_credit": "credit", + "transaction_id": 575126, + "type": "deposit" + } + ] + }, + "result": "success" +} + + +getNewDepositAddress(): +-------------------- +{ + "data": { + "address": "**********************************" + }, + "result": "success" +} diff --git a/examples/python3/example.py b/examples/python3/example.py new file mode 100755 index 0000000..c60aa17 --- /dev/null +++ b/examples/python3/example.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + + +import bl3p + +import json + + +def d(j): + print (json.dumps(j, sort_keys=True, indent=4, separators=(',', ': '))) + +def main(): + # example: + public_key = '' + secret_key = '' + + b = bl3p.Bl3pApi('https://api.bl3p.eu/1/', public_key, secret_key) +# b.setVerbose(True) + ''' + koers_in_eur = 5000 + kapitaal_in_eur = 10000 + btc = round(kapitaal_in_eur / koers_in_eur, 8) # round to 8 decimals + market = 'BTC' + order_type = 'bid' # 'bid' (=buy BTC) or 'ask' (=sell BTC) + order_amount = int(btc * b.getBtcMultiplier()) # 1 BTC = 100000000 + order_price = int(koers_in_eur * b.getEurMultiplier()) # 1 EUR = 100000 + d(b.addOrder(market, order_type, order_amount, order_price)) + ''' + ''' + market = 'BTC' + order_id = 0 + d(b.cancelOrder(market, order_id)) + ''' + ''' + market = 'BTC' + order_id = 0 + d(b.orderInfo(market, order_id)) + ''' + ''' + market = 'BTC' + d(b.fullDepth(market)) + ''' + ''' + market = 'BTC' + d(b.getNewDepositAddress(market)) + ''' + ''' + market = 'BTC' + d(b.getLastDepositAddress(market)) + ''' + ''' + market = 'BTC' + trade_id = 0 + d(b.fetchLast1000Trades(market, trade_id)) + ''' + ''' + currency = 'BTC' + n = 10 + d(b.walletHistory(currency, n)) + ''' + ''' + market = 'BTC' + d(b.getAllActiveOrders(market)) + ''' +# ''' + d(b.getBalances()) +# ''' + + +if __name__ == '__main__': + main() + diff --git a/examples/python3/setup.py b/examples/python3/setup.py new file mode 100644 index 0000000..4630b64 --- /dev/null +++ b/examples/python3/setup.py @@ -0,0 +1,20 @@ +from setuptools import setup, find_packages + + +setup( + name='bl3p', + version='20180412.0', + description='BL3P.eu Python 3 exchange API', + keywords='bl3p python3 exchange api', + url='https://github.com/joosthoeks/bl3p-api', + author='Joost Hoeks', + author_email='joosthoeks@gmail.com', + license='GNU', + packages=find_packages(), + install_requires=[ +# 'numpy', +# 'pandas', + ], + zip_safe=False +) +