# Polkadot Manual WiP ## Abstract Polkadot is Substrate based chain. A block in Substrate is composed of a **header** and an array of [**extrinsics**](https://substrate.dev/docs/en/knowledgebase/learn-substrate/extrinsics). The **header** contains: - block height - parent hash - extrinsics root - state root - digest. **Extrinsics** are bundled together into a block as a series to be executed as each is defined in the runtime. The *extrinsics root* is a cryptographic digest of this series. This serves two purposes. First, it prevents any alterations to the series of extrinsics after the header has been built and distributed. Second, it provides a means of allowing light clients to succinctly verify that any given extrinsic did indeed exist in a block given only knowledge of the header. **Extrinsics** fall into three categories: *inherents*, *signed transactions*, and *unsigned transactions*. As a result collecting the transactions for address turns into extrinsics retreival, filtering and processing. Following interfaces can be used to communicate with Subtrate RPC to retreive the blocks and their extrinsics: 1. Polkadot JS API (Javascript) 3. Python Substrate Interface 4. GetBlock.io (any language, is a gateway to Polkadot JS API) ## Polkadot JS API ### Summary The API provides application developers the ability to query a node and interact with the Polkadot or Substrate chains using Javascript. ### Quick Guide #### Installation ```bash yarn add @polkadot/api ``` #### Get head block and its extrinsics ```javascript // Import the API import {ApiPromise, WsProvider} from '@polkadot/api'; async function main () { // Here we don't pass the (optional) provider, connecting directly to the default // node/port, i.e. `ws://127.0.0.1:9944`. Await for the isReady promise to ensure // the API has connected to the node and completed the initialisation process const provider = new WsProvider('wss://rpc.polkadot.io'); // Create the API and wait until ready const api = await ApiPromise.create({ provider }); // Wait for API init await api.isReady; // Get head hash const headHash = await api.rpc.chain.getFinalizedHead(); // Get head block by hash const headBlock = await api.rpc.chain.getBlock(headHash); // Get extrinsics and extrinsics root const {header: {extrinsicsRoot}, extrinsics} = headBlock.block; } main().catch(console.error).finally(() => process.exit()); ``` ### Useful Links [API Overview](https://polkadot.js.org/docs/api) [Substrate JSON-RPC](https://polkadot.js.org/docs/substrate/rpc) ## Python Substrate Interface ### Summary This library specializes in interfacing with a Substrate node, providing additional convenience methods to deal with SCALE encoding/decoding (the default output and input format of the Substrate JSONRPC), metadata parsing, type registry management and versioning of types. ### Quick Guide #### Installation ```bash pip install substrate-interface ``` #### Initialization ##### Autodiscover mode ```python substrate = SubstrateInterface( url="wss://rpc.polkadot.io" ) ``` When only an `url` is provided, it tries to determine certain properties like `ss58_format` and `type_registry_preset` automatically by calling the RPC method `system_properties`. At the moment this will work for Polkadot, Kusama, Kulupu and Westend nodes, for other chains the `ss58_format` (default 42) and `type_registry` (defaults to latest vanilla Substrate types) should be set manually. ##### Manually set required properties ```python substrate = SubstrateInterface( url="wss://rpc.polkadot.io", ss58_format=0, type_registry_preset='polkadot' ) ``` #### Retrieve extrinsics for a certain block (Method 1: access serialized value) ```python # Set block_hash to None for chaintip block_hash = "0x51d15792ff3c5ee9c6b24ddccd95b377d5cccc759b8e76e5de9250cf58225087" # Retrieve extrinsics in block result = substrate.get_block(block_hash=block_hash) for extrinsic in result['extrinsics']: if 'address' in extrinsic.value: signed_by_address = extrinsic.value['address'] else: signed_by_address = None print('\nPallet: {}\nCall: {}\nSigned by: {}'.format( extrinsic.value["call"]["call_module"], extrinsic.value["call"]["call_function"], signed_by_address )) # Loop through call params for param in extrinsic.value["call"]['call_args']: if param['type'] == 'Balance': param['value'] = '{} {}'.format(param['value'] / 10 ** substrate.token_decimals, substrate.token_symbol) print("Param '{}': {}".format(param['name'], param['value'])) ``` #### Retrieve extrinsics for a certain block (Method 2: access nested objects) ```python # Set block_hash to None for chaintip block_hash = "0x51d15792ff3c5ee9c6b24ddccd95b377d5cccc759b8e76e5de9250cf58225087" # Retrieve extrinsics in block result = substrate.get_block(block_hash=block_hash) for extrinsic in result['extrinsics']: if 'address' in extrinsic: signed_by_address = extrinsic['address'].value else: signed_by_address = None print('\nPallet: {}\nCall: {}\nSigned by: {}'.format( extrinsic["call"]["call_module"].name, extrinsic["call"]["call_function"].name, signed_by_address )) # Loop through call params for param in extrinsic["call"]['call_args']: if param['type'] == 'Balance': param['value'] = '{} {}'.format(param['value'] / 10 ** substrate.token_decimals, substrate.token_symbol) print("Param '{}': {}".format(param['name'], param['value'])) ``` ### Useful Links [Library Repo](https://github.com/polkascan/py-substrate-interface) [Documentation](https://polkascan.github.io/py-substrate-interface/) ## GetBlock.io ### Summary The service provides a gateway to Polkadot API methods. ### Quick Guide #### Authentication with API Key Once you’ve registered at getblock.io, you will get an API key in your account. Use the API key to start interacting with the GetBlock infrastructure. To send YOUR-API-KEY, use x-api-key as a request header (preferred): ```http POST / HTTP/1.1 Host: <SYMBOL>.getblock.io x-api-key: YOUR-API-KEY ``` Or add your [API_KEY] to the request parameters: ```http https://<SYMBOL>.getblock.io/?api_key=YOUR-API-KEY ``` #### API methods (JSON-RPC, REST, WebSockets, etc.) Each node has its own set of methods for interaction with the blockchain network. You can find the documentation for each node supported by GetBlock [here](https://getblock.io/docs/en/nodes-endpoints/). Choose the desired node and press the link with the provided method in the “API Docs” section. For example, you can get information about the last block in the Ethereum network as follows: ```curl curl --location --request POST 'https://eth.getblock.io/mainnet/' \ --header 'x-api-key: <YOUR-API-KEY>' \ --header 'Content-Type: application/json' \ --data-raw '{ "id": "blockNumber", "jsonrpc": "2.0", "method": "eth_getBlockByNumber", "params": ["latest", false] }' ``` #### Get head block Python (Requests, API Key included): ```python import requests url = "https://dot.getblock.io/mainnet/" payload="{\"id\": \"getblock.io\", \"jsonrpc\": \"2.0\", \"method\": \"chain_getFinalizedHead\", \"params\": []}" headers = { 'x-api-key': '662ad343-84e3-4bf9-9bee-de26b475df78', 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) ``` Python (http.client, API Key included): ```python import http.client conn = http.client.HTTPSConnection("dot.getblock.io") payload = "{\"id\": \"getblock.io\", \"jsonrpc\": \"2.0\", \"method\": \"chain_getFinalizedHead\", \"params\": []}" headers = { 'x-api-key': '662ad343-84e3-4bf9-9bee-de26b475df78', 'Content-Type': 'application/json' } conn.request("POST", "/mainnet/", payload, headers) res = conn.getresponse() data = res.read() print(data.decode("utf-8")) ```