{ "info": { "author": "Fenix Blockchain Technology", "author_email": "support@fenixblockchain.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Framework :: AsyncIO", "Intended Audience :: Developers", "Intended Audience :: Financial and Insurance Industry", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.7", "Topic :: Office/Business :: Financial" ], "description": "# Fenix Pipeline Python SDK\n\nThe Fenix Pipeline Python SDK facilitates connection to and interaction with the [Fenix Pipeline API](https://github.com/fenix-blockchain/fenix-pipeline) from any Python application.\n\n\n## Prerequisites and Notes\n\nThe following should be considered when using the SDK:\n\n* The Fenix Pipeline API requires an authentication token. Tokens are currently only available to select beta customers.\n* The Python SDK is written using `asyncio` for performance. There are not currently specific plans to add other async libraries (such as `gevent`) but this may be considered in future releases. If you need such support, contact Fenix to discuss.\n\n\n## Sample Usage\n\nThe following program demonstrates the basic use of the SDK:\n\n```python\nimport asyncio\nimport os\n\nfrom fenix_pipeline import ConnectionClosed\nfrom fenix_pipeline import RawDataSocket\nfrom fenix_pipeline import SubscriptionTypes\nfrom fenix_pipeline import Trade\n\nasync def simple_sample(event_loop):\n # read the API key from a local environment variable called `FENIX_API_KEY`\n socket = RawDataSocket(os.environ.get('FENIX_API_KEY'))\n # using a context manager\n async with await socket.connect(message_handler=print_messages) as subscriber:\n # subscribe to the `btc-usdt` stream\n await subscriber.subscribe(\n SubscriptionTypes.TRADES_BY_MARKET, 'btc-usdt')\n # just receive messages for the next 10 seconds\n await subscriber.monitor(10)\n # unsubscribe from the `btc-usdt` stream\n await subscriber.unsubscribe(\n SubscriptionTypes.TRADES_BY_MARKET, 'btc-usdt')\n # done\n\nasync def print_messages(item):\n if isinstance(item, Trade):\n log.info('received: %r', item)\n else:\n log.info('other message: %s', item)\n\nevent_loop = asyncio.get_event_loop()\nevent_loop.run_until_complete(simple_sample(event_loop))\n```\n\n\n## Detailed Documentation\n\nThe SDK uses a context manager to manage connection state and an async coroutine to provide data to the user.\n\n\n### RawDataSocket Context Manager\n\nThe `RawDataSocket` class provides the context manager and manages all async activity. Create a RawDataSocket by passing an API key, and then call `connect(message_handler)` on the object to establish the connection:\n\n```python\nsocket = RawDataSocket(my_api_key)\n\n# alternate, condensed version\nwith socket.connect(my_message_handler) as subscriber:\n # ... interact with server\n # now sleep this coroutine\n await subscriber.monitor(10)\n```\n\n**Note:** all following sections assume you are using the name `subscriber` as shown above.\n\nOnce you have a subscriber, you can check it's current connection state with the `.connected` property:\n\n```python\nif not subscriber.connected:\n # the connection has been closed\n pass\n```\n\nYou can let the subscriber receive events for a prescribed amount of time or indefinitely using the `.monitor()` method:\n\n```python\ntry:\n # monitor for 10 seconds\n await subscriber.monitor(timeout=10)\n # monitor indefinitely\n await subscriber.monitor()\nexcept ConnectionClosed:\n # the connection to the API was closed unexpectedly\n pass\n```\n\nThe subscriber will continue to receive data after the call to `.monitor()` returns; this is simply a convenience method to sleep the context manager while data is being received.\n\n\n### Subscribing to Channels\n\nWithin the context manager, the `subscriber` object gives you methods for requesting the channels you receive.\n\n\n#### Trade Data\n\nYou can get trade data in three basic subscription types. Each of these types is selectable from the `SubscriptionTypes` enum:\n\n* `SubscriptionTypes.TRADES_BY_EXCHANGE`: all trades on any market within a certain exchange\n* `SubscriptionTypes.TRADES_BY_MARKET`: all trades from any exchange associated with a specific market (such as `BTC-USDT`)\n* `SubscriptionTypes.ALL_TRADES`: every received trade regardless of market and regardless of exchange\n\n\n```python\nfrom fenix_pipeline import SubscriptionType\nsubscription_type = SubscriptionTypes.ALL_TRADES\n```\n\n\n##### All Trades\n\nTo subscribe to all trades:\n\n```python\nawait subscriber.subscribe(SubscriptionTypes.ALL_TRADES)\n```\n\n**Note:** the `ALL_TRADES` subscription will contain a very large number of trades; ensure your code is performant and your network connection is sufficient to avoid losing data in the stream.\n\n\n##### Trades by Market\n\nTo subscribe to all trades within a given market (in this example, BTC-USDT):\n\n```python\nawait subscriber.subscribe(SubscriptionTypes.TRADES_BY_MARKET, 'btc-usdt')\n```\n\n\n##### Trades by Exchange\n\nTo subscribe to all trades coming from a given exchange (in this example, Binance):\n\n```python\nawait subscriber.subscribe(SubscriptionTypes.TRADES_BY_EXCHANGE, 'binance')\n```\n\n\n##### Subscription Response\n\nAfter sending a subscription request, a message will be sent back confirming the channel has been successfully subscribed:\n\n```python\nawait subscriber.subscribe(SubscriptionTypes.TRADES_BY_EXCHANGE, 'binance')\n```\n\n... will result in the following message being passed into the `message_handler` coroutine:\n\n```python\n{'type': 'subscribed', 'message': 'trades/exchange/binance'}\n```\n\nYou should then begin receiving trade data from that exchange being passed into the `message_handler` coroutine.\n\nIf you supply an invalid channel reference:\n\n```python\nawait subscriber.subscribe(SubscriptionTypes.TRADES_BY_MARKET, 'btc-%')\n```\n\n... will result in the following message being passed into the `message_handler` coroutine:\n\n```python\n{'type': 'error', 'message': 'trades/market/btc-% invalid'}\n```\n\n\n#### Duplicate Data\n\nNote that subscriptions may include overlapping data; for instance, if you subscribe to all trades on the BTC-USDT market and also all trades on the Binance exchange, trades that take place on Binance related to the BTC-USDT market belong to both subscriptions.\n\nData coming from the API may contain duplicate entities as documented in the [API reference documentation](https://github.com/fenix-blockchain/fenix-pipeline/blob/master/api/README.md). This behavior applies equally to all subscription types.\n\n\n### Unsubscribing from Channels\n\nUnsubscribing from channels is exactly like subscribing but calling the `unsubscribe()` method of `subscriber`:\n\n```python\nawait subscriber.unsubscribe(SubscriptionTypes.TRADES_BY_EXCHANGE, 'binance')\n```\n\n... will result in the following message being passed into the `message_handler` coroutine:\n\n```python\n{'type': 'unsubscribed', 'message': 'trades/exchange/binance'}\n```\n\nIf you supply a reference to a channel you are not subscribed to:\n\n```python\nawait subscriber.unsubscribe(SubscriptionTypes.TRADES_BY_MARKET, 'btc-eudt')\n```\n\n... will result in the following message being passed into the `message_handler` coroutine:\n\n```python\n{'type': 'error', 'message': 'trades/market/btc-eudt not subscribed'}\n```\n\n\n### Data Model\n\nApart from `subscribe`, `unsubscribe`, and `error` messages described above, the messages passed into the `message_handler` coroutine will depend on the type of object being transferred. Currently only `Trade` obejcts are supported; other types will be added in the future.\n\n\n#### Trade Data\n\nTrade data will be received as an object of type `fenix_pipeline.Trade`:\n\n```python\n>>> repr(trade)\nTrade(id=binance:btc-usdt:189128621, timestamp=1570839641.248, exchange=binance, pair=btc-usdt, euid=189128621, price=8272.17, quantity=0.012112, direction=buy)\n>>> trade.timestamp\n1570839641.248\n```\n\nTrades consist of the following fields:\n\n* `exchange`: the exchange where the trade was effected\n* `market`: the market the trade encompasses\n* `euid`: the unique ID as reported by the exchange for that trade\n * the combination of `exchange`, `market`, and `euid` is globally unique amongst all trades in the API\n* `direction`: `buy` or `sell`\n* `price`: a Python `float` representation of the price per unit of the trade\n* `quantity`: a Python `float` representation of the quantity traded\n* `timestamp`: a timestamp in seconds since the epoch with millisecond resolution\n\nTrades also have a method `_key()` that gives a globally-unique key to this trade:\n\n```python\n>>> trade._key()\n'binance:btc-usdt:189128621'\n```\n\n\n**Note:** all floats will be represented by IEEE-754 double-precision values through the PI (with 53 bits of precision, or resolution to 16 significant digits); to ensure you do not lose precision, run only on 64-bit Python implementations.\n\n**Note:** all timestamps can be converted to a `datetime` using `datetime.datetime.utcfromtimestamp(t).astimezone(pytz.utc)`; the value above resolves to `datetime.datetime(2019, 10, 12, 10, 20, 41, 248000, tzinfo=)`\n\n\n### Closing the Connection\n\nExiting the context manager automatically closes the connection and cleans up all resources.\n\n\n### Error Conditions\n\nThe context manager will exit and clean up any resources it is using in any of the following cases:\n\n* an unhandled exception in user code the context of the context manager\n* the socket is closed for any reason (by the server, the client, or the transport layer)\n\nThe socket will close and clean up resources it is using but the context manager will still remain open in the following case:\n\n* the `message_handler` coroutine raises an unhandled exception\n\nIt is the responsibility of the user to ensure any exceptions in thier `message_handler` coroutine are properly handled. This behavior will be simplified in a future version of the SDK.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/fenix-blockchain/fenix-pipeline", "keywords": "fenix pipeline sdk", "license": "MIT License", "maintainer": "", "maintainer_email": "", "name": "fenix-pipeline-sdk", "package_url": "https://pypi.org/project/fenix-pipeline-sdk/", "platform": "", "project_url": "https://pypi.org/project/fenix-pipeline-sdk/", "project_urls": { "Homepage": "https://github.com/fenix-blockchain/fenix-pipeline" }, "release_url": "https://pypi.org/project/fenix-pipeline-sdk/0.9.3/", "requires_dist": [ "websockets (>=8.0.2)" ], "requires_python": ">=3.7", "summary": "SDK for interacting with the Fenix Pipeline API", "version": "0.9.3", "yanked": false, "yanked_reason": null }, "last_serial": 6085198, "releases": { "0.9.1": [ { "comment_text": "", "digests": { "md5": "83f66a9ee6367bf51cb542b7d1a9df46", "sha256": "36944b69e275b0a13ff012d94e9ced8e5078af65c527e51d324b4bbf3548e172" }, "downloads": -1, "filename": "fenix_pipeline_sdk-0.9.1-py3-none-any.whl", "has_sig": false, "md5_digest": "83f66a9ee6367bf51cb542b7d1a9df46", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 6712, "upload_time": "2019-10-15T01:26:53", "upload_time_iso_8601": "2019-10-15T01:26:53.003215Z", "url": "https://files.pythonhosted.org/packages/6c/51/90c47b9a2adba74f6c6811c20cc2fbbb3571f62fb5613129e5580a9906c1/fenix_pipeline_sdk-0.9.1-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "15bf2e6d2d7d96cd1d937203994eec2a", "sha256": "104270b5078d5ff2037b450139afce0cbe41a960201032e1943a3a30df6b6b2b" }, "downloads": -1, "filename": "fenix-pipeline-sdk-0.9.1.tar.gz", "has_sig": false, "md5_digest": "15bf2e6d2d7d96cd1d937203994eec2a", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 6833, "upload_time": "2019-10-15T01:26:54", "upload_time_iso_8601": "2019-10-15T01:26:54.929504Z", "url": "https://files.pythonhosted.org/packages/ae/38/b59692011f1fdf5d1a8f92869be80fe3ae6a5eff5b0d6f1871b7ea95b1c1/fenix-pipeline-sdk-0.9.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.9.2": [ { "comment_text": "", "digests": { "md5": "aa08a7a4b4e02aea22a7a3fdfa41c897", "sha256": "7073bd0ec4df756232d069460a8972af50506743d28556b974cea62edfe747c1" }, "downloads": -1, "filename": "fenix_pipeline_sdk-0.9.2-py3-none-any.whl", "has_sig": false, "md5_digest": "aa08a7a4b4e02aea22a7a3fdfa41c897", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 6908, "upload_time": "2019-10-22T23:18:54", "upload_time_iso_8601": "2019-10-22T23:18:54.552143Z", "url": "https://files.pythonhosted.org/packages/7b/a3/2d9d5b5a2b9c1c84fcd09e322d9337ee791a35aed43b531df5f6bc7bc44f/fenix_pipeline_sdk-0.9.2-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "d946a6f420cf73c64f135c00bcfb4a4f", "sha256": "df737c7be1956d17b8dca7178c7a1bff1a0ab3a80a9f55758a20e86e9cd1a1f6" }, "downloads": -1, "filename": "fenix-pipeline-sdk-0.9.2.tar.gz", "has_sig": false, "md5_digest": "d946a6f420cf73c64f135c00bcfb4a4f", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 7016, "upload_time": "2019-10-22T23:18:56", "upload_time_iso_8601": "2019-10-22T23:18:56.194710Z", "url": "https://files.pythonhosted.org/packages/32/69/4b44e3e214b2e60f9155ea6b5638aba4f9c8cca9c1ce8960a2a9379d9b20/fenix-pipeline-sdk-0.9.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.9.3": [ { "comment_text": "", "digests": { "md5": "1eff6d102aefe4639b70d7f5c70c9417", "sha256": "b21e57c29287ec58947a68f8c0dd483ceabfd5e1fd6259e961d4adf36acc24e6" }, "downloads": -1, "filename": "fenix_pipeline_sdk-0.9.3-py3-none-any.whl", "has_sig": false, "md5_digest": "1eff6d102aefe4639b70d7f5c70c9417", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 7284, "upload_time": "2019-11-06T06:56:46", "upload_time_iso_8601": "2019-11-06T06:56:46.392788Z", "url": "https://files.pythonhosted.org/packages/3e/28/ca4bac5ba2c31d861dad87849599d6cdc73cd0994cc98f931992ad0ff3ef/fenix_pipeline_sdk-0.9.3-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "b1ed1c78e0861d364c8b4b13e854a33c", "sha256": "0dfd1bc2df1e46d1ea71e649101008fcacaa49cbdf3d4f313bfefcd71750e089" }, "downloads": -1, "filename": "fenix-pipeline-sdk-0.9.3.tar.gz", "has_sig": false, "md5_digest": "b1ed1c78e0861d364c8b4b13e854a33c", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 7429, "upload_time": "2019-11-06T06:56:48", "upload_time_iso_8601": "2019-11-06T06:56:48.462794Z", "url": "https://files.pythonhosted.org/packages/f2/14/5232e195ec1360595b536607b242f41e0e694b1b8b57abbaad39c8d6df02/fenix-pipeline-sdk-0.9.3.tar.gz", "yanked": false, "yanked_reason": null } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "1eff6d102aefe4639b70d7f5c70c9417", "sha256": "b21e57c29287ec58947a68f8c0dd483ceabfd5e1fd6259e961d4adf36acc24e6" }, "downloads": -1, "filename": "fenix_pipeline_sdk-0.9.3-py3-none-any.whl", "has_sig": false, "md5_digest": "1eff6d102aefe4639b70d7f5c70c9417", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.7", "size": 7284, "upload_time": "2019-11-06T06:56:46", "upload_time_iso_8601": "2019-11-06T06:56:46.392788Z", "url": "https://files.pythonhosted.org/packages/3e/28/ca4bac5ba2c31d861dad87849599d6cdc73cd0994cc98f931992ad0ff3ef/fenix_pipeline_sdk-0.9.3-py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "b1ed1c78e0861d364c8b4b13e854a33c", "sha256": "0dfd1bc2df1e46d1ea71e649101008fcacaa49cbdf3d4f313bfefcd71750e089" }, "downloads": -1, "filename": "fenix-pipeline-sdk-0.9.3.tar.gz", "has_sig": false, "md5_digest": "b1ed1c78e0861d364c8b4b13e854a33c", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.7", "size": 7429, "upload_time": "2019-11-06T06:56:48", "upload_time_iso_8601": "2019-11-06T06:56:48.462794Z", "url": "https://files.pythonhosted.org/packages/f2/14/5232e195ec1360595b536607b242f41e0e694b1b8b57abbaad39c8d6df02/fenix-pipeline-sdk-0.9.3.tar.gz", "yanked": false, "yanked_reason": null } ], "vulnerabilities": [] }