Metadata-Version: 2.1
Name: python-feclient
Version: 0.0.5
Summary: Client for Fusion Explorer API
Home-page: https://github.com/FusionSolutions/python-feclient
Author: Andor `iFA88` Rajci - Fusions Solutions KFT
Author-email: ifa@fusionsolutions.io
License: GPL-3
Description: # Fusion Explorer API python client
        
        ## Introduction
        
        This utility makes easier to use Fusion Explorer API which uses JSON-RPC protocol.
        
        ## Installation
        
        Requires python 3.8 or later version.
        
        To install the latest release on [PyPI](https://pypi.org/project/python-feclient/),
        simply run:
        
        ```shell
        pip3 install python-feclient
        ```
        
        Or to install the latest version, run:
        
        ```shell
        git clone https://github.com/FusionSolutions/python-feclient.git
        cd python-feclient
        python3 setup.py install
        ```
        
        ## Command Line Interface
        
        **IMPORTANT**
        
        The CLI utility downloads method and bitmask definitions from the server and stores it temporary for the terminal session. You can disable it when you set the following environment key: `FECLI_DISABLE_CACHE=1`
        
        For get usage information please use:
        ```shell
        $fexplorer-cli
        ```
        
        ## Python library
        
        ### Usage
        
        Just import the `Client` class from the `feClient` library and it is ready to use.
        
        Example for standard usage:
        ```python
        from feClient import Client
        
        fec = Client()
        request = fec.request("ping")
        print(request.get())
        ```
        
        **IMPORTANT**
        
        Object sharing is **MAY NOT** safe for multi-threading/processing, do not share any initialized objects with another thread or process. If you want to use another thread or process you need [clone](#clone) it and give that as argument.
        
        ### Initialize Client
        ```python
        feClient.Client(projectPublicKey:Union[str, bytes]=None, projectSecretKey:Union[str, bytes]=None, hexNumbers:bool=False, connectTimeout:int=15, timeout:int=320, compression:bool=True, timeWindow:int=60, retryCount:int=10, retryDelay:int=5, stopSignal:Any=None, log:Any=None)
        ```
        | Parameter | Type | Default | Description |
        | - | - | - | - |
        | `projectPublicKey` | Union[str, bytes] | `None` | Project public key - if available - 16 byte hex like: "9cd433f765a8818c1002241190deae51". |
        | `projectSecretKey` | Union[str, bytes] | `None` | Project secret key - if available - 16 byte hex like: "ace3ebb9a17b5b40b8b2bd87b92296b1". Required when `projectPublicKey` is used. |
        | `hexNumbers` | bool | `False` | All integer in the result will be converted to hex (javascript compatible for big numbers). |
        | `connectTimeout` | int | `15` | Connection timeout in second. |
        | `timeout` | int | `320` | Send/Receive timeout in second. |
        | `compression` | bool | `True` | Enable or disable compression for transmitting results. |
        | `timeWindow` | int | `60` | Security time window for avoid old queries repeat attack. The amount is in seconds. |
        | `retryCount` | int | `10` | How many retries should be have before Error raises during operation. |
        | `retryDelay` | int | `5` | Delay in seconds between two retry. |
        | `stopSignal` | Any | `None` | Object ([example](#stopsignal)) with `get()` function which returns _true_ if we need to stop, and _False_ when not. |
        | `log` | Any | `None` | Logger object. If `None` given default will use built-in `logging.logger`. |
        
        ### `Client` API reference
        
        #### Create request
        ```python
        feClient.Client.request(method:str, args:List[Any]=[], kwargs:Dict[str, Any]={}, id:Union[str, int]=None)
        ```
        | Parameter | Type | Default | Description |
        | - | - | - | - |
        | `method` | str | | Method name |
        | `args` | List[Any] | `[]` | Arguments of parameters |
        | `kwargs` | Dict[str, Any] | `{}` | Keyword arguments of parameters |
        | `id` | Union[str, int] | `None` | ID of the request. If `None` given an automatic incremental number will be used. Do not reuse older values. |
        
        Returns a [`feClient.Request`](#request-object) object.
        
        #### Create iterator
        ```python
        feClient.Client.createIterator(method:str, *args:List[Any], sortBy:str=None, fromKey:str=None, desc:bool=None, bitmask:int=None, chunks:int=12)
        ```
        | Parameter | Type | Default | Description |
        | - | - | - | - |
        | `method` | str | | Method name which need to begin with _iter_. |
        | `*args` | List[Any] | | This parameter definition is given by the method. |
        | `sortBy` | str | `None` | Sorting definition. |
        | `fromKey` | str | `None` | Last referenced item ID. |
        | `desc` | bool | `None` | Ordering option. If _True_ will be descending, when _False_ will be ascending. |
        | `bitmask` | int | `None` | Bitmask value. |
        | `chunks` | int | 12 | How many items should the iterator cache. |
        
        Returns a [`feClient.FEIterator`](#feiterator-object) object.
        
        Example usage:
        ```python
        from feClient import Client
        
        fec = Client()
        it = fec.createIterator("iterTransactionInputs", "btc", "0x8c659902068f0af33849a6d49c4c92150bbb28a9d60c766e47379bbb04726ea0", chunks=5)
        for key, data in it:
        	print((key, data))
        ```
        Example for continue iteration from the last element:
        ```python
        from feClient import Client
        from itertools import islice
        
        fec = Client()
        
        it = fec.createIterator("iterAddresses", "btc", sortBy="balance", desc=True, chunks=2)
        for key, data in islice(it, 2):
        	print((key, data))
        
        it = fec.createIterator("iterAddresses", "btc", sortBy="balance", fromKey=key, desc=True, chunks=2)
        for key, data in it:
        	print((key, data))
        ```
        
        #### `with` usage
        The `Client` class has enter/exit functions, so you can use with `with` statement. You need to know, that on every enter, the client [clones](#clone) himself.
        
        Example:
        ```python
        from feClient import Client
        
        fec = Client()
        
        with fec as c:
        	request = fec.request("ping")
        	print(request.get())
        ```
        
        #### Connect
        ```python
        feClient.Client.connect()
        ```
        Connect to server. It is automatic during request.
        
        #### Close connection
        ```python
        feClient.Client.close()
        ```
        Closing connection and clear cache. It is automatic during deallocation.
        
        #### Clear caches
        ```python
        feClient.Client.clear()
        ```
        Clearing request and response cache. It is automatic during deallocation.
        
        #### Clone
        ```python
        feClient.Client.clone(**kwargs)
        ```
        This will return a brand new created [`Client`](#initialize-client) object which is completely reset/cleared. If you create a thread or process you need give the cloned object. You can give keyword arguments to replace some [initalization parameter](#initialize-client).
        
        Example:
        ```python
        import threading
        from feClient import Client
        
        fec = Client()
        
        def threadFn(id, c):
        	for i in range(2):
        		request = c.request("ping")
        		print(( id, request.get() ))
        
        threads = []
        for i in range(4):
        	threads.append( threading.Thread(target=threadFn, args=(i, fec.clone())) )
        
        for th in threads:
        	th.start()
        
        request = fec.request("ping")
        print(( "Main", request.get() ))
        
        for th in threads:
        	th.join()
        ```
        
        ### Objects
        
        #### Request object
        
        You can create this object with [`feClient.Client.request`](#create-request) function.
        
        Functions:
        - `Request.get()`: Returns the request response. On any server error the `Client` will reconnect and send all un-responded requests again.
        - `Request.getDelay()`: Returns the response delay in seconds as `float`.
        - `Request.getID()`: Returns the request ID.
        - `Request.isDone()`: Returns _True_ as a `bool` when response arrived, _False_ when not.
        - `Request.getUID()`: Returns the unique response ID as `str`. On an issue report you can give this as reference.
        - `Request.isSuccess()`: Returns _True_ when no error happened else return _False_ as a `bool`.
        
        #### FEIterator object
        
        You can create this object with [`feClient.Client.createIterator`](#create-iterator) function.
        
        This is a simple iterator extended with the following functions:
        - `it.__next__` and `it.next()`: Returns a tuple: ```( key, data )```. Technically pops the cache first item and returns it back. The key is the unique ID of the item, may you need reference this when you want continue the iteration later.
        - `it.checkNext()`: This function returns the same as the `__next__`, but will not delete from the cache. Calling this function the iteration would not be moving forward. If there is nothing for next `StopIteration` will be raised.
        
        ### StopSignal
        ```python
        feClient.StopSignal()
        ```
        This is an example class which ready to use. If the process get _SIGINT_ signal, then during any request/get call will raise [StopSignalError](#Stop-signal-error)
        
        ### Exceptions
        
        #### Stop signal error
        ```python
        feClient.StopSignalError(Exception)
        ```
        Will be raised when the process get _SIGINT_ signal.
        
        #### Base error
        ```python
        feClient.Error(Exception)
        ```
        Example to catch errors:
        ```python
        try:
          # some request..
        except feClient.Error as err:
          print(err.message)
          # do something else..
        ```
        
        #### Initialization error
        ```python
        feClient.InitializationError(Error)
        ```
        Will be raises when you give bad parameters during initializing the client.
        
        #### Socket error
        ```python
        feClient.SocketError(Error)
        ```
        Will be raised when the client has lost the connection with the server or can not connect to it.
        
        #### Request error
        ```python
        feClient.RequestError(Error)
        ```
        Will be raised when you give bad type for [`feClient.Client.request`](#create-request) `id` parameter or the `id` is already in use.
        
        #### Response error
        ```python
        feClient.ResponseError(Error)
        ```
        Will be raised:
        - when the server did not answered for the request or you did not have sent the request for that ID.
        - when you give bad parameters to `createIterator` and server sends error back.
        
        ## Contribution
        
        Bug reports, constructive criticism and suggestions are welcome. If you have some create an issue on [github](https://github.com/FusionSolutions/python-feclient/issues).
        
        ## API Limitations
        
        Server limitations are very strict. As GUEST you will share resources with other GUEST sessions, currently one GUEST request can run at the same time.
        
        Every project has his own resources and one request can run at the same time.
        
        At the moment subscriptions are not free and can be requested in private.
        
        ## Copyright
        
        All of the code in this distribution is Copyright (c) 2021 Fusion Solutions Kft.
        
        The utility is made available under the GNU General Public license. The included LICENSE file describes this in detail.
        
        ## Warranty
        
        THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE USE OF THIS SOFTWARE IS WITH YOU.
        
        IN NO EVENT WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY, BE LIABLE TO YOU FOR ANY DAMAGES, EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
        
        Again, see the included LICENSE file for specific legal details.
Keywords: explorer client fusion solutions fusionsolutions fusionexplorer
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Topic :: Utilities
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
Requires-Python: >=3.8.*
Description-Content-Type: text/markdown
