Integrate Wownero so that we don't have to maintain a fork of feather-ws

refactor-wow
dsc 4 years ago
parent 38e192ab5a
commit 9517029841

@ -1,41 +1,61 @@
{
"mainnet": {
"tor": [
"fdlnlt5mr5o7lmhg.onion:18081",
"xmkwypann4ly64gh.onion:18081",
"xmrtolujkxnlinre.onion:18081",
"xmrag4hf5xlabmob.onion:18081",
"monero26mmldsallmxok2kwamne4ve3mybvvn2yijsvss7ey63hc4yyd.onion:18081",
"nrw57zxw5zyevn3i.onion:18081",
"monero5sjoz5xmjn.onion:18081",
"56wl7y2ebhamkkiza4b7il4mrzwtyvpdym7bm2bkg3jrei2je646k3qd.onion:18089",
"mxcd4577fldb3ppzy7obmmhnu3tf57gbcbd4qhwr2kxyjj2qi3dnbfqd.onion:18081",
"moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18089",
"moneroptqodufzxj.onion:18081",
"3hvpnd4xejtzcuowvru2wfjum5wjf7synigm44rrizr3k4v5vzam2bad.onion:18081"
],
"clearnet": [
"eu-west.node.xmr.pm:18089",
"eu-west-2.node.xmr.pm:18089",
"usa-east-va.node.xmr.pm:18089",
"canada.node.xmr.pm:18089",
"singapore.node.xmr.pm:18089",
"192.110.160.146:18089",
"nodes.hashvault.pro:18081",
"node.supportxmr.com:18081",
"node.imonero.org:18081",
"xmr-node-eu.cakewallet.com:18081",
"xmr-node-usa-east.cakewallet.com:18081",
"node.xmr.pt:18081",
"node.xmr.ru:18081",
"xmr-peer-070.cypherpunklabs.com:18081"
]
"xmr": {
"mainnet": {
"tor": [
"fdlnlt5mr5o7lmhg.onion:18081",
"xmkwypann4ly64gh.onion:18081",
"xmrtolujkxnlinre.onion:18081",
"xmrag4hf5xlabmob.onion:18081",
"monero26mmldsallmxok2kwamne4ve3mybvvn2yijsvss7ey63hc4yyd.onion:18081",
"nrw57zxw5zyevn3i.onion:18081",
"monero5sjoz5xmjn.onion:18081",
"56wl7y2ebhamkkiza4b7il4mrzwtyvpdym7bm2bkg3jrei2je646k3qd.onion:18089",
"mxcd4577fldb3ppzy7obmmhnu3tf57gbcbd4qhwr2kxyjj2qi3dnbfqd.onion:18081",
"moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18089",
"moneroptqodufzxj.onion:18081",
"3hvpnd4xejtzcuowvru2wfjum5wjf7synigm44rrizr3k4v5vzam2bad.onion:18081"
],
"clearnet": [
"eu-west.node.xmr.pm:18089",
"eu-west-2.node.xmr.pm:18089",
"usa-east-va.node.xmr.pm:18089",
"canada.node.xmr.pm:18089",
"singapore.node.xmr.pm:18089",
"192.110.160.146:18089",
"nodes.hashvault.pro:18081",
"node.supportxmr.com:18081",
"node.imonero.org:18081",
"xmr-node-eu.cakewallet.com:18081",
"xmr-node-usa-east.cakewallet.com:18081",
"node.xmr.pt:18081",
"node.xmr.ru:18081",
"xmr-peer-070.cypherpunklabs.com:18081"
]
},
"stagenet": {
"tor": [],
"clearnet": [
"run.your.own.node.xmr.pm:38089",
"super.fast.node.xmr.pm:38089"
]
}
},
"stagenet": {
"tor": [],
"clearnet": [
"run.your.own.node.xmr.pm:38089",
"super.fast.node.xmr.pm:38089"
]
"wow": {
"mainnet": {
"tor": [
"wowbuxx535x4exuexja2xfezpwcyznxkofui4ndjiectj4yuh2xheiid.onion:34568"
],
"clearnet": [
"wow.pwned.systems:34568",
"global.wownodes.com:34568",
"node.suchwow.xyz:34568",
"super.fast.node.xmr.pm:34568",
"wowbux.org:34568"
]
},
"stagenet": {
"tor": [],
"clearnet": []
}
}
}
}

@ -19,7 +19,7 @@ nodes = {}
user_agents = None
txfiatdb = None
print("""\033[91m
print(f"""\033[91m
@ -28,7 +28,7 @@ print("""\033[91m
\033[0m
{settings.crypto_symbol}\033[0m
""".strip())
@ -58,7 +58,7 @@ def create_app():
loop = asyncio.get_event_loop()
f = open("data/nodes.json", "r")
nodes = json.loads(f.read())
nodes = json.loads(f.read())[settings.crypto_symbol]
f.close()
f = open("data/user_agents.txt", "r")
@ -67,13 +67,26 @@ def create_app():
from fapi.fapi import FeatherApi
from fapi.utils import loopyloop, TxFiatDb, XmrRig
txfiatdb = TxFiatDb(settings.crypto_name, settings.crypto_block_date_start)
loop.create_task(loopyloop(20, FeatherApi.xmrto_rates, FeatherApi.after_xmrto))
txfiatdb = TxFiatDb(settings.crypto_block_date_start)
if settings.crypto_symbol == "xmr":
loop.create_task(loopyloop(20, FeatherApi.xmrto_rates, FeatherApi.after_xmrto))
loop.create_task(loopyloop(120, FeatherApi.crypto_rates, FeatherApi.after_crypto))
loop.create_task(loopyloop(600, FeatherApi.fiat_rates, FeatherApi.after_fiat))
loop.create_task(loopyloop(300, FeatherApi.ccs, FeatherApi.after_ccs))
if settings.crypto_symbol == "xmr":
loop.create_task(loopyloop(300, FeatherApi.ccs, FeatherApi.after_ccs))
elif settings.crypto_symbol == "wow":
loop.create_task(loopyloop(300, FeatherApi.wfs, FeatherApi.after_wfs))
loop.create_task(loopyloop(900, FeatherApi.reddit, FeatherApi.after_reddit))
loop.create_task(loopyloop(60, FeatherApi.blockheight, FeatherApi.after_blockheight))
if settings.crypto_symbol == "xmr":
loop.create_task(loopyloop(60, FeatherApi.blockheight, FeatherApi.after_blockheight))
elif settings.crypto_symbol == "wow":
loop.create_task(loopyloop(60, FeatherApi.wowheight, FeatherApi.after_blockheight))
loop.create_task(loopyloop(60, FeatherApi.check_nodes, FeatherApi.after_check_nodes))
loop.create_task(loopyloop(43200, txfiatdb.update))
loop.create_task(loopyloop(43200, XmrRig.releases, XmrRig.after_releases))

@ -3,25 +3,34 @@
# Copyright (c) 2020, dsc@xmr.pm
import json
from typing import Union
import aiohttp
from bs4 import BeautifulSoup
from aiohttp_socks import ProxyType, ProxyConnector, ChainProxyConnector
from fapi.utils import broadcast_blockheight, broadcast_nodes, httpget, BlockHeight
from fapi.utils import broadcast_nodes, httpget, BlockHeight
import settings
class FeatherApi:
@staticmethod
async def redis_get(key):
async def redis_get(key: str) -> dict:
from fapi.factory import app, cache
try:
data = await cache.get(key)
data = await cache.get(f"{settings.crypto_symbol}_{key}")
if data:
return json.loads(data)
except Exception as ex:
app.logger.error(f"Redis error: {ex}")
app.logger.error(f"Redis SET error: {ex}")
@staticmethod
async def redis_set(key: str, val: Union[list, dict]) -> None:
from fapi.factory import app, cache
try:
await cache.set(f"{settings.crypto_symbol}_{key}", json.dumps(val))
except Exception as ex:
app.logger.error(f"Redis GET error: {ex}")
@staticmethod
async def xmrto_rates():
@ -75,7 +84,6 @@ class FeatherApi:
return crypto_rates
# grab WOW price while we're at it...
try:
_result = await httpget(settings.urls["crypto_wow_rates"])
if not _result:
@ -92,7 +100,7 @@ class FeatherApi:
"price_change_percentage_24h": 0.0
})
await cache.set("crypto_rates", json.dumps(crypto_rates))
await FeatherApi.redis_set("crypto_rates", crypto_rates)
return crypto_rates
@staticmethod
@ -137,12 +145,11 @@ class FeatherApi:
result = await httpget(settings.urls["fiat_rates"], json=True)
if not result:
raise Exception("empty response")
await cache.set("fiat_rates", json.dumps(result))
await FeatherApi.redis_set("fiat_rates", result)
return result
except Exception as ex:
app.logger.error(f"error parsing fiat_rates blob: {ex}")
# old cache
app.logger.warning("USING OLD CACHE FOR FIAT RATES")
return fiat_rates
@ -166,6 +173,62 @@ class FeatherApi:
}
})
@staticmethod
async def wfs():
# wownero-funding-system
from fapi.factory import app, cache
wfs = await FeatherApi.redis_get("wfs")
if wfs and app.config["DEBUG"]:
return wfs
try:
blob = await httpget(f"{settings.urls['wfs']}?offset=0&limit=1&status=2")
if "data" not in blob:
raise Exception("invalid json response")
await FeatherApi.redis_set("wfs", blob)
return blob
except Exception as ex:
app.logger.error(f"error fetching wfs JSON: {ex}")
# old cache
app.logger.warning("USING OLD CACHE FOR WFS")
return wfs
@staticmethod
async def after_wfs(data):
from fapi.factory import app, cache, api_data, connected_websockets
if not data:
return
proposals = []
for p in data['data']:
item = {
"address": p["addr_donation"],
"url": f"https://funding.wownero.com/proposal/{p['id']}",
"state": "FUNDING-REQUIRED",
"date": p['date_posted'],
"title": p['headline'],
'target_amount': p['funds_target'],
'raised_amount': round(p['funds_target'] / 100 * p['funded_pct'], 2),
'contributors': 0,
'percentage_funded': round(p['funded_pct'], 2),
'author': p['user']
}
proposals.append(item)
data = proposals
_data = api_data.get("wfs", {})
_data = json.dumps(_data, sort_keys=True, indent=4)
if json.dumps(data, sort_keys=True, indent=4) == _data:
return
api_data["wfs"] = data
for queue in connected_websockets:
await queue.put({
"cmd": "wfs",
"data": api_data["wfs"]
})
@staticmethod
async def ccs():
# CCS JSON api is broken ;x https://hackerone.com/reports/934231
@ -235,7 +298,7 @@ class FeatherApi:
except Exception as ex:
app.logger.error(f"error parsing a ccs item: {ex}")
await cache.set("ccs", json.dumps(data))
await FeatherApi.redis_set("ccs", data)
return data
@staticmethod
@ -264,7 +327,7 @@ class FeatherApi:
return reddit
try:
blob = await httpget(settings.urls["reddit"])
blob = await httpget(settings.urls[f"reddit_{settings.crypto_symbol}"])
if not blob:
raise Exception("no data from url")
blob = [{
@ -276,7 +339,7 @@ class FeatherApi:
# success
if blob:
await cache.set("reddit", json.dumps(blob))
await FeatherApi.redis_set("reddit", blob)
return blob
except Exception as ex:
app.logger.error(f"error parsing reddit blob: {ex}")
@ -302,6 +365,16 @@ class FeatherApi:
"data": api_data["reddit"]
})
@staticmethod
async def wowheight():
from fapi.factory import app, cache
data = {"mainnet": 0, "stagenet": 0}
try:
data['mainnet'] = await BlockHeight.wowheight()
except Exception as ex:
app.logger.error(f"Could not fetch blockheight for wownero: {ex}")
return data
@staticmethod
async def blockheight():
from fapi.factory import app, cache
@ -334,7 +407,14 @@ class FeatherApi:
changed = True
if changed:
await broadcast_blockheight()
from fapi.factory import connected_websockets, api_data
for queue in connected_websockets:
await queue.put({
"cmd": "blockheights",
"data": {
"height": api_data.get("blockheights", {})
}
})
@staticmethod
async def check_nodes():

@ -16,6 +16,15 @@ import settings
class BlockHeight:
@staticmethod
async def wowheight(stagenet: bool = False):
re_blockheight = r"block\/(\d+)\"\>"
url = "https://explore.wownero.com/"
content = await httpget(url, json=False)
xmrchain = re.findall(re_blockheight, content)
current = max(map(int, xmrchain))
return current
@staticmethod
async def xmrchain(stagenet: bool = False):
re_blockheight = r"block\/(\d+)\"\>"
@ -66,17 +75,6 @@ def collect_websocket(func):
return wrapper
async def broadcast_blockheight():
from fapi.factory import connected_websockets, api_data
for queue in connected_websockets:
await queue.put({
"cmd": "blockheights",
"data": {
"height": api_data.get("blockheights", {})
}
})
async def broadcast_nodes():
from fapi.factory import connected_websockets, api_data
for queue in connected_websockets:
@ -100,12 +98,12 @@ def random_agent():
class TxFiatDb:
# historical fiat price db for given symbol
def __init__(self, symbol, block_date_start):
self.fn = "data/fiatdb"
self.symbol = symbol
# class for keeping the historical fiat price db up-to-date
def __init__(self, block_date_start):
self.fn = f"data/fiatdb_{settings.crypto_symbol}"
self.symbol = settings.crypto_name
self.block_start = block_date_start
self._url = "https://www.coingecko.com/price_charts/69/usd/max.json"
self._url = settings.urls_fiathistory[settings.crypto_symbol]
self.data = {}
self.load()
@ -125,9 +123,9 @@ class TxFiatDb:
return rtn
def load(self):
if not os.path.exists("fiatdb"):
if not os.path.exists(self.fn):
return {}
f = open("fiatdb", "r")
f = open(self.fn, "r")
data = f.read()
f.close()
data = json.loads(data)
@ -136,14 +134,14 @@ class TxFiatDb:
self.data = {int(k): {int(_k): {int(__k): __v for __k, __v in _v.items()} for _k, _v in v.items()} for k, v in data.items()}
def write(self):
f = open("fiatdb", "w")
f = open(self.fn, "w")
f.write(json.dumps(self.data))
f.close()
async def update(self):
try:
content = await httpget(self._url, json=True)
if not "stats" in content:
if "stats" not in content:
raise Exception()
except Exception as ex:
return

Loading…
Cancel
Save