Libraries refactor and add some sinks #4
|
@ -175,42 +175,6 @@ class Agora(object):
|
||||||
current_trades.append(reference)
|
current_trades.append(reference)
|
||||||
self.tx.cleanup(current_trades)
|
self.tx.cleanup(current_trades)
|
||||||
|
|
||||||
@handle_exceptions
|
|
||||||
def dashboard_release_urls(self):
|
|
||||||
"""
|
|
||||||
Get information about our open trades.
|
|
||||||
Post new trades to IRC and cache trades for the future.
|
|
||||||
:return: human readable list of strings about our trades or False
|
|
||||||
:rtype: list or bool
|
|
||||||
"""
|
|
||||||
dash = self.agora.dashboard_seller()
|
|
||||||
if dash is False:
|
|
||||||
return False
|
|
||||||
dash_tmp = []
|
|
||||||
if "data" not in dash["response"]:
|
|
||||||
self.log.error("Data not in dashboard response: {content}", content=dash)
|
|
||||||
return False
|
|
||||||
if dash["response"]["data"]["contact_count"] > 0:
|
|
||||||
for contact in dash["response"]["data"]["contact_list"]:
|
|
||||||
contact_id = contact["data"]["contact_id"]
|
|
||||||
buyer = contact["data"]["buyer"]["username"]
|
|
||||||
amount = contact["data"]["amount"]
|
|
||||||
asset = contact["data"]["advertisement"]["asset"]
|
|
||||||
if asset == "XMR":
|
|
||||||
amount_crypto = contact["data"]["amount_xmr"]
|
|
||||||
elif asset == "BTC":
|
|
||||||
amount_crypto = contact["data"]["amount_btc"]
|
|
||||||
currency = contact["data"]["currency"]
|
|
||||||
release_url = contact["actions"]["release_url"]
|
|
||||||
if not contact["data"]["is_selling"]:
|
|
||||||
continue
|
|
||||||
reference = self.tx.tx_to_ref(contact_id)
|
|
||||||
if not reference:
|
|
||||||
reference = "not_set"
|
|
||||||
dash_tmp.append(f"{reference}: {buyer} {amount}{currency} {amount_crypto}{asset} {release_url}")
|
|
||||||
|
|
||||||
return dash_tmp
|
|
||||||
|
|
||||||
@handle_exceptions
|
@handle_exceptions
|
||||||
def get_recent_messages(self, send_irc=True):
|
def get_recent_messages(self, send_irc=True):
|
||||||
"""
|
"""
|
||||||
|
@ -310,6 +274,7 @@ class Agora(object):
|
||||||
ads_total.append([ad[0], ad[1], ad[2], ad[3], ad[4]])
|
ads_total.append([ad[0], ad[1], ad[2], ad[3], ad[4]])
|
||||||
return ads_total
|
return ads_total
|
||||||
|
|
||||||
|
# TODO: move to utils library
|
||||||
def last_online_recent(self, date):
|
def last_online_recent(self, date):
|
||||||
"""
|
"""
|
||||||
Check if the last online date was recent.
|
Check if the last online date was recent.
|
||||||
|
@ -381,6 +346,7 @@ class Agora(object):
|
||||||
to_return.append(to_append)
|
to_return.append(to_append)
|
||||||
return to_return
|
return to_return
|
||||||
|
|
||||||
|
# TODO: move to money library
|
||||||
def lookup_rates(self, ads, rates=None):
|
def lookup_rates(self, ads, rates=None):
|
||||||
"""
|
"""
|
||||||
Lookup the rates for a list of public ads.
|
Lookup the rates for a list of public ads.
|
||||||
|
@ -430,6 +396,7 @@ class Agora(object):
|
||||||
to_update = self.markets.get_new_ad_equations(public_ads, assets)
|
to_update = self.markets.get_new_ad_equations(public_ads, assets)
|
||||||
self.slow_ad_update(to_update)
|
self.slow_ad_update(to_update)
|
||||||
|
|
||||||
|
# TODO: make generic and move to markets
|
||||||
@handle_exceptions
|
@handle_exceptions
|
||||||
def get_all_public_ads(self, assets=None, currencies=None, providers=None):
|
def get_all_public_ads(self, assets=None, currencies=None, providers=None):
|
||||||
"""
|
"""
|
||||||
|
@ -480,7 +447,6 @@ class Agora(object):
|
||||||
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.
|
||||||
:param ads: our list of ads
|
:param ads: our list of ads
|
||||||
"""
|
"""
|
||||||
# self.log.info("Beginning slow ad update for {num} ads", num=len(ads))
|
|
||||||
iterations = 0
|
iterations = 0
|
||||||
throttled = 0
|
throttled = 0
|
||||||
assets = set()
|
assets = set()
|
||||||
|
@ -495,7 +461,6 @@ class Agora(object):
|
||||||
if rtrn["success"]:
|
if rtrn["success"]:
|
||||||
ads[ad_index][4] = True
|
ads[ad_index][4] = True
|
||||||
throttled = 0
|
throttled = 0
|
||||||
# self.log.info("Successfully updated ad: {id}", id=ad_id)
|
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
if "error_code" not in rtrn["response"]["error"]:
|
if "error_code" not in rtrn["response"]["error"]:
|
||||||
|
@ -515,17 +480,6 @@ class Agora(object):
|
||||||
self.log.error("Error updating ad {ad_id}: {response}", ad_id=ad_id, response=rtrn["response"])
|
self.log.error("Error updating ad {ad_id}: {response}", ad_id=ad_id, response=rtrn["response"])
|
||||||
continue
|
continue
|
||||||
iterations += 1
|
iterations += 1
|
||||||
# if iterations == 0:
|
|
||||||
# self.log.info("Slow ad update finished, no ads to update")
|
|
||||||
# self.irc.sendmsg("Slow ad update finished, no ads to update")
|
|
||||||
# else:
|
|
||||||
# self.log.info(
|
|
||||||
# "Slow ad update completed with {iterations} iterations: [{assets}] | [{currencies}]",
|
|
||||||
# iterations=iterations,
|
|
||||||
# assets=", ".join(assets),
|
|
||||||
# currencies=", ".join(currencies),
|
|
||||||
# )
|
|
||||||
# self.irc.sendmsg(f"Slow ad update completed with {iterations} iterations: [{', '.join(assets)}] | [{', '.join(currencies)}]")
|
|
||||||
|
|
||||||
@handle_exceptions
|
@handle_exceptions
|
||||||
def nuke_ads(self):
|
def nuke_ads(self):
|
||||||
|
@ -543,6 +497,7 @@ class Agora(object):
|
||||||
return_ids.append(rtrn["success"])
|
return_ids.append(rtrn["success"])
|
||||||
return all(return_ids)
|
return all(return_ids)
|
||||||
|
|
||||||
|
# TODO: move to money
|
||||||
def get_rates_all(self):
|
def get_rates_all(self):
|
||||||
"""
|
"""
|
||||||
Get all rates that pair with USD.
|
Get all rates that pair with USD.
|
||||||
|
@ -552,6 +507,7 @@ class Agora(object):
|
||||||
rates = self.cr.get_rates("USD")
|
rates = self.cr.get_rates("USD")
|
||||||
return rates
|
return rates
|
||||||
|
|
||||||
|
# TODO: move to money
|
||||||
def get_acceptable_margins(self, currency, amount):
|
def get_acceptable_margins(self, currency, amount):
|
||||||
"""
|
"""
|
||||||
Get the minimum and maximum amounts we would accept a trade for.
|
Get the minimum and maximum amounts we would accept a trade for.
|
||||||
|
@ -615,11 +571,8 @@ class Agora(object):
|
||||||
min_amount = rates[currency] * min_usd
|
min_amount = rates[currency] * min_usd
|
||||||
max_amount = rates[currency] * max_usd
|
max_amount = rates[currency] * max_usd
|
||||||
price_formula = f"coingecko{asset.lower()}usd*usd{currency.lower()}*{settings.Agora.Margin}"
|
price_formula = f"coingecko{asset.lower()}usd*usd{currency.lower()}*{settings.Agora.Margin}"
|
||||||
# price_formula = f"coingeckoxmrusd*{settings.Agora.Margin}"
|
|
||||||
|
|
||||||
# Remove extra tabs
|
# Remove extra tabs
|
||||||
ad = ad.replace("\\t", "\t")
|
ad = ad.replace("\\t", "\t")
|
||||||
|
|
||||||
form = {
|
form = {
|
||||||
"country_code": countrycode,
|
"country_code": countrycode,
|
||||||
"currency": currency,
|
"currency": currency,
|
||||||
|
@ -635,10 +588,6 @@ class Agora(object):
|
||||||
"payment_method_details": settings.Agora.PaymentMethodDetails,
|
"payment_method_details": settings.Agora.PaymentMethodDetails,
|
||||||
"account_info": paymentdetailstext,
|
"account_info": paymentdetailstext,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Dirty hack to test
|
|
||||||
# if asset == "BTC":
|
|
||||||
# del form["min_amount"]
|
|
||||||
if edit:
|
if edit:
|
||||||
ad = self.agora.ad(ad_id=ad_id, **form)
|
ad = self.agora.ad(ad_id=ad_id, **form)
|
||||||
else:
|
else:
|
||||||
|
@ -817,6 +766,7 @@ class Agora(object):
|
||||||
self.irc.sendmsg(f"Withdrawal: {rtrn1['success']} | {rtrn2['success']}")
|
self.irc.sendmsg(f"Withdrawal: {rtrn1['success']} | {rtrn2['success']}")
|
||||||
self.notify.notify_withdrawal(half_rounded)
|
self.notify.notify_withdrawal(half_rounded)
|
||||||
|
|
||||||
|
# TODO: move to money
|
||||||
def to_usd(self, amount, currency):
|
def to_usd(self, amount, currency):
|
||||||
if currency == "USD":
|
if currency == "USD":
|
||||||
return float(amount)
|
return float(amount)
|
||||||
|
|
|
@ -140,28 +140,6 @@ class IRCCommands(object):
|
||||||
rtrn = agora.strip_duplicate_ads()
|
rtrn = agora.strip_duplicate_ads()
|
||||||
msg(dumps(rtrn))
|
msg(dumps(rtrn))
|
||||||
|
|
||||||
class find(object):
|
|
||||||
name = "find"
|
|
||||||
authed = True
|
|
||||||
helptext = "Find a transaction. Usage: find <currency> <amount>"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
|
||||||
"""
|
|
||||||
Find a transaction received by Revolut with the given reference and amount.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
int(spl[2])
|
|
||||||
except ValueError:
|
|
||||||
msg("Amount is not an integer.")
|
|
||||||
rtrn = tx.find_tx(spl[1], spl[2])
|
|
||||||
if rtrn == "AMOUNT_INVALID":
|
|
||||||
msg("Reference found but amount invalid.")
|
|
||||||
elif not rtrn:
|
|
||||||
msg("Reference not found.")
|
|
||||||
else:
|
|
||||||
return dumps(rtrn)
|
|
||||||
|
|
||||||
class accounts(object):
|
class accounts(object):
|
||||||
name = "accounts"
|
name = "accounts"
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -227,19 +205,6 @@ class IRCCommands(object):
|
||||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||||
notify.sendmsg("You have been summoned!")
|
notify.sendmsg("You have been summoned!")
|
||||||
|
|
||||||
class release_url(object):
|
|
||||||
name = "release_url"
|
|
||||||
authed = True
|
|
||||||
helptext = "Get release URL for all open trades."
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
|
||||||
trades = agora.dashboard_release_urls()
|
|
||||||
if not trades:
|
|
||||||
msg("No trades.")
|
|
||||||
for trade in trades:
|
|
||||||
msg(trade)
|
|
||||||
|
|
||||||
class message(object):
|
class message(object):
|
||||||
name = "msg"
|
name = "msg"
|
||||||
authed = True
|
authed = True
|
||||||
|
|
|
@ -45,44 +45,31 @@ class Transactions(object):
|
||||||
self.log.error("Could not find entry in DB for typeless transaction: {id}", id=txid)
|
self.log.error("Could not find entry in DB for typeless transaction: {id}", id=txid)
|
||||||
return
|
return
|
||||||
stored_trade = convert(stored_trade)
|
stored_trade = convert(stored_trade)
|
||||||
print("stored trade", stored_trade)
|
|
||||||
print("received event", dumps(data, indent=2))
|
|
||||||
if "old_state" in inside:
|
if "old_state" in inside:
|
||||||
print("Old state is inside")
|
|
||||||
if "new_state" in inside:
|
if "new_state" in inside:
|
||||||
print("New state is inside")
|
|
||||||
# We don't care unless we're being told a transaction is now completed
|
# We don't care unless we're being told a transaction is now completed
|
||||||
if not inside["new_state"] == "completed":
|
if not inside["new_state"] == "completed":
|
||||||
print("New state is note completed, aborting")
|
|
||||||
return
|
return
|
||||||
# We don't care unless the existing trade is pending
|
# We don't care unless the existing trade is pending
|
||||||
if not stored_trade["state"] == "pending":
|
if not stored_trade["state"] == "pending":
|
||||||
print("State is not pending, aborting")
|
|
||||||
return
|
return
|
||||||
# Check the old state is what we also think it is
|
# Check the old state is what we also think it is
|
||||||
if inside["old_state"] == stored_trade["state"]:
|
if inside["old_state"] == stored_trade["state"]:
|
||||||
print("Old state is the state we think it should be")
|
|
||||||
# Set the state to the new state
|
# Set the state to the new state
|
||||||
stored_trade["state"] = inside["new_state"]
|
stored_trade["state"] = inside["new_state"]
|
||||||
# Store the updated state
|
# Store the updated state
|
||||||
r.hmset(f"tx.{txid}", stored_trade)
|
r.hmset(f"tx.{txid}", stored_trade)
|
||||||
# Check it's all been previously validated
|
# Check it's all been previously validated
|
||||||
if "valid" not in stored_trade:
|
if "valid" not in stored_trade:
|
||||||
print("valid not in stored_trade", stored_trade)
|
self.log.error("Valid not in stored trade for {txid}, aborting.", txid=txid)
|
||||||
|
return
|
||||||
if stored_trade["valid"] == "1":
|
if stored_trade["valid"] == "1":
|
||||||
print("STORED TRADE IS VALID")
|
|
||||||
# Make it invalid immediately, as we're going to release now
|
# Make it invalid immediately, as we're going to release now
|
||||||
stored_trade["valid"] = "0"
|
stored_trade["valid"] = "0"
|
||||||
print("SETTING STORED TRADE INVALID")
|
|
||||||
r.hmset(f"tx.{txid}", stored_trade)
|
r.hmset(f"tx.{txid}", stored_trade)
|
||||||
print("SAVING STORED TRADE")
|
|
||||||
print("STORED TRADE SAVED:", dumps(stored_trade, indent=2))
|
|
||||||
reference = self.tx_to_ref(stored_trade["trade_id"])
|
reference = self.tx_to_ref(stored_trade["trade_id"])
|
||||||
print("REFERENCE", reference)
|
|
||||||
self.release_funds(stored_trade["trade_id"], reference)
|
self.release_funds(stored_trade["trade_id"], reference)
|
||||||
print("RELEASED FUNDS")
|
|
||||||
self.notify.notify_complete_trade(stored_trade["amount"], stored_trade["currency"])
|
self.notify.notify_complete_trade(stored_trade["amount"], stored_trade["currency"])
|
||||||
print("NOTIFICATION SENT")
|
|
||||||
return
|
return
|
||||||
# If type not in inside and we haven't hit any more returns
|
# If type not in inside and we haven't hit any more returns
|
||||||
return
|
return
|
||||||
|
@ -282,26 +269,6 @@ class Transactions(object):
|
||||||
else:
|
else:
|
||||||
return reference
|
return reference
|
||||||
|
|
||||||
def find_tx(self, reference, amount):
|
|
||||||
"""
|
|
||||||
Find transactions that match the given reference and amount.
|
|
||||||
:param reference: transaction reference in Revolut
|
|
||||||
:param amount: transaction amount
|
|
||||||
:type reference: string
|
|
||||||
:type amount: int
|
|
||||||
:return: transaction details or AMOUNT_INVALID, or False
|
|
||||||
:rtype: dict or string or bool
|
|
||||||
"""
|
|
||||||
all_transactions = r.scan(0, match="tx.*")
|
|
||||||
for tx_iter in all_transactions[1]:
|
|
||||||
tx_obj = r.hgetall(tx_iter)
|
|
||||||
if tx_obj[b"reference"] == str.encode(reference):
|
|
||||||
if tx_obj[b"amount"] == str.encode(amount):
|
|
||||||
return convert(tx_obj)
|
|
||||||
else:
|
|
||||||
return "AMOUNT_INVALID"
|
|
||||||
return False
|
|
||||||
|
|
||||||
def find_trade(self, txid, currency, amount):
|
def find_trade(self, txid, currency, amount):
|
||||||
"""
|
"""
|
||||||
Get a trade reference that matches the given currency and amount.
|
Get a trade reference that matches the given currency and amount.
|
||||||
|
@ -378,9 +345,6 @@ class Transactions(object):
|
||||||
r.rename(f"trade.{tx}.reference", f"archive.trade.{tx}.reference")
|
r.rename(f"trade.{tx}.reference", f"archive.trade.{tx}.reference")
|
||||||
r.rename(f"trade.{reference}", f"archive.trade.{reference}")
|
r.rename(f"trade.{reference}", f"archive.trade.{reference}")
|
||||||
|
|
||||||
def del_tx(self, txid):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def tx_to_ref(self, tx):
|
def tx_to_ref(self, tx):
|
||||||
refs = self.get_refs()
|
refs = self.get_refs()
|
||||||
for reference in refs:
|
for reference in refs:
|
||||||
|
@ -496,25 +460,14 @@ class Transactions(object):
|
||||||
rate = rates[currency]
|
rate = rates[currency]
|
||||||
amount_usd = float(amount) / rate
|
amount_usd = float(amount) / rate
|
||||||
cumul_usd += amount_usd
|
cumul_usd += amount_usd
|
||||||
|
|
||||||
return cumul_usd
|
return cumul_usd
|
||||||
|
|
||||||
def get_total_remaining(self):
|
def get_total_remaining(self):
|
||||||
print("withdrawalLimit", settings.Money.WithdrawLimit)
|
|
||||||
total_usd = self.get_total_usd()
|
total_usd = self.get_total_usd()
|
||||||
print("total_usd", total_usd)
|
|
||||||
total_trades_usd = self.get_open_trades_usd()
|
total_trades_usd = self.get_open_trades_usd()
|
||||||
print("total_trades_usd", total_trades_usd)
|
|
||||||
if not total_usd:
|
if not total_usd:
|
||||||
return False
|
return False
|
||||||
total_usd += total_trades_usd
|
total_usd += total_trades_usd
|
||||||
print("total_usd after add trades", total_usd)
|
|
||||||
|
|
||||||
print("baseUSD", settings.Money.BaseUSD)
|
|
||||||
print("withdrawalLimit", settings.Money.WithdrawLimit)
|
|
||||||
withdraw_threshold = float(settings.Money.BaseUSD) + float(settings.Money.WithdrawLimit)
|
withdraw_threshold = float(settings.Money.BaseUSD) + float(settings.Money.WithdrawLimit)
|
||||||
print("withdraw_threshold", withdraw_threshold)
|
|
||||||
remaining = withdraw_threshold - total_usd
|
remaining = withdraw_threshold - total_usd
|
||||||
print("remaining", remaining)
|
|
||||||
|
|
||||||
return remaining
|
return remaining
|
||||||
|
|
Loading…
Reference in New Issue