Make everything work with BTC

This commit is contained in:
Mark Veidemanis 2022-01-21 13:54:47 +00:00
parent d579f25e59
commit df592785fb
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
3 changed files with 132 additions and 106 deletions

View File

@ -95,16 +95,15 @@ class Agora(object):
reference = self.tx.tx_to_ref(contact_id) reference = self.tx.tx_to_ref(contact_id)
buyer = contact["data"]["buyer"]["username"] buyer = contact["data"]["buyer"]["username"]
amount = contact["data"]["amount"] amount = contact["data"]["amount"]
if "amount_xmr" in contact["data"]: asset = contact["data"]["advertisement"]["asset"]
if asset == "XMR":
amount_crypto = contact["data"]["amount_xmr"] amount_crypto = contact["data"]["amount_xmr"]
crypto = "XMR" elif asset == "BTC":
elif "amount_btc" in contact["data"]:
amount_crypto = contact["data"]["amount_btc"] amount_crypto = contact["data"]["amount_btc"]
crypto = "BTC"
currency = contact["data"]["currency"] currency = contact["data"]["currency"]
if not contact["data"]["is_selling"]: if not contact["data"]["is_selling"]:
continue continue
rtrn.append(f"{reference}: {buyer} {amount}{currency} {amount_crypto}{crypto}") rtrn.append(f"{reference}: {buyer} {amount}{currency} {amount_crypto}{asset}")
return rtrn return rtrn
def dashboard_hook(self, dash): def dashboard_hook(self, dash):
@ -123,22 +122,21 @@ class Agora(object):
current_trades.append(reference) current_trades.append(reference)
buyer = contact["data"]["buyer"]["username"] buyer = contact["data"]["buyer"]["username"]
amount = contact["data"]["amount"] amount = contact["data"]["amount"]
if "amount_xmr" in contact["data"]: asset = contact["data"]["advertisement"]["asset"]
if asset == "XMR":
amount_crypto = contact["data"]["amount_xmr"] amount_crypto = contact["data"]["amount_xmr"]
crypto = "XMR" elif asset == "BTC":
elif "amount_btc" in contact["data"]:
amount_crypto = contact["data"]["amount_btc"] amount_crypto = contact["data"]["amount_btc"]
crypto = "BTC"
currency = contact["data"]["currency"] currency = contact["data"]["currency"]
if not contact["data"]["is_selling"]: if not contact["data"]["is_selling"]:
continue continue
if reference not in self.last_dash: 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:
if reference not in current_trades: if reference not in current_trades:
current_trades.append(reference) current_trades.append(reference)
# Let us know there is a new trade # 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 # Note that we have seen this reference
self.last_dash.add(reference) self.last_dash.add(reference)
@ -167,12 +165,11 @@ class Agora(object):
contact_id = contact["data"]["contact_id"] contact_id = contact["data"]["contact_id"]
buyer = contact["data"]["buyer"]["username"] buyer = contact["data"]["buyer"]["username"]
amount = contact["data"]["amount"] amount = contact["data"]["amount"]
if "amount_xmr" in contact["data"]: asset = contact["data"]["advertisement"]["asset"]
if asset == "XMR":
amount_crypto = contact["data"]["amount_xmr"] amount_crypto = contact["data"]["amount_xmr"]
crypto = "XMR" elif asset == "BTC":
elif "amount_btc" in contact["data"]:
amount_crypto = contact["data"]["amount_btc"] amount_crypto = contact["data"]["amount_btc"]
crypto = "BTC"
currency = contact["data"]["currency"] currency = contact["data"]["currency"]
release_url = contact["actions"]["release_url"] release_url = contact["actions"]["release_url"]
if not contact["data"]["is_selling"]: if not contact["data"]["is_selling"]:
@ -180,7 +177,7 @@ class Agora(object):
reference = self.tx.tx_to_ref(contact_id) reference = self.tx.tx_to_ref(contact_id)
if not reference: if not reference:
reference = "not_set" 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 return dash_tmp
@ -443,10 +440,12 @@ class Agora(object):
max_local = max_usd * rates[currency] max_local = max_usd * rates[currency]
return (min_local, max_local) 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. 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 countrycode: country code
:param currency: currency code :param currency: currency code
:type countrycode: string :type countrycode: string
@ -463,6 +462,7 @@ class Agora(object):
else: else:
adtext = ad.replace("$PAYMENT$", settings.Agora.DefaultDetailsAd) adtext = ad.replace("$PAYMENT$", settings.Agora.DefaultDetailsAd)
paymentdetailstext = paymentdetails.replace("$PAYMENT$", settings.Agora.DefaultDetailsPayment) paymentdetailstext = paymentdetails.replace("$PAYMENT$", settings.Agora.DefaultDetailsPayment)
ad = ad.replace("$ASSET$", asset)
rates = self.get_rates_all() rates = self.get_rates_all()
if currency == "USD": if currency == "USD":
min_amount = float(settings.Agora.MinUSD) min_amount = float(settings.Agora.MinUSD)
@ -478,7 +478,7 @@ class Agora(object):
country_code=countrycode, country_code=countrycode,
currency=currency, currency=currency,
trade_type="ONLINE_SELL", trade_type="ONLINE_SELL",
asset="XMR", asset=asset,
price_equation=price_formula, price_equation=price_formula,
track_max_amount=False, track_max_amount=False,
require_trusted_by_advertiser=False, require_trusted_by_advertiser=False,
@ -500,52 +500,53 @@ class Agora(object):
:return: False or dict with response :return: False or dict with response
:rtype: bool or dict :rtype: bool or dict
""" """
for currency, countrycode in loads(settings.Agora.DistList): for asset in loads(settings.Agora.AssetList):
rtrn = self.create_ad(countrycode, currency) for currency, countrycode in loads(settings.Agora.DistList):
if not rtrn: rtrn = self.create_ad(asset, countrycode, currency)
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 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: if not rtrn:
yield False return False
yield rtrn 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 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): def strip_duplicate_ads(self):
""" """
Remove duplicate ads. Remove duplicate ads.

View File

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

View File

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