Finish implementation and tests for the cheat system #3

Closed
m wants to merge 67 commits from cheat-refactor into master
3 changed files with 132 additions and 106 deletions
Showing only changes of commit df592785fb - Show all commits

View File

@ -95,16 +95,15 @@ class Agora(object):
reference = self.tx.tx_to_ref(contact_id)
buyer = contact["data"]["buyer"]["username"]
amount = contact["data"]["amount"]
if "amount_xmr" in contact["data"]:
asset = contact["data"]["advertisement"]["asset"]
if asset == "XMR":
amount_crypto = contact["data"]["amount_xmr"]
crypto = "XMR"
elif "amount_btc" in contact["data"]:
elif asset == "BTC":
amount_crypto = contact["data"]["amount_btc"]
crypto = "BTC"
currency = contact["data"]["currency"]
if not contact["data"]["is_selling"]:
continue
rtrn.append(f"{reference}: {buyer} {amount}{currency} {amount_crypto}{crypto}")
rtrn.append(f"{reference}: {buyer} {amount}{currency} {amount_crypto}{asset}")
return rtrn
def dashboard_hook(self, dash):
@ -123,22 +122,21 @@ class Agora(object):
current_trades.append(reference)
buyer = contact["data"]["buyer"]["username"]
amount = contact["data"]["amount"]
if "amount_xmr" in contact["data"]:
asset = contact["data"]["advertisement"]["asset"]
if asset == "XMR":
amount_crypto = contact["data"]["amount_xmr"]
crypto = "XMR"
elif "amount_btc" in contact["data"]:
elif asset == "BTC":
amount_crypto = contact["data"]["amount_btc"]
crypto = "BTC"
currency = contact["data"]["currency"]
if not contact["data"]["is_selling"]:
continue
if reference not in self.last_dash:
reference = self.tx.new_trade(contact_id, buyer, currency, amount, amount_xmr)
reference = self.tx.new_trade(asset, contact_id, buyer, currency, amount, amount_crypto)
if reference:
if reference not in current_trades:
current_trades.append(reference)
# Let us know there is a new trade
self.irc.sendmsg(f"AUTO {reference}: {buyer} {amount}{currency} {amount_crypto}{crypto}")
self.irc.sendmsg(f"AUTO {reference}: {buyer} {amount}{currency} {amount_crypto}{asset}")
# Note that we have seen this reference
self.last_dash.add(reference)
@ -167,12 +165,11 @@ class Agora(object):
contact_id = contact["data"]["contact_id"]
buyer = contact["data"]["buyer"]["username"]
amount = contact["data"]["amount"]
if "amount_xmr" in contact["data"]:
asset = contact["data"]["advertisement"]["asset"]
if asset == "XMR":
amount_crypto = contact["data"]["amount_xmr"]
crypto = "XMR"
elif "amount_btc" in contact["data"]:
elif asset == "BTC":
amount_crypto = contact["data"]["amount_btc"]
crypto = "BTC"
currency = contact["data"]["currency"]
release_url = contact["actions"]["release_url"]
if not contact["data"]["is_selling"]:
@ -180,7 +177,7 @@ class Agora(object):
reference = self.tx.tx_to_ref(contact_id)
if not reference:
reference = "not_set"
dash_tmp.append(f"{reference}: {buyer} {amount}{currency} {amount_crypto}{crypto} {release_url}")
dash_tmp.append(f"{reference}: {buyer} {amount}{currency} {amount_crypto}{asset} {release_url}")
return dash_tmp
@ -443,10 +440,12 @@ class Agora(object):
max_local = max_usd * rates[currency]
return (min_local, max_local)
def create_ad(self, countrycode, currency):
def create_ad(self, asset, countrycode, currency):
"""
Post an ad in a country with a given currency.
Post an ad with the given asset in a country with a given currency.
Convert the min and max amounts from settings to the given currency with CurrencyRates.
:param asset: the crypto asset to list (XMR or BTC)
:type asset: string
:param countrycode: country code
:param currency: currency code
:type countrycode: string
@ -463,6 +462,7 @@ class Agora(object):
else:
adtext = ad.replace("$PAYMENT$", settings.Agora.DefaultDetailsAd)
paymentdetailstext = paymentdetails.replace("$PAYMENT$", settings.Agora.DefaultDetailsPayment)
ad = ad.replace("$ASSET$", asset)
rates = self.get_rates_all()
if currency == "USD":
min_amount = float(settings.Agora.MinUSD)
@ -478,7 +478,7 @@ class Agora(object):
country_code=countrycode,
currency=currency,
trade_type="ONLINE_SELL",
asset="XMR",
asset=asset,
price_equation=price_formula,
track_max_amount=False,
require_trusted_by_advertiser=False,
@ -500,51 +500,52 @@ class Agora(object):
:return: False or dict with response
:rtype: bool or dict
"""
for asset in loads(settings.Agora.AssetList):
for currency, countrycode in loads(settings.Agora.DistList):
rtrn = self.create_ad(countrycode, currency)
rtrn = self.create_ad(asset, countrycode, currency)
if not rtrn:
return False
yield rtrn
def get_combinations(self):
"""
Get all combinations of currencies and countries from the configuration.
:return: list of [country, currency]
:rtype: list
"""
currencies = loads(settings.Agora.BruteCurrencies)
countries = loads(settings.Agora.BruteCountries)
combinations = [[country, currency] for country in countries for currency in currencies]
return combinations
# def get_combinations(self):
# """
# Get all combinations of currencies and countries from the configuration.
# :return: list of [country, currency]
# :rtype: list
# """
# currencies = loads(settings.Agora.BruteCurrencies)
# countries = loads(settings.Agora.BruteCountries)
# combinations = [[country, currency] for country in countries for currency in currencies]
# return combinations
def dist_bruteforce(self):
"""
Bruteforce all possible ads from the currencies and countries in the config.
Does not exit on errors.
:return: False or dict with response
:rtype: bool or dict
"""
combinations = self.get_combinations()
for country, currency in combinations:
rtrn = self.create_ad(country, currency)
if not rtrn:
yield False
yield rtrn
def bruteforce_fill_blanks(self):
"""
Get the ads that we want to configure but have not, and fill in the blanks.
:return: False or dict with response
:rtype: bool or dict
"""
existing_ads = self.enum_ads()
combinations = self.get_combinations()
for country, currency in combinations:
if not [country, currency] in existing_ads:
rtrn = self.create_ad(country, currency)
if not rtrn:
yield False
yield rtrn
# def dist_bruteforce(self):
# """
# Bruteforce all possible ads from the currencies and countries in the config.
# Does not exit on errors.
# :return: False or dict with response
# :rtype: bool or dict
# """
# combinations = self.get_combinations()
# for country, currency in combinations:
# rtrn = self.create_ad(country, currency)
# if not rtrn:
# yield False
# yield rtrn
#
# def bruteforce_fill_blanks(self):
# """
# Get the ads that we want to configure but have not, and fill in the blanks.
# :return: False or dict with response
# :rtype: bool or dict
# """
# existing_ads = self.enum_ads()
# combinations = self.get_combinations()
# for country, currency in combinations:
# if not [country, currency] in existing_ads:
# rtrn = self.create_ad(country, currency)
# if not rtrn:
# yield False
# yield rtrn
def strip_duplicate_ads(self):
"""

View File

@ -33,7 +33,11 @@ class IRCCommands(object):
"""
Post an ad on AgoraDesk with the given country and currency code.
"""
posted = agora.create_ad(spl[1], spl[2])
if length == 4:
if spl[1] not in loads(settings.Agora.AssetList):
msg(f"Not a valid asset: {spl[1]}")
return
posted = agora.create_ad(spl[1], spl[2], spl[3])
if posted["success"]:
msg(f"{posted['response']['data']['message']}: {posted['response']['data']['ad_id']}")
else:
@ -87,31 +91,31 @@ class IRCCommands(object):
else:
msg(x["response"]["data"]["message"])
class brute(object):
name = "brute"
authed = True
helptext = "Use a bruteforce algorithm to create all possible currency and country pairs."
@staticmethod
def run(cmd, spl, length, authed, msg, agora, revolut, tx):
for x in agora.dist_bruteforce():
if x["success"]:
msg(f"{x['response']['data']['message']}: {x['response']['data']['ad_id']}")
else:
msg(dumps(x))
class fillblanks(object):
name = "fillblanks"
authed = True
helptext = "Resume a run of brute by getting all our adverts then filling the blanks."
@staticmethod
def run(cmd, spl, length, authed, msg, agora, revolut, tx):
for x in agora.bruteforce_fill_blanks():
if x["success"]:
msg(f"{x['response']['data']['message']}: {x['response']['data']['ad_id']}")
else:
msg(dumps(x))
# class brute(object):
# name = "brute"
# authed = True
# helptext = "Use a bruteforce algorithm to create all possible currency and country pairs."
#
# @staticmethod
# def run(cmd, spl, length, authed, msg, agora, revolut, tx):
# for x in agora.dist_bruteforce():
# if x["success"]:
# msg(f"{x['response']['data']['message']}: {x['response']['data']['ad_id']}")
# else:
# msg(dumps(x))
#
# class fillblanks(object):
# name = "fillblanks"
# authed = True
# helptext = "Resume a run of brute by getting all our adverts then filling the blanks."
#
# @staticmethod
# def run(cmd, spl, length, authed, msg, agora, revolut, tx):
# for x in agora.bruteforce_fill_blanks():
# if x["success"]:
# msg(f"{x['response']['data']['message']}: {x['response']['data']['ad_id']}")
# else:
# msg(dumps(x))
class stripdupes(object):
name = "stripdupes"
@ -190,16 +194,30 @@ class IRCCommands(object):
if total_usd_revolut is False:
msg("Error getting Revolut balance.")
return
agora_wallet = agora.agora.wallet_balance_xmr()
if not agora_wallet["success"]:
msg("Error getting Agora balance.")
agora_wallet_xmr = agora.agora.wallet_balance_xmr()
if not agora_wallet_xmr["success"]:
msg("Error getting Agora XMR balance.")
return
total_xmr_agora = agora_wallet["response"]["data"]["total"]["balance"]
agora_wallet_btc = agora.agora.wallet_balance_btc()
if not agora_wallet_btc["success"]:
msg("Error getting Agora BTC balance.")
return
total_xmr_agora = agora_wallet_xmr["response"]["data"]["total"]["balance"]
total_btc_agora = agora_wallet_btc["response"]["data"]["total"]["balance"]
# Get the XMR -> USD exchange rate
xmr_usd = agora.cg.get_price(ids="monero", vs_currencies=["USD"])
# Get the BTC -> USD exchange rate
btc_usd = agora.cg.get_price(ids="bitcoin", vs_currencies=["USD"])
# Convert the Agora XMR total to USD
total_usd_agora = float(total_xmr_agora) * xmr_usd["monero"]["usd"]
total_usd_agora_xmr = float(total_xmr_agora) * xmr_usd["monero"]["usd"]
# Convert the Agora BTC total to USD
total_usd_agora_btc = float(total_btc_agora) * btc_usd["bitcoin"]["usd"]
# Add it all up
total_usd_agora = total_usd_agora_xmr + total_usd_agora_btc
total_usd = total_usd_agora + total_usd_revolut
# Convert the total USD price to GBP and SEK
@ -315,16 +333,22 @@ class IRCCommands(object):
class wallet(object):
name = "wallet"
authed = True
helptext = "Get Agora wallet balance in XMR."
helptext = "Get Agora wallet balances."
@staticmethod
def run(cmd, spl, length, authed, msg, agora, revolut, tx):
rtrn = agora.agora.wallet_balance_xmr()
if not rtrn["success"]:
msg("Error getting wallet details.")
rtrn_xmr = agora.agora.wallet_balance_xmr()
if not rtrn_xmr["success"]:
msg("Error getting XMR wallet details.")
return
balance = rtrn["response"]["data"]["total"]["balance"]
msg(f"Wallet balance: {balance}XMR")
rtrn_btc = agora.agora.wallet_balance()
if not rtrn_btc["success"]:
msg("Error getting BTC wallet details.")
return
balance_xmr = rtrn_xmr["response"]["data"]["total"]["balance"]
balance_btc = rtrn_btc["response"]["data"]["total"]["balance"]
msg(f"XMR wallet balance: {balance_xmr}")
msg(f"BTC wallet balance: {balance_btc}")
class pubads(object):
name = "pubads"

View File

@ -183,22 +183,23 @@ class Transactions(object):
message_long = rtrn["response"]["data"]["message"]
self.irc.sendmsg(f"{message} - {message_long}")
def new_trade(self, trade_id, buyer, currency, amount, amount_xmr):
def new_trade(self, asset, trade_id, buyer, currency, amount, amount_crypto):
"""
Called when we have a new trade in Agora.
Store details in Redis, generate a reference and optionally let the customer know the reference.
"""
reference = "".join(choices(ascii_uppercase, k=5))
reference = f"XMR-{reference}"
reference = f"{asset}-{reference}"
existing_ref = r.get(f"trade.{trade_id}.reference")
if not existing_ref:
r.set(f"trade.{trade_id}.reference", reference)
to_store = {
"id": trade_id,
"asset": asset,
"buyer": buyer,
"currency": currency,
"amount": amount,
"amount_xmr": amount_xmr,
"amount_crypto": amount_crypto,
"reference": reference,
}
self.log.info("Storing trade information: {info}", info=str(to_store))