Skip to content
This repository has been archived by the owner on Aug 29, 2023. It is now read-only.

Docker support #11

Open
wants to merge 4 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
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.idea
*.pyc
config/main.yml
env/
.env
7 changes: 3 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
.idea
*.pyc
configs/client_secret.json
configs/poloniex_keys.py
configs/kraken_keys.py
configs/main.yml
config/main.yml
env/
.env

18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Use an official Python runtime as a parent image
FROM python:3.6-slim

# Install any needed packages specified in requirements.txt
COPY requirements.txt /tmp/requirements.txt
RUN pip3 install -r /tmp/requirements.txt

# Copy the current directory contents into the container at /app
ADD . /app

# Set the working directory to /app
WORKDIR /app

EXPOSE 8888

# Run app.py when the container launches
CMD ["python3", "server.py"]

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
Requires authorisation via etherionlab@gmail.com

## Config
Default config path is `configs/main.yml`
App can be configured using environment variables or using yaml config file and `--config` command line option

You need to fill config file with your credentials information. For example see [example.yml](configs/example.yml)
You need to fill config file your credentials information. For example see [example.yml](config/example.yml)


## Server endpoints
Expand Down
51 changes: 51 additions & 0 deletions config/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import os
import logging

logger = logging.getLogger(__name__)

STRUCTURE = {
'bugsnag': {
'api_key': 'BUGSNAG_API_KEY',
},
'kraken': {
'key': 'KRAKEN_KEY',
'secret': 'KRAKEN_SECRET',
},
'poloniex': {
'key': 'POLONIEX_KEY',
'secret': 'POLONIEX_SECRET',
},
'bitstamp': {
'key': 'BITSTAMP_KEY',
'secret': 'BITSTAMP_SECRET',
'customer_id': 'BITSTAMP_CUSTOMER_ID',
},
'sheets': {
'auth_provider_x509_cert_url': 'SHEETS_AUTH_PROVIDER_X509_CERT_URL',
'auth_uri': 'SHEETS_AUTH_URI',
'client_email': 'SHEETS_CLIENT_EMAIL',
'client_id': 'SHEETS_CLIENT_ID',
'client_x509_cert_url': 'SHEETS_CLIENT_X509_CERT_URL',
'private_key': 'SHEETS_PRIVATE_KEY',
'private_key_id': 'SHEETS_PRIVATE_KEY_ID',
'project_id': 'SHEETS_PROJECT_ID',
'sheet_id': 'SHEETS_SHEET_ID',
'token_uri': 'SHEETS_TOKEN_URI',
'type': 'SHEETS_TYPE',
},
}

def _fill_structure(d):
if type(d) is str:
return os.environ.get(d).replace('\\\\n', '\n')
res = {}
for key, value in d.items():
res[key] = _fill_structure(d[key])
return res

def config_from_env():
config = _fill_structure(STRUCTURE)

logger.debug(str(config))
return config

25 changes: 25 additions & 0 deletions config/example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
kraken:
secret: "put your kraken secret here" # KRAKEN_SECRET
key: "put your kraken key here" # KRAKEN_KEY
poloniex:
secret: "put your poloniex secret here" # POLONIEX_SECRET
key: "put your poloniex key here" # POLONIEX_key
bitstamp:
secret: "put your bitstamp secret here" # BITSTAMP_SECRET
key: "put your bitstamp key here" # BITSTAMP_KEY
customer_id: "put your bitstamp customer id here" # BITSTAMP_CUSTOMER_ID
bugsnag:
api_key: 'bugsnag api key here' # BUGSNAG_API_KEY
sheets:
sheet_id: 'your google sheet id' # SHEETS_SHEET_ID
# Google API service account key data (from json)
auth_provider_x509_cert_url: https://www.googleapis.com/oauth2/v1/certs # SHEETS_AUTH_PROVIDER_X509_CERT_URL
auth_uri: https://accounts.google.com/o/oauth2/auth # SHEETS_AUTH_URI
token_uri: https://accounts.google.com/o/oauth2/token # SHEETS_TOKEN_URI
type: service_account # SHEETS_TYPE
client_email: '' # SHEETS_CLIENT_EMAIL
client_id: '' # SHEETS_CLIENT_ID
client_x509_cert_url: '' # SHEETS_CLIENT_X509_CERT_URL
private_key: '' # SHEETS_PRIVATE_KEY
private_key_id: '' # SHEETS_PRIVATE_KEY_ID
project_id: '' # SHEETS_PROJECT_ID
15 changes: 0 additions & 15 deletions configs/example.yml

This file was deleted.

3 changes: 2 additions & 1 deletion fetchers/portfolio.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ def fetch_portfolio(balances=None, prices=None):
portfolio[symbol] = {
'USD': balances.get(symbol) * float(prices.get(symbol).get('USD')),
'BTC': balances.get(symbol) * float(prices.get(symbol).get('BTC')),
'ETH': balances.get(symbol) * float(prices.get(symbol).get('BTC')) / float(prices.get('ETH').get('BTC')),
'ETH': balances.get(symbol) * float(prices.get(symbol).get('BTC')) / float(
prices.get('ETH').get('BTC')),
'share': balances.get(symbol) * float(prices.get(symbol).get('USD')) / whole_usd_price,
}
return portfolio
4 changes: 2 additions & 2 deletions models/coinmarketcap.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import aiohttp
import asyncio
import json

from .fetcher import Fetcher
Expand Down Expand Up @@ -37,7 +36,8 @@ async def request_assets(self, loop, assets, callback=None):
asset.get("symbol"),
asset.get("price_usd"),
asset.get("price_btc"),
int(asset.get("last_updated", -1)) or -1) for asset in ticker if asset.get("symbol") in assets]
int(asset.get("last_updated", -1)) or -1)
for asset in ticker if asset.get("symbol") in assets]
if callback is not None:
callback(prices)
return prices
9 changes: 6 additions & 3 deletions models/dash.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import aiohttp
import json
import logging

from .fetcher import Fetcher

logger = logging.getLogger(__name__)


class DashAPI(Fetcher):

Expand All @@ -22,9 +25,9 @@ async def get_dash_balance(self, loop, address, symbol='DASH', callback=None):
except TypeError as _:
try:
err_mess = response.get("error")
print(err_mess)
logger.error("No balance:", err_mess)
except Exception as _:
print("Something strange happened with Dash API.")
logger.error("Something strange happened with Dash API.")
if callback is not None:
callback(symbol, balance)
return symbol, balance
return symbol, balance
5 changes: 4 additions & 1 deletion models/etcchain.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import aiohttp
import json
import logging

from .fetcher import Fetcher

logger = logging.getLogger(__name__)


class EtcChainAPI(Fetcher):

Expand All @@ -19,7 +22,7 @@ async def get_etc_balance(self, loop, address, symbol='ETC', callback=None):
try:
balance = float(response.get('balance', -1))
except TypeError as _:
print("You provided wrong address!")
logger.error("Wrong address provided")
if callback is not None:
callback(symbol, balance)
return symbol, balance
15 changes: 12 additions & 3 deletions models/etherscan.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import aiohttp
import json
import logging

from .fetcher import Fetcher

logger = logging.getLogger(__name__)


class EtherscanAPI(Fetcher):

Expand Down Expand Up @@ -68,7 +71,13 @@ async def get_tokens_balance(self, loop, address, token, decimals=None, callback
callback(token, amount)
return token, amount

async def get_tokens_balance_by_address(self, loop, address, token, contract_address=None, decimals=None, callback=None):
async def get_tokens_balance_by_address(self,
loop,
address,
token,
contract_address=None,
decimals=None,
callback=None):
if address is None:
raise ValueError("address must be specified")
if decimals is None:
Expand All @@ -82,7 +91,7 @@ async def get_tokens_balance_by_address(self, loop, address, token, contract_add
response = json.loads(response)
message = response.get('message')
if message == 'NOTOK':
print("{} doesn't exist".format(token))
logger.error("{} doesn't exist".format(token))
return
amount = float(response.get('result')) / (10 ** decimals)
if callback is not None:
Expand All @@ -96,7 +105,7 @@ async def get_total_supply(self, loop, contract_address, callback):
response = json.loads(response)
message = response.get('message')
if message == 'NOTOK':
print("can't read total supply from contract {}".format(contract_address))
logger.error("Can't read total supply from contract {}".format(contract_address))
return
amount = float(response.get('result'))
callback(amount)
Expand Down
3 changes: 2 additions & 1 deletion models/fetcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ async def _fetch_post(self, session, url, data, headers=None, attempts=5):
with async_timeout.timeout(10):
async with session.post(url, data=data, headers=headers) as response:
result = await response.text()
if result is None: raise Exception()
if result is None:
raise Exception()
return result
except:
asyncio.sleep(1)
Loading