diff --git a/silkaj/tx.py b/silkaj/tx.py index 7360d37137b1ced4831b898137fe9e32900c5024..b74be66a77091108838c0163b05cbddde1a65ebd 100644 --- a/silkaj/tx.py +++ b/silkaj/tx.py @@ -144,6 +144,28 @@ async def send_transaction( await client.close() +async def transaction_amount(amounts, UDs_amounts, outputAddresses): + """ + Check that the number of passed amounts(UD) and recipients are the same + Returns a list of amounts. + """ + # Create amounts list + if amounts: + amounts_list = compute_amounts(amounts, CENT_MULT_TO_UNIT) + elif UDs_amounts: + UD_value = await money.UDValue().ud_value + amounts_list = compute_amounts(UDs_amounts, UD_value) + if len(amounts_list) != len(outputAddresses) and len(amounts_list) != 1: + message_exit( + "Error: The number of passed recipients is not the same as the passed amounts." + ) + # In case one amount is passed with multiple recipients + # generate list containing multiple time the same amount + if len(amounts_list) == 1 and len(outputAddresses) > 1: + amounts_list = [amounts_list[0]] * len(outputAddresses) + return amounts_list + + def compute_amounts(amounts, multiplicator): """ Computes the amounts(UD) and returns a list. @@ -163,16 +185,6 @@ def compute_amounts(amounts, multiplicator): return amounts_list -async def transaction_amount(amount, amountUD, allSources): - """ - Return transaction amount - """ - if amount: - return round(amount * 100) - if amountUD: - return round(amountUD * await money.UDValue().ud_value) - - def check_transaction_values( comment, outputAddresses, outputBackChange, enough_source, issuer_pubkey ): diff --git a/tests/test_tx.py b/tests/test_tx.py index 55f1eb4d3b9d4b3ff460858d8ab93a659512777c..d38ed48de548e94f1819961f01fecd535732bfdc 100644 --- a/tests/test_tx.py +++ b/tests/test_tx.py @@ -11,15 +11,24 @@ async def test_transaction_amount(): """test passed amounts passed tx command float ≠100 does not give the exact value""" - assert await transaction_amount(141.89, None, None) == 14189 - assert await transaction_amount(141.99, None, None) == 14199 - assert await transaction_amount(141.01, None, None) == 14101 + udvalue = await UDValue().ud_value + trials = ( + # tests for --amount (unit) + ([141.89], None, ["A"], [14189]), + ([141.99], None, ["A"], [14199]), + ([141.01], None, ["A"], [14101]), + ([141.89], None, ["A", "B"], [14189, 14189]), + ([141.89, 141.99], None, ["A", "B"], [14189, 14199]), + # tests for --amount_UD + (None, [1.1], ["A"], [round(1.1 * udvalue)]), + (None, [1.9], ["A", "B",], [round(1.9 * udvalue), round(1.9 * udvalue)]), + (None, [1.0001], ["A"], [round(1.0001 * udvalue)]), + (None, [9.9999], ["A"], [round(9.9999 * udvalue)]), + (None, [1.9, 2.3], ["A", "B"], [round(1.9 * udvalue), round(2.3 * udvalue)]), + ) - ud_value = await UDValue().ud_value - assert await transaction_amount(None, 1.1, None) == round(1.1 * ud_value) - assert await transaction_amount(None, 1.9, None) == round(1.9 * ud_value) - assert await transaction_amount(None, 1.0001, None) == round(1.0001 * ud_value) - assert await transaction_amount(None, 9.9999, None) == round(9.9999 * ud_value) + for trial in trials: + assert trial[3] == await transaction_amount(trial[0], trial[1], trial[2]) def test_tx_passed_amount_cli(): @@ -69,3 +78,19 @@ def test_tx_passed_amount_cli(): result = CliRunner().invoke(cli, ["tx", "-r", "A", "-a", MINIMAL_TX_AMOUNT - 0.001]) assert 'Error: Invalid value for "--amount"' in result.output assert result.exit_code == 2 + + result = CliRunner().invoke(cli, ["tx", "-r", "A", "-a", 1, "-a", 2]) + assert ( + "Error: The number of passed recipients is not the same as the passed amounts." + in result.output + ) + assert result.exit_code == 1 + + result = CliRunner().invoke( + cli, ["tx", "-r", "A", "-r", "B", "-r", "C", "-a", 1, "-a", 2] + ) + assert ( + "Error: The number of passed recipients is not the same as the passed amounts." + in result.output + ) + assert result.exit_code == 1 diff --git a/tests/test_unit_tx.py b/tests/test_unit_tx.py index 770e3967dbfcc6823835d13fe7e74ba1942088b9..dd608cb40b6a05d9c33f9dc3984735005bdef71f 100644 --- a/tests/test_unit_tx.py +++ b/tests/test_unit_tx.py @@ -1,8 +1,13 @@ import pytest -from silkaj.tx import truncBase, transaction_confirmation, compute_amounts +from silkaj.tx import ( + truncBase, + transaction_confirmation, + compute_amounts, + transaction_amount, +) from silkaj.tui import display_pubkey, display_amount from silkaj.money import UDValue -from silkaj.constants import G1_SYMBOL +from silkaj.constants import G1_SYMBOL, MINIMAL_TX_AMOUNT, CENT_MULT_TO_UNIT import patched # truncBase() @@ -195,3 +200,103 @@ def test_compute_amounts(): assert compute_amounts([1.009], ud_value) == [317] # This case will not happen in real use, but this particular function will allow it. assert compute_amounts([0.0099], 100,) == [1] + + +# transaction_amount() +@pytest.mark.parametrize( + "amounts, UDs_amounts, outputAddresses, expected", + [ + ([10], None, ["DBM6F5ChMJzpmkUdL5zD9UXKExmZGfQ1AgPDQy4MxSBw"], [1000]), + ( + [10, 2.37], + None, + [ + "DBM6F5ChMJzpmkUdL5zD9UXKExmZGfQ1AgPDQy4MxSBw", + "4szFkvQ5tzzhwcfUtZD32hdoG2ZzhvG3ZtfR61yjnxdw", + ], + [1000, 237], + ), + ( + [10], + None, + [ + "DBM6F5ChMJzpmkUdL5zD9UXKExmZGfQ1AgPDQy4MxSBw", + "4szFkvQ5tzzhwcfUtZD32hdoG2ZzhvG3ZtfR61yjnxdw", + ], + [1000, 1000], + ), + (None, [1.263], ["DBM6F5ChMJzpmkUdL5zD9UXKExmZGfQ1AgPDQy4MxSBw"], [397]), + ( + None, + [0.5, 10], + [ + "DBM6F5ChMJzpmkUdL5zD9UXKExmZGfQ1AgPDQy4MxSBw", + "4szFkvQ5tzzhwcfUtZD32hdoG2ZzhvG3ZtfR61yjnxdw", + ], + [157, 3140], + ), + ( + None, + [0.5], + [ + "DBM6F5ChMJzpmkUdL5zD9UXKExmZGfQ1AgPDQy4MxSBw", + "4szFkvQ5tzzhwcfUtZD32hdoG2ZzhvG3ZtfR61yjnxdw", + ], + [157, 157], + ), + ( + None, + [0.00002], + ["DBM6F5ChMJzpmkUdL5zD9UXKExmZGfQ1AgPDQy4MxSBw",], + "Error: amount 0.00002 is too low.", + ), + ( + [10, 56], + None, + ["DBM6F5ChMJzpmkUdL5zD9UXKExmZGfQ1AgPDQy4MxSBw"], + "Error: The number of passed recipients is not the same as the passed amounts.", + ), + ( + None, + [1, 45], + "DBM6F5ChMJzpmkUdL5zD9UXKExmZGfQ1AgPDQy4MxSBw", + "Error: The number of passed recipients is not the same as the passed amounts.", + ), + ], +) +@pytest.mark.asyncio +async def test_transaction_amount( + amounts, UDs_amounts, outputAddresses, expected, capsys, monkeypatch +): + # patched functions + monkeypatch.setattr("silkaj.money.UDValue.get_ud_value", patched.ud_value) + udvalue = patched.mock_ud_value + + def too_little_amount(amounts, multiplicator): + for amount in amounts: + if amount * multiplicator < MINIMAL_TX_AMOUNT * CENT_MULT_TO_UNIT: + return True + return False + + # run tests + if amounts: + given_amounts = amounts + if UDs_amounts: + given_amounts = UDs_amounts + # test errors + if ( + (len(given_amounts) > 1 and len(outputAddresses) != len(given_amounts)) + or (UDs_amounts and too_little_amount(given_amounts, udvalue)) + or (amounts and too_little_amount(given_amounts, CENT_MULT_TO_UNIT)) + ): + # check program exit on error + with pytest.raises(SystemExit) as pytest_exit: + # read output to check error. + await transaction_amount(amounts, UDs_amounts, outputAddresses) + assert expected == capsys.readouterr() + assert pytest_exit.type == SystemExit + # test good values + else: + assert expected == await transaction_amount( + amounts, UDs_amounts, outputAddresses + )