Reformat to reduce line length
This commit is contained in:
parent
6dbed22e49
commit
be356c2721
|
@ -216,7 +216,16 @@ class Markets(util.Base):
|
||||||
provider = ad[4]
|
provider = ad[4]
|
||||||
payment_details = currency_account_info_map[currency]
|
payment_details = currency_account_info_map[currency]
|
||||||
ad_id = ad[1]
|
ad_id = ad[1]
|
||||||
self.agora.create_ad(asset, countrycode, currency, provider, payment_details, visible=True, edit=True, ad_id=ad_id)
|
self.agora.create_ad(
|
||||||
|
asset,
|
||||||
|
countrycode,
|
||||||
|
currency,
|
||||||
|
provider,
|
||||||
|
payment_details,
|
||||||
|
visible=True,
|
||||||
|
edit=True,
|
||||||
|
ad_id=ad_id,
|
||||||
|
)
|
||||||
|
|
||||||
for ad in not_supported_ads:
|
for ad in not_supported_ads:
|
||||||
asset = ad[0]
|
asset = ad[0]
|
||||||
|
@ -224,7 +233,16 @@ class Markets(util.Base):
|
||||||
currency = ad[3]
|
currency = ad[3]
|
||||||
provider = ad[4]
|
provider = ad[4]
|
||||||
ad_id = ad[1]
|
ad_id = ad[1]
|
||||||
self.agora.create_ad(asset, countrycode, currency, provider, payment_details=False, visible=False, edit=True, ad_id=ad_id)
|
self.agora.create_ad(
|
||||||
|
asset,
|
||||||
|
countrycode,
|
||||||
|
currency,
|
||||||
|
provider,
|
||||||
|
payment_details=False,
|
||||||
|
visible=False,
|
||||||
|
edit=True,
|
||||||
|
ad_id=ad_id,
|
||||||
|
)
|
||||||
|
|
||||||
def format_ad(self, asset, currency, payment_details_text):
|
def format_ad(self, asset, currency, payment_details_text):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -27,7 +27,10 @@ class Money(util.Base):
|
||||||
Lookup the rates for a list of public ads.
|
Lookup the rates for a list of public ads.
|
||||||
"""
|
"""
|
||||||
if not rates:
|
if not rates:
|
||||||
rates = self.cg.get_price(ids=["monero", "bitcoin"], vs_currencies=self.markets.get_all_currencies())
|
rates = self.cg.get_price(
|
||||||
|
ids=["monero", "bitcoin"],
|
||||||
|
vs_currencies=self.markets.get_all_currencies(),
|
||||||
|
)
|
||||||
# Set the price based on the asset
|
# Set the price based on the asset
|
||||||
for ad in ads:
|
for ad in ads:
|
||||||
if ad[4] == "XMR":
|
if ad[4] == "XMR":
|
||||||
|
|
|
@ -37,7 +37,6 @@ class Sinks(util.Base):
|
||||||
# setattr(self.truelayer, "sinks", self)
|
# setattr(self.truelayer, "sinks", self)
|
||||||
|
|
||||||
def got_transactions(self, subclass, account_id, transactions):
|
def got_transactions(self, subclass, account_id, transactions):
|
||||||
print("GOT TX", transactions[0:10])
|
|
||||||
if not transactions:
|
if not transactions:
|
||||||
return False
|
return False
|
||||||
transaction_ids = [x["transaction_id"] for x in transactions]
|
transaction_ids = [x["transaction_id"] for x in transactions]
|
||||||
|
@ -96,11 +95,14 @@ class Sinks(util.Base):
|
||||||
"""
|
"""
|
||||||
Get the total balance of our accounts in USD.
|
Get the total balance of our accounts in USD.
|
||||||
"""
|
"""
|
||||||
total_nordigen = self.nordigen.get_total_map()
|
total = 0
|
||||||
total_truelayer = self.truelayer.get_total_map()
|
if settings.Nordigen.enabled == "1":
|
||||||
|
total_nordigen = self.nordigen.get_total_map()
|
||||||
|
total_nordigen_usd = self.money.multiple_to_usd(total_nordigen)
|
||||||
|
total += total_nordigen_usd
|
||||||
|
if settings.TrueLayer.enabled == "1":
|
||||||
|
total_truelayer = self.truelayer.get_total_map()
|
||||||
|
total_truelayer_usd = self.money.multiple_to_usd(total_truelayer)
|
||||||
|
total += total_truelayer_usd
|
||||||
|
|
||||||
# Yes, we can save an API call by merging but I think this is clearer
|
return total
|
||||||
total_nordigen_usd = self.money.multiple_to_usd(total_nordigen)
|
|
||||||
total_truelayer_usd = self.money.multiple_to_usd(total_truelayer)
|
|
||||||
|
|
||||||
return total_truelayer_usd + total_nordigen_usd
|
|
||||||
|
|
|
@ -49,7 +49,10 @@ class Nordigen(util.Base):
|
||||||
|
|
||||||
# Filter for added accounts since we only do that for TrueLayer
|
# Filter for added accounts since we only do that for TrueLayer
|
||||||
account_infos = {
|
account_infos = {
|
||||||
bank: accounts for bank, accounts in account_infos.items() for account in accounts if account["account_id"] in self.banks
|
bank: accounts
|
||||||
|
for bank, accounts in account_infos.items()
|
||||||
|
for account in accounts
|
||||||
|
if account["account_id"] in self.banks
|
||||||
}
|
}
|
||||||
|
|
||||||
self.sinks.got_account_info("nordigen", account_infos)
|
self.sinks.got_account_info("nordigen", account_infos)
|
||||||
|
@ -68,7 +71,10 @@ class Nordigen(util.Base):
|
||||||
:return: True or False
|
:return: True or False
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
headers = {"accept": "application/json", "Content-Type": "application/json"}
|
headers = {
|
||||||
|
"accept": "application/json",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
data = {
|
data = {
|
||||||
"secret_id": settings.Nordigen.ID,
|
"secret_id": settings.Nordigen.ID,
|
||||||
"secret_key": settings.Nordigen.Key,
|
"secret_key": settings.Nordigen.Key,
|
||||||
|
@ -97,7 +103,10 @@ class Nordigen(util.Base):
|
||||||
"""
|
"""
|
||||||
if not len(country) == 2:
|
if not len(country) == 2:
|
||||||
return False
|
return False
|
||||||
headers = {"accept": "application/json", "Authorization": f"Bearer {self.token}"}
|
headers = {
|
||||||
|
"accept": "application/json",
|
||||||
|
"Authorization": f"Bearer {self.token}",
|
||||||
|
}
|
||||||
path = f"{settings.Nordigen.Base}/institutions/?country={country}"
|
path = f"{settings.Nordigen.Base}/institutions/?country={country}"
|
||||||
r = requests.get(path, headers=headers)
|
r = requests.get(path, headers=headers)
|
||||||
try:
|
try:
|
||||||
|
@ -124,9 +133,15 @@ class Nordigen(util.Base):
|
||||||
"""Create a link to access an institution.
|
"""Create a link to access an institution.
|
||||||
:param institution_id: ID of the institution
|
:param institution_id: ID of the institution
|
||||||
"""
|
"""
|
||||||
headers = {"accept": "application/json", "Authorization": f"Bearer {self.token}"}
|
headers = {
|
||||||
|
"accept": "application/json",
|
||||||
|
"Authorization": f"Bearer {self.token}",
|
||||||
|
}
|
||||||
path = f"{settings.Nordigen.Base}/requisitions/"
|
path = f"{settings.Nordigen.Base}/requisitions/"
|
||||||
data = {"institution_id": institution_id, "redirect": settings.Nordigen.CallbackURL}
|
data = {
|
||||||
|
"institution_id": institution_id,
|
||||||
|
"redirect": settings.Nordigen.CallbackURL,
|
||||||
|
}
|
||||||
r = requests.post(path, headers=headers, data=data)
|
r = requests.post(path, headers=headers, data=data)
|
||||||
try:
|
try:
|
||||||
obj = Agreement.from_json(r.content)
|
obj = Agreement.from_json(r.content)
|
||||||
|
@ -156,7 +171,10 @@ class Nordigen(util.Base):
|
||||||
"""
|
"""
|
||||||
Get a list of active accounts.
|
Get a list of active accounts.
|
||||||
"""
|
"""
|
||||||
headers = {"accept": "application/json", "Authorization": f"Bearer {self.token}"}
|
headers = {
|
||||||
|
"accept": "application/json",
|
||||||
|
"Authorization": f"Bearer {self.token}",
|
||||||
|
}
|
||||||
path = f"{settings.Nordigen.Base}/requisitions"
|
path = f"{settings.Nordigen.Base}/requisitions"
|
||||||
r = requests.get(path, headers=headers)
|
r = requests.get(path, headers=headers)
|
||||||
try:
|
try:
|
||||||
|
@ -176,7 +194,10 @@ class Nordigen(util.Base):
|
||||||
"""
|
"""
|
||||||
Delete a requisision ID.
|
Delete a requisision ID.
|
||||||
"""
|
"""
|
||||||
headers = {"accept": "application/json", "Authorization": f"Bearer {self.token}"}
|
headers = {
|
||||||
|
"accept": "application/json",
|
||||||
|
"Authorization": f"Bearer {self.token}",
|
||||||
|
}
|
||||||
path = f"{settings.Nordigen.Base}/requisitions/{requisition_id}/"
|
path = f"{settings.Nordigen.Base}/requisitions/{requisition_id}/"
|
||||||
r = requests.delete(path, headers=headers)
|
r = requests.delete(path, headers=headers)
|
||||||
try:
|
try:
|
||||||
|
@ -191,7 +212,10 @@ class Nordigen(util.Base):
|
||||||
"""
|
"""
|
||||||
Get a list of accounts for a requisition.
|
Get a list of accounts for a requisition.
|
||||||
:param requisition: requisition ID"""
|
:param requisition: requisition ID"""
|
||||||
headers = {"accept": "application/json", "Authorization": f"Bearer {self.token}"}
|
headers = {
|
||||||
|
"accept": "application/json",
|
||||||
|
"Authorization": f"Bearer {self.token}",
|
||||||
|
}
|
||||||
path = f"{settings.Nordigen.Base}/requisitions/{requisition}/"
|
path = f"{settings.Nordigen.Base}/requisitions/{requisition}/"
|
||||||
r = requests.get(path, headers=headers)
|
r = requests.get(path, headers=headers)
|
||||||
try:
|
try:
|
||||||
|
@ -208,7 +232,10 @@ class Nordigen(util.Base):
|
||||||
"""
|
"""
|
||||||
Get details of an account.
|
Get details of an account.
|
||||||
:param requisition: requisition ID"""
|
:param requisition: requisition ID"""
|
||||||
headers = {"accept": "application/json", "Authorization": f"Bearer {self.token}"}
|
headers = {
|
||||||
|
"accept": "application/json",
|
||||||
|
"Authorization": f"Bearer {self.token}",
|
||||||
|
}
|
||||||
path = f"{settings.Nordigen.Base}/accounts/{account_id}/details/"
|
path = f"{settings.Nordigen.Base}/accounts/{account_id}/details/"
|
||||||
r = requests.get(path, headers=headers)
|
r = requests.get(path, headers=headers)
|
||||||
try:
|
try:
|
||||||
|
@ -317,7 +344,10 @@ class Nordigen(util.Base):
|
||||||
:return: list of transactions
|
:return: list of transactions
|
||||||
:rtype: dict
|
:rtype: dict
|
||||||
"""
|
"""
|
||||||
headers = {"accept": "application/json", "Authorization": f"Bearer {self.token}"}
|
headers = {
|
||||||
|
"accept": "application/json",
|
||||||
|
"Authorization": f"Bearer {self.token}",
|
||||||
|
}
|
||||||
path = f"{settings.Nordigen.Base}/accounts/{account_id}/transactions/"
|
path = f"{settings.Nordigen.Base}/accounts/{account_id}/transactions/"
|
||||||
r = requests.get(path, headers=headers)
|
r = requests.get(path, headers=headers)
|
||||||
try:
|
try:
|
||||||
|
@ -336,7 +366,10 @@ class Nordigen(util.Base):
|
||||||
:return: tuple of (currency, amount)
|
:return: tuple of (currency, amount)
|
||||||
:rtype: tuple
|
:rtype: tuple
|
||||||
"""
|
"""
|
||||||
headers = {"accept": "application/json", "Authorization": f"Bearer {self.token}"}
|
headers = {
|
||||||
|
"accept": "application/json",
|
||||||
|
"Authorization": f"Bearer {self.token}",
|
||||||
|
}
|
||||||
path = f"{settings.Nordigen.Base}/accounts/{account_id}/balances/"
|
path = f"{settings.Nordigen.Base}/accounts/{account_id}/balances/"
|
||||||
r = requests.get(path, headers=headers)
|
r = requests.get(path, headers=headers)
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -160,7 +160,11 @@ class TrueLayer(util.Base):
|
||||||
"client_id": settings.TrueLayer.ID,
|
"client_id": settings.TrueLayer.ID,
|
||||||
"client_secret": settings.TrueLayer.Key,
|
"client_secret": settings.TrueLayer.Key,
|
||||||
}
|
}
|
||||||
r = requests.post(f"{settings.TrueLayer.AuthBase}/connect/token", data=data, headers=headers)
|
r = requests.post(
|
||||||
|
f"{settings.TrueLayer.AuthBase}/connect/token",
|
||||||
|
data=data,
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
parsed = r.json()
|
parsed = r.json()
|
||||||
except JSONDecodeError:
|
except JSONDecodeError:
|
||||||
|
|
|
@ -130,7 +130,16 @@ class Agora(util.Base):
|
||||||
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("agora", asset, contact_id, buyer, currency, amount, amount_crypto, provider)
|
reference = self.tx.new_trade(
|
||||||
|
"agora",
|
||||||
|
asset,
|
||||||
|
contact_id,
|
||||||
|
buyer,
|
||||||
|
currency,
|
||||||
|
amount,
|
||||||
|
amount_crypto,
|
||||||
|
provider,
|
||||||
|
)
|
||||||
if reference:
|
if reference:
|
||||||
if reference not in current_trades:
|
if reference not in current_trades:
|
||||||
current_trades.append(reference)
|
current_trades.append(reference)
|
||||||
|
@ -258,10 +267,10 @@ class Agora(util.Base):
|
||||||
providers = ["REVOLUT"]
|
providers = ["REVOLUT"]
|
||||||
# buy-monero-online, buy-bitcoin-online
|
# buy-monero-online, buy-bitcoin-online
|
||||||
# Work around Agora weirdness calling it bitcoins
|
# Work around Agora weirdness calling it bitcoins
|
||||||
# if len(providers) == 1:
|
ads = self.agora._api_call(
|
||||||
# ads = self.agora._api_call(api_method=f"buy-{coin}-online/{currency}/{providers[0]}", query_values={"page": page})
|
api_method=f"buy-{coin}-online/{currency}",
|
||||||
# elif len(providers) > 1:
|
query_values={"page": page},
|
||||||
ads = self.agora._api_call(api_method=f"buy-{coin}-online/{currency}", query_values={"page": page})
|
)
|
||||||
# with open("pub.json", "a") as f:
|
# with open("pub.json", "a") as f:
|
||||||
# import json
|
# import json
|
||||||
# f.write(json.dumps([page, currency, asset, ads])+"\n")
|
# f.write(json.dumps([page, currency, asset, ads])+"\n")
|
||||||
|
@ -427,7 +436,9 @@ class Agora(util.Base):
|
||||||
if rtrn["response"]["error"]["error_code"] == 429:
|
if rtrn["response"]["error"]["error_code"] == 429:
|
||||||
throttled += 1
|
throttled += 1
|
||||||
sleep_time = pow(throttled, float(settings.Agora.SleepExponent))
|
sleep_time = pow(throttled, float(settings.Agora.SleepExponent))
|
||||||
self.log.info(f"Throttled {throttled} times while updating {ad_id}, sleeping for {sleep_time} seconds")
|
self.log.info(
|
||||||
|
f"Throttled {throttled} times while updating {ad_id}, sleeping for {sleep_time} seconds"
|
||||||
|
)
|
||||||
# We're running in a thread, so this is fine
|
# We're running in a thread, so this is fine
|
||||||
sleep(sleep_time)
|
sleep(sleep_time)
|
||||||
self.log.error(f"Error updating ad {ad_id}: {rtrn['response']}")
|
self.log.error(f"Error updating ad {ad_id}: {rtrn['response']}")
|
||||||
|
@ -451,7 +462,17 @@ class Agora(util.Base):
|
||||||
return all(return_ids)
|
return all(return_ids)
|
||||||
|
|
||||||
@util.handle_exceptions
|
@util.handle_exceptions
|
||||||
def create_ad(self, asset, countrycode, currency, provider, payment_details, visible=None, edit=False, ad_id=None):
|
def create_ad(
|
||||||
|
self,
|
||||||
|
asset,
|
||||||
|
countrycode,
|
||||||
|
currency,
|
||||||
|
provider,
|
||||||
|
payment_details,
|
||||||
|
visible=None,
|
||||||
|
edit=False,
|
||||||
|
ad_id=None,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Post an ad with the given asset 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.
|
||||||
|
@ -511,14 +532,23 @@ class Agora(util.Base):
|
||||||
"""
|
"""
|
||||||
dist_list = list(self.markets.create_distribution_list(filter_asset))
|
dist_list = list(self.markets.create_distribution_list(filter_asset))
|
||||||
our_ads = self.enum_ads()
|
our_ads = self.enum_ads()
|
||||||
supported_currencies, account_info = self.markets.get_valid_account_details()
|
(
|
||||||
|
supported_currencies,
|
||||||
|
account_info,
|
||||||
|
) = self.markets.get_valid_account_details()
|
||||||
# Let's get rid of the ad IDs and make it a tuple like dist_list
|
# Let's get rid of the ad IDs and make it a tuple like dist_list
|
||||||
our_ads = [(x[0], x[2], x[3], x[4]) for x in our_ads]
|
our_ads = [(x[0], x[2], x[3], x[4]) for x in our_ads]
|
||||||
for asset, countrycode, currency, provider in dist_list:
|
for asset, countrycode, currency, provider in dist_list:
|
||||||
if (asset, countrycode, currency, provider) not in our_ads:
|
if (asset, countrycode, currency, provider) not in our_ads:
|
||||||
if currency in supported_currencies:
|
if currency in supported_currencies:
|
||||||
# Create the actual ad and pass in all the stuff
|
# Create the actual ad and pass in all the stuff
|
||||||
rtrn = self.create_ad(asset, countrycode, currency, provider, payment_details=account_info[currency])
|
rtrn = self.create_ad(
|
||||||
|
asset,
|
||||||
|
countrycode,
|
||||||
|
currency,
|
||||||
|
provider,
|
||||||
|
payment_details=account_info[currency],
|
||||||
|
)
|
||||||
# Bail on first error, let's not continue
|
# Bail on first error, let's not continue
|
||||||
if rtrn is False:
|
if rtrn is False:
|
||||||
return False
|
return False
|
||||||
|
@ -534,11 +564,20 @@ class Agora(util.Base):
|
||||||
:rtype: bool or dict
|
:rtype: bool or dict
|
||||||
"""
|
"""
|
||||||
our_ads = self.enum_ads()
|
our_ads = self.enum_ads()
|
||||||
supported_currencies, account_info = self.markets.get_valid_account_details()
|
(
|
||||||
|
supported_currencies,
|
||||||
|
account_info,
|
||||||
|
) = self.markets.get_valid_account_details()
|
||||||
for asset, ad_id, countrycode, currency, provider in our_ads:
|
for asset, ad_id, countrycode, currency, provider in our_ads:
|
||||||
if currency in supported_currencies:
|
if currency in supported_currencies:
|
||||||
rtrn = self.create_ad(
|
rtrn = self.create_ad(
|
||||||
asset, countrycode, currency, provider, payment_details=account_info[currency], edit=True, ad_id=ad_id
|
asset,
|
||||||
|
countrycode,
|
||||||
|
currency,
|
||||||
|
provider,
|
||||||
|
payment_details=account_info[currency],
|
||||||
|
edit=True,
|
||||||
|
ad_id=ad_id,
|
||||||
)
|
)
|
||||||
# Bail on first error, let's not continue
|
# Bail on first error, let's not continue
|
||||||
if rtrn is False:
|
if rtrn is False:
|
||||||
|
@ -581,7 +620,11 @@ class Agora(util.Base):
|
||||||
self.log.error(f"Running in dummy mode, not releasing funds for {contact_id}")
|
self.log.error(f"Running in dummy mode, not releasing funds for {contact_id}")
|
||||||
return
|
return
|
||||||
payload = {"tradeId": contact_id, "password": settings.Agora.Pass}
|
payload = {"tradeId": contact_id, "password": settings.Agora.Pass}
|
||||||
rtrn = self.agora._api_call(api_method=f"contact_release/{contact_id}", http_method="POST", query_values=payload)
|
rtrn = self.agora._api_call(
|
||||||
|
api_method=f"contact_release/{contact_id}",
|
||||||
|
http_method="POST",
|
||||||
|
query_values=payload,
|
||||||
|
)
|
||||||
|
|
||||||
# Check if we can withdraw funds
|
# Check if we can withdraw funds
|
||||||
self.withdraw_funds()
|
self.withdraw_funds()
|
||||||
|
|
|
@ -25,7 +25,7 @@ class LBTC(util.Base):
|
||||||
Initialise the last_dash storage for detecting new trades.
|
Initialise the last_dash storage for detecting new trades.
|
||||||
"""
|
"""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.lbtc = LocalBitcoins(settings.LocalBitcoins.Token)
|
self.lbtc = LocalBitcoins(settings.LocalBitcoins.Token, settings.LocalBitcoins.Secret)
|
||||||
|
|
||||||
# Cache for detecting new trades
|
# Cache for detecting new trades
|
||||||
self.last_dash = set()
|
self.last_dash = set()
|
||||||
|
@ -124,7 +124,16 @@ class LBTC(util.Base):
|
||||||
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("lbtc", asset, contact_id, buyer, currency, amount, amount_crypto, provider)
|
reference = self.tx.new_trade(
|
||||||
|
"lbtc",
|
||||||
|
asset,
|
||||||
|
contact_id,
|
||||||
|
buyer,
|
||||||
|
currency,
|
||||||
|
amount,
|
||||||
|
amount_crypto,
|
||||||
|
provider,
|
||||||
|
)
|
||||||
if reference:
|
if reference:
|
||||||
if reference not in current_trades:
|
if reference not in current_trades:
|
||||||
current_trades.append(reference)
|
current_trades.append(reference)
|
||||||
|
@ -247,10 +256,10 @@ class LBTC(util.Base):
|
||||||
providers = ["REVOLUT"]
|
providers = ["REVOLUT"]
|
||||||
# buy-monero-online, buy-bitcoin-online
|
# buy-monero-online, buy-bitcoin-online
|
||||||
# Work around weirdness calling it bitcoins
|
# Work around weirdness calling it bitcoins
|
||||||
# if len(providers) == 1:
|
ads = self.lbtc._api_call(
|
||||||
# ads = self.lbtc._api_call(api_method=f"buy-{coin}-online/{currency}/{providers[0]}", query_values={"page": page})
|
api_method=f"buy-bitcoins-online/{currency}",
|
||||||
# elif len(providers) > 1:
|
query_values={"page": page},
|
||||||
ads = self.lbtc._api_call(api_method=f"buy-bitcoins-online/{currency}", query_values={"page": page})
|
)
|
||||||
# with open("pub.json", "a") as f:
|
# with open("pub.json", "a") as f:
|
||||||
# import json
|
# import json
|
||||||
# f.write(json.dumps([page, currency, asset, ads])+"\n")
|
# f.write(json.dumps([page, currency, asset, ads])+"\n")
|
||||||
|
@ -414,8 +423,13 @@ class LBTC(util.Base):
|
||||||
return
|
return
|
||||||
if rtrn["response"]["error"]["error_code"] == 429:
|
if rtrn["response"]["error"]["error_code"] == 429:
|
||||||
throttled += 1
|
throttled += 1
|
||||||
sleep_time = pow(throttled, float(settings.LocalBitcoins.SleepExponent))
|
sleep_time = pow(
|
||||||
self.log.info(f"Throttled {throttled} times while updating {ad_id}, sleeping for {sleep_time} seconds")
|
throttled,
|
||||||
|
float(settings.LocalBitcoins.SleepExponent),
|
||||||
|
)
|
||||||
|
self.log.info(
|
||||||
|
f"Throttled {throttled} times while updating {ad_id}, sleeping for {sleep_time} seconds"
|
||||||
|
)
|
||||||
# We're running in a thread, so this is fine
|
# We're running in a thread, so this is fine
|
||||||
sleep(sleep_time)
|
sleep(sleep_time)
|
||||||
self.log.error(f"Error updating ad {ad_id}: {rtrn['response']}")
|
self.log.error(f"Error updating ad {ad_id}: {rtrn['response']}")
|
||||||
|
@ -439,7 +453,17 @@ class LBTC(util.Base):
|
||||||
return all(return_ids)
|
return all(return_ids)
|
||||||
|
|
||||||
@util.handle_exceptions
|
@util.handle_exceptions
|
||||||
def create_ad(self, asset, countrycode, currency, provider, payment_details, visible=None, edit=False, ad_id=None):
|
def create_ad(
|
||||||
|
self,
|
||||||
|
asset,
|
||||||
|
countrycode,
|
||||||
|
currency,
|
||||||
|
provider,
|
||||||
|
payment_details,
|
||||||
|
visible=None,
|
||||||
|
edit=False,
|
||||||
|
ad_id=None,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Post an ad with the given asset 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.
|
||||||
|
@ -498,14 +522,23 @@ class LBTC(util.Base):
|
||||||
"""
|
"""
|
||||||
dist_list = list(self.markets.create_distribution_list(filter_asset))
|
dist_list = list(self.markets.create_distribution_list(filter_asset))
|
||||||
our_ads = self.enum_ads()
|
our_ads = self.enum_ads()
|
||||||
supported_currencies, account_info = self.markets.get_valid_account_details()
|
(
|
||||||
|
supported_currencies,
|
||||||
|
account_info,
|
||||||
|
) = self.markets.get_valid_account_details()
|
||||||
# Let's get rid of the ad IDs and make it a tuple like dist_list
|
# Let's get rid of the ad IDs and make it a tuple like dist_list
|
||||||
our_ads = [(x[0], x[2], x[3], x[4]) for x in our_ads]
|
our_ads = [(x[0], x[2], x[3], x[4]) for x in our_ads]
|
||||||
for asset, countrycode, currency, provider in dist_list:
|
for asset, countrycode, currency, provider in dist_list:
|
||||||
if (asset, countrycode, currency, provider) not in our_ads:
|
if (asset, countrycode, currency, provider) not in our_ads:
|
||||||
if currency in supported_currencies:
|
if currency in supported_currencies:
|
||||||
# Create the actual ad and pass in all the stuff
|
# Create the actual ad and pass in all the stuff
|
||||||
rtrn = self.create_ad(asset, countrycode, currency, provider, payment_details=account_info[currency])
|
rtrn = self.create_ad(
|
||||||
|
asset,
|
||||||
|
countrycode,
|
||||||
|
currency,
|
||||||
|
provider,
|
||||||
|
payment_details=account_info[currency],
|
||||||
|
)
|
||||||
# Bail on first error, let's not continue
|
# Bail on first error, let's not continue
|
||||||
if rtrn is False:
|
if rtrn is False:
|
||||||
return False
|
return False
|
||||||
|
@ -521,11 +554,20 @@ class LBTC(util.Base):
|
||||||
:rtype: bool or dict
|
:rtype: bool or dict
|
||||||
"""
|
"""
|
||||||
our_ads = self.enum_ads()
|
our_ads = self.enum_ads()
|
||||||
supported_currencies, account_info = self.markets.get_valid_account_details()
|
(
|
||||||
|
supported_currencies,
|
||||||
|
account_info,
|
||||||
|
) = self.markets.get_valid_account_details()
|
||||||
for asset, ad_id, countrycode, currency, provider in our_ads:
|
for asset, ad_id, countrycode, currency, provider in our_ads:
|
||||||
if currency in supported_currencies:
|
if currency in supported_currencies:
|
||||||
rtrn = self.create_ad(
|
rtrn = self.create_ad(
|
||||||
asset, countrycode, currency, provider, payment_details=account_info[currency], edit=True, ad_id=ad_id
|
asset,
|
||||||
|
countrycode,
|
||||||
|
currency,
|
||||||
|
provider,
|
||||||
|
payment_details=account_info[currency],
|
||||||
|
edit=True,
|
||||||
|
ad_id=ad_id,
|
||||||
)
|
)
|
||||||
# Bail on first error, let's not continue
|
# Bail on first error, let's not continue
|
||||||
if rtrn is False:
|
if rtrn is False:
|
||||||
|
@ -564,8 +606,15 @@ class LBTC(util.Base):
|
||||||
if settings.LocalBitcoins.Dummy == "1":
|
if settings.LocalBitcoins.Dummy == "1":
|
||||||
self.log.error(f"Running in dummy mode, not releasing funds for {contact_id}")
|
self.log.error(f"Running in dummy mode, not releasing funds for {contact_id}")
|
||||||
return
|
return
|
||||||
payload = {"tradeId": contact_id, "password": settings.LocalBitcoins.Pass}
|
payload = {
|
||||||
rtrn = self.lbtc._api_call(api_method=f"contact_release/{contact_id}", http_method="POST", query_values=payload)
|
"tradeId": contact_id,
|
||||||
|
"password": settings.LocalBitcoins.Pass,
|
||||||
|
}
|
||||||
|
rtrn = self.lbtc._api_call(
|
||||||
|
api_method=f"contact_release/{contact_id}",
|
||||||
|
http_method="POST",
|
||||||
|
query_values=payload,
|
||||||
|
)
|
||||||
|
|
||||||
# Check if we can withdraw funds
|
# Check if we can withdraw funds
|
||||||
self.withdraw_funds()
|
self.withdraw_funds()
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -167,7 +167,14 @@ class TestAgora(TestCase):
|
||||||
provider = ad["data"]["online_provider"]
|
provider = ad["data"]["online_provider"]
|
||||||
asset = "XMR"
|
asset = "XMR"
|
||||||
currency = ad["data"]["currency"]
|
currency = ad["data"]["currency"]
|
||||||
to_append = [ad_id, username, temp_price, provider, asset, currency]
|
to_append = [
|
||||||
|
ad_id,
|
||||||
|
username,
|
||||||
|
temp_price,
|
||||||
|
provider,
|
||||||
|
asset,
|
||||||
|
currency,
|
||||||
|
]
|
||||||
if to_append not in expected_return:
|
if to_append not in expected_return:
|
||||||
expected_return.append(to_append)
|
expected_return.append(to_append)
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,51 @@ class TestMarkets(TestCase):
|
||||||
|
|
||||||
def test_autoprice(self):
|
def test_autoprice(self):
|
||||||
ads = [
|
ads = [
|
||||||
["2b6dba4d-c9db-48f2-adba-4dc9dba8f2a0", "Xpoterlolipop", "182.80", "REVOLUT", "XMR", "USD", 1.18],
|
[
|
||||||
["57e3e8d6-45fe-40da-a3e8-d645fe20da46", "SecureMole", "183.26", "REVOLUT", "XMR", "USD", 1.19],
|
"2b6dba4d-c9db-48f2-adba-4dc9dba8f2a0",
|
||||||
["87af6467-be02-476e-af64-67be02676e9a", "topmonero", "183.42", "REVOLUT", "XMR", "USD", 1.19],
|
"Xpoterlolipop",
|
||||||
["65b452e3-a29f-4233-b452-e3a29fe23369", "topmonero", "183.42", "REVOLUT", "XMR", "USD", 1.19],
|
"182.80",
|
||||||
["d2c6645c-6d56-4094-8664-5c6d5640941b", "topmonero", "183.42", "REVOLUT", "XMR", "USD", 1.19],
|
"REVOLUT",
|
||||||
|
"XMR",
|
||||||
|
"USD",
|
||||||
|
1.18,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"57e3e8d6-45fe-40da-a3e8-d645fe20da46",
|
||||||
|
"SecureMole",
|
||||||
|
"183.26",
|
||||||
|
"REVOLUT",
|
||||||
|
"XMR",
|
||||||
|
"USD",
|
||||||
|
1.19,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"87af6467-be02-476e-af64-67be02676e9a",
|
||||||
|
"topmonero",
|
||||||
|
"183.42",
|
||||||
|
"REVOLUT",
|
||||||
|
"XMR",
|
||||||
|
"USD",
|
||||||
|
1.19,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"65b452e3-a29f-4233-b452-e3a29fe23369",
|
||||||
|
"topmonero",
|
||||||
|
"183.42",
|
||||||
|
"REVOLUT",
|
||||||
|
"XMR",
|
||||||
|
"USD",
|
||||||
|
1.19,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"d2c6645c-6d56-4094-8664-5c6d5640941b",
|
||||||
|
"topmonero",
|
||||||
|
"183.42",
|
||||||
|
"REVOLUT",
|
||||||
|
"XMR",
|
||||||
|
"USD",
|
||||||
|
1.19,
|
||||||
|
],
|
||||||
]
|
]
|
||||||
currency = "EUR"
|
currency = "EUR"
|
||||||
margin = self.markets.autoprice(ads, currency)
|
margin = self.markets.autoprice(ads, currency)
|
||||||
|
@ -42,7 +82,10 @@ class TestMarkets(TestCase):
|
||||||
settings.settings.Platform.Ad = """* Set **Country of recipient's bank** to **"United Kingdom"**
|
settings.settings.Platform.Ad = """* Set **Country of recipient's bank** to **"United Kingdom"**
|
||||||
$PAYMENT$
|
$PAYMENT$
|
||||||
* Set **Company name** to **"PATHOGEN LIMITED"**"""
|
* Set **Company name** to **"PATHOGEN LIMITED"**"""
|
||||||
payment_details = {"sort_code": "02-03-04", "account_number": "0023-0045"}
|
payment_details = {
|
||||||
|
"sort_code": "02-03-04",
|
||||||
|
"account_number": "0023-0045",
|
||||||
|
}
|
||||||
payment_details_text = self.markets.format_payment_details("GBP", payment_details)
|
payment_details_text = self.markets.format_payment_details("GBP", payment_details)
|
||||||
ad_text = self.markets.format_ad("XMR", "GBP", payment_details_text)
|
ad_text = self.markets.format_ad("XMR", "GBP", payment_details_text)
|
||||||
expected = """* Set **Country of recipient's bank** to **"United Kingdom"**
|
expected = """* Set **Country of recipient's bank** to **"United Kingdom"**
|
||||||
|
@ -56,7 +99,10 @@ $PAYMENT$
|
||||||
self.assertEqual(ad_text, expected)
|
self.assertEqual(ad_text, expected)
|
||||||
|
|
||||||
def test_format_payment_details(self):
|
def test_format_payment_details(self):
|
||||||
payment_details = {"sort_code": "02-03-04", "account_number": "0023-0045"}
|
payment_details = {
|
||||||
|
"sort_code": "02-03-04",
|
||||||
|
"account_number": "0023-0045",
|
||||||
|
}
|
||||||
payment_details_text = self.markets.format_payment_details("GBP", payment_details)
|
payment_details_text = self.markets.format_payment_details("GBP", payment_details)
|
||||||
|
|
||||||
expected = """* Recipient name: Mark Veidemanis
|
expected = """* Recipient name: Mark Veidemanis
|
||||||
|
|
|
@ -186,7 +186,13 @@ class Transactions(util.Base):
|
||||||
if not stored_trade["currency"] == currency:
|
if not stored_trade["currency"] == currency:
|
||||||
self.log.info(f"Currency mismatch, Agora: {stored_trade['currency']} / Sink: {currency}")
|
self.log.info(f"Currency mismatch, Agora: {stored_trade['currency']} / Sink: {currency}")
|
||||||
self.irc.sendmsg(f"Currency mismatch, Agora: {stored_trade['currency']} / Sink: {currency}")
|
self.irc.sendmsg(f"Currency mismatch, Agora: {stored_trade['currency']} / Sink: {currency}")
|
||||||
self.ux.notify.notify_tx_lookup_failed(currency, amount, reference, "CURRENCY_MISMATCH", stored_trade["id"])
|
self.ux.notify.notify_tx_lookup_failed(
|
||||||
|
currency,
|
||||||
|
amount,
|
||||||
|
reference,
|
||||||
|
"CURRENCY_MISMATCH",
|
||||||
|
stored_trade["id"],
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -196,9 +202,19 @@ class Transactions(util.Base):
|
||||||
self.log.info(f"Amount does not match exactly, trying with margins: min: {min_amount} / max: {max_amount}")
|
self.log.info(f"Amount does not match exactly, trying with margins: min: {min_amount} / max: {max_amount}")
|
||||||
self.irc.sendmsg(f"Amount does not match exactly, trying with margins: min: {min_amount} / max: {max_amount}")
|
self.irc.sendmsg(f"Amount does not match exactly, trying with margins: min: {min_amount} / max: {max_amount}")
|
||||||
if not min_amount < amount < max_amount:
|
if not min_amount < amount < max_amount:
|
||||||
self.log.info("Amount mismatch - not in margins: {stored_trade['amount']} (min: {min_amount} / max: {max_amount}")
|
self.log.info(
|
||||||
self.irc.sendmsg(f"Amount mismatch - not in margins: {stored_trade['amount']} (min: {min_amount} / max: {max_amount}")
|
"Amount mismatch - not in margins: {stored_trade['amount']} (min: {min_amount} / max: {max_amount}"
|
||||||
self.ux.notify.notify_tx_lookup_failed(currency, amount, reference, "AMOUNT_MARGIN_MISMATCH", stored_trade["id"])
|
)
|
||||||
|
self.irc.sendmsg(
|
||||||
|
f"Amount mismatch - not in margins: {stored_trade['amount']} (min: {min_amount} / max: {max_amount}"
|
||||||
|
)
|
||||||
|
self.ux.notify.notify_tx_lookup_failed(
|
||||||
|
currency,
|
||||||
|
amount,
|
||||||
|
reference,
|
||||||
|
"AMOUNT_MARGIN_MISMATCH",
|
||||||
|
stored_trade["id"],
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -413,7 +429,17 @@ class Transactions(util.Base):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def new_trade(self, subclass, asset, trade_id, buyer, currency, amount, amount_crypto, provider):
|
def new_trade(
|
||||||
|
self,
|
||||||
|
subclass,
|
||||||
|
asset,
|
||||||
|
trade_id,
|
||||||
|
buyer,
|
||||||
|
currency,
|
||||||
|
amount,
|
||||||
|
amount_crypto,
|
||||||
|
provider,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
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.
|
||||||
|
@ -440,7 +466,10 @@ class Transactions(util.Base):
|
||||||
self.irc.sendmsg(f"Generated reference for {trade_id}: {reference}")
|
self.irc.sendmsg(f"Generated reference for {trade_id}: {reference}")
|
||||||
self.ux.notify.notify_new_trade(amount, currency)
|
self.ux.notify.notify_new_trade(amount, currency)
|
||||||
if settings.Agora.Send == "1":
|
if settings.Agora.Send == "1":
|
||||||
self.agora.agora.contact_message_post(trade_id, f"Hi! When sending the payment please use reference code: {reference}")
|
self.agora.agora.contact_message_post(
|
||||||
|
trade_id,
|
||||||
|
f"Hi! When sending the payment please use reference code: {reference}",
|
||||||
|
)
|
||||||
if existing_ref:
|
if existing_ref:
|
||||||
return util.convert(existing_ref)
|
return util.convert(existing_ref)
|
||||||
else:
|
else:
|
||||||
|
@ -662,8 +691,15 @@ class Transactions(util.Base):
|
||||||
price_gbp = rates["GBP"] * total_usd
|
price_gbp = rates["GBP"] * total_usd
|
||||||
|
|
||||||
cast = (
|
cast = (
|
||||||
(price_sek, price_usd, price_gbp), # Total prices in our 3 favourite currencies
|
(
|
||||||
(total_usd_agora_xmr, total_usd_agora_btc), # Total USD balance in only Agora
|
price_sek,
|
||||||
|
price_usd,
|
||||||
|
price_gbp,
|
||||||
|
), # Total prices in our 3 favourite currencies
|
||||||
|
(
|
||||||
|
total_usd_agora_xmr,
|
||||||
|
total_usd_agora_btc,
|
||||||
|
), # Total USD balance in only Agora
|
||||||
(total_xmr_agora, total_btc_agora),
|
(total_xmr_agora, total_btc_agora),
|
||||||
) # Total XMR and BTC balance in Agora
|
) # Total XMR and BTC balance in Agora
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,13 @@ log = logging.getLogger("util")
|
||||||
|
|
||||||
# Color definitions
|
# Color definitions
|
||||||
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
|
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
|
||||||
COLORS = {"WARNING": YELLOW, "INFO": WHITE, "DEBUG": BLUE, "CRITICAL": YELLOW, "ERROR": RED}
|
COLORS = {
|
||||||
|
"WARNING": YELLOW,
|
||||||
|
"INFO": WHITE,
|
||||||
|
"DEBUG": BLUE,
|
||||||
|
"CRITICAL": YELLOW,
|
||||||
|
"ERROR": RED,
|
||||||
|
}
|
||||||
RESET_SEQ = "\033[0m"
|
RESET_SEQ = "\033[0m"
|
||||||
COLOR_SEQ = "\033[1;%dm"
|
COLOR_SEQ = "\033[1;%dm"
|
||||||
BOLD_SEQ = "\033[1m"
|
BOLD_SEQ = "\033[1m"
|
||||||
|
|
Loading…
Reference in New Issue