def _wait_for_final_transaction_outcome(transaction_hash: str, wallet: Wallet, client: Client) -> Response: """ The core logic of reliable submission. Polls the ledger until the result of the transaction can be considered final, meaning it has either been included in a validated ledger, or the transaction's lastLedgerSequence has been surpassed by the latest ledger sequence (meaning it will never be included in a validated ledger). """ sleep(_LEDGER_CLOSE_TIME) # new persisted transaction # query transaction by hash transaction_response = client.request(Tx(transaction=transaction_hash)) result = cast(Dict[str, Any], transaction_response.result) if "validated" in result and result["validated"]: # result is in a validated ledger, outcome is final return transaction_response last_ledger_sequence = result["LastLedgerSequence"] latest_ledger_sequence = get_latest_validated_ledger_sequence(client) if last_ledger_sequence > latest_ledger_sequence: # outcome is not yet final return _wait_for_final_transaction_outcome(transaction_hash, wallet, client) raise LastLedgerSequenceExpiredException(last_ledger_sequence, latest_ledger_sequence)
def submit_transaction( transaction: Transaction, client: Client, ) -> Response: """ Submits a transaction to the ledger. Args: transaction: the Transaction to be submitted. client: the network client with which to submit the transaction. Returns: The response from the ledger. Raises: XRPLRequestFailureException: if the rippled API call fails. """ transaction_json = transaction.to_xrpl() transaction_blob = encode(transaction_json) response = client.request(SubmitOnly(tx_blob=transaction_blob)) if response.is_successful(): return response result = cast(Dict[str, Any], response.result) raise XRPLRequestFailureException(result)
def get_account_info(address: str, client: Client) -> Response: """ Query the ledger for account info of given address. Args: address: the account to query. client: the network client used to make network calls. Returns: The account info for the address. Raises: XRPLRequestFailureException: if the transaction fails. """ response = client.request( AccountInfo( account=address, ledger_index="validated", ) ) if response.is_successful(): return response result = cast(Dict[str, Any], response.result) raise XRPLRequestFailureException(result["error"], result["error_message"])
def get_latest_validated_ledger_sequence(client: Client) -> int: """ Returns the sequence number of the latest validated ledger. Args: client: The network client to use to send the request. Returns: The sequence number of the latest validated ledger. """ response = client.request(Ledger(ledger_index="validated")) result = cast(Dict[str, Any], response.result) return cast(int, result["ledger_index"])
def get_fee(client: Client) -> str: """ Query the ledger for the current minimum transaction fee. Args: client: the network client used to make network calls. Returns: The minimum fee for transactions. """ response = client.request(Fee()) result = cast(Dict[str, Any], response.result) return cast(str, result["drops"]["minimum_fee"])
def submit_transaction_blob( transaction_blob: str, client: Client, ) -> Response: """ Submits a transaction blob to the ledger. Args: transaction_blob: the transaction blob to be submitted. client: the network client with which to submit the transaction. Returns: The response from the ledger. """ submit_request = SubmitOnly(tx_blob=transaction_blob) return client.request(submit_request)
def get_transaction_from_hash(tx_hash: str, client: Client) -> Response: """ Given a transaction hash, fetch the corresponding transaction from the ledger. Args: tx_hash: the transaction hash. client: the network client used to communicate with a rippled node. Returns: The Response object containing the transaction info. Raises: XRPLRequestFailureException: if the transaction fails. """ response = client.request(Tx(transaction=tx_hash)) if not response.is_successful(): result = cast(Dict[str, Any], response.result) raise XRPLRequestFailureException(result) return response
def get_latest_validated_ledger_sequence(client: Client) -> int: """ Returns the sequence number of the latest validated ledger. Args: client: The network client to use to send the request. Returns: The sequence number of the latest validated ledger. Raises: XRPLRequestFailureException: if the rippled API call fails. """ response = client.request(Ledger(ledger_index="validated")) result = cast(Dict[str, Any], response.result) if response.is_successful(): return cast(int, result["ledger_index"]) raise XRPLRequestFailureException(result)
def get_fee(client: Client) -> str: """ Query the ledger for the current minimum transaction fee. Args: client: the network client used to make network calls. Returns: The minimum fee for transactions. Raises: XRPLRequestFailureException: if the rippled API call fails. """ response = client.request(Fee()) result = cast(Dict[str, Any], response.result) if response.is_successful(): return cast(str, result["drops"]["minimum_fee"]) raise XRPLRequestFailureException(result)
def get_transaction_from_hash( tx_hash: str, client: Client, binary: bool = False, min_ledger: Optional[int] = None, max_ledger: Optional[int] = None, ) -> Response: """ Given a transaction hash, fetch the corresponding transaction from the ledger. Args: tx_hash: the transaction hash. client: the network client used to communicate with a rippled node. binary: If true, return transaction data and metadata as binary serialized to hexadecimal strings. If false, return transaction data and metadata as JSON. The default is false. min_ledger: Use this with max_ledger to specify a range of up to 1000 ledger indexes, starting with this ledger (inclusive). If the server cannot find the transaction, it confirms whether it was able to search all the ledgers in this range. max_ledger: Use this with min_ledger to specify a range of up to 1000 ledger indexes, ending with this ledger (inclusive). If the server cannot find the transaction, it confirms whether it was able to search all the ledgers in the requested range. Returns: The Response object containing the transaction info. Raises: XRPLRequestFailureException: if the transaction fails. """ response = client.request( Tx( transaction=tx_hash, binary=binary, max_ledger=max_ledger, min_ledger=min_ledger, )) if not response.is_successful(): result = cast(Dict[str, Any], response.result) raise XRPLRequestFailureException(result) return response
def get_latest_transaction(account: str, client: Client) -> Response: """ Fetches the most recent transaction on the ledger associated with an account. Args: account: the classic address of the account. client: the network client used to communicate with a rippled node. Returns: The Response object containing the transaction info. Raises: XRPLRequestFailureException: if the transaction fails. """ # max == -1 means that it's the most recent validated ledger version response = client.request( AccountTx(account=account, ledger_index_max=-1, limit=1)) if not response.is_successful(): result = cast(Dict[str, Any], response.result) raise XRPLRequestFailureException(result) return response
def get_account_transactions(address: str, client: Client) -> List[Dict[str, Any]]: """ Query the ledger for a list of transactions that involved a given account. Args: address: the account to query. client: the network client used to make network calls. Returns: The transaction history for the address. Raises: XRPLRequestFailureException: if the transaction fails. """ request = AccountTx(account=address) response = client.request(request) result = cast(Dict[str, Any], response.result) if not response.is_successful(): raise XRPLRequestFailureException(result) return cast(List[Dict[str, Any]], result["transactions"])