{ "info": { "author": "HealthVerity", "author_email": "", "bugtrack_url": null, "classifiers": [], "description": "# Snakeskin\n\n```\nPython + Fabric == snakeskin\n```\n\nThis library is a re-implementation of the official Hyperledger Fabric (HLF) Python SDK, providing simpler Python interfaces with HLF while still allowing for fine-grained control over communication with your network.\n\nSpecifically, we are building this library with the following goals in mind:\n\n- Clear configuration - offer configuration that is clearly documented, easy to use, and free of redundancies\n- Simplicity - offer simple, high-level interfaces for use with less complex networks\n- Control - offer fine-grained communication interfaces for interaction with the network, that are as clearly documented as their higher-level counterparts\n- Stateless - where feasible, avoid the complexities of managing state transitions, allowing for a more reliable development experience\n- Fail gracefully - raise semantic, hierarchical, and meaningful error messages\n- Pythonic - use Python naming conventions to allow for cleaner integration into your Python app\n\n\nWith snakeskin you can manage transaction life-cycles, request retries, and complex network gateways with a high degree of specificity and control, while still leveraging higher-level operations when the control is not needed or desired.\n\n## Installation\n\n```console\n$ [sudo] pip install snakeskin-fabric\n```\n\n## Config\n\nSnakeskin can be configured using a static file, or dynamically in Python, and is relatively flexible, as the requirements for a configuration depend largely on the use case.\n\nSee the example configuration in `examples/config-files/example-blockchain-config.yaml` for example configuration structure. Note that the following file formats are supported:\n\n- YAML - (`.yaml`, `.yml`)\n- JSON - (`.json`)\n\nTo load a configuration into the framework, simply do:\n\n```python\nfrom snakeskin.config import BlockchainConfig\n\n# Or load from a static file\nblockchain = BlockchainConfig.from_file('/path/to/config/file.yaml')\n\n# Or load from a dictionary\nblockchain = BlockchainConfig.from_dict({\n # ...\n})\n```\n\n## Interacting with the Blockchain\n\nTo run transactions against the blockchain, it's easiest to use a Gateway,\nwhich is pre-configured with the requisite peers, orderers, channel, and chaincode\nspecification. See the `gateways` section of the example config for\nconfiguration options. Once configured, you can retrieve your gateway from the\nblockchain config with:\n\n```python\ngateway = blockchain.get_gateway('my-gateway')\n\n# or build your own programatically:\nfrom snakeskin.models.gateway import Gateway\ngateway = Gateway(\n # ...\n)\n```\n\n\n### Transactions\n\nOnce configured, performing transactions against the chaincode is relatively straight-forward. Gateways expose the same high-level abstractions - `invoke` and `query` - as the HLF `peer` CLI command.\n\n```python\n\n# query the chaincode to retrieve data\ntransaction = await gateway.query(\n fcn='doSomething',\n args=['arg1', 'arg2']\n)\n\n# invoke the chaincode to persist data, waiting for the chaincode to\n# successfully commit\ntransaction = await gateway.invoke(\n fcn='doSomething',\n args=['arg1', 'arg2'],\n timeout=50\n)\n\ntransaction.response_payload #=> b''\n```\n\nHowever, if you want more control over the transaction flow, you can use the `transact` method and chain operations (see `snakeskin.models.GatewayTXBuilder` for available options):\n\n```python\n# A step-by-step transaction flow\ntransaction = await (\n gateway.transact(\n fcn='doSomething',\n args=['arg1', 'arg2']\n )\n # Sends the transaction to the peers for endorsement\n .propose()\n # Optionally sends the transaction to the orderers for committing\n .submit()\n # Optionally wait (up to 50 seconds) for the transaction to be successfully\n # committed to the peer\n .wait_for_commit(timeout=50)\n)\n\ntransaction.response_payload #=> b''\n```\n\n\n### Network Administration\n\nMost administrative operations are also available through the Gateway:\n\n```python\n# Creates the channel, via the orderer\nawait gateway.create_channel(tx_file_path='/path/to/channel.tx')\n# Joins the gateway's endorsing peers to the channel\nawait gateway.join_channel()\n# Query instantiated chaincode for the channel\nresp = await gateway.query_instantiated_chaincodes()\nresp.chaincodes[0].name # => 'my-chaincode'\n# Installs the chaincode\nawait gateway.install_chaincode()\n# Instantiates the chaincode\nawait gateway.instantiate_chaincode(timeout=60)\n# Upgrades the chaincode\nawait gateway.instantiate_chaincode(timeout=60, upgrade=True)\n```\n\nNote that not all assets on the Gateway are required for each administrative operation. `create_channel`, for instance, doesn't require any endorsing peers defined on the Gateway.\n\n\n### Standalone Operations\n\nA Gateway definition is not required to perform any operation against the blockchain, it is simply a helpful tool in configuring groupings of assets. To perform operations without a Gateway, import them from the `snakeskin.operations` module. For example:\n\n```python\nfrom snakeskin.operations import create_channel\n\nawait create_channel(\n requestor=config.get_user('my-user'),\n orderers=[config.get_orderer('my-orderer')],\n channel=config.get_channel('my-channel'),\n tx_file_path='/path/to/channel.tx'\n)\n```\n\nSimilarly, fine-grained transaction management is available from `snakeskin.transact`:\n\n```python\nfrom snakeskin.transact import (\n generate_cc_tx, propose_tx, commit_tx, raise_tx_proposal_error\n)\n\nrequestor = config.get_user('my-user')\n\n# Generate a new chaincode transaction against mycc on my-channel\ngenerated_tx = await generate_cc_tx(\n requestor=requestor,\n cc_name=config.get_chaincode('mycc').name,\n channel=config.get_channel('my-channel'),\n fcn='doSomething',\n args=['arg1', 'arg2']\n)\n\n# Send the proposal to my-peer\nendorsed_tx = await propose_tx(\n peers=[config.get_peer('my-peer')],\n generated_tx=generated_tx\n)\n\n# Raise errors on endorsement failure\nraise_tx_proposal_error(\n endorsed_tx,\n 'Endorsements failed for '\n)\n\n\n# Commit the transaction via the orderer\ncommitted_transaction = await commit_tx(\n requestor=requestor,\n orderers=[config.get_orderer('my-orderer')],\n endorsed_tx=endorsed_tx,\n)\n```\n\n### Events\n\nTo stream blocks from a Peer or Orderer node, use the `snakeskin.events` module, as such:\n\n```python\nfrom snakeskin.events import PeerEvents\n\nevents = PeerEvents(\n requestor=requestor,\n channel=config.get('my-channel'),\n peer=config.get('my-peer')\n)\n\nstream = events.stream_blocks(\n start=0, # start at block 0\n stop=10 # end at block 10 (if omitted, will stream forever)\n)\nasync for raw_block in stream:\n block = raw_block.decode()\n for transaction in block.transactions:\n transaction.tx_id # => '1234567'\n```\n\nTo stream [filtered blocks](https://hyperledger-fabric.readthedocs.io/en/release-1.4/peer_event_services.html), from the peer, use `snakeskin.events.PeerFilteredEvents`, and to stream blocks from the orderer use `snakeskin.events.OrdererEvents`. All of these classes implement similar interfaces.\n\n## Contributing\n\nComing soon\n\n## License\n\nThis software uses the Apache License Version 2.0 software license.\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "https://github.com/healthverity/snakeskin-fabric/", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/healthverity/snakeskin-fabric/", "keywords": "Hyperledger Fabric,SDK,Snakeskin", "license": "Apache License v2.0", "maintainer": "", "maintainer_email": "", "name": "snakeskin-fabric", "package_url": "https://pypi.org/project/snakeskin-fabric/", "platform": "any", "project_url": "https://pypi.org/project/snakeskin-fabric/", "project_urls": { "Download": "https://github.com/healthverity/snakeskin-fabric/", "Homepage": "https://github.com/healthverity/snakeskin-fabric/" }, "release_url": "https://pypi.org/project/snakeskin-fabric/0.1.1/", "requires_dist": [ "aiogrpc (>=1.6)", "cryptography (>=2.7)", "hkdf (>=0.0.3)", "pycryptodomex (>=3.8.2)", "pysha3 (>=1.0.2)", "requests (>=2.22.0)", "six (>=1.12.0)", "protobuf (>=3.9.0)", "pyyaml (>=5.1)", "dacite (>=1.0.2)" ], "requires_python": "", "summary": "An unofficial Python SDK for Hyperledger Fabric", "version": "0.1.1" }, "last_serial": 5704573, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "74b57975cf915757f58140f474eb16a2", "sha256": "4d8163eb9a3746c5b631dcc6a58a21be6a5ada67dbb2e49efcb4abb66c6c9ba4" }, "downloads": -1, "filename": "snakeskin_fabric-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "74b57975cf915757f58140f474eb16a2", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 151144, "upload_time": "2019-08-08T14:03:36", "url": "https://files.pythonhosted.org/packages/d4/91/c022baff485baea1cbcd250fae0a81bce934ddc3400677d8373f49ad6a03/snakeskin_fabric-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e426105748dc073af83c0278d9075f01", "sha256": "f9788fb354295c89267d8fdb41431ded939fb5d6472c964f0ff7aed2f5b82222" }, "downloads": -1, "filename": "snakeskin-fabric-0.1.0.tar.gz", "has_sig": false, "md5_digest": "e426105748dc073af83c0278d9075f01", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 93173, "upload_time": "2019-08-08T14:03:39", "url": "https://files.pythonhosted.org/packages/1e/6c/584c65d77b76b46dd301ffe1df045fadd41b38e061d2e0ca80a09e7f061c/snakeskin-fabric-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "99e67de16d9c31eec690ec80b9aeccf6", "sha256": "be70a432dabae48d9341932373b0b13127124e4ff1ccc54a5c41a218f631b458" }, "downloads": -1, "filename": "snakeskin_fabric-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "99e67de16d9c31eec690ec80b9aeccf6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 151191, "upload_time": "2019-08-20T17:19:28", "url": "https://files.pythonhosted.org/packages/f0/61/a83e8f51f8f3d386b84a8eab228d0ab53a9c0a585f30ecf2cd70a501d309/snakeskin_fabric-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f867c4a90c06c6db6f4723edf1af0dd2", "sha256": "e8295a040ccad07cb55fd4c522a63e2e5b6193b7249b1fb09f315430864da705" }, "downloads": -1, "filename": "snakeskin-fabric-0.1.1.tar.gz", "has_sig": false, "md5_digest": "f867c4a90c06c6db6f4723edf1af0dd2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 93166, "upload_time": "2019-08-20T17:19:30", "url": "https://files.pythonhosted.org/packages/d7/38/53ec562c3b2467bb053accf19fcf9579c96a961178d95c057094ca1e0ed8/snakeskin-fabric-0.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "99e67de16d9c31eec690ec80b9aeccf6", "sha256": "be70a432dabae48d9341932373b0b13127124e4ff1ccc54a5c41a218f631b458" }, "downloads": -1, "filename": "snakeskin_fabric-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "99e67de16d9c31eec690ec80b9aeccf6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 151191, "upload_time": "2019-08-20T17:19:28", "url": "https://files.pythonhosted.org/packages/f0/61/a83e8f51f8f3d386b84a8eab228d0ab53a9c0a585f30ecf2cd70a501d309/snakeskin_fabric-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f867c4a90c06c6db6f4723edf1af0dd2", "sha256": "e8295a040ccad07cb55fd4c522a63e2e5b6193b7249b1fb09f315430864da705" }, "downloads": -1, "filename": "snakeskin-fabric-0.1.1.tar.gz", "has_sig": false, "md5_digest": "f867c4a90c06c6db6f4723edf1af0dd2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 93166, "upload_time": "2019-08-20T17:19:30", "url": "https://files.pythonhosted.org/packages/d7/38/53ec562c3b2467bb053accf19fcf9579c96a961178d95c057094ca1e0ed8/snakeskin-fabric-0.1.1.tar.gz" } ] }