Reformat project
This commit is contained in:
parent
933642def6
commit
ea81748c0a
|
@ -1,13 +1,21 @@
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/ambv/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 22.3.0
|
rev: 22.6.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
args:
|
exclude: ^core/migrations
|
||||||
- --line-length=120
|
- repo: https://github.com/PyCQA/isort
|
||||||
- repo: https://gitlab.com/pycqa/flake8
|
rev: 5.10.1
|
||||||
|
hooks:
|
||||||
|
- id: isort
|
||||||
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 4.0.1
|
rev: 4.0.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
args:
|
args: [--max-line-length=88]
|
||||||
- "--max-line-length=120"
|
exclude: ^core/migrations
|
||||||
|
- repo: https://github.com/thibaudcolas/curlylint
|
||||||
|
rev: v0.13.1
|
||||||
|
hooks:
|
||||||
|
- id: curlylint
|
||||||
|
files: \.(html|sls)$
|
||||||
|
|
|
@ -1,27 +1,25 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Twisted/Klein imports
|
# Twisted/Klein imports
|
||||||
from twisted.internet import reactor
|
|
||||||
from klein import Klein
|
|
||||||
from twisted.internet.protocol import Factory
|
|
||||||
|
|
||||||
# Other library imports
|
# Other library imports
|
||||||
from json import dumps
|
from json import dumps
|
||||||
from signal import signal, SIGINT
|
from signal import SIGINT, signal
|
||||||
from sys import argv
|
from sys import argv
|
||||||
|
|
||||||
# Project imports
|
import lib.antifraud
|
||||||
from settings import settings
|
import lib.logstash
|
||||||
import util
|
import lib.markets
|
||||||
|
import lib.money
|
||||||
|
import lib.transactions
|
||||||
# New style classes
|
# New style classes
|
||||||
import sinks
|
import sinks
|
||||||
import sources
|
import sources
|
||||||
|
import util
|
||||||
import ux
|
import ux
|
||||||
import lib.antifraud
|
from klein import Klein
|
||||||
import lib.transactions
|
# Project imports
|
||||||
import lib.markets
|
from settings import settings
|
||||||
import lib.money
|
from twisted.internet import reactor
|
||||||
import lib.logstash
|
from twisted.internet.protocol import Factory
|
||||||
|
|
||||||
init_map = None
|
init_map = None
|
||||||
Factory.noisy = False
|
Factory.noisy = False
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
# Other library imports
|
# Other library imports
|
||||||
|
import util
|
||||||
from redis import StrictRedis
|
from redis import StrictRedis
|
||||||
|
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
import util
|
|
||||||
|
|
||||||
log = util.get_logger("DB")
|
log = util.get_logger("DB")
|
||||||
|
|
||||||
|
@ -129,7 +128,9 @@ def cleanup(subclass, references):
|
||||||
for tx, reference in get_ref_map().items():
|
for tx, reference in get_ref_map().items():
|
||||||
if reference not in references:
|
if reference not in references:
|
||||||
if get_subclass(reference) == subclass:
|
if get_subclass(reference) == subclass:
|
||||||
logmessage = f"[{reference}] ({subclass}): Archiving trade reference. TX: {tx}"
|
logmessage = (
|
||||||
|
f"[{reference}] ({subclass}): Archiving trade reference. TX: {tx}"
|
||||||
|
)
|
||||||
messages.append(logmessage)
|
messages.append(logmessage)
|
||||||
log.info(logmessage)
|
log.info(logmessage)
|
||||||
r.rename(f"trade.{tx}.reference", f"archive.trade.{tx}.reference")
|
r.rename(f"trade.{tx}.reference", f"archive.trade.{tx}.reference")
|
||||||
|
|
|
@ -3,18 +3,13 @@
|
||||||
# Large API. Lots of lines can't be avoided.
|
# Large API. Lots of lines can't be avoided.
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any, Dict, List, Optional, Union
|
||||||
from typing import Dict
|
|
||||||
from typing import List
|
|
||||||
from typing import Optional
|
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
import treq
|
import treq
|
||||||
from twisted.internet.defer import inlineCallbacks
|
|
||||||
|
|
||||||
# Project imports
|
# Project imports
|
||||||
import util
|
import util
|
||||||
|
from twisted.internet.defer import inlineCallbacks
|
||||||
|
|
||||||
__author__ = "marvin8"
|
__author__ = "marvin8"
|
||||||
__copyright__ = "(C) 2021 https://codeberg.org/MarvinsCryptoTools/agoradesk_py"
|
__copyright__ = "(C) 2021 https://codeberg.org/MarvinsCryptoTools/agoradesk_py"
|
||||||
|
@ -88,7 +83,8 @@ class AgoraDesk:
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"User-Agent": f"agoradesk_py/{__version__} " f"https://codeberg.org/MarvinsCryptoTools/agoradesk_py",
|
"User-Agent": f"agoradesk_py/{__version__} "
|
||||||
|
f"https://codeberg.org/MarvinsCryptoTools/agoradesk_py",
|
||||||
"Authorization": self.api_key,
|
"Authorization": self.api_key,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +249,9 @@ class AgoraDesk:
|
||||||
# ===========================
|
# ===========================
|
||||||
|
|
||||||
# post/feedback/{username} • Give feedback to a user
|
# post/feedback/{username} • Give feedback to a user
|
||||||
def feedback(self, username: str, feedback: str, msg: Optional[str]) -> Dict[str, Any]:
|
def feedback(
|
||||||
|
self, username: str, feedback: str, msg: Optional[str]
|
||||||
|
) -> Dict[str, Any]:
|
||||||
"""See Agoradesk API.
|
"""See Agoradesk API.
|
||||||
|
|
||||||
https://agoradesk.com/api-docs/v1#operation/setUserFeedback
|
https://agoradesk.com/api-docs/v1#operation/setUserFeedback
|
||||||
|
@ -279,7 +277,9 @@ class AgoraDesk:
|
||||||
|
|
||||||
https://agoradesk.com/api-docs/v1#operation/markPaid
|
https://agoradesk.com/api-docs/v1#operation/markPaid
|
||||||
"""
|
"""
|
||||||
return self._api_call(api_method=f"contact_mark_as_paid/{trade_id}", http_method="POST")
|
return self._api_call(
|
||||||
|
api_method=f"contact_mark_as_paid/{trade_id}", http_method="POST"
|
||||||
|
)
|
||||||
|
|
||||||
# post/contact_cancel/{trade_id} • Cancel the trade
|
# post/contact_cancel/{trade_id} • Cancel the trade
|
||||||
def contact_cancel(
|
def contact_cancel(
|
||||||
|
@ -299,7 +299,9 @@ class AgoraDesk:
|
||||||
# post/contact_escrow/{trade_id} • Enable escrow
|
# post/contact_escrow/{trade_id} • Enable escrow
|
||||||
|
|
||||||
# get/contact_messages/{trade_id} • Get trade messages
|
# get/contact_messages/{trade_id} • Get trade messages
|
||||||
def contact_messages(self, trade_id: str, after: Optional[arrow.Arrow] = None) -> Dict[str, Any]:
|
def contact_messages(
|
||||||
|
self, trade_id: str, after: Optional[arrow.Arrow] = None
|
||||||
|
) -> Dict[str, Any]:
|
||||||
"""See Agoradesk API.
|
"""See Agoradesk API.
|
||||||
|
|
||||||
https://agoradesk.com/api-docs/v1#operation/getTradeMessages
|
https://agoradesk.com/api-docs/v1#operation/getTradeMessages
|
||||||
|
@ -354,7 +356,9 @@ class AgoraDesk:
|
||||||
|
|
||||||
# Todo: Add image upload functionality
|
# Todo: Add image upload functionality
|
||||||
# post/contact_message_post/{trade_id} • Send a chat message/attachment
|
# post/contact_message_post/{trade_id} • Send a chat message/attachment
|
||||||
def contact_message_post(self, trade_id: str, msg: Optional[str] = None) -> Dict[str, Any]:
|
def contact_message_post(
|
||||||
|
self, trade_id: str, msg: Optional[str] = None
|
||||||
|
) -> Dict[str, Any]:
|
||||||
"""See Agoradesk API.
|
"""See Agoradesk API.
|
||||||
|
|
||||||
https://agoradesk.com/api-docs/v1#operation/sendChatMessage
|
https://agoradesk.com/api-docs/v1#operation/sendChatMessage
|
||||||
|
@ -504,7 +508,9 @@ class AgoraDesk:
|
||||||
if track_max_amount:
|
if track_max_amount:
|
||||||
params["track_max_amount"] = 1 if track_max_amount else 0
|
params["track_max_amount"] = 1 if track_max_amount else 0
|
||||||
if require_trusted_by_advertiser:
|
if require_trusted_by_advertiser:
|
||||||
params["require_trusted_by_advertiser"] = 1 if require_trusted_by_advertiser else 0
|
params["require_trusted_by_advertiser"] = (
|
||||||
|
1 if require_trusted_by_advertiser else 0
|
||||||
|
)
|
||||||
if verified_email_required:
|
if verified_email_required:
|
||||||
params["verified_email_required"] = 1 if verified_email_required else 0
|
params["verified_email_required"] = 1 if verified_email_required else 0
|
||||||
if online_provider:
|
if online_provider:
|
||||||
|
@ -680,7 +686,8 @@ class AgoraDesk:
|
||||||
|
|
||||||
params = self._generic_search_parameters(amount, page)
|
params = self._generic_search_parameters(amount, page)
|
||||||
return self._api_call(
|
return self._api_call(
|
||||||
api_method=f"{direction}-{main_currency}-online/" f"{exchange_currency}{add_to_api_method}",
|
api_method=f"{direction}-{main_currency}-online/"
|
||||||
|
f"{exchange_currency}{add_to_api_method}",
|
||||||
query_values=params,
|
query_values=params,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -823,7 +830,8 @@ class AgoraDesk:
|
||||||
params = self._generic_search_parameters(amount, page)
|
params = self._generic_search_parameters(amount, page)
|
||||||
|
|
||||||
return self._api_call(
|
return self._api_call(
|
||||||
api_method=f"{direction}-{main_currency}-with-cash/" f"{exchange_currency}/{country_code}/{lat}/{lon}",
|
api_method=f"{direction}-{main_currency}-with-cash/"
|
||||||
|
f"{exchange_currency}/{country_code}/{lat}/{lon}",
|
||||||
query_values=params,
|
query_values=params,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -938,7 +946,9 @@ class AgoraDesk:
|
||||||
# Statistics related API Methods
|
# Statistics related API Methods
|
||||||
# ==============================
|
# ==============================
|
||||||
|
|
||||||
def moneroaverage(self, currency: Optional[str] = "ticker-all-currencies") -> Dict[str, Any]:
|
def moneroaverage(
|
||||||
|
self, currency: Optional[str] = "ticker-all-currencies"
|
||||||
|
) -> Dict[str, Any]:
|
||||||
"""See Agoradesk API.
|
"""See Agoradesk API.
|
||||||
|
|
||||||
https://agoradesk.com/api-docs/v1#operation/getXmrTicker and
|
https://agoradesk.com/api-docs/v1#operation/getXmrTicker and
|
||||||
|
@ -1028,7 +1038,9 @@ class AgoraDesk:
|
||||||
if otp:
|
if otp:
|
||||||
params["otp"] = otp
|
params["otp"] = otp
|
||||||
|
|
||||||
return self._api_call(api_method="wallet-send", http_method="POST", query_values=params)
|
return self._api_call(
|
||||||
|
api_method="wallet-send", http_method="POST", query_values=params
|
||||||
|
)
|
||||||
|
|
||||||
def wallet_send_xmr(
|
def wallet_send_xmr(
|
||||||
self,
|
self,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Project imports
|
# Project imports
|
||||||
import util
|
|
||||||
import db
|
import db
|
||||||
|
import util
|
||||||
|
|
||||||
|
|
||||||
class AntiFraud(util.Base):
|
class AntiFraud(util.Base):
|
||||||
|
@ -46,7 +46,9 @@ class AntiFraud(util.Base):
|
||||||
return True
|
return True
|
||||||
if platform_buyer in senders:
|
if platform_buyer in senders:
|
||||||
return True
|
return True
|
||||||
self.ux.notify.notify_sender_name_mismatch(reference, platform_buyer, bank_sender)
|
self.ux.notify.notify_sender_name_mismatch(
|
||||||
|
reference, platform_buyer, bank_sender
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def check_tx_sender(self, tx, reference):
|
def check_tx_sender(self, tx, reference):
|
||||||
|
@ -65,7 +67,9 @@ class AntiFraud(util.Base):
|
||||||
bank_sender = stored_tx["sender"]
|
bank_sender = stored_tx["sender"]
|
||||||
platform_buyer = stored_trade["buyer"]
|
platform_buyer = stored_trade["buyer"]
|
||||||
platform = stored_trade["subclass"]
|
platform = stored_trade["subclass"]
|
||||||
is_allowed = self.check_valid_sender(reference, platform, bank_sender, platform_buyer)
|
is_allowed = self.check_valid_sender(
|
||||||
|
reference, platform, bank_sender, platform_buyer
|
||||||
|
)
|
||||||
if is_allowed is True:
|
if is_allowed is True:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -1,29 +1,22 @@
|
||||||
"""See https://agoradesk.com/api-docs/v1."""
|
"""See https://agoradesk.com/api-docs/v1."""
|
||||||
# pylint: disable=too-many-lines
|
# pylint: disable=too-many-lines
|
||||||
# Large API. Lots of lines can't be avoided.
|
# Large API. Lots of lines can't be avoided.
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
from typing import Any
|
|
||||||
from typing import Dict
|
|
||||||
from typing import List
|
|
||||||
from typing import Optional
|
|
||||||
from typing import Union
|
|
||||||
import arrow
|
|
||||||
|
|
||||||
# Project imports
|
|
||||||
import util
|
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import hmac as hmac_lib
|
import hmac as hmac_lib
|
||||||
import requests
|
import json
|
||||||
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import treq
|
from typing import Any, Dict, List, Optional, Union
|
||||||
from twisted.internet.defer import inlineCallbacks
|
|
||||||
|
|
||||||
|
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
import arrow
|
||||||
|
import requests
|
||||||
|
import treq
|
||||||
|
# Project imports
|
||||||
|
import util
|
||||||
|
from twisted.internet.defer import inlineCallbacks
|
||||||
|
|
||||||
__author__ = "marvin8"
|
__author__ = "marvin8"
|
||||||
__copyright__ = "(C) 2021 https://codeberg.org/MarvinsCryptoTools/agoradesk_py"
|
__copyright__ = "(C) 2021 https://codeberg.org/MarvinsCryptoTools/agoradesk_py"
|
||||||
__version__ = "0.1.0"
|
__version__ = "0.1.0"
|
||||||
|
@ -86,17 +79,25 @@ class LocalBitcoins:
|
||||||
message += params_encoded.encode("ascii")
|
message += params_encoded.encode("ascii")
|
||||||
else:
|
else:
|
||||||
message += params_encoded
|
message += params_encoded
|
||||||
signature = hmac_lib.new(self.hmac_secret, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
|
signature = (
|
||||||
|
hmac_lib.new(self.hmac_secret, msg=message, digestmod=hashlib.sha256)
|
||||||
|
.hexdigest()
|
||||||
|
.upper()
|
||||||
|
)
|
||||||
return signature
|
return signature
|
||||||
|
|
||||||
def encode_params(self, http_method, api_call_url, query_values):
|
def encode_params(self, http_method, api_call_url, query_values):
|
||||||
if http_method == "POST":
|
if http_method == "POST":
|
||||||
api_request = requests.Request("POST", api_call_url, data=query_values).prepare()
|
api_request = requests.Request(
|
||||||
|
"POST", api_call_url, data=query_values
|
||||||
|
).prepare()
|
||||||
params_encoded = api_request.body
|
params_encoded = api_request.body
|
||||||
|
|
||||||
# GET method
|
# GET method
|
||||||
else:
|
else:
|
||||||
api_request = requests.Request("GET", api_call_url, params=query_values).prepare()
|
api_request = requests.Request(
|
||||||
|
"GET", api_call_url, params=query_values
|
||||||
|
).prepare()
|
||||||
params_encoded = urlparse(api_request.url).query
|
params_encoded = urlparse(api_request.url).query
|
||||||
return (api_request, params_encoded)
|
return (api_request, params_encoded)
|
||||||
|
|
||||||
|
@ -132,7 +133,9 @@ class LocalBitcoins:
|
||||||
url = url[len(SERVER) :] # noqa
|
url = url[len(SERVER) :] # noqa
|
||||||
|
|
||||||
# HMAC crypto stuff
|
# HMAC crypto stuff
|
||||||
api_request, params_encoded = self.encode_params(http_method, api_call_url, query_values)
|
api_request, params_encoded = self.encode_params(
|
||||||
|
http_method, api_call_url, query_values
|
||||||
|
)
|
||||||
nonce = str(int(time.time() * 1000)).encode("ascii")
|
nonce = str(int(time.time() * 1000)).encode("ascii")
|
||||||
signature = self.sign_payload(nonce, url, params_encoded)
|
signature = self.sign_payload(nonce, url, params_encoded)
|
||||||
|
|
||||||
|
@ -288,7 +291,9 @@ class LocalBitcoins:
|
||||||
# ===========================
|
# ===========================
|
||||||
|
|
||||||
# post/feedback/{username} • Give feedback to a user
|
# post/feedback/{username} • Give feedback to a user
|
||||||
def feedback(self, username: str, feedback: str, msg: Optional[str]) -> Dict[str, Any]:
|
def feedback(
|
||||||
|
self, username: str, feedback: str, msg: Optional[str]
|
||||||
|
) -> Dict[str, Any]:
|
||||||
"""See LocalBitcoins API.
|
"""See LocalBitcoins API.
|
||||||
|
|
||||||
https://localbitcoins.com/api-docs/#feedback
|
https://localbitcoins.com/api-docs/#feedback
|
||||||
|
@ -314,7 +319,9 @@ class LocalBitcoins:
|
||||||
|
|
||||||
https://localbitcoins.com/api-docs/#contact-paid
|
https://localbitcoins.com/api-docs/#contact-paid
|
||||||
"""
|
"""
|
||||||
return self._api_call(api_method=f"contact_mark_as_paid/{trade_id}/", http_method="POST")
|
return self._api_call(
|
||||||
|
api_method=f"contact_mark_as_paid/{trade_id}/", http_method="POST"
|
||||||
|
)
|
||||||
|
|
||||||
# post/contact_cancel/{trade_id} • Cancel the trade
|
# post/contact_cancel/{trade_id} • Cancel the trade
|
||||||
def contact_cancel(
|
def contact_cancel(
|
||||||
|
@ -334,7 +341,9 @@ class LocalBitcoins:
|
||||||
# post/contact_escrow/{trade_id} • Enable escrow
|
# post/contact_escrow/{trade_id} • Enable escrow
|
||||||
|
|
||||||
# get/contact_messages/{trade_id} • Get trade messages
|
# get/contact_messages/{trade_id} • Get trade messages
|
||||||
def contact_messages(self, trade_id: str, after: Optional[arrow.Arrow] = None) -> Dict[str, Any]:
|
def contact_messages(
|
||||||
|
self, trade_id: str, after: Optional[arrow.Arrow] = None
|
||||||
|
) -> Dict[str, Any]:
|
||||||
"""See LocalBitcoins API.
|
"""See LocalBitcoins API.
|
||||||
|
|
||||||
https://localbitcoins.com/api-docs/#contact-message
|
https://localbitcoins.com/api-docs/#contact-message
|
||||||
|
@ -389,7 +398,9 @@ class LocalBitcoins:
|
||||||
|
|
||||||
# Todo: Add image upload functionality
|
# Todo: Add image upload functionality
|
||||||
# post/contact_message_post/{trade_id} • Send a chat message/attachment
|
# post/contact_message_post/{trade_id} • Send a chat message/attachment
|
||||||
def contact_message_post(self, trade_id: str, msg: Optional[str] = None) -> Dict[str, Any]:
|
def contact_message_post(
|
||||||
|
self, trade_id: str, msg: Optional[str] = None
|
||||||
|
) -> Dict[str, Any]:
|
||||||
"""See LocalBitcoins API.
|
"""See LocalBitcoins API.
|
||||||
|
|
||||||
https://localbitcoins.com/api-docs/#contact-post
|
https://localbitcoins.com/api-docs/#contact-post
|
||||||
|
@ -726,7 +737,8 @@ class LocalBitcoins:
|
||||||
params = self._generic_search_parameters(amount, page)
|
params = self._generic_search_parameters(amount, page)
|
||||||
|
|
||||||
return self._api_call(
|
return self._api_call(
|
||||||
api_method=f"{direction}-{main_currency}-online/" f"{exchange_currency}{add_to_api_method}/.json",
|
api_method=f"{direction}-{main_currency}-online/"
|
||||||
|
f"{exchange_currency}{add_to_api_method}/.json",
|
||||||
query_values=params,
|
query_values=params,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Other library imports
|
# Other library imports
|
||||||
from json import dumps
|
|
||||||
import logstash
|
|
||||||
import logging
|
import logging
|
||||||
|
from json import dumps
|
||||||
|
|
||||||
|
import logstash
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
# Other library imports
|
# Other library imports
|
||||||
from json import loads
|
from json import loads
|
||||||
|
|
||||||
|
import db
|
||||||
|
import util
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
import util
|
|
||||||
import db
|
|
||||||
|
|
||||||
|
|
||||||
class Markets(util.Base):
|
class Markets(util.Base):
|
||||||
|
@ -60,7 +60,9 @@ class Markets(util.Base):
|
||||||
self.log.info(f"Sending bank details/reference for {platform}/{trade_id}")
|
self.log.info(f"Sending bank details/reference for {platform}/{trade_id}")
|
||||||
if send_setting == "1":
|
if send_setting == "1":
|
||||||
account_info = self.get_matching_account_details(platform, currency)
|
account_info = self.get_matching_account_details(platform, currency)
|
||||||
formatted_account_info = self.format_payment_details(currency, account_info, real=True)
|
formatted_account_info = self.format_payment_details(
|
||||||
|
currency, account_info, real=True
|
||||||
|
)
|
||||||
if not formatted_account_info:
|
if not formatted_account_info:
|
||||||
self.log.error(f"Payment info invalid: {formatted_account_info}")
|
self.log.error(f"Payment info invalid: {formatted_account_info}")
|
||||||
return
|
return
|
||||||
|
@ -110,12 +112,21 @@ class Markets(util.Base):
|
||||||
currencies = self.get_all_currencies(platform)
|
currencies = self.get_all_currencies(platform)
|
||||||
providers = self.get_all_providers(platform)
|
providers = self.get_all_providers(platform)
|
||||||
if platform == "lbtc":
|
if platform == "lbtc":
|
||||||
providers = [self.sources.lbtc.map_provider(x, reverse=True) for x in providers]
|
providers = [
|
||||||
|
self.sources.lbtc.map_provider(x, reverse=True) for x in providers
|
||||||
|
]
|
||||||
sinks_currencies = self.sinks.currencies
|
sinks_currencies = self.sinks.currencies
|
||||||
supported_currencies = [currency for currency in currencies if currency in sinks_currencies]
|
supported_currencies = [
|
||||||
|
currency for currency in currencies if currency in sinks_currencies
|
||||||
|
]
|
||||||
currencies = supported_currencies
|
currencies = supported_currencies
|
||||||
|
|
||||||
brute = [(asset, currency, provider) for asset in assets for currency in currencies for provider in providers]
|
brute = [
|
||||||
|
(asset, currency, provider)
|
||||||
|
for asset in assets
|
||||||
|
for currency in currencies
|
||||||
|
for provider in providers
|
||||||
|
]
|
||||||
for asset, currency, provider in brute:
|
for asset, currency, provider in brute:
|
||||||
# Filter currency
|
# Filter currency
|
||||||
try:
|
try:
|
||||||
|
@ -123,22 +134,32 @@ class Markets(util.Base):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# self.log.error("Error getting public ads for currency {currency}", currency=currency)
|
# self.log.error("Error getting public ads for currency {currency}", currency=currency)
|
||||||
if currency == "GBP":
|
if currency == "GBP":
|
||||||
self.log.error("Error getting public ads for currency GBP, aborting")
|
self.log.error(
|
||||||
|
"Error getting public ads for currency GBP, aborting"
|
||||||
|
)
|
||||||
break
|
break
|
||||||
continue
|
continue
|
||||||
# Filter asset
|
# Filter asset
|
||||||
public_ads_filtered = [ad for ad in public_ads_currency if ad[4] == asset]
|
public_ads_filtered = [ad for ad in public_ads_currency if ad[4] == asset]
|
||||||
|
|
||||||
# Filter provider
|
# Filter provider
|
||||||
public_ads_filtered = [ad for ad in public_ads_filtered if ad[3] == provider]
|
public_ads_filtered = [
|
||||||
|
ad for ad in public_ads_filtered if ad[3] == provider
|
||||||
|
]
|
||||||
our_ads = [ad for ad in public_ads_filtered if ad[1] == username]
|
our_ads = [ad for ad in public_ads_filtered if ad[1] == username]
|
||||||
if not our_ads:
|
if not our_ads:
|
||||||
self.log.warning(f"No ads found in {platform} public listing for {asset} {currency} {provider}")
|
self.log.warning(
|
||||||
|
f"No ads found in {platform} public listing for {asset} {currency} {provider}"
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
new_margin = self.autoprice(username, min_margin, max_margin, public_ads_filtered, currency)
|
new_margin = self.autoprice(
|
||||||
|
username, min_margin, max_margin, public_ads_filtered, currency
|
||||||
|
)
|
||||||
# self.log.info("New rate for {currency}: {rate}", currency=currency, rate=new_margin)
|
# self.log.info("New rate for {currency}: {rate}", currency=currency, rate=new_margin)
|
||||||
if platform == "agora":
|
if platform == "agora":
|
||||||
new_formula = f"coingecko{asset.lower()}usd*usd{currency.lower()}*{new_margin}"
|
new_formula = (
|
||||||
|
f"coingecko{asset.lower()}usd*usd{currency.lower()}*{new_margin}"
|
||||||
|
)
|
||||||
elif platform == "lbtc":
|
elif platform == "lbtc":
|
||||||
new_formula = f"btc_in_usd*{new_margin}*USD_in_{currency}"
|
new_formula = f"btc_in_usd*{new_margin}*USD_in_{currency}"
|
||||||
for ad in our_ads:
|
for ad in our_ads:
|
||||||
|
@ -172,7 +193,9 @@ class Markets(util.Base):
|
||||||
ads_without_us = [ad for ad in ads if not ad[1] == username]
|
ads_without_us = [ad for ad in ads if not ad[1] == username]
|
||||||
# self.log.debug("Ads without us: {x}", x=ads_without_us)
|
# self.log.debug("Ads without us: {x}", x=ads_without_us)
|
||||||
# Find ads above our min that are not us
|
# Find ads above our min that are not us
|
||||||
ads_above_our_min_not_us = [ad for ad in ads_without_us if ad[6] > float(min_margin)]
|
ads_above_our_min_not_us = [
|
||||||
|
ad for ad in ads_without_us if ad[6] > float(min_margin)
|
||||||
|
]
|
||||||
# self.log.debug("Ads above our min not us: {x}", x=ads_above_our_min_not_us)
|
# self.log.debug("Ads above our min not us: {x}", x=ads_above_our_min_not_us)
|
||||||
# Check that this list without us is not empty
|
# Check that this list without us is not empty
|
||||||
if ads_without_us:
|
if ads_without_us:
|
||||||
|
@ -247,7 +270,9 @@ class Markets(util.Base):
|
||||||
currencies = self.sinks.currencies
|
currencies = self.sinks.currencies
|
||||||
account_info = self.sinks.account_info
|
account_info = self.sinks.account_info
|
||||||
all_currencies = self.get_all_currencies(platform)
|
all_currencies = self.get_all_currencies(platform)
|
||||||
supported_currencies = [currency for currency in currencies if currency in all_currencies]
|
supported_currencies = [
|
||||||
|
currency for currency in currencies if currency in all_currencies
|
||||||
|
]
|
||||||
currency_account_info_map = {}
|
currency_account_info_map = {}
|
||||||
for currency in supported_currencies:
|
for currency in supported_currencies:
|
||||||
for bank, accounts in account_info.items():
|
for bank, accounts in account_info.items():
|
||||||
|
@ -255,11 +280,16 @@ class Markets(util.Base):
|
||||||
if account["currency"] == currency:
|
if account["currency"] == currency:
|
||||||
currency_account_info_map[currency] = account["account_number"]
|
currency_account_info_map[currency] = account["account_number"]
|
||||||
currency_account_info_map[currency]["bank"] = bank.split("_")[0]
|
currency_account_info_map[currency]["bank"] = bank.split("_")[0]
|
||||||
currency_account_info_map[currency]["recipient"] = account["recipient"]
|
currency_account_info_map[currency]["recipient"] = account[
|
||||||
|
"recipient"
|
||||||
|
]
|
||||||
return (supported_currencies, currency_account_info_map)
|
return (supported_currencies, currency_account_info_map)
|
||||||
|
|
||||||
def get_matching_account_details(self, platform, currency):
|
def get_matching_account_details(self, platform, currency):
|
||||||
supported_currencies, currency_account_info_map = self.get_valid_account_details(platform)
|
(
|
||||||
|
supported_currencies,
|
||||||
|
currency_account_info_map,
|
||||||
|
) = self.get_valid_account_details(platform)
|
||||||
if currency not in supported_currencies:
|
if currency not in supported_currencies:
|
||||||
return False
|
return False
|
||||||
return currency_account_info_map[currency]
|
return currency_account_info_map[currency]
|
||||||
|
@ -278,7 +308,10 @@ class Markets(util.Base):
|
||||||
currencies = self.sinks.currencies
|
currencies = self.sinks.currencies
|
||||||
if not account_info:
|
if not account_info:
|
||||||
account_info = self.sinks.account_info
|
account_info = self.sinks.account_info
|
||||||
supported_currencies, currency_account_info_map = self.get_valid_account_details(platform)
|
(
|
||||||
|
supported_currencies,
|
||||||
|
currency_account_info_map,
|
||||||
|
) = self.get_valid_account_details(platform)
|
||||||
|
|
||||||
# not_supported = [currency for currency in all_currencies if currency not in supported_currencies]
|
# not_supported = [currency for currency in all_currencies if currency not in supported_currencies]
|
||||||
|
|
||||||
|
@ -329,7 +362,9 @@ class Markets(util.Base):
|
||||||
"""
|
"""
|
||||||
platforms = ("agora", "lbtc")
|
platforms = ("agora", "lbtc")
|
||||||
for platform in platforms:
|
for platform in platforms:
|
||||||
self._distribute_account_details(platform, currencies=currencies, account_info=account_info)
|
self._distribute_account_details(
|
||||||
|
platform, currencies=currencies, account_info=account_info
|
||||||
|
)
|
||||||
|
|
||||||
def format_ad(self, asset, currency, payment_details_text):
|
def format_ad(self, asset, currency, payment_details_text):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
# Twisted imports
|
# Twisted imports
|
||||||
from twisted.internet.task import LoopingCall
|
|
||||||
from twisted.internet.defer import inlineCallbacks
|
|
||||||
|
|
||||||
# Other library imports
|
|
||||||
from pycoingecko import CoinGeckoAPI
|
|
||||||
from forex_python.converter import CurrencyRates
|
|
||||||
import urllib3
|
|
||||||
import logging
|
import logging
|
||||||
from opensearchpy import OpenSearch
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
import urllib3
|
||||||
|
import util
|
||||||
|
from forex_python.converter import CurrencyRates
|
||||||
|
from lib.logstash import send_logstash
|
||||||
|
from opensearchpy import OpenSearch
|
||||||
|
# Other library imports
|
||||||
|
from pycoingecko import CoinGeckoAPI
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
import util
|
from twisted.internet.defer import inlineCallbacks
|
||||||
from lib.logstash import send_logstash
|
from twisted.internet.task import LoopingCall
|
||||||
|
|
||||||
# TODO: secure ES traffic properly
|
# TODO: secure ES traffic properly
|
||||||
urllib3.disable_warnings()
|
urllib3.disable_warnings()
|
||||||
|
@ -74,7 +73,15 @@ class Money(util.Base):
|
||||||
total_remaining = self.get_total_remaining()
|
total_remaining = self.get_total_remaining()
|
||||||
total_with_trades = self.get_total_with_trades()
|
total_with_trades = self.get_total_with_trades()
|
||||||
# This will make them all run concurrently, hopefully not hitting rate limits
|
# This will make them all run concurrently, hopefully not hitting rate limits
|
||||||
for x in (total, remaining, profit, profit_with_trades, open_trades, total_remaining, total_with_trades):
|
for x in (
|
||||||
|
total,
|
||||||
|
remaining,
|
||||||
|
profit,
|
||||||
|
profit_with_trades,
|
||||||
|
open_trades,
|
||||||
|
total_remaining,
|
||||||
|
total_with_trades,
|
||||||
|
):
|
||||||
yield x
|
yield x
|
||||||
|
|
||||||
def setup_loops(self):
|
def setup_loops(self):
|
||||||
|
@ -382,7 +389,9 @@ class Money(util.Base):
|
||||||
if not total_usd:
|
if not total_usd:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
withdraw_threshold = float(settings.Money.BaseUSD) + float(settings.Money.WithdrawLimit)
|
withdraw_threshold = float(settings.Money.BaseUSD) + float(
|
||||||
|
settings.Money.WithdrawLimit
|
||||||
|
)
|
||||||
remaining = withdraw_threshold - total_usd
|
remaining = withdraw_threshold - total_usd
|
||||||
cast_es = {
|
cast_es = {
|
||||||
"remaining_usd": remaining,
|
"remaining_usd": remaining,
|
||||||
|
@ -416,13 +425,17 @@ class Money(util.Base):
|
||||||
asset = "BTC"
|
asset = "BTC"
|
||||||
if asset == "XMR":
|
if asset == "XMR":
|
||||||
amount_crypto = contact["data"]["amount_xmr"]
|
amount_crypto = contact["data"]["amount_xmr"]
|
||||||
history = self.cg.get_coin_history_by_id(id="monero", date=date_formatted)
|
history = self.cg.get_coin_history_by_id(
|
||||||
|
id="monero", date=date_formatted
|
||||||
|
)
|
||||||
if "market_data" not in history:
|
if "market_data" not in history:
|
||||||
return False
|
return False
|
||||||
crypto_usd = float(history["market_data"]["current_price"]["usd"])
|
crypto_usd = float(history["market_data"]["current_price"]["usd"])
|
||||||
elif asset == "BTC":
|
elif asset == "BTC":
|
||||||
amount_crypto = contact["data"]["amount_btc"]
|
amount_crypto = contact["data"]["amount_btc"]
|
||||||
history = self.cg.get_coin_history_by_id(id="bitcoin", date=date_formatted)
|
history = self.cg.get_coin_history_by_id(
|
||||||
|
id="bitcoin", date=date_formatted
|
||||||
|
)
|
||||||
crypto_usd = float(history["market_data"]["current_price"]["usd"])
|
crypto_usd = float(history["market_data"]["current_price"]["usd"])
|
||||||
# Convert crypto to fiat
|
# Convert crypto to fiat
|
||||||
amount = float(amount_crypto) * crypto_usd
|
amount = float(amount_crypto) * crypto_usd
|
||||||
|
@ -476,7 +489,9 @@ class Money(util.Base):
|
||||||
if not total_usd:
|
if not total_usd:
|
||||||
return False
|
return False
|
||||||
total_usd += total_trades_usd
|
total_usd += total_trades_usd
|
||||||
withdraw_threshold = float(settings.Money.BaseUSD) + float(settings.Money.WithdrawLimit)
|
withdraw_threshold = float(settings.Money.BaseUSD) + float(
|
||||||
|
settings.Money.WithdrawLimit
|
||||||
|
)
|
||||||
remaining = withdraw_threshold - total_usd
|
remaining = withdraw_threshold - total_usd
|
||||||
|
|
||||||
cast_es = {
|
cast_es = {
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
# Twisted/Klein imports
|
# Twisted/Klein imports
|
||||||
from twisted.internet.defer import inlineCallbacks
|
|
||||||
|
|
||||||
# Other library imports
|
# Other library imports
|
||||||
from json import dumps
|
from json import dumps
|
||||||
from random import choices
|
from random import choices
|
||||||
from string import ascii_uppercase
|
from string import ascii_uppercase
|
||||||
|
|
||||||
|
|
||||||
# Project imports
|
|
||||||
from settings import settings
|
|
||||||
import db
|
import db
|
||||||
import util
|
import util
|
||||||
|
# Project imports
|
||||||
|
from settings import settings
|
||||||
|
from twisted.internet.defer import inlineCallbacks
|
||||||
|
|
||||||
|
|
||||||
class Transactions(util.Base):
|
class Transactions(util.Base):
|
||||||
|
@ -95,7 +93,9 @@ class Transactions(util.Base):
|
||||||
if len(stored_trade_reference) > 1:
|
if len(stored_trade_reference) > 1:
|
||||||
self.log.error(f"Multiple references valid for TXID {txid}: {reference}")
|
self.log.error(f"Multiple references valid for TXID {txid}: {reference}")
|
||||||
self.irc.sendmsg(f"Multiple references valid for TXID {txid}: {reference}")
|
self.irc.sendmsg(f"Multiple references valid for TXID {txid}: {reference}")
|
||||||
self.ux.notify.notify_tx_lookup_failed(currency, amount, reference, "MULTIPLE_REFS_MATCH")
|
self.ux.notify.notify_tx_lookup_failed(
|
||||||
|
currency, amount, reference, "MULTIPLE_REFS_MATCH"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
if len(stored_trade_reference) == 0:
|
if len(stored_trade_reference) == 0:
|
||||||
return None
|
return None
|
||||||
|
@ -105,10 +105,16 @@ class Transactions(util.Base):
|
||||||
amount_usd = self.money.to_usd(amount, currency)
|
amount_usd = self.money.to_usd(amount, currency)
|
||||||
# Amount is reliable here as it is checked by find_trade, so no need for stored_trade["amount"]
|
# Amount is reliable here as it is checked by find_trade, so no need for stored_trade["amount"]
|
||||||
if float(amount_usd) > float(settings.Agora.AcceptableAltLookupUSD):
|
if float(amount_usd) > float(settings.Agora.AcceptableAltLookupUSD):
|
||||||
self.log.info("Not checking against amount and currency as amount exceeds MAX")
|
self.log.info(
|
||||||
self.irc.sendmsg("Not checking against amount and currency as amount exceeds MAX")
|
"Not checking against amount and currency as amount exceeds MAX"
|
||||||
|
)
|
||||||
|
self.irc.sendmsg(
|
||||||
|
"Not checking against amount and currency as amount exceeds MAX"
|
||||||
|
)
|
||||||
# Close here if the amount exceeds the allowable limit for no reference
|
# Close here if the amount exceeds the allowable limit for no reference
|
||||||
self.ux.notify.notify_tx_lookup_failed(currency, amount, reference, "EXCEEDS_MAX")
|
self.ux.notify.notify_tx_lookup_failed(
|
||||||
|
currency, amount, reference, "EXCEEDS_MAX"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -124,9 +130,15 @@ class Transactions(util.Base):
|
||||||
return False
|
return False
|
||||||
stored_trade = self.find_trade(txid, currency, amount)
|
stored_trade = self.find_trade(txid, currency, amount)
|
||||||
if not stored_trade:
|
if not stored_trade:
|
||||||
self.log.info(f"Failed to get reference by amount and currency: {txid} {currency} {amount}")
|
self.log.info(
|
||||||
self.irc.sendmsg(f"Failed to get reference by amount and currency: {txid} {currency} {amount}")
|
f"Failed to get reference by amount and currency: {txid} {currency} {amount}"
|
||||||
self.ux.notify.notify_tx_lookup_failed(currency, amount, reference, "ALT_LOOKUP_FAILED")
|
)
|
||||||
|
self.irc.sendmsg(
|
||||||
|
f"Failed to get reference by amount and currency: {txid} {currency} {amount}"
|
||||||
|
)
|
||||||
|
self.ux.notify.notify_tx_lookup_failed(
|
||||||
|
currency, amount, reference, "ALT_LOOKUP_FAILED"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
stored_trade["amount"] = float(stored_trade["amount"]) # convert to float
|
stored_trade["amount"] = float(stored_trade["amount"]) # convert to float
|
||||||
return stored_trade
|
return stored_trade
|
||||||
|
@ -136,15 +148,21 @@ class Transactions(util.Base):
|
||||||
if not stored_trade:
|
if not stored_trade:
|
||||||
self.log.info(f"No reference in DB for {reference}")
|
self.log.info(f"No reference in DB for {reference}")
|
||||||
self.irc.sendmsg(f"No reference in DB for {reference}")
|
self.irc.sendmsg(f"No reference in DB for {reference}")
|
||||||
self.ux.notify.notify_tx_lookup_failed(currency, amount, reference, "NOREF", stored_trade_reference)
|
self.ux.notify.notify_tx_lookup_failed(
|
||||||
|
currency, amount, reference, "NOREF", stored_trade_reference
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
stored_trade["amount"] = float(stored_trade["amount"]) # convert to float
|
stored_trade["amount"] = float(stored_trade["amount"]) # convert to float
|
||||||
return stored_trade
|
return stored_trade
|
||||||
|
|
||||||
def currency_check(self, currency, amount, reference, stored_trade):
|
def currency_check(self, currency, amount, reference, stored_trade):
|
||||||
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(
|
||||||
self.irc.sendmsg(f"Currency mismatch, Agora: {stored_trade['currency']} / Sink: {currency}")
|
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(
|
self.ux.notify.notify_tx_lookup_failed(
|
||||||
currency,
|
currency,
|
||||||
amount,
|
amount,
|
||||||
|
@ -157,9 +175,15 @@ class Transactions(util.Base):
|
||||||
|
|
||||||
def alt_amount_check(self, platform, amount, currency, reference, stored_trade):
|
def alt_amount_check(self, platform, amount, currency, reference, stored_trade):
|
||||||
# If the amount does not match exactly, get the min and max values for our given acceptable margins for trades
|
# If the amount does not match exactly, get the min and max values for our given acceptable margins for trades
|
||||||
min_amount, max_amount = self.money.get_acceptable_margins(platform, currency, stored_trade["amount"])
|
min_amount, max_amount = self.money.get_acceptable_margins(
|
||||||
self.log.info(f"Amount does not match exactly, trying with margins: min: {min_amount} / max: {max_amount}")
|
platform, currency, stored_trade["amount"]
|
||||||
self.irc.sendmsg(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}"
|
||||||
|
)
|
||||||
if not min_amount < amount < max_amount:
|
if not min_amount < amount < max_amount:
|
||||||
self.log.info(
|
self.log.info(
|
||||||
"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}"
|
||||||
|
@ -209,9 +233,13 @@ class Transactions(util.Base):
|
||||||
db.r.hmset(f"tx.{txid}", to_store)
|
db.r.hmset(f"tx.{txid}", to_store)
|
||||||
|
|
||||||
self.log.info(f"Transaction processed: {dumps(to_store, indent=2)}")
|
self.log.info(f"Transaction processed: {dumps(to_store, indent=2)}")
|
||||||
self.irc.sendmsg(f"AUTO Incoming transaction on {subclass}: {txid} {amount}{currency} ({reference})")
|
self.irc.sendmsg(
|
||||||
|
f"AUTO Incoming transaction on {subclass}: {txid} {amount}{currency} ({reference})"
|
||||||
|
)
|
||||||
|
|
||||||
stored_trade_reference = self.reference_partial_check(reference, txid, currency, amount)
|
stored_trade_reference = self.reference_partial_check(
|
||||||
|
reference, txid, currency, amount
|
||||||
|
)
|
||||||
if stored_trade_reference is False: # can be None though
|
if stored_trade_reference is False: # can be None though
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -220,14 +248,18 @@ class Transactions(util.Base):
|
||||||
|
|
||||||
# Normal implementation for when we have a reference
|
# Normal implementation for when we have a reference
|
||||||
if stored_trade_reference:
|
if stored_trade_reference:
|
||||||
stored_trade = self.normal_lookup(stored_trade_reference, reference, currency, amount)
|
stored_trade = self.normal_lookup(
|
||||||
|
stored_trade_reference, reference, currency, amount
|
||||||
|
)
|
||||||
# if not stored_trade:
|
# if not stored_trade:
|
||||||
# return
|
# return
|
||||||
|
|
||||||
# Amount/currency lookup implementation for when we have no reference
|
# Amount/currency lookup implementation for when we have no reference
|
||||||
else:
|
else:
|
||||||
if not stored_trade: # check we don't overwrite the lookup above
|
if not stored_trade: # check we don't overwrite the lookup above
|
||||||
stored_trade = self.amount_currency_lookup(amount, currency, txid, reference)
|
stored_trade = self.amount_currency_lookup(
|
||||||
|
amount, currency, txid, reference
|
||||||
|
)
|
||||||
if stored_trade is False:
|
if stored_trade is False:
|
||||||
return
|
return
|
||||||
if stored_trade:
|
if stored_trade:
|
||||||
|
@ -249,13 +281,17 @@ class Transactions(util.Base):
|
||||||
if looked_up_without_reference:
|
if looked_up_without_reference:
|
||||||
return
|
return
|
||||||
platform = stored_trade["subclass"]
|
platform = stored_trade["subclass"]
|
||||||
if not self.alt_amount_check(platform, amount, currency, reference, stored_trade):
|
if not self.alt_amount_check(
|
||||||
|
platform, amount, currency, reference, stored_trade
|
||||||
|
):
|
||||||
return
|
return
|
||||||
platform = stored_trade["subclass"]
|
platform = stored_trade["subclass"]
|
||||||
platform_buyer = stored_trade["buyer"]
|
platform_buyer = stored_trade["buyer"]
|
||||||
|
|
||||||
# Check sender - we don't do anything with this yet
|
# Check sender - we don't do anything with this yet
|
||||||
sender_valid = self.antifraud.check_valid_sender(reference, platform, sender, platform_buyer)
|
sender_valid = self.antifraud.check_valid_sender(
|
||||||
|
reference, platform, sender, platform_buyer
|
||||||
|
)
|
||||||
self.log.info(f"Trade {reference} buyer {platform_buyer} valid: {sender_valid}")
|
self.log.info(f"Trade {reference} buyer {platform_buyer} valid: {sender_valid}")
|
||||||
# trade_released = self.release_map_trade(reference, txid)
|
# trade_released = self.release_map_trade(reference, txid)
|
||||||
# if trade_released:
|
# if trade_released:
|
||||||
|
@ -325,7 +361,9 @@ class Transactions(util.Base):
|
||||||
return True
|
return True
|
||||||
elif is_updated is False:
|
elif is_updated is False:
|
||||||
# Already mapped
|
# Already mapped
|
||||||
self.log.error(f"Trade {reference} already has a TX mapped, cannot map {tx}.")
|
self.log.error(
|
||||||
|
f"Trade {reference} already has a TX mapped, cannot map {tx}."
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def new_trade(
|
def new_trade(
|
||||||
|
@ -396,9 +434,13 @@ class Transactions(util.Base):
|
||||||
# TODO: use get_ref_map in this function instead of calling get_ref multiple times
|
# TODO: use get_ref_map in this function instead of calling get_ref multiple times
|
||||||
for ref in refs:
|
for ref in refs:
|
||||||
stored_trade = db.get_ref(ref)
|
stored_trade = db.get_ref(ref)
|
||||||
if stored_trade["currency"] == currency and float(stored_trade["amount"]) == float(amount):
|
if stored_trade["currency"] == currency and float(
|
||||||
|
stored_trade["amount"]
|
||||||
|
) == float(amount):
|
||||||
matching_refs.append(stored_trade)
|
matching_refs.append(stored_trade)
|
||||||
if len(matching_refs) != 1:
|
if len(matching_refs) != 1:
|
||||||
self.log.error(f"Find trade returned multiple results for TXID {txid}: {matching_refs}")
|
self.log.error(
|
||||||
|
f"Find trade returned multiple results for TXID {txid}: {matching_refs}"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
return matching_refs[0]
|
return matching_refs[0]
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
# import requests
|
# import requests
|
||||||
# from json import dumps
|
# from json import dumps
|
||||||
|
|
||||||
# Project imports
|
|
||||||
from settings import settings
|
|
||||||
import sinks.nordigen
|
import sinks.nordigen
|
||||||
import sinks.truelayer
|
import sinks.truelayer
|
||||||
import util
|
import util
|
||||||
from db import r
|
from db import r
|
||||||
|
# Project imports
|
||||||
|
from settings import settings
|
||||||
|
|
||||||
|
|
||||||
class Sinks(util.Base):
|
class Sinks(util.Base):
|
||||||
|
@ -54,7 +54,9 @@ class Sinks(util.Base):
|
||||||
|
|
||||||
difference = util.convert(difference)
|
difference = util.convert(difference)
|
||||||
|
|
||||||
new_transactions = [x for x in transactions if x["transaction_id"] in difference]
|
new_transactions = [
|
||||||
|
x for x in transactions if x["transaction_id"] in difference
|
||||||
|
]
|
||||||
|
|
||||||
# Rename the new key to the old key so we can run the diff again
|
# Rename the new key to the old key so we can run the diff again
|
||||||
r.rename(new_key_name, old_key_name)
|
r.rename(new_key_name, old_key_name)
|
||||||
|
@ -79,12 +81,18 @@ class Sinks(util.Base):
|
||||||
fields = ["sort_code", "number", "iban"]
|
fields = ["sort_code", "number", "iban"]
|
||||||
for field in fields:
|
for field in fields:
|
||||||
if field in account:
|
if field in account:
|
||||||
account_infos[bank][index]["account_number"][field] = account[field]
|
account_infos[bank][index]["account_number"][
|
||||||
|
field
|
||||||
|
] = account[field]
|
||||||
del account_infos[bank][index][field]
|
del account_infos[bank][index][field]
|
||||||
if len(account["account_number"]) == 1:
|
if len(account["account_number"]) == 1:
|
||||||
account_infos[bank].remove(account)
|
account_infos[bank].remove(account)
|
||||||
self.log.warning(f"Potentially useless bank account: {account}")
|
self.log.warning(f"Potentially useless bank account: {account}")
|
||||||
currencies = [account["currency"] for bank, accounts in account_infos.items() for account in accounts]
|
currencies = [
|
||||||
|
account["currency"]
|
||||||
|
for bank, accounts in account_infos.items()
|
||||||
|
for account in accounts
|
||||||
|
]
|
||||||
for bank, accounts in account_infos.items():
|
for bank, accounts in account_infos.items():
|
||||||
self.account_info[bank] = []
|
self.account_info[bank] = []
|
||||||
for account in accounts:
|
for account in accounts:
|
||||||
|
|
|
@ -1,28 +1,20 @@
|
||||||
# Twisted/Klein imports
|
# Twisted/Klein imports
|
||||||
from twisted.internet.task import LoopingCall
|
from hashlib import sha256
|
||||||
from twisted.internet.defer import inlineCallbacks
|
from json import dumps, loads
|
||||||
|
|
||||||
# Other library imports
|
# Other library imports
|
||||||
import requests
|
import requests
|
||||||
from simplejson.errors import JSONDecodeError
|
|
||||||
from json import dumps, loads
|
|
||||||
from lib.serde.nordigen import (
|
|
||||||
TXRoot,
|
|
||||||
AccessToken,
|
|
||||||
Institutions,
|
|
||||||
Agreement,
|
|
||||||
Requisitions,
|
|
||||||
AccountDetails,
|
|
||||||
AccountBalancesRoot,
|
|
||||||
RequisitionResponse,
|
|
||||||
)
|
|
||||||
from serde import ValidationError
|
|
||||||
from hashlib import sha256
|
|
||||||
import treq
|
import treq
|
||||||
|
import util
|
||||||
|
from lib.serde.nordigen import (AccessToken, AccountBalancesRoot,
|
||||||
|
AccountDetails, Agreement, Institutions,
|
||||||
|
RequisitionResponse, Requisitions, TXRoot)
|
||||||
|
from serde import ValidationError
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
import util
|
from simplejson.errors import JSONDecodeError
|
||||||
|
from twisted.internet.defer import inlineCallbacks
|
||||||
|
from twisted.internet.task import LoopingCall
|
||||||
|
|
||||||
|
|
||||||
class Nordigen(util.Base):
|
class Nordigen(util.Base):
|
||||||
|
@ -296,7 +288,9 @@ class Nordigen(util.Base):
|
||||||
ownernames = self.get_ownernames()
|
ownernames = self.get_ownernames()
|
||||||
if account_id in ownernames:
|
if account_id in ownernames:
|
||||||
parsed["ownerName"] = ownernames[account_id]
|
parsed["ownerName"] = ownernames[account_id]
|
||||||
self.log.info(f"Found supplementary owner name for {account_id}: {ownernames[account_id]}")
|
self.log.info(
|
||||||
|
f"Found supplementary owner name for {account_id}: {ownernames[account_id]}"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.log.error(f"No owner name in parsed, cannot use: {account_id}")
|
self.log.error(f"No owner name in parsed, cannot use: {account_id}")
|
||||||
return False
|
return False
|
||||||
|
@ -387,7 +381,9 @@ class Nordigen(util.Base):
|
||||||
else:
|
else:
|
||||||
# No transaction ID. This is a problem for our implementation
|
# No transaction ID. This is a problem for our implementation
|
||||||
|
|
||||||
tx_hash = sha256(dumps(transaction, sort_keys=True).encode("utf8")).hexdigest()
|
tx_hash = sha256(
|
||||||
|
dumps(transaction, sort_keys=True).encode("utf8")
|
||||||
|
).hexdigest()
|
||||||
transaction["transaction_id"] = tx_hash
|
transaction["transaction_id"] = tx_hash
|
||||||
|
|
||||||
# Rename timestamp
|
# Rename timestamp
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
# Twisted/Klein imports
|
# Twisted/Klein imports
|
||||||
from twisted.internet.task import LoopingCall
|
import urllib
|
||||||
|
from json import dumps, loads
|
||||||
|
from time import time
|
||||||
|
|
||||||
# Other library imports
|
# Other library imports
|
||||||
import requests
|
import requests
|
||||||
from simplejson.errors import JSONDecodeError
|
import util
|
||||||
from time import time
|
|
||||||
from json import dumps, loads
|
|
||||||
from lib.serde.truelayer import AccountBalancesRoot
|
from lib.serde.truelayer import AccountBalancesRoot
|
||||||
import urllib
|
|
||||||
from serde import ValidationError
|
from serde import ValidationError
|
||||||
|
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
import util
|
from simplejson.errors import JSONDecodeError
|
||||||
|
from twisted.internet.task import LoopingCall
|
||||||
|
|
||||||
|
|
||||||
class TrueLayer(util.Base):
|
class TrueLayer(util.Base):
|
||||||
|
@ -130,7 +129,9 @@ class TrueLayer(util.Base):
|
||||||
else:
|
else:
|
||||||
self.log.error("Received an authcode we didn't ask for")
|
self.log.error("Received an authcode we didn't ask for")
|
||||||
return
|
return
|
||||||
self.log.info(f"Retrieved access/refresh tokens for {self.current_authcode_bank}")
|
self.log.info(
|
||||||
|
f"Retrieved access/refresh tokens for {self.current_authcode_bank}"
|
||||||
|
)
|
||||||
|
|
||||||
def get_new_tokens_all(self):
|
def get_new_tokens_all(self):
|
||||||
refresh_tokens = loads(settings.TrueLayer.RefreshKeys)
|
refresh_tokens = loads(settings.TrueLayer.RefreshKeys)
|
||||||
|
@ -174,7 +175,10 @@ class TrueLayer(util.Base):
|
||||||
if "access_token" in parsed.keys():
|
if "access_token" in parsed.keys():
|
||||||
self.tokens[bank] = parsed["access_token"]
|
self.tokens[bank] = parsed["access_token"]
|
||||||
# self.log.info(f"Refreshed access token for {bank}")
|
# self.log.info(f"Refreshed access token for {bank}")
|
||||||
if len(self.refresh_tokens.keys()) == len(self.tokens.keys()) and not self.authed:
|
if (
|
||||||
|
len(self.refresh_tokens.keys()) == len(self.tokens.keys())
|
||||||
|
and not self.authed
|
||||||
|
):
|
||||||
# We are now fully authenticated and ready to start loops!
|
# We are now fully authenticated and ready to start loops!
|
||||||
self.__authed__()
|
self.__authed__()
|
||||||
self.authed = True
|
self.authed = True
|
||||||
|
@ -197,7 +201,9 @@ class TrueLayer(util.Base):
|
||||||
try:
|
try:
|
||||||
parsed = r.json()
|
parsed = r.json()
|
||||||
except JSONDecodeError:
|
except JSONDecodeError:
|
||||||
self.log.error("Error parsing accounts response: {content}", content=r.content)
|
self.log.error(
|
||||||
|
"Error parsing accounts response: {content}", content=r.content
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return parsed
|
return parsed
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
# Project imports
|
# Project imports
|
||||||
# from settings import settings
|
# from settings import settings
|
||||||
import util
|
|
||||||
import sources.agora
|
import sources.agora
|
||||||
|
|
||||||
import sources.localbitcoins
|
import sources.localbitcoins
|
||||||
|
import util
|
||||||
|
|
||||||
|
|
||||||
class Sources(util.Base):
|
class Sources(util.Base):
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
# Twisted/Klein imports
|
# Twisted/Klein imports
|
||||||
from twisted.internet.defer import inlineCallbacks
|
import sources.local
|
||||||
|
|
||||||
# Other library imports
|
# Other library imports
|
||||||
from pyotp import TOTP
|
from pyotp import TOTP
|
||||||
|
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
import sources.local
|
from twisted.internet.defer import inlineCallbacks
|
||||||
|
|
||||||
|
|
||||||
class Agora(sources.local.Local):
|
class Agora(sources.local.Local):
|
||||||
|
@ -42,7 +40,9 @@ class Agora(sources.local.Local):
|
||||||
"""
|
"""
|
||||||
print("CALLING RELEASE FUNDS", contact_id)
|
print("CALLING RELEASE FUNDS", contact_id)
|
||||||
if self.sets.Dummy == "1":
|
if self.sets.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": self.sets.Pass}
|
payload = {"tradeId": contact_id, "password": self.sets.Pass}
|
||||||
rtrn = yield self.api._api_call(
|
rtrn = yield self.api._api_call(
|
||||||
|
@ -90,8 +90,12 @@ class Agora(sources.local.Local):
|
||||||
|
|
||||||
if not float(wallet_xmr) > profit_usd_in_xmr:
|
if not float(wallet_xmr) > profit_usd_in_xmr:
|
||||||
# Not enough funds to withdraw
|
# Not enough funds to withdraw
|
||||||
self.log.error(f"Not enough funds to withdraw {profit_usd_in_xmr}, as wallet only contains {wallet_xmr}")
|
self.log.error(
|
||||||
self.irc.sendmsg(f"Not enough funds to withdraw {profit_usd_in_xmr}, as wallet only contains {wallet_xmr}")
|
f"Not enough funds to withdraw {profit_usd_in_xmr}, as wallet only contains {wallet_xmr}"
|
||||||
|
)
|
||||||
|
self.irc.sendmsg(
|
||||||
|
f"Not enough funds to withdraw {profit_usd_in_xmr}, as wallet only contains {wallet_xmr}"
|
||||||
|
)
|
||||||
self.ux.notify.notify_need_topup(profit_usd_in_xmr)
|
self.ux.notify.notify_need_topup(profit_usd_in_xmr)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
# Twisted/Klein imports
|
# Twisted/Klein imports
|
||||||
from twisted.internet.task import LoopingCall
|
from datetime import datetime
|
||||||
from twisted.internet.defer import inlineCallbacks
|
|
||||||
|
|
||||||
# Other library imports
|
# Other library imports
|
||||||
from json import loads
|
from json import loads
|
||||||
from datetime import datetime
|
|
||||||
from time import sleep # TODO: async
|
from time import sleep # TODO: async
|
||||||
|
|
||||||
|
import db
|
||||||
# Project imports
|
|
||||||
from settings import settings
|
|
||||||
import util
|
import util
|
||||||
from lib.agoradesk_py import AgoraDesk
|
from lib.agoradesk_py import AgoraDesk
|
||||||
from lib.localbitcoins_py import LocalBitcoins
|
from lib.localbitcoins_py import LocalBitcoins
|
||||||
import db
|
|
||||||
from lib.logstash import send_logstash
|
from lib.logstash import send_logstash
|
||||||
|
# Project imports
|
||||||
|
from settings import settings
|
||||||
|
from twisted.internet.defer import inlineCallbacks
|
||||||
|
from twisted.internet.task import LoopingCall
|
||||||
|
|
||||||
|
|
||||||
class Local(util.Base):
|
class Local(util.Base):
|
||||||
|
@ -28,7 +26,9 @@ class Local(util.Base):
|
||||||
self.api = AgoraDesk(settings.Agora.Token)
|
self.api = AgoraDesk(settings.Agora.Token)
|
||||||
self.sets = settings.Agora
|
self.sets = settings.Agora
|
||||||
elif self.platform == "lbtc":
|
elif self.platform == "lbtc":
|
||||||
self.api = LocalBitcoins(settings.LocalBitcoins.Token, settings.LocalBitcoins.Secret)
|
self.api = LocalBitcoins(
|
||||||
|
settings.LocalBitcoins.Token, settings.LocalBitcoins.Secret
|
||||||
|
)
|
||||||
self.sets = settings.LocalBitcoins
|
self.sets = settings.LocalBitcoins
|
||||||
else:
|
else:
|
||||||
self.log.error("Platform not defined.")
|
self.log.error("Platform not defined.")
|
||||||
|
@ -49,7 +49,9 @@ class Local(util.Base):
|
||||||
provider_map = {"NATIONAL_BANK": "national-bank-transfer"}
|
provider_map = {"NATIONAL_BANK": "national-bank-transfer"}
|
||||||
if reverse:
|
if reverse:
|
||||||
try:
|
try:
|
||||||
return next(key for key, value in provider_map.items() if value == provider)
|
return next(
|
||||||
|
key for key, value in provider_map.items() if value == provider
|
||||||
|
)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
|
@ -221,13 +223,17 @@ class Local(util.Base):
|
||||||
for user, message in messages_tmp[reference][::-1]:
|
for user, message in messages_tmp[reference][::-1]:
|
||||||
if reference in self.last_messages:
|
if reference in self.last_messages:
|
||||||
if not [user, message] in self.last_messages[reference]:
|
if not [user, message] in self.last_messages[reference]:
|
||||||
self.irc.sendmsg(f"[{reference}] ({self.platform}) <{user}> {message}")
|
self.irc.sendmsg(
|
||||||
|
f"[{reference}] ({self.platform}) <{user}> {message}"
|
||||||
|
)
|
||||||
# Append sent messages to last_messages so we don't send them again
|
# Append sent messages to last_messages so we don't send them again
|
||||||
self.last_messages[reference].append([user, message])
|
self.last_messages[reference].append([user, message])
|
||||||
else:
|
else:
|
||||||
self.last_messages[reference] = [[user, message]]
|
self.last_messages[reference] = [[user, message]]
|
||||||
for x in messages_tmp[reference]:
|
for x in messages_tmp[reference]:
|
||||||
self.irc.sendmsg(f"[{reference}] ({self.platform}) <{user}> {message}")
|
self.irc.sendmsg(
|
||||||
|
f"[{reference}] ({self.platform}) <{user}> {message}"
|
||||||
|
)
|
||||||
|
|
||||||
# Purge old trades from cache
|
# Purge old trades from cache
|
||||||
for ref in list(self.last_messages): # We're removing from the list on the fly
|
for ref in list(self.last_messages): # We're removing from the list on the fly
|
||||||
|
@ -419,10 +425,14 @@ class Local(util.Base):
|
||||||
if not providers:
|
if not providers:
|
||||||
providers = self.markets.get_all_providers(self.platform)
|
providers = self.markets.get_all_providers(self.platform)
|
||||||
sinks_currencies = self.sinks.currencies
|
sinks_currencies = self.sinks.currencies
|
||||||
supported_currencies = [currency for currency in currencies if currency in sinks_currencies]
|
supported_currencies = [
|
||||||
|
currency for currency in currencies if currency in sinks_currencies
|
||||||
|
]
|
||||||
currencies = supported_currencies
|
currencies = supported_currencies
|
||||||
# We want to get the ads for each of these currencies and return the result
|
# We want to get the ads for each of these currencies and return the result
|
||||||
rates = self.money.cg.get_price(ids=["monero", "bitcoin"], vs_currencies=currencies)
|
rates = self.money.cg.get_price(
|
||||||
|
ids=["monero", "bitcoin"], vs_currencies=currencies
|
||||||
|
)
|
||||||
for asset in assets:
|
for asset in assets:
|
||||||
for currency in currencies:
|
for currency in currencies:
|
||||||
cg_asset_name = crypto_map[asset]
|
cg_asset_name = crypto_map[asset]
|
||||||
|
@ -493,7 +503,9 @@ class Local(util.Base):
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
if "error_code" not in rtrn["response"]["error"]:
|
if "error_code" not in rtrn["response"]["error"]:
|
||||||
self.log.error(f"Error code not in return for ad {ad_id}: {rtrn['response']}")
|
self.log.error(
|
||||||
|
f"Error code not in return for ad {ad_id}: {rtrn['response']}"
|
||||||
|
)
|
||||||
return
|
return
|
||||||
if rtrn["response"]["error"]["error_code"] == 429:
|
if rtrn["response"]["error"]["error_code"] == 429:
|
||||||
throttled += 1
|
throttled += 1
|
||||||
|
@ -551,14 +563,20 @@ class Local(util.Base):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if payment_details:
|
if payment_details:
|
||||||
payment_details_text = self.markets.format_payment_details(currency, payment_details)
|
payment_details_text = self.markets.format_payment_details(
|
||||||
|
currency, payment_details
|
||||||
|
)
|
||||||
ad_text = self.markets.format_ad(asset, currency, payment_details_text)
|
ad_text = self.markets.format_ad(asset, currency, payment_details_text)
|
||||||
min_amount, max_amount = self.money.get_minmax(self.platform, asset, currency)
|
min_amount, max_amount = self.money.get_minmax(
|
||||||
|
self.platform, asset, currency
|
||||||
|
)
|
||||||
if self.platform == "lbtc":
|
if self.platform == "lbtc":
|
||||||
bank_name = payment_details["bank"]
|
bank_name = payment_details["bank"]
|
||||||
|
|
||||||
if self.platform == "agora":
|
if self.platform == "agora":
|
||||||
price_formula = f"coingecko{asset.lower()}usd*usd{currency.lower()}*{self.sets.Margin}"
|
price_formula = (
|
||||||
|
f"coingecko{asset.lower()}usd*usd{currency.lower()}*{self.sets.Margin}"
|
||||||
|
)
|
||||||
elif self.platform == "lbtc":
|
elif self.platform == "lbtc":
|
||||||
price_formula = f"btc_in_usd*{self.sets.Margin}*USD_in_{currency}"
|
price_formula = f"btc_in_usd*{self.sets.Margin}*USD_in_{currency}"
|
||||||
|
|
||||||
|
@ -605,7 +623,9 @@ class Local(util.Base):
|
||||||
:return: False or dict with response
|
:return: False or dict with response
|
||||||
:rtype: bool or dict
|
:rtype: bool or dict
|
||||||
"""
|
"""
|
||||||
dist_list = list(self.markets.create_distribution_list(self.platform, filter_asset))
|
dist_list = list(
|
||||||
|
self.markets.create_distribution_list(self.platform, filter_asset)
|
||||||
|
)
|
||||||
our_ads = yield self.enum_ads()
|
our_ads = yield self.enum_ads()
|
||||||
(
|
(
|
||||||
supported_currencies,
|
supported_currencies,
|
||||||
|
@ -683,7 +703,10 @@ class Local(util.Base):
|
||||||
for i in range(_size):
|
for i in range(_size):
|
||||||
k = i + 1
|
k = i + 1
|
||||||
for j in range(k, _size):
|
for j in range(k, _size):
|
||||||
if existing_ads[i] == existing_ads[j] and existing_ads[i] not in repeated:
|
if (
|
||||||
|
existing_ads[i] == existing_ads[j]
|
||||||
|
and existing_ads[i] not in repeated
|
||||||
|
):
|
||||||
repeated.append(existing_ads[i])
|
repeated.append(existing_ads[i])
|
||||||
|
|
||||||
actioned = []
|
actioned = []
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
# Other library imports
|
# Other library imports
|
||||||
|
import sources.local
|
||||||
|
import util
|
||||||
from pyotp import TOTP
|
from pyotp import TOTP
|
||||||
|
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
import util
|
|
||||||
import sources.local
|
|
||||||
|
|
||||||
|
|
||||||
class LBTC(sources.local.Local):
|
class LBTC(sources.local.Local):
|
||||||
|
@ -39,7 +38,9 @@ class LBTC(sources.local.Local):
|
||||||
:rtype: dict
|
:rtype: dict
|
||||||
"""
|
"""
|
||||||
if self.sets.Dummy == "1":
|
if self.sets.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 = {
|
payload = {
|
||||||
"tradeId": contact_id,
|
"tradeId": contact_id,
|
||||||
|
@ -89,8 +90,12 @@ class LBTC(sources.local.Local):
|
||||||
|
|
||||||
if not float(wallet_xmr) > profit_usd_in_xmr:
|
if not float(wallet_xmr) > profit_usd_in_xmr:
|
||||||
# Not enough funds to withdraw
|
# Not enough funds to withdraw
|
||||||
self.log.error(f"Not enough funds to withdraw {profit_usd_in_xmr}, as wallet only contains {wallet_xmr}")
|
self.log.error(
|
||||||
self.irc.sendmsg(f"Not enough funds to withdraw {profit_usd_in_xmr}, as wallet only contains {wallet_xmr}")
|
f"Not enough funds to withdraw {profit_usd_in_xmr}, as wallet only contains {wallet_xmr}"
|
||||||
|
)
|
||||||
|
self.irc.sendmsg(
|
||||||
|
f"Not enough funds to withdraw {profit_usd_in_xmr}, as wallet only contains {wallet_xmr}"
|
||||||
|
)
|
||||||
self.ux.notify.notify_need_topup(profit_usd_in_xmr)
|
self.ux.notify.notify_need_topup(profit_usd_in_xmr)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,17 +1,16 @@
|
||||||
|
import logging
|
||||||
|
from copy import deepcopy
|
||||||
|
from json import loads
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from twisted.internet.defer import inlineCallbacks
|
|
||||||
from json import loads
|
|
||||||
from copy import deepcopy
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from tests.common import fake_public_ads, cg_prices, expected_to_update
|
|
||||||
import sources.agora
|
|
||||||
import lib.markets
|
import lib.markets
|
||||||
import lib.money
|
import lib.money
|
||||||
import util
|
|
||||||
import settings
|
import settings
|
||||||
|
import sources.agora
|
||||||
|
import util
|
||||||
|
from tests.common import cg_prices, expected_to_update, fake_public_ads
|
||||||
|
from twisted.internet.defer import inlineCallbacks
|
||||||
|
|
||||||
|
|
||||||
class TestAgora(TestCase):
|
class TestAgora(TestCase):
|
||||||
|
@ -20,7 +19,9 @@ class TestAgora(TestCase):
|
||||||
with open("tests/data/agora_ads.json", "r") as f:
|
with open("tests/data/agora_ads.json", "r") as f:
|
||||||
for line in f.readlines():
|
for line in f.readlines():
|
||||||
parsed = loads(line)
|
parsed = loads(line)
|
||||||
self.test_return_data[(parsed[2], parsed[1], str(parsed[0]))] = parsed[3]
|
self.test_return_data[(parsed[2], parsed[1], str(parsed[0]))] = parsed[
|
||||||
|
3
|
||||||
|
]
|
||||||
|
|
||||||
super().__init__(*args, *kwargs)
|
super().__init__(*args, *kwargs)
|
||||||
|
|
||||||
|
@ -181,10 +182,14 @@ class TestAgora(TestCase):
|
||||||
util.last_online_recent = MagicMock()
|
util.last_online_recent = MagicMock()
|
||||||
util.last_online_recent.return_value = True
|
util.last_online_recent.return_value = True
|
||||||
|
|
||||||
enum_ads_return = yield self.agora.enum_public_ads("XMR", "USD", self.all_providers)
|
enum_ads_return = yield self.agora.enum_public_ads(
|
||||||
|
"XMR", "USD", self.all_providers
|
||||||
|
)
|
||||||
|
|
||||||
# Ensure there are no duplicates
|
# Ensure there are no duplicates
|
||||||
enum_ads_return_ids = [(x[0], x[1], x[2], x[3], x[4], x[5]) for x in enum_ads_return]
|
enum_ads_return_ids = [
|
||||||
|
(x[0], x[1], x[2], x[3], x[4], x[5]) for x in enum_ads_return
|
||||||
|
]
|
||||||
enum_ads_return_ids_dedup = set(enum_ads_return_ids)
|
enum_ads_return_ids_dedup = set(enum_ads_return_ids)
|
||||||
self.assertEqual(len(enum_ads_return_ids), len(enum_ads_return_ids_dedup))
|
self.assertEqual(len(enum_ads_return_ids), len(enum_ads_return_ids_dedup))
|
||||||
|
|
||||||
|
@ -243,7 +248,9 @@ class TestAgora(TestCase):
|
||||||
ad.append(margin)
|
ad.append(margin)
|
||||||
expected_return.append(ad)
|
expected_return.append(ad)
|
||||||
|
|
||||||
lookup_rates_return = self.agora.money.lookup_rates("agora", enum_ads_return) # TODO: do this properly
|
lookup_rates_return = self.agora.money.lookup_rates(
|
||||||
|
"agora", enum_ads_return
|
||||||
|
) # TODO: do this properly
|
||||||
self.assertCountEqual(lookup_rates_return, expected_return)
|
self.assertCountEqual(lookup_rates_return, expected_return)
|
||||||
|
|
||||||
def test_lookup_rates_not_usd(self):
|
def test_lookup_rates_not_usd(self):
|
||||||
|
@ -271,5 +278,7 @@ class TestAgora(TestCase):
|
||||||
ad.append(margin)
|
ad.append(margin)
|
||||||
expected_return.append(ad)
|
expected_return.append(ad)
|
||||||
# Test specifying rates=
|
# Test specifying rates=
|
||||||
lookup_rates_return = self.agora.money.lookup_rates("agora", enum_ads_return, rates=cg_prices)
|
lookup_rates_return = self.agora.money.lookup_rates(
|
||||||
|
"agora", enum_ads_return, rates=cg_prices
|
||||||
|
)
|
||||||
self.assertCountEqual(lookup_rates_return, expected_return)
|
self.assertCountEqual(lookup_rates_return, expected_return)
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
|
import logging
|
||||||
|
from copy import deepcopy
|
||||||
|
from json import loads
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from twisted.internet.defer import inlineCallbacks
|
|
||||||
from json import loads
|
|
||||||
from copy import deepcopy
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from tests.common import fake_public_ads_lbtc, cg_prices, expected_to_update_lbtc
|
|
||||||
import sources.localbitcoins
|
|
||||||
import lib.markets
|
import lib.markets
|
||||||
import lib.money
|
import lib.money
|
||||||
import util
|
|
||||||
import settings
|
import settings
|
||||||
import sources
|
import sources
|
||||||
|
import sources.localbitcoins
|
||||||
|
import util
|
||||||
|
from tests.common import (cg_prices, expected_to_update_lbtc,
|
||||||
|
fake_public_ads_lbtc)
|
||||||
|
from twisted.internet.defer import inlineCallbacks
|
||||||
|
|
||||||
|
|
||||||
class TestLBTC(TestCase):
|
class TestLBTC(TestCase):
|
||||||
|
@ -21,7 +21,9 @@ class TestLBTC(TestCase):
|
||||||
with open("tests/data/lbtc_ads.json", "r") as f:
|
with open("tests/data/lbtc_ads.json", "r") as f:
|
||||||
for line in f.readlines():
|
for line in f.readlines():
|
||||||
parsed = loads(line)
|
parsed = loads(line)
|
||||||
self.test_return_data[(parsed[2], parsed[1], str(parsed[0]))] = parsed[3]
|
self.test_return_data[(parsed[2], parsed[1], str(parsed[0]))] = parsed[
|
||||||
|
3
|
||||||
|
]
|
||||||
|
|
||||||
super().__init__(*args, *kwargs)
|
super().__init__(*args, *kwargs)
|
||||||
|
|
||||||
|
@ -126,10 +128,14 @@ class TestLBTC(TestCase):
|
||||||
util.last_online_recent = MagicMock()
|
util.last_online_recent = MagicMock()
|
||||||
util.last_online_recent.return_value = True
|
util.last_online_recent.return_value = True
|
||||||
|
|
||||||
enum_ads_return = yield self.lbtc.enum_public_ads("BTC", "GBP", self.all_providers)
|
enum_ads_return = yield self.lbtc.enum_public_ads(
|
||||||
|
"BTC", "GBP", self.all_providers
|
||||||
|
)
|
||||||
|
|
||||||
# Ensure there are no duplicates
|
# Ensure there are no duplicates
|
||||||
enum_ads_return_ids = [(x[0], x[1], x[2], x[3], x[4], x[5]) for x in enum_ads_return]
|
enum_ads_return_ids = [
|
||||||
|
(x[0], x[1], x[2], x[3], x[4], x[5]) for x in enum_ads_return
|
||||||
|
]
|
||||||
enum_ads_return_ids_dedup = set(enum_ads_return_ids)
|
enum_ads_return_ids_dedup = set(enum_ads_return_ids)
|
||||||
self.assertEqual(len(enum_ads_return_ids), len(enum_ads_return_ids_dedup))
|
self.assertEqual(len(enum_ads_return_ids), len(enum_ads_return_ids_dedup))
|
||||||
|
|
||||||
|
@ -187,7 +193,9 @@ class TestLBTC(TestCase):
|
||||||
ad.append(margin)
|
ad.append(margin)
|
||||||
expected_return.append(ad)
|
expected_return.append(ad)
|
||||||
|
|
||||||
lookup_rates_return = self.lbtc.money.lookup_rates("lbtc", enum_ads_return) # TODO: do this properly
|
lookup_rates_return = self.lbtc.money.lookup_rates(
|
||||||
|
"lbtc", enum_ads_return
|
||||||
|
) # TODO: do this properly
|
||||||
self.assertCountEqual(lookup_rates_return, expected_return)
|
self.assertCountEqual(lookup_rates_return, expected_return)
|
||||||
|
|
||||||
def test_lookup_rates_not_usd(self):
|
def test_lookup_rates_not_usd(self):
|
||||||
|
@ -215,5 +223,7 @@ class TestLBTC(TestCase):
|
||||||
ad.append(margin)
|
ad.append(margin)
|
||||||
expected_return.append(ad)
|
expected_return.append(ad)
|
||||||
# Test specifying rates=
|
# Test specifying rates=
|
||||||
lookup_rates_return = self.lbtc.money.lookup_rates("lbtc", enum_ads_return, rates=cg_prices)
|
lookup_rates_return = self.lbtc.money.lookup_rates(
|
||||||
|
"lbtc", enum_ads_return, rates=cg_prices
|
||||||
|
)
|
||||||
self.assertCountEqual(lookup_rates_return, expected_return)
|
self.assertCountEqual(lookup_rates_return, expected_return)
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
import logging
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
from tests.common import fake_public_ads, expected_to_update
|
|
||||||
import lib.markets
|
import lib.markets
|
||||||
from sources.agora import Agora
|
|
||||||
import settings
|
import settings
|
||||||
import logging
|
from sources.agora import Agora
|
||||||
|
from tests.common import expected_to_update, fake_public_ads
|
||||||
|
|
||||||
|
|
||||||
class TestMarkets(TestCase):
|
class TestMarkets(TestCase):
|
||||||
|
@ -105,7 +106,9 @@ class TestMarkets(TestCase):
|
||||||
expected_btc_to_update = [x for x in expected_to_update if x[2] == "BTC"]
|
expected_btc_to_update = [x for x in expected_to_update if x[2] == "BTC"]
|
||||||
self.assertCountEqual(res_btc, expected_btc_to_update)
|
self.assertCountEqual(res_btc, expected_btc_to_update)
|
||||||
|
|
||||||
res_both = self.markets.get_new_ad_equations("agora", fake_public_ads, ["XMR", "BTC"])
|
res_both = self.markets.get_new_ad_equations(
|
||||||
|
"agora", fake_public_ads, ["XMR", "BTC"]
|
||||||
|
)
|
||||||
self.assertCountEqual(res_both, expected_to_update)
|
self.assertCountEqual(res_both, expected_to_update)
|
||||||
|
|
||||||
def test_format_ad(self):
|
def test_format_ad(self):
|
||||||
|
@ -116,7 +119,9 @@ $PAYMENT$
|
||||||
"sort_code": "02-03-04",
|
"sort_code": "02-03-04",
|
||||||
"account_number": "0023-0045",
|
"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"**
|
||||||
Payment details will be released after verification has passed.
|
Payment details will be released after verification has passed.
|
||||||
|
@ -130,7 +135,9 @@ If you've already completed verification, they will be sent immediately.
|
||||||
"sort_code": "02-03-04",
|
"sort_code": "02-03-04",
|
||||||
"account_number": "0023-0045",
|
"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 = """Payment details will be released after verification has passed.
|
expected = """Payment details will be released after verification has passed.
|
||||||
If you've already completed verification, they will be sent immediately."""
|
If you've already completed verification, they will be sent immediately."""
|
||||||
|
@ -139,5 +146,7 @@ If you've already completed verification, they will be sent immediately."""
|
||||||
expected_real = """* Sort code: **02-03-04**
|
expected_real = """* Sort code: **02-03-04**
|
||||||
* Account number: **0023-0045**
|
* Account number: **0023-0045**
|
||||||
Please send in GBP."""
|
Please send in GBP."""
|
||||||
payment_details_text_real = self.markets.format_payment_details("GBP", payment_details, real=True)
|
payment_details_text_real = self.markets.format_payment_details(
|
||||||
|
"GBP", payment_details, real=True
|
||||||
|
)
|
||||||
self.assertEqual(payment_details_text_real, expected_real)
|
self.assertEqual(payment_details_text_real, expected_real)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from unittest import TestCase
|
|
||||||
import lib.money
|
|
||||||
import logging
|
import logging
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
import lib.money
|
||||||
|
|
||||||
|
|
||||||
class TestMoney(TestCase):
|
class TestMoney(TestCase):
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
|
import logging
|
||||||
|
from copy import deepcopy
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
from copy import deepcopy
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import lib.transactions
|
|
||||||
import lib.money
|
|
||||||
import lib.antifraud
|
import lib.antifraud
|
||||||
|
import lib.money
|
||||||
|
import lib.transactions
|
||||||
|
|
||||||
|
|
||||||
class TestTransactions(TestCase):
|
class TestTransactions(TestCase):
|
||||||
|
@ -57,7 +57,9 @@ class TestTransactions(TestCase):
|
||||||
self.money = lib.money.Money()
|
self.money = lib.money.Money()
|
||||||
self.money.get_rates_all = MagicMock()
|
self.money.get_rates_all = MagicMock()
|
||||||
self.money.get_rates_all.return_value = {"GBP": 0.8}
|
self.money.get_rates_all.return_value = {"GBP": 0.8}
|
||||||
self.transactions.money.get_acceptable_margins = self.money.get_acceptable_margins
|
self.transactions.money.get_acceptable_margins = (
|
||||||
|
self.money.get_acceptable_margins
|
||||||
|
)
|
||||||
|
|
||||||
self.trades = {
|
self.trades = {
|
||||||
1: {
|
1: {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Other library imports
|
# Other library imports
|
||||||
from httpx import ReadTimeout, ReadError, RemoteProtocolError
|
|
||||||
from datetime import datetime, timezone
|
|
||||||
import logging
|
import logging
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
from httpx import ReadError, ReadTimeout, RemoteProtocolError
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
|
|
||||||
|
@ -40,7 +40,9 @@ class ColoredFormatter(logging.Formatter):
|
||||||
def format(self, record):
|
def format(self, record):
|
||||||
levelname = record.levelname
|
levelname = record.levelname
|
||||||
if self.use_color and levelname in COLORS:
|
if self.use_color and levelname in COLORS:
|
||||||
levelname_color = COLOR_SEQ % (30 + COLORS[levelname]) + levelname + RESET_SEQ
|
levelname_color = (
|
||||||
|
COLOR_SEQ % (30 + COLORS[levelname]) + levelname + RESET_SEQ
|
||||||
|
)
|
||||||
record.levelname = levelname_color
|
record.levelname = levelname_color
|
||||||
return logging.Formatter.format(self, record)
|
return logging.Formatter.format(self, record)
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
# Project imports
|
# Project imports
|
||||||
# from settings import settings
|
# from settings import settings
|
||||||
import util
|
import util
|
||||||
|
|
||||||
import ux.irc
|
|
||||||
import ux.commands
|
import ux.commands
|
||||||
|
import ux.irc
|
||||||
import ux.notify
|
import ux.notify
|
||||||
import ux.verify
|
import ux.verify
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# Other library imports
|
# Other library imports
|
||||||
from json import dumps, loads
|
from json import dumps, loads
|
||||||
|
|
||||||
|
import db
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
import db
|
|
||||||
|
|
||||||
|
|
||||||
class GenericCommands(object):
|
class GenericCommands(object):
|
||||||
|
@ -27,7 +27,19 @@ class GenericCommands(object):
|
||||||
|
|
||||||
class create(object):
|
class create(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux, asset_list, provider_list, caller):
|
def run(
|
||||||
|
cmd,
|
||||||
|
spl,
|
||||||
|
length,
|
||||||
|
authed,
|
||||||
|
msg,
|
||||||
|
agora,
|
||||||
|
tx,
|
||||||
|
ux,
|
||||||
|
asset_list,
|
||||||
|
provider_list,
|
||||||
|
caller,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Post an ad on AgoraDesk/LBTC with the given country and currency code.
|
Post an ad on AgoraDesk/LBTC with the given country and currency code.
|
||||||
"""
|
"""
|
||||||
|
@ -47,7 +59,9 @@ class GenericCommands(object):
|
||||||
payment_details=account_info[currency],
|
payment_details=account_info[currency],
|
||||||
)
|
)
|
||||||
if posted["success"]:
|
if posted["success"]:
|
||||||
msg(f"{posted['response']['data']['message']}: {posted['response']['data']['ad_id']}")
|
msg(
|
||||||
|
f"{posted['response']['data']['message']}: {posted['response']['data']['ad_id']}"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
msg(dumps(posted["response"]))
|
msg(dumps(posted["response"]))
|
||||||
elif length == 5:
|
elif length == 5:
|
||||||
|
@ -70,7 +84,9 @@ class GenericCommands(object):
|
||||||
payment_details=account_info[currency],
|
payment_details=account_info[currency],
|
||||||
)
|
)
|
||||||
if posted["success"]:
|
if posted["success"]:
|
||||||
msg(f"{posted['response']['data']['message']}: {posted['response']['data']['ad_id']}")
|
msg(
|
||||||
|
f"{posted['response']['data']['message']}: {posted['response']['data']['ad_id']}"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
msg(dumps(posted["response"]))
|
msg(dumps(posted["response"]))
|
||||||
|
|
||||||
|
@ -106,13 +122,17 @@ class GenericCommands(object):
|
||||||
return
|
return
|
||||||
for x in caller.dist_countries(filter_asset=asset):
|
for x in caller.dist_countries(filter_asset=asset):
|
||||||
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["response"]))
|
msg(dumps(x["response"]))
|
||||||
elif length == 1:
|
elif length == 1:
|
||||||
for x in caller.dist_countries():
|
for x in caller.dist_countries():
|
||||||
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["response"]))
|
msg(dumps(x["response"]))
|
||||||
|
|
||||||
|
@ -188,7 +208,9 @@ class GenericCommands(object):
|
||||||
return
|
return
|
||||||
providers = spl[3].split(",")
|
providers = spl[3].split(",")
|
||||||
currency = spl[2]
|
currency = spl[2]
|
||||||
c = caller.get_all_public_ads(assets=[asset], currencies=[currency], providers=providers)
|
c = caller.get_all_public_ads(
|
||||||
|
assets=[asset], currencies=[currency], providers=providers
|
||||||
|
)
|
||||||
c.addCallback(GenericCommands.pubads.got_pubads, currency, msg)
|
c.addCallback(GenericCommands.pubads.got_pubads, currency, msg)
|
||||||
|
|
||||||
class cheat(object):
|
class cheat(object):
|
||||||
|
@ -268,7 +290,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.trades.run(cmd, spl, length, authed, msg, agora, tx, ux, agora)
|
GenericCommands.trades.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, agora
|
||||||
|
)
|
||||||
|
|
||||||
class ltrades(object):
|
class ltrades(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -277,7 +301,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.trades.run(cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc)
|
GenericCommands.trades.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc
|
||||||
|
)
|
||||||
|
|
||||||
class acreate(object):
|
class acreate(object):
|
||||||
name = "acreate"
|
name = "acreate"
|
||||||
|
@ -328,7 +354,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.messages.run(cmd, spl, length, authed, msg, agora, tx, ux, agora)
|
GenericCommands.messages.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, agora
|
||||||
|
)
|
||||||
|
|
||||||
class lmessages(object):
|
class lmessages(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -337,7 +365,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.messages.run(cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc)
|
GenericCommands.messages.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc
|
||||||
|
)
|
||||||
|
|
||||||
class adist(object):
|
class adist(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -346,7 +376,18 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.dist.run(cmd, spl, length, authed, msg, agora, tx, ux, settings.Agora.AssetList, agora)
|
GenericCommands.dist.run(
|
||||||
|
cmd,
|
||||||
|
spl,
|
||||||
|
length,
|
||||||
|
authed,
|
||||||
|
msg,
|
||||||
|
agora,
|
||||||
|
tx,
|
||||||
|
ux,
|
||||||
|
settings.Agora.AssetList,
|
||||||
|
agora,
|
||||||
|
)
|
||||||
|
|
||||||
class ldist(object):
|
class ldist(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -356,7 +397,16 @@ class IRCCommands(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.dist.run(
|
GenericCommands.dist.run(
|
||||||
cmd, spl, length, authed, msg, agora, tx, ux, settings.LocalBitcoins.AssetList, tx.lbtc
|
cmd,
|
||||||
|
spl,
|
||||||
|
length,
|
||||||
|
authed,
|
||||||
|
msg,
|
||||||
|
agora,
|
||||||
|
tx,
|
||||||
|
ux,
|
||||||
|
settings.LocalBitcoins.AssetList,
|
||||||
|
tx.lbtc,
|
||||||
)
|
)
|
||||||
|
|
||||||
class aredist(object):
|
class aredist(object):
|
||||||
|
@ -366,7 +416,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.redist.run(cmd, spl, length, authed, msg, agora, tx, ux, agora)
|
GenericCommands.redist.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, agora
|
||||||
|
)
|
||||||
|
|
||||||
class lredist(object):
|
class lredist(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -375,7 +427,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.redist.run(cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc)
|
GenericCommands.redist.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc
|
||||||
|
)
|
||||||
|
|
||||||
class astripdupes(object):
|
class astripdupes(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -384,7 +438,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.stripdupes.run(cmd, spl, length, authed, msg, agora, tx, ux, agora)
|
GenericCommands.stripdupes.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, agora
|
||||||
|
)
|
||||||
|
|
||||||
class lstripdupes(object):
|
class lstripdupes(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -393,7 +449,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.stripdupes.run(cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc)
|
GenericCommands.stripdupes.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc
|
||||||
|
)
|
||||||
|
|
||||||
class total(object):
|
class total(object):
|
||||||
name = "total"
|
name = "total"
|
||||||
|
@ -440,7 +498,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.message.run(cmd, spl, length, authed, msg, agora, tx, ux, agora.agora)
|
GenericCommands.message.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, agora.agora
|
||||||
|
)
|
||||||
|
|
||||||
class lmessage(object):
|
class lmessage(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -449,7 +509,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.message.run(cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc.lbtc)
|
GenericCommands.message.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc.lbtc
|
||||||
|
)
|
||||||
|
|
||||||
class refs(object):
|
class refs(object):
|
||||||
name = "refs"
|
name = "refs"
|
||||||
|
@ -496,7 +558,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.release.run(cmd, spl, length, authed, msg, agora, tx, ux, agora)
|
GenericCommands.release.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, agora
|
||||||
|
)
|
||||||
|
|
||||||
class lrelease(object):
|
class lrelease(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -505,7 +569,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.release.run(cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc)
|
GenericCommands.release.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc
|
||||||
|
)
|
||||||
|
|
||||||
class map(object):
|
class map(object):
|
||||||
name = "map"
|
name = "map"
|
||||||
|
@ -535,7 +601,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.nuke.run(cmd, spl, length, authed, msg, agora, tx, ux, agora)
|
GenericCommands.nuke.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, agora
|
||||||
|
)
|
||||||
|
|
||||||
class lnuke(object):
|
class lnuke(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -544,7 +612,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.nuke.run(cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc)
|
GenericCommands.nuke.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc
|
||||||
|
)
|
||||||
|
|
||||||
class awallet(object):
|
class awallet(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -553,7 +623,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.wallet.run(cmd, spl, length, authed, msg, agora, tx, ux, True, agora.api)
|
GenericCommands.wallet.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, True, agora.api
|
||||||
|
)
|
||||||
|
|
||||||
class lwallet(object):
|
class lwallet(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -562,7 +634,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.wallet.run(cmd, spl, length, authed, msg, agora, tx, ux, False, tx.lbtc.api)
|
GenericCommands.wallet.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, False, tx.lbtc.api
|
||||||
|
)
|
||||||
|
|
||||||
class apubads(object):
|
class apubads(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -571,7 +645,18 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.pubads.run(cmd, spl, length, authed, msg, agora, tx, ux, settings.Agora.AssetList, agora)
|
GenericCommands.pubads.run(
|
||||||
|
cmd,
|
||||||
|
spl,
|
||||||
|
length,
|
||||||
|
authed,
|
||||||
|
msg,
|
||||||
|
agora,
|
||||||
|
tx,
|
||||||
|
ux,
|
||||||
|
settings.Agora.AssetList,
|
||||||
|
agora,
|
||||||
|
)
|
||||||
|
|
||||||
class lpubads(object):
|
class lpubads(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -581,7 +666,16 @@ class IRCCommands(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.pubads.run(
|
GenericCommands.pubads.run(
|
||||||
cmd, spl, length, authed, msg, agora, tx, ux, settings.LocalBitcoins.AssetList, tx.lbtc
|
cmd,
|
||||||
|
spl,
|
||||||
|
length,
|
||||||
|
authed,
|
||||||
|
msg,
|
||||||
|
agora,
|
||||||
|
tx,
|
||||||
|
ux,
|
||||||
|
settings.LocalBitcoins.AssetList,
|
||||||
|
tx.lbtc,
|
||||||
)
|
)
|
||||||
|
|
||||||
class acheat(object):
|
class acheat(object):
|
||||||
|
@ -591,7 +685,18 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.cheat.run(cmd, spl, length, authed, msg, agora, tx, ux, settings.Agora.AssetList, agora)
|
GenericCommands.cheat.run(
|
||||||
|
cmd,
|
||||||
|
spl,
|
||||||
|
length,
|
||||||
|
authed,
|
||||||
|
msg,
|
||||||
|
agora,
|
||||||
|
tx,
|
||||||
|
ux,
|
||||||
|
settings.Agora.AssetList,
|
||||||
|
agora,
|
||||||
|
)
|
||||||
|
|
||||||
class lcheat(object):
|
class lcheat(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -601,7 +706,16 @@ class IRCCommands(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.cheat.run(
|
GenericCommands.cheat.run(
|
||||||
cmd, spl, length, authed, msg, agora, tx, ux, settings.LocalBitcoins.AssetList, tx.lbtc
|
cmd,
|
||||||
|
spl,
|
||||||
|
length,
|
||||||
|
authed,
|
||||||
|
msg,
|
||||||
|
agora,
|
||||||
|
tx,
|
||||||
|
ux,
|
||||||
|
settings.LocalBitcoins.AssetList,
|
||||||
|
tx.lbtc,
|
||||||
)
|
)
|
||||||
|
|
||||||
class acheatnext(object):
|
class acheatnext(object):
|
||||||
|
@ -611,7 +725,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.cheatnext.run(cmd, spl, length, authed, msg, agora, tx, ux, agora)
|
GenericCommands.cheatnext.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, agora
|
||||||
|
)
|
||||||
|
|
||||||
class lcheatnext(object):
|
class lcheatnext(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -620,7 +736,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.cheatnext.run(cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc)
|
GenericCommands.cheatnext.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc
|
||||||
|
)
|
||||||
|
|
||||||
class aads(object):
|
class aads(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -638,7 +756,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.ads.run(cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc)
|
GenericCommands.ads.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc
|
||||||
|
)
|
||||||
|
|
||||||
class xmr(object):
|
class xmr(object):
|
||||||
name = "xmr"
|
name = "xmr"
|
||||||
|
@ -647,7 +767,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
xmr_prices = agora.money.cg.get_price(ids="monero", vs_currencies=["sek", "usd", "gbp"])
|
xmr_prices = agora.money.cg.get_price(
|
||||||
|
ids="monero", vs_currencies=["sek", "usd", "gbp"]
|
||||||
|
)
|
||||||
price_sek = xmr_prices["monero"]["sek"]
|
price_sek = xmr_prices["monero"]["sek"]
|
||||||
price_usd = xmr_prices["monero"]["usd"]
|
price_usd = xmr_prices["monero"]["usd"]
|
||||||
price_gbp = xmr_prices["monero"]["gbp"]
|
price_gbp = xmr_prices["monero"]["gbp"]
|
||||||
|
@ -660,7 +782,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
xmr_prices = agora.money.cg.get_price(ids="bitcoin", vs_currencies=["sek", "usd", "gbp"])
|
xmr_prices = agora.money.cg.get_price(
|
||||||
|
ids="bitcoin", vs_currencies=["sek", "usd", "gbp"]
|
||||||
|
)
|
||||||
price_sek = xmr_prices["bitcoin"]["sek"]
|
price_sek = xmr_prices["bitcoin"]["sek"]
|
||||||
price_usd = xmr_prices["bitcoin"]["usd"]
|
price_usd = xmr_prices["bitcoin"]["usd"]
|
||||||
price_gbp = xmr_prices["bitcoin"]["gbp"]
|
price_gbp = xmr_prices["bitcoin"]["gbp"]
|
||||||
|
@ -673,7 +797,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.withdraw.run(cmd, spl, length, authed, msg, agora, tx, ux, agora)
|
GenericCommands.withdraw.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, agora
|
||||||
|
)
|
||||||
|
|
||||||
class lwithdraw(object):
|
class lwithdraw(object):
|
||||||
authed = True
|
authed = True
|
||||||
|
@ -682,7 +808,9 @@ class IRCCommands(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
GenericCommands.withdraw.run(cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc)
|
GenericCommands.withdraw.run(
|
||||||
|
cmd, spl, length, authed, msg, agora, tx, ux, tx.lbtc
|
||||||
|
)
|
||||||
|
|
||||||
class remaining(object):
|
class remaining(object):
|
||||||
name = "r"
|
name = "r"
|
||||||
|
@ -807,7 +935,9 @@ class IRCCommands(object):
|
||||||
account = spl[1]
|
account = spl[1]
|
||||||
accounts = tx.sinks.truelayer.get_accounts(account)
|
accounts = tx.sinks.truelayer.get_accounts(account)
|
||||||
for account in accounts["results"]:
|
for account in accounts["results"]:
|
||||||
msg(f"{account['account_id']} {account['display_name']} {account['currency']}")
|
msg(
|
||||||
|
f"{account['account_id']} {account['display_name']} {account['currency']}"
|
||||||
|
)
|
||||||
|
|
||||||
class naccounts(object):
|
class naccounts(object):
|
||||||
name = "naccounts"
|
name = "naccounts"
|
||||||
|
@ -870,7 +1000,9 @@ class IRCCommands(object):
|
||||||
if length == 2:
|
if length == 2:
|
||||||
account_id = spl[1]
|
account_id = spl[1]
|
||||||
transactions = tx.sinks.nordigen.get_transactions(account_id)
|
transactions = tx.sinks.nordigen.get_transactions(account_id)
|
||||||
transactions.addCallback(IRCCommands.ntransactions.got_transactions, msg)
|
transactions.addCallback(
|
||||||
|
IRCCommands.ntransactions.got_transactions, msg
|
||||||
|
)
|
||||||
|
|
||||||
class nreqs(object):
|
class nreqs(object):
|
||||||
name = "nreqs"
|
name = "nreqs"
|
||||||
|
@ -964,7 +1096,9 @@ class IRCCommands(object):
|
||||||
accounts_active.append(account)
|
accounts_active.append(account)
|
||||||
accounts_all = tx.sinks.truelayer.get_accounts(bank)
|
accounts_all = tx.sinks.truelayer.get_accounts(bank)
|
||||||
accounts_unmapped = [
|
accounts_unmapped = [
|
||||||
x["account_id"] for x in accounts_all["results"] if x["account_id"] not in accounts_active
|
x["account_id"]
|
||||||
|
for x in accounts_all["results"]
|
||||||
|
if x["account_id"] not in accounts_active
|
||||||
]
|
]
|
||||||
msg(f"Unmapped accounts: {', '.join(accounts_unmapped)}")
|
msg(f"Unmapped accounts: {', '.join(accounts_unmapped)}")
|
||||||
|
|
||||||
|
@ -982,7 +1116,9 @@ class IRCCommands(object):
|
||||||
class authlink(object):
|
class authlink(object):
|
||||||
name = "authlink"
|
name = "authlink"
|
||||||
authed = True
|
authed = True
|
||||||
helptext = "Create a URL for identity verification. Usage: authlink <identifier>"
|
helptext = (
|
||||||
|
"Create a URL for identity verification. Usage: authlink <identifier>"
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
|
@ -994,7 +1130,9 @@ class IRCCommands(object):
|
||||||
class checkauth(object):
|
class checkauth(object):
|
||||||
name = "checkauth"
|
name = "checkauth"
|
||||||
authed = True
|
authed = True
|
||||||
helptext = "Check the authentication for an identifier. Usage: checkauth <identifier>"
|
helptext = (
|
||||||
|
"Check the authentication for an identifier. Usage: checkauth <identifier>"
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
|
@ -1013,8 +1151,12 @@ class IRCCommands(object):
|
||||||
if length == 3:
|
if length == 3:
|
||||||
platform = spl[1]
|
platform = spl[1]
|
||||||
currency = spl[2]
|
currency = spl[2]
|
||||||
account_info = tx.markets.get_matching_account_details(platform, currency)
|
account_info = tx.markets.get_matching_account_details(
|
||||||
bank_details = tx.markets.format_payment_details(currency, account_info, real=True)
|
platform, currency
|
||||||
|
)
|
||||||
|
bank_details = tx.markets.format_payment_details(
|
||||||
|
currency, account_info, real=True
|
||||||
|
)
|
||||||
if not bank_details:
|
if not bank_details:
|
||||||
msg("Could not get bank details.")
|
msg("Could not get bank details.")
|
||||||
return
|
return
|
||||||
|
@ -1023,7 +1165,9 @@ class IRCCommands(object):
|
||||||
class id(object):
|
class id(object):
|
||||||
name = "id"
|
name = "id"
|
||||||
authed = True
|
authed = True
|
||||||
helptext = "Get the identity information of a user. Usage: id <platform> <username>"
|
helptext = (
|
||||||
|
"Get the identity information of a user. Usage: id <platform> <username>"
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
def run(cmd, spl, length, authed, msg, agora, tx, ux):
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
# Twisted/Klein imports
|
# Twisted/Klein imports
|
||||||
from twisted.words.protocols import irc
|
import util
|
||||||
from twisted.internet import protocol, reactor, ssl
|
|
||||||
|
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
|
from twisted.internet import protocol, reactor, ssl
|
||||||
|
from twisted.words.protocols import irc
|
||||||
from ux.commands import IRCCommands
|
from ux.commands import IRCCommands
|
||||||
import util
|
|
||||||
|
|
||||||
|
|
||||||
class IRCBot(irc.IRCClient):
|
class IRCBot(irc.IRCClient):
|
||||||
|
@ -18,7 +17,9 @@ class IRCBot(irc.IRCClient):
|
||||||
self.log = log
|
self.log = log
|
||||||
self.cmd = IRCCommands()
|
self.cmd = IRCCommands()
|
||||||
# Parse the commands into "commandname": "commandclass"
|
# Parse the commands into "commandname": "commandclass"
|
||||||
self.cmdhash = {getattr(self.cmd, x).name: x for x in dir(self.cmd) if not x.startswith("_")}
|
self.cmdhash = {
|
||||||
|
getattr(self.cmd, x).name: x for x in dir(self.cmd) if not x.startswith("_")
|
||||||
|
}
|
||||||
self.nickname = settings.IRC.Nick
|
self.nickname = settings.IRC.Nick
|
||||||
self.password = settings.IRC.Pass
|
self.password = settings.IRC.Pass
|
||||||
self.realname = self.nickname
|
self.realname = self.nickname
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
# Other library imports
|
# Other library imports
|
||||||
import requests
|
import requests
|
||||||
|
import util
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
import util
|
|
||||||
|
|
||||||
|
|
||||||
class Notify(util.Base):
|
class Notify(util.Base):
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# Other library imports
|
# Other library imports
|
||||||
import requests
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import hmac
|
import hmac
|
||||||
import time
|
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import util
|
||||||
# Project imports
|
# Project imports
|
||||||
from settings import settings
|
from settings import settings
|
||||||
import util
|
|
||||||
|
|
||||||
|
|
||||||
class Verify(util.Base):
|
class Verify(util.Base):
|
||||||
|
@ -35,7 +35,9 @@ class Verify(util.Base):
|
||||||
"""
|
"""
|
||||||
self.antifraud.user_verification_successful(external_user_id)
|
self.antifraud.user_verification_successful(external_user_id)
|
||||||
|
|
||||||
def update_verification_status(self, external_user_id, review_status, review_answer=None):
|
def update_verification_status(
|
||||||
|
self, external_user_id, review_status, review_answer=None
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Update the authentication status of a external user ID.
|
Update the authentication status of a external user ID.
|
||||||
"""
|
"""
|
||||||
|
@ -46,7 +48,11 @@ class Verify(util.Base):
|
||||||
if type(content) == str:
|
if type(content) == str:
|
||||||
content = content.encode("utf-8")
|
content = content.encode("utf-8")
|
||||||
# hmac needs bytes
|
# hmac needs bytes
|
||||||
signature = hmac.new(settings.Verify.WebHookSecret.encode("utf-8"), content, digestmod=hashlib.sha1).hexdigest()
|
signature = hmac.new(
|
||||||
|
settings.Verify.WebHookSecret.encode("utf-8"),
|
||||||
|
content,
|
||||||
|
digestmod=hashlib.sha1,
|
||||||
|
).hexdigest()
|
||||||
|
|
||||||
return signature == payload_digest
|
return signature == payload_digest
|
||||||
|
|
||||||
|
@ -68,7 +74,9 @@ class Verify(util.Base):
|
||||||
if "reviewAnswer" in content_json["reviewResult"]:
|
if "reviewAnswer" in content_json["reviewResult"]:
|
||||||
review_answer = content_json["reviewResult"]["reviewAnswer"]
|
review_answer = content_json["reviewResult"]["reviewAnswer"]
|
||||||
|
|
||||||
self.update_verification_status(external_user_id, review_status, review_answer=review_answer)
|
self.update_verification_status(
|
||||||
|
external_user_id, review_status, review_answer=review_answer
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def handle_callback(self, request):
|
def handle_callback(self, request):
|
||||||
|
@ -137,7 +145,10 @@ class Verify(util.Base):
|
||||||
"""
|
"""
|
||||||
Get the status of an applicant by the external user ID.
|
Get the status of an applicant by the external user ID.
|
||||||
"""
|
"""
|
||||||
url = settings.Verify.Base + f"/resources/applicants/-;externalUserId={external_user_id}/one"
|
url = (
|
||||||
|
settings.Verify.Base
|
||||||
|
+ f"/resources/applicants/-;externalUserId={external_user_id}/one"
|
||||||
|
)
|
||||||
resp = self.sign_request(requests.Request("GET", url))
|
resp = self.sign_request(requests.Request("GET", url))
|
||||||
s = requests.Session()
|
s = requests.Session()
|
||||||
response = s.send(resp)
|
response = s.send(resp)
|
||||||
|
@ -173,10 +184,19 @@ class Verify(util.Base):
|
||||||
"""
|
"""
|
||||||
Get an access token for an external user ID.
|
Get an access token for an external user ID.
|
||||||
"""
|
"""
|
||||||
params = {"userId": external_user_id, "ttlInSecs": "600", "levelName": level_name}
|
params = {
|
||||||
|
"userId": external_user_id,
|
||||||
|
"ttlInSecs": "600",
|
||||||
|
"levelName": level_name,
|
||||||
|
}
|
||||||
headers = {"Content-Type": "application/json", "Content-Encoding": "utf-8"}
|
headers = {"Content-Type": "application/json", "Content-Encoding": "utf-8"}
|
||||||
resp = self.sign_request(
|
resp = self.sign_request(
|
||||||
requests.Request("POST", f"{settings.Verify.Base}/resources/accessTokens", params=params, headers=headers)
|
requests.Request(
|
||||||
|
"POST",
|
||||||
|
f"{settings.Verify.Base}/resources/accessTokens",
|
||||||
|
params=params,
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
s = requests.Session()
|
s = requests.Session()
|
||||||
response = s.send(resp)
|
response = s.send(resp)
|
||||||
|
@ -196,9 +216,16 @@ class Verify(util.Base):
|
||||||
body = b"" if prepared_request.body is None else prepared_request.body
|
body = b"" if prepared_request.body is None else prepared_request.body
|
||||||
if type(body) == str:
|
if type(body) == str:
|
||||||
body = body.encode("utf-8")
|
body = body.encode("utf-8")
|
||||||
data_to_sign = str(now).encode("utf-8") + method.encode("utf-8") + path_url.encode("utf-8") + body
|
data_to_sign = (
|
||||||
|
str(now).encode("utf-8")
|
||||||
|
+ method.encode("utf-8")
|
||||||
|
+ path_url.encode("utf-8")
|
||||||
|
+ body
|
||||||
|
)
|
||||||
# hmac needs bytes
|
# hmac needs bytes
|
||||||
signature = hmac.new(settings.Verify.Key.encode("utf-8"), data_to_sign, digestmod=hashlib.sha256)
|
signature = hmac.new(
|
||||||
|
settings.Verify.Key.encode("utf-8"), data_to_sign, digestmod=hashlib.sha256
|
||||||
|
)
|
||||||
prepared_request.headers["X-App-Token"] = settings.Verify.Token
|
prepared_request.headers["X-App-Token"] = settings.Verify.Token
|
||||||
prepared_request.headers["X-App-Access-Ts"] = str(now)
|
prepared_request.headers["X-App-Access-Ts"] = str(now)
|
||||||
prepared_request.headers["X-App-Access-Sig"] = signature.hexdigest()
|
prepared_request.headers["X-App-Access-Sig"] = signature.hexdigest()
|
||||||
|
|
Loading…
Reference in New Issue