Skip to main content

Using Substrate API Sidecar with Elysium

Substrate API Sidecar allows applications to access blocks, account balance, and other information of Substrate-based blockchains through a REST API. This can be useful for exchanges, wallets or other types of applications that need to keep track of account balance and other state changes on a Elysium network. This page will describe how to install and run a Substrate API Sidecar for Elysium, and the commonly used API endpoints.

Installing and Running Substrate API Sidecar

There are multiple ways of installing and running the Substrate API Sidecar. This guide will describe the steps for installing and running it locally through NPM. For running Substrate API Sidecar through Docker, or building and running it from source, please refer to the Substrate API Sidecar Github Repository.

Checking Prerequisites

Running this service locally through NPM requires Node.js to be installed.

You need to install Node.js (for this example, you can use v16.x) and the npm package manager. You can download directly from Node.js or in your terminal:

Ubuntu

curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -

sudo apt install -y nodejs

MacOs

# You can use homebrew (https://docs.brew.sh/Installation)
brew install node

# Or you can use nvm (https://github.com/nvm-sh/nvm)
nvm install node

You can verify that everything is installed correctly by querying the version for each package:

node -v
npm -v

Installing the Substrate API Sidecar

To install the Substrate API Sidecar service locally in the current directory, run this from the command line:

npm install @substrate/api-sidecar@{{ networks.elysium.substrate_api_sidecar.stable_version }}

NOTE: If the current folder does not already have a Node.js project structure, you need to manually created the node_modules directory by typing mkdir node_modules.

Substrate API Sidecar v{{ networks.elysium.substrate_api_sidecar.stable_version }} is the current stable version that has been tested to work with Elysium networks. You can verify the installation was successful by typing from the installation directory root:

node_modules/.bin/substrate-api-sidecar --version

Setting up the Substrate API Sidecar

In the terminal that Sidecar will run, export the environmental variable for the WS endpoint of the network. Examples:

export SAS_SUBSTRATE_URL=wss://ws.elysiumchain.tech

Please reference the Public Endpoints page for a full list of Elysium network endpoints.

After setting the environmental variable, you can use the echo command to check that the environmental variable has been set correctly, by typing:

echo $SAS_SUBSTRATE_URL

And it should display the network endpoint you have just set.

Running Substrate API Sidecar

With the network endpoint environmental variable set, and from the installation directory root, run:

node_modules/.bin/substrate-api-sidecar 

Substrate API Sidecar Endpoints

Some of the commonly used Substrate API Sidecar endpoints include:

  • GET /blocks​/head — Get the most recently finalized block. The optional parameter finalized can be set to false to the get the newest known block, which may not be finalized.
  • GET /blocks/head/header — Get the most recently finalized block header. The optional parameter finalized can be set to false to the get the newest known block header, which may not be finalized.
  • GET /blocks/{blockId} — Get a block by its height or hash.
  • GET /accounts/{accountId}/balance-info — Get balance information for an account.
  • GET /node/version — Get information about the Substrates node's implementation and versioning.
  • GET /runtime/metadata — Get the runtime metadata in decoded, JSON form.

For a full list of API endpoints available on Substrate API Sidecar, please refer to the official documentation.

EVM Field Mapping in Block JSON Object

Substrate API Sidecar returns Elysium blocks as a JSON object. Information related to EVM execution of Elysium transactions is under the extrinsics top level field, where individual extrinsics are organized numerically as nested JSON objects. The nesting structure is as following:

RESPONSE JSON Block Object:
|--extrinsics
|--{extrinsic_number}
|--method
|--pallet: "ethereum"
|--method: "transact"
|--signature
|--nonce
|--args
|--transaction
|--{
transaction_type
}
|--hash
|--events
|--{event_number}
|--method
|--pallet: "ethereum"
|--method: "Executed"
|--data
|--0
|--1
|--2
|--3
...

Elysium EVM transactions can be identify by the method field under the current extrinsic object, where it is set to:

{extrinsic_number}.method.pallet = "ethereum"
{extrinsic_number}.method.method = "transact"

Transaction Types and Payload

The Elysium EVM currently supports three transaction standards: legacy, eip1559, and eip2930. These correspond to the transaction type field in the above JSON object diagram. For each transaction type, the transaction payload contains the following fields:

EIP1559

...
|--eip1559
|--chainId
|--nonce
|--maxPriorityFeePerGas
|--maxFeePerGas
|--gasLimit
|--action
|--value
|--input
|--accessList
|--oddYParity
|--r
|--s
...

Legacy

...
|--legacy
|--nonce
|--gasPrice
|--gasLimit
|--action
|--value
|--input
|--signature
...

EIP2930

...
|--eip2930
|--chainId
|--nonce
|--gasPrice
|--gasLimit
|--action
|--value
|--input
|--accessList
|--oddYParity
|--r
|--s
...

For more information on the new EIP1559 and EIP2930 transaction types and what each field means, please refer to the respective official Ethereum proposal specs.

Transaction Field Mappings

To obtain the EVM sender address, recipient address, and EVM hash of any EVM transaction type, check the events field under the current extrinsic object, and identify the event where the method field is set to:

{event_number}.method.pallet: "ethereum"
{event_number}.method.method: "Executed"

The EVM field mappings are then summarized as the following:

EIP1559

EVM FieldBlock JSON Field
Chain IDextrinsics[extrinsic_number].args.transaction.eip1559.chainId
Nonceextrinsics[extrinsic_number].args.transaction.eip1559.nonce
Max priority fee per gasextrinsics[extrinsic_number].args.transaction.eip1559.maxPriorityFeePerGas
Max fee per gasextrinsics[extrinsic_number].args.transaction.eip1559.maxFeePerGas
Gas limitextrinsics[extrinsic_number].args.transaction.eip1559.gasLimit
Access listextrinsics[extrinsic_number].args.transaction.eip1559.accessList
Signatureextrinsics[extrinsic_number].args.transaction.eip1559.oddYParity/r/s
Sender addressextrinsics[extrinsic_number].events[event_number].data[0]
Recipient addressextrinsics[extrinsic_number].events[event_number].data[1]
EVM hashextrinsics[extrinsic_number].events[event_number].data[2]
EVM execution statusextrinsics[extrinsic_number].events[event_number].data[3]

Legacy

EVM FieldBlock JSON Field
Nonceextrinsics[extrinsic_number].args.transaction.legacy.nonce
Gas priceextrinsics[extrinsic_number].args.transaction.legacy.gasPrice
Gas limitextrinsics[extrinsic_number].args.transaction.legacy.gasLimit
Valueextrinsics[extrinsic_number].args.transaction.legacy.value
Signatureextrinsics[extrinsic_number].args.transaction.legacy.signature
Sender addressextrinsics[extrinsic_number].events[event_number].data[0]
Recipient addressextrinsics[extrinsic_number].events[event_number].data[1]
EVM hashextrinsics[extrinsic_number].events[event_number].data[2]
EVM execution statusextrinsics[extrinsic_number].events[event_number].data[3]

EIP2930

EVM FieldBlock JSON Field
Chain IDextrinsics[extrinsic_number].args.transaction.eip2930.chainId
Nonceextrinsics[extrinsic_number].args.transaction.eip2930.nonce
Gas priceextrinsics[extrinsic_number].args.transaction.eip2930.gasPrice
Gas limitextrinsics[extrinsic_number].args.transaction.eip2930.gasLimit
Valueextrinsics[extrinsic_number].args.transaction.eip2930.value
Access listextrinsics[extrinsic_number].args.transaction.eip2930.accessList
Signatureextrinsics[extrinsic_number].args.transaction.eip2930.oddYParity/r/s
Sender addressextrinsics[extrinsic_number].events[event_number].data[0]
Recipient addressextrinsics[extrinsic_number].events[event_number].data[1]
EVM hashextrinsics[extrinsic_number].events[event_number].data[2]
EVM execution statusextrinsics[extrinsic_number].events[event_number].data[3]

NOTE: For Substrate transactions, the "Nonce" and "Signature" fields are under extrinsics[extrinsic_number]. For EVM transactions, the "Nonce" and "Signature" fields are under extrinsics[extrinsic_number].args.transaction[transaction_type], leaving the "Nonce" and "Signature" under extrinsics[extrinsic_number] to be null. A successfully executed EVM transaction will return either succeed: "Stopped" or succeed: "Returned" under the " EVM Execution Status" field.

ERC-20 Token Transfers

Events emitted by smart contracts such as an ERC-20 token contract deployed on Elysium can be decoded from Sidecar block JSON objects. The nesting structure is as following:

RESPONSE JSON Block Object:
|--extrinsics
|--{extrinsic_number}
|--method
|--pallet: "ethereum"
|--method: "transact"
|--signature:
|--nonce: |--args
|--transaction
|--{transaction_type
}
|--hash
|--events
|--{
event_number}
|--method
|--pallet: "evm"
|--method: "Log"
|--data
|--0
|-- address
|-- topics
|--0
|--1
|--2
|-- data
...
...

Elysium ERC-20 token transfers will emit the Transfer event which can be decoded as the following:

Tx InformationBlock JSON Field
ERC-20 contract addressextrinsics[extrinsic_number].events[event_number].data[0].address
Event signature hashextrinsics[extrinsic_number].events[event_number].data[0].topics[0]
Sender addressextrinsics[extrinsic_number].events[event_number].data[0].topics[1]
Recipient addressextrinsics[extrinsic_number].events[event_number].data[0].topics[2]
Amountextrinsics[extrinsic_number].events[event_number].data[0].data

Other events emitted by EVM smart contracts can be decoded in a similar fashion, but the content of the topics and data fields will change depending on the definition of the specific event.

NOTE: The amount transferred is given in Wei and in hexadecimal format.

Sample Code for Monitoring Native Token Transfers

The Transfers API page has a code snippet demonstrating how to use Substrate API Sidecar to retrieve and decode native token transfers sent with both Substrate and Ethereum APIs on Elysium networks. You can reference that as a starting point to build out backends that utilize Sidecar to listen to transfers on Elysium networks.

Calculating Transaction Fees

For more detailed information and sample code on how to calculate the transaction fees of Elysium transactions using Substrate Sidecar API, please check the Calculating Transaction Fees on Elysium page.