You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

564 lines
19 KiB
Python

from unittest.mock import patch
from django.test import TransactionTestCase
from core.models import Trade, Transaction
from core.tests.helpers import AggregatorPlatformMixin
class TestTransactions(AggregatorPlatformMixin, TransactionTestCase):
def setUp(self):
super().setUp()
self.transaction = Transaction.objects.create(
aggregator=self.aggregator,
account_id="my account id",
transaction_id="BANKTX",
amount=1,
currency="GBP",
note="TEST-1",
)
self.trades = {
1: {
"contact_id": "uuid1",
"buyer": "test_buyer_1",
"currency": "GBP",
"asset": "XMR",
"amount_fiat": 1,
"amount_crypto": 0.3,
"reference": "TEST-1",
"provider": "REVOLUT",
},
2: {
"contact_id": "uuid2",
"buyer": "test_buyer_2",
"currency": "GBP",
"asset": "XMR",
"amount_fiat": 1,
"amount_crypto": 0.3,
"reference": "TEST-2",
"provider": "REVOLUT",
},
3: {
"contact_id": "uuid3",
"buyer": "test_buyer_3",
"currency": "GBP",
"asset": "XMR",
"amount_fiat": 1000,
"amount_crypto": 3,
"reference": "TEST-3",
"provider": "REVOLUT",
},
4: {
"contact_id": "uuid4",
"buyer": "test_buyer_4",
"currency": "GBP",
"asset": "XMR",
"amount_fiat": 10,
"amount_crypto": 0.5,
"reference": "TEST-4",
"provider": "REVOLUT",
},
5: { # to conflict with 1
"contact_id": "uuid1",
"buyer": "test_buyer_2",
"currency": "GBP",
"asset": "XMR",
"amount_fiat": 1,
"amount_crypto": 0.3,
"reference": "TEST-1",
"provider": "REVOLUT",
},
}
def create_trades(self, *numbers):
for trade_key in self.trades.keys():
if trade_key in numbers:
Trade.objects.create(
platform=self.platform,
# open=True,
**self.trades[trade_key],
)
def mock_to_usd(self, amount, currency):
if currency == "GBP":
return amount * 1.3
elif currency == "USD":
return amount
# fuck it who cares
elif currency == "SEK":
return 100
elif currency == "EUR":
return 10
@patch("core.lib.notify.sendmsg")
async def test_reference_partial_check(self, _):
self.create_trades(1, 2, 3, 4)
result = await self.agg_client.reference_partial_check(
self.platform,
"TEST-1",
"for notifications only",
"GBP",
1,
)
self.assertEqual(result, "TEST-1")
@patch("core.lib.notify.sendmsg")
async def test_reference_partial_check_subset(self, _):
self.create_trades(1, 2, 3, 4)
result = await self.agg_client.reference_partial_check(
self.platform,
"the TEST-1 in string",
"for notifications only",
"GBP",
1,
)
self.assertEqual(result, "TEST-1")
@patch("core.lib.notify.sendmsg")
async def test_reference_partial_check_multiple_match(self, _):
self.create_trades(1, 2, 3, 4, 5)
result = await self.agg_client.reference_partial_check(
self.platform,
"TEST-1",
"for notifications only",
"GBP",
1,
)
self.assertEqual(result, False)
@patch("core.lib.notify.sendmsg")
async def test_reference_partial_check_none(self, _):
# self.create_trades(1, 2, 3, 4, 5)
result = await self.agg_client.reference_partial_check(
self.platform,
"TEST-1",
"for notifications only",
"GBP",
1,
)
self.assertEqual(result, None)
@patch("core.lib.notify.sendmsg")
async def test_reference_partial_check_none_match(self, _):
self.create_trades(1, 2, 3, 4, 5)
result = await self.agg_client.reference_partial_check(
self.platform,
"NOWHERE",
"for notifications only",
"GBP",
1,
)
self.assertEqual(result, None)
def test_valid_transaction(self):
result = self.agg_client.valid_transaction(self.transaction)
self.assertEqual(result, True)
def test_valid_transaction_fail(self):
self.transaction.amount = -100
result = self.agg_client.valid_transaction(self.transaction)
self.assertEqual(result, False)
self.transaction.amount = 1
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=100)
async def test_can_alt_lookup(self, *args):
result = await self.agg_client.can_alt_lookup(
self.platform,
999999999, # ignored
"GBP",
"IGNORED",
)
self.assertEqual(result, True)
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=500)
async def test_can_alt_lookup_fail(self, *args):
result = await self.agg_client.can_alt_lookup(
self.platform,
999999999, # ignored
"GBP",
"IGNORED",
)
self.assertEqual(result, False)
def test_find_trade(self):
self.create_trades(1, 3, 4)
result = self.agg_client.find_trade(
self.platform,
"BANKTX",
"GBP",
1,
)
self.assertEqual(result.reference, "TEST-1")
self.assertEqual(result.currency, "GBP")
self.assertEqual(result.amount_fiat, 1)
def test_find_trade_fail_two_match(self):
self.create_trades(1, 2, 3, 4) # 2 trades with same amount and currency
result = self.agg_client.find_trade(
self.platform,
"BANKTX",
"GBP",
1,
)
self.assertEqual(result, False)
def test_find_trade_fail_two_match_alt(self):
self.create_trades(1, 3, 4)
result = self.agg_client.find_trade(
self.platform,
"BANKTX",
"GBP",
88,
)
self.assertEqual(result, False)
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=100)
async def test_amount_currency_lookup(self, *args):
self.create_trades(1, 3, 4)
result = await self.agg_client.amount_currency_lookup(
self.platform,
1,
"GBP",
"BANKTX",
"TEST-1",
)
self.assertEqual(result.reference, "TEST-1")
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=100)
async def test_amount_currency_lookup_fail(self, *args):
self.create_trades(1, 3, 4)
result = await self.agg_client.amount_currency_lookup(
self.platform,
88,
"GBP",
"BANKTX",
"TEST-1",
)
self.assertEqual(result, None)
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=500)
async def test_amount_currency_lookup_fail_too_high(self, *args):
self.create_trades(1, 3, 4)
result = await self.agg_client.amount_currency_lookup(
self.platform,
1,
"GBP",
"BANKTX",
"TEST-1",
)
self.assertEqual(result, False)
@patch("core.lib.notify.sendmsg")
async def test_normal_lookup(self, _):
self.create_trades(1, 2, 3, 4)
result = await self.agg_client.normal_lookup(
self.platform,
"TEST-1",
"BANKTX",
"GBP",
1,
)
self.assertEqual(result.reference, "TEST-1")
self.assertEqual(result.currency, "GBP")
self.assertEqual(result.amount_fiat, 1)
@patch("core.lib.notify.sendmsg")
async def test_currency_check(self, _):
self.create_trades(1)
trade = Trade.objects.all().first()
result = await self.agg_client.currency_check(
"GBP",
trade,
)
self.assertEqual(result, True)
@patch("core.lib.notify.sendmsg")
async def test_currency_check_fail(self, _):
self.create_trades(1)
trade = Trade.objects.all().first()
result = await self.agg_client.currency_check(
"AYZ",
trade,
)
self.assertEqual(result, False)
@patch("core.lib.notify.sendmsg")
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1.5)
)
async def test_alt_amount_check(self, *args):
self.create_trades(1)
trade = Trade.objects.all().first()
result = await self.agg_client.alt_amount_check(
self.platform,
1.123,
"GBP",
trade,
)
self.assertEqual(result, True)
@patch("core.lib.notify.sendmsg")
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1.5)
)
async def test_alt_amount_check_fail(self, *args):
self.create_trades(1)
trade = Trade.objects.all().first()
result = await self.agg_client.alt_amount_check(
self.platform,
1.501,
"GBP",
trade,
)
self.assertEqual(result, False)
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=1)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1.5)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction(self, release, gam, to_usd, sendmsg):
self.create_trades(1, 2, 3, 4)
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_called_once_with("uuid1", "TEST-1")
self.assertEqual(self.transaction.reconciled, True)
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=1)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1.5)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction_second(self, release, gam, to_usd, sendmsg):
self.create_trades(1, 2, 3, 4)
self.transaction.note = "TEST-2"
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_called_once_with("uuid2", "TEST-2")
self.assertEqual(self.transaction.reconciled, True)
self.transaction.note = "TEST-1"
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=1)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1.5)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction_invalid(self, release, gam, to_usd, sendmsg):
self.create_trades(1, 2, 3, 4)
self.transaction.amount = -1
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_not_called()
self.assertEqual(self.transaction.reconciled, False)
self.transaction.amount = 1
# def test_transaction_malformed(self):
# malformed_data = self.test_data_copy
# del malformed_data["amount"]
# self.transactions.transaction(malformed_data)
# self.transactions.release_funds.assert_not_called()
# malformed_data = self.test_data_copy
# del malformed_data["currency"]
# self.transactions.transaction(malformed_data)
# self.transactions.release_funds.assert_not_called()
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=1)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1.5)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction_no_reference_fail(self, release, gam, to_usd, sendmsg):
self.create_trades(1, 2, 3, 4)
self.transaction.note = "none"
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_not_called()
self.assertEqual(self.transaction.reconciled, False)
self.transaction.note = "TEST-1"
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=1)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1.5)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction_no_reference_pass(self, release, gam, to_usd, sendmsg):
self.create_trades(1)
self.transaction.note = "none"
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_called_with("uuid1", "TEST-1")
self.assertEqual(self.transaction.reconciled, True)
self.transaction.note = "TEST-1"
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=1000)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction_large(self, release, gam, to_usd, sendmsg):
self.create_trades(1, 2, 3, 4)
self.transaction.amount = 1000
self.transaction.note = "TEST-3"
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_called_once_with("uuid3", "TEST-3")
self.assertEqual(self.transaction.reconciled, True)
self.transaction_amount_fiat = 1
self.transaction.note = "TEST-1"
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=1000)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction_no_reference_exceeds_max(
self, release, gam, to_usd, sendmsg
):
self.create_trades(1, 2, 3, 4)
self.transaction.amount = 1000
self.transaction.note = "noref"
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_not_called()
self.assertEqual(self.transaction.reconciled, False)
self.transaction.amount = 1
self.transaction.note = "TEST-1"
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=100)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction_wrong_currency(self, release, gam, to_usd, sendmsg):
self.create_trades(1, 2, 3, 4)
self.transaction.currency = "EUR"
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_not_called()
self.assertEqual(self.transaction.reconciled, False)
self.transaction.currency = "GBP"
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=100)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction_wrong_currency_noref(
self, release, gam, to_usd, sendmsg
):
self.transaction.currency = "EUR"
self.transaction.note = "none"
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_not_called()
self.assertEqual(self.transaction.reconciled, False)
self.transaction.currency = "GBP"
self.transaction.note = "TEST-1"
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=100)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.8, 1.8)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction_wrong_amount(self, release, gam, to_usd, sendmsg):
self.create_trades(1, 2, 3, 4)
self.transaction.amount = 10
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_not_called()
self.assertEqual(self.transaction.reconciled, False)
self.transaction.amount = 1
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=100)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.8, 1.8)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction_wrong_amount_noref(self, release, gam, to_usd, sendmsg):
self.transaction.amount = 10
self.transaction.note = "none"
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_not_called()
self.assertEqual(self.transaction.reconciled, False)
self.transaction.amount = 1
self.transaction.note = "TEST-1"
# def test_transaction_pending(self):
# pending_tx = self.test_data_copy
# pending_tx["data"]["state"] = "pending"
# self.transactions.transaction(pending_tx)
# self.transactions.release_funds.assert_not_called()
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=100)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction_too_low(self, release, gam, to_usd, sendmsg):
self.create_trades(1, 2, 3, 4)
self.transaction.amount = 5
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_not_called()
self.assertEqual(self.transaction.reconciled, False)
self.transaction.amount = 1
@patch("core.lib.notify.sendmsg")
@patch("core.clients.aggregator.money.to_usd", return_value=100)
@patch(
"core.clients.aggregator.money.get_acceptable_margins", return_value=(0.5, 1)
)
@patch("core.clients.aggregator.AgoraClient.release_trade_escrow")
async def test_transaction_too_high(self, release, gam, to_usd, sendmsg):
self.create_trades(1, 2, 3, 4)
self.transaction.amount = 15
await self.agg_client.transaction([self.platform], self.transaction)
release.assert_not_called()
self.assertEqual(self.transaction.reconciled, False)
self.transaction.amount = 1