From 7323c9446cb75358ac5b542672fbceb9e55d4a0d Mon Sep 17 00:00:00 2001 From: Mark Veidemanis Date: Tue, 22 Mar 2022 15:35:22 +0000 Subject: [PATCH] Start implementing LBTC class --- handler/sources/__init__.py | 7 ++- handler/sources/agora.py | 2 +- handler/sources/localbitcoins.py | 94 ++++++-------------------------- handler/ux/commands.py | 48 +++++++++++++++- 4 files changed, 67 insertions(+), 84 deletions(-) diff --git a/handler/sources/__init__.py b/handler/sources/__init__.py index f1451dd..3585efe 100644 --- a/handler/sources/__init__.py +++ b/handler/sources/__init__.py @@ -3,7 +3,7 @@ import util import sources.agora -# import sources.localbitcoins +import sources.localbitcoins class Sources(util.Base): @@ -14,11 +14,11 @@ class Sources(util.Base): def __init__(self): super().__init__() self.agora = sources.agora.Agora() - # self.localbitcoins = sources.localbitcoins.LocalBitcoins() + self.lbtc = sources.localbitcoins.LBTC() def __irc_started__(self): self.agora.setup_loop() - # self.localbitcoins.setup_loop() + # self.lbtc.setup_loop() def __xmerged__(self): """ @@ -28,6 +28,7 @@ class Sources(util.Base): init_map = { "ux": self.ux, "agora": self.agora, + "lbtc": self.lbtc, "markets": self.markets, "sinks": self.sinks, "sources": self, diff --git a/handler/sources/agora.py b/handler/sources/agora.py index 27cab21..1d1b322 100644 --- a/handler/sources/agora.py +++ b/handler/sources/agora.py @@ -21,7 +21,7 @@ class Agora(util.Base): def __init__(self): """ - Initialise the AgoraDesk and CurrencyRates APIs. + Initialise the AgoraDesk API. Initialise the last_dash storage for detecting new trades. """ super().__init__() diff --git a/handler/sources/localbitcoins.py b/handler/sources/localbitcoins.py index 6beef59..0a5cee7 100644 --- a/handler/sources/localbitcoins.py +++ b/handler/sources/localbitcoins.py @@ -4,9 +4,7 @@ from twisted.internet.threads import deferToThread # Other library imports from json import loads -from forex_python.converter import CurrencyRates from lib.localbitcoins_py import LocalBitcoins -from pycoingecko import CoinGeckoAPI # TODO: remove this import and defer to money from time import sleep from pyotp import TOTP from datetime import datetime @@ -23,13 +21,11 @@ class LBTC(util.Base): def __init__(self): """ - Initialise the LocalBitcoins and CurrencyRates APIs. + Initialise the LocalBitcoins API. Initialise the last_dash storage for detecting new trades. """ super().__init__() self.lbtc = LocalBitcoins(settings.LocalBitcoins.Token) - self.cr = CurrencyRates() # TODO: remove this and defer to money - self.cg = CoinGeckoAPI() # TODO: remove this and defer to money # Cache for detecting new trades self.last_dash = set() @@ -40,7 +36,7 @@ class LBTC(util.Base): # Assets that cheat has been run on self.cheat_run_on = [] - def setup_loop(self): # TODO:: move to main sources + def setup_loop(self): # TODO: move to main sources """ Set up the LoopingCall to get all active trades and messages. """ @@ -250,9 +246,9 @@ class LBTC(util.Base): if not providers: providers = ["REVOLUT"] # buy-monero-online, buy-bitcoin-online - # Work around Agora weirdness calling it bitcoins + # Work around weirdness calling it bitcoins # if len(providers) == 1: - # ads = self.agora._api_call(api_method=f"buy-{coin}-online/{currency}/{providers[0]}", query_values={"page": page}) + # ads = self.lbtc._api_call(api_method=f"buy-{coin}-online/{currency}/{providers[0]}", query_values={"page": page}) # elif len(providers) > 1: ads = self.lbtc._api_call(api_method=f"buy-bitcoins-online/{currency}", query_values={"page": page}) # with open("pub.json", "a") as f: @@ -349,7 +345,7 @@ class LBTC(util.Base): if not providers: providers = self.markets.get_all_providers() # We want to get the ads for each of these currencies and return the result - rates = self.cg.get_price(ids=["bitcoin"], vs_currencies=currencies) + rates = self.money.cg.get_price(ids=["bitcoin"], vs_currencies=currencies) for asset in assets: for currency in currencies: cg_asset_name = crypto_map[asset] @@ -407,7 +403,7 @@ class LBTC(util.Base): assets.add(asset) currencies.add(currency) if not actioned: - rtrn = self.agora.ad_equation(ad_id, new_formula) + rtrn = self.lbtc.ad_equation(ad_id, new_formula) if rtrn["success"]: ads[ad_index][4] = True throttled = 0 @@ -442,64 +438,6 @@ class LBTC(util.Base): return_ids.append(rtrn["success"]) return all(return_ids) - def format_ad(self, asset, currency, payment_details_text): - """ - Format the ad. - """ - ad = settings.Platform.Ad - - # Substitute the currency - ad = ad.replace("$CURRENCY$", currency) - - # Substitute the asset - ad = ad.replace("$ASSET$", asset) - - # Substitute the payment details - ad = ad.replace("$PAYMENT$", payment_details_text) - - # Strip extra tabs - ad = ad.replace("\\t", "\t") - return ad - - def format_payment_details(self, currency, payment_details): - """ - Format the payment details. - """ - payment = settings.Platform.PaymentDetails - - payment_text = "" - for field, value in payment_details.items(): - formatted_name = field.replace("_", " ") - formatted_name = formatted_name.capitalize() - payment_text += f"* {formatted_name}: **{value}**" - if field != list(payment_details.keys())[-1]: # No trailing newline - payment_text += "\n" - - payment = payment.replace("$PAYMENT$", payment_text) - payment = payment.replace("$CURRENCY$", currency) - - return payment - - def get_minmax(self, asset, currency): - rates = self.money.get_rates_all() - if currency not in rates and not currency == "USD": - self.log.error(f"Can't create ad without rates: {currency}") - return - if asset == "XMR": - min_usd = float(settings.Agora.MinUSDXMR) - max_usd = float(settings.Agora.MaxUSDXMR) - elif asset == "BTC": - min_usd = float(settings.Agora.MinUSDBTC) - max_usd = float(settings.Agora.MaxUSDBTC) - if currency == "USD": - min_amount = min_usd - max_amount = max_usd - else: - min_amount = rates[currency] * min_usd - max_amount = rates[currency] * max_usd - - return (min_amount, max_amount) - @util.handle_exceptions def create_ad(self, asset, countrycode, currency, provider, payment_details, visible=None, edit=False, ad_id=None): """ @@ -518,9 +456,9 @@ class LBTC(util.Base): """ if payment_details: - payment_details_text = self.format_payment_details(currency, payment_details) - ad_text = self.format_ad(asset, currency, payment_details_text) - min_amount, max_amount = self.get_minmax(asset, currency) + payment_details_text = self.markets.format_payment_details(currency, payment_details) + ad_text = self.markets.format_ad(asset, currency, payment_details_text) + min_amount, max_amount = self.money.get_minmax(asset, currency) price_formula = f"coingecko{asset.lower()}usd*usd{currency.lower()}*{settings.LocalBitcoins.Margin}" @@ -546,9 +484,9 @@ class LBTC(util.Base): form["max_amount"] = max_amount if edit: - ad = self.agora.ad(ad_id=ad_id, **form) + ad = self.lbtc.ad(ad_id=ad_id, **form) else: - ad = self.agora.ad_create(**form) + ad = self.lbtc.ad_create(**form) return ad def dist_countries(self, filter_asset=None): @@ -627,7 +565,7 @@ class LBTC(util.Base): self.log.error(f"Running in dummy mode, not releasing funds for {contact_id}") return payload = {"tradeId": contact_id, "password": settings.LocalBitcoins.Pass} - rtrn = self.agora._api_call(api_method=f"contact_release/{contact_id}", http_method="POST", query_values=payload) + rtrn = self.lbtc._api_call(api_method=f"contact_release/{contact_id}", http_method="POST", query_values=payload) # Check if we can withdraw funds self.withdraw_funds() @@ -657,7 +595,7 @@ class LBTC(util.Base): profit_usd = total_usd - float(settings.Money.BaseUSD) # Get the XMR -> USD exchange rate - xmr_usd = self.cg.get_price(ids="bitcoin", vs_currencies=["USD"]) + xmr_usd = self.money.cg.get_price(ids="bitcoin", vs_currencies=["USD"]) # Convert the USD total to XMR profit_usd_in_xmr = float(profit_usd) / xmr_usd["bitcoin"]["usd"] @@ -694,15 +632,15 @@ class LBTC(util.Base): send_cast = { "address": None, "amount": half_rounded, - "password": settings.Agora.Pass, + "password": settings.LocalBitcoins.Pass, "otp": otp_code.now(), } send_cast["address"] = settings.XMR.Wallet1 - rtrn1 = self.agora.wallet_send_xmr(**send_cast) + rtrn1 = self.lbtc.wallet_send_xmr(**send_cast) send_cast["address"] = settings.XMR.Wallet2 - rtrn2 = self.agora.wallet_send_xmr(**send_cast) + rtrn2 = self.lbtc.wallet_send_xmr(**send_cast) self.irc.sendmsg(f"Withdrawal: {rtrn1['success']} | {rtrn2['success']}") self.ux.notify.notify_withdrawal(half_rounded) diff --git a/handler/ux/commands.py b/handler/ux/commands.py index 6304678..07a6337 100644 --- a/handler/ux/commands.py +++ b/handler/ux/commands.py @@ -275,7 +275,7 @@ class IRCCommands(object): class pubads(object): name = "pubads" authed = True - helptext = "View public adverts. Usage: pubads []" + helptext = "View public adverts for Agora. Usage: pubads []" @staticmethod def run(cmd, spl, length, authed, msg, agora, tx, ux): @@ -305,6 +305,39 @@ class IRCCommands(object): for ad in rtrn[currency]: msg(f"({ad[0]}) {ad[1]} {ad[2]} {ad[3]} {ad[4]} {ad[5]} {ad[6]}") + class apubads(object): + name = "apubads" + authed = True + helptext = "View public adverts for LocalBitcoins. Usage: pubads []" + + @staticmethod + def run(cmd, spl, length, authed, msg, agora, tx, ux): + if length == 3: + asset = spl[1] + if asset not in loads(settings.LocalBitcoins.AssetList): + msg(f"Not a valid asset: {spl[1]}") + return + currency = spl[2] + rtrn = tx.lbtc.get_all_public_ads(assets=[asset], currencies=[currency]) + if not rtrn: + msg("No results.") + return + for ad in rtrn[currency]: + msg(f"({ad[0]}) {ad[1]} {ad[2]} {ad[3]} {ad[4]} {ad[5]} {ad[6]}") + elif length == 4: + asset = spl[1] + if asset not in loads(settings.LocalBitcoins.AssetList): + msg(f"Not a valid asset: {spl[1]}") + return + providers = spl[3].split(",") + currency = spl[2] + rtrn = tx.lbtc.get_all_public_ads(assets=[asset], currencies=[currency], providers=providers) + if not rtrn: + msg("No results.") + return + for ad in rtrn[currency]: + msg(f"({ad[0]}) {ad[1]} {ad[2]} {ad[3]} {ad[4]} {ad[5]} {ad[6]}") + class cheat(object): name = "cheat" authed = True @@ -337,7 +370,7 @@ class IRCCommands(object): class ads(object): name = "ads" authed = True - helptext = "Get all our ad regions" + helptext = "Get all our ad regions for Agora" @staticmethod def run(cmd, spl, length, authed, msg, agora, tx, ux): @@ -345,6 +378,17 @@ class IRCCommands(object): for ad in ads: msg(f"({ad[0]}) {ad[1]} {ad[2]} {ad[3]} {ad[4]}") + class lads(object): + name = "lads" + authed = True + helptext = "Get all our ad regions for LocalBitcoins" + + @staticmethod + def run(cmd, spl, length, authed, msg, agora, tx, ux): + ads = tx.sources.lbtc.enum_ads() + for ad in ads: + msg(f"({ad[0]}) {ad[1]} {ad[2]} {ad[3]} {ad[4]}") + class xmr(object): name = "xmr" authed = True