Usando o Substrate API Sidecar¶
Introdução¶
O Substrate API Sidecar permite que aplicações acessem blocos, saldos de contas e outras informações de blockchains baseadas em Substrate por meio de uma API REST. Isso é útil para exchanges, carteiras ou outras aplicações que precisam acompanhar saldos e mudanças de estado em uma rede com Tanssi. Esta página descreve como instalar e executar o Sidecar para uma rede Tanssi e os endpoints mais usados.
Instalando e executando o Substrate API Sidecar¶
Há várias formas de instalar e executar o Sidecar. Aqui usamos a instalação local via NPM. Para uso com Docker, ou build a partir do código‑fonte, consulte o repositório oficial.
Note
Os exemplos deste guia partem de um ambiente MacOS ou Ubuntu 20.04. Se estiver usando Windows, adapte os comandos conforme necessário.
Verifique também se você tem o Node.js e um gerenciador de pacotes (como npm ou yarn) instalados. Para saber como instalar o Node.js, consulte a documentação oficial.
Além disso, certifique-se de ter inicializado um arquivo package.json para módulos ES6. Você pode criar um package.json padrão com npm executando npm init --yes.
Instalando o Substrate API Sidecar¶
Para instalar o serviço localmente no diretório atual, execute:
npm install @substrate/api-sidecar@20.2.2
Nota
Se a pasta não tiver um projeto Node.js, crie manualmente node_modules com mkdir node_modules.
A versão estável v20.2.2 foi testada com redes Tanssi. Verifique a instalação a partir da raiz do diretório:
node_modules/.bin/substrate-api-sidecar --version
Configurando o Substrate API Sidecar¶
No terminal em que o Sidecar rodará, exporte a variável de ambiente com o endpoint WSS da rede que deseja usar:
export SAS_SUBSTRATE_URL=wss://services.tanssi-mainnet.network/tanssi
export SAS_SUBSTRATE_URL=wss://services.tanssi-testnet.network/dancelight
export SAS_SUBSTRATE_URL=wss://services.tanssi-testnet.network/dancelight-2001/
export SAS_SUBSTRATE_URL=INSIRA_ENDPOINT_WSS_DA_REDE
Após definir, confirme com:
echo $SAS_SUBSTRATE_URL
Ele deve exibir o endpoint configurado.
Executando o Substrate API Sidecar¶
Com a variável de ambiente definida, a partir da raiz da instalação, execute:
node_modules/.bin/substrate-api-sidecar
Se a instalação e configuração estiverem corretas, verá uma saída semelhante a:
Endpoints do Substrate API Sidecar¶
Alguns endpoints comuns:
- GET /blocks/head — bloco finalizado mais recente. O parâmetro opcional
finalized=falseretorna o bloco mais novo, possivelmente não finalizado - GET /blocks/head/header — cabeçalho do último bloco.
finalized=falseopcional - GET /blocks/{blockId} — bloco por altura ou hash
- GET /accounts/{accountId}/balance-info — saldo e info da conta
- GET /node/version — implementação e versão do nó
- GET /runtime/metadata — metadata do runtime em JSON decodificado
Para a lista completa, consulte a documentação oficial.
Mapeamento de campos em blocos¶
O Sidecar retorna blocos em JSON. Parte do objeto é a estrutura aninhada das extrínsecas processadas:
RESPONSE JSON Block Object:
|--extrinsics
|--{extrinsic_number}
|--method
|--pallet: "MODULE_NAME"
|--method: "METHOD_NAME"
|--signature
|--nonce
|--args
|--transaction
|--{transaction_type}
|--hash
|--events
|--{event_number}
|--method
|--pallet: "MODULE_NAME"
|--method: "METHOD_EVENT_NAME"
|--data
|--0
|--1
|--2
|--3
...
Assim, saber o módulo e método chamados permite extrair informações específicas (por exemplo, transferências de saldo).
Mapeamento EVM em blocos¶
Para redes EVM do Tanssi, as execuções EVM são identificadas por:
{extrinsic_number}.method.pallet = "ethereum"
{extrinsic_number}.method.method = "transact"
Estrutura aninhada:
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
...
Para transações Substrate, campos como “Nonce” e “Signature” ficam em:
extrinsics[extrinsic_number]
Tipos de transação EVM e payload¶
As redes EVM do Tanssi suportam legacy, eip1559 e eip2930. Cada tipo contém o seguinte payload:
...
|--eip1559
|--chainId
|--nonce
|--maxPriorityFeePerGas
|--maxFeePerGas
|--gasLimit
|--action
|--value
|--input
|--accessList
|--oddYParity
|--r
|--s
...
...
|--legacy
|--nonce
|--gasPrice
|--gasLimit
|--action
|--value
|--input
|--signature
...
...
|--eip2930
|--chainId
|--nonce
|--gasPrice
|--gasLimit
|--action
|--value
|--input
|--accessList
|--oddYParity
|--r
|--s
...
Para mais detalhes sobre EIP1559 e EIP2930, consulte as especificações oficiais.
Mapeamento de campos da transação¶
Para obter remetente, destinatário e hash EVM de qualquer transação, verifique o evento com:
{event_number}.method.pallet: "ethereum"
{event_number}.method.method: "Executed"
Mapeamentos:
| Campo EVM | Campo JSON do bloco |
|---|---|
| Chain ID | extrinsics[extrinsic_number].args.transaction.eip1559.chainId |
| Nonce | extrinsics[extrinsic_number].args.transaction.eip1559.nonce |
| Max priority fee per gas | extrinsics[extrinsic_number].args.transaction.eip1559.maxPriorityFeePerGas |
| Max fee per gas | extrinsics[extrinsic_number].args.transaction.eip1559.maxFeePerGas |
| Gas limit | extrinsics[extrinsic_number].args.transaction.eip1559.gasLimit |
| Access list | extrinsics[extrinsic_number].args.transaction.eip1559.accessList |
| Signature | extrinsics[extrinsic_number].args.transaction.eip1559.oddYParity/r/s |
| Endereço remetente | extrinsics[extrinsic_number].events[event_number].data[0] |
| Endereço destinatário | extrinsics[extrinsic_number].events[event_number].data[1] |
| Hash EVM | extrinsics[extrinsic_number].events[event_number].data[2] |
| Status da execução EVM | extrinsics[extrinsic_number].events[event_number].data[3] |
| Campo EVM | Campo JSON do bloco |
|---|---|
| Nonce | extrinsics[extrinsic_number].args.transaction.legacy.nonce |
| Gas price | extrinsics[extrinsic_number].args.transaction.legacy.gasPrice |
| Gas limit | extrinsics[extrinsic_number].args.transaction.legacy.gasLimit |
| Value | extrinsics[extrinsic_number].args.transaction.legacy.value |
| Signature | extrinsics[extrinsic_number].args.transaction.legacy.signature |
| Endereço remetente | extrinsics[extrinsic_number].events[event_number].data[0] |
| Endereço destinatário | extrinsics[extrinsic_number].events[event_number].data[1] |
| Hash EVM | extrinsics[extrinsic_number].events[event_number].data[2] |
| Status execução | extrinsics[extrinsic_number].events[event_number].data[3] |
| Campo EVM | Campo JSON do bloco |
|---|---|
| Chain ID | extrinsics[extrinsic_number].args.transaction.eip2930.chainId |
| Nonce | extrinsics[extrinsic_number].args.transaction.eip2930.nonce |
| Gas price | extrinsics[extrinsic_number].args.transaction.eip2930.gasPrice |
| Gas limit | extrinsics[extrinsic_number].args.transaction.eip2930.gasLimit |
| Value | extrinsics[extrinsic_number].args.transaction.eip2930.value |
| Access list | extrinsics[extrinsic_number].args.transaction.eip2930.accessList |
| Signature | extrinsics[extrinsic_number].args.transaction.eip2930.oddYParity/r/s |
| Endereço remetente | extrinsics[extrinsic_number].events[event_number].data[0] |
| Endereço destinatário | extrinsics[extrinsic_number].events[event_number].data[1] |
| Hash EVM | extrinsics[extrinsic_number].events[event_number].data[2] |
| Status execução | extrinsics[extrinsic_number].events[event_number].data[3] |
Para transações EVM, “Nonce” e “Signature” ficam em:
extrinsics[extrinsic_number].args.transaction[transaction_type]
Logo, os campos “Nonce” e “Signature” no nível Substrate (extrinsics[extrinsic_number]) ficam como null.
Uma transação EVM bem-sucedida retorna succeed: "Stopped" ou succeed: "Returned" no campo de status de execução.
Monitorar transferências de saldo¶
Os exemplos a seguir mostram como ouvir transferências do token nativo (enviadas via Substrate ou Ethereum API) e transferências de tokens ERC-20 via Ethereum API usando o Sidecar. Transferências via Ethereum API se aplicam apenas às redes EVM do Tanssi.
Transferências de token nativo¶
Redes Tanssi EVM e não‑EVM podem fazer transferências nativas via Substrate. O snippet abaixo usa Axios para consultar /blocks/head e decodifica from, to, value, tx hash e status de transferências nativas tanto no nível EVM quanto Substrate:
import axios from 'axios';
// This script will decode all native token transfers (Substrate & Ethereum)
// in a given Sidecar block, and extract the tx hash. It can be adapted for
// any Tanssi-powered network.
// Endpoint to retrieve the latest block
const endpoint = 'http://127.0.0.1:8080/blocks/head';
async function main() {
try {
// Retrieve the block from the Sidecar endpoint
const response = await axios.get(endpoint);
// Retrieve the block height of the current block
console.log('Block Height: ' + response.data.number);
// Iterate through all extrinsics in the block
response.data.extrinsics.forEach((extrinsic) => {
// Retrieve Ethereum Transfers
if (
extrinsic.method.pallet === 'ethereum' &&
extrinsic.method.method === 'transact'
) {
// Get the value for any of the three EIP transaction standards supported
const value =
(extrinsic.args.transaction.legacy &&
extrinsic.args.transaction.legacy.value) ||
(extrinsic.args.transaction.eip1559 &&
extrinsic.args.transaction.eip1559.value) ||
(extrinsic.args.transaction.eip2930 &&
extrinsic.args.transaction.eip2930.value);
// Iterate through the events to get transaction details
extrinsic.events.forEach((event) => {
if (
event.method.pallet === 'ethereum' &&
event.method.method === 'Executed'
) {
console.log('From: ' + event.data[0]);
console.log('To: ' + event.data[1]);
console.log('Tx Hash: ' + event.data[2]);
console.log('Value: ' + value);
// Check the execution status
if (event.data[3].succeed) {
console.log('Status: Success');
} else {
console.log('Status: Failed');
}
}
});
}
// Retrieve Substrate Transfers
if (
extrinsic.method.pallet === 'balances' &&
(extrinsic.method.method === 'transferKeepAlive' ||
extrinsic.method.method === 'transfer')
) {
// Iterate through the events to get transaction details
extrinsic.events.forEach((event) => {
if (
event.method.pallet === 'balances' &&
event.method.method === 'Transfer'
) {
console.log('From: ' + event.data[0]);
console.log('To: ' + event.data[1]);
console.log('Tx Hash: ' + extrinsic.hash);
console.log('Value: ' + event.data[2]);
// Check the execution status
if (extrinsic.success) {
console.log('Status: Success');
} else {
console.log('Status: Failed');
}
}
});
}
});
} catch (err) {
console.log(err);
}
}
main();
Transferências de tokens ERC-20¶
Eventos emitidos por contratos ERC-20 em redes EVM do Tanssi podem ser decodificados do JSON de bloco. Estrutura:
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
...
...
Transferências ERC-20 emitem o evento Transfer, mapeado como:
| Informação da Tx | Campo JSON |
|---|---|
| Contrato ERC-20 | extrinsics[extrinsic_number].events[event_number].data[0].address |
| Assinatura do evento | extrinsics[extrinsic_number].events[event_number].data[0].topics[0] |
| Remetente | extrinsics[extrinsic_number].events[event_number].data[0].topics[1] |
| Destinatário | extrinsics[extrinsic_number].events[event_number].data[0].topics[2] |
| Valor | extrinsics[extrinsic_number].events[event_number].data[0].data |
Outros eventos EVM podem ser decodificados de forma semelhante; tópicos e dados variam conforme o evento.
Nota
O valor transferido considera decimais e está em formato hexadecimal.
Taxas de transação (Substrate)¶
Para redes Tanssi EVM e não‑EVM, informações de taxa de transações enviadas via Substrate API podem ser extraídas de:
GET /blocks/{blockId}
Os endpoints de bloco retornam dados relevantes para um ou mais blocos; veja mais na documentação do Sidecar.
Como JSON, para pallet e method específicos, a taxa é fornecida por um evento:
{event_number}.method.pallet: "transactionPayment"
{event_number}.method.method: "TransactionFeePaid"
Estrutura relevante:
RESPONSE JSON Block Object:
...
|--number
|--extrinsics
|--{extrinsic_number}
|--method
|--signature
|--nonce
|--args
|--tip
|--hash
|--info
|--era
|--events
|--{event_number}
|--method
|--pallet: "transactionPayment"
|--method: "TransactionFeePaid"
|--data
|--0
|--1
|--2
...
Mapeamento:
| Informação da Tx | Campo JSON |
|---|---|
| Conta que paga | extrinsics[extrinsic_number].events[event_number].data[0] |
| Taxa total paga | extrinsics[extrinsic_number].events[event_number].data[1] |
| Gorjeta | extrinsics[extrinsic_number].events[event_number].data[2] |
A taxa total para a extrínseca está em:
extrinsics[extrinsic_number].events[event_number].data[1]
Taxas de transação (API Ethereum)¶
Em redes EVM do Tanssi, usuários podem enviar transações via API Ethereum. As taxas podem ser calculadas assim:
GasPrice = BaseFee + MaxPriorityFeePerGas < MaxFeePerGas ?
BaseFee + MaxPriorityFeePerGas :
MaxFeePerGas;
Transaction Fee = (GasPrice * TransactionWeight) / 25000
Transaction Fee = (GasPrice * TransactionWeight) / 25000
Transaction Fee = (GasPrice * TransactionWeight) / 25000
As seções a seguir detalham cada componente.
Base Fee¶
A BaseFee é o valor mínimo cobrado para enviar uma transação, introduzida pela EIP-1559. Redes EVM do Tanssi ajustam a base fee dinamicamente, de forma semelhante ao mecanismo da EIP-1559, conforme congestionamento do bloco. No template EVM do Tanssi, a gas price mínima é 1 GWei.
A BaseFee pode ser obtida em baseFeePerGas do módulo baseFee:
GET /pallets/baseFee/storage/baseFeePerGas?at={blockId}
Estrutura relevante:
RESPONSE JSON Storage Object:
|--at
|--hash
|--height
|--pallet
|--palletIndex
|--storageItem
|--keys
|--value
O valor está em value (fixed point); divida pelas casas decimais para obter o valor real.
GasPrice, MaxFeePerGas e MaxPriorityFeePerGas¶
GasPrice especifica o gas price em transações legacy (pré‑EIP-1559). MaxFeePerGas e MaxPriorityFeePerGas foram introduzidos com a EIP-1559 juntamente com a BaseFee. MaxFeePerGas define a taxa máxima por unidade de gas (soma de BaseFee + MaxPriorityFeePerGas). MaxPriorityFeePerGas é a gorjeta máxima configurada para priorizar a transação.
Embora redes EVM do Tanssi sejam compatíveis com Ethereum, são cadeias Substrate, e prioridades funcionam de forma diferente: no Substrate as transações não são priorizadas por gas price. O Tanssi usa um sistema de priorização ajustado que reordena transações Substrate com base na taxa por gas (derivada de tip e weight). Para transações Ethereum, a prioridade é definida pela priority fee.
Nota: prioridade não é o único fator para ordenar transações; longevidade também influencia.
Os valores de GasPrice, MaxFeePerGas e MaxPriorityFeePerGas podem ser lidos do JSON do bloco conforme a estrutura descrita em Mapeamento EVM.
Os dados de uma transação Ethereum em um bloco podem ser obtidos de:
GET /blocks/{blockId}
Trajetos relevantes:
| Campo EVM | Campo JSON |
|---|---|
| MaxFeePerGas | extrinsics[extrinsic_number].args.transaction.eip1559.maxFeePerGas |
| MaxPriorityFeePerGas | extrinsics[extrinsic_number].args.transaction.eip1559.maxPriorityFeePerGas |
| Campo EVM | Campo JSON |
|---|---|
| GasPrice | extrinsics[extrinsic_number].args.transaction.legacy.gasPrice |
| Campo EVM | Campo JSON |
|---|---|
| GasPrice | extrinsics[extrinsic_number].args.transaction.eip2930.gasPrice |
Transaction Weight¶
TransactionWeight mede o tempo de execução de uma transação no bloco. Para todos os tipos, pode ser obtido no evento da extrínseca onde:
pallet: "system", method: "ExtrinsicSuccess"
E então o TransactionWeight está em:
extrinsics[extrinsic_number].events[event_number].data[0].weight
| Criada: 9 de dezembro de 2025
