mirror of
https://git.wownero.com/wowlet/wowlet-backend.git
synced 2024-08-15 01:03:13 +00:00
feather-ws -> wowlet-backend
This commit is contained in:
parent
04e10f6d2b
commit
abfe22e89c
20 changed files with 72 additions and 75 deletions
|
@ -10,7 +10,7 @@ Back-end websocket server for Feather wallet.
|
|||
- Monero
|
||||
- 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
|
||||
|
||||
|
@ -26,7 +26,7 @@ When Feather wallet starts up, it will connect to
|
|||
this websocket server and receive the information
|
||||
listed above which is necessary for normal operation.
|
||||
|
||||
See `fapi.tasks.*` for the various tasks.
|
||||
See `wowlet_backend.tasks.*` for the various tasks.
|
||||
|
||||
## Development
|
||||
|
||||
|
@ -37,7 +37,7 @@ virtualenv -p /usr/bin/python3 venv
|
|||
source venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
|
||||
export FEATHER_DEBUG=true
|
||||
export WOWLET_DEBUG=true
|
||||
python run.py
|
||||
```
|
||||
|
||||
|
|
2
asgi.py
2
asgi.py
|
@ -2,5 +2,5 @@
|
|||
# Copyright (c) 2020, The Monero Project.
|
||||
# Copyright (c) 2020, dsc@xmr.pm
|
||||
|
||||
from fapi.factory import create_app
|
||||
from wowlet_backend_backend.factory import create_app
|
||||
app = create_app()
|
||||
|
|
|
@ -16,12 +16,12 @@ services:
|
|||
context: .
|
||||
dockerfile: Dockerfile
|
||||
environment:
|
||||
- FEATHER_DEBUG=false
|
||||
- FEATHER_PORT=1337
|
||||
- FEATHER_REDIS_ADDRESS=redis://redis
|
||||
- FEATHER_TOR_SOCKS_PROXY=socks5://tor-node:9050
|
||||
- FEATHER_COIN_NAME=monero
|
||||
- FEATHER_COIN_SYMBOL=xmr
|
||||
- FEATHER_COIN_MODE=mainnet
|
||||
- WOWLET_DEBUG=false
|
||||
- WOWLET_PORT=1337
|
||||
- WOWLET_REDIS_ADDRESS=redis://redis
|
||||
- WOWLET_TOR_SOCKS_PROXY=socks5://tor-node:9050
|
||||
- WOWLET_COIN_NAME=monero
|
||||
- WOWLET_COIN_SYMBOL=xmr
|
||||
- WOWLET_COIN_MODE=mainnet
|
||||
ports:
|
||||
- "1337:1337"
|
||||
|
|
2
run.py
2
run.py
|
@ -2,7 +2,7 @@
|
|||
# Copyright (c) 2020, The Monero Project.
|
||||
# Copyright (c) 2020, dsc@xmr.pm
|
||||
|
||||
from fapi.factory import create_app
|
||||
from wowlet_backend.factory import create_app
|
||||
import settings
|
||||
|
||||
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'))
|
||||
|
||||
|
||||
DEBUG = bool_env(os.environ.get("FEATHER_DEBUG", False))
|
||||
HOST = os.environ.get("FEATHER_HOST", "127.0.0.1")
|
||||
PORT = int(os.environ.get("FEATHER_PORT", 1337))
|
||||
DEBUG = bool_env(os.environ.get("WOWLET_DEBUG", False))
|
||||
HOST = os.environ.get("WOWLET_HOST", "127.0.0.1")
|
||||
PORT = int(os.environ.get("WOWLET_PORT", 1337))
|
||||
|
||||
REDIS_ADDRESS = os.environ.get("FEATHER_REDIS_ADDRESS", "redis://localhost")
|
||||
REDIS_PASSWORD = os.environ.get("FEATHER_REDIS_PASSWORD")
|
||||
REDIS_ADDRESS = os.environ.get("WOWLET_REDIS_ADDRESS", "redis://localhost")
|
||||
REDIS_PASSWORD = os.environ.get("WOWLET_REDIS_PASSWORD")
|
||||
|
||||
COIN_NAME = os.environ.get("FEATHER_COIN_NAME", "monero").lower() # as per coingecko
|
||||
COIN_SYMBOL = os.environ.get("FEATHER_COIN_SYMBOL", "xmr").lower() # as per coingecko
|
||||
COIN_GENESIS_DATE = os.environ.get("FEATHER_COIN_GENESIS_DATE", "20140418")
|
||||
COIN_MODE = os.environ.get("FEATHER_COIN_MODE", "mainnet").lower()
|
||||
COIN_NAME = os.environ.get("WOWLET_COIN_NAME", "monero").lower() # as per coingecko
|
||||
COIN_SYMBOL = os.environ.get("WOWLET_COIN_SYMBOL", "xmr").lower() # as per coingecko
|
||||
COIN_GENESIS_DATE = os.environ.get("WOWLET_COIN_GENESIS_DATE", "20140418")
|
||||
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:
|
||||
CRYPTO_RATES_COINS_EXTRA = {
|
||||
|
|
|
@ -11,7 +11,7 @@ from quart import Quart
|
|||
from quart_session import Session
|
||||
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
|
||||
|
||||
now = datetime.now()
|
||||
|
@ -56,7 +56,7 @@ async def _setup_tasks(app: Quart):
|
|||
if not _is_primary_worker_thread:
|
||||
return
|
||||
|
||||
from fapi.tasks import (
|
||||
from wowlet_backend.tasks import (
|
||||
BlockheightTask, HistoricalPriceTask, FundingProposalsTask,
|
||||
CryptoRatesTask, FiatRatesTask, RedditTask, RPCNodeCheckTask,
|
||||
XmrigTask, XmrToTask)
|
||||
|
@ -72,9 +72,6 @@ async def _setup_tasks(app: Quart):
|
|||
if settings.COIN_SYMBOL in ["xmr", "wow"]:
|
||||
asyncio.create_task(FundingProposalsTask().start())
|
||||
|
||||
if settings.COIN_SYMBOL == "xmr":
|
||||
asyncio.create_task(XmrToTask().start())
|
||||
|
||||
|
||||
def _setup_logging():
|
||||
from logging import Formatter
|
||||
|
@ -111,6 +108,6 @@ def create_app():
|
|||
await _setup_user_agents(app)
|
||||
await _setup_tasks(app)
|
||||
|
||||
import fapi.routes
|
||||
import wowlet_backend.routes
|
||||
|
||||
return app
|
|
@ -7,9 +7,9 @@ import json
|
|||
|
||||
from quart import websocket, jsonify
|
||||
|
||||
from fapi.factory import app
|
||||
from fapi.wsparse import WebsocketParse
|
||||
from fapi.utils import collect_websocket, feather_data
|
||||
from wowlet_backend.factory import app
|
||||
from wowlet_backend.wsparse import WebsocketParse
|
||||
from wowlet_backend.utils import collect_websocket, feather_data
|
||||
|
||||
|
||||
@app.route("/")
|
|
@ -39,7 +39,7 @@ class FeatherTask:
|
|||
self._running = False
|
||||
|
||||
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:
|
||||
# invalid task
|
||||
return
|
||||
|
@ -124,7 +124,7 @@ class FeatherTask:
|
|||
raise NotImplementedError()
|
||||
|
||||
async def cache_json_get(self, key: str, path="."):
|
||||
from fapi.factory import app, cache
|
||||
from wowlet_backend.factory import app, cache
|
||||
|
||||
try:
|
||||
data = await cache.execute('JSON.GET', key, path)
|
||||
|
@ -134,7 +134,7 @@ class FeatherTask:
|
|||
app.logger.error(f"Redis error: {ex}")
|
||||
|
||||
async def cache_get(self, key: str) -> dict:
|
||||
from fapi.factory import app, cache
|
||||
from wowlet_backend.factory import app, cache
|
||||
|
||||
try:
|
||||
data = await cache.get(key)
|
||||
|
@ -145,7 +145,7 @@ class FeatherTask:
|
|||
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:
|
||||
from fapi.factory import app, cache
|
||||
from wowlet_backend.factory import app, cache
|
||||
try:
|
||||
data = json.dumps(val)
|
||||
if isinstance(expiry, int) and expiry > 0:
|
||||
|
@ -157,12 +157,12 @@ class FeatherTask:
|
|||
app.logger.error(f"Redis SET error with key '{key}': {ex}")
|
||||
|
||||
|
||||
from fapi.tasks.proposals import FundingProposalsTask
|
||||
from fapi.tasks.historical_prices import HistoricalPriceTask
|
||||
from fapi.tasks.blockheight import BlockheightTask
|
||||
from fapi.tasks.rates_fiat import FiatRatesTask
|
||||
from fapi.tasks.rates_crypto import CryptoRatesTask
|
||||
from fapi.tasks.reddit import RedditTask
|
||||
from fapi.tasks.rpc_nodes import RPCNodeCheckTask
|
||||
from fapi.tasks.xmrig import XmrigTask
|
||||
from fapi.tasks.xmrto import XmrToTask
|
||||
from wowlet_backend.tasks.proposals import FundingProposalsTask
|
||||
from wowlet_backend.tasks.historical_prices import HistoricalPriceTask
|
||||
from wowlet_backend.tasks.blockheight import BlockheightTask
|
||||
from wowlet_backend.tasks.rates_fiat import FiatRatesTask
|
||||
from wowlet_backend.tasks.rates_crypto import CryptoRatesTask
|
||||
from wowlet_backend.tasks.reddit import RedditTask
|
||||
from wowlet_backend.tasks.rpc_nodes import RPCNodeCheckTask
|
||||
from wowlet_backend.tasks.xmrig import XmrigTask
|
||||
from wowlet_backend.tasks.xmrto import XmrToTask
|
|
@ -8,8 +8,8 @@ from collections import Counter
|
|||
from functools import partial
|
||||
|
||||
import settings
|
||||
from fapi.utils import httpget, popularity_contest
|
||||
from fapi.tasks import FeatherTask
|
||||
from wowlet_backend.utils import httpget, popularity_contest
|
||||
from wowlet_backend.tasks import FeatherTask
|
||||
|
||||
|
||||
class BlockheightTask(FeatherTask):
|
||||
|
@ -81,7 +81,7 @@ class BlockheightTask(FeatherTask):
|
|||
}
|
||||
|
||||
async def task(self) -> Union[dict, None]:
|
||||
from fapi.factory import app
|
||||
from wowlet_backend.factory import app
|
||||
coin_network_types = ["mainnet", "stagenet", "testnet"]
|
||||
data = {t: 0 for t in coin_network_types}
|
||||
|
|
@ -11,8 +11,8 @@ from datetime import datetime
|
|||
import aiofiles
|
||||
|
||||
import settings
|
||||
from fapi.utils import httpget
|
||||
from fapi.tasks import FeatherTask
|
||||
from wowlet_backend.utils import httpget
|
||||
from wowlet_backend.tasks import FeatherTask
|
||||
|
||||
|
||||
class HistoricalPriceTask(FeatherTask):
|
||||
|
@ -91,7 +91,7 @@ class HistoricalPriceTask(FeatherTask):
|
|||
"""This function is called when a Feather wallet client asks
|
||||
for (a range of) historical fiat information. It returns the
|
||||
data filtered by the parameters."""
|
||||
from fapi.factory import cache
|
||||
from wowlet_backend.factory import cache
|
||||
|
||||
blob = await cache.get("historical_fiat")
|
||||
blob = json.loads(blob)
|
|
@ -6,14 +6,14 @@ from bs4 import BeautifulSoup
|
|||
from typing import List
|
||||
|
||||
import settings
|
||||
from fapi.utils import httpget
|
||||
from fapi.tasks import FeatherTask
|
||||
from wowlet_backend.utils import httpget
|
||||
from wowlet_backend.tasks import FeatherTask
|
||||
|
||||
|
||||
class FundingProposalsTask(FeatherTask):
|
||||
"""Fetch funding proposals made by the community."""
|
||||
def __init__(self, interval: int = 600):
|
||||
from fapi.factory import app
|
||||
from wowlet_backend.factory import app
|
||||
super(FundingProposalsTask, self).__init__(interval)
|
||||
|
||||
self._cache_key = "funding_proposals"
|
||||
|
@ -58,7 +58,7 @@ class FundingProposalsTask(FeatherTask):
|
|||
# - API does not allow filtering
|
||||
# - API sometimes breaks; https://hackerone.com/reports/934231
|
||||
# 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)
|
||||
soup = BeautifulSoup(content, "html.parser")
|
|
@ -5,8 +5,8 @@
|
|||
from typing import List, Union
|
||||
|
||||
import settings
|
||||
from fapi.utils import httpget
|
||||
from fapi.tasks import FeatherTask
|
||||
from wowlet_backend.utils import httpget
|
||||
from wowlet_backend.tasks import FeatherTask
|
||||
|
||||
|
||||
class CryptoRatesTask(FeatherTask):
|
||||
|
@ -22,7 +22,7 @@ class CryptoRatesTask(FeatherTask):
|
|||
|
||||
async def task(self) -> Union[List[dict], None]:
|
||||
"""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"
|
||||
rates = await httpget(url, json=True)
|
|
@ -2,8 +2,8 @@
|
|||
# Copyright (c) 2020, The Monero Project.
|
||||
# Copyright (c) 2020, dsc@xmr.pm
|
||||
|
||||
from fapi.utils import httpget
|
||||
from fapi.tasks import FeatherTask
|
||||
from wowlet_backend.utils import httpget
|
||||
from wowlet_backend.tasks import FeatherTask
|
||||
|
||||
|
||||
class FiatRatesTask(FeatherTask):
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
import html
|
||||
import settings
|
||||
from fapi.utils import httpget
|
||||
from fapi.tasks import FeatherTask
|
||||
from wowlet_backend.utils import httpget
|
||||
from wowlet_backend.tasks import FeatherTask
|
||||
|
||||
|
||||
class RedditTask(FeatherTask):
|
||||
def __init__(self, interval: int = 900):
|
||||
from fapi.factory import app
|
||||
from wowlet_backend.factory import app
|
||||
super(RedditTask, self).__init__(interval)
|
||||
|
||||
self._cache_key = "reddit"
|
||||
|
@ -36,7 +36,7 @@ class RedditTask(FeatherTask):
|
|||
self._http_endpoint = self._http_endpoint[:-1]
|
||||
|
||||
async def task(self):
|
||||
from fapi.factory import app
|
||||
from wowlet_backend.factory import app
|
||||
|
||||
url = f"{self._http_endpoint}/new.json?limit=15"
|
||||
try:
|
|
@ -6,8 +6,8 @@ import json
|
|||
from typing import List
|
||||
|
||||
import settings
|
||||
from fapi.utils import httpget, popularity_contest
|
||||
from fapi.tasks import FeatherTask
|
||||
from wowlet_backend.utils import httpget, popularity_contest
|
||||
from wowlet_backend.tasks import FeatherTask
|
||||
|
||||
|
||||
class RPCNodeCheckTask(FeatherTask):
|
||||
|
@ -24,7 +24,7 @@ class RPCNodeCheckTask(FeatherTask):
|
|||
|
||||
async def task(self) -> List[dict]:
|
||||
"""Check RPC nodes status"""
|
||||
from fapi.factory import app, cache
|
||||
from wowlet_backend.factory import app, cache
|
||||
|
||||
try:
|
||||
heights = json.loads(await cache.get("blockheights"))
|
|
@ -5,8 +5,8 @@
|
|||
from dateutil.parser import parse
|
||||
|
||||
import settings
|
||||
from fapi.utils import httpget
|
||||
from fapi.tasks import FeatherTask
|
||||
from wowlet_backend.utils import httpget
|
||||
from wowlet_backend.tasks import FeatherTask
|
||||
|
||||
|
||||
class XmrigTask(FeatherTask):
|
|
@ -3,8 +3,8 @@
|
|||
# Copyright (c) 2020, dsc@xmr.pm
|
||||
|
||||
import settings
|
||||
from fapi.utils import httpget
|
||||
from fapi.tasks import FeatherTask
|
||||
from wowlet_backend.utils import httpget
|
||||
from wowlet_backend.tasks import FeatherTask
|
||||
|
||||
|
||||
class XmrToTask(FeatherTask):
|
|
@ -35,7 +35,7 @@ def print_banner():
|
|||
def collect_websocket(func):
|
||||
@wraps(func)
|
||||
async def wrapper(*args, **kwargs):
|
||||
from fapi.factory import connected_websockets
|
||||
from wowlet_backend.factory import connected_websockets
|
||||
queue = asyncio.Queue()
|
||||
connected_websockets.add(queue)
|
||||
try:
|
||||
|
@ -63,14 +63,14 @@ async def httpget(url: str, json=True, timeout: int = 5, socks5: str = None, rai
|
|||
|
||||
|
||||
def random_agent():
|
||||
from fapi.factory import user_agents
|
||||
from wowlet_backend.factory import user_agents
|
||||
return random.choice(user_agents)
|
||||
|
||||
|
||||
async def feather_data():
|
||||
"""A collection of data collected by
|
||||
`FeatherTask`, for Feather wallet clients."""
|
||||
from fapi.factory import cache, now
|
||||
from wowlet_backend.factory import cache, now
|
||||
data = await cache.get("data")
|
||||
if data:
|
||||
data = json.loads(data)
|
||||
|
@ -110,7 +110,7 @@ def current_worker_thread_is_primary() -> bool:
|
|||
current instance is responsible for the
|
||||
recurring Feather tasks.
|
||||
"""
|
||||
from fapi.factory import app
|
||||
from wowlet_backend.factory import app
|
||||
|
||||
current_pid = os.getpid()
|
||||
parent_pid = os.getppid()
|
|
@ -21,5 +21,5 @@ class WebsocketParse:
|
|||
year = data.get('year')
|
||||
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)
|
Loading…
Reference in a new issue