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
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
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
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
def _set_retry(tx: Swap): tx.status = Status.SWAP_RETRY tx.save()
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