Ejemplo n.º 1
0
    def test_update_attempt_list(self):
        trigger = AttemptListTrigger(
            tx="792873", receiver=1, currency="waves", senders=[TransactionSender(address="723789")])

        attempt_list = TransactionAttemptList(
            trigger=trigger,
            attempts=[
                TransactionAttempt(
                    currency="coin",
                    fee=100,
                    receivers=[TransactionAttemptReceiver(address="973846", amount=234)],
                    sender="739264857")
            ])

        expected_query = dict()
        expected_query[TransactionAttemptList.DICT_ID] = attempt_list.attempt_list_id
        mock_find_one_result = MagicMock()
        mock_attempt_list_as_dict_result = MagicMock()

        self._collection.find_one_and_replace.return_value = mock_find_one_result
        self._serializer.attempt_list_as_dict.return_value = mock_attempt_list_as_dict_result

        self._storage.update_attempt_list(attempt_list)

        self._collection.find_one_and_replace.assert_called_once_with(expected_query, mock_attempt_list_as_dict_result)
        self._serializer.attempt_list_as_dict.assert_called_once_with(attempt_list)
Ejemplo n.º 2
0
    def test_revert_attempt_list_conversion_waves(self):
        """Ensures that the fee is not converted when using the asset_integer_converter_service."""
        trigger = AttemptListTrigger(
            tx="792873",
            receiver=1,
            currency="coin",
            senders=[TransactionSender(address="723789")])

        attempt_list = TransactionAttemptList(
            trigger=trigger,
            attempts=[
                TransactionAttempt(
                    currency="waves",
                    fee=100,
                    receivers=[
                        TransactionAttemptReceiver(address="973846",
                                                   amount=234),
                        TransactionAttemptReceiver(address="9327468",
                                                   amount=235)
                    ],
                    sender="739264857")
            ])

        expected_attempt_list = TransactionAttemptList(
            trigger=trigger,
            attempts=[
                TransactionAttempt(
                    currency="waves",
                    fee=100,
                    receivers=[
                        TransactionAttemptReceiver(address="973846",
                                                   amount=0.234),
                        TransactionAttemptReceiver(address="9327468",
                                                   amount=0.235)
                    ],
                    sender="739264857")
            ])

        def mock_converter(value: Any):
            return value / 1000

        self._asset_integer_converter_service.revert_amount_conversion.side_effect = mock_converter

        res = self._attempt_list_converter.revert_attempt_list_conversion(
            attempt_list)

        self.assertEqual(res, expected_attempt_list)
    def test_handle_transaction_multi_receiver(self, mock_datetime: MagicMock):
        now = MagicMock()
        mock_datetime.utcnow.return_value = now
        gateway_coin_address = self._gateway_managed_receiver.address
        dst_waves_address = '039769'
        incoming_transaction = Transaction(
            tx='723968', receivers=[self._gateway_managed_receiver])

        amount_after_fees = self._gateway_managed_receiver.amount - self._coin_standard_fee - self._gateway_fee

        attempts = [
            TransactionAttempt(sender=gateway_coin_address,
                               currency="coin",
                               fee=self._coin_standard_fee,
                               receivers=[
                                   TransactionAttemptReceiver(
                                       address=self._gateway_address,
                                       amount=amount_after_fees),
                                   TransactionAttemptReceiver(
                                       address=self._gateway_owner_address,
                                       amount=self._gateway_fee)
                               ]),
            TransactionAttempt(sender=self._gateway_waves_address,
                               fee=self._waves_standard_fee,
                               currency="waves",
                               receivers=[
                                   TransactionAttemptReceiver(
                                       address=dst_waves_address,
                                       amount=amount_after_fees)
                               ])
        ]

        trigger = AttemptListTrigger(tx=incoming_transaction.tx,
                                     currency="coin",
                                     receiver=0)

        attempt_list = TransactionAttemptList(trigger=trigger,
                                              attempts=attempts,
                                              created_at=now,
                                              last_modified=now)

        self._attempt_list_storage.find_by_trigger.return_value = None
        self._map_storage.get_waves_address_by_coin_address.return_value = dst_waves_address

        self._coin_transaction_consumer_impl.handle_transaction(
            incoming_transaction)

        self._attempt_list_storage.find_by_trigger.assert_any_call(
            AttemptListTrigger(tx=incoming_transaction.tx,
                               receiver=0,
                               currency="coin"))
        self._map_storage.get_waves_address_by_coin_address.assert_called_once_with(
            gateway_coin_address)
        self._attempt_service.continue_transaction_attempt_list.assert_not_called(
        )
        self._attempt_list_storage.safely_save_attempt_list.assert_called_once_with(
            attempt_list)
Ejemplo n.º 4
0
    def test_continue_transaction_attempt_list(self, mock_datetime: MagicMock):
        now = MagicMock()
        mock_datetime.utcnow.return_value = now

        trigger = AttemptListTrigger(
            tx="792873", receiver=1, currency="waves", senders=[TransactionSender(address="723789")])

        attempt_list = TransactionAttemptList(
            trigger=trigger,
            attempts=[
                TransactionAttempt(
                    currency="coin",
                    fee=100,
                    receivers=[TransactionAttemptReceiver(address="973846", amount=234)],
                    sender="739264857")
            ],
            created_at=now,
            last_modified=now)

        expected_attempt_list = TransactionAttemptList(
            trigger=trigger,
            attempts=[
                TransactionAttempt(
                    currency="coin",
                    fee=100,
                    receivers=[TransactionAttemptReceiver(address="973846", amount=234)],
                    sender="739264857"),
            ],
            transactions=["97238"],
            created_at=now,
            last_modified=now)

        mock_transaction = Transaction(tx="97238", receivers=[TransactionReceiver(address="973846", amount=234)])

        mock_secret = "9723684"

        self._secret_service.get_secret_by_address.return_value = mock_secret
        self._transaction_service.send_coin.return_value = mock_transaction

        self._attempt_list_service.continue_transaction_attempt_list(attempt_list)

        self._storage.update_attempt_list.assert_called_once_with(expected_attempt_list)
        self._transaction_service.send_coin.assert_called_once_with(attempt_list.attempts[0], mock_secret)
        self._secret_service.get_secret_by_address("coin", "739264857")
    def revert_attempt_list_conversion(self, attempt_list: TransactionAttemptList):
        converted_attempts = []

        for attempt in attempt_list.attempts:
            converted_attempts.append(self.revert_attempt_conversion(attempt))

        return TransactionAttemptList(
            attempts=converted_attempts,
            transactions=attempt_list.transactions,
            trigger=attempt_list.trigger,
            created_at=attempt_list.created_at,
            last_modified=attempt_list.last_modified,
            tries=attempt_list.tries,
            attempt_list_id=attempt_list.attempt_list_id)
    def test_handle_receiver(self, mock_datetime: MagicMock):
        now = MagicMock()
        mock_datetime.utcnow.return_value = now

        coin_receiver = "82396457"
        amount_after_fees = self._gateway_waves_receiver.amount - 2 * self._coin_standard_fee - self._gateway_fee
        tx = "78265"
        self._coin_address_validation_service.validate_address.return_value = True

        attempts = [
            TransactionAttempt(sender=self._gateway_coin_address_secret.public,
                               fee=self._coin_standard_fee,
                               currency="coin",
                               receivers=[
                                   TransactionAttemptReceiver(
                                       address=coin_receiver,
                                       amount=amount_after_fees)
                               ]),
            TransactionAttempt(sender=self._gateway_coin_address_secret.public,
                               fee=self._coin_standard_fee,
                               currency="coin",
                               receivers=[
                                   TransactionAttemptReceiver(
                                       address=self._gateway_owner_address,
                                       amount=self._gateway_fee)
                               ])
        ]

        trigger = AttemptListTrigger(tx=tx, currency="waves", receiver=0)

        self._attempt_list_storage.find_by_trigger.return_value = None
        attempt_list = TransactionAttemptList(trigger=trigger,
                                              attempts=attempts,
                                              created_at=now,
                                              last_modified=now)

        self._waves_chain_query_service.get_coin_receiver_address_from_transaction.return_value = coin_receiver

        self._waves_transaction_consumer_impl._handle_receiver(
            tx, self._gateway_waves_receiver, 0)

        self._waves_chain_query_service.get_coin_receiver_address_from_transaction.assert_called_once_with(
            tx)
        self._attempt_service.continue_transaction_attempt_list.assert_not_called(
        )
        self._attempt_list_storage.find_by_trigger.assert_called_once_with(
            AttemptListTrigger(tx=tx, currency="waves", receiver=0))
        self._attempt_list_storage.safely_save_attempt_list.assert_called_once_with(
            attempt_list)
    def setUp(self):
        self._attempt_list_serializer = TransactionAttemptListSerializer()

        trigger = AttemptListTrigger(
            tx="792873", receiver=1, currency="waves", senders=[TransactionSender(address="723789")])

        self._attempt_list = TransactionAttemptList(
            trigger=trigger,
            attempts=[
                TransactionAttempt(
                    currency="coin",
                    fee=100,
                    receivers=[
                        TransactionAttemptReceiver(address="973846", amount=234),
                        TransactionAttemptReceiver(address="9327468", amount=235)
                    ],
                    sender="739264857")
            ])
    def attempt_list_from_dict(self, data: dict) -> TransactionAttemptList:
        created_at = None
        last_modified = None
        tries = TransactionAttemptList.DEFAULT_TRIES

        if TransactionAttemptList.DICT_CREATED_AT in data:
            created_at = data[TransactionAttemptList.DICT_CREATED_AT]

        if TransactionAttemptList.DICT_LAST_MODIFIED in data:
            last_modified = data[TransactionAttemptList.DICT_LAST_MODIFIED]

        if TransactionAttemptList.DICT_TRIES in data:
            tries = data[TransactionAttemptList.DICT_TRIES]

        return TransactionAttemptList(
            trigger=self._trigger_from_dict(data[TransactionAttemptList.DICT_TRIGGER]),
            attempts=map_array(self._attempt_from_dict, data[TransactionAttemptList.DICT_ATTEMPTS]),
            transactions=data[TransactionAttemptList.DICT_TRANSACTIONS],
            last_modified=last_modified,
            created_at=created_at,
            tries=tries,
            attempt_list_id=data[TransactionAttemptList.DICT_ID])
Ejemplo n.º 9
0
    def _handle_receiver(self,
                         tx: str,
                         receiver: TransactionReceiver,
                         index: int,
                         senders: List[TransactionSender] = None) -> None:

        # ---------- Pre-Calculation ----------

        # fee to be used for the custom currency
        coin_fee = cast(int, self._fee_service.get_coin_fee())

        # fee to be transferred to the Gateway owner
        gateway_fee = cast(int, self._fee_service.get_gateway_fee())

        received_amount = cast(int, receiver.amount)

        # the amount of coins to be transferred after applying the fees
        if self._only_one_transaction_receiver:
            amount_after_fees = received_amount - 2 * coin_fee - gateway_fee
        else:
            amount_after_fees = received_amount - coin_fee - gateway_fee

        # receiver coin address
        coin_receiver = self._waves_chain_query_service.get_coin_receiver_address_from_transaction(
            tx)

        # ---------- Pre-Check ----------

        if not self._coin_address_validation_service.validate_address(
                coin_receiver):
            self._logger.warning(
                "Received transaction %s with an invalid coin receiver address %s. "
                "Will be skipped.", tx, coin_receiver)
            return

        if self._gateway_coin_holder_secret.public == coin_receiver:
            self._logger.warning(
                "Received transaction %s with the address of the Gateway coin holder."
                "Will be skipped as an transaction to itself has no effect.",
                tx)
            return

        # transaction must have at least a specific amount to be processed
        if amount_after_fees < 0:
            self._logger.warning(
                "Received transaction %s with an amount of %s, but it is less than the at least "
                "required amount. Will be skipped.", tx, receiver.amount)
            return

        attempt_list = self._attempt_list_storage.find_by_trigger(
            AttemptListTrigger(tx=tx, currency="waves", receiver=index))

        if attempt_list is None:
            trigger = AttemptListTrigger(tx=tx,
                                         receiver=index,
                                         currency="waves",
                                         senders=senders)

            attempts = list()

            if self._only_one_transaction_receiver:
                attempts.append(
                    TransactionAttempt(
                        sender=self._gateway_coin_holder_secret.public,
                        fee=coin_fee,
                        currency="coin",
                        receivers=[
                            TransactionAttemptReceiver(
                                address=self._gateway_owner_address,
                                amount=gateway_fee)
                        ]))

                attempts.append(
                    TransactionAttempt(
                        sender=self._gateway_coin_holder_secret.public,
                        fee=coin_fee,
                        currency="coin",
                        receivers=[
                            TransactionAttemptReceiver(
                                address=coin_receiver,
                                amount=amount_after_fees)
                        ]))
            else:
                attempts.append(
                    TransactionAttempt(
                        sender=self._gateway_coin_holder_secret.public,
                        fee=coin_fee,
                        currency="coin",
                        receivers=[
                            TransactionAttemptReceiver(
                                address=coin_receiver,
                                amount=amount_after_fees),
                            TransactionAttemptReceiver(
                                address=self._gateway_owner_address,
                                amount=gateway_fee)
                        ]))

            attempt_list = TransactionAttemptList(
                trigger,
                attempts,
                last_modified=datetime.datetime.utcnow(),
                created_at=datetime.datetime.utcnow())

            self._attempt_list_storage.safely_save_attempt_list(attempt_list)
            self._logger.info('Created new attempt list %s',
                              str(attempt_list.attempt_list_id))
    def _handle_transaction_receiver(self,
                                     tx: str,
                                     receiver: TransactionReceiver,
                                     index: int,
                                     senders: List[TransactionSender] = None):

        # ---------- Pre-Calculation ----------

        # the gateway address that coins were transferred to
        gateway_managed_address = receiver.address

        # the custom currency fee to be used
        coin_fee = cast(int, self._fee_service.get_coin_fee())

        # the waves fee to be used; not used in the calculation
        waves_fee = cast(int, self._fee_service.get_waves_fee())

        # the fee for the gateway owner; service costs
        gateway_fee = cast(int, self._fee_service.get_gateway_fee())

        # the amount of coins that were received by this receiver
        received_amount = cast(int, receiver.amount)

        # the waves address to receive the amount of coins
        receiver_waves_address = self._map_storage.get_waves_address_by_coin_address(
            gateway_managed_address)

        # the amount of coins to be transferred after applying the fees
        if self._only_one_transaction_receiver:
            amount_after_fees = received_amount - 2 * coin_fee - gateway_fee
        else:
            amount_after_fees = received_amount - coin_fee - gateway_fee

        # ---------- Pre-Check ----------

        # transaction must have minimum amount to be handled
        if amount_after_fees <= 0:
            self._logger.warn(
                "Received transaction %s with an amount of %s, but it is less than the at least "
                "required amount. Will be skipped, but marked as processed.",
                tx, receiver.amount)
            return

        # no mapping was found for some reason; this in an internal error as this should
        # already be prevented by the filter method
        if receiver_waves_address is None:
            raise MappingNotFoundForCoinAddress(gateway_managed_address)

        attempt_list = self._attempt_list_storage.find_by_trigger(
            AttemptListTrigger(tx=tx, currency="coin", receiver=index))

        if attempt_list is None:

            attempts = list()

            if self._only_one_transaction_receiver:
                attempts.append(
                    TransactionAttempt(
                        sender=gateway_managed_address,
                        currency="coin",
                        fee=coin_fee,
                        receivers=[
                            TransactionAttemptReceiver(
                                address=self._gateway_coin_address,
                                amount=amount_after_fees),
                        ]))

                attempts.append(
                    TransactionAttempt(
                        sender=gateway_managed_address,
                        currency="coin",
                        fee=coin_fee,
                        receivers=[
                            TransactionAttemptReceiver(
                                address=self._gateway_owner_address,
                                amount=gateway_fee)
                        ]))
            else:
                attempts.append(
                    TransactionAttempt(
                        sender=gateway_managed_address,
                        currency="coin",
                        fee=coin_fee,
                        receivers=[
                            TransactionAttemptReceiver(
                                address=self._gateway_coin_address,
                                amount=amount_after_fees),
                            TransactionAttemptReceiver(
                                address=self._gateway_owner_address,
                                amount=gateway_fee)
                        ]))

            attempts.append(
                TransactionAttempt(
                    sender=self._gateway_pywaves_address.address,
                    fee=waves_fee,
                    currency="waves",
                    receivers=[
                        TransactionAttemptReceiver(
                            address=receiver_waves_address,
                            amount=amount_after_fees)
                    ]))

            trigger = AttemptListTrigger(tx, index, "coin", senders=senders)
            attempt_list = TransactionAttemptList(
                trigger,
                attempts,
                last_modified=datetime.datetime.utcnow(),
                created_at=datetime.datetime.utcnow())
            self._attempt_list_storage.safely_save_attempt_list(attempt_list)
            self._logger.info('Created new attempt list %s',
                              str(attempt_list.attempt_list_id))