Source code for stellar_base.horizon

# coding: utf-8

import requests

try:
    from sseclient import SSEClient
except ImportError:
    SSEClient = None
try:
    # Python 3
    from urllib.parse import urlencode
except ImportError:
    # Python 2
    from urllib import urlencode

from .exceptions import HorizonError

HORIZON_LIVE = "https://horizon.stellar.org"
HORIZON_TEST = "https://horizon-testnet.stellar.org"


[docs]class Horizon(object): def __init__(self, horizon=None, sse=False, timeout=20): """The :class:`Horizon` object, which represents the interface for making requests to a Horizon server instance. This class aims to be up to date with Horizon's API endpoints; however, you can utilize the internal session via ``self.session`` (which is a :class:`requests.Session` object) to make arbitrary requests to a Horizon instance's API. In general, on HTTP errors (non 2XX/3XX responses), no exception is raised, and the return dictionary must be checked to see if it is an error or a valid response. Any other errors however are raised by this class. :param str horizon: The horizon base URL :param bool sse: Default to using server side events for streaming responses when available. :param int timeout: The timeout for all requests. """ if sse and SSEClient is None: raise ValueError('SSE not supported, missing sseclient module') if horizon is None: self.horizon = HORIZON_TEST else: self.horizon = horizon self.session = requests.Session() self.sse = sse self.timeout = timeout def _request(self, verb, endpoint, **kwargs): url = '{base}{endpoint}'.format(base=self.horizon, endpoint=endpoint) if kwargs.get('sse', False): if 'params' in kwargs and kwargs['params']: url = '{}?{}'.format(url, urlencode(kwargs['params'])) messages = SSEClient(url) return messages else: kwargs.pop('sse', None) try: # FIXME: We should really consider raising the HTTPError when # it happens and wrapping its JSON response in a HorizonError resp = self.session.request( verb, url, timeout=self.timeout, **kwargs) return resp.json() except requests.RequestException: raise HorizonError( 'Could not successfully make a request to Horizon.') def _get(self, endpoint, **kwargs): # If sse has been passed in by an endpoint (meaning it supports sse) # but it hasn't been explicitly been set by the request, default to the # this instance's setting on SSE requests. if 'sse' in kwargs and kwargs['sse'] is None: kwargs['sse'] = self.sse return self._request('GET', endpoint, **kwargs) def _post(self, endpoint, **kwargs): return self._request('POST', endpoint, **kwargs)
[docs] def submit(self, te, **kwargs): """Submit a transaction to Horizon. `POST /transactions <https://www.stellar.org/developers/horizon/reference/endpoints/transactions-create.html>`_ Uses form-encoded data to send over to Horizon. :param bytes te: The transaction envelope to submit :return: The JSON response indicating the success/failure of the submitted transaction. :rtype: dict """ payload = {'tx': te}
return self._post('/transactions', data=payload, **kwargs)
[docs] def account(self, address, **kwargs): """Returns information and links relating to a single account. `GET /accounts/{account} <https://www.stellar.org/developers/horizon/reference/endpoints/accounts-single.html>`_ :param str address: The account ID to retrieve details about :return: The account details in a JSON response :rtype: dict """ endpoint = '/accounts/{account_id}'.format(account_id=address)
return self._get(endpoint, **kwargs)
[docs] def account_data(self, account_id, data_key, **kwargs): """This endpoint represents a single data associated with a given account. `GET /accounts/{account}/data/{key} <https://www.stellar.org/developers/horizon/reference/endpoints/data-for-account.html>`_ :param str account_id: The account ID to look up a data item from :param str data_key: The name of the key for the data item in question :return: The value of the data field for the given account and data key :rtype: dict """ endpoint = '/accounts/{account_id}/data/{data_key}'.format( account_id=account_id, data_key=data_key)
return self._get(endpoint, **kwargs)
[docs] def account_effects(self, address, params=None, sse=None, **kwargs): """This endpoint represents all effects that changed a given account. `GET /accounts/{account}/effects{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/effects-for-account.html>`_ :param str address: The account ID to look up effects for. :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :param bool sse: Use server side events for streaming responses :return: The list of effects in a JSON response. :rtype: dict """ endpoint = '/accounts/{account_id}/effects'.format(account_id=address)
return self._get(endpoint, params=params, **kwargs)
[docs] def account_offers(self, address, params=None, **kwargs): """This endpoint represents all the offers a particular account makes. `GET /accounts/{account}/offers{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/offers-for-account.html>`_ :param str address: The account ID to retrieve offers from :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :return: The list of offers for an account in a JSON response. :rtype: dict """ endpoint = '/accounts/{account_id}/offers'.format(account_id=address)
return self._get(endpoint, params=params, **kwargs)
[docs] def account_operations(self, address, params=None, sse=None, **kwargs): """This endpoint represents all operations that were included in valid transactions that affected a particular account. `GET /accounts/{account}/operations{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/operations-for-account.html>`_ :param str address: The account ID to list operations on :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :param bool sse: Use server side events for streaming responses :return: The list of operations for an account in a JSON response. :rtype: dict """ endpoint = '/accounts/{account_id}/operations'.format( account_id=address)
return self._get(endpoint, params=params, sse=sse, **kwargs)
[docs] def account_transactions(self, address, params=None, sse=None, **kwargs): """This endpoint represents all transactions that affected a given account. `GET /accounts/{account_id}/transactions{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/transactions-for-account.html>`_ :param str address: The account ID to list transactions from :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :return: The list of transactions for an account in a JSON response. :rtype: dict """ endpoint = '/accounts/{account_id}/transactions'.format( account_id=address)
return self._get(endpoint, params=params, sse=sse, **kwargs)
[docs] def account_payments(self, address, params=None, sse=None, **kwargs): """This endpoint responds with a collection of Payment operations where the given account was either the sender or receiver. `GET /accounts/{id}/payments{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/payments-for-account.html>`_ :param str address: The account ID to list payments to/from :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :param bool sse: Use server side events for streaming responses :return: The list of payments for an account in a JSON response. :rtype: dict """ endpoint = '/accounts/{account_id}/payments'.format( account_id=address)
return self._get(endpoint, params=params, sse=sse, **kwargs)
[docs] def assets(self, params=None, **kwargs): """This endpoint represents all assets. It will give you all the assets in the system along with various statistics about each. See the documentation below for details on query parameters that are available. `GET /assets{?asset_code,asset_issuer,cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/assets-all.html>`_ :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :return: A list of all valid payment operations :rtype: dict """ endpoint = '/assets'
return self._get(endpoint, params=params, **kwargs)
[docs] def transactions(self, params=None, sse=None, **kwargs): """This endpoint represents all validated transactions. `GET /transactions{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/transactions-all.html>`_ :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :param bool sse: Use server side events for streaming responses :return: The list of all transactions :rtype: dict """ endpoint = '/transactions'
return self._get(endpoint, params=params, sse=sse, **kwargs)
[docs] def transaction(self, tx_hash, **kwargs): """The transaction details endpoint provides information on a single transaction. `GET /transactions/{hash} <https://www.stellar.org/developers/horizon/reference/endpoints/transactions-single.html>`_ :param str tx_hash: The hex-encoded transaction hash :return: A single transaction's details :rtype: dict """ endpoint = '/transactions/{tx_hash}'.format(tx_hash=tx_hash)
return self._get(endpoint, **kwargs)
[docs] def transaction_operations(self, tx_hash, params=None, **kwargs): """This endpoint represents all operations that are part of a given transaction. `GET /transactions/{hash}/operations{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/operations-for-transaction.html>`_ :param str tx_hash: The hex-encoded transaction hash :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :return: A single transaction's operations :rtype: dict """ endpoint = '/transactions/{tx_hash}/operations'.format( tx_hash=tx_hash)
return self._get(endpoint, params=params, **kwargs)
[docs] def transaction_effects(self, tx_hash, params=None, **kwargs): """This endpoint represents all effects that occurred as a result of a given transaction. `GET /transactions/{hash}/effects{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/effects-for-transaction.html>`_ :param str tx_hash: The hex-encoded transaction hash :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :return: A single transaction's effects :rtype: dict """ endpoint = '/transactions/{tx_hash}/effects'.format( tx_hash=tx_hash)
return self._get(endpoint, params=params, **kwargs)
[docs] def transaction_payments(self, tx_hash, params=None, **kwargs): """This endpoint represents all payment operations that are part of a given transaction. `GET /transactions/{hash}/payments{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/payments-for-transaction.html>`_ :param str tx_hash: The hex-encoded transaction hash :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :return: A single transaction's payment operations :rtype: dict """ endpoint = '/transactions/{tx_hash}/payments'.format( tx_hash=tx_hash)
return self._get(endpoint, params=params, **kwargs)
[docs] def order_book(self, params=None, **kwargs): """Return, for each orderbook, a summary of the orderbook and the bids and asks associated with that orderbook. See the external docs below for information on the arguments required. `GET /order_book <https://www.stellar.org/developers/horizon/reference/endpoints/orderbook-details.html>`_ :param dict params: The query parameters to pass to this request. :return: A list of orderbook summaries as a JSON object. :rtype: dict """ endpoint = '/order_book'
return self._get(endpoint, params=params, **kwargs)
[docs] def ledgers(self, params=None, sse=None, **kwargs): """This endpoint represents all ledgers. `GET /ledgers{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/ledgers-all.html>`_ :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :return: All ledgers on the network. :rtype: dict """ endpoint = '/ledgers'
return self._get(endpoint, params=params, sse=sse, **kwargs)
[docs] def ledger(self, ledger_id, **kwargs): """The ledger details endpoint provides information on a single ledger. `GET /ledgers/{sequence} <https://www.stellar.org/developers/horizon/reference/endpoints/ledgers-single.html>`_ :param int ledger_id: The id of the ledger to look up :return: The details of a single ledger :rtype: dict """ endpoint = '/ledgers/{ledger_id}'.format(ledger_id=ledger_id)
return self._get(endpoint, **kwargs)
[docs] def ledger_effects(self, ledger_id, params=None, **kwargs): """This endpoint represents all effects that occurred in the given ledger. `GET /ledgers/{id}/effects{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/effects-for-ledger.html>`_ :param int ledger_id: The id of the ledger to look up :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :return: The effects for a single ledger :rtype: dict """ endpoint = '/ledgers/{ledger_id}/effects'.format(ledger_id=ledger_id)
return self._get(endpoint, params=params, **kwargs)
[docs] def ledger_operations(self, ledger_id, params=None, **kwargs): """This endpoint returns all operations that occurred in a given ledger. `GET /ledgers/{id}/operations{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/operations-for-ledger.html>`_ :param int ledger_id: The id of the ledger to look up :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :return: The operations contained in a single ledger :rtype: dict """ endpoint = '/ledgers/{ledger_id}/operations'.format( ledger_id=ledger_id)
return self._get(endpoint, params=params, **kwargs)
[docs] def ledger_payments(self, ledger_id, params=None, **kwargs): """This endpoint represents all payment operations that are part of a valid transactions in a given ledger. `GET /ledgers/{id}/payments{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/payments-for-ledger.html>`_ :param int ledger_id: The id of the ledger to look up :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :return: The payments contained in a single ledger :rtype: dict """ endpoint = '/ledgers/{ledger_id}/payments'.format(ledger_id=ledger_id)
return self._get(endpoint, params=params, **kwargs)
[docs] def ledger_transactions(self, ledger_id, params=None, **kwargs): """This endpoint represents all transactions in a given ledger. `GET /ledgers/{id}/transactions{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/transactions-for-ledger.html>`_ :param int ledger_id: The id of the ledger to look up. :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :return: The transactions contained in a single ledger :rtype: dict """ endpoint = '/ledgers/{ledger_id}/transactions'.format( ledger_id=ledger_id)
return self._get(endpoint, params=params, **kwargs)
[docs] def effects(self, params=None, sse=None, **kwargs): """This endpoint represents all effects. `GET /effects{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/effects-all.html>`_ :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :param bool sse: Use server side events for streaming responses :return: A list of all effects :rtype: dict """ endpoint = '/effects'
return self._get(endpoint, params=params, sse=sse, **kwargs)
[docs] def operations(self, params=None, sse=None, **kwargs): """This endpoint represents all operations that are part of validated transactions. `GET /operations{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/operations-all.html>`_ :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :param bool sse: Use server side events for streaming responses :return: A list of all operations :rtype: dict """ endpoint = '/operations'
return self._get(endpoint, params=params, sse=sse, **kwargs)
[docs] def operation(self, op_id, **kwargs): """The operation details endpoint provides information on a single operation. `GET /operations/{id} <https://www.stellar.org/developers/horizon/reference/endpoints/operations-single.html>`_ :param id op_id: The operation ID to get details on. :return: Details on a single operation :rtype: dict """ endpoint = '/operations/{op_id}'.format(op_id=op_id)
return self._get(endpoint, **kwargs)
[docs] def operation_effects(self, op_id, params=None, **kwargs): """This endpoint represents all effects that occurred as a result of a given operation. `GET /operations/{id}/effects{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/effects-for-operation.html>`_ :param int op_id: The operation ID to get effects on. :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :return: A list of effects on the given operation :rtype: dict """ endpoint = '/operations/{op_id}/effects'.format(op_id=op_id)
return self._get(endpoint, params=params, **kwargs)
[docs] def payments(self, params=None, sse=None, **kwargs): """This endpoint represents all payment operations that are part of validated transactions. `GET /payments{?cursor,limit,order} <https://www.stellar.org/developers/horizon/reference/endpoints/payments-all.html>`_ :param dict params: The query parameters to pass to this request, such as cursor, order, and limit. :param bool sse: Use server side events for streaming responses :return: A list of all valid payment operations :rtype: dict """ endpoint = '/payments'
return self._get(endpoint, params=params, sse=sse, **kwargs)
[docs] def paths(self, params=None, **kwargs): """Load a list of assets available to the source account id and find any payment paths from those source assets to the desired destination asset. See the below docs for more information on required and optional parameters for further specifying your search. `GET /paths <https://www.stellar.org/developers/horizon/reference/endpoints/path-finding.html>`_ :param dict params: The query parameters to pass to this request, such as source_account, destination_account, destination_asset_type, etc. :return: A list of paths that can be used to complete a payment based on a given query. :rtype: dict """ endpoint = '/paths'
return self._get(endpoint, params=params, **kwargs)
[docs] def trades(self, params=None, **kwargs): """Load a list of trades, optionally filtered by an orderbook. See the below docs for more information on required and optional parameters for further specifying your search. `GET /trades <https://www.stellar.org/developers/horizon/reference/endpoints/trades.html>`_ :param dict params: The query parameters to pass to this request, such as base_asset_type, counter_asset_type, cursor, order, limit, etc. :return: A list of trades filtered by a given query :rtype: dict """ endpoint = '/trades'
return self._get(endpoint, params=params, **kwargs)
[docs] def trade_aggregations(self, params=None, **kwargs): """Load a list of aggregated historical trade data, optionally filtered by an orderbook. `GET /trade_aggregations <https://www.stellar.org/developers/horizon/reference/endpoints/trade_aggregations.html>`_ :param dict params: The query parameters to pass to this request, such as start_time, end_time, base_asset_type, counter_asset_type, order, limit, etc. :return: A list of collected trade aggregations :rtype: dict """ endpoint = '/trade_aggregations'
return self._get(endpoint, params=params, **kwargs)
[docs]def horizon_testnet(): """Create a Horizon instance utilizing SDF's Test Network."""
return Horizon(HORIZON_TEST)
[docs]def horizon_livenet(): """Create a Horizon instance utilizing SDF's Live Network."""
return Horizon(HORIZON_LIVE)