From 4a9c9b1ac7550b0b761902fdcf7c1cf2a67d2770 Mon Sep 17 00:00:00 2001 From: Davide Casale Date: Sat, 8 Apr 2023 03:27:17 +0200 Subject: [PATCH 01/11] Add `Unsubscribing from a public channel` sub-paragraph to README.md. --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 0b574ee..e50f7ec 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ python3 -m pip install bitfinex-api-py==3.0.0b1 2. [Running the client](#running-the-client) * [Closing the connection](#closing-the-connection) 3. [Subscribing to public channels](#subscribing-to-public-channels) + * [Unsubscribing from a public channel](#unsubscribing-from-a-public-channel) * [Setting a custom `sub_id`](#setting-a-custom-sub_id) 4. [Listening to events](#listening-to-events) 5. [Advanced Features](#advanced-features) @@ -155,6 +156,16 @@ def on_subscribed(subscription: subscriptions.Subscription): print(f"{subscription['symbol']}: {subscription['subId']}") # tBTCUSD: f2757df2-7e11-4244-9bb7-a53b7343bef8 ``` +### Unsubscribing from a public channel + +It is possible to unsubscribe from a public channel at any time. \ +Unsubscribing from a public channel prevents the client from receiving any more data from it. \ +This can be done using `BfxWebSocketClient::unsubscribe`, and passing the `sub_id` of the public channel you want to unsubscribe from: + +```python +await bfx.wss.unsubscribe(sub_id="f2757df2-7e11-4244-9bb7-a53b7343bef8") +``` + ### Setting a custom `sub_id` The client generates a random `sub_id` for each subscription. \ From d78c90faa8a91c1353f88332e5903f7a0277d400 Mon Sep 17 00:00:00 2001 From: Davide Casale Date: Tue, 11 Apr 2023 05:23:50 +0200 Subject: [PATCH 02/11] Add `Authentication` paragraph and `Filtering` sub-paragraph to README.md documentation. --- README.md | 58 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e50f7ec..21cd9be 100644 --- a/README.md +++ b/README.md @@ -38,17 +38,17 @@ python3 -m pip install bitfinex-api-py==3.0.0b1 ### Index -* [WebSocket Client documentation](#websocket-client-documentation) +* [WebSocket client documentation](#websocket-client-documentation) * [Building the source code](#building-the-source-code) * [How to contribute](#how-to-contribute) --- -# WebSocket Client documentation +# WebSocket client documentation 1. [Instantiating the client](#instantiating-the-client) * [Authentication](#authentication) - * [Configuring the logger](#configuring-the-logger) + - [Filtering](#filtering) 2. [Running the client](#running-the-client) * [Closing the connection](#closing-the-connection) 3. [Subscribing to public channels](#subscribing-to-public-channels) @@ -81,25 +81,57 @@ PUB_WSS_HOST is recommended over WSS_HOST for applications that don't require au ### Authentication -### Configuring the logger +Users can authenticate in their accounts by providing a pair of API-KEY and API-SECRET: +```python +bfx = Client( + [...], + api_key=os.getenv("BFX_API_KEY"), + api_secret=os.getenv("BFX_API_SECRET") +) +``` + +If authentication succeeds, the client will emit the `authenticated` event. \ +All operations that require authentication must be performed after the emission of this event. \ +The `data` argument contains information regarding the authentication, such as the `userId`, the `auth_id`, etc... -`log_filename` (`Optional[str]`, default: `None`): \ -Relative path of the file where to save the logs the client will emit. \ -If not given, the client will emit logs on `stdout` (`stderr` for errors and warnings). +```python +@bfx.wss.on("authenticated") +def on_authenticated(data: Dict[str, Any]): + print(f"Successful login for user <{data['userId']}>.") +``` -`log_level` (`str`, default: `"INFO"`): \ -Available log levels are (in order): `ERROR`, `WARNING`, `INFO` and `DEBUG`. \ -The client will only log messages whose level is lower than or equal to `log_level`. \ -For example, if `log_level=WARNING`, the client will only log errors and warnings. +> **NOTE:** A guide on how to create, edit and revoke API-KEYs and API-SECRETs can be found [here](https://support.bitfinex.com/hc/en-us/articles/115003363429-How-to-create-and-revoke-a-Bitfinex-API-Key). + + +#### Filtering + +`Client` accepts a `filters` argument, which you can use to select which channels the client should subscribe to: ```python bfx = Client( [...], - log_filename="2023-03-26.log", - log_level="WARNING" + api_key=os.getenv("BFX_API_KEY"), + api_secret=os.getenv("BFX_API_SECRET"), + filters=[ "wallet" ] ) ``` +If `filters` is not given, the client will subscribe to all channels. + +Filters can be very useful both for safety reasons and for lightening network traffic (by excluding useless channels). \ +Ideally, you should always use `filters`, selecting only the channels your application will actually use. \ +Below, you can find a complete list of available filters (and the events they will emit): + +Filter | Subscribes the client to... | Available events are... +--- | --- | --- +trading | All channels regarding the user's orders, positions and trades (all trading pairs). | `order_snapshot`, `order_new`, `order_update`, `order_cancel`, `position_snapshot`, `position_new`, `position_update`, `position_close`, `trade_execution`, `trade_execution_update` +trading-tBTCUSD | All channels regarding the user's orders, positions and trades (tBTCUSD). | `order_snapshot`, `order_new`, `order_update`, `order_cancel`, `position_snapshot`, `position_new`, `position_update`, `position_close`, `trade_executed`, `trade_execution_update` +funding | All channels regarding the user's offers, credits and loans (all funding currencies). | `funding_offer_snapshot`, `funding_offer_new`, `funding_offer_update`, `funding_offer_cancel`, `funding_credit_snapshot`, `funding_credit_new`, `funding_credit_update`, `funding_credit_close`, `funding_loan_snapshot`, `funding_loan_new`, `funding_loan_update`, `funding_loan_close` +funding-fBTC | All channels regarding the user's offers, credits and loans (fBTC). | `funding_offer_snapshot`, `funding_offer_new`, `funding_offer_update`, `funding_offer_cancel`, `funding_credit_snapshot`, `funding_credit_new`, `funding_credit_update`, `funding_credit_close`, `funding_loan_snapshot`, `funding_loan_new`, `funding_loan_update`, `funding_loan_close` +wallet | All channels regarding user's exchange, trading and deposit wallets. | `wallet_snapshot`, `wallet_update` +wallet-exchange-BTC | Channel regarding user's BTC exchange wallet. | `wallet_snapshot`, `wallet_update` +balance | Channel regarding user's balances (tradable balance, etc...). | `balance_update` + ## Running the client The client can be run using `BfxWebSocketClient::run`: From 1333e80a8caded0fda677f1a1dd63ee4a2fe5311 Mon Sep 17 00:00:00 2001 From: Davide Casale Date: Wed, 12 Apr 2023 03:12:36 +0200 Subject: [PATCH 03/11] Improve readability for some paragraphs in README.md documentation. --- README.md | 98 ++++++++++++++++++++++++------------------------------- 1 file changed, 43 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 21cd9be..01e2642 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ python3 -m pip install bitfinex-api-py==3.0.0b1 --- -### Index +## Index * [WebSocket client documentation](#websocket-client-documentation) * [Building the source code](#building-the-source-code) @@ -48,17 +48,17 @@ python3 -m pip install bitfinex-api-py==3.0.0b1 1. [Instantiating the client](#instantiating-the-client) * [Authentication](#authentication) - - [Filtering](#filtering) + - [Filtering the channels](#filtering-the-channels) 2. [Running the client](#running-the-client) * [Closing the connection](#closing-the-connection) 3. [Subscribing to public channels](#subscribing-to-public-channels) * [Unsubscribing from a public channel](#unsubscribing-from-a-public-channel) * [Setting a custom `sub_id`](#setting-a-custom-sub_id) 4. [Listening to events](#listening-to-events) -5. [Advanced Features](#advanced-features) - * [Connection multiplexing](#connection-multiplexing) - * [Sending custom notifications](#sending-custom-notifications) - * [Handling reconnections in case of network failure](#handling-reconnections-in-case-of-network-failure) + +### Advanced features +* [Sending custom notifications](#sending-custom-notifications) +* [Setting up connection multiplexing](#setting-up-connection-multiplexing) ## Instantiating the client @@ -71,7 +71,7 @@ The `wss_host` argument is used to indicate the URL to which the WebSocket clien The `bfxapi` package exports 2 constants to quickly set this URL: Constant | URL | When to use ---- | --- | --- +:--- | :--- | :--- WSS_HOST | wss://api.bitfinex.com/ws/2 | Suitable for all situations, supports authentication. PUB_WSS_HOST | wss://api-pub.bitfinex.com/ws/2 | For public uses only, doesn't support authentication. @@ -91,8 +91,8 @@ bfx = Client( ``` If authentication succeeds, the client will emit the `authenticated` event. \ -All operations that require authentication must be performed after the emission of this event. \ -The `data` argument contains information regarding the authentication, such as the `userId`, the `auth_id`, etc... +All operations that require authentication will fail if run before the emission of this event. \ +The `data` argument contains various information about the authentication, such as the `userId`, the `auth_id`, etc... ```python @bfx.wss.on("authenticated") @@ -100,12 +100,24 @@ def on_authenticated(data: Dict[str, Any]): print(f"Successful login for user <{data['userId']}>.") ``` +`data` can also be useful for checking API-KEY's permissions: + +```python +@bfx.wss.on("authenticated") +def on_authenticated(data: Dict[str, Any]): + if not data["caps"]["orders"]["read"]: + raise Exception("This application requires read permissions on orders.") + + if not data["caps"]["positions"]["write"]: + raise Exception("This application requires write permissions on positions.") +``` + > **NOTE:** A guide on how to create, edit and revoke API-KEYs and API-SECRETs can be found [here](https://support.bitfinex.com/hc/en-us/articles/115003363429-How-to-create-and-revoke-a-Bitfinex-API-Key). -#### Filtering +#### Filtering the channels -`Client` accepts a `filters` argument, which you can use to select which channels the client should subscribe to: +It is possible to select which channels the client should subscribe to using the `filters` argument: ```python bfx = Client( @@ -116,21 +128,17 @@ bfx = Client( ) ``` -If `filters` is not given, the client will subscribe to all channels. - -Filters can be very useful both for safety reasons and for lightening network traffic (by excluding useless channels). \ +Filtering can be very useful both for safety reasons and for lightening network traffic (by excluding useless channels). \ Ideally, you should always use `filters`, selecting only the channels your application will actually use. \ -Below, you can find a complete list of available filters (and the events they will emit): +Below, you can find a complete list of available filters (and the channels they will subscribe the client to): Filter | Subscribes the client to... | Available events are... ---- | --- | --- +:--- | :--- | :--- trading | All channels regarding the user's orders, positions and trades (all trading pairs). | `order_snapshot`, `order_new`, `order_update`, `order_cancel`, `position_snapshot`, `position_new`, `position_update`, `position_close`, `trade_execution`, `trade_execution_update` trading-tBTCUSD | All channels regarding the user's orders, positions and trades (tBTCUSD). | `order_snapshot`, `order_new`, `order_update`, `order_cancel`, `position_snapshot`, `position_new`, `position_update`, `position_close`, `trade_executed`, `trade_execution_update` funding | All channels regarding the user's offers, credits and loans (all funding currencies). | `funding_offer_snapshot`, `funding_offer_new`, `funding_offer_update`, `funding_offer_cancel`, `funding_credit_snapshot`, `funding_credit_new`, `funding_credit_update`, `funding_credit_close`, `funding_loan_snapshot`, `funding_loan_new`, `funding_loan_update`, `funding_loan_close` funding-fBTC | All channels regarding the user's offers, credits and loans (fBTC). | `funding_offer_snapshot`, `funding_offer_new`, `funding_offer_update`, `funding_offer_cancel`, `funding_credit_snapshot`, `funding_credit_new`, `funding_credit_update`, `funding_credit_close`, `funding_loan_snapshot`, `funding_loan_new`, `funding_loan_update`, `funding_loan_close` wallet | All channels regarding user's exchange, trading and deposit wallets. | `wallet_snapshot`, `wallet_update` -wallet-exchange-BTC | Channel regarding user's BTC exchange wallet. | `wallet_snapshot`, `wallet_update` -balance | Channel regarding user's balances (tradable balance, etc...). | `balance_update` ## Running the client @@ -231,30 +239,9 @@ You can pass any number of events to register for the same callback function: bfx.wss.on("t_ticker_update", "f_ticker_update", callback=on_ticker_update) ``` -## Advanced features +# Advanced features -### Connection multiplexing - -`BfxWebSocketClient::run` and `BfxWebSocketClient::start` accept a `connections` argument: -```python -bfx.wss.run(connections=3) -``` - -`connections` indicates the number of connections to run concurrently (through connection multiplexing). - -Each of these connections can handle up to 25 subscriptions to public channels. \ -So, using `N` connections will allow the client to handle at most `N * 25` subscriptions. \ -You should always use the minimum number of connections necessary to handle all the subscriptions that will be made. - -For example, if you know that your application will subscribe to 75 public channels, 75 / 25 = 3 connections will be enough to handle all the subscriptions. - -The default number of connections is 5; therefore, if the `connections` argument is not given, the client will be able to handle a maximum of 25 * 5 = 125 subscriptions. - -Keep in mind that using a large number of connections could slow down the client performance. - -The use of more than 20 connections is not recommended. - -### Sending custom notifications +## Sending custom notifications **Sending custom notifications requires user authentication.** @@ -274,25 +261,26 @@ def on_notification(notification: Notification[Any]): print(notification.data) # { "foo": 1 } ``` -### Handling reconnections in case of network failure +## Setting up connection multiplexing + +`BfxWebSocketClient::run` and `BfxWebSocketClient::start` accept a `connections` argument: +```python +bfx.wss.run(connections=3) +``` + +`connections` indicates the number of connections to run concurrently (through connection multiplexing). -In case of network failure, the client will keep waiting until it is able to restore the connection with the server. +Each of these connections can handle up to 25 subscriptions to public channels. \ +So, using `N` connections will allow the client to handle at most `N * 25` subscriptions. \ +You should always use the minimum number of connections necessary to handle all the subscriptions that will be made. -The client will try to reconnect with exponential backoff; the backoff delay starts at three seconds and increases up to one minute. +For example, if you know that your application will subscribe to 75 public channels, 75 / 25 = 3 connections will be enough to handle all the subscriptions. -After a successful reconnection attempt, the client will emit the `reconnection` event. +The default number of connections is 5; therefore, if the `connections` argument is not given, the client will be able to handle a maximum of 25 * 5 = 125 subscriptions. -This event accepts two arguments: \ -`attemps` (`int`) which is the number of reconnection attempts (including the successful one), \ -`timedelta` (`datetime.timedelta`) which contains the amount of time the client has been down. +Keep in mind that using a large number of connections could slow down the client performance. -Users can use this event for a variety of things, such as sending a notification if the client has been down for too long: -```python -@bfx.wss.on("reconnection") -async def on_reconnection(attempts: int, timedelta: datetime.timedelta): - if timedelta.total_seconds() >= 60 * 60: # 60s * 60s = 3600s = 1h - await bfx.wss.notify(f"The client has been down for {timedelta}.") -``` +The use of more than 20 connections is not recommended. --- From 51b4d2c18177b4c69efe941763eae5cb81b61179 Mon Sep 17 00:00:00 2001 From: Davide Casale Date: Thu, 13 Apr 2023 17:29:53 +0200 Subject: [PATCH 04/11] Add and write new `Building from source code` section in README.md. --- README.md | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 01e2642..85d694a 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ python3 -m pip install bitfinex-api-py==3.0.0b1 ## Index * [WebSocket client documentation](#websocket-client-documentation) -* [Building the source code](#building-the-source-code) +* [Building from source code](#building-from-source-code) * [How to contribute](#how-to-contribute) --- @@ -284,10 +284,42 @@ The use of more than 20 connections is not recommended. --- -# Building the source code +# Building from source code + +**Building from source code requires Python 3.8+** + +Make sure to clone the right branch of the repository (`v3-beta`): + +```bash +git clone -b v3-beta --single-branch https://github.com/bitfinexcom/bitfinex-api-py.git +``` + +### Installing the dependencies + +```bash +python3 -m pip install -r requirements.txt +``` + +If you are willing to contribute to the project, you'll need the correct versions of [`pylint`](https://github.com/pylint-dev/pylint) and [`mypy`](https://github.com/python/mypy). + +You can get both by installing the dependencies in `dev-requirements.txt`: + +```bash +python3 -m pip install -r dev-requirements.txt +``` + +### Optional steps + +1. [Testing (with unittest)](#testing-with-unittest) +2. [Linting the project with pylint](#linting-the-project-with-pylint) +3. [Using mypy to ensure correct type-hinting](#using-mypy-to-ensure-correct-type-hinting) ## Testing (with unittest) +```bash +python3 -m unittest -v bfxapi.tests +``` + ## Linting the project with pylint ## Using mypy to ensure correct type-hinting From a1a013fef87487a482a591e1cc560cb51571a937 Mon Sep 17 00:00:00 2001 From: Davide Casale Date: Fri, 14 Apr 2023 04:50:33 +0200 Subject: [PATCH 05/11] Move `Building from source code` in `How to contribute` section in README.md. --- README.md | 131 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 85d694a..56ea3b9 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Provide your API-KEY/API-SECRET, and manage your account and funds at your own r - The WebSocket client logs every reconnection failure, success and attempt (as well as other events). * Connection multiplexing to allow subscribing to a large number of public channels (without affecting performances). - The WebSocket server sets a limit of 25 subscriptions per connection, connection multiplexing allows the WebSocket client to bypass this limit. -- Full type-hinting and type-checking support with [`mypy`](https://github.com/python/mypy). +- Full type hinting and type checking support with [`mypy`](https://github.com/python/mypy). * This allow text editors to show helpful hints about the value of a variable: ![example](https://i.imgur.com/aDjapcN.png "Type-hinting example on a random code snippet") --- @@ -24,11 +24,11 @@ Provide your API-KEY/API-SECRET, and manage your account and funds at your own r ## Installation To install the latest beta release of `bitfinex-api-py`: -```bash +```console python3 -m pip install --pre bitfinex-api-py ``` To install a specific beta version: -```bash +```console python3 -m pip install bitfinex-api-py==3.0.0b1 ``` @@ -39,7 +39,7 @@ python3 -m pip install bitfinex-api-py==3.0.0b1 ## Index * [WebSocket client documentation](#websocket-client-documentation) -* [Building from source code](#building-from-source-code) + - [Advanced features](#advanced-features) * [How to contribute](#how-to-contribute) --- @@ -48,7 +48,6 @@ python3 -m pip install bitfinex-api-py==3.0.0b1 1. [Instantiating the client](#instantiating-the-client) * [Authentication](#authentication) - - [Filtering the channels](#filtering-the-channels) 2. [Running the client](#running-the-client) * [Closing the connection](#closing-the-connection) 3. [Subscribing to public channels](#subscribing-to-public-channels) @@ -114,32 +113,6 @@ def on_authenticated(data: Dict[str, Any]): > **NOTE:** A guide on how to create, edit and revoke API-KEYs and API-SECRETs can be found [here](https://support.bitfinex.com/hc/en-us/articles/115003363429-How-to-create-and-revoke-a-Bitfinex-API-Key). - -#### Filtering the channels - -It is possible to select which channels the client should subscribe to using the `filters` argument: - -```python -bfx = Client( - [...], - api_key=os.getenv("BFX_API_KEY"), - api_secret=os.getenv("BFX_API_SECRET"), - filters=[ "wallet" ] -) -``` - -Filtering can be very useful both for safety reasons and for lightening network traffic (by excluding useless channels). \ -Ideally, you should always use `filters`, selecting only the channels your application will actually use. \ -Below, you can find a complete list of available filters (and the channels they will subscribe the client to): - -Filter | Subscribes the client to... | Available events are... -:--- | :--- | :--- -trading | All channels regarding the user's orders, positions and trades (all trading pairs). | `order_snapshot`, `order_new`, `order_update`, `order_cancel`, `position_snapshot`, `position_new`, `position_update`, `position_close`, `trade_execution`, `trade_execution_update` -trading-tBTCUSD | All channels regarding the user's orders, positions and trades (tBTCUSD). | `order_snapshot`, `order_new`, `order_update`, `order_cancel`, `position_snapshot`, `position_new`, `position_update`, `position_close`, `trade_executed`, `trade_execution_update` -funding | All channels regarding the user's offers, credits and loans (all funding currencies). | `funding_offer_snapshot`, `funding_offer_new`, `funding_offer_update`, `funding_offer_cancel`, `funding_credit_snapshot`, `funding_credit_new`, `funding_credit_update`, `funding_credit_close`, `funding_loan_snapshot`, `funding_loan_new`, `funding_loan_update`, `funding_loan_close` -funding-fBTC | All channels regarding the user's offers, credits and loans (fBTC). | `funding_offer_snapshot`, `funding_offer_new`, `funding_offer_update`, `funding_offer_cancel`, `funding_credit_snapshot`, `funding_credit_new`, `funding_credit_update`, `funding_credit_close`, `funding_loan_snapshot`, `funding_loan_new`, `funding_loan_update`, `funding_loan_close` -wallet | All channels regarding user's exchange, trading and deposit wallets. | `wallet_snapshot`, `wallet_update` - ## Running the client The client can be run using `BfxWebSocketClient::run`: @@ -284,51 +257,97 @@ The use of more than 20 connections is not recommended. --- -# Building from source code +# How to contribute -**Building from source code requires Python 3.8+** +1. [Installation and setup](#installation-and-setup) + * [Cloning the repository](#cloning-the-repository) + * [Installing the dependencies](#installing-the-dependencies) +2. [Before opening a PR](#before-opening-a-pr) + * [Running the unit tests](#running-the-unit-tests) + * [Linting the project with pylint](#linting-the-project-with-pylint) + * [Using mypy to ensure correct type hinting](#using-mypy-to-ensure-correct-type-hinting) +3. [License](#license) -Make sure to clone the right branch of the repository (`v3-beta`): +## Installation and setup -```bash -git clone -b v3-beta --single-branch https://github.com/bitfinexcom/bitfinex-api-py.git -``` +A brief guide on how to install and set up the project in your Python 3.8+ environment. -### Installing the dependencies +### Cloning the repository -```bash -python3 -m pip install -r requirements.txt -``` +The following command will only clone the `v3-beta` branch (excluding all others): -If you are willing to contribute to the project, you'll need the correct versions of [`pylint`](https://github.com/pylint-dev/pylint) and [`mypy`](https://github.com/python/mypy). +```console +git clone --branch v3-beta --single-branch https://github.com/bitfinexcom/bitfinex-api-py.git +``` -You can get both by installing the dependencies in `dev-requirements.txt`: +### Installing the dependencies -```bash +```console python3 -m pip install -r dev-requirements.txt ``` -### Optional steps +Make sure to install `dev-requirements.txt` instead of `requirements.txt`. \ +`dev-requirements.txt` will install all dependencies in `requirements.txt` plus any development dependencies. \ +This will also install the versions in use of [`pylint`](https://github.com/pylint-dev/pylint) and [`mypy`](https://github.com/python/mypy), which you should both use before opening your PRs. + +All done, your Python 3.8+ environment should now be able to run `bitfinex-api-py`'s source code. -1. [Testing (with unittest)](#testing-with-unittest) -2. [Linting the project with pylint](#linting-the-project-with-pylint) -3. [Using mypy to ensure correct type-hinting](#using-mypy-to-ensure-correct-type-hinting) +## Before opening a PR -## Testing (with unittest) +Before opening a new pull request you must... +* run the unit tests. +* lint the project with pylint. +* use mypy to ensure correct type hinting. -```bash +### Running the unit tests + +`bitfinex-api-py` comes with a set of unit tests (written using the [`unittest`](https://docs.python.org/3.8/library/unittest.html) unit testing framework). \ +Contributors must ensure that each unit test passes before opening a pull request. \ +You can run all project's unit tests by calling `unittest` on `bfxapi.tests`: +```console python3 -m unittest -v bfxapi.tests ``` -## Linting the project with pylint +A single unit test can be run as follows: +```console +python3 -m unittest -v bfxapi.tests.test_notification +``` -## Using mypy to ensure correct type-hinting +### Linting the project with pylint ---- +`bitfinex-api-py`'s source code follows [`pylint`](https://github.com/pylint-dev/pylint) style guidelines (with some exceptions and modifications). \ +For a full look at what rules are in use, take a look at the configuration file [`.pylintrc`](https://github.com/bitfinexcom/bitfinex-api-py/blob/v3-beta/.pylintrc). \ +Make sure that `pylint` returns a score of 10.00/10.00 before opening a PR. -# How to contribute +You can run `pylint` against all project's files (`*.py`) by calling it on `bfxapi` (root package): +```console +python3 -m pylint bfxapi +``` + +### Using mypy to ensure correct type hinting + +`bitfinex-api-py` uses [`mypy`](https://github.com/python/mypy) to ensure correct type hinting for end users. \ +`mypy` must not throw any error code when run on your code (excluding notes). \ +You can perform type checks on all project's files by running this command: + +```console +python3 -m mypy bfxapi +``` ## License -This project is released under the `Apache License 2.0`. -The complete license can be found here: https://www.apache.org/licenses/LICENSE-2.0. +``` +Copyright 2023 Bitfinex + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` From 82599e1ffba5c35e73bfb02935cb4bfab53ffc12 Mon Sep 17 00:00:00 2001 From: Davide Casale Date: Fri, 14 Apr 2023 22:05:55 +0200 Subject: [PATCH 06/11] Finish writing `How to contribute` section in README.md. --- README.md | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 56ea3b9..b6b1ca9 100644 --- a/README.md +++ b/README.md @@ -259,13 +259,20 @@ The use of more than 20 connections is not recommended. # How to contribute +All contributions are welcome! :D + + +A guide on how to install and set up `bitfinex-api-py`'s source code can be found [here](#installation-and-setup). \ +Before opening any pull requests, please have a look at [Before Opening a PR](#before-opening-a-pr). \ +Contributors must uphold the [Contributor Covenant code of conduct](https://github.com/bitfinexcom/bitfinex-api-py/blob/v3-beta/CODE_OF_CONDUCT.md). + +### Index + 1. [Installation and setup](#installation-and-setup) * [Cloning the repository](#cloning-the-repository) * [Installing the dependencies](#installing-the-dependencies) 2. [Before opening a PR](#before-opening-a-pr) * [Running the unit tests](#running-the-unit-tests) - * [Linting the project with pylint](#linting-the-project-with-pylint) - * [Using mypy to ensure correct type hinting](#using-mypy-to-ensure-correct-type-hinting) 3. [License](#license) ## Installation and setup @@ -294,10 +301,16 @@ All done, your Python 3.8+ environment should now be able to run `bitfinex-api-p ## Before opening a PR -Before opening a new pull request you must... -* run the unit tests. -* lint the project with pylint. -* use mypy to ensure correct type hinting. +**We won't accept your PR or we will request changes if the following requirements aren't met.** + +Wheter you're submitting a bug fix, a new feature or a documentation change, you should first discuss it in an issue. + +All PRs must follow this [PULL_REQUEST_TEMPLATE](https://github.com/bitfinexcom/bitfinex-api-py/blob/v3-beta/.github/PULL_REQUEST_TEMPLATE.md) and include an exhaustive description. + +Before opening a pull request, you should also make sure that: +- [ ] all unit tests pass (see [Running the unit tests](#running-the-unit-tests)). +- [ ] [`pylint`](https://github.com/pylint-dev/pylint) returns a score of 10.00/10.00 when run against your code. +- [ ] [`mypy`](https://github.com/python/mypy) doesn't throw any error code when run on the project (excluding notes). ### Running the unit tests @@ -313,27 +326,6 @@ A single unit test can be run as follows: python3 -m unittest -v bfxapi.tests.test_notification ``` -### Linting the project with pylint - -`bitfinex-api-py`'s source code follows [`pylint`](https://github.com/pylint-dev/pylint) style guidelines (with some exceptions and modifications). \ -For a full look at what rules are in use, take a look at the configuration file [`.pylintrc`](https://github.com/bitfinexcom/bitfinex-api-py/blob/v3-beta/.pylintrc). \ -Make sure that `pylint` returns a score of 10.00/10.00 before opening a PR. - -You can run `pylint` against all project's files (`*.py`) by calling it on `bfxapi` (root package): -```console -python3 -m pylint bfxapi -``` - -### Using mypy to ensure correct type hinting - -`bitfinex-api-py` uses [`mypy`](https://github.com/python/mypy) to ensure correct type hinting for end users. \ -`mypy` must not throw any error code when run on your code (excluding notes). \ -You can perform type checks on all project's files by running this command: - -```console -python3 -m mypy bfxapi -``` - ## License ``` From 75d4787bbe75966ab8e00f6a9fac70e09a877159 Mon Sep 17 00:00:00 2001 From: Davide Casale Date: Sun, 16 Apr 2023 08:08:57 +0200 Subject: [PATCH 07/11] Write `Quickstart` section in README.md. --- README.md | 90 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index b6b1ca9..af846ec 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Beta versions should not be used in applications which require user authenticati Provide your API-KEY/API-SECRET, and manage your account and funds at your own risk. ### Features + - User-friendly implementations for 75+ public and authenticated REST endpoints. * A complete list of available REST endpoints can be found [here](https://docs.bitfinex.com/reference). - New WebSocket client to ensure fast, secure and persistent connections. @@ -19,27 +20,72 @@ Provide your API-KEY/API-SECRET, and manage your account and funds at your own r - Full type hinting and type checking support with [`mypy`](https://github.com/python/mypy). * This allow text editors to show helpful hints about the value of a variable: ![example](https://i.imgur.com/aDjapcN.png "Type-hinting example on a random code snippet") ---- - ## Installation -To install the latest beta release of `bitfinex-api-py`: ```console python3 -m pip install --pre bitfinex-api-py ``` -To install a specific beta version: + +### Selecting and installing a specific beta version + +It's also possible to select and install a specific beta version: ```console python3 -m pip install bitfinex-api-py==3.0.0b1 ``` -## Basic usage - --- -## Index +# Quickstart + +```python +from bfxapi import Client, REST_HOST + +from bfxapi.rest.types import Notification, Order + +bfx = Client( + rest_host=REST_HOST, + api_key="", + api_secret="" +) + +notification: Notification[Order] = bfx.rest.auth.submit_order( + type="EXCHANGE LIMIT", symbol="tBTCUSD", amount=0.165212, price=30264.0) + +order: Order = notification.data + +if notification.status == "SUCCESS": + print(f"Successful new order for {order.symbol} at {order.price}$.") + +if notification.status == "ERROR": + raise Exception(f"Something went wrong: {notification.text}") +``` + +## Authenticating in your account + +To authenticate in your account, you must provide a valid API-KEY and API-SECRET: +```python +bfx = Client( + [...], + api_key=os.getenv("BFX_API_KEY"), + api_secret=os.getenv("BFX_API_SECRET") +) +``` + +### Warning + +Remember to not share your API-KEYs and API-SECRETs with anyone. \ +Everyone who owns one of your API-KEYs and API-SECRETs will have full access to your account. \ +We suggest saving your credentials in a local `.env` file and accessing them as environment variables. + +_Revoke your API-KEYs and API-SECRETs immediately if you think they might have been stolen._ + +> **NOTE:** A guide on how to create, edit and revoke API-KEYs and API-SECRETs can be found [here](https://support.bitfinex.com/hc/en-us/articles/115003363429-How-to-create-and-revoke-a-Bitfinex-API-Key). + +## Next * [WebSocket client documentation](#websocket-client-documentation) - [Advanced features](#advanced-features) + - [Examples](#examples) * [How to contribute](#how-to-contribute) --- @@ -56,9 +102,11 @@ python3 -m pip install bitfinex-api-py==3.0.0b1 4. [Listening to events](#listening-to-events) ### Advanced features -* [Sending custom notifications](#sending-custom-notifications) +* [Using custom notifications](#using-custom-notifications) * [Setting up connection multiplexing](#setting-up-connection-multiplexing) +#### Examples + ## Instantiating the client ```python @@ -80,18 +128,11 @@ PUB_WSS_HOST is recommended over WSS_HOST for applications that don't require au ### Authentication -Users can authenticate in their accounts by providing a pair of API-KEY and API-SECRET: -```python -bfx = Client( - [...], - api_key=os.getenv("BFX_API_KEY"), - api_secret=os.getenv("BFX_API_SECRET") -) -``` +To learn how to authenticate in your account, have a look at [Authenticating in your account](#authenticating-in-your-account). -If authentication succeeds, the client will emit the `authenticated` event. \ +If authentication is successful, the client will emit the `authenticated` event. \ All operations that require authentication will fail if run before the emission of this event. \ -The `data` argument contains various information about the authentication, such as the `userId`, the `auth_id`, etc... +The `data` argument contains information about the authentication, such as the `userId`, the `auth_id`, etc... ```python @bfx.wss.on("authenticated") @@ -99,7 +140,7 @@ def on_authenticated(data: Dict[str, Any]): print(f"Successful login for user <{data['userId']}>.") ``` -`data` can also be useful for checking API-KEY's permissions: +`data` can also be useful for checking if an API-KEY has certain permissions: ```python @bfx.wss.on("authenticated") @@ -111,8 +152,6 @@ def on_authenticated(data: Dict[str, Any]): raise Exception("This application requires write permissions on positions.") ``` -> **NOTE:** A guide on how to create, edit and revoke API-KEYs and API-SECRETs can be found [here](https://support.bitfinex.com/hc/en-us/articles/115003363429-How-to-create-and-revoke-a-Bitfinex-API-Key). - ## Running the client The client can be run using `BfxWebSocketClient::run`: @@ -214,9 +253,9 @@ bfx.wss.on("t_ticker_update", "f_ticker_update", callback=on_ticker_update) # Advanced features -## Sending custom notifications +## Using custom notifications -**Sending custom notifications requires user authentication.** +**Using custom notifications requires user authentication.** Users can send custom notifications using `BfxWebSocketClient::notify`: ```python @@ -255,13 +294,16 @@ Keep in mind that using a large number of connections could slow down the client The use of more than 20 connections is not recommended. +# Examples + + + --- # How to contribute All contributions are welcome! :D - A guide on how to install and set up `bitfinex-api-py`'s source code can be found [here](#installation-and-setup). \ Before opening any pull requests, please have a look at [Before Opening a PR](#before-opening-a-pr). \ Contributors must uphold the [Contributor Covenant code of conduct](https://github.com/bitfinexcom/bitfinex-api-py/blob/v3-beta/CODE_OF_CONDUCT.md). From 0f95a4ce27eefd41782575b86c5f156a49b76897 Mon Sep 17 00:00:00 2001 From: Davide Casale Date: Sun, 16 Apr 2023 08:58:36 +0200 Subject: [PATCH 08/11] Write `Examples` sub-section and `Creating a new order` paragraph in README.md. --- README.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index af846ec..9e48ede 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,8 @@ _Revoke your API-KEYs and API-SECRETs immediately if you think they might have b * [Using custom notifications](#using-custom-notifications) * [Setting up connection multiplexing](#setting-up-connection-multiplexing) -#### Examples +### Examples +* [Creating a new order](#creating-a-new-order) ## Instantiating the client @@ -296,7 +297,37 @@ The use of more than 20 connections is not recommended. # Examples +## Creating a new order +```python +import os + +from bfxapi import Client, WSS_HOST + +from bfxapi.websocket.types import Notification, Order + +bfx = Client( + wss_host=WSS_HOST, + api_key=os.getenv("BFX_API_KEY"), + api_secret=os.getenv("BFX_API_SECRET") +) + +@bfx.wss.on("authenticated") +async def on_authenticated(_): + await bfx.wss.inputs.submit_order( + type="EXCHANGE LIMIT", symbol="tBTCUSD", amount=0.165212, price=30264.0) + +@bfx.wss.on("order_new") +def on_order_new(order: Order): + print(f"Successful new order for {order.symbol} at {order.price}$.") + +@bfx.wss.on("on-req-notification") +def on_notification(notification: Notification[Order]): + if notification.status == "ERROR": + raise Exception(f"Something went wrong: {notification.text}") + +bfx.wss.run() +``` --- From e6b5b329d537829fa184ffd681216d731abadd50 Mon Sep 17 00:00:00 2001 From: Davide Casale Date: Sun, 16 Apr 2023 18:11:37 +0200 Subject: [PATCH 09/11] Rewrite `Features` sub-paragraph in README.md. --- README.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 9e48ede..97d4553 100644 --- a/README.md +++ b/README.md @@ -9,16 +9,10 @@ Provide your API-KEY/API-SECRET, and manage your account and funds at your own r ### Features -- User-friendly implementations for 75+ public and authenticated REST endpoints. - * A complete list of available REST endpoints can be found [here](https://docs.bitfinex.com/reference). -- New WebSocket client to ensure fast, secure and persistent connections. - * Support for all public channels + authenticated events and inputs (a list can be found [here](https://docs.bitfinex.com/docs/ws-public)). - * Automatic reconnection system in case of network failure (both client and server side). - - The WebSocket client logs every reconnection failure, success and attempt (as well as other events). - * Connection multiplexing to allow subscribing to a large number of public channels (without affecting performances). - - The WebSocket server sets a limit of 25 subscriptions per connection, connection multiplexing allows the WebSocket client to bypass this limit. -- Full type hinting and type checking support with [`mypy`](https://github.com/python/mypy). - * This allow text editors to show helpful hints about the value of a variable: ![example](https://i.imgur.com/aDjapcN.png "Type-hinting example on a random code snippet") +* Support for 75+ REST endpoints (a list of available endpoints can be found [here](https://docs.bitfinex.com/reference)) +* New WebSocket client to ensure fast, secure and persistent connections +* Full support for Bitfinex notifications (including custom notifications) +* Native support for type hinting and type checking with [`mypy`](https://github.com/python/mypy) ## Installation From eeb6e975f4169bfe43c328557de170171e47c58d Mon Sep 17 00:00:00 2001 From: Davide Casale Date: Thu, 20 Apr 2023 04:08:36 +0200 Subject: [PATCH 10/11] Fix bug in code blocks inside README.md. --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 97d4553..4c181ce 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ python3 -m pip install bitfinex-api-py==3.0.0b1 ```python from bfxapi import Client, REST_HOST -from bfxapi.rest.types import Notification, Order +from bfxapi.types import Notification, Order bfx = Client( rest_host=REST_HOST, @@ -166,7 +166,7 @@ To learn more about events and public channels, see [Listening to events](#liste ```python @bfx.wss.on("open") async def on_open(): - await bfx.wss.subscribe(Channel.TICKER, symbol="tBTCUSD") + await bfx.wss.subscribe("ticker", symbol="tBTCUSD") ``` ### Closing the connection @@ -185,7 +185,8 @@ After closing the connection, the client will emit the `disconnection` event: ```python @bfx.wss.on("disconnection") def on_disconnection(code: int, reason: str): - print(f"Closing connection with code: <{code}>. Reason: {reason}.") + if code == 1000 or code == 1001: + print("Closing the connection without errors!") ``` ## Subscribing to public channels @@ -298,7 +299,7 @@ import os from bfxapi import Client, WSS_HOST -from bfxapi.websocket.types import Notification, Order +from bfxapi.types import Notification, Order bfx = Client( wss_host=WSS_HOST, From 353b433247719a05a4c192c376a0a30c70bc1e6e Mon Sep 17 00:00:00 2001 From: Davide Casale Date: Wed, 26 Apr 2023 17:06:19 +0200 Subject: [PATCH 11/11] Update package version to 3.0.0b2. --- bfxapi/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bfxapi/version.py b/bfxapi/version.py index 3996ce8..c9e4186 100644 --- a/bfxapi/version.py +++ b/bfxapi/version.py @@ -1 +1 @@ -__version__ = "3.0.0b1" +__version__ = "3.0.0b2"