Substrate API Sidecar

Parity maintains an RPC client, written in TypeScript, that exposes a limited set of endpoints. It handles the metadata and codec logic so that you are always dealing with decoded information. It also aggregates information that a business may need for accounting and auditing (e.g. transaction fees).

The sidecar facilitates the following operations:

  • Fetch blocks

  • Get the balance of an address atomically (i.e., with a corresponding block number)

  • Get the chain's metadata

  • Get a transaction fee prediction

  • Calculate outstanding staking rewards for an address

  • Submit transactions to a node's transaction queue

  • etc.

The client runs on an HTTP host. The following examples use python3, but you can query any way you prefer at http://HOST:PORT/. The default is http://127.0.0.1:8080.

Fetching a Block

Fetch a block using theblock/numberendpoint. To get the chain tip, omit the block number.

import requests
import json

url = 'http://127.0.0.1:8080/block/2077200'
response = requests.get(url)
if response.ok:
    block_info = json.loads(response.text)
    print(block_info)

This returns a fully decoded block. In thebalances.transferextrinsic, the partialFee item is the transaction fee. It is called a "partial fee" because the total fee would include thetipfield. Notice that some extrinsics do not have a signature. These are inherents.

When tracking transaction fees, theextrinsics.paysFeevalue is not sufficient for determining if the extrinsic had a fee. This field only means that it would require a fee if submitted as a transaction. In order to charge a fee, a transaction also needs to be signed. So in the following example, thetimestamp.setextrinsic does not pay a fee because it is an inherent, put in the block by the block author.

{'number': '1419394', 'hash': '0xaa4ebb82c0fe2a0afddb02872f6fd72cc9b68de1990e54d351d8152da040681e','parentHash':'0x9022a1fe7192366553c0caa3e1d0d9f7d9fd2eab601ea4a26e49ba66375fb735','stateRoot':'0x6b4c0b81bc86e3104ea15b38e457e9f2d2395d997a8737a7072c2c1b2aa057ce','extrinsicsRoot':'0x9a66295996ccfab5b71924f1816a68854bfa4bae92e196770235b8c5ebf67f8a','authorId': '15V6NjwmKkZihe644Tyr8GVLxjEzBAHktf6ZcJCTx7RPCoYS','logs': [{'type': 'PreRuntime','index': '6','value': ['BABE','0x03a0000000be9ce20f000000001815f7649023d7af85be14fe902084fec2bf2bc10175b6c49f5fd37556b58f7b128e4c1de5d4b6df0ef5bcd817b8c2337a381b9e15bdb3b9a831a1308cf797091484ae9f861b7978852164dd018b4dddd6ef7e438a8d2d9b5644567ebec9700d']},{'type': 'Seal','index': '5','value': ['BABE','0x5809634ab178c8484724b19f07035510dd6e6457bfa0423ba74887d67bc4b135713d926a93d62e76950f31750aabd57f93065b6fad273fb77e84b3185645a58d']}],'onInitialize': {'events': []},'extrinsics': [{'method': 'timestamp.set','signature': None,'nonce': '0','args': {'now': '1599057012000'},'tip': '0','hash': '0x830017ff2f8971d488ae4d35c851c389ce74271c4c1daf8aea70baffda018a0b','info': {},'events': [{'method': 'system.ExtrinsicSuccess','data': [{'weight': '158000000','class': 'Mandatory','paysFee': 'Yes'}]}],'success': True,'paysFee': True},{'method': 'parachains.setHeads','signature': None,'nonce': '0','args': {'heads': []},'tip': '0','hash': '0xcf52705d1ade64fc0b05859ac28358c0770a217dd76b75e586ae848c56ae810d','info': {},'events': [{'method': 'system.ExtrinsicSuccess','data': [{'weight': '1000000000','class': 'Mandatory','paysFee': 'Yes'}]}],'success': True,'paysFee': True},{'method': 'staking.bondExtra','signature': {'signature': '0x92b50d7d4317503971f5f670a88adfe1e8e3e5aa4ba62c1d8792590abfd4805dad8ac8d442af8610236af7c3c48269d9487584486dca684dd6b89aed4c7f3d83','signer': '15x3TLV67TVAde2pcuQsNCs8KNWGG769UvzjfNtzex9mL6Ld'},'nonce': '2','args': {'max_additional': '1000000000000'},'tip': '0','hash': '0xab2b0a862a7d4c18a1f7294d2db181af3a7fe00bde70de88b61cefe4f9f74012','info': {'weight': '355000000','class': 'Normal','partialFee': '122000000'},'events': [{'method': 'staking.Bonded','data': ['15x3TLV67TVAde2pcuQsNCs8KNWGG769UvzjfNtzex9mL6Ld','1000000000000']},{'method': 'treasury.Deposit', 'data': ['97600000']},{'method': 'balances.Deposit','data': ['15V6NjwmKkZihe644Tyr8GVLxjEzBAHktf6ZcJCTx7RPCoYS', '24400000']},{'method': 'system.ExtrinsicSuccess','data': [{'weight': '355000000', 'class': 'Normal', 'paysFee': 'Yes'}]}],'success': True,'paysFee': True},{'method': 'balances.transfer','signature': {'signature': '0x5c63107916871286a946c8d06052a0ac7c50c6a052c5a9dee87f26dce3dac64a18f24cf07a4de69dc56733ad9e0a2aa5b95a11428203ed32603c22544369d902','signer': '1JVrK16XZm9vyZjHoYVPjtZ35LvTQ4oyufMoUFTFpAUhath'},'nonce': '3017','args': {'dest': '12YFp3fPi73U3pwRqK9Hwa1iVhaGSTq3e3XaTbM5UfuP1LpX','value': '18539953920000'},'tip': '0','hash': '0x0e7692706202dad75c2a468aff6bf78b88d505ef7031b82b6e9d5220817f082b','info': {'weight': '195000000','class': 'Normal','partialFee': '156000000'},'events': [{'method': 'balances.Transfer','data': ['1JVrK16XZm9vyZjHoYVPjtZ35LvTQ4oyufMoUFTFpAUhath','12YFp3fPi73U3pwRqK9Hwa1iVhaGSTq3e3XaTbM5UfuP1LpX','18539953920000']},{'method': 'treasury.Deposit', 'data': ['124800000']},{'method': 'balances.Deposit','data': ['15V6NjwmKkZihe644Tyr8GVLxjEzBAHktf6ZcJCTx7RPCoYS', '31200000']},{'method': 'system.ExtrinsicSuccess','data': [{'weight': '195000000', 'class': 'Normal', 'paysFee': 'Yes'}]}],'success': True,'paysFee': True}], 'onFinalize': {'events': []}} The JS number type is a 53-bit precision float. There is no guarantee that the numerical values in the response will have a numerical type. Any numbers larger than2**53-1will have a string type.

Submitting a transaction

Submit a serialized transaction using the tx endpoint with an HTTP POST request.

import requests
import json

url = 'http://127.0.0.1:8080/tx/'
tx_headers = {'Content-type' : 'application/json', 'Accept' : 'text/plain'}
response = requests.post(
    url,
    data='{"tx": "0xed0...000"}', # A serialized tx.
    headers=tx_headers
)
tx_response = json.loads(response.text)

If successful, this endpoint returns a JSON with the transaction hash. In case of error, it will return an error report, e.g.:

{ "error": "Failed to parse a tx" | "Failed to submit a tx", "cause": "Upstream error description" }

β€Œ

Last updated