From 37ef5b414801cbd9efe117fc2782f14163685567 Mon Sep 17 00:00:00 2001 From: Janez Podhostnik Date: Sat, 6 Nov 2021 11:20:30 +0000 Subject: [PATCH 1/3] docs cleanup --- CHANGELOG.md | 24 ------------------------ LICENSE | 2 +- README.md | 7 +++++-- 3 files changed, 6 insertions(+), 27 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 28df88c..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,24 +0,0 @@ -### Unreleased - -- 2021-10-01 -- Adding function definition to all client functions -- 2021-09-30 -- Adding ma_script_example.py -- 2021-09-30 -- Adding retrieving_blocks.mdx -- 2021-09-30 -- Adding querying_event.mdx -- 2021-09-30 -- Adding performing_scripts.mdx -- 2021-09-30 -- Adding retrieving_collections.mdx - -### Unreleased - -- 2021-09-28 -- Adding ma_block_example.py -- 2021-09-28 -- Adding ma_events_example.py -- 2021-09-28 -- Adding ma_collections_example.py -- 2021-09-28 -- Adding ma_create_account.py -- 2021-09-28 -- Adding from_seed classmethod AccountKey Class -- 2021-09-28 -- Adding function definition to some client functions -- 2021-09-28 -- Adding generating_keys.mdx file - - - -### Unreleased - -- YYYY-MM-DD **BREAKING?** -- description diff --git a/LICENSE b/LICENSE index 63b4b68..467b611 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) [year] [fullname] +Copyright (c) [2021] [janezpodhostnik] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 1256490..f7f6169 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,14 @@ title: Flow Python SDK description: Packages for Python developers to build applications that interact with the Flow network contentType: INTRO --- + The Flow Python SDK provides a set of packages for Python developers to build applications that interact with the Flow network. [![PyPI](https://img.shields.io/pypi/v/flow-py-sdk.svg)](https://pypi.org/project/flow-py-sdk/) [![codecov](https://codecov.io/gh/janezpodhostnik/flow-py-sdk/branch/master/graph/badge.svg)](https://codecov.io/gh/codecov/example-go) -See the [DOCS](https://janezpodhostnik.github.io/flow-py-sdk)! +See the [guide](./docs/python_SDK_guide.md)! Note: This SDK is also fully compatible with the Flow Emulator and can be used for local development. @@ -24,7 +25,9 @@ pip install flow-py-sdk or if using poetry: -`poetry add flow-py-sdk` +```sh +poetry add flow-py-sdk +``` ## Run examples From f3a1545aedbe30669fadd44093afa951d8a707cc Mon Sep 17 00:00:00 2001 From: Janez Podhostnik Date: Sat, 6 Nov 2021 15:13:14 +0000 Subject: [PATCH 2/3] docs cleanup --- docs/account_&_contract.mdx | 234 ---------------- docs/api_docs/client.md | 55 ++++ docs/api_docs/keys.md | 5 + docs/api_docs/signer.md | 9 + docs/building_transaction.mdx | 479 -------------------------------- docs/cadence_types.md | 3 - docs/contributing.md | 7 +- docs/emulator.md | 12 - docs/events.md | 3 - docs/examples.md | 12 +- docs/generating_keys.mdx | 82 ------ docs/index.md | 17 -- docs/installation.md | 19 -- docs/performing_scripts.mdx | 147 ---------- docs/python_SDK_guide.md | 87 +++--- docs/querying_events.mdx | 65 ----- docs/retrieving_blocks.mdx | 56 ---- docs/retrieving_collections.mdx | 24 -- docs/roadmap.md | 42 --- docs/scripts.md | 101 ------- docs/sdk-banner.svg | 36 --- docs/transactions.md | 3 - docs/usage.md | 6 - flow_py_sdk/__init__.py | 2 +- flow_py_sdk/client/entities.py | 3 +- mkdocs.yml | 26 +- 26 files changed, 145 insertions(+), 1390 deletions(-) delete mode 100644 docs/account_&_contract.mdx create mode 100644 docs/api_docs/client.md create mode 100644 docs/api_docs/keys.md create mode 100644 docs/api_docs/signer.md delete mode 100644 docs/building_transaction.mdx delete mode 100644 docs/cadence_types.md delete mode 100644 docs/emulator.md delete mode 100644 docs/events.md delete mode 100644 docs/generating_keys.mdx delete mode 100644 docs/index.md delete mode 100644 docs/installation.md delete mode 100644 docs/performing_scripts.mdx delete mode 100644 docs/querying_events.mdx delete mode 100644 docs/retrieving_blocks.mdx delete mode 100644 docs/retrieving_collections.mdx delete mode 100644 docs/scripts.md delete mode 100644 docs/sdk-banner.svg delete mode 100644 docs/transactions.md delete mode 100644 docs/usage.md diff --git a/docs/account_&_contract.mdx b/docs/account_&_contract.mdx deleted file mode 100644 index dd042a1..0000000 --- a/docs/account_&_contract.mdx +++ /dev/null @@ -1,234 +0,0 @@ ---- -title: Creating account and add, update remove contracts -description: How to creating account and add, update remove contracts using the Flow Python SDK -contentType: HOWTO ---- - -A account contains the following fields: - -- `address` - A unique account identifier. -- `balance` - Balance of account. -- `code` - The code deployed to this account (deprecated, use contracts instead) -- `keys` - List of keys associated with account. -- `contracts` - List of contracts associated with account. - -## Creating Account - -For creating an account, you need to send a transaction to Flow blockchain. -To create account you need to use another account, for example here emulator service account is used. - -```python -async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - - latest_block = await client.get_latest_block() - proposer = await client.get_account_at_latest_block(address = ctx.service_account_address.bytes) - - tx = ( - create_account_template( - keys = [account_key], - reference_block_id = latest_block.id, - payer = ctx.service_account_address, - proposal_key = ProposalKey( - key_address = ctx.service_account_address, - key_id = ctx.service_account_key_id, - key_sequence_number = proposer.keys[ - ctx.service_account_key_id - ].sequence_number, - ), - ) - .add_authorizers(ctx.service_account_address) - .with_envelope_signature( - ctx.service_account_address, 0, ctx.service_account_signer - ) - ) - result = await client.execute_transaction(tx) - - - print("new address event:\n") - print(result.__dict__) - print("\nCreating account : successfully done...") -``` -Flow smart contracts are Codance scripts that run on Flow blockchain and can returns values. -a contract can be add, update or remove from an account. - -A contract contains the following fields: - -- `Name` - Name of contract. -- `source` - Script of contract. - -## Adding a contract to an account - -```python -async def run(self, ctx: Config): - # First Step : Create a client to connect to the flow blockchain - # flow_client function creates a client using the host and port - # A test Contract define for this example, you can modify it by your self - contract = { - "Name" : "TestOne", - "source" : '''pub contract TestOne { - pub fun add(a: Int, b: Int): Int { - return a + b - } - }''' - } - contract_source_hex = bytes(contract["source"],"UTF-8").hex() - - async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - account_address, account_key, new_signer = await random_account( client = client, ctx = ctx) - latest_block = await client.get_latest_block() - cadenceName = cadence.String(contract["Name"]) - cadenceCode = cadence.String(contract_source_hex) - tx = ( - Tx( - code = addAccountContractTemplate, - reference_block_id = latest_block.id, - payer = account_address, - ).add_arguments(cadenceName) - .add_arguments(cadenceCode) - .add_authorizers([account_address]) - .with_envelope_signature( - account_address, - 0, - new_signer, - ) - ) - - result = await client.execute_transaction(tx) - -``` -## Updating a contract of an account -```python -async def run(self, ctx: Config): - # First Step : Create a client to connect to the flow blockchain - # flow_client function creates a client using the host and port - # A test Contract define for this example, you can modify it by your self - contract = { - "Name" : "TestOne", - "source" : '''pub contract TestOne { - pub fun add(a: Int, b: Int): Int { - return a + b - } - }''' - } - contract_source_hex = bytes(contract["source"],"UTF-8").hex() - - async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - account_address, account_key, new_signer = await random_account( client = client, ctx = ctx) - latest_block = await client.get_latest_block() - cadenceName = cadence.String(contract["Name"]) - cadenceCode = cadence.String(contract_source_hex) - tx = ( - Tx( - code = addAccountContractTemplate, - reference_block_id = latest_block.id, - payer = account_address, - ).add_arguments(cadenceName) - .add_arguments(cadenceCode) - .add_authorizers([account_address]) - .with_envelope_signature( - account_address, - 0, - new_signer, - ) - ) - - result = await client.execute_transaction(tx) - - latest_block = await client.get_latest_block() - #Updated Contract - contract = { - "Name" : "TestOne", - "source" : '''pub contract TestOne { - pub fun add(a: Int, b: Int): Int { - return a * b - } - }''' - } - contract_source_hex = bytes(contract["source"],"UTF-8").hex() - #Update account contract with a transaction - tx = ( - Tx( - code = updateAccountContractTemplate, - reference_block_id = latest_block.id, - payer = account_address, - ).add_arguments(contract["Name"]) - .add_arguments(contract_source_hex) - .add_authorizers([account_address]) - .with_envelope_signature( - account_address, - 0, - new_signer, - ) - ) - - result = await client.execute_transaction(tx) - -``` - -## Removing a contract from an account -```python -async def run(self, ctx: Config): - # First Step : Create a client to connect to the flow blockchain - # flow_client function creates a client using the host and port - # A test Contract define for this example, you can modify it by your self - contract = { - "Name" : "TestOne", - "source" : '''pub contract TestOne { - pub fun add(a: Int, b: Int): Int { - return a + b - } - }''' - } - contract_source_hex = bytes(contract["source"],"UTF-8").hex() - - async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - account_address, account_key, new_signer = await random_account( client = client, ctx = ctx) - latest_block = await client.get_latest_block() - cadenceName = cadence.String(contract["Name"]) - cadenceCode = cadence.String(contract_source_hex) - tx = ( - Tx( - code = addAccountContractTemplate, - reference_block_id = latest_block.id, - payer = account_address, - ).add_arguments(cadenceName) - .add_arguments(cadenceCode) - .add_authorizers([account_address]) - .with_envelope_signature( - account_address, - 0, - new_signer, - ) - ) - - result = await client.execute_transaction(tx) - - # Delete the added contract from the account - - latest_block = await client.get_latest_block() - - tx = ( - Tx( - code = removeAccountContractTemplate, - reference_block_id = latest_block.id, - payer = account_address, - ).add_arguments(cadenceName) - .add_authorizers([account_address]) - .with_envelope_signature( - account_address, - 0, - new_signer, - ) - ) - - result = await client.execute_transaction(tx) - -``` \ No newline at end of file diff --git a/docs/api_docs/client.md b/docs/api_docs/client.md new file mode 100644 index 0000000..9854fda --- /dev/null +++ b/docs/api_docs/client.md @@ -0,0 +1,55 @@ +# Client API Docs + +## Create a flow client + +::: flow_py_sdk.flow_client + +## Query Blocks + +::: flow_py_sdk.AccessAPI.get_latest_block_header + +::: flow_py_sdk.AccessAPI.get_block_header_by_i_d + +::: flow_py_sdk.AccessAPI.get_block_header_by_height + +::: flow_py_sdk.AccessAPI.get_latest_block + +::: flow_py_sdk.AccessAPI.get_block_by_i_d + +::: flow_py_sdk.AccessAPI.get_block_by_height + +## Accounts + +::: flow_py_sdk.AccessAPI.get_account + +::: flow_py_sdk.AccessAPI.get_account_at_latest_block + +::: flow_py_sdk.AccessAPI.get_account_at_block_height + +## Transactions + +::: flow_py_sdk.AccessAPI.get_transaction_result + +::: flow_py_sdk.AccessAPI.get_transaction + +::: flow_py_sdk.AccessAPI.execute_transaction + +::: flow_py_sdk.AccessAPI.send_transaction + +## Events + +::: flow_py_sdk.AccessAPI.get_events_for_height_range + +::: flow_py_sdk.AccessAPI.get_events_for_block_i_ds + +## Collections + +::: flow_py_sdk.AccessAPI.get_collection_by_i_d + +## Scripts + +::: flow_py_sdk.AccessAPI.execute_script_at_latest_block + +::: flow_py_sdk.AccessAPI.execute_script_at_block_i_d + +::: flow_py_sdk.AccessAPI.execute_script_at_block_height \ No newline at end of file diff --git a/docs/api_docs/keys.md b/docs/api_docs/keys.md new file mode 100644 index 0000000..7826ba7 --- /dev/null +++ b/docs/api_docs/keys.md @@ -0,0 +1,5 @@ +# Keys + +## Generate new keys + +::: flow_py_sdk.AccountKey.from_seed \ No newline at end of file diff --git a/docs/api_docs/signer.md b/docs/api_docs/signer.md new file mode 100644 index 0000000..eb35de9 --- /dev/null +++ b/docs/api_docs/signer.md @@ -0,0 +1,9 @@ +# Signer + +## Signer Base Class + +::: flow_py_sdk.Signer + +## In Memory signer Implementation + +::: flow_py_sdk.InMemorySigner \ No newline at end of file diff --git a/docs/building_transaction.mdx b/docs/building_transaction.mdx deleted file mode 100644 index 6aaca53..0000000 --- a/docs/building_transaction.mdx +++ /dev/null @@ -1,479 +0,0 @@ ---- -title: Build and send a Transaction -description: How to prepare and send a transaction with the Flow python SDK -contentType: HOWTO ---- - -Flow, like most blockchains, allows anybody to submit a transaction that mutates -the shared global chain state. A transaction is an object that holds a payload, -which describes the state mutation, and one or more authorizations that permit -the transaction to mutate the state owned by specific accounts. - -You can read more about transactions in the [transaction lifecycle documentation](/concepts/transaction-lifecycle). - -A transaction contains the following fields: - -- `script` - Raw source code for a Cadence script, encoded as UTF-8 bytes -- `arguments` - Arguments passed to the Cadence script, encoded as JSON-Cadence bytes -- `reference_block_id` - Block ID used to determine transaction expiry -- `proposal_key` - Account key used to propose the transaction -- `payer` - Address of the payer account -- `authorizers` - Addresses of the transaction authorizers -- `signatures` - Signatures from all signer accounts - -# Create the Transaction - -A transaction needs some parameters, first have a look on them then implement them in example. - -You can start by creating an empty transaction with the python SDK. -We'll populate the remaining fields one by one. - -## Code - -The `code` field is the portion of the transaction that describes the state mutation logic. - -On Flow, transaction logic is written in [Cadence](/cadence). The value of `code` -is a byte slice containing the UTF-8 encoded source code for a Cadence program. - - -## Gas Limit - -A transaction must specify a limit on the amount of computation it requires, -referred to as the _gas limit_. A transaction will abort if it exceeds its gas limit. - -### How is gas measured? - -Cadence uses metering to measure the number of operations per transaction. -You can read more about it in the [Cadence documentation](/cadence). - -### What should the limit be? - -The gas limit depends on the complexity of the transaction script. -Until dedicated gas estimation tooling exists, it's best to use the emulator -to test complex transactions and determine a safe limit. - -## Reference Block - -A transaction must specify an expiration window (measured in blocks) during which it is considered valid by the network. -A transaction will be rejected if it is submitted past its expiry block. - -## Proposal Key - -A transaction must specify a [sequence number](/concepts/transaction-signing/#sequence-numbers) -to prevent replays and other potential attacks. - -Each account key maintains a separate transaction sequence counter; -the key that lends its sequence number to a transaction is called the _proposal key_. - -A proposal key contains three fields: - -- Account address -- Key index -- Sequence number - -A transaction is only valid if its declared sequence number matches the current -on-chain sequence number for that key. The sequence number increments by one after -the transaction is executed. - -## Payer - -The transaction payer is the account that pays the fees for the transaction. -A transaction must specify exactly one payer. The payer is only responsible -for paying the network and gas fees; the transaction is not authorized to access -resources or code stored in the payer account. - -From what you learn so far now you can create a transaction as below: - -```python -async def run(self, ctx: Config): - # First Step : Create a client to connect to the flow blockchain - # flow_client function creates a client using the host and port - account_key, new_signer = AccountKey.from_seed(seed = "dfghj dfj kjhgf hgfd lkjhgf kjhgfd sdfghjkl") - - async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - latest_block = await client.get_latest_block() - proposer = await client.get_account_at_latest_block(address = ctx.service_account_address) - - tx = Tx( - code="""transaction(){prepare(){log("OK")}}""", - reference_block_id = latest_block.id, - payer = account_key.public_key, - proposal_key = ProposalKey( - key_address = account_key.public_key, - key_id = 0, - key_sequence_number = proposer.keys[ - 0 - ].sequence_number, - ), - ) -``` -There is more you can do with transaction. let's check them: - -## Arguments - -A transaction can accept zero or more arguments that are passed into the Cadence script. - -The arguments on the transaction must match the number and order declared in -the Cadence script. - -```python -tx.add_arguments("argument1") -``` - -## Authorizers - -An authorizer is an account that authorizes a transaction to read and mutate its resources. -A transaction can specify zero or more authorizers, -depending on how many accounts the transaction needs to access. - -The number of authorizers on the transaction must match the number of `AuthAccount` -parameters declared in the `prepare` statement of the Cadence script. - -```python - tx.add_authorizers(authorizerAddress) -} -``` -# Sign a transaction - -Transaction signing is done through the `Signer`. The simplest -(and least secure) implementation of `Signer` is `InMemorySigner`. - -Signatures can be generated more securely using keys stored in a hardware device such -as an [HSM](https://en.wikipedia.org/wiki/Hardware_security_module). - -```python -signer = in_memory_signer.InMemorySigner(hash_algo = hash_algo, - sign_algo = sign_algo, - private_key_hex = private_key.to_string().hex()) - -tx.with_envelope_signature( - account_key.public_key, - 0, - new_signer, - ) -``` - -# How Signatures Work in Flow - -Flow introduces new concepts that allow for more flexibility when creating and signing transactions. - ---- - -## Single party, single signature - -- Proposer, payer and authorizer are the same account (`0x01`). -- Only the envelope must be signed. -- Proposal key must have full signing weight. - -| Account | Key ID | Weight | -| ------- | ------ | ------ | -| `0x01` | 1 | 1.0 | - -```python -async def run(self, ctx: Config): - # First Step : Create a client to connect to the flow blockchain - # flow_client function creates a client using the host and port - address = Address.from_hex("0x01") - account = await client.get_account(address = address) - # Assume you stored private key somewhere safe and restore it in private_key. - signer = in_memory_signer.InMemorySigner(hash_algo = hash_algo, - sign_algo = sign_algo, - private_key_hex = private_key.to_string().hex()) - async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - latest_block = await client.get_latest_block() - - tx = Tx( - code=""" - transaction { - prepare(signer: AuthAccount) { log(signer.address) } - } - """, - reference_block_id = latest_block.id, - payer = account.address, - proposal_key = ProposalKey( - key_address = account.address, - key_id = 0, - key_sequence_number = account.keys[ - 0 - ].sequence_number, - ), - ).add_authorizers([account.address]) - .with_envelope_signature( - account.address, - 0, - signer, - ) -``` ---- - -## Single party, multiple signatures - -- Proposer, payer and authorizer are the same account (`0x01`). -- Only the envelope must be signed. -- Each key has weight 0.5, so two signatures are required. - -| Account | Key ID | Weight | -| ------- | ------ | ------ | -| `0x01` | 1 | 0.5 | -| `0x01` | 2 | 0.5 | - -```python -async def run(self, ctx: Config): - # First Step : Create a client to connect to the flow blockchain - # flow_client function creates a client using the host and port - address = Address.from_hex("0x01") - account = await client.get_account(address = address) - # Assume you stored private key somewhere safe and restore it in private_key. - signer1 = in_memory_signer.InMemorySigner(hash_algo = hash_algo, - sign_algo = sign_algo, - private_key_hex = private_key1.to_string().hex()) - signer2 = in_memory_signer.InMemorySigner(hash_algo = hash_algo, - sign_algo = sign_algo, - private_key_hex = private_key2.to_string().hex()) - async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - latest_block = await client.get_latest_block() - - tx = Tx( - code=""" - transaction { - prepare(signer: AuthAccount) { log(signer.address) } - } - """, - reference_block_id = latest_block.id, - payer = account.address, - proposal_key = ProposalKey( - key_address = account.address, - key_id = 0, - key_sequence_number = account.keys[ - 0 - ].sequence_number, - ), - ).add_authorizers([account.address]) - .with_envelope_signature( - account.address, - 0, - signer1, - ).with_envelope_signature( - account.address, - 1, - signer2, - ) -``` - ---- - -## Multiple parties - -- Proposer and authorizer are the same account (`0x01`). -- Payer is a separate account (`0x02`). -- Account `0x01` signs the payload. -- Account `0x02` signs the envelope. - - Account `0x02` must sign last since it is the payer. - -| Account | Key ID | Weight | -| ------- | ------ | ------ | -| `0x01` | 1 | 1.0 | -| `0x02` | 3 | 1.0 | - -```python -async def run(self, ctx: Config): - # First Step : Create a client to connect to the flow blockchain - # flow_client function creates a client using the host and port - address1 = Address.from_hex("0x01") - address3 = Address.from_hex("0x02") - account = await client.get_account(address = address) - # Assume you stored private key somewhere safe and restore it in private_key. - signer1 = in_memory_signer.InMemorySigner(hash_algo = hash_algo, - sign_algo = sign_algo, - private_key_hex = private_key1.to_string().hex()) - signer3 = in_memory_signer.InMemorySigner(hash_algo = hash_algo, - sign_algo = sign_algo, - private_key_hex = private_key3.to_string().hex()) - async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - latest_block = await client.get_latest_block() - - tx = Tx( - code=""" - transaction { - prepare(signer: AuthAccount) { log(signer.address) } - } - """, - reference_block_id = latest_block.id, - payer = account3.address, - proposal_key = ProposalKey( - key_address = account1.address, - key_id = 0, - key_sequence_number = account.keys[ - 0 - ].sequence_number, - ), - ).add_authorizers([account1.address]) - .with_payload_signature( - account1.address, - 0, - signer1, - ).with_envelope_signature( - account3.address, - 0, - signer3, - ) -``` ---- - -## Multiple parties, two authorizers - -- Proposer and authorizer are the same account (`0x01`). -- Payer is a separate account (`0x02`). -- Account `0x01` signs the payload. -- Account `0x02` signs the envelope. - - Account `0x02` must sign last since it is the payer. -- Account `0x02` is also an authorizer to show how to include two AuthAccounts into an transaction - -| Account | Key ID | Weight | -| ------- | ------ | ------ | -| `0x01` | 1 | 1.0 | -| `0x02` | 3 | 1.0 | - -```python -async def run(self, ctx: Config): - # First Step : Create a client to connect to the flow blockchain - # flow_client function creates a client using the host and port - address1 = Address.from_hex("0x01") - address3 = Address.from_hex("0x02") - account = await client.get_account(address = address) - # Assume you stored private key somewhere safe and restore it in private_key. - signer1 = in_memory_signer.InMemorySigner(hash_algo = hash_algo, - sign_algo = sign_algo, - private_key_hex = private_key1.to_string().hex()) - signer3 = in_memory_signer.InMemorySigner(hash_algo = hash_algo, - sign_algo = sign_algo, - private_key_hex = private_key3.to_string().hex()) - async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - latest_block = await client.get_latest_block() - - tx = Tx( - code=""" - transaction { - prepare(signer: AuthAccount) { log(signer.address) } - } - """, - reference_block_id = latest_block.id, - payer = account3.address, - proposal_key = ProposalKey( - key_address = account1.address, - key_id = 0, - key_sequence_number = account.keys[ - 0 - ].sequence_number, - ), - ).add_authorizers([account1.address, account3.address]) - .with_payload_signature( - account1.address, - 0, - signer1, - ).with_envelope_signature( - account3.address, - 0, - signer3, - ) -``` - ---- - -## Multiple parties, multiple signatures - -- Proposer and authorizer are the same account (`0x01`). -- Payer is a separate account (`0x02`). -- Account `0x01` signs the payload. -- Account `0x02` signs the envelope. - - Account `0x02` must sign last since it is the payer. -- Both accounts must sign twice (once with each of their keys). - -| Account | Key ID | Weight | -| ------- | ------ | ------ | -| `0x01` | 1 | 0.5 | -| `0x01` | 2 | 0.5 | -| `0x02` | 3 | 0.5 | -| `0x02` | 4 | 0.5 | - -```python -async def run(self, ctx: Config): - # First Step : Create a client to connect to the flow blockchain - # flow_client function creates a client using the host and port - address1 = Address.from_hex("0x01") - address3 = Address.from_hex("0x02") - account = await client.get_account(address = address) - # Assume you stored private key somewhere safe and restore it in private_key. - signer1 = in_memory_signer.InMemorySigner(hash_algo = hash_algo, - sign_algo = sign_algo, - private_key_hex = private_key1.to_string().hex()) - signer2 = in_memory_signer.InMemorySigner(hash_algo = hash_algo, - sign_algo = sign_algo, - private_key_hex = private_key2.to_string().hex()) - signer3 = in_memory_signer.InMemorySigner(hash_algo = hash_algo, - sign_algo = sign_algo, - private_key_hex = private_key3.to_string().hex()) - signer4 = in_memory_signer.InMemorySigner(hash_algo = hash_algo, - sign_algo = sign_algo, - private_key_hex = private_key4.to_string().hex()) - async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - latest_block = await client.get_latest_block() - - tx = Tx( - code=""" - transaction { - prepare(signer: AuthAccount) { log(signer.address) } - } - """, - reference_block_id = latest_block.id, - payer = account2.address, - proposal_key = ProposalKey( - key_address = account1.address, - key_id = 0, - key_sequence_number = account.keys[ - 0 - ].sequence_number, - ), - ).add_authorizers([account1.address]) - .with_payload_signature( - account1.address, - 0, - signer1, - ).with_payload_signature( - account1.address, - 1, - signer2, - ).with_envelope_signature( - account3.address, - 0, - signer3, - ).with_envelope_signature( - account3.address, - 1, - signer4, - ) -``` - -# Send transaction and get results - -There is two way to do this: -- you can use `send_transaction` and `get_transaction_result`. -- you can use `execute_transaction` - -The second one is recommanded. you can see a example in below: - -```python -results = await client.execute_transaction(tx) -``` diff --git a/docs/cadence_types.md b/docs/cadence_types.md deleted file mode 100644 index e69580c..0000000 --- a/docs/cadence_types.md +++ /dev/null @@ -1,3 +0,0 @@ -# Cadence types - -⛏️ WIP \ No newline at end of file diff --git a/docs/contributing.md b/docs/contributing.md index f218146..e31a2d3 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -1,7 +1,10 @@ # Contributing -Any contributions are very welcome. +Any contributions are very welcome. + +All bug reports, suggestions, ideas, comments are very useful for the integrity and continual development of `flow-py-sdk`. All of those can be reported as issues [here](https://github.com/janezpodhostnik/flow-py-sdk/issues). If you would like to contribute to the code, the best place to start is to run the [examples](./examples.md) locally. After that your environment will be set up for development. -If you don't have anything specific in mind but still want to contribute make sure to check the [roadmap](./roadmap.md) for ideas. +If you don't have anything specific in mind but still want to contribute make sure to check any open issues. + diff --git a/docs/emulator.md b/docs/emulator.md deleted file mode 100644 index 21a372d..0000000 --- a/docs/emulator.md +++ /dev/null @@ -1,12 +0,0 @@ -# Running the emulator - -To run the examples, the [flow emulator](https://github.com/onflow/flow-emulator) needs to be running locally. -To do that you can use the following instructions or the instructions directly at https://github.com/onflow/flow-emulator. - -1. Install the [Flow CLI](https://docs.onflow.org/flow-cli). - -2. Start the Flow Emulator in the `examples` directory of this repository (where the `flow.json` config is) using the command: - -```sh -flow emulator start -``` \ No newline at end of file diff --git a/docs/events.md b/docs/events.md deleted file mode 100644 index 0a50ffd..0000000 --- a/docs/events.md +++ /dev/null @@ -1,3 +0,0 @@ -# Events - -⛏️ WIP \ No newline at end of file diff --git a/docs/examples.md b/docs/examples.md index 9d63676..79d900e 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -9,20 +9,24 @@ In case you want to debug the examples, or you just want to see them in action y ### 1. Prerequisites -- a locally running [emulator](./emulator.md) +- `flow-cli` for starting the emulator ([step-by-step based installation instructions based on your OS](https://github.com/onflow/flow-cli#flow-cli)) - a checkout of `flow-py-sdk` - python 3.9 or higher - [poetry](https://python-poetry.org/) -Run +The first step is to install the dependencies of `flow-py-sdk` with **poetry**. To do this run the following command on the root of the checkout. ```sh poetry install ``` -in the root of the checkout to install dependencies from `pyproject.toml`. +After that start the flow emulator in **./example** directory (because that is where the `flow.json` the emulator configuration is), using: -### 2. Run examples +```sh +flow emulator +``` + +### 2. Runing examples To run all the examples use: diff --git a/docs/generating_keys.mdx b/docs/generating_keys.mdx deleted file mode 100644 index 51e85b6..0000000 --- a/docs/generating_keys.mdx +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: Generating Keys -description: How to generating Keys using the Flow Python SDK -contentType: HOWTO ---- - -A accountKey contains the following fields: - -- `id` - Index of the key within the account, used as a unique identifier. -- `public_key` - Public key encoded as bytes. -- `sign_algo` - signature algorithm. -- `hash_algo` - hash algorithm. -- `weight` - Each account key has a weight that determines the signing power it holds. -- `sequence_number` - Flow uses sequence numbers to ensure that each transaction runs at most once. -- `revoked` - Flag indicating whether or not the key has been revoked. - -Flow uses [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) -to control access to user accounts. Each key pair can be used in combination with -the SHA2-256 or SHA3-256 hashing algorithms. -### Supported Algorithms - -Hashing algorithms that is supported in Flow: -- SHA2_256 -- SHA2_384 -- SHA3_256 -- SHA3_384 - -Signing algorithms that is supported in Flow: -- SECP256k1 -- SECP256k1 - -Here's a full list of the supported signature and hash algorithms: [Flow Signature & Hash Algorithms](https://docs.onflow.org/concepts/accounts-and-keys/#supported-signature--hash-algorithms) - -Here's how to generate an ECDSA private and public keys for the P-256 (secp256r1) curve: - -```python -from ecdsa import NIST384p,SigningKey -private_key = SigningKey.generate() -public_key = private_key.get_verifying_key() - -# Also you can use seed string for creating keys -# note: this is only an example, please use a secure random generator for the key seed - -secexp = randrange_from_seed__trytryagain(seed, sign_algo.get_signing_curve().order) -private_key = SigningKey.from_secret_exponent(secexp, curve = sign_algo.get_signing_curve()) - -``` - -The private key can then be encoded as bytes (i.e. for storage): - -```python -encPrivateKey := privateKey.encode() -``` - -A private key has an accompanying public key: - -```python -public_key = private_key.get_verifying_key() -``` - -### Other methods -There are two other methods for creating or retrieving account key - -#### from_proto -If you want to retrieve account key of an existing account from Flow, you can use this method. - -```python -loop = asyncio.new_event_loop() -asyncio.set_event_loop(loop) -account = loop.run_until_complete(get_account_from_proto()) -acc_key = AccountKey.from_proto(account.keys[0]) -``` -Notice an account can has multiple keys so you should choose one you want. - -#### from_seed -Using this method You can easily create a pair key. this method use ECDSA library as describe above for creating private and public keys. -It returns an AccountKey and InMemorySigner Object that can be use for further actions. - -```python -# note: this is only an example, please use a secure random generator for the key seed -get_account_key_from_seed(seed = "elephant ears space cowboy octopus rodeo potato cannon pineapple") -``` \ No newline at end of file diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 38f3a52..0000000 --- a/docs/index.md +++ /dev/null @@ -1,17 +0,0 @@ -# Overview - -Current Version: [![PyPI](https://img.shields.io/pypi/v/flow-py-sdk.svg)](https://pypi.org/project/flow-py-sdk/) - -# flow-py-sdk - -Another unofficial flow blockchain python sdk. Which can be found here: https://janezpodhostnik.github.io/flow-py-sdk/. - -Under development! Currently this is close to an "MVP" it is mostly missing more of: docs, tests, examples and organization. - -If you do want to use it, install it with: - -`pip install flow-py-sdk` - -Or if using poetry: - -`poetry add flow-py-sdk` diff --git a/docs/installation.md b/docs/installation.md deleted file mode 100644 index c331992..0000000 --- a/docs/installation.md +++ /dev/null @@ -1,19 +0,0 @@ -# Installation - -## Prerequisites - -Python version 3.9 or higher. - -## Install - -With pip: - -```sh -pip install flow-py-sdk -``` - -with poetry: - -```sh -poetry add flow-py-sdk -``` \ No newline at end of file diff --git a/docs/performing_scripts.mdx b/docs/performing_scripts.mdx deleted file mode 100644 index 33e012d..0000000 --- a/docs/performing_scripts.mdx +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: preforming Scripts -description: How to perform a script blockchain using the Flow Python SDK -contentType: HOWTO ---- - -The Cadence Programming Language is a new high-level programming language intended for smart contract development. - -You can find more information about The Cadence Programming Language [here](https://docs.onflow.org/cadence/language/). - -## Sending Scripts - -You can send scripts with or without parameters. here two example are provided to show you how can you send your requests. - -### scripts without parameters - -```py -from flow_py_sdk import flow_client, Script - -# ... - -async with flow_client(host=access_node_host, port=access_node_port) as client: - script = Script( - code=""" - pub fun main() { - let a = 1 - let b = 1 - log(a + b) - } - """ - ) - await client.execute_script(script) -``` - -When sending this script to an emulator, the log output will be visible in the emulator output. - - -### scripts with parameters - -To execute scripts with arguments (parameters) two approaches can be used. - -- `__init__` parameters -- `add_arguments` - - -#### By using `__init__` parameters. - -```py -async with flow_client(host=access_node_host, port=access_node_port) as client: - script = Script( - code=""" - pub fun main(a: Int, b: Int) { - log(a + b) - } - """, - arguments=[cadence.Int(1), cadence.Int(1)] - ) - await client.execute_script(script) -``` - -#### By using `add_arguments`. - -```py -async with flow_client(host=access_node_host, port=access_node_port) as client: - script = Script( - code=""" - pub fun main(a: Int, b: Int) { - log(a + b) - } - """ - ).add_arguments(cadence.Int(1), cadence.Int(1)) - - await client.execute_script(script) -``` - -`add_arguments` can also be used to add one argument at a time. - -```py -async with flow_client(host=access_node_host, port=access_node_port) as client: - script = Script( - code=""" - pub fun main(a: Int, b: Int) { - log(a + b) - } - """ - ).add_arguments(cadence.Int(1)).add_arguments(cadence.Int(1)) - - await client.execute_script(script) -``` - -All arguments ned to be a `cadence.Value` otherwise a `NotCadenceValueError` is raised. - -## Getting script results - -The return value of `client.execute_script` is the script result if the script returns a result. -The type of the result is an abstract `cadence.Value`. - -```py - a_plus_b = result.as_type(cadence.Int).value -``` - -## Executing a Script - -You can use the `execute_script` method to execute a read-only script against a block. - -You can specify the block with id or height. - -Scripts must be in the following form: - -- A single `main` function with a single return value - -This is an example of a valid script: - -``` -fun main(): Int { return 1 } -``` -```py -async def run(self, ctx: Config): - # First Step : Create a client to connect to the flow blockchain - # flow_client function creates a client using the host and port - - # -------------------------------- - # script without arguments Example - # -------------------------------- - script = Script( - code=""" - pub fun main(): Int { - let a = 1 - let b = 1 - return a + b - } - """ - ) - - script = Script() - - async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - result = await client.execute_script( - script = script - # , block_id - block_height = 1 - ) - print("Script result :\n") - print(result.__dict__) -``` \ No newline at end of file diff --git a/docs/python_SDK_guide.md b/docs/python_SDK_guide.md index 4db3faf..4cccf98 100644 --- a/docs/python_SDK_guide.md +++ b/docs/python_SDK_guide.md @@ -1,16 +1,3 @@ -
-
- - Logo - -


- View on GitHub »

- SDK Specifications · - Contribute · - Report a Bug -

-

- ## Overview This reference documents all the methods available in the SDK, and explains in detail how these methods work. @@ -18,8 +5,7 @@ SDKs are open source, and you can use them according to the licence. The library client specifications can be found here: -// TODO specs here -[]() +[](./api_docs/client.md) ## Getting Started @@ -29,13 +15,23 @@ The library client specifications can be found here: pip install flow-py-sdk ``` +or + +```sh +poetry add flow-py-sdk +``` + ### Importing the Library ```sh import flow-py-sdk ``` +## Running examples + +See [Running examples](./examples.md) + ## Connect -[]() // TODO specs here +[](./api_docs/client.md#create-a-flow-client) The library uses gRPC to communicate with the access nodes and it must be configured with correct access node API URL. @@ -46,15 +42,19 @@ The Access Nodes APIs hosted by DapperLabs are accessible at: - Local Emulator `127.0.0.1:3569` Example: -``` -flow emulator + +```py +async with flow_client( + host="127.0.0.1", port="3569" + ) as flow_client: + # do something with `flow_client` ``` ## Querying the Flow Network After you have established a connection with an access node, you can query the Flow network to retrieve data about blocks, accounts, events and transactions. We will explore how to retrieve each of these entities in the sections below. ### Get Blocks -[]() // TODO specs here +[](./api_docs/client.md#query-blocks) Query the network for block by id, height or get the latest block. @@ -66,7 +66,7 @@ Query the network for block by id, height or get the latest block. This example depicts ways to get the latest block as well as any other block by height or ID: -**[]()** // TODO link to example +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/block_examples.py)** You can use the `GetLatestBlock` method to fetch the latest sealed or unsealed block: @@ -126,7 +126,7 @@ Block timestamp: [2021-10-28 14:12:41.172587+00:00] ``` ### Get Account -[]() // TODO specs here +[](./api_docs/client.md#accounts) Retrieve any account from Flow network's latest block or from a specified block height. @@ -141,7 +141,7 @@ An account includes the following data: #### Examples Example depicts ways to get an account at the latest block and at a specific block height: -**[]()** // TODO example link +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/account_examples.py)** Get an account using its address. ```python @@ -205,7 +205,7 @@ Account Keys: 1 ### Get Transactions -[]() // TODO specs here +[](./api_docs/client.md#accounts) Retrieve transactions from the network by providing a transaction ID. After a transaction has been submitted, you can also get the transaction result to check the status. @@ -225,7 +225,7 @@ Retrieve transactions from the network by providing a transaction ID. After a tr | EXPIRED | ✅ | The transaction reference block is outdated before being executed | -**[]()** // TODO example link +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/transactions_examples.py)** ```python async def run(self, ctx: Config): @@ -281,7 +281,7 @@ transaction script: transaction(){prepare(){log("OK")}} ### Get Events -[]() // TODO specs here +[](./api_docs/client.md#events) Retrieve events by a given type in a specified block height range or through a list of block IDs. @@ -298,7 +298,7 @@ core events, and you should read more about them in [this document](https://docs #### Examples Example depicts ways to get events within block range or by block IDs: -**[]()** // TODO example link +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/events_examples.py)** This example shows how to retrieve events by name in the block height range Class. In this example, an account is created and then we try to get "AccountCreated" event. @@ -406,14 +406,19 @@ event type: A.0dbaa95c7691bc4f.EventDemo.Add event value: A.0dbaa95c7691bc4f.EventDemo.Add(x: 1, y: 6, sum: 7) event value: dfc8c1ea51279ddc74c16ed7644361dbe4828181d56497a4ebb18a6bbf0fd574 ``` + ### Get Collections -[]() // TODO specs here +[](./api_docs/client.md#collections) Retrieve a batch of transactions that have been included in the same block, known as ***collections***. Collections are used to improve consensus throughput by increasing the number of transactions per block and they act as a link between a block and a transaction. 📖 **Collection ID** is SHA3-256 hash of the collection payload. +#### Examples + +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/collections_examples.py)** + ```python async def run(self, ctx: Config): async with flow_client( @@ -438,7 +443,7 @@ Transactions: [d3a6b0cb53dfc72c38f365bb177a327c2bae8d4a6076a2909fc11d8f95510396] ``` ### Execute Scripts -[]() // TODO specs here +[](./api_docs/client.md#scripts) Scripts allow you to write arbitrary non-mutating Cadence code on the Flow blockchain and return data. You can learn more about [Cadence and scripts here](https://docs.onflow.org/cadence/language/), but we are now only interested in executing the script code and getting back the data. @@ -448,7 +453,7 @@ We can execute a script using the latest state of the Flow blockchain or we can 📖 **Block height** expresses the height of the block in the chain. -**[]()** // TODO example link +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/scripts_examples.py)** ``` // simple script pub fun main(a: Int): Int { @@ -603,7 +608,7 @@ A transaction will be rejected if it is submitted past its expiry block. Flow ca A transaction expires after `600` blocks are committed on top of the reference block, which takes about 10 minutes at average Mainnet block rates. ### Build Transactions -[]() // TODO specs here +[](./api_docs/client.md#transactions) Building a transaction involves setting the required properties explained above and producing a transaction object. @@ -624,7 +629,7 @@ transaction(greeting: String) { } ``` -**[]()** // TODO example link +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/transactions_examples.py)** ```python transaction = Tx( code="""transaction(){prepare(){log("OK")}}""", @@ -640,7 +645,7 @@ transaction = Tx( After you have successfully [built a transaction](#build-transactions) the next step in the process is to sign it. ### Sign Transactions -[]() // TODO specs here +[](./api_docs/signer.md) Flow introduces new concepts that allow for more flexibility when creating and signing transactions. Before trying the examples below, we recommend that you read through the [transaction signature documentation](https://docs.onflow.org/concepts/accounts-and-keys/). @@ -719,7 +724,7 @@ Flow supports great flexibility when it comes to transaction signing, we can def | ------- | ------ | ------ | | `0x01` | 1 | 1.0 | -**[](https://github.com/onflow/flow-go-sdk/tree/master/examples#single-party-single-signature)** +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/transactions_examples.py)** ```python async def run(self, ctx: Config): address = Address.from_hex("0x01") @@ -768,7 +773,7 @@ async def run(self, ctx: Config): | `0x01` | 1 | 0.5 | | `0x01` | 2 | 0.5 | -**[](https://github.com/onflow/flow-go-sdk/tree/master/examples#single-party-multiple-signatures)** +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/transactions_examples.py)** ```python async def run(self, ctx: Config): address = Address.from_hex("0x01") @@ -825,7 +830,7 @@ async def run(self, ctx: Config): | `0x01` | 1 | 1.0 | | `0x02` | 3 | 1.0 | -**[](https://github.com/onflow/flow-go-sdk/tree/master/examples#multiple-parties)** +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/trasnactions_examples.py)** ```python async def run(self, ctx: Config): # First Step : Create a client to connect to the flow blockchain @@ -886,7 +891,7 @@ async def run(self, ctx: Config): | `0x01` | 1 | 1.0 | | `0x02` | 3 | 1.0 | -**[](https://github.com/onflow/flow-go-sdk/tree/master/examples#multiple-parties-two-authorizers)** +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/transactions_examples.py)** ```python async def run(self, ctx: Config): # First Step : Create a client to connect to the flow blockchain @@ -949,7 +954,7 @@ async def run(self, ctx: Config): | `0x02` | 3 | 0.5 | | `0x02` | 4 | 0.5 | -**[]()** // TODO example link +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/transactions_examples.py)** ```python async def run(self, ctx: Config): # First Step : Create a client to connect to the flow blockchain @@ -1013,12 +1018,12 @@ async def run(self, ctx: Config): ### Send Transactions -[]() // TODO reference here +[](./api_docs/client.md#transactions) After a transaction has been [built](#build-transactions) and [signed](#sign-transactions), it can be sent to the Flow blockchain where it will be executed. If sending was successful you can then [retrieve the transaction result](#get-transactions). -**[]()** // TODO example here +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/transactions_examples.py)** ```python async def run(self, ctx: Config): async with flow_client( @@ -1051,7 +1056,7 @@ async def run(self, ctx: Config): ``` ### Create Accounts -[]() // TODO reference here +**[](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/account_examples.py)** On Flow, account creation happens inside a transaction. Because the network allows for a many-to-many relationship between public keys and accounts, it's not possible to derive a new account address from a public key offline. @@ -1299,7 +1304,7 @@ async def run(self, ctx: Config): ``` ### Generate Keys -[]() // TODO reference here +[](./api_docs/keys.md#generate-new-keys) Flow uses [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) signatures to control access to user accounts. Each key pair can be used in combination with the `SHA2-256` or `SHA3-256` hashing algorithms. diff --git a/docs/querying_events.mdx b/docs/querying_events.mdx deleted file mode 100644 index 0b41b12..0000000 --- a/docs/querying_events.mdx +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Querying Events -description: How to query events using the Flow python SDK -contentType: HOWTO ---- - -An event is emitted as the result of a transaction execution. Events are either user-defined events originating from a Cadence smart contract, or built-in Flow system events. -An event contains the following fields: - -- `type` - Fully-qualified unique type identifier for the event. -- `transaction_id` - ID of the transaction the event was emitted from. -- `transaction_index` - Zero-based index of the transaction within the block. -- `event_index` - Zero-based index of the event within the transaction. -- `payload` - Event fields encoded as JSON-Cadence values. - -You can query events with the `get_events_for_height_range` function or at a specific block using `get_events_for_block_i_ds` : -## query events with the `get_events_for_height_range` function: - -```python -async def run(self, ctx: Config): - # First Step : Create a client to connect to the flow blockchain - # flow_client function creates a client using the host and port - async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - events = await client.get_events_for_height_range( - type = "", start_height = 0, end_height = 0 - ) - print("Events :\n") - print(events) -``` -note: -If `start_height` is greater than the current sealed chain height, then this method will return an error. -If `end_height` is greater than the current sealed chain height, then this method will return events up to and including the latest sealed block. - - -### `get_events_for_height_range` parameters - -An event query includes the following fields: - -**Type** - -The event type to filter by. Event types are namespaced by the account and contract in which they are declared. - -For example, a `Transfer` event that was defined in the `Token` contract deployed at account `0x55555555555555555555` will have a type of `A.0x55555555555555555555.Token.Transfer`. - -Read the [language documentation](https://docs.onflow.org/cadence/language/events/) for more information on how to define and emit events in Cadence. - -**StartHeight, EndHeight** - -The blocks to filter by. Events will be returned from blocks in the range `StartHeight` to `EndHeight`, inclusive. - -## query events with the `get_events_for_block_i_ds` function: - -```python -async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - latest_block = await client.get_latest_block() - events = await client.get_events_for_block_i_ds( - type = "", block_ids = [latest_block.id] - ) - print("Events :\n") - print(events) -``` \ No newline at end of file diff --git a/docs/retrieving_blocks.mdx b/docs/retrieving_blocks.mdx deleted file mode 100644 index f015030..0000000 --- a/docs/retrieving_blocks.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Retrieving Blocks -description: How to retrieve blocks using the Flow Python SDK -contentType: HOWTO ---- - -A block contains the following fields: - -- `ID` - The ID (hash) of the block. -- `ParentBlockID` - The ID of the previous block in the chain. -- `Height` - The height of the block in the chain. -- `CollectionGuarantees` - The list of collections included in the block. -- `BlockSeal` - The list of block seals. -- `signatures` - BLS signatures of consensus nodes. - -You can use the `GetLatestBlock` method to fetch the latest sealed or unsealed block: - -```python -# First Step : Create a client to connect to the flow blockchain -# flow_client function creates a client using the host and port -async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - block = await client.get_latest_block( - is_sealed = False - # or is_sealed = True can be used for retrieving sealed block - ) - print("Block :\n") - print(block.__dict__) -``` -You can use the `get_block_by_i_d` method to fetch the specific block with desired ID: - -```python -async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port -) as client: - latest_block = await client.get_latest_block() - block = await client.get_block_by_height( - height = latest_block.height - ) - print("Block :\n") - print(block.__dict__) -``` -Also `get_block_by_height` method can be used to fetch the specific block with desired height: - -```python -async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port -) as client: - latest_block = await client.get_latest_block() - block = await client.get_block_by_height( - height = latest_block.height - ) - print("Block :\n") - print(block.__dict__) -``` \ No newline at end of file diff --git a/docs/retrieving_collections.mdx b/docs/retrieving_collections.mdx deleted file mode 100644 index 04de612..0000000 --- a/docs/retrieving_collections.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Retrieving collections -description: How to retrieve collections using the Flow python SDK -contentType: HOWTO ---- - -A collection is a batch of transactions that have been included in a block. Collections are used to improve consensus throughput by increasing the number of transactions per block. -A collection contains the following fields: - -- `id` - SHA3-256 hash of the collection contents. -- `transaction_ids` - Ordered list of transaction IDs in the collection. - -## retrieve collections using the `get_collection_by_i_d` function: - -```python -async with flow_client( - host=ctx.access_node_host, port=ctx.access_node_port - ) as client: - collection = await client.get_collection_by_i_d( - id = bytes.fromhex(collection_id) - ) - print("Collection :\n") - print(collection.__dict__) -``` \ No newline at end of file diff --git a/docs/roadmap.md b/docs/roadmap.md index 1b28d95..34dce2c 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,45 +1,3 @@ # Roadmap -⛏️ WIP - -## MVP Roadmap - -Items that need to be addressed for `flow-py-sdk` to be considered usable. At which point it will become V1. Any [contributions](./contributing.md) to items on this list (or not on the list and you think they should be) are very welcome. - -### Docs - -- [x] Create docs folder - - [x] setup mkdocs -- [ ] Usage example docs: - - [ ] create account - - [ ] transfer flow -- [ ] contribution docs - -### Examples - -- [x] move examples folder to root folder -- [x] make each example runnable separately -- [x] write instructions for running examples -- [ ] add more comments to examples -- [x] add examples to ci -- [ ] add more examples - -### Tests - -- [x] add cadence decode/encode tests -- [ ] add more tests -- [x] add CI for tests - -### CI - -- [x] release automation - -### Implementation - -- [x] decode event payload from grpc -- [x] implement TODOs in cadence decode/encode - - -## Future roadmap - See the issues open in the github [milestones](https://github.com/janezpodhostnik/flow-py-sdk/milestones) \ No newline at end of file diff --git a/docs/scripts.md b/docs/scripts.md deleted file mode 100644 index 35e3f29..0000000 --- a/docs/scripts.md +++ /dev/null @@ -1,101 +0,0 @@ -# Scripts - -Cadence scripts can be used to get information from the Flow blockchain. - -You can see scripts in action in the -examples [here](https://github.com/janezpodhostnik/flow-py-sdk/blob/master/examples/script_examples.py). - -## Sending scripts - -To following code can be used to send a script to an access node or the emulator. - -```py -from flow_py_sdk import flow_client, Script - -# ... - -async with flow_client(host=access_node_host, port=access_node_port) as client: - script = Script( - code=""" - pub fun main() { - let a = 1 - let b = 1 - log(a + b) - } - """ - ) - await client.execute_script(script) -``` - -When sending this script to an emulator, the log output will be visible in the emulator output. - -## Getting script results - -The return value of `client.execute_script` is the script result if the script returns a result. -The type of the result is an abstract `cadence.Value`. - -```py -async with flow_client(host=access_node_host, port=access_node_port) as client: - script = Script( - code=""" - pub fun main(): Int { - let a = 1 - let b = 1 - return a + b - } - """ - ) - result = await client.execute_script(script) - a_plus_b = result.as_type(cadence.Int).value -``` - -## Sending scripts with parameters - -To execute scripts with arguments (parameters) two approaches can be used. - -By using `__init__` parameters. - -```py -async with flow_client(host=access_node_host, port=access_node_port) as client: - script = Script( - code=""" - pub fun main(a: Int, b: Int) { - log(a + b) - } - """, - arguments=[cadence.Int(1), cadence.Int(1)] - ) - await client.execute_script(script) -``` - -By using `add_arguments`. - -```py -async with flow_client(host=access_node_host, port=access_node_port) as client: - script = Script( - code=""" - pub fun main(a: Int, b: Int) { - log(a + b) - } - """ - ).add_arguments(cadence.Int(1), cadence.Int(1)) - - await client.execute_script(script) -``` - -`add_arguments` can also be used to add one argument at a time. - -```py -async with flow_client(host=access_node_host, port=access_node_port) as client: - script = Script( - code=""" - pub fun main(a: Int, b: Int) { - log(a + b) - } - """ - ).add_arguments(cadence.Int(1)).add_arguments(cadence.Int(1)) - - await client.execute_script(script) -``` - -All arguments ned to be a `cadence.Value` otherwise a `NotCadenceValueError` is raised. \ No newline at end of file diff --git a/docs/sdk-banner.svg b/docs/sdk-banner.svg deleted file mode 100644 index bf4f567..0000000 --- a/docs/sdk-banner.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/transactions.md b/docs/transactions.md deleted file mode 100644 index 9572c16..0000000 --- a/docs/transactions.md +++ /dev/null @@ -1,3 +0,0 @@ -# Transactions - -⛏️ WIP \ No newline at end of file diff --git a/docs/usage.md b/docs/usage.md deleted file mode 100644 index b48ca2a..0000000 --- a/docs/usage.md +++ /dev/null @@ -1,6 +0,0 @@ -# Usage Overview - - - - - diff --git a/flow_py_sdk/__init__.py b/flow_py_sdk/__init__.py index 5f46c7b..0d41954 100644 --- a/flow_py_sdk/__init__.py +++ b/flow_py_sdk/__init__.py @@ -1,6 +1,6 @@ import logging -from .client import flow_client, AccessAPI +from .client import flow_client, AccessAPI, entities from .script import Script from .exceptions import PySDKError, NotCadenceValueError from .signer import SignAlgo, HashAlgo, InMemorySigner, Signer diff --git a/flow_py_sdk/client/entities.py b/flow_py_sdk/client/entities.py index 3dc4f1c..6ebe5fd 100644 --- a/flow_py_sdk/client/entities.py +++ b/flow_py_sdk/client/entities.py @@ -1,8 +1,8 @@ import json -from dataclasses import dataclass from datetime import datetime from typing import Dict, List +from flow_py_sdk import cadence from flow_py_sdk.account_key import AccountKey from flow_py_sdk.cadence import cadence_object_hook from flow_py_sdk.proto.flow import entities, access @@ -103,7 +103,6 @@ def from_proto(cls, proto: entities.BlockSeal) -> "BlockSeal": ) -@dataclass class Block(object): def __init__( self, diff --git a/mkdocs.yml b/mkdocs.yml index 68934b2..321119f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -3,20 +3,24 @@ theme: material plugins: - search - - mkdocstrings + - mkdocstrings: + handlers: + python: + rendering: + show_root_heading: True + show_root_full_path: False + show_if_no_docstring: True + show_signature_annotations: True + heading_level: 3 nav: - - Overview: index.md - - Installation: installation.md - - 'Usage Overview': usage.md - - Examples: examples.md - - Concepts: - - Scripts: scripts.md - - Transactions: transactions.md - - 'Cadence Types': cadence_types.md - - Events: events.md + - Overview: python_SDK_guide.md + - 'Running Examples': examples.md + - 'API Docs': + - Client: api_docs/client.md + - Signer: api_docs/signer.md + - Keys: api_docs/keys.md - Contributing: contributing.md - - 'Working with the Flow emulator': emulator.md - Roadmap: roadmap.md markdown_extensions: From 6975b7e0591b620819df5a3d08118d4f59fc8b22 Mon Sep 17 00:00:00 2001 From: Janez Podhostnik Date: Sat, 6 Nov 2021 15:21:28 +0000 Subject: [PATCH 3/3] Update readme --- README.md | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index f7f6169..19dc182 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The Flow Python SDK provides a set of packages for Python developers to build ap [![codecov](https://codecov.io/gh/janezpodhostnik/flow-py-sdk/branch/master/graph/badge.svg)](https://codecov.io/gh/codecov/example-go) -See the [guide](./docs/python_SDK_guide.md)! +See the [guide](https://janezpodhostnik.github.io/flow-py-sdk)! Note: This SDK is also fully compatible with the Flow Emulator and can be used for local development. @@ -29,20 +29,10 @@ or if using poetry: poetry add flow-py-sdk ``` -## Run examples +## Contributors -To run example first you need to install flow emulator and run it locally. + + + -[go step-by-step based on your OS](https://github.com/onflow/flow-cli#flow-cli) - -then install dependencies. to install dependencies of flow SDk run: - -`poetry install` - -after that run flow emulator in example directory, using: - -`flow emulator` - -and then you can run examples using: - -`poetry run examples` +Made with [contrib.rocks](https://contrib.rocks). \ No newline at end of file