Finish implementation and tests for the cheat system #3

Closed
m wants to merge 67 commits from cheat-refactor into master
6 changed files with 239 additions and 169 deletions
Showing only changes of commit 7d101cb02d - Show all commits

View File

@ -386,14 +386,15 @@ class Agora(object):
for ad in ads: for ad in ads:
price = float(ad[2]) price = float(ad[2])
rate = round(price / base_currency_price, 2) rate = round(price / base_currency_price, 2)
ad.append(asset)
ad.append(rate) ad.append(rate)
return sorted(ads, key=lambda x: x[2]) return sorted(ads, key=lambda x: x[2])
def _update_prices(self, xmr=None, btc=None): def run_cheat_in_thread(self, assets=None):
""" """
Update prices in another thread. Update prices in another thread.
""" """
if xmr is None and btc is None: if not assets:
all_assets = loads(settings.Agora.AssetList) all_assets = loads(settings.Agora.AssetList)
assets_not_run = set(all_assets) ^ set(self.cheat_run_on) assets_not_run = set(all_assets) ^ set(self.cheat_run_on)
if not assets_not_run: if not assets_not_run:
@ -403,16 +404,22 @@ class Agora(object):
else: else:
asset = assets_not_run.pop() asset = assets_not_run.pop()
self.cheat_run_on.append(asset) self.cheat_run_on.append(asset)
if asset == "XMR": deferToThread(self.update_prices, [asset])
deferToThread(self.update_prices, True, False) # XMR, BTC
elif asset == "BTC":
deferToThread(self.update_prices, False, True) # XMR, BTC
return asset return asset
else: else:
deferToThread(self.update_prices, xmr, btc) deferToThread(self.update_prices, assets)
@handle_exceptions @handle_exceptions
def get_all_public_ads(self): def update_prices(self, assets=None):
# Get all public ads for the given assets
public_ads = self.get_all_public_ads(assets)
# Get the ads to update
to_update = self.markets.get_new_ad_equations(public_ads, assets)
self.slow_ad_update(to_update)
@handle_exceptions
def get_all_public_ads(self, assets=None):
""" """
Get all public ads for our listed currencies. Get all public ads for our listed currencies.
:return: dict of public ads keyed by currency :return: dict of public ads keyed by currency
@ -424,13 +431,15 @@ class Agora(object):
"BTC": "bitcoin", "BTC": "bitcoin",
} }
if not assets:
assets = self.markets.get_all_assets()
# Get all currencies we have ads for, deduplicated # Get all currencies we have ads for, deduplicated
currencies = list(set([x[0] for x in loads(settings.Agora.DistList)])) currencies = self.markets.get_all_currencies()
providers = loads(settings.Agora.ProviderList) providers = self.markets.get_all_providers()
# We want to get the ads for each of these currencies and return the result # We want to get the ads for each of these currencies and return the result
for asset in loads(settings.Agora.AssetList): rates_crypto = self.cg.get_price(ids=["monero", "bitcoin"], vs_currencies=currencies)
rates_crypto = self.cg.get_price(ids=["monero", "bitcoin"], vs_currencies=currencies) for asset in assets:
for currency in currencies: for currency in currencies:
cg_asset_name = crypto_map[asset] cg_asset_name = crypto_map[asset]
try: try:
@ -442,99 +451,13 @@ class Agora(object):
if not ads: if not ads:
continue continue
if currency in public_ads: if currency in public_ads:
for ad in list(ads): # Copy the list so we don't mutate and get stuck in an infinite loop for ad in list(ads):
public_ads[currency].append(ad) if ad not in public_ads[currency]:
public_ads[currency].append(ad)
else: else:
public_ads[currency] = ads public_ads[currency] = ads
return public_ads return public_ads
@handle_exceptions
def update_prices(self, xmr=True, btc=True):
if xmr and btc:
our_ads = self.enum_ads()
elif xmr and not btc:
our_ads = self.enum_ads("XMR")
elif not xmr and btc:
our_ads = self.enum_ads("BTC")
self.log.debug("Our ads: {ads}", ads=our_ads)
to_update = []
if our_ads is None:
return False
if our_ads is False:
return False
currencies = [x[3].lower() for x in our_ads]
# Sets deduplicate by default
providers = list(set([x[4] for x in our_ads]))
public_ad_dict_xmr = {}
public_ad_dict_btc = {}
rates_crypto = self.cg.get_price(ids=["monero", "bitcoin"], vs_currencies=currencies)
# NOTES:
# Get all ads for each currency, with all the payment methods.
# Create a function to, in turn, filter these so it contains only one payment method. Run autoprice on this.
# Append all results to to_update. Repeat for remaining payment methods, then call slow update.
for currency in currencies:
try:
rates_xmr = rates_crypto["monero"][currency]
rates_btc = rates_crypto["bitcoin"][currency]
if xmr:
public_ad_dict_xmr[currency] = self.wrap_public_ads("XMR", currency, providers=providers, rates=rates_xmr)
if public_ad_dict_xmr[currency] is False:
return False
if btc:
public_ad_dict_btc[currency] = self.wrap_public_ads("BTC", currency, providers=providers, rates=rates_btc)
if public_ad_dict_btc[currency] is False:
return False
except KeyError:
self.log.error("Error getting public ads for currency {currency}", currency=currency)
continue
for asset, ad_id, country, currency, provider in our_ads:
# Get the ads for this country/currency pair
try:
if asset == "XMR":
public_ads = public_ad_dict_xmr[currency.lower()]
elif asset == "BTC":
public_ads = public_ad_dict_btc[currency.lower()]
except KeyError:
continue
if not public_ads:
continue
if xmr:
if asset == "XMR":
new_margin = self.markets.autoprice(public_ads, currency)
new_formula = f"coingeckoxmrusd*usd{currency.lower()}*{new_margin}"
if btc:
if asset == "BTC":
new_margin = self.markets.autoprice(public_ads, currency)
new_formula = f"coingeckobtcusd*usd{currency.lower()}*{new_margin}"
# Get all of our ads
our_ads_list = [ad for ad in public_ads if ad[1] == settings.Agora.Username]
if not len(our_ads_list) == 1:
if not len(set([x[3] for x in our_ads_list])) == 1:
self.log.error("Our ads have different margins: {ads}", ads=our_ads_list)
# Get one from the list, they're probably the same, if not we will deal with the other
# ones in a later pass
# Get one
our_ad = our_ads_list.pop()
# Take the 4th argument, the margin
our_margin = our_ad[3]
# Don't waste API rate limits on setting the same margin as before
if new_margin != our_margin:
# rtrn = self.agora.ad_equation(ad_id, new_formula)
to_update.append([ad_id, new_formula, asset, currency, False])
# if not rtrn["success"]:
# self.log.error("Error updating ad {ad_id}: {response}", ad_id=ad_id, response=rtrn["response"])
self.log.info("Rate for {currency}: {margin}", currency=currency, margin=new_margin)
else:
self.log.info("Not changed rate for {currency}, keeping old margin of {margin}", currency=currency, margin=our_margin)
self.slow_ad_update(to_update)
def slow_ad_update(self, ads): def slow_ad_update(self, ads):
""" """
Slow ad equation update utilising exponential backoff in order to guarantee all ads are updated. Slow ad equation update utilising exponential backoff in order to guarantee all ads are updated.

View File

@ -353,20 +353,14 @@ class IRCCommands(object):
@staticmethod @staticmethod
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify): def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
if length == 1: if length == 1:
agora._update_prices() agora.run_cheat_in_thread()
msg("Running cheat in thread.") msg("Running cheat in thread.")
elif length == 2: elif length == 2:
asset = spl[1] asset = spl[1]
if asset not in loads(settings.Agora.AssetList): if asset not in loads(settings.Agora.AssetList):
msg(f"Not a valid asset: {spl[1]}") msg(f"Not a valid asset: {spl[1]}")
return return
if asset == "XMR": agora.run_cheat_in_thread([asset])
xmr = True
btc = False
elif asset == "BTC":
xmr = False
btc = True
agora._update_prices(xmr=xmr, btc=btc)
msg(f"Running cheat in thread for {asset}.") msg(f"Running cheat in thread for {asset}.")
class cheatnext(object): class cheatnext(object):

View File

@ -1,6 +1,9 @@
# Twisted/Klein imports # Twisted/Klein imports
from twisted.logger import Logger from twisted.logger import Logger
# Other library imports
from json import loads
# Project imports # Project imports
from settings import settings from settings import settings
@ -13,6 +16,68 @@ class Markets(object):
def __init__(self): def __init__(self):
self.log = Logger("markets") self.log = Logger("markets")
def get_all_assets(self):
assets = loads(settings.Agora.AssetList)
return assets
def get_all_providers(self):
providers = loads(settings.Agora.ProviderList)
return providers
def get_all_currencies(self):
currencies = list(set([x[0] for x in loads(settings.Agora.DistList)]))
return currencies
def get_new_ad_equations(self, public_ads, assets=None):
"""
Update all our prices.
:param public_ads: dictionary of public ads keyed by currency
:type public_ads: dict
:return: list of ads to modify
:rtype: list
"""
to_update = []
# NOTES:
# Get all ads for each currency, with all the payment methods.
# Create a function to, in turn, filter these so it contains only one payment method. Run autoprice on this.
# Append all results to to_update. Repeat for remaining payment methods, then call slow update.
# (asset, currency, provider)
if not assets:
assets = self.get_all_assets()
currencies = self.get_all_currencies()
providers = self.get_all_providers()
brute = [(asset, currency, provider) for asset in assets for currency in currencies for provider in providers]
for asset, currency, provider in brute:
# Filter currency
try:
public_ads_currency = public_ads[currency]
except KeyError:
self.log.error("Error getting public ads for currency {currency}", currency=currency)
continue
# Filter asset
public_ads_filtered = [ad for ad in public_ads_currency if ad[4] == asset]
# Filter provider
public_ads_filtered = [ad for ad in public_ads_filtered if ad[3] == provider]
our_ads = [ad for ad in public_ads_filtered if ad[1] == settings.Agora.Username]
if not our_ads:
continue
new_margin = self.autoprice(public_ads_filtered, currency)
new_formula = f"coingecko{asset.lower()}usd*usd{currency.lower()}*{new_margin}"
for ad in our_ads:
ad_id = ad[0]
asset = ad[4]
our_margin = ad[5]
if new_margin != our_margin:
to_update.append([ad_id, new_formula, asset, currency, False])
return to_update
def autoprice(self, ads, currency): def autoprice(self, ads, currency):
""" """
Helper function to automatically adjust the price up/down in certain markets Helper function to automatically adjust the price up/down in certain markets
@ -27,7 +92,7 @@ class Markets(object):
self.log.debug("Autoprice starting for {x}", x=currency) self.log.debug("Autoprice starting for {x}", x=currency)
# Find cheapest ad # Find cheapest ad
# Filter by 3rd index on each ad list to find the cheapest # Filter by 3rd index on each ad list to find the cheapest
min_margin_ad = min(ads, key=lambda x: x[4]) min_margin_ad = min(ads, key=lambda x: x[5])
self.log.debug("Minimum margin ad: {x}", x=min_margin_ad) self.log.debug("Minimum margin ad: {x}", x=min_margin_ad)
# Find second cheapest that is not us # Find second cheapest that is not us
@ -35,15 +100,15 @@ class Markets(object):
ads_without_us = [ad for ad in ads if not ad[1] == settings.Agora.Username] ads_without_us = [ad for ad in ads if not ad[1] == settings.Agora.Username]
self.log.debug("Ads without us: {x}", x=ads_without_us) self.log.debug("Ads without us: {x}", x=ads_without_us)
# Find ads above our min that are not us # Find ads above our min that are not us
ads_above_our_min_not_us = [ad for ad in ads_without_us if ad[4] > float(settings.Agora.MinMargin)] ads_above_our_min_not_us = [ad for ad in ads_without_us if ad[5] > float(settings.Agora.MinMargin)]
self.log.debug("Ads above our min not us: {x}", x=ads_above_our_min_not_us) self.log.debug("Ads above our min not us: {x}", x=ads_above_our_min_not_us)
# Check that this list without us is not empty # Check that this list without us is not empty
if ads_without_us: if ads_without_us:
# Find the cheapest from these # Find the cheapest from these
min_margin_ad_not_us = min(ads_without_us, key=lambda x: x[4]) min_margin_ad_not_us = min(ads_without_us, key=lambda x: x[5])
self.log.debug("Min margin ad not us: {x}", x=min_margin_ad_not_us) self.log.debug("Min margin ad not us: {x}", x=min_margin_ad_not_us)
# Lowball the lowest ad that is not ours # Lowball the lowest ad that is not ours
lowball_lowest_not_ours = min_margin_ad_not_us[4] # - 0.005 lowball_lowest_not_ours = min_margin_ad_not_us[5] # - 0.005
self.log.debug("Lowball lowest not ours: {x}", x=lowball_lowest_not_ours) self.log.debug("Lowball lowest not ours: {x}", x=lowball_lowest_not_ours)
# Check if the username field of the cheapest ad matches ours # Check if the username field of the cheapest ad matches ours
@ -79,7 +144,7 @@ class Markets(object):
return float(settings.Agora.MaxMargin) return float(settings.Agora.MaxMargin)
# Find cheapest ad above our min that is not us # Find cheapest ad above our min that is not us
cheapest_ad = min(ads_above_our_min_not_us, key=lambda x: x[4]) cheapest_ad = min(ads_above_our_min_not_us, key=lambda x: x[4])
cheapest_ad_margin = cheapest_ad[4] # - 0.005 cheapest_ad_margin = cheapest_ad[5] # - 0.005
if cheapest_ad_margin > float(settings.Agora.MaxMargin): if cheapest_ad_margin > float(settings.Agora.MaxMargin):
self.log.debug("Cheapest ad not ours more than MaxMargin") self.log.debug("Cheapest ad not ours more than MaxMargin")
return float(settings.Agora.MaxMargin) return float(settings.Agora.MaxMargin)

View File

@ -1,63 +1,69 @@
fake_public_ads = { fake_public_ads = {
"NOK": [ "JPY": [["b048bad8-3aaa-4727-88ba-d83aaa1727b6", "topmonero", "26978.66", "REVOLUT", "XMR", 1.32]],
["9c3d9fb6-c74c-4a35-bd9f-b6c74c7a3504", "topmonero", "2023.02", "REVOLUT", 1.3], "DKK": [["ef1455dc-4629-4827-9455-dc46291827f0", "topmonero", "1521.50", "REVOLUT", "XMR", 1.32]],
["9c3d9fb6-c74c-4a35-bd9f-b6c74c7a3504", "topmonero", "2023.02", "REVOLUT", 1.3], "CHF": [["fb04a8e2-3c69-45f3-84a8-e23c6975f380", "topmonero", "215.74", "REVOLUT", "XMR", 1.32]],
"SEK": [
["f0e840b9-29ab-4a6f-a840-b929ab7a6fde", "topmonero", "2053.68", "REVOLUT", "XMR", 1.27],
["2252a3f7-6d6b-400b-92a3-f76d6bb00b50", "SwishaMonero", "2053.68", "REVOLUT", "XMR", 1.27],
], ],
"CZK": [["80aa52ef-a5d3-462c-aa52-efa5d3862cbe", "topmonero", "4960.76", "REVOLUT", "XMR", 1.32]],
"PLN": [["b5be2881-4491-4a60-be28-814491ca606a", "topmonero", "926.48", "REVOLUT", "XMR", 1.32]],
"EUR": [ "EUR": [
["65b452e3-a29f-4233-b452-e3a29fe23369", "topmonero", "184.28", "REVOLUT", 1.19], ["87af6467-be02-476e-af64-67be02676e9a", "topmonero", "187.11", "REVOLUT", "XMR", 1.21],
["65b452e3-a29f-4233-b452-e3a29fe23369", "topmonero", "184.28", "REVOLUT", 1.19], ["57e3e8d6-45fe-40da-a3e8-d645fe20da46", "SecureMole", "187.11", "REVOLUT", "XMR", 1.21],
["87af6467-be02-476e-af64-67be02676e9a", "topmonero", "184.28", "REVOLUT", 1.19], ["d2c6645c-6d56-4094-8664-5c6d5640941b", "topmonero", "187.11", "REVOLUT", "XMR", 1.21],
["d2c6645c-6d56-4094-8664-5c6d5640941b", "topmonero", "184.28", "REVOLUT", 1.19], ["65b452e3-a29f-4233-b452-e3a29fe23369", "topmonero", "187.11", "REVOLUT", "XMR", 1.21],
["65b452e3-a29f-4233-b452-e3a29fe23369", "topmonero", "184.28", "REVOLUT", 1.19], ],
["65b452e3-a29f-4233-b452-e3a29fe23369", "topmonero", "184.28", "REVOLUT", 1.19], "NOK": [["9c3d9fb6-c74c-4a35-bd9f-b6c74c7a3504", "topmonero", "2058.76", "REVOLUT", "XMR", 1.32]],
["87af6467-be02-476e-af64-67be02676e9a", "topmonero", "184.28", "REVOLUT", 1.19], "THB": [["9a7bd726-6229-4fda-bbd7-2662295fda98", "topmonero", "7668.74", "REVOLUT", "XMR", 1.31]],
["d2c6645c-6d56-4094-8664-5c6d5640941b", "topmonero", "184.28", "REVOLUT", 1.19], "ZAR": [["92877e53-823e-4ac5-877e-53823e2ac545", "topmonero", "3583.09", "REVOLUT", "XMR", 1.3]],
"MXN": [["bf12756b-0138-49ca-9275-6b0138f9caf1", "topmonero", "4815.61", "REVOLUT", "XMR", 1.31]],
"TRY": [["3c5068ce-fcf9-40cc-9068-cefcf920cc02", "topmonero", "3166.12", "REVOLUT", "XMR", 1.31]],
"RUB": [["24a9cad1-0bce-46f3-a9ca-d10bce86f34f", "topmonero", "17513.23", "REVOLUT", "XMR", 1.31]],
"SGD": [["ac9eb9c8-88c7-4add-9eb9-c888c72addb2", "topmonero", "313.83", "REVOLUT", "XMR", 1.32]],
"HKD": [["b23aa3b3-4c91-42e4-baa3-b34c9162e4e0", "topmonero", "1818.76", "REVOLUT", "XMR", 1.32]],
"AUD": [["68b50d95-91d2-4f21-b50d-9591d22f218d", "topmonero", "327.16", "REVOLUT", "XMR", 1.31]],
"HUF": [["f886768f-b9c9-4cf7-8676-8fb9c9ccf7ee", "topmonero", "72350.54", "REVOLUT", "XMR", 1.32]],
"USD": [
["24871dd9-54e8-4962-871d-d954e82962b1", "topmonero", "224.36", "REVOLUT", "XMR", 1.27],
["b5f80385-73cb-4f98-b803-8573cb6f9846", "SecureMole", "224.36", "REVOLUT", "XMR", 1.27],
["92add2b6-ccd5-4351-add2-b6ccd53351e4", "topmonero", "224.36", "REVOLUT", "XMR", 1.27],
["04be2471-72a5-4ab6-be24-7172a57ab64a", "EmmanuelMuema", "232.98", "REVOLUT", "XMR", 1.31],
["bb0d817d-5d7d-4e76-8d81-7d5d7d9e76fd", "EmmanuelMuema", "233.34", "REVOLUT", "XMR", 1.32],
["a53a9770-69ba-43fc-ba97-7069bad3fc1a", "EmmanuelMuema", "235.13", "REVOLUT", "XMR", 1.33],
["9c7e4b21-359c-4953-be4b-21359c095370", "EmmanuelMuema", "236.93", "REVOLUT", "XMR", 1.34],
["88c72c50-3162-4c91-872c-503162dc9176", "Alphabay", "358.80", "REVOLUT", "XMR", 2.02],
], ],
"GBP": [ "GBP": [
["15e821b8-e570-4b0f-a821-b8e5709b0ffc", "SecureMole", "166.08", "REVOLUT", 1.27], ["15e821b8-e570-4b0f-a821-b8e5709b0ffc", "SecureMole", "167.95", "REVOLUT", "XMR", 1.28],
["071ab272-ba37-4a14-9ab2-72ba37fa1484", "Boozymad89", "166.08", "REVOLUT", 1.27], ["071ab272-ba37-4a14-9ab2-72ba37fa1484", "Boozymad89", "167.95", "REVOLUT", "XMR", 1.28],
["850f28eb-ce63-4ca7-8f28-ebce63dca707", "topmonero", "166.34", "REVOLUT", 1.27], ["6727d9e5-c038-43f5-a7d9-e5c038c3f5be", "topmonero", "168.22", "REVOLUT", "XMR", 1.28],
["6727d9e5-c038-43f5-a7d9-e5c038c3f5be", "topmonero", "166.34", "REVOLUT", 1.27], ["850f28eb-ce63-4ca7-8f28-ebce63dca707", "topmonero", "168.22", "REVOLUT", "XMR", 1.28],
["ca4feeb9-22d5-456d-8fee-b922d5c56d27", "Boozymad89", "175.51", "REVOLUT", 1.34], ["ca4feeb9-22d5-456d-8fee-b922d5c56d27", "Boozymad89", "177.49", "REVOLUT", "XMR", 1.36],
["15e821b8-e570-4b0f-a821-b8e5709b0ffc", "SecureMole", "166.08", "REVOLUT", 1.27], ["78db95b7-e090-48e2-9b95-b7e09098e2d9", "Crypto_Hood", "38150.99", "REVOLUT", "BTC", 1.18],
["071ab272-ba37-4a14-9ab2-72ba37fa1484", "Boozymad89", "166.08", "REVOLUT", 1.27],
["850f28eb-ce63-4ca7-8f28-ebce63dca707", "topmonero", "166.34", "REVOLUT", 1.27],
["6727d9e5-c038-43f5-a7d9-e5c038c3f5be", "topmonero", "166.34", "REVOLUT", 1.27],
["ca4feeb9-22d5-456d-8fee-b922d5c56d27", "Boozymad89", "175.51", "REVOLUT", 1.34],
],
"SEK": [
["f0e840b9-29ab-4a6f-a840-b929ab7a6fde", "topmonero", "2020.45", "REVOLUT", 1.25],
["2252a3f7-6d6b-400b-92a3-f76d6bb00b50", "SwishaMonero", "2020.45", "REVOLUT", 1.25],
["f0e840b9-29ab-4a6f-a840-b929ab7a6fde", "topmonero", "2020.45", "REVOLUT", 1.25],
["2252a3f7-6d6b-400b-92a3-f76d6bb00b50", "SwishaMonero", "2020.45", "REVOLUT", 1.25],
],
"CZK": [
["80aa52ef-a5d3-462c-aa52-efa5d3862cbe", "topmonero", "4872.73", "REVOLUT", 1.3],
["80aa52ef-a5d3-462c-aa52-efa5d3862cbe", "topmonero", "4872.73", "REVOLUT", 1.3],
], ],
"NZD": [["0addd244-c5cb-40bf-9dd2-44c5cbd0bff4", "topmonero", "351.40", "REVOLUT", "XMR", 1.31]],
"CAD": [["388442b4-0cb7-48f3-8442-b40cb7f8f39d", "topmonero", "296.50", "REVOLUT", "XMR", 1.32]],
} }
currency_map = { expected_to_update = [
"CZK": [["80aa52ef-a5d3-462c-aa52-efa5d3862cbe", "topmonero", "4872.73", "REVOLUT", 1.3]], ["fb04a8e2-3c69-45f3-84a8-e23c6975f380", "coingeckoxmrusd*usdchf*1.3", "XMR", "CHF", False],
"GBP": [ ["bf12756b-0138-49ca-9275-6b0138f9caf1", "coingeckoxmrusd*usdmxn*1.3", "XMR", "MXN", False],
["15e821b8-e570-4b0f-a821-b8e5709b0ffc", "SecureMole", "166.08", "REVOLUT", 1.27], ["ef1455dc-4629-4827-9455-dc46291827f0", "coingeckoxmrusd*usddkk*1.3", "XMR", "DKK", False],
["071ab272-ba37-4a14-9ab2-72ba37fa1484", "Boozymad89", "166.08", "REVOLUT", 1.27], ["388442b4-0cb7-48f3-8442-b40cb7f8f39d", "coingeckoxmrusd*usdcad*1.3", "XMR", "CAD", False],
["850f28eb-ce63-4ca7-8f28-ebce63dca707", "topmonero", "166.34", "REVOLUT", 1.27], ["b5be2881-4491-4a60-be28-814491ca606a", "coingeckoxmrusd*usdpln*1.3", "XMR", "PLN", False],
["6727d9e5-c038-43f5-a7d9-e5c038c3f5be", "topmonero", "166.34", "REVOLUT", 1.27], ["3c5068ce-fcf9-40cc-9068-cefcf920cc02", "coingeckoxmrusd*usdtry*1.3", "XMR", "TRY", False],
["ca4feeb9-22d5-456d-8fee-b922d5c56d27", "Boozymad89", "175.51", "REVOLUT", 1.34], ["b23aa3b3-4c91-42e4-baa3-b34c9162e4e0", "coingeckoxmrusd*usdhkd*1.3", "XMR", "HKD", False],
], ["f886768f-b9c9-4cf7-8676-8fb9c9ccf7ee", "coingeckoxmrusd*usdhuf*1.3", "XMR", "HUF", False],
"NOK": [["9c3d9fb6-c74c-4a35-bd9f-b6c74c7a3504", "topmonero", "2023.02", "REVOLUT", 1.3]], ["0addd244-c5cb-40bf-9dd2-44c5cbd0bff4", "coingeckoxmrusd*usdnzd*1.3", "XMR", "NZD", False],
"SEK": [ ["24a9cad1-0bce-46f3-a9ca-d10bce86f34f", "coingeckoxmrusd*usdrub*1.3", "XMR", "RUB", False],
["f0e840b9-29ab-4a6f-a840-b929ab7a6fde", "topmonero", "2020.45", "REVOLUT", 1.25], ["80aa52ef-a5d3-462c-aa52-efa5d3862cbe", "coingeckoxmrusd*usdczk*1.3", "XMR", "CZK", False],
["2252a3f7-6d6b-400b-92a3-f76d6bb00b50", "SwishaMonero", "2020.45", "REVOLUT", 1.25], ["ac9eb9c8-88c7-4add-9eb9-c888c72addb2", "coingeckoxmrusd*usdsgd*1.3", "XMR", "SGD", False],
], ["68b50d95-91d2-4f21-b50d-9591d22f218d", "coingeckoxmrusd*usdaud*1.3", "XMR", "AUD", False],
"EUR": [ ["b048bad8-3aaa-4727-88ba-d83aaa1727b6", "coingeckoxmrusd*usdjpy*1.3", "XMR", "JPY", False],
["65b452e3-a29f-4233-b452-e3a29fe23369", "topmonero", "184.28", "REVOLUT", 1.19], ["9c3d9fb6-c74c-4a35-bd9f-b6c74c7a3504", "coingeckoxmrusd*usdnok*1.3", "XMR", "NOK", False],
["65b452e3-a29f-4233-b452-e3a29fe23369", "topmonero", "184.28", "REVOLUT", 1.19], ["9a7bd726-6229-4fda-bbd7-2662295fda98", "coingeckoxmrusd*usdthb*1.3", "XMR", "THB", False],
["87af6467-be02-476e-af64-67be02676e9a", "topmonero", "184.28", "REVOLUT", 1.19], ]
["d2c6645c-6d56-4094-8664-5c6d5640941b", "topmonero", "184.28", "REVOLUT", 1.19],
],
}
cg_prices = { cg_prices = {
"bitcoin": { "bitcoin": {

View File

@ -1,17 +1,20 @@
from unittest import TestCase from unittest import TestCase
from unittest.mock import MagicMock from unittest.mock import MagicMock, patch
from tests.common import fake_public_ads, currency_map, cg_prices from tests.common import fake_public_ads, cg_prices, expected_to_update
from agora import Agora from agora import Agora
from markets import Markets
class TestAgora(TestCase): class TestAgora(TestCase):
def setUp(self): def setUp(self):
self.markets = Markets()
self.agora = Agora() self.agora = Agora()
setattr(self.agora, "markets", self.markets)
def mock_wrap_public_ads(self, asset, currency, providers, rates): def mock_wrap_public_ads(self, asset, currency, providers, rates):
try: try:
return currency_map[currency] return fake_public_ads[currency]
except KeyError: except KeyError:
return return
@ -21,3 +24,44 @@ class TestAgora(TestCase):
self.agora.wrap_public_ads = self.mock_wrap_public_ads self.agora.wrap_public_ads = self.mock_wrap_public_ads
public_ads = self.agora.get_all_public_ads() public_ads = self.agora.get_all_public_ads()
self.assertDictEqual(public_ads, fake_public_ads) self.assertDictEqual(public_ads, fake_public_ads)
def test_get_all_public_ads_only_one(self):
self.agora.cg.get_price = MagicMock()
self.agora.cg.get_price.return_value = cg_prices
self.agora.wrap_public_ads = self.mock_wrap_public_ads
public_ads = self.agora.get_all_public_ads()
for currency, ads in public_ads.items():
ad_ids = [ad[0] for ad in ads]
len_ad_ids = len(ad_ids)
ad_ids_dedup = set(ad_ids)
len_ad_ids_dedup = len(ad_ids_dedup)
self.assertEqual(len_ad_ids, len_ad_ids_dedup)
@patch("twisted.internet.threads.deferToThread")
def test_run_cheat_in_thread(self, defer):
asset1 = self.agora.run_cheat_in_thread()
asset2 = self.agora.run_cheat_in_thread()
self.assertEqual(set([asset1, asset2]), set(["XMR", "BTC"]))
asset3 = self.agora.run_cheat_in_thread()
asset4 = self.agora.run_cheat_in_thread()
self.assertEqual(set([asset3, asset4]), set(["XMR", "BTC"]))
self.assertNotEqual(asset1, asset2)
self.assertNotEqual(asset3, asset4)
def test_update_prices(self):
self.agora.cg.get_price = MagicMock()
self.agora.cg.get_price.return_value = cg_prices
self.agora.wrap_public_ads = self.mock_wrap_public_ads
self.agora.slow_ad_update = MagicMock()
self.agora.update_prices()
call_args = self.agora.slow_ad_update.call_args_list[0][0][0]
self.assertCountEqual(call_args, expected_to_update)

View File

@ -0,0 +1,38 @@
from unittest import TestCase
from tests.common import fake_public_ads, expected_to_update
from markets import Markets
from agora import Agora
class TestMarkets(TestCase):
def setUp(self):
self.markets = Markets()
self.agora = Agora()
def test_autoprice(self):
ads = [
["2b6dba4d-c9db-48f2-adba-4dc9dba8f2a0", "Xpoterlolipop", "182.80", "REVOLUT", "XMR", 1.18],
["57e3e8d6-45fe-40da-a3e8-d645fe20da46", "SecureMole", "183.26", "REVOLUT", "XMR", 1.19],
["87af6467-be02-476e-af64-67be02676e9a", "topmonero", "183.42", "REVOLUT", "XMR", 1.19],
["65b452e3-a29f-4233-b452-e3a29fe23369", "topmonero", "183.42", "REVOLUT", "XMR", 1.19],
["d2c6645c-6d56-4094-8664-5c6d5640941b", "topmonero", "183.42", "REVOLUT", "XMR", 1.19],
]
currency = "EUR"
margin = self.markets.autoprice(ads, currency)
expected_margin = 1.18
self.assertEqual(margin, expected_margin)
def test_get_new_ad_equation(self):
to_update = self.markets.get_new_ad_equations(fake_public_ads)
self.assertCountEqual(to_update, expected_to_update)
res_xmr = self.markets.get_new_ad_equations(fake_public_ads, ["XMR"])
expected_xmr_to_update = [x for x in expected_to_update if x[2] == "XMR"]
self.assertCountEqual(res_xmr, expected_xmr_to_update)
res_btc = self.markets.get_new_ad_equations(fake_public_ads, ["BTC"])
expected_btc_to_update = [x for x in expected_to_update if x[2] == "BTC"]
self.assertCountEqual(res_btc, expected_btc_to_update)
res_both = self.markets.get_new_ad_equations(fake_public_ads, ["XMR", "BTC"])
self.assertCountEqual(res_both, expected_to_update)