diff --git a/test/python/apps/exchange_navigation_helper.py b/test/python/apps/exchange_navigation_helper.py index 4aaca326..9097621f 100644 --- a/test/python/apps/exchange_navigation_helper.py +++ b/test/python/apps/exchange_navigation_helper.py @@ -10,10 +10,14 @@ def __init__(self, backend: BackendInterface, navigator: Navigator, test_name: s self._backend = backend self._navigator = navigator self._test_name = test_name + self._test_name_suffix = "" + + def set_test_name_suffix(self, suffix: str): + self._test_name_suffix = suffix def _navigate_and_compare(self, accept: bool): # Default behaviors - snapshots_dir_name = self._test_name + snapshots_dir_name = self._test_name + self._test_name_suffix screen_change_after_last_instruction = True if self._backend.firmware.is_nano: diff --git a/test/python/apps/exchange_test_runner.py b/test/python/apps/exchange_test_runner.py new file mode 100644 index 00000000..8e0d20c6 --- /dev/null +++ b/test/python/apps/exchange_test_runner.py @@ -0,0 +1,344 @@ +import pytest +from typing import Optional, Tuple + +from ragger.backend import RaisePolicy +from ragger.utils import RAPDU +from ragger.error import ExceptionRAPDU + +from .exchange import ExchangeClient, Rate, SubCommand, Errors +from .exchange_transaction_builder import get_partner_curve, craft_tx, encode_tx, extract_payout_ticker, extract_refund_ticker +from . import cal as cal +from .signing_authority import SigningAuthority, LEDGER_SIGNER + +from ..utils import handle_lib_call_start_or_stop, int_to_minimally_sized_bytes + +# When adding a new test, have it prefixed by this string in order to have it automatically parametrized for currencies tests +TEST_METHOD_PREFIX="perform_test_" + +# Exchange tests helpers, create a child of this class that define coin-specific elements and call its tests entry points +class ExchangeTestRunner: + + # You will need to define the following elements in the child application: + # currency_ticker: str + # valid_destination_1: str + # valid_destination_memo_1: str + # valid_destination_2: str + # valid_destination_memo_2: str + # valid_refund: str + # valid_refund_memo: str + # valid_send_amount_1: int + # valid_send_amount_2: int + # valid_fees_1: int + # valid_fees_2: int + # fake_refund: str + # fake_refund_memo: str + # fake_payout: str + # fake_payout_memo: str + # signature_refusal_error_code: int + + # You can optionnaly overwrite the following default values if you want + partner_name = "Default name" + fund_user_id = "Jon Wick" + fund_account_name = "My account 00" + sell_trader_email = "john@doe.lost" + sell_out_currency = "USD" + sell_out_amount = {"coefficient": b"\x01", "exponent": 3} + + def __init__(self, backend, exchange_navigation_helper): + self.backend = backend + self.exchange_navigation_helper = exchange_navigation_helper + + def run_test(self, function_to_test: str): + self.exchange_navigation_helper.set_test_name_suffix("_" + function_to_test) + getattr(self, TEST_METHOD_PREFIX + function_to_test)() + + def _perform_valid_exchange(self, subcommand, tx_infos, fees, ui_validation): + # Initialize the exchange client plugin that will format and send the APDUs to the device + ex = ExchangeClient(self.backend, Rate.FIXED, subcommand) + + # The partner we will perform the exchange with + partner = SigningAuthority(curve=get_partner_curve(subcommand), name=self.partner_name) + + # Initialize a new transaction request + transaction_id = ex.init_transaction().data + + # Enroll the partner + ex.set_partner_key(partner.credentials) + ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) + + # Craft the exchange transaction proposal and have it signed by the enrolled partner + tx = craft_tx(subcommand, tx_infos, transaction_id) + encoded_tx = encode_tx(subcommand, partner, tx) + + # Send the exchange transaction proposal and it's signature + ex.process_transaction(tx, fees) + ex.check_transaction_signature(encoded_tx) + + # Ask our fake CAL the coin configuration for both payout and refund tickers (None for refund in case of FUND or SELL) + payout_ticker = extract_payout_ticker(subcommand, tx_infos) + refund_ticker = extract_refund_ticker(subcommand, tx_infos) + payout_configuration = cal.get_conf_for_ticker(payout_ticker) + refund_configuration = cal.get_conf_for_ticker(refund_ticker) + + # Request the final address check and UI approval request on the device + with ex.check_address(payout_configuration, refund_configuration): + if ui_validation: + self.exchange_navigation_helper.simple_accept() + else: + # Calling the navigator delays the RAPDU reception until the end of navigation + # Which is problematic if the RAPDU is an error as we would not raise until the navigation is done + # As a workaround, we avoid calling the navigation if we want the function to raise + pass + + # Ask exchange to start the library application to sign the actual outgoing transaction + ex.start_signing_transaction() + + def perform_valid_swap_from_custom(self, destination, send_amount, fees, memo, refund_address=None, refund_memo=None, ui_validation=True): + refund_address = self.valid_refund if refund_address is None else refund_address + refund_memo = self.valid_refund_memo if refund_memo is None else refund_memo + tx_infos = { + "payin_address": destination, + "payin_extra_id": memo, + "refund_address": refund_address, + "refund_extra_id": refund_memo.encode(), + "payout_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", # Default + "payout_extra_id": b"", # Default + "currency_from": self.currency_ticker, + "currency_to": "ETH", # Default + "amount_to_provider": int_to_minimally_sized_bytes(send_amount), + "amount_to_wallet": b"\246\333t\233+\330\000", # Default + } + self._perform_valid_exchange(SubCommand.SWAP, tx_infos, fees, ui_validation=ui_validation) + + def perform_valid_swap_to_custom(self, destination, send_amount, fees, memo, ui_validation=True): + tx_infos = { + "payin_address": "0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", # Default + "payin_extra_id": "", # Default + "refund_address": "0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", # Default + "refund_extra_id": "", # Default + "payout_address": destination, + "payout_extra_id": memo.encode(), + "currency_from": "ETH", # Default + "currency_to": self.currency_ticker, + "amount_to_provider": int_to_minimally_sized_bytes(send_amount), + "amount_to_wallet": b"\246\333t\233+\330\000", # Default + } + self._perform_valid_exchange(SubCommand.SWAP, tx_infos, fees, ui_validation=ui_validation) + + def perform_valid_fund_from_custom(self, destination, send_amount, fees): + tx_infos = { + "user_id": self.fund_user_id, + "account_name": self.fund_account_name, + "in_currency": self.currency_ticker, + "in_amount": int_to_minimally_sized_bytes(send_amount), + "in_address": destination, + } + self._perform_valid_exchange(SubCommand.FUND, tx_infos, fees, ui_validation=True) + + def perform_valid_sell_from_custom(self, destination, send_amount, fees): + tx_infos = { + "trader_email": self.sell_trader_email, + "out_currency": self.sell_out_currency, + "out_amount": self.sell_out_amount, + "in_currency": self.currency_ticker, + "in_amount": int_to_minimally_sized_bytes(send_amount), + "in_address": destination, + } + self._perform_valid_exchange(SubCommand.SELL, tx_infos, fees, ui_validation=True) + + # Implement this function for each tested coin + def perform_final_tx(self, destination, send_amount, fees, memo): + raise NotImplementedError + + # Wrapper of the function above to handle the USB reset in the parent class instead of the currency class + def perform_coin_specific_final_tx(self, destination, send_amount, fees, memo): + self.perform_final_tx(destination, send_amount, fees, memo) + handle_lib_call_start_or_stop(self.backend) + + ######################################################### + # Generic SWAP tests functions, call them in your tests # + ######################################################### + + # We test that the currency app returns a fail when checking an incorrect refund address + def perform_test_swap_wrong_refund(self): + with pytest.raises(ExceptionRAPDU) as e: + self.perform_valid_swap_from_custom(self.valid_destination_1, + self.valid_send_amount_1, + self.valid_fees_1, + self.valid_destination_memo_1, + refund_address=self.fake_refund, + refund_memo=self.fake_refund_memo, + ui_validation=False) + assert e.value.status == Errors.INVALID_ADDRESS + + # We test that the currency app returns a fail when checking an incorrect payout address + def perform_test_swap_wrong_payout(self): + with pytest.raises(ExceptionRAPDU) as e: + self.perform_valid_swap_to_custom(self.fake_payout, self.valid_send_amount_1, self.valid_fees_1, self.fake_payout_memo, ui_validation=False) + assert e.value.status == Errors.INVALID_ADDRESS + + # The absolute standard swap, using default values, user accepts on UI + def perform_test_swap_valid_1(self): + self.perform_valid_swap_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, self.valid_destination_memo_1) + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, self.valid_destination_memo_1) + + # The second standard swap, using alternate default values, user accepts on UI + def perform_test_swap_valid_2(self): + self.perform_valid_swap_from_custom(self.valid_destination_2, self.valid_send_amount_2, self.valid_fees_2, self.valid_destination_memo_2) + self.perform_coin_specific_final_tx(self.valid_destination_2, self.valid_send_amount_2, self.valid_fees_2, self.valid_destination_memo_2) + + # Make a valid swap and then ask a second signature + def perform_test_swap_refuse_double_sign(self): + self.perform_valid_swap_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, self.valid_destination_memo_1) + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, self.valid_destination_memo_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, self.valid_destination_memo_1) + assert e.value.status == Errors.INVALID_INSTRUCTION or e.value.status == Errors.WRONG_P2 + + # Test swap with a malicious TX with tampered fees + def perform_test_swap_wrong_fees(self): + assert self.valid_fees_1 != self.valid_fees_2, "This test won't work if the values are the same" + self.perform_valid_swap_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, self.valid_destination_memo_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_2, self.valid_destination_memo_1) + assert e.value.status == self.signature_refusal_error_code + + # Test swap with a malicious TX with tampered memo + def perform_test_swap_wrong_memo(self): + assert self.valid_destination_memo_1 != self.valid_destination_memo_2, "This test won't work if the values are the same" + self.perform_valid_swap_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, self.valid_destination_memo_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, self.valid_destination_memo_2) + assert e.value.status == self.signature_refusal_error_code + + # Test swap with a malicious TX with tampered destination + def perform_test_swap_wrong_destination(self): + assert self.valid_destination_1 != self.valid_destination_2, "This test won't work if the values are the same" + self.perform_valid_swap_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, self.valid_destination_memo_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_2, self.valid_send_amount_1, self.valid_fees_1, self.valid_destination_memo_1) + assert e.value.status == self.signature_refusal_error_code + + # Test swap with a malicious TX with tampered amount + def perform_test_swap_wrong_amount(self): + assert self.valid_send_amount_1 != self.valid_send_amount_2, "This test won't work if the values are the same" + self.perform_valid_swap_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, self.valid_destination_memo_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_2, self.valid_fees_1, self.valid_destination_memo_1) + assert e.value.status == self.signature_refusal_error_code + + ######################################################### + # Generic FUND tests functions, call them in your tests # + ######################################################### + + # The absolute standard fund, using default values, user accepts on UI + def perform_test_fund_valid_1(self): + self.perform_valid_fund_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1) + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + + # The second standard fund, using alternate default values, user accepts on UI + def perform_test_fund_valid_2(self): + self.perform_valid_fund_from_custom(self.valid_destination_2, self.valid_send_amount_2, self.valid_fees_2) + self.perform_coin_specific_final_tx(self.valid_destination_2, self.valid_send_amount_2, self.valid_fees_2, "") + + # Make a valid fund and then ask a second signature + def perform_test_fund_refuse_double_sign(self): + self.perform_valid_fund_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1) + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + assert e.value.status == Errors.INVALID_INSTRUCTION + + # Test fund with a malicious TX with tampered fees + def perform_test_fund_wrong_fees(self): + assert self.valid_fees_1 != self.valid_fees_2, "This test won't work if the values are the same" + self.perform_valid_fund_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_2, "") + assert e.value.status == self.signature_refusal_error_code + + # Test fund with a malicious TX with tampered memo + def perform_test_fund_wrong_memo(self): + self.perform_valid_fund_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "no memo expected") + assert e.value.status == self.signature_refusal_error_code + + # Test fund with a malicious TX with tampered destination + def perform_test_fund_wrong_destination(self): + assert self.valid_destination_1 != self.valid_destination_2, "This test won't work if the values are the same" + self.perform_valid_fund_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_2, self.valid_send_amount_1, self.valid_fees_1, "") + assert e.value.status == self.signature_refusal_error_code + + # Test fund with a malicious TX with tampered amount + def perform_test_fund_wrong_amount(self): + assert self.valid_send_amount_1 != self.valid_send_amount_2, "This test won't work if the values are the same" + self.perform_valid_fund_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_2, self.valid_fees_1, "") + assert e.value.status == self.signature_refusal_error_code + + ######################################################### + # Generic SELL tests functions, call them in your tests # + ######################################################### + + # The absolute standard sell, using default values, user accepts on UI + def perform_test_sell_valid_1(self): + self.perform_valid_sell_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1) + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + + # The second standard sell, using alternate default values, user accepts on UI + def perform_test_sell_valid_2(self): + self.perform_valid_sell_from_custom(self.valid_destination_2, self.valid_send_amount_2, self.valid_fees_2) + self.perform_coin_specific_final_tx(self.valid_destination_2, self.valid_send_amount_2, self.valid_fees_2, "") + + # Make a valid sell and then ask a second signature + def perform_test_sell_refuse_double_sign(self): + self.perform_valid_sell_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1) + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "") + assert e.value.status == Errors.INVALID_INSTRUCTION + + # Test sell with a malicious TX with tampered fees + def perform_test_sell_wrong_fees(self): + assert self.valid_fees_1 != self.valid_fees_2, "This test won't work if the values are the same" + self.perform_valid_sell_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_2, "") + assert e.value.status == self.signature_refusal_error_code + + # Test sell with a malicious TX with tampered memo + def perform_test_sell_wrong_memo(self): + self.perform_valid_sell_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1, "no memo expected") + assert e.value.status == self.signature_refusal_error_code + + # Test sell with a malicious TX with tampered destination + def perform_test_sell_wrong_destination(self): + assert self.valid_destination_1 != self.valid_destination_2, "This test won't work if the values are the same" + self.perform_valid_sell_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_2, self.valid_send_amount_1, self.valid_fees_1, "") + assert e.value.status == self.signature_refusal_error_code + + # Test sell with a malicious TX with tampered amount + def perform_test_sell_wrong_amount(self): + assert self.valid_send_amount_1 != self.valid_send_amount_2, "This test won't work if the values are the same" + self.perform_valid_sell_from_custom(self.valid_destination_1, self.valid_send_amount_1, self.valid_fees_1) + with pytest.raises(ExceptionRAPDU) as e: + self.perform_coin_specific_final_tx(self.valid_destination_1, self.valid_send_amount_2, self.valid_fees_1, "") + assert e.value.status == self.signature_refusal_error_code + +# Automatically collect all tests functions and export their name in ready-to-be-parametrized lists +_all_test_methods_prefixed = [method for method in dir(ExchangeTestRunner) if method.startswith(TEST_METHOD_PREFIX)] +# Remove prefix to have nice snapshots directories +ALL_TESTS = [str(i).replace(TEST_METHOD_PREFIX, '') for i in _all_test_methods_prefixed] +ALL_TESTS_EXCEPT_MEMO = [test for test in ALL_TESTS if not "memo" in test] +ALL_TESTS_EXCEPT_MEMO_AND_FEES = [test for test in ALL_TESTS if (not "memo" in test and not "fees" in test)] +SWAP_TESTS = [test for test in ALL_TESTS if "swap" in test] +FUND_TESTS = [test for test in ALL_TESTS if "fund" in test] +SELL_TESTS = [test for test in ALL_TESTS if "sell" in test] diff --git a/test/python/apps/solana_utils.py b/test/python/apps/solana_utils.py index ec7be1e0..d45db03c 100644 --- a/test/python/apps/solana_utils.py +++ b/test/python/apps/solana_utils.py @@ -27,6 +27,9 @@ def lamports_to_bytes(lamports: int) -> str: FEES = sol_to_lamports(0.00000564) FEES_BYTES = lamports_to_bytes(FEES) +FEES_2 = sol_to_lamports(0.0005543) +FEES_2_BYTES = lamports_to_bytes(FEES_2) + ### Proposed foreign and owned addresses ### diff --git a/test/python/conftest.py b/test/python/conftest.py index 117ab431..a55801e7 100644 --- a/test/python/conftest.py +++ b/test/python/conftest.py @@ -28,7 +28,7 @@ configuration.OPTIONAL.SIDELOADED_APPS_DIR = "test/python/lib_binaries/" -configuration.OPTIONAL.BACKEND_SCOPE = "function" +configuration.OPTIONAL.BACKEND_SCOPE = "class" ######################### ### CONFIGURATION END ### diff --git a/test/python/snapshots/nanos/test_ripple_swap_wrong_dest/00000.png b/test/python/snapshots/nanos/test_ripple_swap_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_ripple_swap_wrong_dest/00000.png rename to test/python/snapshots/nanos/test_ripple_swap_wrong_destination/00000.png diff --git a/test/python/snapshots/nanos/test_ripple_swap_wrong_dest/00001.png b/test/python/snapshots/nanos/test_ripple_swap_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_ripple_swap_wrong_dest/00001.png rename to test/python/snapshots/nanos/test_ripple_swap_wrong_destination/00001.png diff --git a/test/python/snapshots/nanos/test_ripple_swap_wrong_dest/00002.png b/test/python/snapshots/nanos/test_ripple_swap_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanos/test_ripple_swap_wrong_dest/00002.png rename to test/python/snapshots/nanos/test_ripple_swap_wrong_destination/00002.png diff --git a/test/python/snapshots/nanos/test_ripple_swap_wrong_dest/00003.png b/test/python/snapshots/nanos/test_ripple_swap_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_ripple_swap_wrong_dest/00003.png rename to test/python/snapshots/nanos/test_ripple_swap_wrong_destination/00003.png diff --git a/test/python/snapshots/nanos/test_ripple_swap_wrong_dest/00004.png b/test/python/snapshots/nanos/test_ripple_swap_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_ripple_swap_wrong_dest/00004.png rename to test/python/snapshots/nanos/test_ripple_swap_wrong_destination/00004.png diff --git a/test/python/snapshots/nanos/test_ripple_swap_wrong_dest/00005.png b/test/python/snapshots/nanos/test_ripple_swap_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_ripple_swap_wrong_dest/00005.png rename to test/python/snapshots/nanos/test_ripple_swap_wrong_destination/00005.png diff --git a/test/python/snapshots/nanos/test_solana_fund_cancel/00006.png b/test/python/snapshots/nanos/test_solana_fund_cancel/00006.png deleted file mode 100644 index 9c7e7049..00000000 Binary files a/test/python/snapshots/nanos/test_solana_fund_cancel/00006.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_fund_cancel/00000.png b/test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_cancel/00000.png rename to test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00000.png diff --git a/test/python/snapshots/nanos/test_solana_fund_cancel/00001.png b/test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_cancel/00001.png rename to test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00001.png diff --git a/test/python/snapshots/nanos/test_solana_fund_cancel/00002.png b/test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00002.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_cancel/00002.png rename to test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00002.png diff --git a/test/python/snapshots/nanos/test_solana_fund_cancel/00003.png b/test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_cancel/00003.png rename to test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00003.png diff --git a/test/python/snapshots/nanos/test_solana_fund_cancel/00004.png b/test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_cancel/00004.png rename to test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00004.png diff --git a/test/python/snapshots/nanos/test_solana_fund_cancel/00005.png b/test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_cancel/00005.png rename to test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00005.png diff --git a/test/python/snapshots/nanos/test_solana_fund_ok/00006.png b/test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00006.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_ok/00006.png rename to test/python/snapshots/nanos/test_solana_fund_refuse_double_sign/00006.png diff --git a/test/python/snapshots/nanos/test_solana_fund_ok/00000.png b/test/python/snapshots/nanos/test_solana_fund_valid_1/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_ok/00000.png rename to test/python/snapshots/nanos/test_solana_fund_valid_1/00000.png diff --git a/test/python/snapshots/nanos/test_solana_fund_ok/00001.png b/test/python/snapshots/nanos/test_solana_fund_valid_1/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_ok/00001.png rename to test/python/snapshots/nanos/test_solana_fund_valid_1/00001.png diff --git a/test/python/snapshots/nanos/test_solana_fund_ok/00002.png b/test/python/snapshots/nanos/test_solana_fund_valid_1/00002.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_ok/00002.png rename to test/python/snapshots/nanos/test_solana_fund_valid_1/00002.png diff --git a/test/python/snapshots/nanos/test_solana_fund_ok/00003.png b/test/python/snapshots/nanos/test_solana_fund_valid_1/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_ok/00003.png rename to test/python/snapshots/nanos/test_solana_fund_valid_1/00003.png diff --git a/test/python/snapshots/nanos/test_solana_fund_ok/00004.png b/test/python/snapshots/nanos/test_solana_fund_valid_1/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_ok/00004.png rename to test/python/snapshots/nanos/test_solana_fund_valid_1/00004.png diff --git a/test/python/snapshots/nanos/test_solana_fund_ok/00005.png b/test/python/snapshots/nanos/test_solana_fund_valid_1/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_ok/00005.png rename to test/python/snapshots/nanos/test_solana_fund_valid_1/00005.png diff --git a/test/python/snapshots/nanos/test_solana_sell_ok/00006.png b/test/python/snapshots/nanos/test_solana_fund_valid_1/00006.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_ok/00006.png rename to test/python/snapshots/nanos/test_solana_fund_valid_1/00006.png diff --git a/test/python/snapshots/nanos/test_solana_sell_cancel/00000.png b/test/python/snapshots/nanos/test_solana_fund_valid_2/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_cancel/00000.png rename to test/python/snapshots/nanos/test_solana_fund_valid_2/00000.png diff --git a/test/python/snapshots/nanos/test_solana_fund_valid_2/00001.png b/test/python/snapshots/nanos/test_solana_fund_valid_2/00001.png new file mode 100644 index 00000000..426fd9a8 Binary files /dev/null and b/test/python/snapshots/nanos/test_solana_fund_valid_2/00001.png differ diff --git a/test/python/snapshots/nanos/test_solana_fund_valid_2/00002.png b/test/python/snapshots/nanos/test_solana_fund_valid_2/00002.png new file mode 100644 index 00000000..b1b0e458 Binary files /dev/null and b/test/python/snapshots/nanos/test_solana_fund_valid_2/00002.png differ diff --git a/test/python/snapshots/nanos/test_solana_fund_valid_2/00003.png b/test/python/snapshots/nanos/test_solana_fund_valid_2/00003.png new file mode 100644 index 00000000..3a699dc3 Binary files /dev/null and b/test/python/snapshots/nanos/test_solana_fund_valid_2/00003.png differ diff --git a/test/python/snapshots/nanos/test_solana_fund_valid_2/00004.png b/test/python/snapshots/nanos/test_solana_fund_valid_2/00004.png new file mode 100644 index 00000000..2bd082bc Binary files /dev/null and b/test/python/snapshots/nanos/test_solana_fund_valid_2/00004.png differ diff --git a/test/python/snapshots/nanos/test_solana_sell_cancel/00005.png b/test/python/snapshots/nanos/test_solana_fund_valid_2/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_cancel/00005.png rename to test/python/snapshots/nanos/test_solana_fund_valid_2/00005.png diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00006.png b/test/python/snapshots/nanos/test_solana_fund_valid_2/00006.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00006.png rename to test/python/snapshots/nanos/test_solana_fund_valid_2/00006.png diff --git a/test/python/snapshots/nanos/test_solana_sell_cancel/00006.png b/test/python/snapshots/nanos/test_solana_sell_cancel/00006.png deleted file mode 100644 index 9c7e7049..00000000 Binary files a/test/python/snapshots/nanos/test_solana_sell_cancel/00006.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_sell_ok/00000.png b/test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_ok/00000.png rename to test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00000.png diff --git a/test/python/snapshots/nanos/test_solana_sell_cancel/00001.png b/test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_cancel/00001.png rename to test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00001.png diff --git a/test/python/snapshots/nanos/test_solana_sell_cancel/00002.png b/test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00002.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_cancel/00002.png rename to test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00002.png diff --git a/test/python/snapshots/nanos/test_solana_sell_cancel/00003.png b/test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_cancel/00003.png rename to test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00003.png diff --git a/test/python/snapshots/nanos/test_solana_sell_cancel/00004.png b/test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_cancel/00004.png rename to test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00004.png diff --git a/test/python/snapshots/nanos/test_solana_sell_ok/00005.png b/test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_ok/00005.png rename to test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00005.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_cancel/00006.png b/test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00006.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_cancel/00006.png rename to test/python/snapshots/nanos/test_solana_sell_refuse_double_sign/00006.png diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00000.png b/test/python/snapshots/nanos/test_solana_sell_valid_1/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00000.png rename to test/python/snapshots/nanos/test_solana_sell_valid_1/00000.png diff --git a/test/python/snapshots/nanos/test_solana_sell_ok/00001.png b/test/python/snapshots/nanos/test_solana_sell_valid_1/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_ok/00001.png rename to test/python/snapshots/nanos/test_solana_sell_valid_1/00001.png diff --git a/test/python/snapshots/nanos/test_solana_sell_ok/00002.png b/test/python/snapshots/nanos/test_solana_sell_valid_1/00002.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_ok/00002.png rename to test/python/snapshots/nanos/test_solana_sell_valid_1/00002.png diff --git a/test/python/snapshots/nanos/test_solana_sell_ok/00003.png b/test/python/snapshots/nanos/test_solana_sell_valid_1/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_ok/00003.png rename to test/python/snapshots/nanos/test_solana_sell_valid_1/00003.png diff --git a/test/python/snapshots/nanos/test_solana_sell_ok/00004.png b/test/python/snapshots/nanos/test_solana_sell_valid_1/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_ok/00004.png rename to test/python/snapshots/nanos/test_solana_sell_valid_1/00004.png diff --git a/test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00005.png b/test/python/snapshots/nanos/test_solana_sell_valid_1/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00005.png rename to test/python/snapshots/nanos/test_solana_sell_valid_1/00005.png diff --git a/test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00006.png b/test/python/snapshots/nanos/test_solana_sell_valid_1/00006.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00006.png rename to test/python/snapshots/nanos/test_solana_sell_valid_1/00006.png diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_ok/00000.png b/test/python/snapshots/nanos/test_solana_sell_valid_2/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_recipient_ok/00000.png rename to test/python/snapshots/nanos/test_solana_sell_valid_2/00000.png diff --git a/test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00001.png b/test/python/snapshots/nanos/test_solana_sell_valid_2/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00001.png rename to test/python/snapshots/nanos/test_solana_sell_valid_2/00001.png diff --git a/test/python/snapshots/nanos/test_solana_sell_valid_2/00002.png b/test/python/snapshots/nanos/test_solana_sell_valid_2/00002.png new file mode 100644 index 00000000..b1b0e458 Binary files /dev/null and b/test/python/snapshots/nanos/test_solana_sell_valid_2/00002.png differ diff --git a/test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00003.png b/test/python/snapshots/nanos/test_solana_sell_valid_2/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00003.png rename to test/python/snapshots/nanos/test_solana_sell_valid_2/00003.png diff --git a/test/python/snapshots/nanos/test_solana_sell_valid_2/00004.png b/test/python/snapshots/nanos/test_solana_sell_valid_2/00004.png new file mode 100644 index 00000000..2bd082bc Binary files /dev/null and b/test/python/snapshots/nanos/test_solana_sell_valid_2/00004.png differ diff --git a/test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00005.png b/test/python/snapshots/nanos/test_solana_sell_valid_2/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00005.png rename to test/python/snapshots/nanos/test_solana_sell_valid_2/00005.png diff --git a/test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00006.png b/test/python/snapshots/nanos/test_solana_sell_valid_2/00006.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00006.png rename to test/python/snapshots/nanos/test_solana_sell_valid_2/00006.png diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00001.png b/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00001.png deleted file mode 100644 index 57e07235..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00001.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00002.png b/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00002.png deleted file mode 100644 index 2222a836..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00003.png b/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00003.png deleted file mode 100644 index 25b667a8..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00003.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00005.png b/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00005.png deleted file mode 100644 index 9c7e7049..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00005.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_ok/00001.png b/test/python/snapshots/nanos/test_solana_swap_recipient_ok/00001.png deleted file mode 100644 index 57e07235..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_recipient_ok/00001.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_ok/00002.png b/test/python/snapshots/nanos/test_solana_swap_recipient_ok/00002.png deleted file mode 100644 index 2222a836..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_recipient_ok/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_ok/00003.png b/test/python/snapshots/nanos/test_solana_swap_recipient_ok/00003.png deleted file mode 100644 index 25b667a8..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_recipient_ok/00003.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_cancel/00000.png b/test/python/snapshots/nanos/test_solana_swap_refuse_double_sign/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_cancel/00000.png rename to test/python/snapshots/nanos/test_solana_swap_refuse_double_sign/00000.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_cancel/00001.png b/test/python/snapshots/nanos/test_solana_swap_refuse_double_sign/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_cancel/00001.png rename to test/python/snapshots/nanos/test_solana_swap_refuse_double_sign/00001.png diff --git a/test/python/snapshots/nanos/test_stellar_swap_wrong_dest/00002.png b/test/python/snapshots/nanos/test_solana_swap_refuse_double_sign/00002.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_swap_wrong_dest/00002.png rename to test/python/snapshots/nanos/test_solana_swap_refuse_double_sign/00002.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_cancel/00003.png b/test/python/snapshots/nanos/test_solana_swap_refuse_double_sign/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_cancel/00003.png rename to test/python/snapshots/nanos/test_solana_swap_refuse_double_sign/00003.png diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00004.png b/test/python/snapshots/nanos/test_solana_swap_refuse_double_sign/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_recipient_cancel/00004.png rename to test/python/snapshots/nanos/test_solana_swap_refuse_double_sign/00004.png diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_ok/00005.png b/test/python/snapshots/nanos/test_solana_swap_refuse_double_sign/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_recipient_ok/00005.png rename to test/python/snapshots/nanos/test_solana_swap_refuse_double_sign/00005.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_cancel/00002.png b/test/python/snapshots/nanos/test_solana_swap_sender_cancel/00002.png deleted file mode 100644 index 25197fbc..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_sender_cancel/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_cancel/00005.png b/test/python/snapshots/nanos/test_solana_swap_sender_cancel/00005.png deleted file mode 100644 index 9c7e7049..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_sender_cancel/00005.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00002.png b/test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00002.png deleted file mode 100644 index 25197fbc..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_ok/00002.png b/test/python/snapshots/nanos/test_solana_swap_sender_ok/00002.png deleted file mode 100644 index 25197fbc..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_sender_ok/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00002.png b/test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00002.png deleted file mode 100644 index 25197fbc..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00001.png b/test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00001.png deleted file mode 100644 index b328d0cb..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00001.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00002.png b/test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00002.png deleted file mode 100644 index 25197fbc..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00003.png b/test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00003.png deleted file mode 100644 index 4a4f58ac..00000000 Binary files a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00003.png and /dev/null differ diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00000.png b/test/python/snapshots/nanos/test_solana_swap_valid_1/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00000.png rename to test/python/snapshots/nanos/test_solana_swap_valid_1/00000.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00001.png b/test/python/snapshots/nanos/test_solana_swap_valid_1/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00001.png rename to test/python/snapshots/nanos/test_solana_swap_valid_1/00001.png diff --git a/test/python/snapshots/nanos/test_tezos_swap_wrong_dest/00002.png b/test/python/snapshots/nanos/test_solana_swap_valid_1/00002.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_swap_wrong_dest/00002.png rename to test/python/snapshots/nanos/test_solana_swap_valid_1/00002.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00003.png b/test/python/snapshots/nanos/test_solana_swap_valid_1/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00003.png rename to test/python/snapshots/nanos/test_solana_swap_valid_1/00003.png diff --git a/test/python/snapshots/nanos/test_solana_swap_recipient_ok/00004.png b/test/python/snapshots/nanos/test_solana_swap_valid_1/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_recipient_ok/00004.png rename to test/python/snapshots/nanos/test_solana_swap_valid_1/00004.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00005.png b/test/python/snapshots/nanos/test_solana_swap_valid_1/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00005.png rename to test/python/snapshots/nanos/test_solana_swap_valid_1/00005.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_ok/00000.png b/test/python/snapshots/nanos/test_solana_swap_valid_2/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_ok/00000.png rename to test/python/snapshots/nanos/test_solana_swap_valid_2/00000.png diff --git a/test/python/snapshots/nanos/test_solana_swap_valid_2/00001.png b/test/python/snapshots/nanos/test_solana_swap_valid_2/00001.png new file mode 100644 index 00000000..b1b0e458 Binary files /dev/null and b/test/python/snapshots/nanos/test_solana_swap_valid_2/00001.png differ diff --git a/test/python/snapshots/nanos/test_solana_swap_valid_2/00002.png b/test/python/snapshots/nanos/test_solana_swap_valid_2/00002.png new file mode 100644 index 00000000..b744ccf6 Binary files /dev/null and b/test/python/snapshots/nanos/test_solana_swap_valid_2/00002.png differ diff --git a/test/python/snapshots/nanos/test_solana_swap_valid_2/00003.png b/test/python/snapshots/nanos/test_solana_swap_valid_2/00003.png new file mode 100644 index 00000000..2bd082bc Binary files /dev/null and b/test/python/snapshots/nanos/test_solana_swap_valid_2/00003.png differ diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_cancel/00004.png b/test/python/snapshots/nanos/test_solana_swap_valid_2/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_cancel/00004.png rename to test/python/snapshots/nanos/test_solana_swap_valid_2/00004.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_ok/00005.png b/test/python/snapshots/nanos/test_solana_swap_valid_2/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_ok/00005.png rename to test/python/snapshots/nanos/test_solana_swap_valid_2/00005.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00000.png b/test/python/snapshots/nanos/test_solana_swap_wrong_amount/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00000.png rename to test/python/snapshots/nanos/test_solana_swap_wrong_amount/00000.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_ok/00001.png b/test/python/snapshots/nanos/test_solana_swap_wrong_amount/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_ok/00001.png rename to test/python/snapshots/nanos/test_solana_swap_wrong_amount/00001.png diff --git a/test/python/snapshots/nanos/test_solana_swap_wrong_amount/00002.png b/test/python/snapshots/nanos/test_solana_swap_wrong_amount/00002.png new file mode 100644 index 00000000..b744ccf6 Binary files /dev/null and b/test/python/snapshots/nanos/test_solana_swap_wrong_amount/00002.png differ diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_ok/00003.png b/test/python/snapshots/nanos/test_solana_swap_wrong_amount/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_ok/00003.png rename to test/python/snapshots/nanos/test_solana_swap_wrong_amount/00003.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00004.png b/test/python/snapshots/nanos/test_solana_swap_wrong_amount/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_double_sign/00004.png rename to test/python/snapshots/nanos/test_solana_swap_wrong_amount/00004.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00005.png b/test/python/snapshots/nanos/test_solana_swap_wrong_amount/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00005.png rename to test/python/snapshots/nanos/test_solana_swap_wrong_amount/00005.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00000.png b/test/python/snapshots/nanos/test_solana_swap_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00000.png rename to test/python/snapshots/nanos/test_solana_swap_wrong_destination/00000.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00001.png b/test/python/snapshots/nanos/test_solana_swap_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00001.png rename to test/python/snapshots/nanos/test_solana_swap_wrong_destination/00001.png diff --git a/test/python/snapshots/nanos/test_solana_swap_wrong_destination/00002.png b/test/python/snapshots/nanos/test_solana_swap_wrong_destination/00002.png new file mode 100644 index 00000000..b744ccf6 Binary files /dev/null and b/test/python/snapshots/nanos/test_solana_swap_wrong_destination/00002.png differ diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00003.png b/test/python/snapshots/nanos/test_solana_swap_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00003.png rename to test/python/snapshots/nanos/test_solana_swap_wrong_destination/00003.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_ok/00004.png b/test/python/snapshots/nanos/test_solana_swap_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_ok/00004.png rename to test/python/snapshots/nanos/test_solana_swap_wrong_destination/00004.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00005.png b/test/python/snapshots/nanos/test_solana_swap_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00005.png rename to test/python/snapshots/nanos/test_solana_swap_wrong_destination/00005.png diff --git a/test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00000.png b/test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00000.png rename to test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00000.png diff --git a/test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00001.png b/test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00001.png rename to test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00001.png diff --git a/test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00002.png b/test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00002.png rename to test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00002.png diff --git a/test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00003.png b/test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00003.png rename to test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00003.png diff --git a/test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00004.png b/test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_fund_wrong_dest/00004.png rename to test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00004.png diff --git a/test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00005.png b/test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00005.png rename to test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00005.png diff --git a/test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00006.png b/test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00006.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00006.png rename to test/python/snapshots/nanos/test_stellar_fund_wrong_destination/00006.png diff --git a/test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00000.png b/test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00000.png rename to test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00000.png diff --git a/test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00001.png b/test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00001.png rename to test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00001.png diff --git a/test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00002.png b/test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00002.png rename to test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00002.png diff --git a/test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00003.png b/test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00003.png rename to test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00003.png diff --git a/test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00004.png b/test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_sell_wrong_dest/00004.png rename to test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00004.png diff --git a/test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00005.png b/test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00005.png rename to test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00005.png diff --git a/test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00006.png b/test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00006.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00006.png rename to test/python/snapshots/nanos/test_stellar_sell_wrong_destination/00006.png diff --git a/test/python/snapshots/nanos/test_stellar_swap_wrong_dest/00000.png b/test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_swap_wrong_dest/00000.png rename to test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00000.png diff --git a/test/python/snapshots/nanos/test_stellar_swap_wrong_dest/00001.png b/test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_swap_wrong_dest/00001.png rename to test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00001.png diff --git a/test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00002.png b/test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00002.png new file mode 100644 index 00000000..b744ccf6 Binary files /dev/null and b/test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00002.png differ diff --git a/test/python/snapshots/nanos/test_stellar_swap_wrong_dest/00003.png b/test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_swap_wrong_dest/00003.png rename to test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00003.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00004.png b/test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_wrong_amount/00004.png rename to test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00004.png diff --git a/test/python/snapshots/nanos/test_stellar_swap_wrong_dest/00005.png b/test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_swap_wrong_dest/00005.png rename to test/python/snapshots/nanos/test_stellar_swap_wrong_destination/00005.png diff --git a/test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00000.png b/test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00000.png rename to test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00000.png diff --git a/test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00001.png b/test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00001.png rename to test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00001.png diff --git a/test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00002.png b/test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00002.png rename to test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00002.png diff --git a/test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00003.png b/test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00003.png rename to test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00003.png diff --git a/test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00004.png b/test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_fund_wrong_dest/00004.png rename to test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00004.png diff --git a/test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00004.png b/test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_swap_sender_wrong_destination/00004.png rename to test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00005.png diff --git a/test/python/snapshots/nanos/test_solana_fund_cancel/00007.png b/test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00006.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_fund_cancel/00007.png rename to test/python/snapshots/nanos/test_tezos_fund_wrong_destination/00006.png diff --git a/test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00000.png b/test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00000.png rename to test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00000.png diff --git a/test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00001.png b/test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00001.png new file mode 100644 index 00000000..ae0a2947 Binary files /dev/null and b/test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00001.png differ diff --git a/test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00002.png b/test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00002.png rename to test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00002.png diff --git a/test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00003.png b/test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00003.png new file mode 100644 index 00000000..01f7f182 Binary files /dev/null and b/test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00003.png differ diff --git a/test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00004.png b/test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_sell_wrong_dest/00004.png rename to test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00004.png diff --git a/test/python/snapshots/nanos/test_stellar_swap_wrong_dest/00004.png b/test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_stellar_swap_wrong_dest/00004.png rename to test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00005.png diff --git a/test/python/snapshots/nanos/test_solana_sell_cancel/00007.png b/test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00006.png similarity index 100% rename from test/python/snapshots/nanos/test_solana_sell_cancel/00007.png rename to test/python/snapshots/nanos/test_tezos_sell_wrong_destination/00006.png diff --git a/test/python/snapshots/nanos/test_tezos_swap_wrong_dest/00000.png b/test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_swap_wrong_dest/00000.png rename to test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00000.png diff --git a/test/python/snapshots/nanos/test_tezos_swap_wrong_dest/00001.png b/test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_swap_wrong_dest/00001.png rename to test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00001.png diff --git a/test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00002.png b/test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00002.png new file mode 100644 index 00000000..b744ccf6 Binary files /dev/null and b/test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00002.png differ diff --git a/test/python/snapshots/nanos/test_tezos_swap_wrong_dest/00003.png b/test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_swap_wrong_dest/00003.png rename to test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00003.png diff --git a/test/python/snapshots/nanos/test_tezos_swap_wrong_dest/00004.png b/test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_swap_wrong_dest/00004.png rename to test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00004.png diff --git a/test/python/snapshots/nanos/test_tezos_swap_wrong_dest/00005.png b/test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanos/test_tezos_swap_wrong_dest/00005.png rename to test/python/snapshots/nanos/test_tezos_swap_wrong_destination/00005.png diff --git a/test/python/snapshots/nanosp/test_ripple_swap_wrong_dest/00000.png b/test/python/snapshots/nanosp/test_ripple_swap_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_ripple_swap_wrong_dest/00000.png rename to test/python/snapshots/nanosp/test_ripple_swap_wrong_destination/00000.png diff --git a/test/python/snapshots/nanosp/test_ripple_swap_wrong_dest/00001.png b/test/python/snapshots/nanosp/test_ripple_swap_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_ripple_swap_wrong_dest/00001.png rename to test/python/snapshots/nanosp/test_ripple_swap_wrong_destination/00001.png diff --git a/test/python/snapshots/nanosp/test_ripple_swap_wrong_dest/00002.png b/test/python/snapshots/nanosp/test_ripple_swap_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanosp/test_ripple_swap_wrong_dest/00002.png rename to test/python/snapshots/nanosp/test_ripple_swap_wrong_destination/00002.png diff --git a/test/python/snapshots/nanosp/test_ripple_swap_wrong_dest/00003.png b/test/python/snapshots/nanosp/test_ripple_swap_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_ripple_swap_wrong_dest/00003.png rename to test/python/snapshots/nanosp/test_ripple_swap_wrong_destination/00003.png diff --git a/test/python/snapshots/nanosp/test_ripple_swap_wrong_dest/00004.png b/test/python/snapshots/nanosp/test_ripple_swap_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_ripple_swap_wrong_dest/00004.png rename to test/python/snapshots/nanosp/test_ripple_swap_wrong_destination/00004.png diff --git a/test/python/snapshots/nanosp/test_ripple_swap_wrong_dest/00005.png b/test/python/snapshots/nanosp/test_ripple_swap_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_ripple_swap_wrong_dest/00005.png rename to test/python/snapshots/nanosp/test_ripple_swap_wrong_destination/00005.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_cancel/00006.png b/test/python/snapshots/nanosp/test_solana_fund_cancel/00006.png deleted file mode 100644 index c9222461..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_fund_cancel/00006.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_fund_cancel/00000.png b/test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_cancel/00000.png rename to test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00000.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_cancel/00001.png b/test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_cancel/00001.png rename to test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00001.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_cancel/00002.png b/test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00002.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_cancel/00002.png rename to test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00002.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_cancel/00003.png b/test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_cancel/00003.png rename to test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00003.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_cancel/00004.png b/test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_cancel/00004.png rename to test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00004.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_cancel/00005.png b/test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_cancel/00005.png rename to test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00005.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_ok/00006.png b/test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00006.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_ok/00006.png rename to test/python/snapshots/nanosp/test_solana_fund_refuse_double_sign/00006.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_ok/00000.png b/test/python/snapshots/nanosp/test_solana_fund_valid_1/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_ok/00000.png rename to test/python/snapshots/nanosp/test_solana_fund_valid_1/00000.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_ok/00001.png b/test/python/snapshots/nanosp/test_solana_fund_valid_1/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_ok/00001.png rename to test/python/snapshots/nanosp/test_solana_fund_valid_1/00001.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_ok/00002.png b/test/python/snapshots/nanosp/test_solana_fund_valid_1/00002.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_ok/00002.png rename to test/python/snapshots/nanosp/test_solana_fund_valid_1/00002.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_ok/00003.png b/test/python/snapshots/nanosp/test_solana_fund_valid_1/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_ok/00003.png rename to test/python/snapshots/nanosp/test_solana_fund_valid_1/00003.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_ok/00004.png b/test/python/snapshots/nanosp/test_solana_fund_valid_1/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_ok/00004.png rename to test/python/snapshots/nanosp/test_solana_fund_valid_1/00004.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_ok/00005.png b/test/python/snapshots/nanosp/test_solana_fund_valid_1/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_ok/00005.png rename to test/python/snapshots/nanosp/test_solana_fund_valid_1/00005.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_ok/00006.png b/test/python/snapshots/nanosp/test_solana_fund_valid_1/00006.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_ok/00006.png rename to test/python/snapshots/nanosp/test_solana_fund_valid_1/00006.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_cancel/00000.png b/test/python/snapshots/nanosp/test_solana_fund_valid_2/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_cancel/00000.png rename to test/python/snapshots/nanosp/test_solana_fund_valid_2/00000.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_valid_2/00001.png b/test/python/snapshots/nanosp/test_solana_fund_valid_2/00001.png new file mode 100644 index 00000000..8a381d03 Binary files /dev/null and b/test/python/snapshots/nanosp/test_solana_fund_valid_2/00001.png differ diff --git a/test/python/snapshots/nanosp/test_solana_fund_valid_2/00002.png b/test/python/snapshots/nanosp/test_solana_fund_valid_2/00002.png new file mode 100644 index 00000000..d6d796d2 Binary files /dev/null and b/test/python/snapshots/nanosp/test_solana_fund_valid_2/00002.png differ diff --git a/test/python/snapshots/nanosp/test_solana_fund_valid_2/00003.png b/test/python/snapshots/nanosp/test_solana_fund_valid_2/00003.png new file mode 100644 index 00000000..d8f5e38c Binary files /dev/null and b/test/python/snapshots/nanosp/test_solana_fund_valid_2/00003.png differ diff --git a/test/python/snapshots/nanosp/test_solana_fund_valid_2/00004.png b/test/python/snapshots/nanosp/test_solana_fund_valid_2/00004.png new file mode 100644 index 00000000..a0671c45 Binary files /dev/null and b/test/python/snapshots/nanosp/test_solana_fund_valid_2/00004.png differ diff --git a/test/python/snapshots/nanosp/test_solana_sell_cancel/00005.png b/test/python/snapshots/nanosp/test_solana_fund_valid_2/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_cancel/00005.png rename to test/python/snapshots/nanosp/test_solana_fund_valid_2/00005.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00006.png b/test/python/snapshots/nanosp/test_solana_fund_valid_2/00006.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00006.png rename to test/python/snapshots/nanosp/test_solana_fund_valid_2/00006.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_cancel/00006.png b/test/python/snapshots/nanosp/test_solana_sell_cancel/00006.png deleted file mode 100644 index c9222461..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_sell_cancel/00006.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_sell_ok/00000.png b/test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_ok/00000.png rename to test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00000.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_cancel/00001.png b/test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_cancel/00001.png rename to test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00001.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_cancel/00002.png b/test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00002.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_cancel/00002.png rename to test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00002.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_cancel/00003.png b/test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_cancel/00003.png rename to test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00003.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_cancel/00004.png b/test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_cancel/00004.png rename to test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00004.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_ok/00005.png b/test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_ok/00005.png rename to test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00005.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00006.png b/test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00006.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00006.png rename to test/python/snapshots/nanosp/test_solana_sell_refuse_double_sign/00006.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00000.png b/test/python/snapshots/nanosp/test_solana_sell_valid_1/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00000.png rename to test/python/snapshots/nanosp/test_solana_sell_valid_1/00000.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_ok/00001.png b/test/python/snapshots/nanosp/test_solana_sell_valid_1/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_ok/00001.png rename to test/python/snapshots/nanosp/test_solana_sell_valid_1/00001.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_ok/00002.png b/test/python/snapshots/nanosp/test_solana_sell_valid_1/00002.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_ok/00002.png rename to test/python/snapshots/nanosp/test_solana_sell_valid_1/00002.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_ok/00003.png b/test/python/snapshots/nanosp/test_solana_sell_valid_1/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_ok/00003.png rename to test/python/snapshots/nanosp/test_solana_sell_valid_1/00003.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_ok/00004.png b/test/python/snapshots/nanosp/test_solana_sell_valid_1/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_ok/00004.png rename to test/python/snapshots/nanosp/test_solana_sell_valid_1/00004.png diff --git a/test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00005.png b/test/python/snapshots/nanosp/test_solana_sell_valid_1/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00005.png rename to test/python/snapshots/nanosp/test_solana_sell_valid_1/00005.png diff --git a/test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00006.png b/test/python/snapshots/nanosp/test_solana_sell_valid_1/00006.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00006.png rename to test/python/snapshots/nanosp/test_solana_sell_valid_1/00006.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00000.png b/test/python/snapshots/nanosp/test_solana_sell_valid_2/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00000.png rename to test/python/snapshots/nanosp/test_solana_sell_valid_2/00000.png diff --git a/test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00001.png b/test/python/snapshots/nanosp/test_solana_sell_valid_2/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00001.png rename to test/python/snapshots/nanosp/test_solana_sell_valid_2/00001.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_valid_2/00002.png b/test/python/snapshots/nanosp/test_solana_sell_valid_2/00002.png new file mode 100644 index 00000000..d6d796d2 Binary files /dev/null and b/test/python/snapshots/nanosp/test_solana_sell_valid_2/00002.png differ diff --git a/test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00003.png b/test/python/snapshots/nanosp/test_solana_sell_valid_2/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00003.png rename to test/python/snapshots/nanosp/test_solana_sell_valid_2/00003.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_valid_2/00004.png b/test/python/snapshots/nanosp/test_solana_sell_valid_2/00004.png new file mode 100644 index 00000000..a0671c45 Binary files /dev/null and b/test/python/snapshots/nanosp/test_solana_sell_valid_2/00004.png differ diff --git a/test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00005.png b/test/python/snapshots/nanosp/test_solana_sell_valid_2/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00005.png rename to test/python/snapshots/nanosp/test_solana_sell_valid_2/00005.png diff --git a/test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00006.png b/test/python/snapshots/nanosp/test_solana_sell_valid_2/00006.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00006.png rename to test/python/snapshots/nanosp/test_solana_sell_valid_2/00006.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00001.png b/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00001.png deleted file mode 100644 index 6c5483cb..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00001.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00002.png b/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00002.png deleted file mode 100644 index 0ab84580..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00003.png b/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00003.png deleted file mode 100644 index 95580750..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00003.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00005.png b/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00005.png deleted file mode 100644 index c9222461..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00005.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00001.png b/test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00001.png deleted file mode 100644 index 6c5483cb..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00001.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00002.png b/test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00002.png deleted file mode 100644 index 0ab84580..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00003.png b/test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00003.png deleted file mode 100644 index 95580750..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00003.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00000.png b/test/python/snapshots/nanosp/test_solana_swap_refuse_double_sign/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00000.png rename to test/python/snapshots/nanosp/test_solana_swap_refuse_double_sign/00000.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00001.png b/test/python/snapshots/nanosp/test_solana_swap_refuse_double_sign/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00001.png rename to test/python/snapshots/nanosp/test_solana_swap_refuse_double_sign/00001.png diff --git a/test/python/snapshots/nanosp/test_stellar_swap_wrong_dest/00002.png b/test/python/snapshots/nanosp/test_solana_swap_refuse_double_sign/00002.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_swap_wrong_dest/00002.png rename to test/python/snapshots/nanosp/test_solana_swap_refuse_double_sign/00002.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00003.png b/test/python/snapshots/nanosp/test_solana_swap_refuse_double_sign/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00003.png rename to test/python/snapshots/nanosp/test_solana_swap_refuse_double_sign/00003.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00004.png b/test/python/snapshots/nanosp/test_solana_swap_refuse_double_sign/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_recipient_cancel/00004.png rename to test/python/snapshots/nanosp/test_solana_swap_refuse_double_sign/00004.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00005.png b/test/python/snapshots/nanosp/test_solana_swap_refuse_double_sign/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00005.png rename to test/python/snapshots/nanosp/test_solana_swap_refuse_double_sign/00005.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00002.png b/test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00002.png deleted file mode 100644 index cf33e5fc..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00005.png b/test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00005.png deleted file mode 100644 index c9222461..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00005.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00002.png b/test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00002.png deleted file mode 100644 index cf33e5fc..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_ok/00002.png b/test/python/snapshots/nanosp/test_solana_swap_sender_ok/00002.png deleted file mode 100644 index cf33e5fc..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_sender_ok/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00002.png b/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00002.png deleted file mode 100644 index cf33e5fc..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00001.png b/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00001.png deleted file mode 100644 index fc19bb25..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00001.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00002.png b/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00002.png deleted file mode 100644 index cf33e5fc..00000000 Binary files a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00000.png b/test/python/snapshots/nanosp/test_solana_swap_valid_1/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00000.png rename to test/python/snapshots/nanosp/test_solana_swap_valid_1/00000.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00001.png b/test/python/snapshots/nanosp/test_solana_swap_valid_1/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00001.png rename to test/python/snapshots/nanosp/test_solana_swap_valid_1/00001.png diff --git a/test/python/snapshots/nanosp/test_tezos_swap_wrong_dest/00002.png b/test/python/snapshots/nanosp/test_solana_swap_valid_1/00002.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_swap_wrong_dest/00002.png rename to test/python/snapshots/nanosp/test_solana_swap_valid_1/00002.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00003.png b/test/python/snapshots/nanosp/test_solana_swap_valid_1/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00003.png rename to test/python/snapshots/nanosp/test_solana_swap_valid_1/00003.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00004.png b/test/python/snapshots/nanosp/test_solana_swap_valid_1/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_recipient_ok/00004.png rename to test/python/snapshots/nanosp/test_solana_swap_valid_1/00004.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00005.png b/test/python/snapshots/nanosp/test_solana_swap_valid_1/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00005.png rename to test/python/snapshots/nanosp/test_solana_swap_valid_1/00005.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_ok/00000.png b/test/python/snapshots/nanosp/test_solana_swap_valid_2/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_ok/00000.png rename to test/python/snapshots/nanosp/test_solana_swap_valid_2/00000.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_valid_2/00001.png b/test/python/snapshots/nanosp/test_solana_swap_valid_2/00001.png new file mode 100644 index 00000000..d6d796d2 Binary files /dev/null and b/test/python/snapshots/nanosp/test_solana_swap_valid_2/00001.png differ diff --git a/test/python/snapshots/nanox/test_ripple_swap_wrong_dest/00002.png b/test/python/snapshots/nanosp/test_solana_swap_valid_2/00002.png similarity index 100% rename from test/python/snapshots/nanox/test_ripple_swap_wrong_dest/00002.png rename to test/python/snapshots/nanosp/test_solana_swap_valid_2/00002.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_valid_2/00003.png b/test/python/snapshots/nanosp/test_solana_swap_valid_2/00003.png new file mode 100644 index 00000000..a0671c45 Binary files /dev/null and b/test/python/snapshots/nanosp/test_solana_swap_valid_2/00003.png differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00004.png b/test/python/snapshots/nanosp/test_solana_swap_valid_2/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_cancel/00004.png rename to test/python/snapshots/nanosp/test_solana_swap_valid_2/00004.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_ok/00005.png b/test/python/snapshots/nanosp/test_solana_swap_valid_2/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_ok/00005.png rename to test/python/snapshots/nanosp/test_solana_swap_valid_2/00005.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00000.png b/test/python/snapshots/nanosp/test_solana_swap_wrong_amount/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00000.png rename to test/python/snapshots/nanosp/test_solana_swap_wrong_amount/00000.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_ok/00001.png b/test/python/snapshots/nanosp/test_solana_swap_wrong_amount/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_ok/00001.png rename to test/python/snapshots/nanosp/test_solana_swap_wrong_amount/00001.png diff --git a/test/python/snapshots/nanox/test_stellar_swap_wrong_dest/00002.png b/test/python/snapshots/nanosp/test_solana_swap_wrong_amount/00002.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_swap_wrong_dest/00002.png rename to test/python/snapshots/nanosp/test_solana_swap_wrong_amount/00002.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_ok/00003.png b/test/python/snapshots/nanosp/test_solana_swap_wrong_amount/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_ok/00003.png rename to test/python/snapshots/nanosp/test_solana_swap_wrong_amount/00003.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00004.png b/test/python/snapshots/nanosp/test_solana_swap_wrong_amount/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_double_sign/00004.png rename to test/python/snapshots/nanosp/test_solana_swap_wrong_amount/00004.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00005.png b/test/python/snapshots/nanosp/test_solana_swap_wrong_amount/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00005.png rename to test/python/snapshots/nanosp/test_solana_swap_wrong_amount/00005.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00000.png b/test/python/snapshots/nanosp/test_solana_swap_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00000.png rename to test/python/snapshots/nanosp/test_solana_swap_wrong_destination/00000.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00001.png b/test/python/snapshots/nanosp/test_solana_swap_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00001.png rename to test/python/snapshots/nanosp/test_solana_swap_wrong_destination/00001.png diff --git a/test/python/snapshots/nanox/test_tezos_swap_wrong_dest/00002.png b/test/python/snapshots/nanosp/test_solana_swap_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_swap_wrong_dest/00002.png rename to test/python/snapshots/nanosp/test_solana_swap_wrong_destination/00002.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00003.png b/test/python/snapshots/nanosp/test_solana_swap_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00003.png rename to test/python/snapshots/nanosp/test_solana_swap_wrong_destination/00003.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_ok/00004.png b/test/python/snapshots/nanosp/test_solana_swap_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_ok/00004.png rename to test/python/snapshots/nanosp/test_solana_swap_wrong_destination/00004.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00005.png b/test/python/snapshots/nanosp/test_solana_swap_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00005.png rename to test/python/snapshots/nanosp/test_solana_swap_wrong_destination/00005.png diff --git a/test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00000.png b/test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00000.png rename to test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00000.png diff --git a/test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00001.png b/test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00001.png rename to test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00001.png diff --git a/test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00002.png b/test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00002.png rename to test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00002.png diff --git a/test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00003.png b/test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00003.png rename to test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00003.png diff --git a/test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00004.png b/test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_fund_wrong_dest/00004.png rename to test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00004.png diff --git a/test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00005.png b/test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00005.png rename to test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00005.png diff --git a/test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00006.png b/test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00006.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00006.png rename to test/python/snapshots/nanosp/test_stellar_fund_wrong_destination/00006.png diff --git a/test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00000.png b/test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00000.png rename to test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00000.png diff --git a/test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00001.png b/test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00001.png rename to test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00001.png diff --git a/test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00002.png b/test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00002.png rename to test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00002.png diff --git a/test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00003.png b/test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00003.png rename to test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00003.png diff --git a/test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00004.png b/test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_sell_wrong_dest/00004.png rename to test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00004.png diff --git a/test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00005.png b/test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00005.png rename to test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00005.png diff --git a/test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00006.png b/test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00006.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00006.png rename to test/python/snapshots/nanosp/test_stellar_sell_wrong_destination/00006.png diff --git a/test/python/snapshots/nanosp/test_stellar_swap_wrong_dest/00000.png b/test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_swap_wrong_dest/00000.png rename to test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00000.png diff --git a/test/python/snapshots/nanosp/test_stellar_swap_wrong_dest/00001.png b/test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_swap_wrong_dest/00001.png rename to test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00001.png diff --git a/test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00002.png b/test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00002.png new file mode 100644 index 00000000..2d2fc70b Binary files /dev/null and b/test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00002.png differ diff --git a/test/python/snapshots/nanosp/test_stellar_swap_wrong_dest/00003.png b/test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_swap_wrong_dest/00003.png rename to test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00003.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00004.png b/test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_wrong_amount/00004.png rename to test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00004.png diff --git a/test/python/snapshots/nanosp/test_stellar_swap_wrong_dest/00005.png b/test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_swap_wrong_dest/00005.png rename to test/python/snapshots/nanosp/test_stellar_swap_wrong_destination/00005.png diff --git a/test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00000.png b/test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00000.png rename to test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00000.png diff --git a/test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00001.png b/test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00001.png rename to test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00001.png diff --git a/test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00002.png b/test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00002.png rename to test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00002.png diff --git a/test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00003.png b/test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00003.png rename to test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00003.png diff --git a/test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00004.png b/test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_fund_wrong_dest/00004.png rename to test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00004.png diff --git a/test/python/snapshots/nanox/test_solana_fund_cancel/00005.png b/test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_cancel/00005.png rename to test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00005.png diff --git a/test/python/snapshots/nanosp/test_solana_fund_cancel/00007.png b/test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00006.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_fund_cancel/00007.png rename to test/python/snapshots/nanosp/test_tezos_fund_wrong_destination/00006.png diff --git a/test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00000.png b/test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00000.png rename to test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00000.png diff --git a/test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00001.png b/test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00001.png new file mode 100644 index 00000000..a7dec8ea Binary files /dev/null and b/test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00001.png differ diff --git a/test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00002.png b/test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00002.png rename to test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00002.png diff --git a/test/python/snapshots/nanox/test_solana_sell_cancel/00003.png b/test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_cancel/00003.png rename to test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00003.png diff --git a/test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00004.png b/test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_sell_wrong_dest/00004.png rename to test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00004.png diff --git a/test/python/snapshots/nanox/test_solana_fund_ok/00005.png b/test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_ok/00005.png rename to test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00005.png diff --git a/test/python/snapshots/nanosp/test_solana_sell_cancel/00007.png b/test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00006.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_sell_cancel/00007.png rename to test/python/snapshots/nanosp/test_tezos_sell_wrong_destination/00006.png diff --git a/test/python/snapshots/nanosp/test_tezos_swap_wrong_dest/00000.png b/test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_swap_wrong_dest/00000.png rename to test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00000.png diff --git a/test/python/snapshots/nanosp/test_tezos_swap_wrong_dest/00001.png b/test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_swap_wrong_dest/00001.png rename to test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00001.png diff --git a/test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00002.png b/test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00002.png new file mode 100644 index 00000000..2d2fc70b Binary files /dev/null and b/test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00002.png differ diff --git a/test/python/snapshots/nanosp/test_tezos_swap_wrong_dest/00003.png b/test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_swap_wrong_dest/00003.png rename to test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00003.png diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00004.png b/test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00004.png rename to test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00004.png diff --git a/test/python/snapshots/nanosp/test_tezos_swap_wrong_dest/00005.png b/test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_swap_wrong_dest/00005.png rename to test/python/snapshots/nanosp/test_tezos_swap_wrong_destination/00005.png diff --git a/test/python/snapshots/nanox/test_ripple_swap_wrong_dest/00000.png b/test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_ripple_swap_wrong_dest/00000.png rename to test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00000.png diff --git a/test/python/snapshots/nanox/test_ripple_swap_wrong_dest/00001.png b/test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_ripple_swap_wrong_dest/00001.png rename to test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00001.png diff --git a/test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00002.png b/test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00002.png new file mode 100644 index 00000000..2d2fc70b Binary files /dev/null and b/test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00002.png differ diff --git a/test/python/snapshots/nanox/test_ripple_swap_wrong_dest/00003.png b/test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_ripple_swap_wrong_dest/00003.png rename to test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00003.png diff --git a/test/python/snapshots/nanosp/test_stellar_swap_wrong_dest/00004.png b/test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_stellar_swap_wrong_dest/00004.png rename to test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00004.png diff --git a/test/python/snapshots/nanox/test_ripple_swap_wrong_dest/00005.png b/test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_ripple_swap_wrong_dest/00005.png rename to test/python/snapshots/nanox/test_ripple_swap_wrong_destination/00005.png diff --git a/test/python/snapshots/nanox/test_solana_fund_cancel/00006.png b/test/python/snapshots/nanox/test_solana_fund_cancel/00006.png deleted file mode 100644 index e90cd9db..00000000 Binary files a/test/python/snapshots/nanox/test_solana_fund_cancel/00006.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_fund_cancel/00000.png b/test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_cancel/00000.png rename to test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00000.png diff --git a/test/python/snapshots/nanox/test_solana_fund_cancel/00001.png b/test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_cancel/00001.png rename to test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00001.png diff --git a/test/python/snapshots/nanox/test_solana_fund_cancel/00002.png b/test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00002.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_cancel/00002.png rename to test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00002.png diff --git a/test/python/snapshots/nanox/test_solana_fund_cancel/00003.png b/test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_cancel/00003.png rename to test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00003.png diff --git a/test/python/snapshots/nanox/test_solana_fund_cancel/00004.png b/test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_cancel/00004.png rename to test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00004.png diff --git a/test/python/snapshots/nanox/test_solana_sell_cancel/00005.png b/test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_cancel/00005.png rename to test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00005.png diff --git a/test/python/snapshots/nanox/test_solana_fund_ok/00006.png b/test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00006.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_ok/00006.png rename to test/python/snapshots/nanox/test_solana_fund_refuse_double_sign/00006.png diff --git a/test/python/snapshots/nanox/test_solana_fund_ok/00000.png b/test/python/snapshots/nanox/test_solana_fund_valid_1/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_ok/00000.png rename to test/python/snapshots/nanox/test_solana_fund_valid_1/00000.png diff --git a/test/python/snapshots/nanox/test_solana_fund_ok/00001.png b/test/python/snapshots/nanox/test_solana_fund_valid_1/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_ok/00001.png rename to test/python/snapshots/nanox/test_solana_fund_valid_1/00001.png diff --git a/test/python/snapshots/nanox/test_solana_fund_ok/00002.png b/test/python/snapshots/nanox/test_solana_fund_valid_1/00002.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_ok/00002.png rename to test/python/snapshots/nanox/test_solana_fund_valid_1/00002.png diff --git a/test/python/snapshots/nanox/test_solana_fund_ok/00003.png b/test/python/snapshots/nanox/test_solana_fund_valid_1/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_ok/00003.png rename to test/python/snapshots/nanox/test_solana_fund_valid_1/00003.png diff --git a/test/python/snapshots/nanox/test_solana_fund_ok/00004.png b/test/python/snapshots/nanox/test_solana_fund_valid_1/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_ok/00004.png rename to test/python/snapshots/nanox/test_solana_fund_valid_1/00004.png diff --git a/test/python/snapshots/nanox/test_solana_sell_ok/00005.png b/test/python/snapshots/nanox/test_solana_fund_valid_1/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_ok/00005.png rename to test/python/snapshots/nanox/test_solana_fund_valid_1/00005.png diff --git a/test/python/snapshots/nanox/test_solana_sell_ok/00006.png b/test/python/snapshots/nanox/test_solana_fund_valid_1/00006.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_ok/00006.png rename to test/python/snapshots/nanox/test_solana_fund_valid_1/00006.png diff --git a/test/python/snapshots/nanox/test_solana_sell_cancel/00000.png b/test/python/snapshots/nanox/test_solana_fund_valid_2/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_cancel/00000.png rename to test/python/snapshots/nanox/test_solana_fund_valid_2/00000.png diff --git a/test/python/snapshots/nanox/test_solana_fund_valid_2/00001.png b/test/python/snapshots/nanox/test_solana_fund_valid_2/00001.png new file mode 100644 index 00000000..218ab5e0 Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_fund_valid_2/00001.png differ diff --git a/test/python/snapshots/nanox/test_solana_fund_valid_2/00002.png b/test/python/snapshots/nanox/test_solana_fund_valid_2/00002.png new file mode 100644 index 00000000..c012d308 Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_fund_valid_2/00002.png differ diff --git a/test/python/snapshots/nanox/test_solana_fund_valid_2/00003.png b/test/python/snapshots/nanox/test_solana_fund_valid_2/00003.png new file mode 100644 index 00000000..f6913414 Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_fund_valid_2/00003.png differ diff --git a/test/python/snapshots/nanox/test_solana_fund_valid_2/00004.png b/test/python/snapshots/nanox/test_solana_fund_valid_2/00004.png new file mode 100644 index 00000000..a0671c45 Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_fund_valid_2/00004.png differ diff --git a/test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00005.png b/test/python/snapshots/nanox/test_solana_fund_valid_2/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00005.png rename to test/python/snapshots/nanox/test_solana_fund_valid_2/00005.png diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00006.png b/test/python/snapshots/nanox/test_solana_fund_valid_2/00006.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00006.png rename to test/python/snapshots/nanox/test_solana_fund_valid_2/00006.png diff --git a/test/python/snapshots/nanox/test_solana_sell_cancel/00006.png b/test/python/snapshots/nanox/test_solana_sell_cancel/00006.png deleted file mode 100644 index e90cd9db..00000000 Binary files a/test/python/snapshots/nanox/test_solana_sell_cancel/00006.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_sell_ok/00000.png b/test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_ok/00000.png rename to test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00000.png diff --git a/test/python/snapshots/nanox/test_solana_sell_cancel/00001.png b/test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_cancel/00001.png rename to test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00001.png diff --git a/test/python/snapshots/nanox/test_solana_sell_cancel/00002.png b/test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00002.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_cancel/00002.png rename to test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00002.png diff --git a/test/python/snapshots/nanox/test_solana_sell_ok/00003.png b/test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_ok/00003.png rename to test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00003.png diff --git a/test/python/snapshots/nanox/test_solana_sell_cancel/00004.png b/test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_cancel/00004.png rename to test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00004.png diff --git a/test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00005.png b/test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00005.png rename to test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00005.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_cancel/00006.png b/test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00006.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_cancel/00006.png rename to test/python/snapshots/nanox/test_solana_sell_refuse_double_sign/00006.png diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00000.png b/test/python/snapshots/nanox/test_solana_sell_valid_1/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00000.png rename to test/python/snapshots/nanox/test_solana_sell_valid_1/00000.png diff --git a/test/python/snapshots/nanox/test_solana_sell_ok/00001.png b/test/python/snapshots/nanox/test_solana_sell_valid_1/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_ok/00001.png rename to test/python/snapshots/nanox/test_solana_sell_valid_1/00001.png diff --git a/test/python/snapshots/nanox/test_solana_sell_ok/00002.png b/test/python/snapshots/nanox/test_solana_sell_valid_1/00002.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_ok/00002.png rename to test/python/snapshots/nanox/test_solana_sell_valid_1/00002.png diff --git a/test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00003.png b/test/python/snapshots/nanox/test_solana_sell_valid_1/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00003.png rename to test/python/snapshots/nanox/test_solana_sell_valid_1/00003.png diff --git a/test/python/snapshots/nanox/test_solana_sell_ok/00004.png b/test/python/snapshots/nanox/test_solana_sell_valid_1/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_ok/00004.png rename to test/python/snapshots/nanox/test_solana_sell_valid_1/00004.png diff --git a/test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00005.png b/test/python/snapshots/nanox/test_solana_sell_valid_1/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00005.png rename to test/python/snapshots/nanox/test_solana_sell_valid_1/00005.png diff --git a/test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00006.png b/test/python/snapshots/nanox/test_solana_sell_valid_1/00006.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00006.png rename to test/python/snapshots/nanox/test_solana_sell_valid_1/00006.png diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_ok/00000.png b/test/python/snapshots/nanox/test_solana_sell_valid_2/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_recipient_ok/00000.png rename to test/python/snapshots/nanox/test_solana_sell_valid_2/00000.png diff --git a/test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00001.png b/test/python/snapshots/nanox/test_solana_sell_valid_2/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00001.png rename to test/python/snapshots/nanox/test_solana_sell_valid_2/00001.png diff --git a/test/python/snapshots/nanox/test_solana_sell_valid_2/00002.png b/test/python/snapshots/nanox/test_solana_sell_valid_2/00002.png new file mode 100644 index 00000000..c012d308 Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_sell_valid_2/00002.png differ diff --git a/test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00003.png b/test/python/snapshots/nanox/test_solana_sell_valid_2/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00003.png rename to test/python/snapshots/nanox/test_solana_sell_valid_2/00003.png diff --git a/test/python/snapshots/nanox/test_solana_sell_valid_2/00004.png b/test/python/snapshots/nanox/test_solana_sell_valid_2/00004.png new file mode 100644 index 00000000..a0671c45 Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_sell_valid_2/00004.png differ diff --git a/test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00005.png b/test/python/snapshots/nanox/test_solana_sell_valid_2/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00005.png rename to test/python/snapshots/nanox/test_solana_sell_valid_2/00005.png diff --git a/test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00006.png b/test/python/snapshots/nanox/test_solana_sell_valid_2/00006.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00006.png rename to test/python/snapshots/nanox/test_solana_sell_valid_2/00006.png diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00001.png b/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00001.png deleted file mode 100644 index 8b0f7d73..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00001.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00002.png b/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00002.png deleted file mode 100644 index 0ab84580..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00003.png b/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00003.png deleted file mode 100644 index 95580750..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00003.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00005.png b/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00005.png deleted file mode 100644 index e90cd9db..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00005.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_ok/00001.png b/test/python/snapshots/nanox/test_solana_swap_recipient_ok/00001.png deleted file mode 100644 index 8b0f7d73..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_recipient_ok/00001.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_ok/00002.png b/test/python/snapshots/nanox/test_solana_swap_recipient_ok/00002.png deleted file mode 100644 index 0ab84580..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_recipient_ok/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_ok/00003.png b/test/python/snapshots/nanox/test_solana_swap_recipient_ok/00003.png deleted file mode 100644 index 95580750..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_recipient_ok/00003.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_cancel/00000.png b/test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_cancel/00000.png rename to test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00000.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_cancel/00001.png b/test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_cancel/00001.png rename to test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00001.png diff --git a/test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00002.png b/test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00002.png new file mode 100644 index 00000000..2d2fc70b Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00002.png differ diff --git a/test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00003.png b/test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00003.png similarity index 100% rename from test/python/snapshots/nanosp/test_solana_swap_sender_wrong_destination/00003.png rename to test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00003.png diff --git a/test/python/snapshots/nanosp/test_tezos_swap_wrong_dest/00004.png b/test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00004.png similarity index 100% rename from test/python/snapshots/nanosp/test_tezos_swap_wrong_dest/00004.png rename to test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00004.png diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_ok/00005.png b/test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_recipient_ok/00005.png rename to test/python/snapshots/nanox/test_solana_swap_refuse_double_sign/00005.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_cancel/00002.png b/test/python/snapshots/nanox/test_solana_swap_sender_cancel/00002.png deleted file mode 100644 index cf33e5fc..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_sender_cancel/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_cancel/00005.png b/test/python/snapshots/nanox/test_solana_swap_sender_cancel/00005.png deleted file mode 100644 index e90cd9db..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_sender_cancel/00005.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00002.png b/test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00002.png deleted file mode 100644 index cf33e5fc..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_ok/00002.png b/test/python/snapshots/nanox/test_solana_swap_sender_ok/00002.png deleted file mode 100644 index cf33e5fc..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_sender_ok/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00002.png b/test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00002.png deleted file mode 100644 index cf33e5fc..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00003.png b/test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00003.png deleted file mode 100644 index 808cc244..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00003.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00001.png b/test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00001.png deleted file mode 100644 index e8b43d16..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00001.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00002.png b/test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00002.png deleted file mode 100644 index cf33e5fc..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00002.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00003.png b/test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00003.png deleted file mode 100644 index 808cc244..00000000 Binary files a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00003.png and /dev/null differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00000.png b/test/python/snapshots/nanox/test_solana_swap_valid_1/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00000.png rename to test/python/snapshots/nanox/test_solana_swap_valid_1/00000.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00001.png b/test/python/snapshots/nanox/test_solana_swap_valid_1/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00001.png rename to test/python/snapshots/nanox/test_solana_swap_valid_1/00001.png diff --git a/test/python/snapshots/nanox/test_solana_swap_valid_1/00002.png b/test/python/snapshots/nanox/test_solana_swap_valid_1/00002.png new file mode 100644 index 00000000..2d2fc70b Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_swap_valid_1/00002.png differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_cancel/00003.png b/test/python/snapshots/nanox/test_solana_swap_valid_1/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_cancel/00003.png rename to test/python/snapshots/nanox/test_solana_swap_valid_1/00003.png diff --git a/test/python/snapshots/nanox/test_ripple_swap_wrong_dest/00004.png b/test/python/snapshots/nanox/test_solana_swap_valid_1/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_ripple_swap_wrong_dest/00004.png rename to test/python/snapshots/nanox/test_solana_swap_valid_1/00004.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00005.png b/test/python/snapshots/nanox/test_solana_swap_valid_1/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00005.png rename to test/python/snapshots/nanox/test_solana_swap_valid_1/00005.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_ok/00000.png b/test/python/snapshots/nanox/test_solana_swap_valid_2/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_ok/00000.png rename to test/python/snapshots/nanox/test_solana_swap_valid_2/00000.png diff --git a/test/python/snapshots/nanox/test_solana_swap_valid_2/00001.png b/test/python/snapshots/nanox/test_solana_swap_valid_2/00001.png new file mode 100644 index 00000000..c012d308 Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_swap_valid_2/00001.png differ diff --git a/test/python/snapshots/nanox/test_solana_swap_valid_2/00002.png b/test/python/snapshots/nanox/test_solana_swap_valid_2/00002.png new file mode 100644 index 00000000..2d2fc70b Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_swap_valid_2/00002.png differ diff --git a/test/python/snapshots/nanox/test_solana_swap_valid_2/00003.png b/test/python/snapshots/nanox/test_solana_swap_valid_2/00003.png new file mode 100644 index 00000000..a0671c45 Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_swap_valid_2/00003.png differ diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00004.png b/test/python/snapshots/nanox/test_solana_swap_valid_2/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_recipient_cancel/00004.png rename to test/python/snapshots/nanox/test_solana_swap_valid_2/00004.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_ok/00005.png b/test/python/snapshots/nanox/test_solana_swap_valid_2/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_ok/00005.png rename to test/python/snapshots/nanox/test_solana_swap_valid_2/00005.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00000.png b/test/python/snapshots/nanox/test_solana_swap_wrong_amount/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00000.png rename to test/python/snapshots/nanox/test_solana_swap_wrong_amount/00000.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_ok/00001.png b/test/python/snapshots/nanox/test_solana_swap_wrong_amount/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_ok/00001.png rename to test/python/snapshots/nanox/test_solana_swap_wrong_amount/00001.png diff --git a/test/python/snapshots/nanox/test_solana_swap_wrong_amount/00002.png b/test/python/snapshots/nanox/test_solana_swap_wrong_amount/00002.png new file mode 100644 index 00000000..2d2fc70b Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_swap_wrong_amount/00002.png differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00003.png b/test/python/snapshots/nanox/test_solana_swap_wrong_amount/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00003.png rename to test/python/snapshots/nanox/test_solana_swap_wrong_amount/00003.png diff --git a/test/python/snapshots/nanox/test_solana_swap_recipient_ok/00004.png b/test/python/snapshots/nanox/test_solana_swap_wrong_amount/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_recipient_ok/00004.png rename to test/python/snapshots/nanox/test_solana_swap_wrong_amount/00004.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00005.png b/test/python/snapshots/nanox/test_solana_swap_wrong_amount/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00005.png rename to test/python/snapshots/nanox/test_solana_swap_wrong_amount/00005.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00000.png b/test/python/snapshots/nanox/test_solana_swap_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00000.png rename to test/python/snapshots/nanox/test_solana_swap_wrong_destination/00000.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00001.png b/test/python/snapshots/nanox/test_solana_swap_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00001.png rename to test/python/snapshots/nanox/test_solana_swap_wrong_destination/00001.png diff --git a/test/python/snapshots/nanox/test_solana_swap_wrong_destination/00002.png b/test/python/snapshots/nanox/test_solana_swap_wrong_destination/00002.png new file mode 100644 index 00000000..2d2fc70b Binary files /dev/null and b/test/python/snapshots/nanox/test_solana_swap_wrong_destination/00002.png differ diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_ok/00003.png b/test/python/snapshots/nanox/test_solana_swap_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_ok/00003.png rename to test/python/snapshots/nanox/test_solana_swap_wrong_destination/00003.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_cancel/00004.png b/test/python/snapshots/nanox/test_solana_swap_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_cancel/00004.png rename to test/python/snapshots/nanox/test_solana_swap_wrong_destination/00004.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00005.png b/test/python/snapshots/nanox/test_solana_swap_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00005.png rename to test/python/snapshots/nanox/test_solana_swap_wrong_destination/00005.png diff --git a/test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00000.png b/test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00000.png rename to test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00000.png diff --git a/test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00001.png b/test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00001.png rename to test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00001.png diff --git a/test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00002.png b/test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00002.png rename to test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00002.png diff --git a/test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00003.png b/test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00003.png rename to test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00003.png diff --git a/test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00004.png b/test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_fund_wrong_dest/00004.png rename to test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00004.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00004.png b/test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_double_sign/00004.png rename to test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00005.png diff --git a/test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00006.png b/test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00006.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00006.png rename to test/python/snapshots/nanox/test_stellar_fund_wrong_destination/00006.png diff --git a/test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00000.png b/test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00000.png rename to test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00000.png diff --git a/test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00001.png b/test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00001.png rename to test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00001.png diff --git a/test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00002.png b/test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00002.png rename to test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00002.png diff --git a/test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00003.png b/test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00003.png new file mode 100644 index 00000000..6749f273 Binary files /dev/null and b/test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00003.png differ diff --git a/test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00004.png b/test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_sell_wrong_dest/00004.png rename to test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00004.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_ok/00004.png b/test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_ok/00004.png rename to test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00005.png diff --git a/test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00006.png b/test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00006.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00006.png rename to test/python/snapshots/nanox/test_stellar_sell_wrong_destination/00006.png diff --git a/test/python/snapshots/nanox/test_stellar_swap_wrong_dest/00000.png b/test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_swap_wrong_dest/00000.png rename to test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00000.png diff --git a/test/python/snapshots/nanox/test_stellar_swap_wrong_dest/00001.png b/test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_swap_wrong_dest/00001.png rename to test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00001.png diff --git a/test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00002.png b/test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00002.png new file mode 100644 index 00000000..2d2fc70b Binary files /dev/null and b/test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00002.png differ diff --git a/test/python/snapshots/nanox/test_stellar_swap_wrong_dest/00003.png b/test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_swap_wrong_dest/00003.png rename to test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00003.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00004.png b/test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_wrong_amount/00004.png rename to test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00004.png diff --git a/test/python/snapshots/nanox/test_stellar_swap_wrong_dest/00005.png b/test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_swap_wrong_dest/00005.png rename to test/python/snapshots/nanox/test_stellar_swap_wrong_destination/00005.png diff --git a/test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00000.png b/test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00000.png rename to test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00000.png diff --git a/test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00001.png b/test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00001.png rename to test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00001.png diff --git a/test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00002.png b/test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00002.png rename to test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00002.png diff --git a/test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00003.png b/test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00003.png rename to test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00003.png diff --git a/test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00004.png b/test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_fund_wrong_dest/00004.png rename to test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00004.png diff --git a/test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00004.png b/test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_swap_sender_wrong_destination/00004.png rename to test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00005.png diff --git a/test/python/snapshots/nanox/test_solana_fund_cancel/00007.png b/test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00006.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_fund_cancel/00007.png rename to test/python/snapshots/nanox/test_tezos_fund_wrong_destination/00006.png diff --git a/test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00000.png b/test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00000.png rename to test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00000.png diff --git a/test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00001.png b/test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00001.png new file mode 100644 index 00000000..60ee7698 Binary files /dev/null and b/test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00001.png differ diff --git a/test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00002.png b/test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00002.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00002.png rename to test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00002.png diff --git a/test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00003.png b/test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00003.png new file mode 100644 index 00000000..6749f273 Binary files /dev/null and b/test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00003.png differ diff --git a/test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00004.png b/test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_sell_wrong_dest/00004.png rename to test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00004.png diff --git a/test/python/snapshots/nanox/test_stellar_swap_wrong_dest/00004.png b/test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_stellar_swap_wrong_dest/00004.png rename to test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00005.png diff --git a/test/python/snapshots/nanox/test_solana_sell_cancel/00007.png b/test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00006.png similarity index 100% rename from test/python/snapshots/nanox/test_solana_sell_cancel/00007.png rename to test/python/snapshots/nanox/test_tezos_sell_wrong_destination/00006.png diff --git a/test/python/snapshots/nanox/test_tezos_swap_wrong_dest/00000.png b/test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00000.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_swap_wrong_dest/00000.png rename to test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00000.png diff --git a/test/python/snapshots/nanox/test_tezos_swap_wrong_dest/00001.png b/test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00001.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_swap_wrong_dest/00001.png rename to test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00001.png diff --git a/test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00002.png b/test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00002.png new file mode 100644 index 00000000..2d2fc70b Binary files /dev/null and b/test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00002.png differ diff --git a/test/python/snapshots/nanox/test_tezos_swap_wrong_dest/00003.png b/test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00003.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_swap_wrong_dest/00003.png rename to test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00003.png diff --git a/test/python/snapshots/nanox/test_tezos_swap_wrong_dest/00004.png b/test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00004.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_swap_wrong_dest/00004.png rename to test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00004.png diff --git a/test/python/snapshots/nanox/test_tezos_swap_wrong_dest/00005.png b/test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00005.png similarity index 100% rename from test/python/snapshots/nanox/test_tezos_swap_wrong_dest/00005.png rename to test/python/snapshots/nanox/test_tezos_swap_wrong_destination/00005.png diff --git a/test/python/test_ripple.py b/test/python/test_ripple.py index 60bc6fb8..517eeb31 100644 --- a/test/python/test_ripple.py +++ b/test/python/test_ripple.py @@ -1,405 +1,40 @@ import pytest -from typing import Optional, Tuple -from ragger.backend import RaisePolicy -from ragger.utils import pack_APDU, RAPDU -from ragger.error import ExceptionRAPDU - -from .apps.exchange import ExchangeClient, Rate, SubCommand, Errors +from .apps.exchange_test_runner import ExchangeTestRunner, SWAP_TESTS from .apps.xrp import XRPClient, DEFAULT_PATH, XRP_PACKED_DERIVATION_PATH, RippleErrors -from .apps.signing_authority import SigningAuthority, LEDGER_SIGNER -from .apps.exchange_transaction_builder import get_partner_curve, craft_tx, encode_tx, extract_payout_ticker, extract_refund_ticker -from .apps import cal as cal - -from .utils import handle_lib_call_start_or_stop - - -def test_ripple_wrong_refund(backend): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Default name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - - tx_infos = { - "payin_address": b"ra7Zr8ddy9tB88RaXL8B87YkqhEJG2vkAJ", - "payin_extra_id": b"", - "refund_address": b"abcdabcd", - "refund_extra_id": b"", - "payout_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", - "payout_extra_id": b"", - "currency_from": "XRP", - "currency_to": "ETH", - "amount_to_provider": int.to_bytes(1000, length=8, byteorder='big'), - "amount_to_wallet": b"\246\333t\233+\330\000", - } - tx = craft_tx(SubCommand.SWAP, tx_infos, transaction_id) - ex.process_transaction(tx, 100) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - - backend.raise_policy = RaisePolicy.RAISE_NOTHING - with ex.check_address(cal.get_conf_for_ticker(tx_infos["currency_to"]), cal.get_conf_for_ticker(tx_infos["currency_from"])): - pass - assert ex.get_check_address_response().status == Errors.INVALID_ADDRESS - - -def test_ripple_wrong_payout(backend): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Default name") +# ExchangeTestRunner implementation for Stellar +class RippleTests(ExchangeTestRunner): + currency_ticker = "XRP" + valid_destination_1 = "ra7Zr8ddy9tB88RaXL8B87YkqhEJG2vkAJ" + valid_destination_memo_1 = "0" + valid_destination_2 = "rhBuYom8agWA4s7DFoM7AvsDA9XGkVCJz4" + valid_destination_memo_2 = "123" + valid_refund = "ra7Zr8ddy9tB88RaXL8B87YkqhEJG2vkAJ" + valid_refund_memo = "" + valid_send_amount_1 = 1000000 + valid_send_amount_2 = 446739662 + valid_fees_1 = 100 + valid_fees_2 = 10078 + fake_refund = "abcdabcd" + fake_refund_memo = "" + fake_payout = "abcdabcd" + fake_payout_memo = "" + signature_refusal_error_code = RippleErrors.SW_SWAP_CHECKING_FAIL + + def perform_final_tx(self, destination, send_amount, fees, memo): + XRPClient(self.backend).send_simple_sign_tx(path="m/44'/144'/0'/0'/0", + fees=fees, + memo=memo, + destination=destination, + send_amount=send_amount) - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - - tx_infos = { - "payin_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", - "payin_extra_id": b"", - "refund_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", - "refund_extra_id": b"", - "payout_address": b"abcdabcd", - "payout_extra_id": b"", - "currency_from": "ETH", - "currency_to": "XRP", - "amount_to_provider": int.to_bytes(1000, length=8, byteorder='big'), - "amount_to_wallet": b"\246\333t\233+\330\000", - } - tx = craft_tx(SubCommand.SWAP, tx_infos, transaction_id) - ex.process_transaction(tx, 100) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - - backend.raise_policy = RaisePolicy.RAISE_NOTHING - with ex.check_address(cal.get_conf_for_ticker(tx_infos["currency_to"]), cal.get_conf_for_ticker(tx_infos["currency_from"])): - pass - assert ex.get_check_address_response().status == Errors.INVALID_ADDRESS - - -class RippleValidTxPerformer: - # Default valid tx values used for the tests - def_path = "m/44'/144'/0'/0'/0" - def_fees = 100 - def_memo = "0" - def_destination = "ra7Zr8ddy9tB88RaXL8B87YkqhEJG2vkAJ" - def_send_amount = 1000000 - - # Helper to use default args if none provided - def _maybe_default(self, fees, memo, destination, send_amount) -> Tuple[int, str, str, int]: - fees = self.def_fees if fees is None else fees - memo = self.def_memo if memo is None else memo - destination = self.def_destination if destination is None else destination - send_amount = self.def_send_amount if send_amount is None else send_amount - return (fees, memo, destination, send_amount) - - # Helper to send a valid TX to the Ripple app, provide parameters to overload te default values - def perform_ripple_tx(self, - backend, - fees: Optional[int]=None, - memo: Optional[str]=None, - destination: Optional[str]=None, - send_amount: Optional[int]=None) -> RAPDU: - fees, memo, destination, send_amount = self._maybe_default(fees, memo, destination, send_amount) - - rapdu = XRPClient(backend).send_simple_sign_tx(path=self.def_path, - fees=fees, - memo=memo, - destination=destination, - send_amount=send_amount) # TODO : assert signature validity - handle_lib_call_start_or_stop(backend) - return rapdu - - def perform_valid_exchange_tx(self, backend, exchange_navigation_helper, subcommand, tx_infos, fees): - ex = ExchangeClient(backend, Rate.FIXED, subcommand) - partner = SigningAuthority(curve=get_partner_curve(subcommand), name="Default name") - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(subcommand, tx_infos, transaction_id) - ex.process_transaction(tx, fees) - encoded_tx = encode_tx(subcommand, partner, tx) - ex.check_transaction_signature(encoded_tx) - payout_ticker = extract_payout_ticker(subcommand, tx_infos) - refund_ticker = extract_refund_ticker(subcommand, tx_infos) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker), cal.get_conf_for_ticker(refund_ticker)): - exchange_navigation_helper.simple_accept() - ex.start_signing_transaction() - - -############## -# SWAP tests # -############## - -class RippleValidSwapPerformer(RippleValidTxPerformer): - # Helper to send a valid SWAP TX to the Exchange app, provide parameters to overload te default values - def perform_valid_swap(self, - backend, - exchange_navigation_helper, - fees: Optional[int]=None, - memo: Optional[str]=None, - destination: Optional[str]=None, - send_amount: Optional[int]=None): - fees, memo, destination, send_amount = self._maybe_default(fees, memo, destination, send_amount) - tx_infos = { - "payin_address": destination, - "payin_extra_id": memo.encode(), - "refund_address": b"ra7Zr8ddy9tB88RaXL8B87YkqhEJG2vkAJ", - "refund_extra_id": b"", - "payout_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", - "payout_extra_id": b"", - "currency_from": "XRP", - "currency_to": "ETH", - "amount_to_provider": int.to_bytes(send_amount, length=8, byteorder='big'), - "amount_to_wallet": b"\246\333t\233+\330\000", - } - self.perform_valid_exchange_tx(backend, exchange_navigation_helper, SubCommand.SWAP, tx_infos, fees) - - -# Valid swap test with default values -def test_ripple_swap_valid_1(backend, exchange_navigation_helper): - performer = RippleValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - performer.perform_ripple_tx(backend) - - -# Valid swap test with non default values -def test_ripple_swap_valid_2(backend, exchange_navigation_helper): - fees = 10078 - memo = "123" - destination = "rhBuYom8agWA4s7DFoM7AvsDA9XGkVCJz4" - send_amount = 446739662 - - performer = RippleValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper, fees=fees, memo=memo, destination=destination, send_amount=send_amount) - performer.perform_ripple_tx(backend, fees=fees, memo=memo, destination=destination, send_amount=send_amount) - - -# Make a valid swap and then ask a second signature -def test_ripple_swap_refuse_double_sign(backend, exchange_navigation_helper): - performer = RippleValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - performer.perform_ripple_tx(backend) - - with pytest.raises(ExceptionRAPDU) as e: - performer.perform_ripple_tx(backend) - assert e.value.status == Errors.WRONG_P2 - - -# Test swap with a malicious Ripple TX with tampered fees -def test_ripple_swap_wrong_fees(backend, exchange_navigation_helper): - performer = RippleValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_ripple_tx(backend, fees=performer.def_fees + 100) - assert rapdu.status == RippleErrors.SW_SWAP_CHECKING_FAIL - - -# Test swap with a malicious Ripple TX with tampered memo -def test_ripple_swap_wrong_memo(backend, exchange_navigation_helper): - performer = RippleValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_ripple_tx(backend, memo=performer.def_memo + "1") - assert rapdu.status == RippleErrors.SW_SWAP_CHECKING_FAIL - - -# Test swap with a malicious Ripple TX with tampered dest -def test_ripple_swap_wrong_dest(backend, exchange_navigation_helper): - performer = RippleValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_ripple_tx(backend, destination="rhBuYom8agWA4s7DFoM7AvsDA9XGkVCJz4") - assert rapdu.status == RippleErrors.SW_SWAP_CHECKING_FAIL - - -# Test swap with a malicious Ripple TX with tampered amount -def test_ripple_swap_wrong_amount(backend, exchange_navigation_helper): - performer = RippleValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_ripple_tx(backend, send_amount=performer.def_send_amount + 351) - assert rapdu.status == RippleErrors.SW_SWAP_CHECKING_FAIL - - -############## -# FUND tests # -############## - -# class RippleValidFundPerformer(RippleValidTxPerformer): -# # Helper to send a valid FUND TX to the Exchange app, provide parameters to overload te default values -# def perform_valid_fund(self, -# backend, -# navigator, -# test_name, -# fees: Optional[int]=None, -# memo: Optional[str]=None, -# destination: Optional[str]=None, -# send_amount: Optional[int]=None): -# fees, memo, destination, send_amount = self._maybe_default(fees, memo, destination, send_amount) -# tx_infos = { -# "user_id": "Jon Wick", -# "account_name": "My account 00", -# "in_currency": "XRP", -# "in_amount": int.to_bytes(send_amount, length=4, byteorder='big'), -# "in_address": destination, -# } -# self.perform_valid_exchange_tx(backend, exchange_navigation_helper, SubCommand.FUND, tx_infos, fees) - - -# # Valid fund test with default values -# def test_ripple_fund_valid_1(backend, exchange_navigation_helper): -# performer = RippleValidFundPerformer() -# performer.perform_valid_fund(backend, exchange_navigation_helper) -# performer.perform_ripple_tx(backend) - - -# # Valid fund test with non default values -# def test_ripple_fund_valid_2(backend, exchange_navigation_helper): -# fees = 10078 -# destination="rhBuYom8agWA4s7DFoM7AvsDA9XGkVCJz4" -# send_amount = 446739662 - -# performer = RippleValidFundPerformer() -# performer.perform_valid_fund(backend, exchange_navigation_helper, fees=fees, destination=destination, send_amount=send_amount) -# performer.perform_ripple_tx(backend, fees=fees, destination=destination, send_amount=send_amount) - - -# # Make a valid fund and then ask a second signature -# def test_ripple_fund_refuse_double_sign(backend, exchange_navigation_helper): -# performer = RippleValidFundPerformer() -# performer.perform_valid_fund(backend, exchange_navigation_helper) -# performer.perform_ripple_tx(backend) - -# with pytest.raises(ExceptionRAPDU) as e: -# performer.perform_ripple_tx(backend) -# assert e.value.status == Errors.WRONG_P2 - - -# # Test fund with a malicious Ripple TX with tampered fees -# def test_ripple_fund_wrong_fees(backend, exchange_navigation_helper): -# performer = RippleValidFundPerformer() -# performer.perform_valid_fund(backend, exchange_navigation_helper) -# backend.raise_policy = RaisePolicy.RAISE_NOTHING -# rapdu = performer.perform_ripple_tx(backend, fees=performer.def_fees + 100) -# assert rapdu.status == RippleErrors.SW_SWAP_CHECKING_FAIL - - -# # Test fund with a malicious Ripple TX with tampered memo -# def test_ripple_fund_wrong_memo(backend, exchange_navigation_helper): -# performer = RippleValidFundPerformer() -# performer.perform_valid_fund(backend, exchange_navigation_helper) -# backend.raise_policy = RaisePolicy.RAISE_NOTHING -# rapdu = performer.perform_ripple_tx(backend, memo=performer.def_memo + "1") -# assert rapdu.status == RippleErrors.SW_SWAP_CHECKING_FAIL - - -# # Test fund with a malicious Ripple TX with tampered dest -# def test_ripple_fund_wrong_dest(backend, exchange_navigation_helper): -# performer = RippleValidFundPerformer() -# performer.perform_valid_fund(backend, exchange_navigation_helper) -# backend.raise_policy = RaisePolicy.RAISE_NOTHING -# rapdu = performer.perform_ripple_tx(backend, destination="rhBuYom8agWA4s7DFoM7AvsDA9XGkVCJz4") -# assert rapdu.status == RippleErrors.SW_SWAP_CHECKING_FAIL - - -# # Test fund with a malicious Ripple TX with tampered amount -# def test_ripple_fund_wrong_amount(backend, exchange_navigation_helper): -# performer = RippleValidFundPerformer() -# performer.perform_valid_fund(backend, exchange_navigation_helper) -# backend.raise_policy = RaisePolicy.RAISE_NOTHING -# rapdu = performer.perform_ripple_tx(backend, send_amount=performer.def_send_amount + 351) -# assert rapdu.status == RippleErrors.SW_SWAP_CHECKING_FAIL - - -# ############## -# # SELL tests # -# ############## - -# class RippleValidSellPerformer(RippleValidTxPerformer): -# # Helper to send a valid SELL TX to the Exchange app, provide parameters to overload te default values -# def perform_valid_sell(self, -# backend, -# navigator, -# test_name, -# fees: Optional[int]=None, -# memo: Optional[str]=None, -# destination: Optional[str]=None, -# send_amount: Optional[int]=None): -# fees, memo, destination, send_amount = self._maybe_default(fees, memo, destination, send_amount) -# tx_infos = { -# "trader_email": "john@doe.lost", -# "out_currency": "USD", -# "out_amount": {"coefficient": b"\x01", "exponent": 3}, -# "in_currency": "XRP", -# "in_amount": int.to_bytes(send_amount, length=4, byteorder='big'), -# "in_address": destination, -# } -# self.perform_valid_exchange_tx(backend, exchange_navigation_helper, SubCommand.SELL, tx_infos, fees) - - -# # Valid sell test with default values -# def test_ripple_sell_valid_1(backend, exchange_navigation_helper): -# performer = RippleValidSellPerformer() -# performer.perform_valid_sell(backend, exchange_navigation_helper) -# performer.perform_ripple_tx(backend) - - -# # Valid sell test with non default values -# def test_ripple_sell_valid_2(backend, exchange_navigation_helper): -# fees = 10078 -# destination="rhBuYom8agWA4s7DFoM7AvsDA9XGkVCJz4" -# send_amount = 446739662 - -# performer = RippleValidSellPerformer() -# performer.perform_valid_sell(backend, exchange_navigation_helper, fees=fees, destination=destination, send_amount=send_amount) -# performer.perform_ripple_tx(backend, fees=fees, destination=destination, send_amount=send_amount) - - -# # Make a valid sell and then ask a second signature -# def test_ripple_sell_refuse_double_sign(backend, exchange_navigation_helper): -# performer = RippleValidSellPerformer() -# performer.perform_valid_sell(backend, exchange_navigation_helper) -# performer.perform_ripple_tx(backend) - -# with pytest.raises(ExceptionRAPDU) as e: -# performer.perform_ripple_tx(backend) -# assert e.value.status == Errors.WRONG_P2 - - -# # Test sell with a malicious Ripple TX with tampered fees -# def test_ripple_sell_wrong_fees(backend, exchange_navigation_helper): -# performer = RippleValidSellPerformer() -# performer.perform_valid_sell(backend, exchange_navigation_helper) -# backend.raise_policy = RaisePolicy.RAISE_NOTHING -# rapdu = performer.perform_ripple_tx(backend, fees=performer.def_fees + 100) -# assert rapdu.status == RippleErrors.SW_SWAP_CHECKING_FAIL - - -# # Test sell with a malicious Ripple TX with tampered memo -# def test_ripple_sell_wrong_memo(backend, exchange_navigation_helper): -# performer = RippleValidSellPerformer() -# performer.perform_valid_sell(backend, exchange_navigation_helper) -# backend.raise_policy = RaisePolicy.RAISE_NOTHING -# rapdu = performer.perform_ripple_tx(backend, memo=performer.def_memo + "1") -# assert rapdu.status == RippleErrors.SW_SWAP_CHECKING_FAIL - - -# # Test sell with a malicious Ripple TX with tampered dest -# def test_ripple_sell_wrong_dest(backend, exchange_navigation_helper): -# performer = RippleValidSellPerformer() -# performer.perform_valid_sell(backend, exchange_navigation_helper) -# backend.raise_policy = RaisePolicy.RAISE_NOTHING -# rapdu = performer.perform_ripple_tx(backend, destination="rhBuYom8agWA4s7DFoM7AvsDA9XGkVCJz4") -# assert rapdu.status == RippleErrors.SW_SWAP_CHECKING_FAIL +# Use a class to reuse the same Speculos instance +class TestsRipple: -# # Test sell with a malicious Ripple TX with tampered amount -# def test_ripple_sell_wrong_amount(backend, exchange_navigation_helper): -# performer = RippleValidSellPerformer() -# performer.perform_valid_sell(backend, exchange_navigation_helper) -# backend.raise_policy = RaisePolicy.RAISE_NOTHING -# rapdu = performer.perform_ripple_tx(backend, send_amount=performer.def_send_amount + 351) -# assert rapdu.status == RippleErrors.SW_SWAP_CHECKING_FAIL + @pytest.mark.parametrize('test_to_run', SWAP_TESTS) + def test_ripple(self, backend, exchange_navigation_helper, test_to_run): + RippleTests(backend, exchange_navigation_helper).run_test(test_to_run) diff --git a/test/python/test_solana.py b/test/python/test_solana.py new file mode 100644 index 00000000..5f3afd0f --- /dev/null +++ b/test/python/test_solana.py @@ -0,0 +1,52 @@ +import pytest + +from .apps.exchange_test_runner import ExchangeTestRunner, ALL_TESTS_EXCEPT_MEMO_AND_FEES +from .apps.solana import SolanaClient, ErrorType +from .apps.solana_utils import SOL_PACKED_DERIVATION_PATH +from .apps.solana_cmd_builder import SystemInstructionTransfer, Message, verify_signature +from .apps import solana_utils as SOL + +# A bit hacky but way less hassle than actually writing an actual address decoder +SOLANA_ADDRESS_DECODER = { + SOL.FOREIGN_ADDRESS: SOL.FOREIGN_PUBLIC_KEY, + SOL.FOREIGN_ADDRESS_2: SOL.FOREIGN_PUBLIC_KEY_2, +} + +# ExchangeTestRunner implementation for Stellar +class SolanaTests(ExchangeTestRunner): + currency_ticker = "SOL" + valid_destination_1 = SOL.FOREIGN_ADDRESS + valid_destination_memo_1 = "" + valid_destination_2 = SOL.FOREIGN_ADDRESS_2 + valid_destination_memo_2 = "" + valid_refund = SOL.OWNED_ADDRESS + valid_refund_memo = "" + valid_send_amount_1 = SOL.AMOUNT + valid_send_amount_2 = SOL.AMOUNT_2 + valid_fees_1 = SOL.FEES + valid_fees_2 = SOL.FEES_2 + fake_refund = SOL.FOREIGN_ADDRESS + fake_refund_memo = "" + fake_payout = SOL.FOREIGN_ADDRESS + fake_payout_memo = "" + signature_refusal_error_code = ErrorType.SOLANA_SUMMARY_FINALIZE_FAILED + + partner_name = "Partner name" + fund_user_id = "Daft Punk" + fund_account_name = "Account 0" + + def perform_final_tx(self, destination, send_amount, fees, memo): + decoded_destination = SOLANA_ADDRESS_DECODER[destination] + instruction: SystemInstructionTransfer = SystemInstructionTransfer(SOL.OWNED_PUBLIC_KEY, decoded_destination, send_amount) + message: bytes = Message([instruction]).serialize() + sol = SolanaClient(self.backend) + with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): + pass + signature: bytes = sol.get_async_response().data + verify_signature(SOL.OWNED_PUBLIC_KEY, message, signature) + + +# Use a class to reuse the same Speculos instance +@pytest.mark.parametrize('test_to_run', ALL_TESTS_EXCEPT_MEMO_AND_FEES) +def test_solana(backend, exchange_navigation_helper, test_to_run): + SolanaTests(backend, exchange_navigation_helper).run_test(test_to_run) diff --git a/test/python/test_solana_fund.py b/test/python/test_solana_fund.py deleted file mode 100644 index 662b6a85..00000000 --- a/test/python/test_solana_fund.py +++ /dev/null @@ -1,105 +0,0 @@ -from ragger.backend.interface import RAPDU, RaisePolicy - -from .apps.exchange import ExchangeClient, Rate, SubCommand, Errors -from .apps.ethereum import EthereumClient - -from .apps.solana import SolanaClient, ErrorType -from .apps.solana_utils import SOL_PACKED_DERIVATION_PATH -from .apps.solana_cmd_builder import SystemInstructionTransfer, Message, verify_signature -from .apps import solana_utils as SOL - -from .apps.signing_authority import SigningAuthority, LEDGER_SIGNER -from .apps.exchange_transaction_builder import get_partner_curve, craft_tx, encode_tx, extract_payout_ticker, extract_refund_ticker -from .apps import cal as cal - - -# Swap transaction infos for valid ETH <-> SOL exchanges. Tamper the values to generate errors -VALID_FUND_SOL_TX_INFOS = { - "user_id": "Daft Punk", - "account_name": "Account 0", - "in_currency": "SOL", - "in_amount": SOL.AMOUNT_BYTES, - "in_address": SOL.FOREIGN_ADDRESS -} - -# Helper to validate a FUND transaction by the Exchange app and put the Solana app in front -def valid_fund(backend, exchange_navigation_helper, tx_infos, fees): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.FUND) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.FUND), name="Partner name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(SubCommand.FUND, tx_infos, transaction_id) - ex.process_transaction(tx, fees) - encoded_tx = encode_tx(SubCommand.FUND, partner, tx) - ex.check_transaction_signature(encoded_tx) - payout_ticker = extract_payout_ticker(SubCommand.FUND, tx_infos) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker)): - exchange_navigation_helper.simple_accept() - ex.start_signing_transaction() - - -def test_solana_fund_ok(backend, exchange_navigation_helper): - valid_fund(backend, exchange_navigation_helper, VALID_FUND_SOL_TX_INFOS, SOL.FEES) - - instruction: SystemInstructionTransfer = SystemInstructionTransfer(SOL.OWNED_PUBLIC_KEY, SOL.FOREIGN_PUBLIC_KEY, SOL.AMOUNT) - message: bytes = Message([instruction]).serialize() - - sol = SolanaClient(backend) - with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): - # Instant rapdu expected - pass - signature: bytes = sol.get_async_response().data - verify_signature(SOL.OWNED_PUBLIC_KEY, message, signature) - - -def test_solana_fund_wrong_amount(backend, exchange_navigation_helper): - valid_fund(backend, exchange_navigation_helper, VALID_FUND_SOL_TX_INFOS, SOL.FEES) - - instruction: SystemInstructionTransfer = SystemInstructionTransfer(SOL.OWNED_PUBLIC_KEY, SOL.FOREIGN_PUBLIC_KEY, SOL.AMOUNT + 1) - message: bytes = Message([instruction]).serialize() - - sol = SolanaClient(backend) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): - # Instant rapdu expected - pass - rapdu: RAPDU = sol.get_async_response() - print("Received rapdu :", rapdu) - assert rapdu.status == ErrorType.SOLANA_SUMMARY_FINALIZE_FAILED - - -def test_solana_fund_wrong_destination(backend, exchange_navigation_helper): - valid_fund(backend, exchange_navigation_helper, VALID_FUND_SOL_TX_INFOS, SOL.FEES) - - instruction: SystemInstructionTransfer = SystemInstructionTransfer(SOL.OWNED_PUBLIC_KEY, SOL.FOREIGN_PUBLIC_KEY_2, SOL.AMOUNT) - message: bytes = Message([instruction]).serialize() - - sol = SolanaClient(backend) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): - # Instant rapdu expected - pass - rapdu: RAPDU = sol.get_async_response() - print("Received rapdu :", rapdu) - assert rapdu.status == ErrorType.SOLANA_SUMMARY_FINALIZE_FAILED - - -def test_solana_fund_cancel(backend, exchange_navigation_helper): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.FUND) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.FUND), name="Partner name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(SubCommand.FUND, VALID_FUND_SOL_TX_INFOS, transaction_id) - ex.process_transaction(tx, SOL.FEES) - encoded_tx = encode_tx(SubCommand.FUND, partner, tx) - ex.check_transaction_signature(encoded_tx) - payout_ticker = extract_payout_ticker(SubCommand.FUND, VALID_FUND_SOL_TX_INFOS) - - backend.raise_policy = RaisePolicy.RAISE_NOTHING - with ex.check_address(cal.get_conf_for_ticker(payout_ticker)): - exchange_navigation_helper.simple_reject() - assert ex.get_check_address_response().status == Errors.USER_REFUSED diff --git a/test/python/test_solana_sell.py b/test/python/test_solana_sell.py deleted file mode 100644 index 34dc026b..00000000 --- a/test/python/test_solana_sell.py +++ /dev/null @@ -1,107 +0,0 @@ -from ragger.backend.interface import RAPDU, RaisePolicy - -from .apps.exchange import ExchangeClient, Rate, SubCommand, Errors -from .apps.ethereum import EthereumClient - -from .apps.solana import SolanaClient, ErrorType -from .apps.solana_utils import SOL_PACKED_DERIVATION_PATH -from .apps.solana_cmd_builder import SystemInstructionTransfer, Message, verify_signature -from .apps import solana_utils as SOL - -from .apps.signing_authority import SigningAuthority, LEDGER_SIGNER -from .apps.exchange_transaction_builder import get_partner_curve, craft_tx, encode_tx, extract_payout_ticker, extract_refund_ticker -from .apps import cal as cal - - -# Sell transaction infos for valid SOL SELL. Tamper the values to generate errors -VALID_SELL_SOL_TX_INFOS = { - "trader_email": "john@doe.lost", - "out_currency": "USD", - "out_amount": {"coefficient": b"\x01", "exponent": 3}, - "in_currency": "SOL", - "in_amount": SOL.AMOUNT_BYTES, - "in_address": SOL.FOREIGN_ADDRESS -} - -# Helper to validate a SELL transaction by the Exchange app and put the Solana app in front -def valid_sell(backend, exchange_navigation_helper, tx_infos, fees): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SELL) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.FUND), name="Partner name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(SubCommand.SELL, tx_infos, transaction_id) - ex.process_transaction(tx, fees) - encoded_tx = encode_tx(SubCommand.SELL, partner, tx) - ex.check_transaction_signature(encoded_tx) - - payout_ticker = extract_payout_ticker(SubCommand.SELL, tx_infos) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker)): - exchange_navigation_helper.simple_accept() - ex.start_signing_transaction() - - -def test_solana_sell_ok(backend, exchange_navigation_helper): - valid_sell(backend, exchange_navigation_helper, VALID_SELL_SOL_TX_INFOS, SOL.FEES) - - instruction: SystemInstructionTransfer = SystemInstructionTransfer(SOL.OWNED_PUBLIC_KEY, SOL.FOREIGN_PUBLIC_KEY, SOL.AMOUNT) - message: bytes = Message([instruction]).serialize() - - sol = SolanaClient(backend) - with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): - # Instant rapdu expected - pass - signature: bytes = sol.get_async_response().data - verify_signature(SOL.OWNED_PUBLIC_KEY, message, signature) - - -def test_solana_sell_wrong_amount(backend, exchange_navigation_helper): - valid_sell(backend, exchange_navigation_helper, VALID_SELL_SOL_TX_INFOS, SOL.FEES) - - instruction: SystemInstructionTransfer = SystemInstructionTransfer(SOL.OWNED_PUBLIC_KEY, SOL.FOREIGN_PUBLIC_KEY, SOL.AMOUNT + 1) - message: bytes = Message([instruction]).serialize() - - sol = SolanaClient(backend) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): - # Instant rapdu expected - pass - rapdu: RAPDU = sol.get_async_response() - print("Received rapdu :", rapdu) - assert rapdu.status == ErrorType.SOLANA_SUMMARY_FINALIZE_FAILED - - -def test_solana_sell_wrong_destination(backend, exchange_navigation_helper): - valid_sell(backend, exchange_navigation_helper, VALID_SELL_SOL_TX_INFOS, SOL.FEES) - - instruction: SystemInstructionTransfer = SystemInstructionTransfer(SOL.OWNED_PUBLIC_KEY, SOL.FOREIGN_PUBLIC_KEY_2, SOL.AMOUNT) - message: bytes = Message([instruction]).serialize() - - sol = SolanaClient(backend) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): - # Instant rapdu expected - pass - rapdu: RAPDU = sol.get_async_response() - print("Received rapdu :", rapdu) - assert rapdu.status == ErrorType.SOLANA_SUMMARY_FINALIZE_FAILED - - -def test_solana_sell_cancel(backend, exchange_navigation_helper): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SELL) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.FUND), name="Partner name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(SubCommand.SELL, VALID_SELL_SOL_TX_INFOS, transaction_id) - ex.process_transaction(tx, SOL.FEES) - encoded_tx = encode_tx(SubCommand.SELL, partner, tx) - ex.check_transaction_signature(encoded_tx) - payout_ticker = extract_payout_ticker(SubCommand.SELL, VALID_SELL_SOL_TX_INFOS) - - backend.raise_policy = RaisePolicy.RAISE_NOTHING - with ex.check_address(cal.get_conf_for_ticker(payout_ticker)): - exchange_navigation_helper.simple_reject() - assert ex.get_check_address_response().status == Errors.USER_REFUSED diff --git a/test/python/test_solana_swap.py b/test/python/test_solana_swap.py deleted file mode 100644 index 946b94b5..00000000 --- a/test/python/test_solana_swap.py +++ /dev/null @@ -1,281 +0,0 @@ -import pytest -from time import sleep - -from ragger.backend import RaisePolicy -from ragger.utils import pack_APDU, RAPDU -from ragger.error import ExceptionRAPDU - -from .apps.exchange import ExchangeClient, Rate, SubCommand, Errors -from .apps.ethereum import EthereumClient, ERR_SILENT_MODE_CHECK_FAILED, eth_amount_to_wei_hex_string, eth_amount_to_wei - -from .apps.solana import SolanaClient, ErrorType -from .apps.solana_utils import SOL_PACKED_DERIVATION_PATH -from .apps.solana_cmd_builder import SystemInstructionTransfer, Message, verify_signature -from .apps import solana_utils as SOL - -from .apps.signing_authority import SigningAuthority, LEDGER_SIGNER -from .apps.exchange_transaction_builder import get_partner_curve, craft_tx, encode_tx, extract_payout_ticker, extract_refund_ticker -from .apps import cal as cal - - -ETH_AMOUNT = eth_amount_to_wei_hex_string(0.09000564) -ETH_FEES = eth_amount_to_wei(0.000588) - -FOREIGN_ETH_ADDRESS = b"0xd692Cb1346262F584D17B4B470954501f6715a82" -OWNED_ETH_ADDRESS = b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D" - - -# Swap transaction infos for valid ETH <-> SOL exchanges. Tamper the values to generate errors -VALID_SWAP_ETH_TO_SOL_TX_INFOS = { - "payin_address": FOREIGN_ETH_ADDRESS, - "payin_extra_id": b"", - "refund_address": OWNED_ETH_ADDRESS, - "refund_extra_id": b"", - "payout_address": SOL.OWNED_ADDRESS, - "payout_extra_id": b"", - "currency_from": "ETH", - "currency_to": "SOL", - "amount_to_provider": bytes.fromhex(ETH_AMOUNT), - "amount_to_wallet": SOL.AMOUNT_BYTES, -} - -VALID_SWAP_SOL_TO_ETH_TX_INFOS = { - "payin_address": SOL.FOREIGN_ADDRESS, - "payin_extra_id": b"", - "refund_address": SOL.OWNED_ADDRESS, - "refund_extra_id": b"", - "payout_address": OWNED_ETH_ADDRESS, - "payout_extra_id": b"", - "currency_from": "SOL", - "currency_to": "ETH", - "amount_to_provider": SOL.AMOUNT_BYTES, - "amount_to_wallet": bytes.fromhex(ETH_AMOUNT), -} - -# Helper to validate a SWAP transaction by the Exchange app and put the Solana app in front -def valid_swap(backend, exchange_navigation_helper, tx_infos, fees): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Partner name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(SubCommand.SWAP, tx_infos, transaction_id) - ex.process_transaction(tx, fees) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - - payout_ticker = extract_payout_ticker(SubCommand.SWAP, tx_infos) - refund_ticker = extract_refund_ticker(SubCommand.SWAP, tx_infos) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker), cal.get_conf_for_ticker(refund_ticker)): - exchange_navigation_helper.simple_accept() - ex.start_signing_transaction() - - -# Validate regular ETH <-> SOL exchanges - -def test_solana_swap_recipient_ok(backend, exchange_navigation_helper): - valid_swap(backend, exchange_navigation_helper, VALID_SWAP_ETH_TO_SOL_TX_INFOS, ETH_FEES) - - eth = EthereumClient(backend, derivation_path=bytes.fromhex("058000002c8000003c800000000000000000000000")) - eth.get_public_key() - eth.sign(extra_payload=bytes.fromhex("ec09850684ee180082520894d692cb1346262f584d17b4b470954501f6715a8288" + ETH_AMOUNT + "80018080")) - -def test_solana_swap_sender_ok(backend, exchange_navigation_helper): - valid_swap(backend, exchange_navigation_helper, VALID_SWAP_SOL_TO_ETH_TX_INFOS, SOL.FEES) - - instruction: SystemInstructionTransfer = SystemInstructionTransfer(SOL.OWNED_PUBLIC_KEY, SOL.FOREIGN_PUBLIC_KEY, SOL.AMOUNT) - message: bytes = Message([instruction]).serialize() - - sol = SolanaClient(backend) - with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): - pass - signature: bytes = sol.get_async_response().data - verify_signature(SOL.OWNED_PUBLIC_KEY, message, signature) - -def test_solana_swap_sender_double_sign(backend, exchange_navigation_helper): - valid_swap(backend, exchange_navigation_helper, VALID_SWAP_SOL_TO_ETH_TX_INFOS, SOL.FEES) - - instruction: SystemInstructionTransfer = SystemInstructionTransfer(SOL.OWNED_PUBLIC_KEY, SOL.FOREIGN_PUBLIC_KEY, SOL.AMOUNT) - message: bytes = Message([instruction]).serialize() - - sol = SolanaClient(backend) - with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): - pass - signature: bytes = sol.get_async_response().data - verify_signature(SOL.OWNED_PUBLIC_KEY, message, signature) - - sleep(0.5) - - with pytest.raises(ExceptionRAPDU) as e: - with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): - pass - assert e.value.status == Errors.INVALID_INSTRUCTION - -# Validate canceled ETH <-> SOL exchanges - -def test_solana_swap_recipient_cancel(backend, exchange_navigation_helper): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Partner name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(SubCommand.SWAP, VALID_SWAP_ETH_TO_SOL_TX_INFOS, transaction_id) - ex.process_transaction(tx, ETH_FEES) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - - backend.raise_policy = RaisePolicy.RAISE_NOTHING - - payout_ticker = extract_payout_ticker(SubCommand.SWAP, VALID_SWAP_ETH_TO_SOL_TX_INFOS) - refund_ticker = extract_refund_ticker(SubCommand.SWAP, VALID_SWAP_ETH_TO_SOL_TX_INFOS) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker), cal.get_conf_for_ticker(refund_ticker)): - exchange_navigation_helper.simple_reject() - assert ex.get_check_address_response().status == Errors.USER_REFUSED - -def test_solana_swap_sender_cancel(backend, exchange_navigation_helper): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Partner name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(SubCommand.SWAP, VALID_SWAP_SOL_TO_ETH_TX_INFOS, transaction_id) - ex.process_transaction(tx, SOL.FEES) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - - backend.raise_policy = RaisePolicy.RAISE_NOTHING - - payout_ticker = extract_payout_ticker(SubCommand.SWAP, VALID_SWAP_SOL_TO_ETH_TX_INFOS) - refund_ticker = extract_refund_ticker(SubCommand.SWAP, VALID_SWAP_SOL_TO_ETH_TX_INFOS) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker), cal.get_conf_for_ticker(refund_ticker)): - exchange_navigation_helper.simple_reject() - assert ex.get_check_address_response().status == Errors.USER_REFUSED - - -# SOL callbacks refuse to validate exchange fields - -def test_solana_swap_recipient_unowned_payout_address(backend): - tampered_tx_infos = VALID_SWAP_ETH_TO_SOL_TX_INFOS.copy() - tampered_tx_infos["payout_address"] = SOL.FOREIGN_ADDRESS - - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Partner name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(SubCommand.SWAP, tampered_tx_infos, transaction_id) - ex.process_transaction(tx, ETH_FEES) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - - payout_ticker = extract_payout_ticker(SubCommand.SWAP, tampered_tx_infos) - refund_ticker = extract_refund_ticker(SubCommand.SWAP, tampered_tx_infos) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker), cal.get_conf_for_ticker(refund_ticker)): - pass - assert ex.get_check_address_response().status == Errors.INVALID_ADDRESS - - -def test_solana_swap_sender_unowned_refund_address(backend): - tampered_tx_infos = VALID_SWAP_SOL_TO_ETH_TX_INFOS.copy() - tampered_tx_infos["refund_address"] = SOL.FOREIGN_ADDRESS - - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Partner name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(SubCommand.SWAP, tampered_tx_infos, transaction_id) - ex.process_transaction(tx, SOL.FEES) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - - payout_ticker = extract_payout_ticker(SubCommand.SWAP, tampered_tx_infos) - refund_ticker = extract_refund_ticker(SubCommand.SWAP, tampered_tx_infos) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker), cal.get_conf_for_ticker(refund_ticker)): - pass - assert ex.get_check_address_response().status == Errors.INVALID_ADDRESS - - -def test_solana_swap_recipient_payout_extra_id(backend): - tampered_tx_infos = VALID_SWAP_ETH_TO_SOL_TX_INFOS.copy() - tampered_tx_infos["payout_extra_id"] = "0xCAFE" - - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Partner name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(SubCommand.SWAP, tampered_tx_infos, transaction_id) - ex.process_transaction(tx, ETH_FEES) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - - payout_ticker = extract_payout_ticker(SubCommand.SWAP, tampered_tx_infos) - refund_ticker = extract_refund_ticker(SubCommand.SWAP, tampered_tx_infos) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker), cal.get_conf_for_ticker(refund_ticker)): - pass - assert ex.get_check_address_response().status == Errors.INVALID_ADDRESS - - -def test_solana_swap_recipient_refund_extra_id(backend): - tampered_tx_infos = VALID_SWAP_SOL_TO_ETH_TX_INFOS.copy() - tampered_tx_infos["refund_extra_id"] = "0xCAFE" - - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Partner name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(SubCommand.SWAP, tampered_tx_infos, transaction_id) - ex.process_transaction(tx, SOL.FEES) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - - payout_ticker = extract_payout_ticker(SubCommand.SWAP, tampered_tx_infos) - refund_ticker = extract_refund_ticker(SubCommand.SWAP, tampered_tx_infos) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker), cal.get_conf_for_ticker(refund_ticker)): - pass - assert ex.get_check_address_response().status == Errors.INVALID_ADDRESS - - -# Transaction validated in Exchange but Solana app receives a different message to sign - -def test_solana_swap_sender_wrong_amount(backend, exchange_navigation_helper): - valid_swap(backend, exchange_navigation_helper, VALID_SWAP_SOL_TO_ETH_TX_INFOS, SOL.FEES) - - instruction: SystemInstructionTransfer = SystemInstructionTransfer(SOL.OWNED_PUBLIC_KEY, SOL.FOREIGN_PUBLIC_KEY, SOL.AMOUNT + 1) - message: bytes = Message([instruction]).serialize() - - sol = SolanaClient(backend) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): - pass - rapdu: RAPDU = sol.get_async_response() - print("Received rapdu :", rapdu) - assert rapdu.status == ErrorType.SOLANA_SUMMARY_FINALIZE_FAILED - - -def test_solana_swap_sender_wrong_destination(backend, exchange_navigation_helper): - valid_swap(backend, exchange_navigation_helper, VALID_SWAP_SOL_TO_ETH_TX_INFOS, SOL.FEES) - - instruction: SystemInstructionTransfer = SystemInstructionTransfer(SOL.OWNED_PUBLIC_KEY, SOL.FOREIGN_PUBLIC_KEY_2, SOL.AMOUNT) - message: bytes = Message([instruction]).serialize() - - sol = SolanaClient(backend) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): - pass - rapdu: RAPDU = sol.get_async_response() - print("Received rapdu :", rapdu) - assert rapdu.status == ErrorType.SOLANA_SUMMARY_FINALIZE_FAILED diff --git a/test/python/test_stellar.py b/test/python/test_stellar.py index a07e2289..7180925d 100644 --- a/test/python/test_stellar.py +++ b/test/python/test_stellar.py @@ -1,403 +1,40 @@ import pytest -from typing import Optional, Tuple -from ragger.backend import RaisePolicy -from ragger.utils import RAPDU -from ragger.error import ExceptionRAPDU - -from .apps.exchange import ExchangeClient, Rate, SubCommand, Errors -from .apps.exchange_transaction_builder import get_partner_curve, craft_tx, encode_tx, extract_payout_ticker, extract_refund_ticker +from .apps.exchange_test_runner import ExchangeTestRunner, ALL_TESTS from .apps.stellar import Network, StellarClient, StellarErrors -from .apps import cal as cal -from .apps.signing_authority import SigningAuthority, LEDGER_SIGNER - -from .utils import handle_lib_call_start_or_stop - - -def test_stellar_wrong_refund(backend): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Default name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - - tx_infos = { - "payin_address": b"GCKUD4BHIYSAYHU7HBB5FDSW6CSYH3GSOUBPWD2KE7KNBERP4BSKEJDV", - "payin_extra_id": b"starlight", - "refund_address": b"abcdabcd", - "refund_extra_id": b"", - "payout_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", - "payout_extra_id": b"", - "currency_from": "XLM", - "currency_to": "ETH", - "amount_to_provider": int.to_bytes(1000, length=8, byteorder='big'), - "amount_to_wallet": b"\246\333t\233+\330\000", - } - tx = craft_tx(SubCommand.SWAP, tx_infos, transaction_id) - ex.process_transaction(tx, 100) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - - backend.raise_policy = RaisePolicy.RAISE_NOTHING - with ex.check_address(cal.get_conf_for_ticker(tx_infos["currency_to"]), cal.get_conf_for_ticker(tx_infos["currency_from"])): - pass - assert ex.get_check_address_response().status == Errors.INVALID_ADDRESS - - -def test_stellar_wrong_payout(backend): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Default name") - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - - tx_infos = { - "payin_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", - "payin_extra_id": b"", - "refund_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", - "refund_extra_id": b"", - "payout_address": b"abcdabcd", - "payout_extra_id": b"", - "currency_from": "ETH", - "currency_to": "XLM", - "amount_to_provider": int.to_bytes(1000, length=8, byteorder='big'), - "amount_to_wallet": b"\246\333t\233+\330\000", - } - tx = craft_tx(SubCommand.SWAP, tx_infos, transaction_id) - ex.process_transaction(tx, 100) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - - backend.raise_policy = RaisePolicy.RAISE_NOTHING - with ex.check_address(cal.get_conf_for_ticker(tx_infos["currency_to"]), cal.get_conf_for_ticker(tx_infos["currency_from"])): - pass - assert ex.get_check_address_response().status == Errors.INVALID_ADDRESS - - -class StellarValidTxPerformer: - # Default valid tx values used for the tests - def_path = "m/44'/148'/0'" - def_fees = 100 - def_memo = "" - def_destination = "GCKUD4BHIYSAYHU7HBB5FDSW6CSYH3GSOUBPWD2KE7KNBERP4BSKEJDV" - def_send_amount = 10000000 - - # Helper to use default args if none provided - def _maybe_default(self, fees, memo, destination, send_amount) -> Tuple[int, str, str, int]: - fees = self.def_fees if fees is None else fees - memo = self.def_memo if memo is None else memo - destination = self.def_destination if destination is None else destination - send_amount = self.def_send_amount if send_amount is None else send_amount - return (fees, memo, destination, send_amount) - - # Helper to send a valid TX to the Stellar app, provide parameters to overload te default values - def perform_stellar_tx(self, - backend, - fees: Optional[int]=None, - memo: Optional[str]=None, - destination: Optional[str]=None, - send_amount: Optional[int]=None) -> RAPDU: - fees, memo, destination, send_amount = self._maybe_default(fees, memo, destination, send_amount) - - rapdu = StellarClient(backend).send_simple_sign_tx(path=self.def_path, - network=Network.MAINNET, - fees=fees, - memo=memo, - destination=destination, - send_amount=send_amount) +# ExchangeTestRunner implementation for Stellar +class StellarTests(ExchangeTestRunner): + currency_ticker = "XLM" + valid_destination_1 = "GCKUD4BHIYSAYHU7HBB5FDSW6CSYH3GSOUBPWD2KE7KNBERP4BSKEJDV" + valid_destination_memo_1 = "" + valid_destination_2 = "GB5ZQJYKSZP3JOMOCWCBI7SPQUBW6ZL3642FUB7IYNAOC2EQMAFXI3P2" + valid_destination_memo_2 = "starlight" + valid_refund = "GCNCEJIAZ5D3APIF5XWAJ3JSSTHM4HPHE7GK3NAB6R6WWSZDB2A2BQ5B" + valid_refund_memo = "" + valid_send_amount_1 = 10000000 + valid_send_amount_2 = 446739662 + valid_fees_1 = 100 + valid_fees_2 = 10078 + fake_refund = "abcdabcd" + fake_refund_memo = "" + fake_payout = "abcdabcd" + fake_payout_memo = "" + signature_refusal_error_code = StellarErrors.SW_SWAP_CHECKING_FAIL + + def perform_final_tx(self, destination, send_amount, fees, memo): + StellarClient(self.backend).send_simple_sign_tx(path="m/44'/148'/0'", + network=Network.MAINNET, + fees=fees, + memo=memo, + destination=destination, + send_amount=send_amount) # TODO : assert signature validity - handle_lib_call_start_or_stop(backend) - return rapdu - - def perform_valid_exchange_tx(self, backend, exchange_navigation_helper, subcommand, tx_infos, fees): - ex = ExchangeClient(backend, Rate.FIXED, subcommand) - partner = SigningAuthority(curve=get_partner_curve(subcommand), name="Default name") - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(subcommand, tx_infos, transaction_id) - ex.process_transaction(tx, fees) - encoded_tx = encode_tx(subcommand, partner, tx) - ex.check_transaction_signature(encoded_tx) - payout_ticker = extract_payout_ticker(subcommand, tx_infos) - refund_ticker = extract_refund_ticker(subcommand, tx_infos) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker), cal.get_conf_for_ticker(refund_ticker)): - exchange_navigation_helper.simple_accept() - ex.start_signing_transaction() - - -############## -# SWAP tests # -############## - -class StellarValidSwapPerformer(StellarValidTxPerformer): - # Helper to send a valid SWAP TX to the Exchange app, provide parameters to overload te default values - def perform_valid_swap(self, - backend, - exchange_navigation_helper, - fees: Optional[int]=None, - memo: Optional[str]=None, - destination: Optional[str]=None, - send_amount: Optional[int]=None): - fees, memo, destination, send_amount = self._maybe_default(fees, memo, destination, send_amount) - tx_infos = { - "payin_address": destination, - "payin_extra_id": memo.encode(), - "refund_address": b"GCNCEJIAZ5D3APIF5XWAJ3JSSTHM4HPHE7GK3NAB6R6WWSZDB2A2BQ5B", - "refund_extra_id": b"", - "payout_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", - "payout_extra_id": b"", - "currency_from": "XLM", - "currency_to": "ETH", - "amount_to_provider": int.to_bytes(send_amount, length=8, byteorder='big'), - "amount_to_wallet": b"\246\333t\233+\330\000", - } - self.perform_valid_exchange_tx(backend, exchange_navigation_helper, SubCommand.SWAP, tx_infos, fees) - - -# Valid swap test with default values -def test_stellar_swap_valid_1(backend, exchange_navigation_helper): - performer = StellarValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - performer.perform_stellar_tx(backend) - - -# Valid swap test with non default values -def test_stellar_swap_valid_2(backend, exchange_navigation_helper): - fees = 10078 - memo = "starlight" - destination = "GB5ZQJYKSZP3JOMOCWCBI7SPQUBW6ZL3642FUB7IYNAOC2EQMAFXI3P2" - send_amount = 446739662 - - performer = StellarValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper, fees=fees, memo=memo, destination=destination, send_amount=send_amount) - performer.perform_stellar_tx(backend, fees=fees, memo=memo, destination=destination, send_amount=send_amount) - - -# Make a valid swap and then ask a second signature -def test_stellar_swap_refuse_double_sign(backend, exchange_navigation_helper): - performer = StellarValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - performer.perform_stellar_tx(backend) - - with pytest.raises(ExceptionRAPDU) as e: - performer.perform_stellar_tx(backend) - assert e.value.status == Errors.INVALID_INSTRUCTION - - -# Test swap with a malicious Stellar TX with tampered fees -def test_stellar_swap_wrong_fees(backend, exchange_navigation_helper): - performer = StellarValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_stellar_tx(backend, fees=performer.def_fees + 100) - assert rapdu.status == StellarErrors.SW_SWAP_CHECKING_FAIL - - -# Test swap with a malicious Stellar TX with tampered memo -def test_stellar_swap_wrong_memo(backend, exchange_navigation_helper): - performer = StellarValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_stellar_tx(backend, memo=performer.def_memo + "0") - assert rapdu.status == StellarErrors.SW_SWAP_CHECKING_FAIL - - -# Test swap with a malicious Stellar TX with tampered dest -def test_stellar_swap_wrong_dest(backend, exchange_navigation_helper): - performer = StellarValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_stellar_tx(backend, destination="GB5ZQJYKSZP3JOMOCWCBI7SPQUBW6ZL3642FUB7IYNAOC2EQMAFXI3P2") - assert rapdu.status == StellarErrors.SW_SWAP_CHECKING_FAIL - - -# Test swap with a malicious Stellar TX with tampered amount -def test_stellar_swap_wrong_amount(backend, exchange_navigation_helper): - performer = StellarValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_stellar_tx(backend, send_amount=performer.def_send_amount + 351) - assert rapdu.status == StellarErrors.SW_SWAP_CHECKING_FAIL - - -############## -# FUND tests # -############## - -class StellarValidFundPerformer(StellarValidTxPerformer): - # Helper to send a valid FUND TX to the Exchange app, provide parameters to overload te default values - def perform_valid_fund(self, - backend, - exchange_navigation_helper, - fees: Optional[int]=None, - memo: Optional[str]=None, - destination: Optional[str]=None, - send_amount: Optional[int]=None): - fees, memo, destination, send_amount = self._maybe_default(fees, memo, destination, send_amount) - tx_infos = { - "user_id": "Jon Wick", - "account_name": "My account 00", - "in_currency": "XLM", - "in_amount": int.to_bytes(send_amount, length=4, byteorder='big'), - "in_address": destination, - } - self.perform_valid_exchange_tx(backend, exchange_navigation_helper, SubCommand.FUND, tx_infos, fees) - - -# Valid fund test with default values -def test_stellar_fund_valid_1(backend, exchange_navigation_helper): - performer = StellarValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper) - performer.perform_stellar_tx(backend) - - -# Valid fund test with non default values -def test_stellar_fund_valid_2(backend, exchange_navigation_helper): - fees = 10078 - destination="GB5ZQJYKSZP3JOMOCWCBI7SPQUBW6ZL3642FUB7IYNAOC2EQMAFXI3P2" - send_amount = 446739662 - - performer = StellarValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper, fees=fees, destination=destination, send_amount=send_amount) - performer.perform_stellar_tx(backend, fees=fees, destination=destination, send_amount=send_amount) - - -# Make a valid fund and then ask a second signature -def test_stellar_fund_refuse_double_sign(backend, exchange_navigation_helper): - performer = StellarValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper) - performer.perform_stellar_tx(backend) - - with pytest.raises(ExceptionRAPDU) as e: - performer.perform_stellar_tx(backend) - assert e.value.status == Errors.INVALID_INSTRUCTION - - -# Test fund with a malicious Stellar TX with tampered fees -def test_stellar_fund_wrong_fees(backend, exchange_navigation_helper): - performer = StellarValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_stellar_tx(backend, fees=performer.def_fees + 100) - assert rapdu.status == StellarErrors.SW_SWAP_CHECKING_FAIL - - -# Test fund with a malicious Stellar TX with tampered memo -def test_stellar_fund_wrong_memo(backend, exchange_navigation_helper): - performer = StellarValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_stellar_tx(backend, memo=performer.def_memo + "0") - assert rapdu.status == StellarErrors.SW_SWAP_CHECKING_FAIL - - -# Test fund with a malicious Stellar TX with tampered dest -def test_stellar_fund_wrong_dest(backend, exchange_navigation_helper): - performer = StellarValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_stellar_tx(backend, destination="GB5ZQJYKSZP3JOMOCWCBI7SPQUBW6ZL3642FUB7IYNAOC2EQMAFXI3P2") - assert rapdu.status == StellarErrors.SW_SWAP_CHECKING_FAIL - - -# Test fund with a malicious Stellar TX with tampered amount -def test_stellar_fund_wrong_amount(backend, exchange_navigation_helper): - performer = StellarValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_stellar_tx(backend, send_amount=performer.def_send_amount + 351) - assert rapdu.status == StellarErrors.SW_SWAP_CHECKING_FAIL - - -############## -# SELL tests # -############## - -class StellarValidSellPerformer(StellarValidTxPerformer): - # Helper to send a valid SELL TX to the Exchange app, provide parameters to overload te default values - def perform_valid_sell(self, - backend, - exchange_navigation_helper, - fees: Optional[int]=None, - memo: Optional[str]=None, - destination: Optional[str]=None, - send_amount: Optional[int]=None): - fees, memo, destination, send_amount = self._maybe_default(fees, memo, destination, send_amount) - tx_infos = { - "trader_email": "john@doe.lost", - "out_currency": "USD", - "out_amount": {"coefficient": b"\x01", "exponent": 3}, - "in_currency": "XLM", - "in_amount": int.to_bytes(send_amount, length=4, byteorder='big'), - "in_address": destination, - } - self.perform_valid_exchange_tx(backend, exchange_navigation_helper, SubCommand.SELL, tx_infos, fees) - - -# Valid sell test with default values -def test_stellar_sell_valid_1(backend, exchange_navigation_helper): - performer = StellarValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper) - performer.perform_stellar_tx(backend) - - -# Valid sell test with non default values -def test_stellar_sell_valid_2(backend, exchange_navigation_helper): - fees = 10078 - destination="GB5ZQJYKSZP3JOMOCWCBI7SPQUBW6ZL3642FUB7IYNAOC2EQMAFXI3P2" - send_amount = 446739662 - - performer = StellarValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper, fees=fees, destination=destination, send_amount=send_amount) - performer.perform_stellar_tx(backend, fees=fees, destination=destination, send_amount=send_amount) - - -# Make a valid sell and then ask a second signature -def test_stellar_sell_refuse_double_sign(backend, exchange_navigation_helper): - performer = StellarValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper) - performer.perform_stellar_tx(backend) - - with pytest.raises(ExceptionRAPDU) as e: - performer.perform_stellar_tx(backend) - assert e.value.status == Errors.INVALID_INSTRUCTION - - -# Test sell with a malicious Stellar TX with tampered fees -def test_stellar_sell_wrong_fees(backend, exchange_navigation_helper): - performer = StellarValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_stellar_tx(backend, fees=performer.def_fees + 100) - assert rapdu.status == StellarErrors.SW_SWAP_CHECKING_FAIL - - -# Test sell with a malicious Stellar TX with tampered memo -def test_stellar_sell_wrong_memo(backend, exchange_navigation_helper): - performer = StellarValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_stellar_tx(backend, memo=performer.def_memo + "0") - assert rapdu.status == StellarErrors.SW_SWAP_CHECKING_FAIL - - -# Test sell with a malicious Stellar TX with tampered dest -def test_stellar_sell_wrong_dest(backend, exchange_navigation_helper): - performer = StellarValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_stellar_tx(backend, destination="GB5ZQJYKSZP3JOMOCWCBI7SPQUBW6ZL3642FUB7IYNAOC2EQMAFXI3P2") - assert rapdu.status == StellarErrors.SW_SWAP_CHECKING_FAIL +# Use a class to reuse the same Speculos instance +class TestsStellar: -# Test sell with a malicious Stellar TX with tampered amount -def test_stellar_sell_wrong_amount(backend, exchange_navigation_helper): - performer = StellarValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_stellar_tx(backend, send_amount=performer.def_send_amount + 351) - assert rapdu.status == StellarErrors.SW_SWAP_CHECKING_FAIL + @pytest.mark.parametrize('test_to_run', ALL_TESTS) + def test_stellar(self, backend, exchange_navigation_helper, test_to_run): + StellarTests(backend, exchange_navigation_helper).run_test(test_to_run) diff --git a/test/python/test_tezos.py b/test/python/test_tezos.py index 33f65eb1..cf9b11c8 100644 --- a/test/python/test_tezos.py +++ b/test/python/test_tezos.py @@ -1,400 +1,58 @@ import pytest -from typing import Optional, Tuple -from requests.exceptions import ChunkedEncodingError, ConnectionError -from urllib3.exceptions import ProtocolError -from http.client import IncompleteRead -from ragger.backend import RaisePolicy -from ragger.utils import pack_APDU, RAPDU -from ragger.error import ExceptionRAPDU -from ragger.bip import pack_derivation_path - -from .apps.exchange import ExchangeClient, Rate, SubCommand, Errors +from .apps.exchange_test_runner import ExchangeTestRunner, ALL_TESTS_EXCEPT_MEMO from .apps.tezos import TezosClient, encode_address, XTZ_PACKED_DERIVATION_PATH, StatusCode -from .apps.signing_authority import SigningAuthority, LEDGER_SIGNER -from .apps.exchange_transaction_builder import get_partner_curve, craft_tx, encode_tx, extract_payout_ticker, extract_refund_ticker -from .apps import cal as cal - -def test_tezos_wrong_refund(backend): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Default name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - - tx_infos = { - "payin_address": b"tz1YPjCVqgimTAPmxZX9egDeTFRCmrTRqmp9", - "payin_extra_id": b"starlight", - "refund_address": b"abcdabcd", - "refund_extra_id": b"", - "payout_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", - "payout_extra_id": b"", - "currency_from": "XTZ", - "currency_to": "ETH", - "amount_to_provider": int.to_bytes(1000, length=8, byteorder='big'), - "amount_to_wallet": b"\246\333t\233+\330\000", - } - tx = craft_tx(SubCommand.SWAP, tx_infos, transaction_id) - ex.process_transaction(tx, 100) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - - backend.raise_policy = RaisePolicy.RAISE_NOTHING - payout_ticker = extract_payout_ticker(SubCommand.SWAP, tx_infos) - refund_ticker = extract_refund_ticker(SubCommand.SWAP, tx_infos) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker), cal.get_conf_for_ticker(refund_ticker)): - pass - assert ex.get_check_address_response().status == Errors.INVALID_ADDRESS - - -def test_tezos_wrong_payout(backend): - ex = ExchangeClient(backend, Rate.FIXED, SubCommand.SWAP) - partner = SigningAuthority(curve=get_partner_curve(SubCommand.SWAP), name="Default name") - - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - - tx_infos = { - "payin_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", - "payin_extra_id": b"", - "refund_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", - "refund_extra_id": b"", - "payout_address": b"abcdabcd", - "payout_extra_id": b"", - "currency_from": "ETH", - "currency_to": "XTZ", - "amount_to_provider": int.to_bytes(1000, length=8, byteorder='big'), - "amount_to_wallet": b"\246\333t\233+\330\000", - } - tx = craft_tx(SubCommand.SWAP, tx_infos, transaction_id) - ex.process_transaction(tx, 100) - encoded_tx = encode_tx(SubCommand.SWAP, partner, tx) - ex.check_transaction_signature(encoded_tx) - - backend.raise_policy = RaisePolicy.RAISE_NOTHING - payout_ticker = extract_payout_ticker(SubCommand.SWAP, tx_infos) - refund_ticker = extract_refund_ticker(SubCommand.SWAP, tx_infos) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker), cal.get_conf_for_ticker(refund_ticker)): - pass - assert ex.get_check_address_response().status == Errors.INVALID_ADDRESS - - -class TezosValidTxPerformer: - # Default valid tx values used for the tests - def_path = XTZ_PACKED_DERIVATION_PATH - def_fees = 100 - def_memo = "" - def_destination = "e6330795ffe18f873b83cb13662442b87bd98c22" - def_send_amount = 10000000 - - # Helper to use default args if none provided - def _maybe_default(self, fees, memo, destination, send_amount) -> Tuple[int, str, str, int]: - fees = self.def_fees if fees is None else fees - memo = self.def_memo if memo is None else memo - destination = self.def_destination if destination is None else destination - send_amount = self.def_send_amount if send_amount is None else send_amount - return (fees, memo, destination, send_amount) - - # Helper to send a valid TX to the Tezos app, provide parameters to overload te default values - def perform_tezos_tx(self, - backend, - fees: Optional[int]=None, - memo: Optional[str]=None, - destination: Optional[str]=None, - send_amount: Optional[int]=None) -> RAPDU: - fees, memo, destination, send_amount = self._maybe_default(fees, memo, destination, send_amount) - - return TezosClient(backend).send_simple_sign_tx(path=self.def_path, - fees=fees, - memo=memo, - destination=destination, - send_amount=send_amount) - - def perform_valid_exchange_tx(self, backend, exchange_navigation_helper, subcommand, tx_infos, fees): - ex = ExchangeClient(backend, Rate.FIXED, subcommand) - partner = SigningAuthority(curve=get_partner_curve(subcommand), name="Default name") - transaction_id = ex.init_transaction().data - ex.set_partner_key(partner.credentials) - ex.check_partner_key(LEDGER_SIGNER.sign(partner.credentials)) - tx = craft_tx(subcommand, tx_infos, transaction_id) - ex.process_transaction(tx, fees) - encoded_tx = encode_tx(subcommand, partner, tx) - ex.check_transaction_signature(encoded_tx) - payout_ticker = extract_payout_ticker(subcommand, tx_infos) - refund_ticker = extract_refund_ticker(subcommand, tx_infos) - with ex.check_address(cal.get_conf_for_ticker(payout_ticker), cal.get_conf_for_ticker(refund_ticker)): - exchange_navigation_helper.simple_accept() - ex.start_signing_transaction() - - -# ############## -# # SWAP tests # -# ############## -class TezosValidSwapPerformer(TezosValidTxPerformer): - # Helper to send a valid SWAP TX to the Exchange app, provide parameters to overload te default values - def perform_valid_swap(self, - backend, - exchange_navigation_helper, - fees: Optional[int]=None, - memo: Optional[str]=None, - destination: Optional[str]=None, - send_amount: Optional[int]=None): - fees, memo, destination, send_amount = self._maybe_default(fees, memo, destination, send_amount) - tx_infos = { - "payin_address": encode_address(destination), - "payin_extra_id": memo.encode(), - "refund_address": b"tz1YPjCVqgimTAPmxZX9egDeTFRCmrTRqmp9", - "refund_extra_id": b"", - "payout_address": b"0xDad77910DbDFdE764fC21FCD4E74D71bBACA6D8D", - "payout_extra_id": b"", - "currency_from": "XTZ", - "currency_to": "ETH", - "amount_to_provider": int.to_bytes(send_amount, length=8, byteorder='big'), - "amount_to_wallet": b"\246\333t\233+\330\000", - } - self.perform_valid_exchange_tx(backend, exchange_navigation_helper, SubCommand.SWAP, tx_infos, fees) - - -# Valid swap test with default values -def test_tezos_swap_valid_1(backend, exchange_navigation_helper): - performer = TezosValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - performer.perform_tezos_tx(backend) - - -# Valid swap test with non default values -def test_tezos_swap_valid_2(backend, exchange_navigation_helper): - fees = 10078 - memo = "" - destination = "e6330795ffe18f873b83cb13662442b87bd98c40" - send_amount = 446739662 - - performer = TezosValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper, fees=fees, memo=memo, destination=destination, send_amount=send_amount) - performer.perform_tezos_tx(backend, fees=fees, memo=memo, destination=destination, send_amount=send_amount) - - -# Make a valid swap and then ask a second signature -def test_tezos_swap_refuse_double_sign(backend, exchange_navigation_helper): - performer = TezosValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - performer.perform_tezos_tx(backend) - - with pytest.raises((ChunkedEncodingError, ConnectionError, ProtocolError, IncompleteRead)): - performer.perform_tezos_tx(backend) - - -# Test swap with a malicious Tezos TX with tampered fees -def test_tezos_swap_wrong_fees(backend, exchange_navigation_helper): - performer = TezosValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_tezos_tx(backend, fees=performer.def_fees + 100) - assert rapdu.status == StatusCode.EXC_REJECT - - -# # Test swap with a malicious Tezos TX with tampered memo -# def test_tezos_swap_wrong_memo(backend, exchange_navigation_helper): -# performer = TezosValidSwapPerformer() -# performer.perform_valid_swap(backend, exchange_navigation_helper) -# backend.raise_policy = RaisePolicy.RAISE_NOTHING -# rapdu = performer.perform_tezos_tx(backend, memo=performer.def_memo + "0") -# assert rapdu.status == StatusCode.EXC_REJECT - - -# Test swap with a malicious Tezos TX with tampered dest -def test_tezos_swap_wrong_dest(backend, exchange_navigation_helper): - performer = TezosValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_tezos_tx(backend, destination="e6330795ffe18f873b83cb13662442b87bd98c45") - assert rapdu.status == StatusCode.EXC_REJECT - - -# Test swap with a malicious Tezos TX with tampered amount -def test_tezos_swap_wrong_amount(backend, exchange_navigation_helper): - performer = TezosValidSwapPerformer() - performer.perform_valid_swap(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_tezos_tx(backend, send_amount=performer.def_send_amount + 351) - assert rapdu.status == StatusCode.EXC_REJECT - - -# ############## -# # FUND tests # -# ############## - -class TezosValidFundPerformer(TezosValidTxPerformer): - # Helper to send a valid FUND TX to the Exchange app, provide parameters to overload te default values - def perform_valid_fund(self, - backend, - exchange_navigation_helper, - fees: Optional[int]=None, - memo: Optional[str]=None, - destination: Optional[str]=None, - send_amount: Optional[int]=None): - fees, memo, destination, send_amount = self._maybe_default(fees, memo, destination, send_amount) - tx_infos = { - "user_id": "Jon Wick", - "account_name": "My account 00", - "in_currency": "XTZ", - "in_amount": int.to_bytes(send_amount, length=4, byteorder='big'), - "in_address": encode_address(destination), - } - self.perform_valid_exchange_tx(backend, exchange_navigation_helper, SubCommand.FUND, tx_infos, fees) - - -# Valid fund test with default values -def test_tezos_fund_valid_1(backend, exchange_navigation_helper): - performer = TezosValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper) - performer.perform_tezos_tx(backend) - - -# Valid fund test with non default values -def test_tezos_fund_valid_2(backend, exchange_navigation_helper): - fees = 10078 - destination="e6330795ffe18f873b83cb13662442b87bd98c40" - send_amount = 446739662 - - performer = TezosValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper, fees=fees, destination=destination, send_amount=send_amount) - performer.perform_tezos_tx(backend, fees=fees, destination=destination, send_amount=send_amount) - - -# Make a valid fund and then ask a second signature -def test_tezos_fund_refuse_double_sign(backend, exchange_navigation_helper): - performer = TezosValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper) - performer.perform_tezos_tx(backend) - - with pytest.raises((ChunkedEncodingError, ConnectionError, ProtocolError, IncompleteRead)): - performer.perform_tezos_tx(backend) - - -# Test fund with a malicious Tezos TX with tampered fees -def test_tezos_fund_wrong_fees(backend, exchange_navigation_helper): - performer = TezosValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_tezos_tx(backend, fees=performer.def_fees + 100) - assert rapdu.status == StatusCode.EXC_REJECT - - -# # Test fund with a malicious Tezos TX with tampered memo -# def test_tezos_fund_wrong_memo(backend, exchange_navigation_helper): -# performer = TezosValidFundPerformer() -# performer.perform_valid_fund(backend, exchange_navigation_helper) -# backend.raise_policy = RaisePolicy.RAISE_NOTHING -# rapdu = performer.perform_tezos_tx(backend, memo=performer.def_memo + "0") -# assert rapdu.status == StatusCode.EXC_REJECT - - -# Test fund with a malicious Tezos TX with tampered dest -def test_tezos_fund_wrong_dest(backend, exchange_navigation_helper): - performer = TezosValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_tezos_tx(backend, destination="e6330795ffe18f873b83cb13662442b87bd98c45") - assert rapdu.status == StatusCode.EXC_REJECT - - -# Test fund with a malicious Tezos TX with tampered amount -def test_tezos_fund_wrong_amount(backend, exchange_navigation_helper): - performer = TezosValidFundPerformer() - performer.perform_valid_fund(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_tezos_tx(backend, send_amount=performer.def_send_amount + 351) - assert rapdu.status == StatusCode.EXC_REJECT - - -# ############## -# # SELL tests # -# ############## - -class TezosValidSellPerformer(TezosValidTxPerformer): - # Helper to send a valid SELL TX to the Exchange app, provide parameters to overload te default values - def perform_valid_sell(self, - backend, - exchange_navigation_helper, - fees: Optional[int]=None, - memo: Optional[str]=None, - destination: Optional[str]=None, - send_amount: Optional[int]=None): - fees, memo, destination, send_amount = self._maybe_default(fees, memo, destination, send_amount) - tx_infos = { - "trader_email": "john@doe.lost", - "out_currency": "USD", - "out_amount": {"coefficient": b"\x01", "exponent": 3}, - "in_currency": "XTZ", - "in_amount": int.to_bytes(send_amount, length=4, byteorder='big'), - "in_address": encode_address(destination), - } - self.perform_valid_exchange_tx(backend, exchange_navigation_helper, SubCommand.SELL, tx_infos, fees) - - -# Valid sell test with default values -def test_tezos_sell_valid_1(backend, exchange_navigation_helper): - performer = TezosValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper) - performer.perform_tezos_tx(backend) - - -# Valid sell test with non default values -def test_tezos_sell_valid_2(backend, exchange_navigation_helper): - fees = 10078 - destination="e6330795ffe18f873b83cb13662442b87bd98c40" - send_amount = 446739662 - - performer = TezosValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper, fees=fees, destination=destination, send_amount=send_amount) - performer.perform_tezos_tx(backend, fees=fees, destination=destination, send_amount=send_amount) - - -# Make a valid sell and then ask a second signature -def test_tezos_sell_refuse_double_sign(backend, exchange_navigation_helper): - performer = TezosValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper) - performer.perform_tezos_tx(backend) - - with pytest.raises((ChunkedEncodingError, ConnectionError, ProtocolError, IncompleteRead)): - performer.perform_tezos_tx(backend) - - -# Test sell with a malicious Tezos TX with tampered fees -def test_tezos_sell_wrong_fees(backend, exchange_navigation_helper): - performer = TezosValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_tezos_tx(backend, fees=performer.def_fees + 100) - assert rapdu.status == StatusCode.EXC_REJECT - - -# # Test sell with a malicious Tezos TX with tampered memo -# def test_tezos_sell_wrong_memo(backend, exchange_navigation_helper): -# performer = TezosValidSellPerformer() -# performer.perform_valid_sell(backend, exchange_navigation_helper) -# backend.raise_policy = RaisePolicy.RAISE_NOTHING -# rapdu = performer.perform_tezos_tx(backend, memo=performer.def_memo + "0") -# assert rapdu.status == StatusCode.EXC_REJECT - - -# Test sell with a malicious Tezos TX with tampered dest -def test_tezos_sell_wrong_dest(backend, exchange_navigation_helper): - performer = TezosValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_tezos_tx(backend, destination="e6330795ffe18f873b83cb13662442b87bd98c45") - assert rapdu.status == StatusCode.EXC_REJECT - +from requests.exceptions import ChunkedEncodingError, ConnectionError +from urllib3.exceptions import ProtocolError +from http.client import IncompleteRead -# Test sell with a malicious Tezos TX with tampered amount -def test_tezos_sell_wrong_amount(backend, exchange_navigation_helper): - performer = TezosValidSellPerformer() - performer.perform_valid_sell(backend, exchange_navigation_helper) - backend.raise_policy = RaisePolicy.RAISE_NOTHING - rapdu = performer.perform_tezos_tx(backend, send_amount=performer.def_send_amount + 351) - assert rapdu.status == StatusCode.EXC_REJECT +# A bit hacky but way less hassle than actually writing an actual address decoder +TEZOS_ADDRESS_DECODER = { + encode_address("e6330795ffe18f873b83cb13662442b87bd98c22"): "e6330795ffe18f873b83cb13662442b87bd98c22", + encode_address("e6330795ffe18f873b83cb13662442b87bd98c40"): "e6330795ffe18f873b83cb13662442b87bd98c40", +} + +# ExchangeTestRunner implementation for Stellar +class TezosTests(ExchangeTestRunner): + currency_ticker = "XTZ" + valid_destination_1 = encode_address("e6330795ffe18f873b83cb13662442b87bd98c22") + valid_destination_memo_1 = "" + valid_destination_2 = encode_address("e6330795ffe18f873b83cb13662442b87bd98c40") + valid_destination_memo_2 = "0" + valid_refund = "tz1YPjCVqgimTAPmxZX9egDeTFRCmrTRqmp9" + valid_refund_memo = "" + valid_send_amount_1 = 10000000 + valid_send_amount_2 = 446739662 + valid_fees_1 = 100 + valid_fees_2 = 10078 + fake_refund = "abcdabcd" + fake_refund_memo = "" + fake_payout = "abcdabcd" + fake_payout_memo = "" + signature_refusal_error_code = StatusCode.EXC_REJECT + + def perform_final_tx(self, destination, send_amount, fees, memo): + decoded_destination = TEZOS_ADDRESS_DECODER[destination] + TezosClient(self.backend).send_simple_sign_tx(path=XTZ_PACKED_DERIVATION_PATH, + fees=fees, + memo=memo, + destination=decoded_destination, + send_amount=send_amount) + + # TODO : assert signature validity + + +# Use a class to reuse the same Speculos instance +# class TestsTezos: +# TODO: Restore the class after the return in exchange in Tezos is merged + +@pytest.mark.parametrize('test_to_run', ALL_TESTS_EXCEPT_MEMO) +def test_tezos(backend, exchange_navigation_helper, test_to_run): + if "double_sign" in test_to_run: + # The double_sign protection in Tezos quits after the first send which breaks the generic TestRunner + # TODO: Remove this special handling after the return in exchange in Tezos is merged + with pytest.raises((ChunkedEncodingError, ConnectionError, ProtocolError, IncompleteRead)): + TezosTests(backend, exchange_navigation_helper).run_test(test_to_run) + else: + TezosTests(backend, exchange_navigation_helper).run_test(test_to_run)