Esempio n. 1
0
    def _create_and_broadcast(self, tx: Swap) -> bool:
        # reacts to signed tx in the DB that are ready to be sent to secret20
        signatures = [
            signature.signed_tx
            for signature in Signatures.objects(tx_id=tx.id)
        ]
        if len(signatures
               ) < self.config['signatures_threshold']:  # sanity check
            self.logger.error(
                msg=f"Tried to sign tx {tx.id}, without enough signatures"
                f" (required: {self.config['signatures_threshold']}, have: {len(signatures)})"
            )
            return False

        try:
            signed_tx = self._create_multisig(tx.unsigned_tx, tx.sequence,
                                              signatures)
            scrt_tx_hash = self._broadcast(signed_tx)
            self.logger.info(
                f"Broadcasted {tx.id} successfully - {scrt_tx_hash}")
            tx.status = Status.SWAP_SUBMITTED
            tx.dst_tx_hash = scrt_tx_hash
            tx.save()
            self.logger.info(f"Changed status of tx {tx.id} to submitted")
            return True
        except (RuntimeError, OperationError) as e:
            self.logger.error(
                msg=f"Failed to create multisig and broadcast, error: {e}")
            tx.status = Status.SWAP_FAILED
            tx.save()
            return False
Esempio n. 2
0
    def _validate_and_sign(self, tx: Swap):
        """
        Makes sure that the tx is valid and signs it

        :raises: ValueError
        """
        if self._is_signed(tx):
            self.logger.debug(
                f"This signer already signed this transaction. Waiting for other signers... id:{tx.id}"
            )
            return

        if not self._is_valid(tx):
            self.logger.error(
                f"Validation failed. Signer: {self.multisig.name}. Tx id:{tx.id}."
            )
            tx.status = Status.SWAP_FAILED
            tx.save()
            raise ValueError

        try:
            signed_tx = self._sign_with_secret_cli(tx.unsigned_tx, tx.sequence)
        except RuntimeError as e:
            tx.status = Status.SWAP_FAILED
            tx.save()
            raise ValueError from e

        try:
            Signatures(tx_id=tx.id,
                       signer=self.multisig.name,
                       signed_tx=signed_tx).save()
        except OperationError as e:
            self.logger.error(f'Failed to save tx in database: {tx}')
            raise ValueError from e
Esempio n. 3
0
 def _retry(self, tx: Swap):
     for signature in Signatures.objects(tx_id=tx.id):
         signature.delete()
     tx.status = Status.SWAP_UNSIGNED
     tx.sequence = self.sequence
     tx.save()
     self.sequence = self.sequence + 1
Esempio n. 4
0
    def _broadcast_and_save(self, msg: message.Submit, swap: Swap, swap_id: str):
        try:
            tx_hash = self._broadcast_transaction(msg)
            swap.dst_tx_hash = tx_hash

            swap.status = Status.SWAP_SUBMITTED
            self.pending_txs.append(swap_id)
        except (ValueError, TransactionNotFound) as e:
            self.logger.critical(f"Failed to broadcast transaction for msg {repr(msg)}: {e}")
        finally:
            try:
                swap.save()
            except (DuplicateKeyError, NotUniqueError):
                pass
Esempio n. 5
0
def _set_retry(tx: Swap):
    tx.status = Status.SWAP_RETRY
    tx.save()
Esempio n. 6
0
    def _handle_swap(self, swap_data: str, src_token: str, dst_token: str):
        swap_json = swap_query_res(swap_data)
        # this is an id, and not the TX hash since we don't actually know where the TX happened, only the id of the
        # swap reported by the contract
        swap_id = get_swap_id(swap_json)
        dest_address = swap_json['destination']
        self.logger.info(f'{swap_json}')
        amount = int(swap_json['amount'])

        if dst_token == 'native':
            data, tx_dest, tx_amount, tx_token, fee = self._tx_native_params(
                amount, dest_address)
        else:
            self.erc20.address = dst_token
            data, tx_dest, tx_amount, tx_token, fee = self._tx_erc20_params(
                amount, dest_address, dst_token)

        if not self._validate_fee(amount, fee):
            self.logger.error("Tried to swap an amount too low to cover fee")
            swap = Swap(src_network="Secret",
                        src_tx_hash=swap_id,
                        unsigned_tx=data,
                        src_coin=src_token,
                        dst_coin=dst_token,
                        dst_address=dest_address,
                        amount=str(amount),
                        dst_network="Ethereum",
                        status=Status.SWAP_FAILED)
            try:
                swap.save()
            except (DuplicateKeyError, NotUniqueError):
                pass
            return

        msg = message.Submit(
            tx_dest,
            tx_amount,  # if we are swapping token, no ether should be rewarded
            int(swap_json['nonce']),
            tx_token,
            fee,
            data)
        # todo: check we have enough ETH
        swap = Swap(src_network="Secret",
                    src_tx_hash=swap_id,
                    unsigned_tx=data,
                    src_coin=src_token,
                    dst_coin=dst_token,
                    dst_address=dest_address,
                    amount=str(amount),
                    dst_network="Ethereum",
                    status=Status.SWAP_FAILED)
        try:
            tx_hash = self._broadcast_transaction(msg)
            swap.dst_tx_hash = tx_hash
            swap.status = Status.SWAP_SUBMITTED
        except (ValueError, TransactionNotFound) as e:
            self.logger.critical(
                f"Failed to broadcast transaction for msg {repr(msg)}: {e}")
        finally:
            try:
                swap.save()
            except (DuplicateKeyError, NotUniqueError):
                pass