def post_transaction_to_relay_service(self, safe_tx: SafeTx) -> bool: safe_tx.gas_token = self.gas_token estimation = self.safe_relay_service.get_estimation( self.address, safe_tx) safe_tx.base_gas = estimation["baseGas"] safe_tx.safe_tx_gas = estimation["safeTxGas"] safe_tx.gas_price = estimation["gasPrice"] last_used_nonce: Optional[int] = estimation["lastUsedNonce"] safe_tx.safe_nonce = 0 if last_used_nonce is None else last_used_nonce + 1 safe_tx.refund_receiver = estimation["refundReceiver"] or NULL_ADDRESS safe_tx.signatures = b"" # Sign transaction again self.sign_transaction(safe_tx) if yes_or_no_question("Do you want to execute tx " + str(safe_tx)): try: call_result = safe_tx.call(self.default_sender.address) print_formatted_text( HTML(f"Result: <ansigreen>{call_result}</ansigreen>")) transaction_data = self.safe_relay_service.send_transaction( self.address, safe_tx) tx_hash = transaction_data["txHash"] print_formatted_text( HTML( f"<ansigreen>Gnosis Safe Relay has queued transaction with " f"transaction-hash <b>{tx_hash}</b></ansigreen>")) return True except InvalidInternalTx as invalid_internal_tx: print_formatted_text( HTML( f"Result: <ansired>InvalidTx - {invalid_internal_tx}</ansired>" )) return False
def batch_txs(self, safe_nonce: int, safe_tx_hashes: Sequence[bytes]) -> bool: """ Submit signatures to the tx service. It's recommended to be on Safe v1.3.0 to prevent issues with `safeTxGas` and gas estimation. :return: """ if not self.ethereum_client.is_contract( LAST_MULTISEND_CALL_ONLY_CONTRACT): print_formatted_text( HTML( f"<ansired>Multisend call only contract {LAST_MULTISEND_CALL_ONLY_CONTRACT} " f"is not deployed on this network and it's required for batching txs</ansired>" )) multisend_txs = [] for safe_tx_hash in safe_tx_hashes: safe_tx, _ = self.safe_tx_service.get_safe_transaction( safe_tx_hash) # Check if call is already a Multisend call inner_txs = MultiSend.from_transaction_data(safe_tx.data) if inner_txs: multisend_txs.extend(inner_txs) else: multisend_txs.append( MultiSendTx(MultiSendOperation.CALL, safe_tx.to, safe_tx.value, safe_tx.data)) if len(multisend_txs) > 1: multisend = MultiSend(LAST_MULTISEND_CALL_ONLY_CONTRACT, self.ethereum_client) safe_tx = SafeTx( self.ethereum_client, self.address, LAST_MULTISEND_CALL_ONLY_CONTRACT, 0, multisend.build_tx_data(multisend_txs), SafeOperation.DELEGATE_CALL.value, 0, 0, 0, None, None, safe_nonce=safe_nonce, ) else: safe_tx.safe_tx_gas = 0 safe_tx.base_gas = 0 safe_tx.gas_price = 0 safe_tx.signatures = b"" safe_tx.safe_nonce = safe_nonce # Resend single transaction safe_tx = self.sign_transaction(safe_tx) if not safe_tx.signatures: print_formatted_text( HTML("<ansired>At least one owner must be loaded</ansired>")) return False else: return self.post_transaction_to_tx_service(safe_tx)