Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial structure #1

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,96 @@
# client-py

## Install (Python 3)

To install this package you should execute the command below. (but this is in tests yet)

```console
pip install git+https://github.com/OmniTrade/client-py.git
```
Another way to install this package, you should clone this repository with:

```console
git clone https://github.com/OmniTrade/client-py.git
cd client-py
```

and to install, please execute:

```console
python3 setup.py install
```

## Usage

Require the client in your code by adding:


```python
from omnitradeClient import Client
from omnitradeClient import StreamingClient
```

You can use both the public or private API.
#### Note:

Every http requests will returns a `<class 'requests.models.Response'>` object, so use that as you want.

### Public
------

Instance your public client by using:

```python
public_client = Client()
```

#### .get_public

Use **`.get_public`** to make a GET request to an URL, as the following example:

```python
client_public.get_public('/api/v2/markets')
```

### Private
------

When using the private client, you also have to specify your access and private keys in the instantiation:

```python
private_client = Client(access_key = 'your_access_key', secret_key = 'your_secret_key')
```

You can also set a timeout and/or endpoit by adding the arguments:

```python
private_client = Client(access_key = 'your_access_key', secret_key = 'your_secret_key', timeout = 60, endpoint = 'https://omnitrade.io/')
```
#### .get

Use **`.get`** to make a GET request to an URL, you can also set the required arguments, as the following example:

```python
private_client.get('/api/v2/orders', market = 'btcbrl')
```

#### .post

Use **`.post`** to make a POST request to an URL, you can also set the required arguments, as the following example:

```python
private_client.post('/api/v2/order', market = 'btcbrl', side = 'buy', volume = '0.42', price = '4200.0')
```

### WebSocket
------

```python
streaming_client = StreamingClient(callbackFunction, access_key = '123456', secret_key = '123412')
```

This `callbackFunction` must to receive one parameter.

## Licence

OmniTrade (C) All Rights Reserved.
112 changes: 112 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
alembic==0.9.3.dev0
apt-xapian-index==0.47
apturl==0.5.2
asn1crypto==0.24.0
astroid==2.3.3
Babel==2.4.0
beautifulsoup4==4.6.0
blinker==1.4
Brlapi==0.6.6
certifi==2019.11.28
chardet==3.0.4
click==6.7
colorama==0.3.7
command-not-found==0.3
cryptography==2.1.4
cupshelpers==1.0
defer==1.0.6
distro-info===0.18ubuntu0.18.04.1
evdev==0.7.0
Flask==0.12.2
Flask-BabelEx==0.9.3
Flask-Compress==1.4.0
Flask-Gravatar==0.4.2
Flask-Login==0.4.0
Flask-Mail==0.9.1
Flask-Migrate==2.1.1
Flask-Paranoid==0.2.0
Flask-Principal==0.4.0
Flask-Security==1.7.5
Flask-SQLAlchemy==2.1
Flask-WTF==0.14.2
gevent==1.4.0
greenlet==0.4.15
html5lib==0.999999999
httplib2==0.9.2
idna==2.9
isort==4.3.21
itsdangerous==0.24
Jinja2==2.10
keyring==10.6.0
keyrings.alt==3.0
language-selector==0.1
launchpadlib==1.10.6
lazr.restfulclient==0.13.5
lazr.uri==1.0.3
lazy-object-proxy==1.4.3
logging==0.4.9.6
louis==3.5.0
lxml==4.2.1
macaroonbakery==1.1.3
Mako==1.0.7
MarkupSafe==1.0
mccabe==0.6.1
mock==4.0.1
netifaces==0.10.4
nose==1.3.7
oauth==1.0.1
olefile==0.45.1
omnitrade-client==0.1
omnitradeClient==0.2
paramiko==2.0.0
passlib==1.7.1
pexpect==4.2.1
Pillow==5.1.0
protobuf==3.0.0
psutil==5.4.2
psycopg2==2.8.4
pyasn1==0.4.2
pycairo==1.16.2
pycrypto==2.6.1
pycups==1.9.73
pygobject==3.26.1
pyinotify==0.9.6
pylint==2.4.4
pymacaroons==0.13.0
PyNaCl==1.1.2
pynotify==0.1.1
pyOpenSSL==17.5.0
pyRFC3339==1.0
python-apt==1.6.5+ubuntu0.2
python-dateutil==2.6.1
python-debian==0.1.32
pytz==2018.3
pyxdg==0.25
PyYAML==3.12
reportlab==3.4.0
requests==2.23.0
requests-unixsocket==0.1.5
screen-resolution-extra==0.0.0
SecretStorage==2.3.1
simple-websocket-server==0.4.0
simplejson==3.13.2
six==1.14.0
SQLAlchemy==1.1.11
sqlparse==0.2.4
sshtunnel==0.1.4
system-service==0.3
systemd-python==234
typed-ast==1.4.1
ubuntu-drivers-common==0.0.0
ufw==0.36
unattended-upgrades==0.1
urllib3==1.25.8
wadllib==1.3.2
webencodings==0.5
websocket==0.2.1
websockets==8.1
Werkzeug==0.16.0
wrapt==1.11.2
WTForms==2.1
xkit==0.0.0
zope.interface==4.3.2
27 changes: 27 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from setuptools import find_packages
from setuptools import setup

from glob import glob
from os.path import basename
from os.path import dirname
from os.path import join
from os.path import splitext


setup(
name="omnitradeClient",
version="0.1.0",
license="MIT license",
description="Python client for Omnitrade API",
author="Omnitrade",
author_email="@codeminer42.com",
url="https://github.com/OmniTrade/client-py",
packages=find_packages("src"),
package_dir={"": "src/"},
py_modules=[splitext(basename(path))[0] for path in glob("src/omnitradeClient/*.py")],
include_package_data=True,
zip_safe=False,
keywords=["omnitrade", "api"],
install_requires=open("requirements.txt").readlines(),
extras_require={}
)
2 changes: 2 additions & 0 deletions src/omnitradeClient/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .client import Client
from .streaming_client import StreamingClient
37 changes: 37 additions & 0 deletions src/omnitradeClient/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from platform import python_version
if '2.7' in python_version():
import urllib
else:
import urllib.parse as urllib
import hashlib
import hmac
import time
from .ordered_dict import ordered_dict

class Auth(object):
def __init__(self, access_key, secret_key):
self.access_key = access_key
self.secret_key = secret_key

def signed_challenge(self, challenge):
signature = hmac.new(str(self.secret_key).encode(),"{access_key}{challenge}".format(access_key=self.access_key, challenge=challenge).encode(), hashlib.sha256).hexdigest()

return { 'auth': { 'access_key': self.access_key, 'answer': signature } }

def signed_params(self, verb, path, **params):
sign_params = self.__format_params(params)

signature = self.__sign(verb, path, urllib.urlencode(sign_params))
params['signature'] = signature
return params

def __sign(self, verb, path, params):
return hmac.new(self.secret_key.encode(), self.__payload(verb, path, params).encode(), hashlib.sha256).hexdigest()

def __payload(self, verb, path, params):
return "{verb}|{path}|{params}".format(verb = verb.upper(), path = path, params = params)

def __format_params(self, params):
params['access_key'] = self.access_key
params['tonce'] = int(time.time()) * 1000
return ordered_dict(params)
61 changes: 61 additions & 0 deletions src/omnitradeClient/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from platform import python_version
if '2.7' in python_version():
import urllib
else:
import urllib.parse as urllib
import requests
from .auth import Auth
from .ordered_dict import ordered_dict

OMNITRADE_URL = 'https://omnitrade.io/'
class Client(object):
def __init__(self, **options):
self.auth = None
self.__setup_auth_keys(options)

self.endpoint = options['endpoint'] if 'endpoint' in options.keys() else OMNITRADE_URL
self.timeout = options['timeout'] if 'timeout' in options.keys() else 60

def get_public(self, path, params={}):
uri, params = self.__parameters('GET',path, params)
return self.__get_request(uri, params)


def get(self, path, **params):
self.__check_auth()

uri, params = self.__parameters('GET',path, params)
return self.__get_request(uri, params)

def post(self, path, **params):
self.__check_auth()

uri, params = self.__parameters('POST', path, params)
return self.__post_request(uri, params)

def __setup_auth_keys(self, options):
if not('access_key' in options.keys() and 'secret_key' in options.keys()):
return

self.access_key = options['access_key']
self.secret_key = options['secret_key']
self.auth = Auth(self.access_key, self.secret_key)


def __check_auth(self):
if self.auth == None:
raise Exception('Missing access key and/or secret key')

def __get_request(self, uri, params):
return requests.get(uri, params = urllib.urlencode(params))

def __post_request(self, uri, params):
return requests.post(uri, params = urllib.urlencode(params))

def __parameters(self, action, path, params):
uri = '{endpoint}{path}'.format(endpoint=self.endpoint, path=path)
dict_params = self.auth.signed_params(action, path, **params) if self.auth != None else params

return uri, ordered_dict(dict_params)


2 changes: 2 additions & 0 deletions src/omnitradeClient/ordered_dict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def ordered_dict(dict_params):
return [(key, dict_params[key]) for key in sorted(dict_params.keys())]
47 changes: 47 additions & 0 deletions src/omnitradeClient/streaming_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import websocket
import logging
import json
import ast
from .client import Client

logging.basicConfig(level=logging.INFO)

OMNITRADE_URL = 'wss://omnitrade.com:8080'
class StreamingClient(Client):
def __init__(self, callback, **options):
super(StreamingClient, self).__init__(**options)
self.endpoint = options['endpoint'] if 'endpoint' in options.keys() else OMNITRADE_URL
self.logger = options['logger'] if 'logger' in options.keys() else logging

websocket.enableTrace(True)

self.callback = callback
self.ws = websocket.WebSocketApp(self.endpoint,
on_message = self.on_message,
on_error = self.on_error,
on_close = self.on_close)
self.ws.on_open = self.on_open
self.ws.run_forever()

def on_message(self, message):
msg = ast.literal_eval(message.decode())

key = msg.keys()[0]
data = msg[key]
if data != None and key == 'challenge':
self.ws.send(str(self.auth.signed_challenge(data)).encode())
else:
try:
self.callback(msg)
except Exception as e:
self.logger.error("Failed to process message: {error}".format(error=e))

def on_error(self, error):
self.logger.info(error)

def on_close(self):
self.ws.close()
self.logger.info("### closed ###")

def on_open(self):
self.logger.info("Connected")
Loading