Remove calls to Revolut
This commit is contained in:
parent
b53fbfc905
commit
2266300064
|
@ -12,7 +12,6 @@ from signal import signal, SIGINT
|
|||
# Project imports
|
||||
from settings import settings
|
||||
import util
|
||||
from revolut import Revolut
|
||||
from agora import Agora
|
||||
from transactions import Transactions
|
||||
from irc import bot
|
||||
|
@ -99,7 +98,6 @@ if __name__ == "__main__":
|
|||
"irc": bot(),
|
||||
"agora": Agora(),
|
||||
"markets": Markets(),
|
||||
"revolut": Revolut(),
|
||||
"nordigen": Nordigen(),
|
||||
"truelayer": TrueLayer(),
|
||||
"fidor": Fidor(),
|
||||
|
@ -110,21 +108,6 @@ if __name__ == "__main__":
|
|||
# Merge all classes into each other
|
||||
util.xmerge_attrs(init_map)
|
||||
|
||||
# Setup the authcode -> refresh token and refresh_token -> auth_token stuff
|
||||
# util.setup_call_loops(
|
||||
# token_setting=settings.Revolut.SetupToken,
|
||||
# function_init=init_map["revolut"].setup_auth,
|
||||
# function_continuous=init_map["revolut"].get_new_token,
|
||||
# delay=int(settings.Revolut.RefreshSec),
|
||||
# function_post_start=init_map["revolut"].setup_webhook,
|
||||
# )
|
||||
# util.setup_call_loops(
|
||||
# token_setting=settings.TrueLayer.SetupToken,
|
||||
# function_init=init_map["truelayer"].setup_auth,
|
||||
# function_continuous=init_map["truelayer"].get_new_token,
|
||||
# delay=int(settings.TrueLayer.RefreshSec),
|
||||
# )
|
||||
|
||||
# Set up the loops to put data in ES
|
||||
init_map["tx"].setup_loops()
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ class IRCCommands(object):
|
|||
helptext = "Get all open trades."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
"""
|
||||
Get details of open trades and post on IRC.
|
||||
"""
|
||||
|
@ -32,7 +32,7 @@ class IRCCommands(object):
|
|||
helptext = "Create an ad. Usage: create <XMR/BTC> <country> <currency> [<provider>]"
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
"""
|
||||
Post an ad on AgoraDesk with the given country and currency code.
|
||||
"""
|
||||
|
@ -64,7 +64,7 @@ class IRCCommands(object):
|
|||
helptext = "Get messages. Usage: messages [<reference>]"
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
"""
|
||||
Get all messages for all open trades or a given trade.
|
||||
"""
|
||||
|
@ -98,7 +98,7 @@ class IRCCommands(object):
|
|||
helptext = "Distribute all our chosen currency and country ad pairs. Usage: dist [<XMR/BTC>]"
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
# Distribute out our ad to all countries in the config
|
||||
if length == 2:
|
||||
asset = spl[1]
|
||||
|
@ -123,7 +123,7 @@ class IRCCommands(object):
|
|||
helptext = "Update all ads with details."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
for x in agora.redist_countries():
|
||||
if x[0]["success"]:
|
||||
msg(f"{x[0]['response']['data']['message']}: {x[1]}")
|
||||
|
@ -136,51 +136,17 @@ class IRCCommands(object):
|
|||
helptext = "Remove all duplicate adverts."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
rtrn = agora.strip_duplicate_ads()
|
||||
msg(dumps(rtrn))
|
||||
|
||||
class accounts(object):
|
||||
name = "accounts"
|
||||
authed = True
|
||||
helptext = "Get all account information from Revolut."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
accounts = revolut.accounts()
|
||||
accounts_posted = 0
|
||||
if accounts is None:
|
||||
msg("Error getting accounts.")
|
||||
for account in accounts:
|
||||
if account["balance"] > 0:
|
||||
if "name" in account:
|
||||
name = account["name"]
|
||||
else:
|
||||
name = "not_set"
|
||||
msg(f"{name} {account['currency']}: {account['balance']}")
|
||||
accounts_posted += 1
|
||||
if accounts_posted == 0:
|
||||
msg("No accounts with balances.")
|
||||
|
||||
class balance(object):
|
||||
name = "balance"
|
||||
authed = True
|
||||
helptext = "Get total account balance from Revolut in USD."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
total_usd = revolut.get_total_usd()
|
||||
if total_usd is False:
|
||||
msg("Error getting total balance.")
|
||||
msg(f"Total: {round(total_usd, 2)}USD")
|
||||
|
||||
class total(object):
|
||||
name = "total"
|
||||
authed = True
|
||||
helptext = "Get total account balance from Revolut and Agora."
|
||||
helptext = "Get total account balance from Sinks and Agora."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
totals_all = tx.get_total()
|
||||
totals = totals_all[0]
|
||||
wallets = totals_all[1]
|
||||
|
@ -202,7 +168,7 @@ class IRCCommands(object):
|
|||
helptext = "Summon all operators."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
notify.sendmsg("You have been summoned!")
|
||||
|
||||
class message(object):
|
||||
|
@ -211,7 +177,7 @@ class IRCCommands(object):
|
|||
helptext = "Send a message on a trade. Usage: msg <reference> <message...>"
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
if length > 2:
|
||||
full_msg = " ".join(spl[2:])
|
||||
reference = tx.ref_to_tx(spl[1])
|
||||
|
@ -227,7 +193,7 @@ class IRCCommands(object):
|
|||
helptext = "List all references"
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
msg(f"References: {', '.join(tx.get_refs())}")
|
||||
|
||||
class ref(object):
|
||||
|
@ -236,7 +202,7 @@ class IRCCommands(object):
|
|||
helptext = "Get more information about a reference. Usage: ref <reference>"
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
if length == 2:
|
||||
ref_data = tx.get_ref(spl[1])
|
||||
if not ref_data:
|
||||
|
@ -250,7 +216,7 @@ class IRCCommands(object):
|
|||
helptext = "Delete a reference. Usage: del <reference>"
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
if length == 2:
|
||||
ref_data = tx.get_ref(spl[1])
|
||||
if not ref_data:
|
||||
|
@ -265,7 +231,7 @@ class IRCCommands(object):
|
|||
helptext = "Release funds for a trade. Usage: release <reference>"
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
if length == 2:
|
||||
tx = tx.ref_to_tx(spl[1])
|
||||
if not tx:
|
||||
|
@ -282,7 +248,7 @@ class IRCCommands(object):
|
|||
helptext = "Delete all our adverts."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
rtrn = agora.nuke_ads()
|
||||
msg(dumps(rtrn))
|
||||
|
||||
|
@ -292,7 +258,7 @@ class IRCCommands(object):
|
|||
helptext = "Get Agora wallet balances."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
rtrn_xmr = agora.agora.wallet_balance_xmr()
|
||||
if not rtrn_xmr["success"]:
|
||||
msg("Error getting XMR wallet details.")
|
||||
|
@ -312,7 +278,7 @@ class IRCCommands(object):
|
|||
helptext = "View public adverts. Usage: pubads <XMR/BTC> <currency> [<provider,...>]"
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
if length == 3:
|
||||
asset = spl[1]
|
||||
if asset not in loads(settings.Agora.AssetList):
|
||||
|
@ -345,7 +311,7 @@ class IRCCommands(object):
|
|||
helptext = "Cheat the markets by manipulating our prices to exploit people. Usage: cheat [<XMR/BTC>]"
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
if length == 1:
|
||||
agora.run_cheat_in_thread()
|
||||
msg("Running cheat in thread.")
|
||||
|
@ -363,7 +329,7 @@ class IRCCommands(object):
|
|||
helptext = "Run the next currency for cheat."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
if length == 1:
|
||||
asset = agora.run_cheat_in_thread()
|
||||
msg(f"Running next asset for cheat in thread: {asset}")
|
||||
|
@ -374,7 +340,7 @@ class IRCCommands(object):
|
|||
helptext = "Get all our ad regions"
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
ads = agora.enum_ads()
|
||||
for ad in ads:
|
||||
msg(f"({ad[0]}) {ad[1]} {ad[2]} {ad[3]} {ad[4]}")
|
||||
|
@ -385,7 +351,7 @@ class IRCCommands(object):
|
|||
helptext = "Get current XMR price."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
xmr_prices = agora.cg.get_price(ids="monero", vs_currencies=["sek", "usd", "gbp"])
|
||||
price_sek = xmr_prices["monero"]["sek"]
|
||||
price_usd = xmr_prices["monero"]["usd"]
|
||||
|
@ -398,7 +364,7 @@ class IRCCommands(object):
|
|||
helptext = "Get current BTC price."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
xmr_prices = agora.cg.get_price(ids="bitcoin", vs_currencies=["sek", "usd", "gbp"])
|
||||
price_sek = xmr_prices["bitcoin"]["sek"]
|
||||
price_usd = xmr_prices["bitcoin"]["usd"]
|
||||
|
@ -411,28 +377,16 @@ class IRCCommands(object):
|
|||
helptext = "Take profit."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
agora.withdraw_funds()
|
||||
|
||||
class shuffle(object):
|
||||
name = "shuffle"
|
||||
authed = True
|
||||
helptext = "Convert all currencies in Revolut to supplied one. Usage: shuffle <currency>"
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
if length == 2:
|
||||
currency = spl[1]
|
||||
rtrn = revolut.shuffle(currency)
|
||||
msg(dumps(rtrn))
|
||||
|
||||
class remaining(object):
|
||||
name = "r"
|
||||
authed = True
|
||||
helptext = "Show how much is left before we are able to withdraw funds."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
remaining = tx.get_remaining()
|
||||
msg(f"Remaining: {remaining}USD")
|
||||
|
||||
|
@ -442,7 +396,7 @@ class IRCCommands(object):
|
|||
helptext = "Show how much is left before we are able to withdraw funds (including open trades)."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
remaining = tx.get_total_remaining()
|
||||
msg(f"Total remaining: {remaining}USD")
|
||||
|
||||
|
@ -452,7 +406,7 @@ class IRCCommands(object):
|
|||
helptext = "Get total value of all open trades in USD."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
total = tx.get_open_trades_usd()
|
||||
msg(f"Total trades: {total}USD")
|
||||
|
||||
|
@ -462,7 +416,7 @@ class IRCCommands(object):
|
|||
helptext = "Get total value of everything, including open trades."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
total = tx.get_total_with_trades()
|
||||
msg(f"${total}")
|
||||
|
||||
|
@ -472,7 +426,7 @@ class IRCCommands(object):
|
|||
helptext = "Get total profit."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
total = tx.money.get_profit()
|
||||
msg(f"Profit: {total}USD")
|
||||
|
||||
|
@ -482,7 +436,7 @@ class IRCCommands(object):
|
|||
helptext = "Get total profit with open trades."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
total = tx.money.get_profit(True)
|
||||
msg(f"Profit: {total}USD")
|
||||
|
||||
|
@ -492,6 +446,6 @@ class IRCCommands(object):
|
|||
helptext = "Generate a TrueLayer signin URL."
|
||||
|
||||
@staticmethod
|
||||
def run(cmd, spl, length, authed, msg, agora, revolut, tx, notify):
|
||||
def run(cmd, spl, length, authed, msg, agora, tx, notify):
|
||||
auth_url = agora.truelayer.create_auth_url()
|
||||
msg(f"Auth URL: {auth_url}")
|
||||
|
|
|
@ -88,7 +88,7 @@ class IRCBot(irc.IRCClient):
|
|||
# Check if the command required authentication
|
||||
if obj.authed:
|
||||
if host in self.admins:
|
||||
obj.run(cmd, spl, length, authed, msgl, self.agora, self.revolut, self.tx, self.notify)
|
||||
obj.run(cmd, spl, length, authed, msgl, self.agora, self.tx, self.notify)
|
||||
else:
|
||||
# Handle authentication here instead of in the command module for security
|
||||
self.msg(channel, "Access denied.")
|
||||
|
@ -192,7 +192,8 @@ class IRCBotFactory(protocol.ClientFactory):
|
|||
prcol = IRCBot(self.log)
|
||||
self.client = prcol
|
||||
setattr(self.client, "agora", self.agora)
|
||||
setattr(self.client, "revolut", self.revolut)
|
||||
setattr(self.client, "truelayer", self.truelayer)
|
||||
setattr(self.client, "nordigen", self.nordigen)
|
||||
setattr(self.client, "tx", self.tx)
|
||||
setattr(self.client, "notify", self.notify)
|
||||
return prcol
|
||||
|
|
|
@ -1,247 +0,0 @@
|
|||
# Twisted/Klein imports
|
||||
from twisted.logger import Logger
|
||||
|
||||
# Other library imports
|
||||
from json import dumps
|
||||
from simplejson.errors import JSONDecodeError
|
||||
import requests
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
import jwt
|
||||
from random import choices
|
||||
from string import ascii_uppercase
|
||||
|
||||
# Project imports
|
||||
from settings import settings
|
||||
|
||||
|
||||
class Revolut(object):
|
||||
"""
|
||||
Class to handle Revolut API calls.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialise the Revolut object.
|
||||
Set the logger and token.
|
||||
"""
|
||||
self.log = Logger("revolut")
|
||||
self.token = None
|
||||
|
||||
def setup_auth(self):
|
||||
"""
|
||||
Function to create a new Java Web Token and use it to get a refresh/access token.
|
||||
"""
|
||||
self.create_new_jwt()
|
||||
self.get_access_token()
|
||||
|
||||
def create_new_jwt(self):
|
||||
"""
|
||||
Create a new Java Web Token.
|
||||
"""
|
||||
payload = {
|
||||
"iss": settings.Revolut.Domain,
|
||||
"sub": settings.Revolut.ClientID,
|
||||
"aud": "https://revolut.com",
|
||||
"exp": int(settings.Revolut.Expiry),
|
||||
}
|
||||
with open(settings.Revolut.PrivateKey, "rb") as f:
|
||||
pem_bytes = f.read()
|
||||
|
||||
# payload = {jwt_header, jwt_body}
|
||||
private_key = serialization.load_pem_private_key(pem_bytes, password=None, backend=default_backend())
|
||||
encoded = jwt.encode(payload, private_key, algorithm="RS256")
|
||||
settings.Revolut.JWT = encoded
|
||||
settings.write()
|
||||
|
||||
def get_access_token(self):
|
||||
"""
|
||||
Get an access token with our JWT.
|
||||
:return: True or False
|
||||
:rtype: bool
|
||||
"""
|
||||
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
||||
data = {
|
||||
"grant_type": "authorization_code",
|
||||
"code": settings.Revolut.AuthCode,
|
||||
"client_id": settings.Revolut.ClientID,
|
||||
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
||||
"client_assertion": settings.Revolut.JWT,
|
||||
}
|
||||
r = requests.post(f"{settings.Revolut.Base}/auth/token", data=data, headers=headers)
|
||||
try:
|
||||
parsed = r.json()
|
||||
except JSONDecodeError:
|
||||
self.log.error("Error parsing access token response: {content}", content=r.content)
|
||||
return False
|
||||
if r.status_code == 200:
|
||||
try:
|
||||
settings.Revolut.RefreshToken = parsed["refresh_token"]
|
||||
settings.Revolut.SetupToken = "0"
|
||||
settings.write()
|
||||
self.log.info("Refreshed refresh token - Revolut")
|
||||
self.token = parsed["access_token"]
|
||||
self.log.info("Refreshed access token - Revolut")
|
||||
except KeyError:
|
||||
self.log.error(f"Token authorization didn't contain refresh or access token: {parsed}", parsed=parsed)
|
||||
return False
|
||||
else:
|
||||
self.log.error(f"Cannot refresh token: {parsed}", parsed=parsed)
|
||||
return False
|
||||
|
||||
def get_new_token(self, fail=False):
|
||||
"""
|
||||
Get a new access token with the refresh token.
|
||||
:param fail: whether to exit() if this fails
|
||||
:type fail: bool
|
||||
:return: True or False
|
||||
:rtype: bool
|
||||
"""
|
||||
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
||||
data = {
|
||||
"grant_type": "refresh_token",
|
||||
"refresh_token": settings.Revolut.RefreshToken,
|
||||
"client_id": settings.Revolut.ClientID,
|
||||
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
||||
"client_assertion": settings.Revolut.JWT,
|
||||
}
|
||||
r = requests.post(f"{settings.Revolut.Base}/auth/token", data=data, headers=headers)
|
||||
try:
|
||||
parsed = r.json()
|
||||
except JSONDecodeError:
|
||||
if fail:
|
||||
exit()
|
||||
return False
|
||||
if r.status_code == 200:
|
||||
if "access_token" in parsed.keys():
|
||||
self.token = parsed["access_token"]
|
||||
self.log.info("Refreshed access token - Revolut")
|
||||
return True
|
||||
else:
|
||||
self.log.error(f"Token refresh didn't contain access token: {parsed}", parsed=parsed)
|
||||
if fail:
|
||||
exit()
|
||||
return False
|
||||
else:
|
||||
self.log.error(f"Cannot refresh token: {parsed}", parsed=parsed)
|
||||
if fail:
|
||||
exit()
|
||||
return False
|
||||
|
||||
def setup_webhook(self):
|
||||
"""
|
||||
Check the webhook we have set up in Revolut.
|
||||
Set up configured webhook if not already set up.
|
||||
:return: True or False
|
||||
:rtype: bool
|
||||
"""
|
||||
webhook = self.get_webhook()
|
||||
if "url" in webhook.keys():
|
||||
if webhook["url"] == settings.Revolut.WebhookURL:
|
||||
self.log.info("Webhook exists - skipping setup: {url}", url=webhook["url"])
|
||||
return True # Webhook already exists
|
||||
self.log.info("Setting up webhook: {url}", url=settings.Revolut.WebhookURL)
|
||||
headers = {"Authorization": f"Bearer {self.token}"}
|
||||
data = {"url": settings.Revolut.WebhookURL}
|
||||
r = requests.post(f"{settings.Revolut.Base}/webhook", data=dumps(data), headers=headers)
|
||||
if r.status_code == 204:
|
||||
self.log.info("Set up webhook: {url}", url=settings.Revolut.WebhookURL)
|
||||
return True
|
||||
else:
|
||||
parsed = r.json()
|
||||
self.log.info("Failed setting up webhook: {parsed}", parsed=parsed)
|
||||
return False
|
||||
|
||||
def get_webhook(self):
|
||||
"""
|
||||
Get the webhook address active in Revolut.
|
||||
:return: dict of hook with key url or False
|
||||
:rtype: dict or bool
|
||||
"""
|
||||
headers = {"Authorization": f"Bearer {self.token}"}
|
||||
r = requests.get(f"{settings.Revolut.Base}/webhook", headers=headers)
|
||||
if r.status_code == 200:
|
||||
parsed = r.json()
|
||||
return parsed
|
||||
elif r.status_code == 404:
|
||||
return {}
|
||||
else:
|
||||
self.log.error("Cannot get webhook: {content}", r.content)
|
||||
return False
|
||||
|
||||
def accounts(self):
|
||||
"""
|
||||
Get the details and balances of all Revolut accounts.
|
||||
:return: account details
|
||||
:rtype: dict
|
||||
"""
|
||||
headers = {"Authorization": f"Bearer {self.token}"}
|
||||
r = requests.get(f"{settings.Revolut.Base}/accounts", headers=headers)
|
||||
if r.status_code == 200:
|
||||
return r.json()
|
||||
else:
|
||||
self.log.error("Error getting accounts: {content}", content=r.content)
|
||||
return False
|
||||
|
||||
def get_total_usd(self):
|
||||
rates = self.money.get_rates_all()
|
||||
accounts = self.accounts()
|
||||
if not accounts:
|
||||
return False
|
||||
total_usd = 0
|
||||
for account in accounts:
|
||||
if account["currency"] == "USD":
|
||||
total_usd += account["balance"]
|
||||
else:
|
||||
total_usd += account["balance"] / rates[account["currency"]]
|
||||
return total_usd
|
||||
|
||||
def convert(self, from_account_id, from_currency, to_account_id, to_currency, sell_amount):
|
||||
"""
|
||||
Convert currency.
|
||||
:param sell_currency: currency to sell
|
||||
:param buy_currency: currency to buy
|
||||
:param sell_amount: amount of currency to sell
|
||||
"""
|
||||
reference = "".join(choices(ascii_uppercase, k=5))
|
||||
headers = {"Authorization": f"Bearer {self.token}"}
|
||||
data = {
|
||||
"from": {
|
||||
"account_id": from_account_id,
|
||||
"currency": from_currency,
|
||||
"amount": sell_amount,
|
||||
},
|
||||
"to": {
|
||||
"account_id": to_account_id,
|
||||
"currency": to_currency,
|
||||
},
|
||||
"request_id": reference,
|
||||
}
|
||||
r = requests.post(f"{settings.Revolut.Base}/exchange", headers=headers, data=dumps(data))
|
||||
if r.status_code == 200:
|
||||
return r.json()
|
||||
else:
|
||||
self.log.error("Error converting balance: {content}", content=r.content)
|
||||
return False
|
||||
|
||||
def shuffle(self, currency):
|
||||
"""
|
||||
Exchange money in all accounts to the given currency.
|
||||
:param currency: the currency to convert all our funds to
|
||||
"""
|
||||
accounts = self.accounts()
|
||||
|
||||
# Find given currency account
|
||||
for account in accounts:
|
||||
if account["currency"] == currency:
|
||||
if account["state"] == "active" and account["public"] is True:
|
||||
dest_account = account
|
||||
# Remove this account
|
||||
accounts.remove(dest_account)
|
||||
break
|
||||
|
||||
for account in accounts:
|
||||
if account["balance"] > 0:
|
||||
self.convert(account["id"], account["currency"], dest_account["id"], dest_account["currency"], account["balance"])
|
||||
|
||||
return True
|
Loading…
Reference in New Issue