From 9b7affb87e94a4cbf5c212d321bc29a2353938b2 Mon Sep 17 00:00:00 2001 From: vtexier <vit@free.fr> Date: Mon, 30 Mar 2020 15:51:06 +0200 Subject: [PATCH] [enh] #798 fully functional "Send as source" feature for a CSV/CLTV locked source --- src/sakia/gui/sub/transfer/controller.py | 9 ++++++ src/sakia/gui/sub/transfer/view.py | 9 +++++- src/sakia/services/documents.py | 4 ++- tests/functional/test_transfer_dialog.py | 40 ++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/sakia/gui/sub/transfer/controller.py b/src/sakia/gui/sub/transfer/controller.py index 74be7cb3..b2acda6c 100644 --- a/src/sakia/gui/sub/transfer/controller.py +++ b/src/sakia/gui/sub/transfer/controller.py @@ -306,9 +306,13 @@ class TransferController(QObject): else: self.view.set_button_box(TransferView.ButtonBoxState.NO_RECEIVER) elif self.password_input.valid(): + # if source and check source successful... self.view.set_button_box(TransferView.ButtonBoxState.OK) else: self.view.set_button_box(TransferView.ButtonBoxState.WRONG_PASSWORD) + # if source and check source button still enabled... + if self.model.current_source and self.view.button_source_check.isEnabled(): + self.view.set_button_box(TransferView.ButtonBoxState.SOURCE_LOCKED) max_relative = self.model.quant_to_rel(current_base_amount / 100) self.view.spinbox_amount.setSuffix(Quantitative.base_str(current_base)) @@ -331,6 +335,7 @@ class TransferController(QObject): self.refresh() def check_source(self): + # evaluate condition source = self.model.current_source condition = pypeg2.parse(source.conditions, Condition) result, _errors = self.model.app.sources_service.evaluate_condition( @@ -340,10 +345,14 @@ class TransferController(QObject): [], source.identifier, ) + # if success... if result: message = QCoreApplication.translate( "TransferController", "Check is successful!" ) + self.view.button_source_check.setDisabled(True) + self.refresh() + # if failure... else: message = QCoreApplication.translate( "TransferController", "<p><b>Condition</b></p>{}" diff --git a/src/sakia/gui/sub/transfer/view.py b/src/sakia/gui/sub/transfer/view.py index 53c10e63..45e1fd31 100644 --- a/src/sakia/gui/sub/transfer/view.py +++ b/src/sakia/gui/sub/transfer/view.py @@ -18,6 +18,7 @@ class TransferView(QWidget, Ui_TransferMoneyWidget): WRONG_PASSWORD = 2 NO_RECEIVER = 3 WRONG_RECIPIENT = 4 + SOURCE_LOCKED = 5 class RecipientMode(Enum): PUBKEY = 1 @@ -45,6 +46,10 @@ class TransferView(QWidget, Ui_TransferMoneyWidget): False, QT_TRANSLATE_NOOP("TransferView", "Incorrect receiver address or pubkey"), ), + ButtonBoxState.SOURCE_LOCKED: ( + False, + QT_TRANSLATE_NOOP("TransferView", "Source locked"), + ), } def __init__( @@ -60,7 +65,9 @@ class TransferView(QWidget, Ui_TransferMoneyWidget): super().__init__(parent) self.setupUi(self) - regexp = QRegExp("^([ a-zA-Z0-9-_:/;*?\[\]\(\)\\\?!^+=@&~#{}|<>%.]{0,255})$") + regexp = QRegExp( + "^([ a-zA-Z0-9-_:/;*?\\[\\]\\(\\)\\\\?!^+=@&~#{}|<>%.]{0,255})$" + ) validator = QRegExpValidator(regexp) self.edit_message.setValidator(validator) diff --git a/src/sakia/services/documents.py b/src/sakia/services/documents.py index 2ca92823..b9011c80 100644 --- a/src/sakia/services/documents.py +++ b/src/sakia/services/documents.py @@ -534,6 +534,8 @@ class DocumentsService: forged_tx += chained_tx else: sources = [source] + computed_outputs = [(source.amount, source.base)] + overheads = [] logging.debug("Inputs: {0}".format(sources)) @@ -596,7 +598,6 @@ class DocumentsService: ): """ Send money to a given recipient in a specified community - :param Source source: Source instance or None :param int lock_mode: Index in the combo_locks combobox :param sakia.data.entities.Connection connection: The account salt :param str secret_key: The account secret_key @@ -605,6 +606,7 @@ class DocumentsService: :param int amount: The amount of money to transfer :param int amount_base: The amount base of the transfer :param str message: The message to send with the transfer + :param Source source: Source instance or None """ blockstamp = self._blockchain_processor.current_buid(connection.currency) key = SigningKey.from_credentials( diff --git a/tests/functional/test_transfer_dialog.py b/tests/functional/test_transfer_dialog.py index 52a31315..b156c899 100644 --- a/tests/functional/test_transfer_dialog.py +++ b/tests/functional/test_transfer_dialog.py @@ -74,3 +74,43 @@ async def test_transfer_chained_tx( transfer_dialog.view.show() await exec_test() + + +@pytest.mark.asyncio +async def test_transfer_from_source( + application_with_one_connection, fake_server_with_blockchain, bob, alice +): + def close_dialog(): + if transfer_dialog.view.isVisible(): + transfer_dialog.view.hide() + + async def exec_test(): + await asyncio.sleep(0.1) + assert not transfer_dialog.view.button_box.button( + QDialogButtonBox.Ok + ).isEnabled() + assert transfer_dialog.view.spinbox_amount.value() == 1 + await asyncio.sleep(0.1) + # simulate checked source condition + transfer_dialog.view.button_source_check.setDisabled(True) + QTest.keyClicks(transfer_dialog.view.password_input.edit_secret_key, bob.salt) + QTest.keyClicks(transfer_dialog.view.password_input.edit_password, bob.password) + assert transfer_dialog.view.button_box.button(QDialogButtonBox.Ok).isEnabled() + QTest.mouseClick( + transfer_dialog.view.button_box.button(QDialogButtonBox.Ok), Qt.LeftButton + ) + await asyncio.sleep(0.2) + assert isinstance(fake_server_with_blockchain.forge.pool[0], Transaction) + + application_with_one_connection.loop.call_later(10, close_dialog) + + bob_connection = application_with_one_connection.db.connections_repo.get_one( + pubkey=bob.key.pubkey + ) + source = application_with_one_connection.sources_service.get_one( + pubkey=bob.key.pubkey + ) + transfer_dialog = TransferController.open_transfer_with_pubkey( + None, application_with_one_connection, bob_connection, alice.key.pubkey, source + ) + await exec_test() -- GitLab