feather-ws -> wowlet-backend

tempfix
dsc 3 years ago
parent 04e10f6d2b
commit abfe22e89c

@ -10,7 +10,7 @@ Back-end websocket server for Feather wallet.
- Monero - Monero
- Wownero - Wownero
See also the environment variables `FEATHER_COIN_NAME`, `FEATHER_COIN_SYMBOL`, etc. in `settings.py`. See also the environment variables `WOWLET_COIN_NAME`, `WOWLET_COIN_SYMBOL`, etc. in `settings.py`.
## Tasks ## Tasks
@ -26,7 +26,7 @@ When Feather wallet starts up, it will connect to
this websocket server and receive the information this websocket server and receive the information
listed above which is necessary for normal operation. listed above which is necessary for normal operation.
See `fapi.tasks.*` for the various tasks. See `wowlet_backend.tasks.*` for the various tasks.
## Development ## Development
@ -37,7 +37,7 @@ virtualenv -p /usr/bin/python3 venv
source venv/bin/activate source venv/bin/activate
pip install -r requirements.txt pip install -r requirements.txt
export FEATHER_DEBUG=true export WOWLET_DEBUG=true
python run.py python run.py
``` ```

@ -2,5 +2,5 @@
# Copyright (c) 2020, The Monero Project. # Copyright (c) 2020, The Monero Project.
# Copyright (c) 2020, dsc@xmr.pm # Copyright (c) 2020, dsc@xmr.pm
from fapi.factory import create_app from wowlet_backend_backend.factory import create_app
app = create_app() app = create_app()

@ -16,12 +16,12 @@ services:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
environment: environment:
- FEATHER_DEBUG=false - WOWLET_DEBUG=false
- FEATHER_PORT=1337 - WOWLET_PORT=1337
- FEATHER_REDIS_ADDRESS=redis://redis - WOWLET_REDIS_ADDRESS=redis://redis
- FEATHER_TOR_SOCKS_PROXY=socks5://tor-node:9050 - WOWLET_TOR_SOCKS_PROXY=socks5://tor-node:9050
- FEATHER_COIN_NAME=monero - WOWLET_COIN_NAME=monero
- FEATHER_COIN_SYMBOL=xmr - WOWLET_COIN_SYMBOL=xmr
- FEATHER_COIN_MODE=mainnet - WOWLET_COIN_MODE=mainnet
ports: ports:
- "1337:1337" - "1337:1337"

@ -2,7 +2,7 @@
# Copyright (c) 2020, The Monero Project. # Copyright (c) 2020, The Monero Project.
# Copyright (c) 2020, dsc@xmr.pm # Copyright (c) 2020, dsc@xmr.pm
from fapi.factory import create_app from wowlet_backend.factory import create_app
import settings import settings
app = create_app() app = create_app()

@ -10,19 +10,19 @@ def bool_env(val):
return val is True or (isinstance(val, str) and (val.lower() == 'true' or val == '1')) return val is True or (isinstance(val, str) and (val.lower() == 'true' or val == '1'))
DEBUG = bool_env(os.environ.get("FEATHER_DEBUG", False)) DEBUG = bool_env(os.environ.get("WOWLET_DEBUG", False))
HOST = os.environ.get("FEATHER_HOST", "127.0.0.1") HOST = os.environ.get("WOWLET_HOST", "127.0.0.1")
PORT = int(os.environ.get("FEATHER_PORT", 1337)) PORT = int(os.environ.get("WOWLET_PORT", 1337))
REDIS_ADDRESS = os.environ.get("FEATHER_REDIS_ADDRESS", "redis://localhost") REDIS_ADDRESS = os.environ.get("WOWLET_REDIS_ADDRESS", "redis://localhost")
REDIS_PASSWORD = os.environ.get("FEATHER_REDIS_PASSWORD") REDIS_PASSWORD = os.environ.get("WOWLET_REDIS_PASSWORD")
COIN_NAME = os.environ.get("FEATHER_COIN_NAME", "monero").lower() # as per coingecko COIN_NAME = os.environ.get("WOWLET_COIN_NAME", "monero").lower() # as per coingecko
COIN_SYMBOL = os.environ.get("FEATHER_COIN_SYMBOL", "xmr").lower() # as per coingecko COIN_SYMBOL = os.environ.get("WOWLET_COIN_SYMBOL", "xmr").lower() # as per coingecko
COIN_GENESIS_DATE = os.environ.get("FEATHER_COIN_GENESIS_DATE", "20140418") COIN_GENESIS_DATE = os.environ.get("WOWLET_COIN_GENESIS_DATE", "20140418")
COIN_MODE = os.environ.get("FEATHER_COIN_MODE", "mainnet").lower() COIN_MODE = os.environ.get("WOWLET_COIN_MODE", "mainnet").lower()
TOR_SOCKS_PROXY = os.environ.get("FEATHER_TOR_SOCKS_PROXY", "socks5://127.0.0.1:9050") TOR_SOCKS_PROXY = os.environ.get("WOWLET_TOR_SOCKS_PROXY", "socks5://127.0.0.1:9050")
# while fetching USD price from coingecko, also include these extra coins: # while fetching USD price from coingecko, also include these extra coins:
CRYPTO_RATES_COINS_EXTRA = { CRYPTO_RATES_COINS_EXTRA = {

@ -11,7 +11,7 @@ from quart import Quart
from quart_session import Session from quart_session import Session
import aioredis import aioredis
from fapi.utils import current_worker_thread_is_primary, print_banner from wowlet_backend.utils import current_worker_thread_is_primary, print_banner
import settings import settings
now = datetime.now() now = datetime.now()
@ -56,7 +56,7 @@ async def _setup_tasks(app: Quart):
if not _is_primary_worker_thread: if not _is_primary_worker_thread:
return return
from fapi.tasks import ( from wowlet_backend.tasks import (
BlockheightTask, HistoricalPriceTask, FundingProposalsTask, BlockheightTask, HistoricalPriceTask, FundingProposalsTask,
CryptoRatesTask, FiatRatesTask, RedditTask, RPCNodeCheckTask, CryptoRatesTask, FiatRatesTask, RedditTask, RPCNodeCheckTask,
XmrigTask, XmrToTask) XmrigTask, XmrToTask)
@ -72,9 +72,6 @@ async def _setup_tasks(app: Quart):
if settings.COIN_SYMBOL in ["xmr", "wow"]: if settings.COIN_SYMBOL in ["xmr", "wow"]:
asyncio.create_task(FundingProposalsTask().start()) asyncio.create_task(FundingProposalsTask().start())
if settings.COIN_SYMBOL == "xmr":
asyncio.create_task(XmrToTask().start())
def _setup_logging(): def _setup_logging():
from logging import Formatter from logging import Formatter
@ -111,6 +108,6 @@ def create_app():
await _setup_user_agents(app) await _setup_user_agents(app)
await _setup_tasks(app) await _setup_tasks(app)
import fapi.routes import wowlet_backend.routes
return app return app

@ -7,9 +7,9 @@ import json
from quart import websocket, jsonify from quart import websocket, jsonify
from fapi.factory import app from wowlet_backend.factory import app
from fapi.wsparse import WebsocketParse from wowlet_backend.wsparse import WebsocketParse
from fapi.utils import collect_websocket, feather_data from wowlet_backend.utils import collect_websocket, feather_data
@app.route("/") @app.route("/")

@ -39,7 +39,7 @@ class FeatherTask:
self._running = False self._running = False
async def start(self, *args, **kwargs): async def start(self, *args, **kwargs):
from fapi.factory import app, connected_websockets from wowlet_backend.factory import app, connected_websockets
if not self._active: if not self._active:
# invalid task # invalid task
return return
@ -124,7 +124,7 @@ class FeatherTask:
raise NotImplementedError() raise NotImplementedError()
async def cache_json_get(self, key: str, path="."): async def cache_json_get(self, key: str, path="."):
from fapi.factory import app, cache from wowlet_backend.factory import app, cache
try: try:
data = await cache.execute('JSON.GET', key, path) data = await cache.execute('JSON.GET', key, path)
@ -134,7 +134,7 @@ class FeatherTask:
app.logger.error(f"Redis error: {ex}") app.logger.error(f"Redis error: {ex}")
async def cache_get(self, key: str) -> dict: async def cache_get(self, key: str) -> dict:
from fapi.factory import app, cache from wowlet_backend.factory import app, cache
try: try:
data = await cache.get(key) data = await cache.get(key)
@ -145,7 +145,7 @@ class FeatherTask:
app.logger.error(f"Redis GET error with key '{key}': {ex}") app.logger.error(f"Redis GET error with key '{key}': {ex}")
async def cache_set(self, key, val: Union[dict, int], expiry: int = 0) -> bool: async def cache_set(self, key, val: Union[dict, int], expiry: int = 0) -> bool:
from fapi.factory import app, cache from wowlet_backend.factory import app, cache
try: try:
data = json.dumps(val) data = json.dumps(val)
if isinstance(expiry, int) and expiry > 0: if isinstance(expiry, int) and expiry > 0:
@ -157,12 +157,12 @@ class FeatherTask:
app.logger.error(f"Redis SET error with key '{key}': {ex}") app.logger.error(f"Redis SET error with key '{key}': {ex}")
from fapi.tasks.proposals import FundingProposalsTask from wowlet_backend.tasks.proposals import FundingProposalsTask
from fapi.tasks.historical_prices import HistoricalPriceTask from wowlet_backend.tasks.historical_prices import HistoricalPriceTask
from fapi.tasks.blockheight import BlockheightTask from wowlet_backend.tasks.blockheight import BlockheightTask
from fapi.tasks.rates_fiat import FiatRatesTask from wowlet_backend.tasks.rates_fiat import FiatRatesTask
from fapi.tasks.rates_crypto import CryptoRatesTask from wowlet_backend.tasks.rates_crypto import CryptoRatesTask
from fapi.tasks.reddit import RedditTask from wowlet_backend.tasks.reddit import RedditTask
from fapi.tasks.rpc_nodes import RPCNodeCheckTask from wowlet_backend.tasks.rpc_nodes import RPCNodeCheckTask
from fapi.tasks.xmrig import XmrigTask from wowlet_backend.tasks.xmrig import XmrigTask
from fapi.tasks.xmrto import XmrToTask from wowlet_backend.tasks.xmrto import XmrToTask

@ -8,8 +8,8 @@ from collections import Counter
from functools import partial from functools import partial
import settings import settings
from fapi.utils import httpget, popularity_contest from wowlet_backend.utils import httpget, popularity_contest
from fapi.tasks import FeatherTask from wowlet_backend.tasks import FeatherTask
class BlockheightTask(FeatherTask): class BlockheightTask(FeatherTask):
@ -81,7 +81,7 @@ class BlockheightTask(FeatherTask):
} }
async def task(self) -> Union[dict, None]: async def task(self) -> Union[dict, None]:
from fapi.factory import app from wowlet_backend.factory import app
coin_network_types = ["mainnet", "stagenet", "testnet"] coin_network_types = ["mainnet", "stagenet", "testnet"]
data = {t: 0 for t in coin_network_types} data = {t: 0 for t in coin_network_types}

@ -11,8 +11,8 @@ from datetime import datetime
import aiofiles import aiofiles
import settings import settings
from fapi.utils import httpget from wowlet_backend.utils import httpget
from fapi.tasks import FeatherTask from wowlet_backend.tasks import FeatherTask
class HistoricalPriceTask(FeatherTask): class HistoricalPriceTask(FeatherTask):
@ -91,7 +91,7 @@ class HistoricalPriceTask(FeatherTask):
"""This function is called when a Feather wallet client asks """This function is called when a Feather wallet client asks
for (a range of) historical fiat information. It returns the for (a range of) historical fiat information. It returns the
data filtered by the parameters.""" data filtered by the parameters."""
from fapi.factory import cache from wowlet_backend.factory import cache
blob = await cache.get("historical_fiat") blob = await cache.get("historical_fiat")
blob = json.loads(blob) blob = json.loads(blob)

@ -6,14 +6,14 @@ from bs4 import BeautifulSoup
from typing import List from typing import List
import settings import settings
from fapi.utils import httpget from wowlet_backend.utils import httpget
from fapi.tasks import FeatherTask from wowlet_backend.tasks import FeatherTask
class FundingProposalsTask(FeatherTask): class FundingProposalsTask(FeatherTask):
"""Fetch funding proposals made by the community.""" """Fetch funding proposals made by the community."""
def __init__(self, interval: int = 600): def __init__(self, interval: int = 600):
from fapi.factory import app from wowlet_backend.factory import app
super(FundingProposalsTask, self).__init__(interval) super(FundingProposalsTask, self).__init__(interval)
self._cache_key = "funding_proposals" self._cache_key = "funding_proposals"
@ -58,7 +58,7 @@ class FundingProposalsTask(FeatherTask):
# - API does not allow filtering # - API does not allow filtering
# - API sometimes breaks; https://hackerone.com/reports/934231 # - API sometimes breaks; https://hackerone.com/reports/934231
# we'll web scrape instead # we'll web scrape instead
from fapi.factory import app from wowlet_backend.factory import app
content = await httpget(f"{self._http_endpoint}/funding-required/", json=False) content = await httpget(f"{self._http_endpoint}/funding-required/", json=False)
soup = BeautifulSoup(content, "html.parser") soup = BeautifulSoup(content, "html.parser")

@ -5,8 +5,8 @@
from typing import List, Union from typing import List, Union
import settings import settings
from fapi.utils import httpget from wowlet_backend.utils import httpget
from fapi.tasks import FeatherTask from wowlet_backend.tasks import FeatherTask
class CryptoRatesTask(FeatherTask): class CryptoRatesTask(FeatherTask):
@ -22,7 +22,7 @@ class CryptoRatesTask(FeatherTask):
async def task(self) -> Union[List[dict], None]: async def task(self) -> Union[List[dict], None]:
"""Fetch USD prices for various coins""" """Fetch USD prices for various coins"""
from fapi.factory import app from wowlet_backend.factory import app
url = f"{self._http_api_gecko}/coins/markets?vs_currency=usd" url = f"{self._http_api_gecko}/coins/markets?vs_currency=usd"
rates = await httpget(url, json=True) rates = await httpget(url, json=True)

@ -2,8 +2,8 @@
# Copyright (c) 2020, The Monero Project. # Copyright (c) 2020, The Monero Project.
# Copyright (c) 2020, dsc@xmr.pm # Copyright (c) 2020, dsc@xmr.pm
from fapi.utils import httpget from wowlet_backend.utils import httpget
from fapi.tasks import FeatherTask from wowlet_backend.tasks import FeatherTask
class FiatRatesTask(FeatherTask): class FiatRatesTask(FeatherTask):

@ -4,13 +4,13 @@
import html import html
import settings import settings
from fapi.utils import httpget from wowlet_backend.utils import httpget
from fapi.tasks import FeatherTask from wowlet_backend.tasks import FeatherTask
class RedditTask(FeatherTask): class RedditTask(FeatherTask):
def __init__(self, interval: int = 900): def __init__(self, interval: int = 900):
from fapi.factory import app from wowlet_backend.factory import app
super(RedditTask, self).__init__(interval) super(RedditTask, self).__init__(interval)
self._cache_key = "reddit" self._cache_key = "reddit"
@ -36,7 +36,7 @@ class RedditTask(FeatherTask):
self._http_endpoint = self._http_endpoint[:-1] self._http_endpoint = self._http_endpoint[:-1]
async def task(self): async def task(self):
from fapi.factory import app from wowlet_backend.factory import app
url = f"{self._http_endpoint}/new.json?limit=15" url = f"{self._http_endpoint}/new.json?limit=15"
try: try:

@ -6,8 +6,8 @@ import json
from typing import List from typing import List
import settings import settings
from fapi.utils import httpget, popularity_contest from wowlet_backend.utils import httpget, popularity_contest
from fapi.tasks import FeatherTask from wowlet_backend.tasks import FeatherTask
class RPCNodeCheckTask(FeatherTask): class RPCNodeCheckTask(FeatherTask):
@ -24,7 +24,7 @@ class RPCNodeCheckTask(FeatherTask):
async def task(self) -> List[dict]: async def task(self) -> List[dict]:
"""Check RPC nodes status""" """Check RPC nodes status"""
from fapi.factory import app, cache from wowlet_backend.factory import app, cache
try: try:
heights = json.loads(await cache.get("blockheights")) heights = json.loads(await cache.get("blockheights"))

@ -5,8 +5,8 @@
from dateutil.parser import parse from dateutil.parser import parse
import settings import settings
from fapi.utils import httpget from wowlet_backend.utils import httpget
from fapi.tasks import FeatherTask from wowlet_backend.tasks import FeatherTask
class XmrigTask(FeatherTask): class XmrigTask(FeatherTask):

@ -3,8 +3,8 @@
# Copyright (c) 2020, dsc@xmr.pm # Copyright (c) 2020, dsc@xmr.pm
import settings import settings
from fapi.utils import httpget from wowlet_backend.utils import httpget
from fapi.tasks import FeatherTask from wowlet_backend.tasks import FeatherTask
class XmrToTask(FeatherTask): class XmrToTask(FeatherTask):

@ -35,7 +35,7 @@ def print_banner():
def collect_websocket(func): def collect_websocket(func):
@wraps(func) @wraps(func)
async def wrapper(*args, **kwargs): async def wrapper(*args, **kwargs):
from fapi.factory import connected_websockets from wowlet_backend.factory import connected_websockets
queue = asyncio.Queue() queue = asyncio.Queue()
connected_websockets.add(queue) connected_websockets.add(queue)
try: try:
@ -63,14 +63,14 @@ async def httpget(url: str, json=True, timeout: int = 5, socks5: str = None, rai
def random_agent(): def random_agent():
from fapi.factory import user_agents from wowlet_backend.factory import user_agents
return random.choice(user_agents) return random.choice(user_agents)
async def feather_data(): async def feather_data():
"""A collection of data collected by """A collection of data collected by
`FeatherTask`, for Feather wallet clients.""" `FeatherTask`, for Feather wallet clients."""
from fapi.factory import cache, now from wowlet_backend.factory import cache, now
data = await cache.get("data") data = await cache.get("data")
if data: if data:
data = json.loads(data) data = json.loads(data)
@ -110,7 +110,7 @@ def current_worker_thread_is_primary() -> bool:
current instance is responsible for the current instance is responsible for the
recurring Feather tasks. recurring Feather tasks.
""" """
from fapi.factory import app from wowlet_backend.factory import app
current_pid = os.getpid() current_pid = os.getpid()
parent_pid = os.getppid() parent_pid = os.getppid()

@ -21,5 +21,5 @@ class WebsocketParse:
year = data.get('year') year = data.get('year')
month = data.get('month') month = data.get('month')
from fapi.tasks.historical_prices import HistoricalPriceTask from wowlet_backend.tasks.historical_prices import HistoricalPriceTask
return await HistoricalPriceTask.get(year, month) return await HistoricalPriceTask.get(year, month)
Loading…
Cancel
Save