Source code for stellar_base.transaction

# coding: utf-8

import base64

from stellar_base.exceptions import NotValidParamError
from .memo import xdr_to_memo, NoneMemo
from .operation import Operation
from .stellarxdr import Xdr
from .stellarxdr.StellarXDR_type import TimeBounds
from .utils import account_xdr_object, encode_check, \

[docs]class Transaction(object): """The :class:`Transaction` object, which represents a transaction on Stellar's network. A transaction contains a list of operations (see :class:`Operation <stellar_base.operation.Operation>`), which are all executed in order as one ACID transaction, along with an associated source account, fee, account sequence number, list of signatures, both an optional memo and an optional timebound. Typically a :class:`Transaction` is placed in a :class:`TransactionEnvelope <stellar_base.transaction_envelope.TransactionEnvelope>` which is then signed before being sent over the network. For more information on Transactions in Stellar, see `Stellar's guide on transactions`_. .. _Stellar's guide on transactions: :param str source: A strkey encoded account ID (public key) of the source account for the transaction. :param sequence: The current sequence number of the source account. The sequence number is incremented by 1 automatically, as is necessary for a new transaction for a given source account. :type sequence: int, str :param dict time_bounds: A dict that contains a minTime and maxTime attribute (`{'minTime': 1534392138, 'maxTime': 1534392238}`) representing the lower and upper bound of when a given transaction will be valid. :param Memo memo: The memo being sent with the transaction, being represented as one of the subclasses of the :class:`Memo <stellar_base.memo.Memo>` object. :param int fee: The fee amount for the transaction, which should equal FEE (currently 100 stroops) multiplied by the number of operations in the transaction. See `Stellar's latest documentation on fees <>`_ for more information. :param list operations: A list of :class:`Operation <stellar_base.operation.Operation>` objects (typically its subclasses as defined in :mod:`stellar_base.operation` to be included in the transaction. By default this is an empty list. """ default_fee = 100 def __init__(self, source, sequence, time_bounds=None, memo=None, fee=None, operations=None): assert is_valid_address(source) self.source = source self.sequence = int(sequence) + 1 self.memo = memo or NoneMemo() self.fee = int(fee) if fee else self.default_fee self.operations = operations or [] # self.time_bounds = [time_bounds['minTime'], # time_bounds['maxTime']] if time_bounds else [] if time_bounds is None: self.time_bounds = [] else: if not isinstance(time_bounds, dict): raise NotValidParamError("time_bounds should be a dict that contains " "minTime and maxTime fields") self.time_bounds = [TimeBounds(minTime=time_bounds['minTime'], maxTime=time_bounds['maxTime'])]
[docs] def add_operation(self, operation): """Add an :class:`Operation <stellar_base.operation.Operation>` to this transaction. This method will only add an operation if it is not already in the transaction's list of operations, i.e. every operation in the transaction should be unique. :param Operation operation: The operation to add to this transaction. """ if operation not in self.operations: self.operations.append(operation)
[docs] def to_xdr_object(self): """Creates an XDR Transaction object that represents this :class:`Transaction`. """ source_account = account_xdr_object(self.source) memo = self.memo.to_xdr_object() operations = [o.to_xdr_object() for o in self.operations] ext = Xdr.nullclass() ext.v = 0 return Xdr.types.Transaction(source_account, self.fee, self.sequence, self.time_bounds, memo, operations, ext)
[docs] def xdr(self): """Packs and base64 encodes this :class:`Transaction` as an XDR string. """ tx = Xdr.StellarXDRPacker() tx.pack_Transaction(self.to_xdr_object()) return base64.b64encode(tx.get_buffer())
[docs] @classmethod def from_xdr_object(cls, tx_xdr_object): """Create a :class:`Transaction` object from a Transaction XDR object. """ source = encode_check('account', tx_xdr_object.sourceAccount.ed25519) sequence = tx_xdr_object.seqNum - 1 time_bounds_in_xdr = tx_xdr_object.timeBounds # TODO test if time_bounds_in_xdr: time_bounds = { 'maxTime': time_bounds_in_xdr[0].maxTime, 'minTime': time_bounds_in_xdr[0].minTime } else: time_bounds = None memo = xdr_to_memo(tx_xdr_object.memo) operations = list(map( Operation.from_xdr_object, tx_xdr_object.operations )) return cls( source=source, sequence=sequence, time_bounds=time_bounds, memo=memo, fee=tx_xdr_object.fee, operations=operations)