diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index ce23833..759cf5c 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.5, 3.6, 3.7, 3.8, 3.9] + python-version: [ 3.7, 3.8, 3.9, '3.10' ] steps: - uses: actions/checkout@v2 diff --git a/README.md b/README.md index 897d190..5f80f51 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,17 @@ # Messari -[![Python 3.5](https://img.shields.io/badge/python-3.5-blue.svg)](https://www.python.org/downloads/release/python-350/) -[![Python 3.6](https://img.shields.io/badge/python-3.6-blue.svg)](https://www.python.org/downloads/release/python-360/) [![Python 3.7](https://img.shields.io/badge/python-3.7-blue.svg)](https://www.python.org/downloads/release/python-370/) [![Python 3.8](https://img.shields.io/badge/python-3.8-blue.svg)](https://www.python.org/downloads/release/python-380/) [![Python 3.9](https://img.shields.io/badge/python-3.9-blue.svg)](https://www.python.org/downloads/release/python-390/) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -![Build](https://github.com/itzmestar/Messari/workflows/Build/badge.svg) - ------- ### Unofficial [Messari's Crypto Data API](https://messari.io/) client in python The library can be used for crypto prices, market data metrics, on-chain metrics, and qualitative information (asset profile). -For more information, see [Messari API Documentation](https://messari.io/api/docs) +For more information, see [Messari API Documentation](https://messari.io/api) ### Installation: use pip to install: @@ -26,9 +22,7 @@ pip install messari ### Authentication: -Most endpoints are accessible without an API key. - -Pass API key in object initialization if required. +Pass API key in object initialization. ----------- @@ -37,75 +31,17 @@ Pass API key in object initialization if required. from messari import Messari # initialize api client -# API Key is optional + messari = Messari(key='xxxxxxxxxxxxxxx') # Get the paginated list of all assets and their metrics and profiles. response = messari.get_all_assets() -# Use query parameters -query = { - 'with-profiles': True, - 'with-metrics': True, - 'fields': 'id,slug,symbol,metrics/market_data/price_usd' -} -response = messari.get_all_assets(**query) - -# set filter fields -fields='symbol,name,slug' - -# Get basic metadata for an asset. -response = messari.get_asset(asset_key='btc', fields=fields) - -# Get all of our qualitative information for an asset. -fields='symbol,name,profile/general/overview/project_details' -response = messari.get_asset_profile(asset_key='btc', fields=fields) - -# Get all of our quantitative metrics for an asset. -fields = 'id,slug,symbol,market_data/price_usd,market_data/volume_last_24_hours' -response = messari.get_asset_metrics(asset_key='btc', fields=fields) - -# Get the latest market data for an asset. -fields = 'id,slug,symbol,market_data/price_usd,market_data/volume_last_24_hours' -response = messari.get_asset_market_data(asset_key='btc', fields=fields) - -# Lists all of the available timeseries metric IDs for assets. -response = messari.list_asset_timeseries_metric_ids() - -# Retrieve historical timeseries data for an asset. -query_params = { - 'start': '2020-01-01', - 'end': '2020-02-01', - 'interval': '1d', - 'columns': 'open,close', - 'order': 'ascending', - 'format': 'json', - 'timestamp-format': 'rfc3339' -} -response = messari.get_asset_timeseries(asset_key='bitcoin', metric_id='price', **query_params) - -# Get the list of all exchanges and pairs that our WebSocket-based -# market real-time market data API supports. -fields = 'exchange_name,pair,last_trade_at' -response = messari.get_all_markets(fields=fields) - -# Retrieve historical timeseries data for a market. -query_params = { - 'start': '2020-01-01', - 'end': '2020-03-01', - 'interval': '1d', - 'columns': 'open,close', - 'order': 'ascending', - 'format': 'json', - 'timestamp-format': 'rfc3339' -} -response = messari.get_market_timeseries(market_key='binance-btc-usdt', metric_id='price', **query_params) - -# Get the latest (paginated) news and analysis for all assets. -fields='title,content' -response = messari.get_all_news(fields=fields) - -# Get the latest (paginated) news and analysis for all assets. -fields='title,content' -response = messari.get_news_for_asset(asset_key='btc', fields=fields) ``` + +------- +#### Donate & Help maintain the library + +[![Paypal](qrcode.png)](https://www.paypal.com/ncp/payment/KLFNJN7SH39EN) + +------- \ No newline at end of file diff --git a/messari/__version__.py b/messari/__version__.py index 884ccd2..807fc99 100644 --- a/messari/__version__.py +++ b/messari/__version__.py @@ -2,7 +2,7 @@ __title__ = 'messari' __description__ = 'Unofficial Messari API client.' __url__ = 'https://github.com/itzmestar/Messari' -__version__ = '1.0.1' +__version__ = '2.0.0' __build__ = 0x010001 __author__ = 'Tarique Anwer' __author_email__ = 'itzmetariq@gmail.com' diff --git a/messari/messari.py b/messari/messari.py index 56ba9f7..32cbac9 100644 --- a/messari/messari.py +++ b/messari/messari.py @@ -6,7 +6,7 @@ # --------- Constants --------- # -BASE_URL = "https://data.messari.io" +BASE_URL = "https://api.messari.io" # --------- Constants --------- # @@ -17,15 +17,15 @@ class Messari: All the requests can be made through this class. """ - def __init__(self, key=None): + def __init__(self, key): """ Initialize the object :param key: API key """ self.key = key self.session = requests.Session() - if self.key: - self.session.headers.update({'x-messari-api-key': key}) + self.session.headers.update({'x-messari-api-key': key}) + self.session.headers.update({'accept': "application/json"}) def _send_message(self, method, endpoint, params=None, data=None): """ @@ -53,209 +53,184 @@ def _get(self, endpoint, params=None): def get_all_assets(self, **query_params): """ Get the paginated list of all assets and their metrics and profiles. - Endpoint: GET /api/v2/assets :param query_params: dict of query parameters to filter the list :return: JSON response """ - path = '/api/v2/assets' - if query_params.get('with-profiles', False) and query_params.get('with-metrics', False): - path += '?with-metrics&with-profiles' - elif query_params.get('with-profiles', False): - path += '?with-profiles' - elif query_params.get('with-metrics', False): - path += '?with-metrics' - - if 'with-metrics' in query_params: - del query_params['with-metrics'] - if 'with-profiles' in query_params: - del query_params['with-profiles'] + path = '/asset/v1/assets' return self._get(path, params=query_params) - def get_asset(self, asset_key, fields=None): + def get_asset_by_id(self, asset_id: str): """ - Get basic metadata for an asset. - Endpoint: GET /api/v1/assets/{assetKey} - - :param asset_key: This "key" can be the asset's ID (unique), slug (unique), - or symbol (non-unique) - :param fields: string: pare down the returned fields (comma , separated, - drill down with a slash /) - example: fields='id,slug,symbol,metrics/market_data/price_usd' + Returns the ID, name, symbol, slug, market cap, sector, category, and tags for a single asset. :return: JSON response """ - path = '/api/v1/assets/{}'.format(asset_key) - param = { - 'fields': fields - } - return self._get(path, params=param) + path = f'/asset/v1/assets/{asset_id}' - def get_asset_profile(self, asset_key, fields=None): - """ - Get all of our qualitative information for an asset. - Endpoint: GET /api/v2/assets/{assetKey}/profile + return self._get(path) - :param asset_key: This "key" can be the asset's ID (unique), slug (unique), - or symbol (non-unique) - :param fields: string: pare down the returned fields (comma , separated, - drill down with a slash /) - example: fields='id,slug,symbol,metrics/market_data/price_usd' + def get_market_data_by_asset(self, asset_id: str): + """ + Returns market data for a specific asset. :return: JSON response """ - path = '/api/v2/assets/{}/profile'.format(asset_key) - - param = { - 'fields': fields - } + path = f'/marketdata/v1/assets/{asset_id}/price' - return self._get(path, params=param) + return self._get(path) - def get_asset_metrics(self, asset_key, fields=None): + def get_timeseries_by_asset(self, asset_id: str, startTime: str, endTime: str, interval: str = None, vwapType: str = None): """ - Get all of our quantitative metrics for an asset. - Endpoint: GET /api/v1/assets/{assetKey}/metrics + Lists all the available timeseries for asset. - :param asset_key: This "key" can be the asset's ID (unique), slug (unique), - or symbol (non-unique) - :param fields: string: pare down the returned fields (comma , separated, - drill down with a slash /) - example: fields='id,slug,symbol,metrics/market_data/price_usd' :return: JSON response """ - path = '/api/v1/assets/{}/metrics'.format(asset_key) - param = { - 'fields': fields + path = f'/marketdata/v1/assets/{asset_id}/price/time-series' + params = { + 'interval': interval, + 'vwapType': vwapType, + 'startTime': startTime, + 'endTime': endTime, } + return self._get(path, params=params) - return self._get(path, params=param) - - def get_asset_market_data(self, asset_key, fields=None): + def get_all_time_high(self): """ - Get the latest market data for an asset. - This data is also included in the metrics endpoint, - but if all you need is market-data, use this. - Endpoint: GET /api/v1/assets/{assetKey}/metrics/market-data - - :param asset_key: This "key" can be the asset's ID (unique), slug (unique), - or symbol (non-unique) - :param fields: string: pare down the returned fields (comma , separated, - drill down with a slash /) - example: fields='id,slug,symbol,metrics/market_data/price_usd' - :return: JSON response + Returns a list of all time high data for all assets. """ - path = '/api/v1/assets/{}/metrics/market-data'.format(asset_key) - param = { - 'fields': fields - } + path = '/marketdata/v1/assets/ath' - return self._get(path, params=param) + return self._get(path) - def list_asset_timeseries_metric_ids(self): + def get_all_time_high_by_asset(self, asset_id): """ - Lists all of the available timeseries metric IDs for assets. - Endpoint: GET https://data.messari.io/api/v1/assets/metrics - - :return: JSON response + Returns a single assets ATH data. """ - path = '/api/v1/assets/metrics' + path = f'/marketdata/v1/assets/{asset_id}/ath' + return self._get(path) - def get_asset_timeseries(self, asset_key, metric_id, **query_params): + def get_roi(self): """ - Retrieve historical timeseries data for an asset. - You can specify the range of what points will be returned - using (begin, end, start, before, after) query parameters. - All range parameters are inclusive of the specified date. + Returns a list ROI data for all assets. + """ + path = f'/marketdata/v1/assets/roi' - Endpoint: GET /api/v1/assets/{assetKey}/metrics/{metric_id}/time-series + return self._get(path) - :param asset_key: This "key" can be the asset's ID (unique), slug (unique), - or symbol (non-unique) - :param metric_id: specifies which timeseries will be returned. - :param query_params: dict of query parameters to filter the list - :return: JSON response + def get_roi_by_asset(self, asset_id): """ - path = '/api/v1/assets/{}/metrics/{}/time-series'.format(asset_key, metric_id) - return self._get(path, params=query_params) - - def get_all_markets(self, fields=None): + Returns a single assets ROI data. """ - Get the list of all exchanges and pairs that our WebSocket-based - market real-time market data API supports. - Endpoint: GET /api/v1/markets + path = f'/marketdata/v1/assets/{asset_id}/roi' - :param fields: string: pare down the returned fields (comma , separated, - drill down with a slash /) - example: fields='id,slug,symbol,metrics/market_data/price_usd' - :return: JSON response + return self._get(path) + + def get_markets(self, + exchangeId: str = None, + baseAssetId: str = None, + quoteAssetId: str = None, + volumeAbove: str = None, + volumeBelow: str = None, + vwapAbove: str = None, + vwapBelow: str = None + ): + """ + Returns a list of market specific data for all markets. """ - path = '/api/v1/markets' - param = { - 'fields': fields + path = f'/marketdata/v1/markets' + + params = { + 'exchangeId': exchangeId, + 'baseAssetId': baseAssetId, + 'quoteAssetId': quoteAssetId, + 'volumeAbove': volumeAbove, + 'volumeBelow': volumeBelow, + 'vwapAbove': vwapAbove, + 'vwapBelow': vwapBelow } - return self._get(path, params=param) + return self._get(path, params=params) - def get_market_timeseries(self, market_key, metric_id, **query_params): + def get_market(self, market_id: str): """ - Retrieve historical timeseries data for a market. + Returns a list of market specific data for one market. + """ + path = f'/marketdata/v1/markets/{market_id}' - Endpoint: GET /api/v1/markets/{assetKey}/metrics/{metric_id}/time-series + return self._get(path) - :param market_key: This "key" can be the asset's ID (unique), slug (unique), - or symbol (non-unique) - :param metric_id: The metricID is a unique identifier which determines which - columns are returned by time-series endpoints. For a list of valid - metric ids, check the API response at https://data.messari.io/api/assets/metrics. - :param query_params: dict of query parameters to filter the list - :return: JSON response + def get_timeseries_by_market( + self, + market_id: str, + startTime: str, + endTime: str, + interval: str = None, + denominatedIn: str = None + ): """ - path = '/api/v1/markets/{}/metrics/{}/time-series'.format(market_key, metric_id) - return self._get(path, params=query_params) - - def get_all_news(self, page=None, fields=None): + Returns timeseries price and volume data for a given market. """ - Get the latest (paginated) news and analysis for all assets. + path = f'/marketdata/v1/markets/{market_id}/price/time-series' - Endpoint: GET /api/v1/news - - :param page: Page number, starts at 1. Increment to paginate through - results (until result is empty array) - :param fields: string: pare down the returned fields (comma , separated, - drill down with a slash /) - example: fields='id,slug,symbol,metrics/market_data/price_usd' - :return: JSON response - """ - path = '/api/v1/news' params = { - 'fields': fields + 'interval': interval, + 'denominatedIn': denominatedIn, + 'startTime': startTime, + 'endTime': endTime } - if page: - params['page'] = page return self._get(path, params=params) - def get_news_for_asset(self, asset_key, page=None, fields=None): + def get_exchanges(self): + """ + Returns a list of exchanges with market data. """ - Get the latest (paginated) news and analysis for all assets. + path = '/marketdata/v1/exchanges' - Endpoint: GET /api/v1/news/{asset_key} + return self._get(path) - :param asset_key: This "key" can be the asset's ID (unique), slug (unique), - or symbol (non-unique) - :param page: Page number, starts at 1. Increment to paginate through results - (until result is empty array) - :param fields: string: pare down the returned fields (comma , separated, - drill down with a slash /) - example: fields='id,slug,symbol,metrics/market_data/price_usd' - :return: JSON response + def get_volume_timeseries_by_exchange( + self, + exchange_id: str, + startTime: str = None, + endTime: str = None, + interval: str = None + ): + """ + Provides time series volume data for a given exchange. """ - path = '/api/v1/news/{}'.format(asset_key) + path = f'/marketdata/v1/exchanges/{exchange_id}/volume/time-series' + params = { - 'fields': fields + 'interval': interval, + 'startTime': startTime, + 'endTime': endTime } - if page: - params['page'] = page return self._get(path, params=params) + + def get_events(self, **kwargs): + """ + Returns a list of all events and the most recent update. If there is no latest update to the event, + the response will return updateDetails: null. + """ + path = f'/intel/v1/events' + + return self._get(path, params=kwargs) + + def get_event_history(self, eventId: str): + """ + Returns a single event and its entire history of updates by event ID. + """ + path = f'/intel/v1/events/{eventId}' + + return self._get(path) + + def get_supported_assets(self, **kwargs): + """ + Returns a list of all assets that Messari Intel actively covers. + """ + path = f'/intel/v1/assets' + + return self._get(path, params=kwargs) diff --git a/qrcode.png b/qrcode.png new file mode 100644 index 0000000..e13d221 Binary files /dev/null and b/qrcode.png differ