stellar module
# -*- coding: utf-8 -*- __all__ = [ 'random_keypair', 'account_from_secret', 'setup_test_network', 'setup_public_network', 'setup_custom_network', 'get_current_network', 'account', 'transaction', 'ledger', 'operation', 'transactions', 'ledgers', 'effects', 'operations', 'payments', 'find_payment_path', 'assets', 'trades', 'orderbook', 'new_transaction', 'post_transaction', 'Fetchable', 'NewTransaction', 'Asset', 'Accounts', 'Transactions', 'Ledgers', 'Operations', 'Payments', 'Effects', 'Offers', 'Orderbooks', 'Assets', 'PaymentPaths', ] from .keys import random_keypair, account_from_secret from .api import setup_test_network, setup_public_network, setup_custom_network, get_current_network from .api import account, transaction, ledger, operation from .api import transactions, ledgers, effects, operations, payments from .api import find_payment_path, assets, trades, orderbook from .api import new_transaction, post_transaction from .api import Fetchable, NewTransaction from .api import Asset, Accounts, Transactions, Ledgers, Operations, Payments from .api import Effects, Offers, Orderbooks, Assets, PaymentPaths import logging try: # Python 2.7+ from logging import NullHandler except ImportError: class NullHandler(logging.Handler): def emit(self, record): pass logging.getLogger(__name__).addHandler(NullHandler())
Functions
def account(
accid)
Returns Fetchable object to retrieve account details of the accid. You can chain other operations e.g. stellar.account(accid).operations() to retrieve operations of the given account.
a = stellar.account('GAEE..IB4V..').fetch() a_ops = stellar.account('GAEE..IB4V..'). operations().fetch().entries()
def account(accid): """ Returns Fetchable object to retrieve account details of the accid. You can chain other operations e.g. stellar.account(accid).operations() to retrieve operations of the given account. a = stellar.account('GAEE..IB4V..').fetch() a_ops = stellar.account('GAEE..IB4V..'). operations().fetch().entries() """ return Accounts(accid)
def account_from_secret(
secret)
Returns account-id given the secret
def account_from_secret(secret): """Returns account-id given the secret""" key = base64.b32decode(secret) checksum = struct.pack('H', crc16.crc16xmodem(key[0:-2])) keytype = binascii.a2b_hex(KEY_TYPES['seed']) if key[0] != keytype or key[-2:] != checksum: raise Exception('Invalid Secret Key') signing_key = ed25519.SigningKey(key[1:-2]) payload = binascii.a2b_hex(KEY_TYPES['public']) + signing_key.get_verifying_key().to_bytes() checksum = crc16.crc16xmodem(payload) checksum = struct.pack('H', checksum) return base64.b32encode(payload + checksum)
def assets(
asset_code=None, asset_issuer=None)
Returns all the assets. Optionally assets can be filtered based on asset_code or asset_issuer.
usds = stellar.assets(asset_code='USD').fetch().entries()
def assets(asset_code=None, asset_issuer=None): """ Returns all the assets. Optionally assets can be filtered based on asset_code or asset_issuer. usds = stellar.assets(asset_code='USD').fetch().entries() """ return Assets._All(asset_code, asset_issuer)
def effects(
)
Returns all the effets that are being performed on stellar network.
es = stellar.effects().fetch()
def effects(): """ Returns all the effets that are being performed on stellar network. es = stellar.effects().fetch() """ return Effects._All()
def find_payment_path(
from_account, to_account, to_asset, amount)
A path payment specifies a series of assets to route a payment through from source asset (the asset debited from the payer) to destination asset (the asset credited to the payee). As part of the search, horizon will load a list of assets available to the source account id and will find any payment paths from those source assets to the desired destination asset. The search’s amount parameter will be used to determine if there a given path can satisfy a payment of the desired amount.
path = stellar.find_payment_path('GAEE__ADED__', 'GDAA__3EFD__', ('USD', 'GDKG__GZ2O__'), "10.1").fetch()
def find_payment_path(from_account, to_account, to_asset, amount): """ A path payment specifies a series of assets to route a payment through from source asset (the asset debited from the payer) to destination asset (the asset credited to the payee). As part of the search, horizon will load a list of assets available to the source account id and will find any payment paths from those source assets to the desired destination asset. The search’s amount parameter will be used to determine if there a given path can satisfy a payment of the desired amount. path = stellar.find_payment_path('GAEE__ADED__', 'GDAA__3EFD__', ('USD', 'GDKG__GZ2O__'), "10.1").fetch() """ return PaymentPaths._All(from_account, to_account, to_asset, amount)
def get_current_network(
)
Returns tuple containing horizon endpoint url and current network_id
def get_current_network(): """Returns tuple containing horizon endpoint url and current network_id""" global horizon, network_id, network_password return (horizon, network_id)
def ledger(
ledseq)
Returns single ledger with given ledseq. Can be chained to retreive other details such as transactions that are part of given ledger.
l = stellar.ledger(12345).fetch()
def ledger(ledseq): """ Returns single ledger with given ledseq. Can be chained to retreive other details such as transactions that are part of given ledger. l = stellar.ledger(12345).fetch() """ return Ledgers(ledseq);
def ledgers(
)
Returns ledgers that are being processed be on stellar network.
ls = stellar.ledgers().fetch( cursor=15, order='asc').entries()
def ledgers(): """ Returns ledgers that are being processed be on stellar network. ls = stellar.ledgers().fetch( cursor=15, order='asc').entries() """ return Ledgers._All()
def new_transaction(
account, signers=[], seq=None, fee=None, memo=None, time_bounds=[])
Creates new transaction. account - can be public key or secret. If account is self signed then secret of the account is sufficient. Otherwise public key in account parameter and signers must have secrets of the necessary signers of that account. seq - sequence of transaction(int), if not given will get last sequence and increment by one fee - fee(int), if given, will be used instead of default fee of 100 stroops/op. memo - optional text memo in string format or tuple (memo_type, memo_data) for other formats. available other formats are ('id', 'hash', 'return') time_bounds - if given, upper and lower bounds for the transaction to be effective.
Can be used with with-statement as follows:
with stellar.new_transaction(account, memo='double payment') as t: t.pay(destination1, amount1) t.pay(destination2, amount2)
This will autmoatically submit the transaction when with-statement completes.
You can prepare transaction in xdr format and then submit this prepared transaction (as required in smart contracts) at some later time:
trx = stellar.new_transaction(account, time_bounds=(some_future_time,0)) .pay(dest, amount).build() #at some_future_time submit the transaction envelope result = stellar.post_transaction(trx)
Each operation in transaction costs atleast a base fee (which is 100 stroops). So if you submit 5 different operations in single transaction it will cost you atleast 500 stroops. Only exception are set_options operation. So if you set inflation destination and auth flags in single transaction then it will only cost you 100 stroops.
def new_transaction(account, signers=[], seq=None, fee=None, memo=None, time_bounds=[]): """ Creates new transaction. account - can be public key or secret. If account is self signed then secret of the account is sufficient. Otherwise public key in account parameter and signers must have secrets of the necessary signers of that account. seq - sequence of transaction(int), if not given will get last sequence and increment by one fee - fee(int), if given, will be used instead of default fee of 100 stroops/op. memo - optional text memo in string format or tuple (memo_type, memo_data) for other formats. available other formats are ('id', 'hash', 'return') time_bounds - if given, upper and lower bounds for the transaction to be effective. Can be used with with-statement as follows: with stellar.new_transaction(account, memo='double payment') as t: t.pay(destination1, amount1) t.pay(destination2, amount2) This will autmoatically submit the transaction when with-statement completes. You can prepare transaction in xdr format and then submit this prepared transaction (as required in smart contracts) at some later time: trx = stellar.new_transaction(account, time_bounds=(some_future_time,0)) .pay(dest, amount).build() #at some_future_time submit the transaction envelope result = stellar.post_transaction(trx) Each operation in transaction costs atleast a base fee (which is 100 stroops). So if you submit 5 different operations in single transaction it will cost you atleast 500 stroops. Only exception are set_options operation. So if you set inflation destination and auth flags in single transaction then it will only cost you 100 stroops. """ return NewTransaction(account, signers, seq, fee, memo, time_bounds)
def operation(
opid)
Returns single opreation with given opid to be fetched from stellar network.
o = stellar.operation('28551568194277377').fetch() o_effs = stellar.operation('28551568194277377'). effects().fetch().entries()
def operation(opid): """ Returns single opreation with given opid to be fetched from stellar network. o = stellar.operation('28551568194277377').fetch() o_effs = stellar.operation('28551568194277377'). effects().fetch().entries() """ return Operations(opid);
def operations(
)
Returns all the operaion that are being performed on stellar network.
ops = stellar.operations().fetch( limit=5, order='desc')
def operations(): """ Returns all the operaion that are being performed on stellar network. ops = stellar.operations().fetch( limit=5, order='desc') """ return Operations._All()
def orderbook(
buying, selling)
All the pending offers where people are 'buying' asset in exchange of 'selling' asset.
book = stellar.orderbook(selling=('AST1', 'GAEE__ADED__'), buying=('AST2', 'GDAA__3EFD__')).fetch().entries()
def orderbook(buying, selling): """ All the pending offers where people are 'buying' asset in exchange of 'selling' asset. book = stellar.orderbook(selling=('AST1', 'GAEE__ADED__'), buying=('AST2', 'GDAA__3EFD__')).fetch().entries() """ return Orderbooks._All(buying, selling)
def payments(
)
Returns all the payment operation that are done on stellar network.
ps = stellar.payments().fetch().entries()
def payments(): """ Returns all the payment operation that are done on stellar network. ps = stellar.payments().fetch().entries() """ return Payments._All()
def post_transaction(
envelope_xdr)
Submits earlier prepared transaction envelope to the stellar network. envelope_xdr either created through NewTransaction.build() method or using some external utility such as Stellar laboratory.
def post_transaction(envelope_xdr): """ Submits earlier prepared transaction envelope to the stellar network. envelope_xdr either created through NewTransaction.build() method or using some external utility such as Stellar laboratory. """ res = HTTP.post(horizon + '/transactions/', {'tx': envelope_xdr }) return TransactionResult(res)
def random_keypair(
)
Generates pair of (secret,account-id).
def random_keypair(): """Generates pair of (secret,account-id). """ seed = os.urandom(32) signing_key = ed25519.SigningKey(seed) verifying_key = signing_key.get_verifying_key() def encode_key(key_type, key): payload = binascii.a2b_hex(KEY_TYPES[key_type]) + key checksum = crc16.crc16xmodem(payload) checksum = struct.pack('H', checksum) return base64.b32encode(payload + checksum) return (encode_key('seed', signing_key.to_seed()), encode_key('public', verifying_key.to_bytes()))
def setup_custom_network(
horizon_url, password)
Sets network to custom horizon endpoint
def setup_custom_network(horizon_url, password): """Sets network to custom horizon endpoint""" global horizon, network_id, network_password horizon = horizon_url network_password = password network_id = hashlib.sha256(network_password).digest()
def setup_public_network(
)
Sets the current network to stellar.org public network
def setup_public_network(): """Sets the current network to stellar.org public network""" global horizon, network_id, network_password horizon = HORIZON_PUBLIC_ENDPOINT network_password = NETWORK_PASSWORD_PUBLIC network_id = hashlib.sha256(network_password).digest()
def setup_test_network(
)
Sets the current network to stellar.org test network
def setup_test_network(): """Sets the current network to stellar.org test network""" global horizon, network_id, network_password horizon = HORIZON_TESTNET_ENDPOINT network_password = NETWORK_PASSWORD_TESTNET network_id = hashlib.sha256(network_password).digest()
def trades(
buying, selling)
Returns all the trade where buying <-> selling assets are being traded. Curently stellar network always returns resource not found for this query.
def trades(buying, selling): """Returns all the trade where buying <-> selling assets are being traded. Curently stellar network always returns resource not found for this query. """ raise NotImplementedError
def transaction(
trxid)
Returns single transaction with given trxid. Can be chained to retrieve other details of the given transactions such as all operations in given transaction etc.
t = stellar.transaction('aefe__b781__').fetch() t_ops = stellar.transaction('aefe__b781__') .operations().fetch().entries()
def transaction(trxid): """ Returns single transaction with given trxid. Can be chained to retrieve other details of the given transactions such as all operations in given transaction etc. t = stellar.transaction('aefe__b781__').fetch() t_ops = stellar.transaction('aefe__b781__') .operations().fetch().entries() """ return Transactions(trxid)
def transactions(
)
Returns transactions thats are being submitted to stellar network.
ts = stellar.transactions().fetch( limit=5, order='desc').entries()
def transactions(): """ Returns transactions thats are being submitted to stellar network. ts = stellar.transactions().fetch( limit=5, order='desc').entries() """ return Transactions._All()
Classes
class Accounts
class Accounts(Fetchable): class Thresholds(object): def __init__(self, data): self.low_threshold = int(data['low_threshold']) self.med_threshold = int(data['med_threshold']) self.high_threshold = int(data['high_threshold']) def __repr__(self): return 'Thresholds(l=%s, m=%s, h=%s)' % (self.low_threshold, self.med_threshold, self.high_threshold) class Flags(object): def __init__(self, data): self.auth_required = data['auth_required'] self.auth_revocable = data['auth_revocable'] def __repr__(self): return 'Flags(required=%s, revocable=%s)' % (self.auth_required, self.auth_revocable) class Balance(object): def __init__(self, data): self.balance = data['balance'] self.asset = Asset(data) def __repr__(self): return 'Balance(%s %s)' % (self.balance, self.asset.asset_code) class Signer(object): def __init__(self, data): self.public_key = data['public_key'] self.weight = int(data['weight']) self.key = data['key'] self.type = data['type'] def __repr__(self): return 'Signer(%s, %s)' % (_shorten_address(self.public_key), self.weight) class Data(object): def __init__(self, data): self.key = data['key'] self.value = base64.b64decode(data['value']) def __repr__(self): return 'Data(%s, %s)' % (self.key, self.value) class Account(object): """Account:https://www.stellar.org/developers/horizon/reference/resources/account.html""" def __init__(self, data): """Construct Account object given data dict having all the account related field.""" self.account_id = data['id'] self.paging_token = data['paging_token'] self.sequence = data['sequence'] self.subentry_count = int(data['subentry_count']) self.thresholds = Accounts.Thresholds(data['thresholds']) self.flags = Accounts.Flags(data['flags']) self.balances = [Accounts.Balance(b) for b in data['balances']] self.signers = [Accounts.Signer(s) for s in data['signers']] self.data = [Accounts.Data({'key' : k, 'value' : v}) for k,v in data['data'].iteritems()] if 'inflation_destination' in data: self.inflation_destination = data['inflation_destination'] else: self.inflation_destination = None def __repr__(self): return 'Account(id=%s,seq=%s,balances=%s)' % (self.account_id, self.sequence, self.balances) def __init__(self, accid): if not accid: raise ValueError('accid expected') self.accid = _address_to_account(accid) self.paginated = False self.streamed = False self.url = '/accounts/%s' % self.accid def _map2obj(self, data): return Accounts.Account(data) def transactions(self): """Returns fechable object for transactions associated with given account""" return Transactions._All(self.url) def operations(self): """Returns fechable object for operations associated with given account""" return Operations._All(self.url) def payments(self): """Returns fechable object for payments associated with given account""" return Payments._All(self.url) def offers(self): """Returns fechable object for offers associated with given account""" return Offers._Offers__All(self.url) def effects(self): """Returns fechable object for effects associated with given account""" return Effects._All(self.url)
Ancestors (in MRO)
Class variables
var Account
var Balance
var Data
var Flags
var Signer
var Thresholds
Instance variables
var accid
var paginated
var streamed
var url
Methods
def __init__(
self, accid)
def __init__(self, accid): if not accid: raise ValueError('accid expected') self.accid = _address_to_account(accid) self.paginated = False self.streamed = False self.url = '/accounts/%s' % self.accid
def effects(
self)
Returns fechable object for effects associated with given account
def effects(self): """Returns fechable object for effects associated with given account""" return Effects._All(self.url)
def fetch(
self, cursor=None, limit=10, order='asc')
Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'.
def fetch(self, cursor=None, limit=10, order='asc'): """Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'. """ if self.paginated: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) r = HTTP.get(horizon + self.url) if not self.paginated: return self._map2obj(r) return Fetchable.Page(lambda x : self._map2obj(x), r)
def first(
self)
Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction:
>>> stellar.transactions().first()
def first(self): """Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction: >>> stellar.transactions().first() """ r = self.fetch(limit=1, order='asc').records if len(r) > 0: return r[0] else: return None
def last(
self)
Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction:
>>> stellar.transactions().last()
def last(self): """Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction: >>> stellar.transactions().last() """ r = self.fetch(limit=1, order='desc').records if len(r) > 0: return r[0] else: return None
def offers(
self)
Returns fechable object for offers associated with given account
def offers(self): """Returns fechable object for offers associated with given account""" return Offers._Offers__All(self.url)
def operations(
self)
Returns fechable object for operations associated with given account
def operations(self): """Returns fechable object for operations associated with given account""" return Operations._All(self.url)
def payments(
self)
Returns fechable object for payments associated with given account
def payments(self): """Returns fechable object for payments associated with given account""" return Payments._All(self.url)
def stream(
self, cursor=None, limit=10, order='asc')
Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop.
def stream(self, cursor=None, limit=10, order='asc'): """Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop. """ if self.streamed: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) eventsource = HTTP.stream(horizon + self.url) for event in eventsource: if event.data == '"hello"': continue yield self._map2obj(json.loads(event.data)) else: raise Exception('stream not supported')
def transactions(
self)
Returns fechable object for transactions associated with given account
def transactions(self): """Returns fechable object for transactions associated with given account""" return Transactions._All(self.url)
class Asset
Asset represents either stellar native asset or asset code with given issuer
class Asset(object): """ Asset represents either stellar native asset or asset code with given issuer """ def __init__(self, data, prefix=''): """Constructs Asset given data dict having following keys: asset_type, asset_code, asset_issuer. if asset_type is 'native' then rest of the fields are not needed. If prefix is passed then all above keys are prefixed with it and then searched in the dict, e.g. if prefix = 'sender' then 'sender_asset_type', etc will be searched instead of default asset_type. """ type_key = prefix + 'asset_type' self.asset_type = data[type_key] '''asset type (either native, credit_alphanum4 or credit_alphanum12)''' self.asset_code = None '''asset code for asset''' self.asset_issuer = None '''asset issuer of the non-native asset''' self.limit = None '''limit on holding the asset if any''' if self.asset_type != 'native': self.asset_code = data[prefix + 'asset_code'] self.asset_issuer = data[prefix + 'asset_issuer'] limit_key = (prefix + 'limit') if limit_key in data: self.limit = data[limit_key] else: self.asset_code = 'XLM' def __repr__(self): return 'Asset(native)' if self.asset_type == 'native' else 'Asset(%s,%s,%s)'\ % (self.asset_type, self.asset_code, _shorten_address(self.asset_issuer)) @staticmethod def format_url_parameters(asset, prefix=''): """Formats asset for url parameter. e.g. asset_type=credit_alphanum4&asset_code=USD&asset_issuer=GFED..CBAH asset is tuple in form (asset_code,asset_issuer) or 'native' if prefix is given then url parameter will be prefixed with it. """ if ((type(asset) == str or type(asset) == unicode) and asset == 'native') \ or (len(asset) == 1 and asset[0] == 'native'): return '%sasset_type=native' % prefix else: if len(asset) == 1: raise ValueError('Needed asset in (asset_code, asset_issuer) format or "native"') if len(asset[0]) <= 4: return '%sasset_type=credit_alphanum4&%sasset_code=%s&%sasset_issuer=%s'\ % (prefix, prefix, asset[0], prefix, asset[1]) else: return '%sasset_type=credit_alphanum12&%sasset_code=%s&%sasset_issuer=%s'\ % (prefix, prefix, asset[0], prefix, asset[1])
Ancestors (in MRO)
- Asset
- __builtin__.object
Static methods
def format_url_parameters(
asset, prefix='')
Formats asset for url parameter. e.g. asset_type=credit_alphanum4&asset_code=USD&asset_issuer=GFED..CBAH asset is tuple in form (asset_code,asset_issuer) or 'native' if prefix is given then url parameter will be prefixed with it.
@staticmethod def format_url_parameters(asset, prefix=''): """Formats asset for url parameter. e.g. asset_type=credit_alphanum4&asset_code=USD&asset_issuer=GFED..CBAH asset is tuple in form (asset_code,asset_issuer) or 'native' if prefix is given then url parameter will be prefixed with it. """ if ((type(asset) == str or type(asset) == unicode) and asset == 'native') \ or (len(asset) == 1 and asset[0] == 'native'): return '%sasset_type=native' % prefix else: if len(asset) == 1: raise ValueError('Needed asset in (asset_code, asset_issuer) format or "native"') if len(asset[0]) <= 4: return '%sasset_type=credit_alphanum4&%sasset_code=%s&%sasset_issuer=%s'\ % (prefix, prefix, asset[0], prefix, asset[1]) else: return '%sasset_type=credit_alphanum12&%sasset_code=%s&%sasset_issuer=%s'\ % (prefix, prefix, asset[0], prefix, asset[1])
Instance variables
var asset_code
asset code for asset
var asset_issuer
asset issuer of the non-native asset
var asset_type
asset type (either native, credit_alphanum4 or credit_alphanum12)
var limit
limit on holding the asset if any
Methods
def __init__(
self, data, prefix='')
Constructs Asset given data dict having following keys: asset_type, asset_code, asset_issuer. if asset_type is 'native' then rest of the fields are not needed. If prefix is passed then all above keys are prefixed with it and then searched in the dict, e.g. if prefix = 'sender' then 'sender_asset_type', etc will be searched instead of default asset_type.
def __init__(self, data, prefix=''): """Constructs Asset given data dict having following keys: asset_type, asset_code, asset_issuer. if asset_type is 'native' then rest of the fields are not needed. If prefix is passed then all above keys are prefixed with it and then searched in the dict, e.g. if prefix = 'sender' then 'sender_asset_type', etc will be searched instead of default asset_type. """ type_key = prefix + 'asset_type' self.asset_type = data[type_key] '''asset type (either native, credit_alphanum4 or credit_alphanum12)''' self.asset_code = None '''asset code for asset''' self.asset_issuer = None '''asset issuer of the non-native asset''' self.limit = None '''limit on holding the asset if any''' if self.asset_type != 'native': self.asset_code = data[prefix + 'asset_code'] self.asset_issuer = data[prefix + 'asset_issuer'] limit_key = (prefix + 'limit') if limit_key in data: self.limit = data[limit_key] else: self.asset_code = 'XLM'
class Assets
class Assets(object): class AssetDetails(object): def __init__(self, data): self.asset = Asset(data) self.paging_token = data['paging_token'] self.num_accounts = data['num_accounts'] self.amount = data['amount'] self.flags = Accounts.Flags(data['flags']) self.toml = data['_links']['toml']['href'] def __repr__(self): return str(self.asset) class _All(Fetchable): def __init__(self, asset_code, asset_issuer): self.paginated = True self.streamed = False self.url = '/assets?' if asset_code: self.url = '%sasset_code=%s&' % (self.url, asset_code) if asset_issuer: self.url = '%sasset_issuer=%s&' % (self.url, asset_issuer) self.url = self.url[:-1] def _map2obj(self, data): return Assets.AssetDetails(data)
class Effects
class Effects(object): class Effect(object): def __init__(self, data): self.effectid = data['id'] self.paging_token = data['paging_token'] self.account = data['account'] self.type = data['type'] self.type_i = t = data['type_i'] if t == 0: self.starting_balance = data['starting_balance'] elif t == 1: pass elif t == 2 or t == 3: self.amount = data['amount'] self.asset = Asset(data) elif t == 4: self.thresholds = Accounts.Thresholds(data) elif t == 5: self.home_domain = data['home_domain'] elif t == 6: if 'auth_required_flag' in data: self.auth_required = (True, data['auth_required_flag']) else: self.auth_required = (False, None) if 'auth_revokable_flag' in data: self.auth_revokable = (True, data['auth_revokable_flag']) else: self.auth_revokable = (False, None) elif t == 10 or t == 11 or t == 12: self.weight = data['weight'] self.public_key = data['public_key'] elif t == 20 or t == 21 or t == 22: self.trustlimit = data['limit'] self.trustasset = Asset(data) elif t == 23 or t == 24: self.trustor = data['trustor'] self.asset_type = data['asset_type'] self.asset_code = data['asset_code'] elif t == 30 or t == 31 or t == 32: pass elif t == 33: self.seller = data['seller'] self.offer_id = data['offer_id'] self.sold_amount = data['sold_amount'] self.sold_asset = Asset(data, 'sold_') self.bought_amount = data['bought_amount'] self.bought_asset = Asset(data, 'bought_') elif t == 40: pass else: raise Exception('type not supported = %s' % self.type) def __repr__(self): return 'Effect(%s,%s,%s)' % (self.effectid,\ _shorten_address(self.account), self.type) class _All(Fetchable): def __init__(self, baseurl=''): self.paginated = True self.streamed = True self.url = baseurl + '/effects' def _map2obj(self, data): return Effects.Effect(data)
class Fetchable
Base class representing resource that can be retrieved from horizon endpoint. Resource can be fetched or streamed. Fetched object returns single object for point queries or Page object for paginated queries. Stream object returns generator which can be iterated.
class Fetchable(object): """Base class representing resource that can be retrieved from horizon endpoint. Resource can be fetched or streamed. Fetched object returns single object for point queries or Page object for paginated queries. Stream object returns generator which can be iterated. """ class Page(object): """Page containing records, link to next page and previous page. """ def __init__(self, mapper, data): self.mapper = mapper self.records = [self.mapper(r) for r in data['_embedded']['records']] self.nextlink = data['_links']['next']['href'] self.prevlink = data['_links']['prev']['href'] def entries(self): """returns records in current page""" return self.records def next(self): """fetches next page from the network and returns page object""" r = HTTP.get(self.nextlink) return Fetchable.Page(self.mapper, r) def prev(self): """fetches prev page from the network and returns page object""" r = HTTP.get(self.prevlink) return Fetchable.Page(self.mapper, r) def fetch(self, cursor=None, limit=10, order='asc'): """Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'. """ if self.paginated: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) r = HTTP.get(horizon + self.url) if not self.paginated: return self._map2obj(r) return Fetchable.Page(lambda x : self._map2obj(x), r) def first(self): """Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction: >>> stellar.transactions().first() """ r = self.fetch(limit=1, order='asc').records if len(r) > 0: return r[0] else: return None def last(self): """Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction: >>> stellar.transactions().last() """ r = self.fetch(limit=1, order='desc').records if len(r) > 0: return r[0] else: return None def stream(self, cursor=None, limit=10, order='asc'): """Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop. """ if self.streamed: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) eventsource = HTTP.stream(horizon + self.url) for event in eventsource: if event.data == '"hello"': continue yield self._map2obj(json.loads(event.data)) else: raise Exception('stream not supported') def _map2obj(self, data): """Function that subclass need to implemet to convert parsed json object to python object, according to resource that is requested """ pass
Ancestors (in MRO)
- Fetchable
- __builtin__.object
Class variables
var Page
Methods
def fetch(
self, cursor=None, limit=10, order='asc')
Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'.
def fetch(self, cursor=None, limit=10, order='asc'): """Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'. """ if self.paginated: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) r = HTTP.get(horizon + self.url) if not self.paginated: return self._map2obj(r) return Fetchable.Page(lambda x : self._map2obj(x), r)
def first(
self)
Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction:
>>> stellar.transactions().first()
def first(self): """Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction: >>> stellar.transactions().first() """ r = self.fetch(limit=1, order='asc').records if len(r) > 0: return r[0] else: return None
def last(
self)
Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction:
>>> stellar.transactions().last()
def last(self): """Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction: >>> stellar.transactions().last() """ r = self.fetch(limit=1, order='desc').records if len(r) > 0: return r[0] else: return None
def stream(
self, cursor=None, limit=10, order='asc')
Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop.
def stream(self, cursor=None, limit=10, order='asc'): """Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop. """ if self.streamed: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) eventsource = HTTP.stream(horizon + self.url) for event in eventsource: if event.data == '"hello"': continue yield self._map2obj(json.loads(event.data)) else: raise Exception('stream not supported')
class Ledgers
class Ledgers(Fetchable): class Ledger(object): """Ledger: https://www.stellar.org/developers/horizon/reference/resources/ledger.html""" def __init__(self, data): self.ledid = data['id'] self.paging_token = data['paging_token'] self.hash = data['hash'] self.prev_hash = data['prev_hash'] self.ledseq = int(data['sequence']) self.transaction_count = int(data['transaction_count']) self.operation_count = int(data['operation_count']) self.closed_at = datetime.datetime.strptime( data['closed_at'], "%Y-%m-%dT%H:%M:%SZ") self.total_coins = data['total_coins'] self.fee_pool = data['fee_pool'] self.base_fee = int(data['base_fee']) self.base_reserve = data['base_reserve'] self.max_tx_set_size = int(data['max_tx_set_size']) def __repr__(self): return 'Ledger(id=%s,ledseq=%s)' % (self.ledid, self.ledseq) def __init__(self, ledseq): if not ledseq: raise ValueError('ledger id expected') self.ledseq = ledseq self.paginated = False self.streamed = False self.url = '/ledgers/%s' % self.ledseq def _map2obj(self, data): return Ledgers.Ledger(data) def transactions(self): """Returns fechable object for transactions associated with given ledger""" return Transactions._All(self.url) def operations(self): """Returns fechable object for operations associated with given ledger""" return Operations._All(self.url) def payments(self): """Returns fechable object for payments associated with given ledger""" return Payments._All(self.url) def effects(self): """Returns fechable object for effects associated with given ledger""" return Effects._All(self.url) class _All(Fetchable): def __init__(self, baseurl=''): self.paginated = True self.streamed = True self.url = baseurl + '/ledgers' def _map2obj(self, data): return Ledgers.Ledger(data)
Ancestors (in MRO)
Class variables
var Ledger
Instance variables
var ledseq
var paginated
var streamed
var url
Methods
def __init__(
self, ledseq)
def __init__(self, ledseq): if not ledseq: raise ValueError('ledger id expected') self.ledseq = ledseq self.paginated = False self.streamed = False self.url = '/ledgers/%s' % self.ledseq
def effects(
self)
Returns fechable object for effects associated with given ledger
def effects(self): """Returns fechable object for effects associated with given ledger""" return Effects._All(self.url)
def fetch(
self, cursor=None, limit=10, order='asc')
Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'.
def fetch(self, cursor=None, limit=10, order='asc'): """Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'. """ if self.paginated: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) r = HTTP.get(horizon + self.url) if not self.paginated: return self._map2obj(r) return Fetchable.Page(lambda x : self._map2obj(x), r)
def first(
self)
Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction:
>>> stellar.transactions().first()
def first(self): """Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction: >>> stellar.transactions().first() """ r = self.fetch(limit=1, order='asc').records if len(r) > 0: return r[0] else: return None
def last(
self)
Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction:
>>> stellar.transactions().last()
def last(self): """Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction: >>> stellar.transactions().last() """ r = self.fetch(limit=1, order='desc').records if len(r) > 0: return r[0] else: return None
def operations(
self)
Returns fechable object for operations associated with given ledger
def operations(self): """Returns fechable object for operations associated with given ledger""" return Operations._All(self.url)
def payments(
self)
Returns fechable object for payments associated with given ledger
def payments(self): """Returns fechable object for payments associated with given ledger""" return Payments._All(self.url)
def stream(
self, cursor=None, limit=10, order='asc')
Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop.
def stream(self, cursor=None, limit=10, order='asc'): """Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop. """ if self.streamed: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) eventsource = HTTP.stream(horizon + self.url) for event in eventsource: if event.data == '"hello"': continue yield self._map2obj(json.loads(event.data)) else: raise Exception('stream not supported')
def transactions(
self)
Returns fechable object for transactions associated with given ledger
def transactions(self): """Returns fechable object for transactions associated with given ledger""" return Transactions._All(self.url)
class NewTransaction
class NewTransaction(object): def __init__(self, account, signers, seq, fee, memo, time_bounds): self.account = account '''account on which transaction will be executed''' self.signers = signers '''signers of the transaction. if account is not secret, key then signers must be provided''' self.seq = seq '''sequence of the transaction''' self.fee = fee '''fee for the transaction''' self.memo = memo '''memo of the transaction''' self.time_bounds = time_bounds self.ops = [] '''operations in transaction''' self.set_options_op = {} if len(signers) == 0 and account.startswith('G'): raise ValueError('signer(s) missing') elif len(signers) == 0 and account.startswith('S'): self.signers = [account] if self.account.startswith('S'): self.account = account_from_secret(account) self.account = _address_to_account(self.account) self.trx_result = None def __enter__(self): return self def __exit__(self, *args): self.submit() def build(self): """Creates transaction and returns 'Transaction Envelope XDR' without submitting it to network """ account_seq = self.seq if self.seq else (int(account(self.account).fetch().sequence) + 1) self.__add_set_options_op() base_fee = self.fee if self.fee else BASE_FEE*len(self.ops) time_bounds = [XDR.time_bounds_to_xdr(self.time_bounds)] if self.time_bounds else [] xdr = Xdr.nullclass() xdr.v = 0 trxxdr = Xdr.types.Transaction( XDR.address_to_xdr(self.account), base_fee, account_seq, time_bounds, XDR.memo_to_xdr(self.memo), self.ops, xdr) trxtypepacker = Xdr.StellarXDRPacker() trxtypepacker.pack_EnvelopeType(Xdr.const.ENVELOPE_TYPE_TX) trxtype = trxtypepacker.get_buffer() trxpacker = Xdr.StellarXDRPacker() trxpacker.pack_Transaction(trxxdr) trx = trxpacker.get_buffer() trx_hash = hashlib.sha256(network_id + trxtype + trx).digest() signatures = [] for signer in self.signers: signatures += [_sign_trx_hash(signer, trx_hash)] tre = Xdr.types.TransactionEnvelope(trxxdr, signatures) txpacker = Xdr.StellarXDRPacker() txpacker.pack_TransactionEnvelope(tre) return base64.b64encode(txpacker.get_buffer()) def submit(self): """Submits transaction to network in context of this new transaction. """ self.trx_result = post_transaction(self.build()) def is_success(self): """Returns whether transaction was successful after submitting to network """ if not self.trx_result: raise Exception('Transaction not submitted') return self.trx_result.is_success() def result(self): """If transaction was successful then (transaction-id, ledger-id) pair""" if not self.trx_result: raise Exception('Transaction not submitted') return self.trx_result.result() def errors(self): """If transaction was not successful then (transaction-error, list-of operation error) pair""" if not self.trx_result: raise Exception('Transaction not submitted') return self.trx_result.errors() def create_account(self, account, starting_balance): """Creates account with given starting balance """ account = _address_to_account(account) body = Xdr.nullclass() body.type = Xdr.const.CREATE_ACCOUNT body.createAccountOp = Xdr.types.CreateAccountOp( XDR.address_to_xdr(account), XDR.amount_to_xdr(starting_balance)) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self def pay(self, account, amount, asset='native'): """Pays given account with given amount of specified asset. asset can be 'native' or tuple in format (asset_code, asset_issuer). """ account = _address_to_account(account) body = Xdr.nullclass() body.type = Xdr.const.PAYMENT body.paymentOp = Xdr.types.PaymentOp( XDR.address_to_xdr(account), XDR.asset_to_xdr(asset), XDR.amount_to_xdr(amount)) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self def pathpay(self, destination, dest_amount, dest_asset, max_send, send_asset, path): """Does the pathpay operation for given destination account, for dest_amount of dest_asset. It will send send_amount of send_asset upto max of max_send. Optionally path containing asset for intermediate exchanges can be specified (those path asset can be 'native' or tuple in format (asset_code, asset_issuer). """ destination = _address_to_account(destination) pathxdr = [] #XXX is this tested? for p in path: pathxdr += [XDR.asset_to_xdr(p)] body = Xdr.nullclass() body.type = Xdr.const.PATH_PAYMENT body.pathPaymentOp = Xdr.types.PathPaymentOp( XDR.asset_to_xdr(send_asset), XDR.amount_to_xdr(max_send), XDR.address_to_xdr(destination), XDR.asset_to_xdr(dest_asset), XDR.amount_to_xdr(dest_amount), pathxdr) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self def add_offer(self, sell_amount, sell_asset, buy_asset, price): """Adds offer of sell_amount for selling asset sell_asset, to buy buy_asset at given price. sell_asset, buy_asset are asset in 'native' or tuple in format (asset_code, asset_issuer). price in (numerator, denominator) format. To buy 1 BTC at 100 XLM price would be (1, 100) """ return self.update_offer(0, sell_amount, sell_asset, buy_asset, price) def add_passive_offer(self, sell_amount, sell_asset, buy_asset, price): """Creates passive offer of sell_amount for selling asset sell_asset, to buy buy_asset at given price. sell_asset, buy_asset are asset in 'native' or tuple in format (asset_code, asset_issuer). price in (numerator, denominator) format. To buy 1 BTC at 100 XLM price would be (1, 100) """ body = Xdr.nullclass() body.type = Xdr.const.CREATE_PASSIVE_OFFER body.createPassiveOfferOp = Xdr.types.CreatePassiveOfferOp( XDR.asset_to_xdr(sell_asset), XDR.asset_to_xdr(buy_asset), XDR.amount_to_xdr(sell_amount), XDR.price_to_xdr(price)) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self def update_offer(self, offer_id, sell_amount, sell_asset, buy_asset, price): """Updates offer with given offer_id with specified details. sell_asset, buy_asset are asset in 'native' or tuple in format (asset_code, asset_issuer). price in (numerator, denominator) format. To buy 1 BTC at 100 XLM price would be (1, 100) """ body = Xdr.nullclass() body.type = Xdr.const.MANAGE_OFFER body.manageOfferOp = Xdr.types.ManageOfferOp( XDR.asset_to_xdr(sell_asset), XDR.asset_to_xdr(buy_asset), XDR.amount_to_xdr(sell_amount), XDR.price_to_xdr(price), offer_id) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self def remove_offer(self, offer_id, sell_asset, buy_asset): """Removes existing offer with given offer_id of sell_asset <-> buy_asset trade """ return self.update_offer(offer_id, "0", sell_asset, buy_asset, (1,1)) def set_inflation_destination(self, account): """Sets the inflation of given account (SET_OPTIONS operation)""" self.set_options_op['inflation'] = _address_to_account(account) return self def set_flags(self, auth_required=False, auth_revocable=False, auth_immutable=False): """Sets the auth flags of the given account (SET_OPTIONS operation)""" auth_flags = 0 if auth_required or auth_revocable or auth_immutable: if auth_required: auth_flags += 1 if auth_revocable: auth_flags += 2 if auth_immutable: auth_flags += 4 self.set_options_op['set_flags'] = auth_flags return self def clear_flags(self, auth_required=False, auth_revocable=False, auth_immutable=False): """Clear auth flags of the given account (SET_OPTIONS operation)""" auth_flags = 0 if auth_required or auth_revocable or auth_immutable: if auth_required: auth_flags += 1 if auth_revocable: auth_flags += 2 if auth_immutable: auth_flags += 4 self.set_options_op['clear_flags'] = auth_flags return self def set_thresholds(self, high=None, medium=None, low=None): """Sets threshold of given account (SET_OPTIONS operation)""" if high or medium or low: if high: self.set_options_op['high'] = high if medium: self.set_options_op['medium'] = medium if low: self.set_options_op['low'] = low return self def set_master_weight(self, weight): """Sets master weight of the given account (SET_OPTIONS operation)""" self.set_options_op['master_weight'] = weight return self def set_signer(self, signer_type, key, weight): """ Sets sigers of the given account (SET_OPTIONS operation). available signer_type are ('ed25519PublicKey','hashX','preAuthTx') """ self.set_options_op['signer'] = (signer_type, key, weight) return self def set_home_domain(self, domain): """Sets home domain of the given account (SET_OPTIONS operation)""" self.set_options_op['home_domain'] = domain; return self def __add_set_options_op(self): if len(self.set_options_op) > 0: toarray = lambda m, x : [] if x not in m else [m[x]] inflation_destination_ = [] if 'inflation' not in self.set_options_op\ else [XDR.address_to_xdr(self.set_options_op['inflation'])] set_flags_ = toarray(self.set_options_op, 'set_flags') clear_flags_ = toarray(self.set_options_op, 'clear_flags') high_ = toarray(self.set_options_op, 'high') medium_ = toarray(self.set_options_op, 'medium') low_ = toarray(self.set_options_op, 'low') master_weight_ = toarray(self.set_options_op, 'master_weight') signer_ = toarray(self.set_options_op, 'signer') if len(signer_) > 0: signer_ = signer_[0] signer_ = [XDR.signer_to_xdr(signer_[0], signer_[1], signer_[2])] home_domain_ = toarray(self.set_options_op, 'home_domain') body = Xdr.nullclass() body.type = Xdr.const.SET_OPTIONS body.setOptionsOp = Xdr.types.SetOptionsOp( inflation_destination_, clear_flags_, set_flags_, master_weight_, low_, medium_, high_, home_domain_, signer_) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] def create_or_update_trust(self, asset, limit): """Creates or update trust for given asset with specified limit. asset is tuple in format (asset_code, asset_issuer) or 'native'. limit is amount indicating limit of given asset """ body = Xdr.nullclass() body.type = Xdr.const.CHANGE_TRUST body.changeTrustOp = Xdr.types.ChangeTrustOp( XDR.asset_to_xdr(asset), XDR.amount_to_xdr(limit)) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self def remove_trust(self, asset): """Remove trust for given asset. asset is tuple in format (asset_code, asset_issuer) or 'native'. """ return self.create_or_update_trust(asset, "0") def __perform_trust_op(self, account, asset_code, is_allow): body = Xdr.nullclass() body.type = Xdr.const.ALLOW_TRUST body.allowTrustOp = Xdr.types.AllowTrustOp( XDR.address_to_xdr(account), XDR.assetcode_to_xdr(asset_code), is_allow) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self def authorize_trust(self, account, asset_code): """Authorize given account to perform transaction for given asset_code. """ account = _address_to_account(account) return self.__perform_trust_op(account, asset_code, True) def deauthorize_trust(self, account, asset_code): """Deauthorize given account to perform transaction for given asset_code. """ account = _address_to_account(account) return self.__perform_trust_op(account, asset_code, False) def merge_this_account_with(self, account): """Merges current account with input account""" account = _address_to_account(account) body = Xdr.nullclass() body.type = Xdr.const.ACCOUNT_MERGE body.destination = XDR.address_to_xdr(account) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self def run_inflation(self): """Runs inflation process with this account """ body = Xdr.nullclass() body.type = Xdr.const.INFLATION self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self def put_or_update_data(self, key, value): """Puts the key value pair if not already present. If key is already presents then updates old value with input value. """ key = bytearray(key, encoding='utf-8') value = [bytearray(value, encoding='utf-8')] if value else [] body = Xdr.nullclass() body.type = Xdr.const.MANAGE_DATA body.manageDataOp = Xdr.types.ManageDataOp(key, value) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self def remove_data(self, key): """Removes the key value pair associated with given input key""" return self.put_or_update_data(key, None)
Ancestors (in MRO)
- NewTransaction
- __builtin__.object
Instance variables
var account
var fee
fee for the transaction
var memo
memo of the transaction
var ops
operations in transaction
var seq
sequence of the transaction
var set_options_op
var signers
signers of the transaction. if account is not secret, key then signers must be provided
var time_bounds
var trx_result
Methods
def __init__(
self, account, signers, seq, fee, memo, time_bounds)
def __init__(self, account, signers, seq, fee, memo, time_bounds): self.account = account '''account on which transaction will be executed''' self.signers = signers '''signers of the transaction. if account is not secret, key then signers must be provided''' self.seq = seq '''sequence of the transaction''' self.fee = fee '''fee for the transaction''' self.memo = memo '''memo of the transaction''' self.time_bounds = time_bounds self.ops = [] '''operations in transaction''' self.set_options_op = {} if len(signers) == 0 and account.startswith('G'): raise ValueError('signer(s) missing') elif len(signers) == 0 and account.startswith('S'): self.signers = [account] if self.account.startswith('S'): self.account = account_from_secret(account) self.account = _address_to_account(self.account) self.trx_result = None
def add_offer(
self, sell_amount, sell_asset, buy_asset, price)
Adds offer of sell_amount for selling asset sell_asset, to buy buy_asset at given price. sell_asset, buy_asset are asset in 'native' or tuple in format (asset_code, asset_issuer). price in (numerator, denominator) format. To buy 1 BTC at 100 XLM price would be (1, 100)
def add_offer(self, sell_amount, sell_asset, buy_asset, price): """Adds offer of sell_amount for selling asset sell_asset, to buy buy_asset at given price. sell_asset, buy_asset are asset in 'native' or tuple in format (asset_code, asset_issuer). price in (numerator, denominator) format. To buy 1 BTC at 100 XLM price would be (1, 100) """ return self.update_offer(0, sell_amount, sell_asset, buy_asset, price)
def add_passive_offer(
self, sell_amount, sell_asset, buy_asset, price)
Creates passive offer of sell_amount for selling asset sell_asset, to buy buy_asset at given price. sell_asset, buy_asset are asset in 'native' or tuple in format (asset_code, asset_issuer). price in (numerator, denominator) format. To buy 1 BTC at 100 XLM price would be (1, 100)
def add_passive_offer(self, sell_amount, sell_asset, buy_asset, price): """Creates passive offer of sell_amount for selling asset sell_asset, to buy buy_asset at given price. sell_asset, buy_asset are asset in 'native' or tuple in format (asset_code, asset_issuer). price in (numerator, denominator) format. To buy 1 BTC at 100 XLM price would be (1, 100) """ body = Xdr.nullclass() body.type = Xdr.const.CREATE_PASSIVE_OFFER body.createPassiveOfferOp = Xdr.types.CreatePassiveOfferOp( XDR.asset_to_xdr(sell_asset), XDR.asset_to_xdr(buy_asset), XDR.amount_to_xdr(sell_amount), XDR.price_to_xdr(price)) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self
def authorize_trust(
self, account, asset_code)
Authorize given account to perform transaction for given asset_code.
def build(
self)
Creates transaction and returns 'Transaction Envelope XDR' without submitting it to network
def build(self): """Creates transaction and returns 'Transaction Envelope XDR' without submitting it to network """ account_seq = self.seq if self.seq else (int(account(self.account).fetch().sequence) + 1) self.__add_set_options_op() base_fee = self.fee if self.fee else BASE_FEE*len(self.ops) time_bounds = [XDR.time_bounds_to_xdr(self.time_bounds)] if self.time_bounds else [] xdr = Xdr.nullclass() xdr.v = 0 trxxdr = Xdr.types.Transaction( XDR.address_to_xdr(self.account), base_fee, account_seq, time_bounds, XDR.memo_to_xdr(self.memo), self.ops, xdr) trxtypepacker = Xdr.StellarXDRPacker() trxtypepacker.pack_EnvelopeType(Xdr.const.ENVELOPE_TYPE_TX) trxtype = trxtypepacker.get_buffer() trxpacker = Xdr.StellarXDRPacker() trxpacker.pack_Transaction(trxxdr) trx = trxpacker.get_buffer() trx_hash = hashlib.sha256(network_id + trxtype + trx).digest() signatures = [] for signer in self.signers: signatures += [_sign_trx_hash(signer, trx_hash)] tre = Xdr.types.TransactionEnvelope(trxxdr, signatures) txpacker = Xdr.StellarXDRPacker() txpacker.pack_TransactionEnvelope(tre) return base64.b64encode(txpacker.get_buffer())
def clear_flags(
self, auth_required=False, auth_revocable=False, auth_immutable=False)
Clear auth flags of the given account (SET_OPTIONS operation)
def clear_flags(self, auth_required=False, auth_revocable=False, auth_immutable=False): """Clear auth flags of the given account (SET_OPTIONS operation)""" auth_flags = 0 if auth_required or auth_revocable or auth_immutable: if auth_required: auth_flags += 1 if auth_revocable: auth_flags += 2 if auth_immutable: auth_flags += 4 self.set_options_op['clear_flags'] = auth_flags return self
def create_account(
self, account, starting_balance)
Creates account with given starting balance
def create_account(self, account, starting_balance): """Creates account with given starting balance """ account = _address_to_account(account) body = Xdr.nullclass() body.type = Xdr.const.CREATE_ACCOUNT body.createAccountOp = Xdr.types.CreateAccountOp( XDR.address_to_xdr(account), XDR.amount_to_xdr(starting_balance)) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self
def create_or_update_trust(
self, asset, limit)
Creates or update trust for given asset with specified limit. asset is tuple in format (asset_code, asset_issuer) or 'native'. limit is amount indicating limit of given asset
def create_or_update_trust(self, asset, limit): """Creates or update trust for given asset with specified limit. asset is tuple in format (asset_code, asset_issuer) or 'native'. limit is amount indicating limit of given asset """ body = Xdr.nullclass() body.type = Xdr.const.CHANGE_TRUST body.changeTrustOp = Xdr.types.ChangeTrustOp( XDR.asset_to_xdr(asset), XDR.amount_to_xdr(limit)) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self
def deauthorize_trust(
self, account, asset_code)
Deauthorize given account to perform transaction for given asset_code.
def errors(
self)
If transaction was not successful then (transaction-error, list-of operation error) pair
def errors(self): """If transaction was not successful then (transaction-error, list-of operation error) pair""" if not self.trx_result: raise Exception('Transaction not submitted') return self.trx_result.errors()
def is_success(
self)
Returns whether transaction was successful after submitting to network
def is_success(self): """Returns whether transaction was successful after submitting to network """ if not self.trx_result: raise Exception('Transaction not submitted') return self.trx_result.is_success()
def merge_this_account_with(
self, account)
Merges current account with input account
def merge_this_account_with(self, account): """Merges current account with input account""" account = _address_to_account(account) body = Xdr.nullclass() body.type = Xdr.const.ACCOUNT_MERGE body.destination = XDR.address_to_xdr(account) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self
def pathpay(
self, destination, dest_amount, dest_asset, max_send, send_asset, path)
Does the pathpay operation for given destination account, for dest_amount of dest_asset. It will send send_amount of send_asset upto max of max_send. Optionally path containing asset for intermediate exchanges can be specified (those path asset can be 'native' or tuple in format (asset_code, asset_issuer).
def pathpay(self, destination, dest_amount, dest_asset, max_send, send_asset, path): """Does the pathpay operation for given destination account, for dest_amount of dest_asset. It will send send_amount of send_asset upto max of max_send. Optionally path containing asset for intermediate exchanges can be specified (those path asset can be 'native' or tuple in format (asset_code, asset_issuer). """ destination = _address_to_account(destination) pathxdr = [] #XXX is this tested? for p in path: pathxdr += [XDR.asset_to_xdr(p)] body = Xdr.nullclass() body.type = Xdr.const.PATH_PAYMENT body.pathPaymentOp = Xdr.types.PathPaymentOp( XDR.asset_to_xdr(send_asset), XDR.amount_to_xdr(max_send), XDR.address_to_xdr(destination), XDR.asset_to_xdr(dest_asset), XDR.amount_to_xdr(dest_amount), pathxdr) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self
def pay(
self, account, amount, asset='native')
Pays given account with given amount of specified asset. asset can be 'native' or tuple in format (asset_code, asset_issuer).
def pay(self, account, amount, asset='native'): """Pays given account with given amount of specified asset. asset can be 'native' or tuple in format (asset_code, asset_issuer). """ account = _address_to_account(account) body = Xdr.nullclass() body.type = Xdr.const.PAYMENT body.paymentOp = Xdr.types.PaymentOp( XDR.address_to_xdr(account), XDR.asset_to_xdr(asset), XDR.amount_to_xdr(amount)) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self
def put_or_update_data(
self, key, value)
Puts the key value pair if not already present. If key is already presents then updates old value with input value.
def put_or_update_data(self, key, value): """Puts the key value pair if not already present. If key is already presents then updates old value with input value. """ key = bytearray(key, encoding='utf-8') value = [bytearray(value, encoding='utf-8')] if value else [] body = Xdr.nullclass() body.type = Xdr.const.MANAGE_DATA body.manageDataOp = Xdr.types.ManageDataOp(key, value) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self
def remove_data(
self, key)
Removes the key value pair associated with given input key
def remove_data(self, key): """Removes the key value pair associated with given input key""" return self.put_or_update_data(key, None)
def remove_offer(
self, offer_id, sell_asset, buy_asset)
Removes existing offer with given offer_id of sell_asset <-> buy_asset trade
def remove_offer(self, offer_id, sell_asset, buy_asset): """Removes existing offer with given offer_id of sell_asset <-> buy_asset trade """ return self.update_offer(offer_id, "0", sell_asset, buy_asset, (1,1))
def remove_trust(
self, asset)
Remove trust for given asset. asset is tuple in format (asset_code, asset_issuer) or 'native'.
def remove_trust(self, asset): """Remove trust for given asset. asset is tuple in format (asset_code, asset_issuer) or 'native'. """ return self.create_or_update_trust(asset, "0")
def result(
self)
If transaction was successful then (transaction-id, ledger-id) pair
def result(self): """If transaction was successful then (transaction-id, ledger-id) pair""" if not self.trx_result: raise Exception('Transaction not submitted') return self.trx_result.result()
def run_inflation(
self)
Runs inflation process with this account
def run_inflation(self): """Runs inflation process with this account """ body = Xdr.nullclass() body.type = Xdr.const.INFLATION self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self
def set_flags(
self, auth_required=False, auth_revocable=False, auth_immutable=False)
Sets the auth flags of the given account (SET_OPTIONS operation)
def set_flags(self, auth_required=False, auth_revocable=False, auth_immutable=False): """Sets the auth flags of the given account (SET_OPTIONS operation)""" auth_flags = 0 if auth_required or auth_revocable or auth_immutable: if auth_required: auth_flags += 1 if auth_revocable: auth_flags += 2 if auth_immutable: auth_flags += 4 self.set_options_op['set_flags'] = auth_flags return self
def set_home_domain(
self, domain)
Sets home domain of the given account (SET_OPTIONS operation)
def set_home_domain(self, domain): """Sets home domain of the given account (SET_OPTIONS operation)""" self.set_options_op['home_domain'] = domain; return self
def set_inflation_destination(
self, account)
Sets the inflation of given account (SET_OPTIONS operation)
def set_inflation_destination(self, account): """Sets the inflation of given account (SET_OPTIONS operation)""" self.set_options_op['inflation'] = _address_to_account(account) return self
def set_master_weight(
self, weight)
Sets master weight of the given account (SET_OPTIONS operation)
def set_master_weight(self, weight): """Sets master weight of the given account (SET_OPTIONS operation)""" self.set_options_op['master_weight'] = weight return self
def set_signer(
self, signer_type, key, weight)
Sets sigers of the given account (SET_OPTIONS operation). available signer_type are ('ed25519PublicKey','hashX','preAuthTx')
def set_signer(self, signer_type, key, weight): """ Sets sigers of the given account (SET_OPTIONS operation). available signer_type are ('ed25519PublicKey','hashX','preAuthTx') """ self.set_options_op['signer'] = (signer_type, key, weight) return self
def set_thresholds(
self, high=None, medium=None, low=None)
Sets threshold of given account (SET_OPTIONS operation)
def set_thresholds(self, high=None, medium=None, low=None): """Sets threshold of given account (SET_OPTIONS operation)""" if high or medium or low: if high: self.set_options_op['high'] = high if medium: self.set_options_op['medium'] = medium if low: self.set_options_op['low'] = low return self
def submit(
self)
Submits transaction to network in context of this new transaction.
def submit(self): """Submits transaction to network in context of this new transaction. """ self.trx_result = post_transaction(self.build())
def update_offer(
self, offer_id, sell_amount, sell_asset, buy_asset, price)
Updates offer with given offer_id with specified details. sell_asset, buy_asset are asset in 'native' or tuple in format (asset_code, asset_issuer). price in (numerator, denominator) format. To buy 1 BTC at 100 XLM price would be (1, 100)
def update_offer(self, offer_id, sell_amount, sell_asset, buy_asset, price): """Updates offer with given offer_id with specified details. sell_asset, buy_asset are asset in 'native' or tuple in format (asset_code, asset_issuer). price in (numerator, denominator) format. To buy 1 BTC at 100 XLM price would be (1, 100) """ body = Xdr.nullclass() body.type = Xdr.const.MANAGE_OFFER body.manageOfferOp = Xdr.types.ManageOfferOp( XDR.asset_to_xdr(sell_asset), XDR.asset_to_xdr(buy_asset), XDR.amount_to_xdr(sell_amount), XDR.price_to_xdr(price), offer_id) self.ops += [Xdr.types.Operation([XDR.address_to_xdr(self.account)], body)] return self
class Offers
class Offers(Fetchable): class Offer(object): def __init__(self, data): self.offerid = data['id'] self.paging_token = data['paging_token'] self.seller = data['seller'] self.selling = Asset(data['selling']) self.buying = Asset(data['buying']) self.amount = data['amount'] self.price_r = (int(data['price_r']['n']), int(data['price_r']['d'])) self.price = data['price'] def __repr__(self): return 'Offer(%s,%s,%s,%s)' % (self.offerid, _shorten_address(self.seller),\ self.selling.asset_code, self.buying.asset_code) class __All(Fetchable): def __init__(self, baseurl=''): self.paginated = True self.streamed = False self.url = baseurl + '/offers' def _map2obj(self, data): return Offers.Offer(data) def stream(self): raise Exception('Stream not supported')
Ancestors (in MRO)
Class variables
var Offer
Methods
def fetch(
self, cursor=None, limit=10, order='asc')
Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'.
def fetch(self, cursor=None, limit=10, order='asc'): """Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'. """ if self.paginated: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) r = HTTP.get(horizon + self.url) if not self.paginated: return self._map2obj(r) return Fetchable.Page(lambda x : self._map2obj(x), r)
def first(
self)
Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction:
>>> stellar.transactions().first()
def first(self): """Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction: >>> stellar.transactions().first() """ r = self.fetch(limit=1, order='asc').records if len(r) > 0: return r[0] else: return None
def last(
self)
Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction:
>>> stellar.transactions().last()
def last(self): """Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction: >>> stellar.transactions().last() """ r = self.fetch(limit=1, order='desc').records if len(r) > 0: return r[0] else: return None
def stream(
self, cursor=None, limit=10, order='asc')
Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop.
def stream(self, cursor=None, limit=10, order='asc'): """Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop. """ if self.streamed: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) eventsource = HTTP.stream(horizon + self.url) for event in eventsource: if event.data == '"hello"': continue yield self._map2obj(json.loads(event.data)) else: raise Exception('stream not supported')
class Operations
class Operations(Fetchable): class Operation(object): """Operation: https://www.stellar.org/developers/horizon/reference/resources/operation.html""" def __init__(self, data): self.opid = data['id'] self.paging_token = data['paging_token'] self.source_account = data['source_account'] self.type = data['type'] self.type_i = t = int(data['type_i']) self.created_at = datetime.datetime.strptime( data['created_at'], "%Y-%m-%dT%H:%M:%SZ") self.transaction_hash = data['transaction_hash'] if t == 0: self.account = data['account'] self.funder = data['funder'] self.starting_balance = data['starting_balance'] elif t == 1: self.amount = data['amount'] self.asset = Asset(data) self.from_account = data['from'] self.to_account = data['to'] elif t == 2: self.amount = data['amount'] self.source_amount = data['source_amount'] self.from_account = data['from'] self.to_account = data['to'] self.asset = Asset(data) self.send_asset = Asset(data, 'send_') elif t == 3: self.offer_id = data['offer_id'] self.amount = data['amount'] self.price = data['price'] self.buying_asset = Asset(data, 'buying_') self.selling_asset = Asset(data, 'selling_') elif t == 4: self.amount = data['amount'] self.price = data['price'] self.buying_asset = Asset(data, 'buying_') self.selling_asset = Asset(data, 'selling_') elif t == 5: if 'low_threshold' in data: self.low_threshold = (True, data['low_threshold']) else: self.low_threshold = (False, None) if 'med_threshold' in data: self.med_threshold = (True, data['med_threshold']) else: self.med_threshold = (False, None) if 'high_threshold' in data: self.high_threshold = (True, data['high_threshold']) else: self.high_threshold = (False, None) if 'inflation_dest' in data: self.inflation_dest = (True, data['inflation_dest']) else: self.inflation_dest = (False, None) if 'home_domain' in data: self.home_domain = (True, data['home_domain']) else: self.home_domain = (False, None) if 'signer_key' in data: self.signer_key = (True, data['signer_key']) else: self.signer_key = (False, None) if 'signer_weight' in data: self.signer_weight = (True, int(data['signer_weight'])) else: self.signer_weight = (False, None) if 'master_key_weight' in data: self.master_key_weight = (True, int(data['master_key_weight'])) else: self.master_key_weight = (False, None) if 'set_flags' in data: self.set_flags = (True, data['set_flags']) else: self.set_flags = (False, None) if 'clear_flags' in data: self.clear_flags = (True, data['clear_flags']) else: self.clear_flags = (False, None) elif t == 6: self.trustor = data['trustor'] self.trustee = data['trustee'] self.asset = Asset(data) elif t == 7: self.trustor = data['trustor'] self.trustee = data['trustee'] self.asset = Asset(data) self.authorize = data['authorize'] elif t == 8: self.account = data['account'] self.merged_to = data['into'] elif t == 9: pass elif t == 10: self.key = data['name'] self.value = base64.b64decode(data['value']) else: raise Exception('Unsupported operation = %s' % self.type) def __repr__(self): return 'Operation(id=%s,account=%s,type=%s)' %\ (self.opid, _shorten_address(self.source_account), self.type) def __init__(self, opid): if not opid: raise ValueError('operation id expected') self.opid = opid self.paginated = False self.streamed = False self.url = '/operations/%s' % self.opid def _map2obj(self, data): return Operations.Operation(data) def effects(self): """Returns fechable object for effects associated with given operation""" return Effects._All(self.url) class _All(Fetchable): def __init__(self, baseurl=''): self.paginated = True self.streamed = True self.url = baseurl + '/operations' def _map2obj(self, data): return Operations.Operation(data)
Ancestors (in MRO)
- Operations
- Fetchable
- __builtin__.object
Class variables
var Operation
Instance variables
var opid
var paginated
var streamed
var url
Methods
def __init__(
self, opid)
def __init__(self, opid): if not opid: raise ValueError('operation id expected') self.opid = opid self.paginated = False self.streamed = False self.url = '/operations/%s' % self.opid
def effects(
self)
Returns fechable object for effects associated with given operation
def effects(self): """Returns fechable object for effects associated with given operation""" return Effects._All(self.url)
def fetch(
self, cursor=None, limit=10, order='asc')
Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'.
def fetch(self, cursor=None, limit=10, order='asc'): """Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'. """ if self.paginated: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) r = HTTP.get(horizon + self.url) if not self.paginated: return self._map2obj(r) return Fetchable.Page(lambda x : self._map2obj(x), r)
def first(
self)
Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction:
>>> stellar.transactions().first()
def first(self): """Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction: >>> stellar.transactions().first() """ r = self.fetch(limit=1, order='asc').records if len(r) > 0: return r[0] else: return None
def last(
self)
Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction:
>>> stellar.transactions().last()
def last(self): """Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction: >>> stellar.transactions().last() """ r = self.fetch(limit=1, order='desc').records if len(r) > 0: return r[0] else: return None
def stream(
self, cursor=None, limit=10, order='asc')
Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop.
def stream(self, cursor=None, limit=10, order='asc'): """Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop. """ if self.streamed: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) eventsource = HTTP.stream(horizon + self.url) for event in eventsource: if event.data == '"hello"': continue yield self._map2obj(json.loads(event.data)) else: raise Exception('stream not supported')
class Orderbooks
class Orderbooks(object): class Orderbook(object): def __init__(self, data): self.base_asset = Asset(data['base']) self.counter_asset = Asset(data['counter']) self.asks = [] self.bids = [] for a in data['asks']: self.asks += [( a['amount'], (a['price_r']['n'], a['price_r']['d']), a['price'], )] for b in data['bids']: self.bids += [( b['amount'], (b['price_r']['n'], b['price_r']['d']), b['price'], )] def __repr__(self): return 'Orderbook(base=%s,counter=%s)' % (self.base_asset, self.counter_asset) class _All(Fetchable): def __init__(self, selling, buying): self.paginated = False self.streamed = False self.url = '/order_book?%s&%s' %\ (Asset.format_url_parameters(selling, 'selling_'), Asset.format_url_parameters(buying, 'buying_')) def _map2obj(self, data): return Orderbooks.Orderbook(data)
class PaymentPaths
class PaymentPaths(object): class PaymentPath(object): def __init__(self, data): self.source_asset_type = data['source_asset_type'] if self.source_asset_type != 'native': self.source_asset_code = data['source_asset_code'] self.source_asset_issuer = data['source_asset_issuer'] self.source_amount = data['source_amount'] self.destination_asset_type = data['destination_asset_type'] if self.destination_asset_type != 'native': self.destination_asset_code = data['destination_asset_code'] self.destination_asset_issuer = data['destination_asset_issuer'] self.destination_amount = data['destination_amount'] self.path = [] for p in data['path']: self.path += [Asset(p)] def __repr__(self): return 'PaymentPath(src=%s,dest=%s,path=%s)' % (self.source_asset_type,\ self.destination_asset_type,self.path) def __init__(self, data): self.records = [PaymentPaths.PaymentPath(r) for r in data['_embedded']['records']] class _All(Fetchable): def __init__(self, from_account, to_account, to_asset, amount): self.paginated = False self.streamed = False self.url = '/paths?source_account=%s&destination_account=%s&%s&destination_amount=%s'\ % (from_account, to_account, Asset.format_url_parameters(to_asset, 'destination_'), amount) def _map2obj(self, data): return PaymentPaths(data)
Ancestors (in MRO)
- PaymentPaths
- __builtin__.object
Class variables
var PaymentPath
Instance variables
var records
Methods
def __init__(
self, data)
def __init__(self, data): self.records = [PaymentPaths.PaymentPath(r) for r in data['_embedded']['records']]
class Payments
class Payments(object): class Payment(object): def __init__(self, data): self.pid = data['id'] self.paging_token = data['paging_token'] self.source_account = data['source_account'] self.type = data['type'] self.type_i = int(data['type_i']) self.created_at = datetime.datetime.strptime( data['created_at'], "%Y-%m-%dT%H:%M:%SZ") self.transaction_hash = data['transaction_hash'] if self.type_i == 0: self.amount = data['starting_balance'] self.asset = native_asset self.destination = data['account'] else: self.amount = data['amount'] self.asset = Asset(data) self.destination = data['to'] def __repr__(self): return 'Payment(%s,from=%s,to=%s,amount=%s,asset=%s)' %\ (self.type, _shorten_address(self.source_account),\ _shorten_address(self.destination), self.amount, self.asset) class _All(Fetchable): def __init__(self, baseurl=''): self.paginated = True self.streamed = True self.url = baseurl + '/payments' def _map2obj(self, data): return Payments.Payment(data)
class Transactions
class Transactions(Fetchable): class Transaction(object): """Transactin: https://www.stellar.org/developers/horizon/reference/resources/transaction.html""" def __init__(self, data): self.trxid = data['id'] self.paging_token = data['paging_token'] self.hash = data['hash'] self.ledger = int(data['ledger']) self.account = data['source_account'] self.account_seq = data['source_account_sequence'] self.fee_paid = int(data['fee_paid']) self.operation_count = int(data['operation_count']) self.created_at = datetime.datetime.strptime( data['created_at'], '%Y-%m-%dT%H:%M:%SZ') memo_type = data['memo_type'] if memo_type == 'text': self.memo = (memo_type, data['memo']) elif memo_type == 'id': self.memo = (memo_type, int(data['memo'])) elif memo_type in ['hash', 'return']: self.memo = (memo_type, binascii.hexlify(base64.b64decode(data['memo']))) else: self.memo = None def __repr__(self): return 'Transaction(id=%s,ledger=%s,account=%s,seq=%s)' % (self.trxid,\ self.ledger, _shorten_address(self.account), self.account_seq) def __init__(self, trxid): if not trxid: raise ValueError('transaction id required') self.trxid = trxid self.paginated = False self.streamed = False self.url = '/transactions/%s' % self.trxid def _map2obj(self, data): return Transactions.Transaction(data) def operations(self): """Returns fechable object for operations associated with given transaction""" return Operations._All(self.url) def payments(self): """Returns fechable object for payments associated with given transaction""" return Payments._All(self.url) def effects(self): """Returns fechable object for effects associated with given transaction""" return Effects._All(self.url) class _All(Fetchable): def __init__(self, baseurl=''): self.paginated = True self.streamed = True self.url = baseurl + '/transactions' def _map2obj(self, data): return Transactions.Transaction(data)
Ancestors (in MRO)
- Transactions
- Fetchable
- __builtin__.object
Class variables
var Transaction
Instance variables
var paginated
var streamed
var trxid
var url
Methods
def __init__(
self, trxid)
def __init__(self, trxid): if not trxid: raise ValueError('transaction id required') self.trxid = trxid self.paginated = False self.streamed = False self.url = '/transactions/%s' % self.trxid
def effects(
self)
Returns fechable object for effects associated with given transaction
def effects(self): """Returns fechable object for effects associated with given transaction""" return Effects._All(self.url)
def fetch(
self, cursor=None, limit=10, order='asc')
Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'.
def fetch(self, cursor=None, limit=10, order='asc'): """Returns single or page object for given query. If paged object then optionally accepts cursor (default none), limit (default 10) and order (default asc). order can be 'asc' or 'desc'. """ if self.paginated: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) r = HTTP.get(horizon + self.url) if not self.paginated: return self._map2obj(r) return Fetchable.Page(lambda x : self._map2obj(x), r)
def first(
self)
Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction:
>>> stellar.transactions().first()
def first(self): """Helper method for paginated query. returns first record for given paged resource or None if thier are not records for given query. e.g. to fetch first transaction: >>> stellar.transactions().first() """ r = self.fetch(limit=1, order='asc').records if len(r) > 0: return r[0] else: return None
def last(
self)
Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction:
>>> stellar.transactions().last()
def last(self): """Helper method for paginated query. returns last record for given paged resource or None if thier are not records for given query. e.g. to fetch last transaction: >>> stellar.transactions().last() """ r = self.fetch(limit=1, order='desc').records if len(r) > 0: return r[0] else: return None
def operations(
self)
Returns fechable object for operations associated with given transaction
def operations(self): """Returns fechable object for operations associated with given transaction""" return Operations._All(self.url)
def payments(
self)
Returns fechable object for payments associated with given transaction
def payments(self): """Returns fechable object for payments associated with given transaction""" return Payments._All(self.url)
def stream(
self, cursor=None, limit=10, order='asc')
Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop.
def stream(self, cursor=None, limit=10, order='asc'): """Returns iterable stream for the given query. You can start stream from given cursor and order specified in the input. Returned stream can be iterable using for-loop. """ if self.streamed: urlsep = '&' if self.url.find('?') >= 0 else '?' if cursor: self.url = '%s%scursor=%s&limit=%s&order=%s' %\ (self.url, urlsep, cursor, limit, order) else: self.url = '%s%slimit=%s&order=%s' % (self.url,\ urlsep, limit, order) eventsource = HTTP.stream(horizon + self.url) for event in eventsource: if event.data == '"hello"': continue yield self._map2obj(json.loads(event.data)) else: raise Exception('stream not supported')