Ir para o conteúdo

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:

Successful Output

Endpoints do Substrate API Sidecar

Alguns endpoints comuns:

  • GET /blocks/head — bloco finalizado mais recente. O parâmetro opcional finalized=false retorna o bloco mais novo, possivelmente não finalizado
  • GET /blocks/head/header — cabeçalho do último bloco. finalized=false opcional
  • 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
As informações apresentadas aqui foram fornecidas por terceiros e estão disponíveis apenas para fins informativos gerais. A Tanssi não endossa nenhum projeto listado e descrito no Site de Documentação da Tanssi (https://docs.tanssi.network/). A Tanssi Foundation não garante a precisão, integridade ou utilidade dessas informações. Qualquer confiança depositada nelas é de sua exclusiva responsabilidade. A Tanssi Foundation se exime de toda responsabilidade decorrente de qualquer confiança que você ou qualquer outra pessoa possa ter em qualquer parte deste conteúdo. Todas as declarações e/ou opiniões expressas nesses materiais são de responsabilidade exclusiva da pessoa ou entidade que as fornece e não representam necessariamente a opinião da Tanssi Foundation. As informações aqui não devem ser interpretadas como aconselhamento profissional ou financeiro de qualquer tipo. Sempre busque orientação de um profissional devidamente qualificado em relação a qualquer assunto ou circunstância em particular. As informações aqui podem conter links ou integração com outros sites operados ou conteúdo fornecido por terceiros, e tais sites podem apontar para este site. A Tanssi Foundation não tem controle sobre esses sites ou seu conteúdo e não terá responsabilidade decorrente ou relacionada a eles. A existência de qualquer link não constitui endosso desses sites, de seu conteúdo ou de seus operadores. Esses links são fornecidos apenas para sua conveniência, e você isenta e exonera a Tanssi Foundation de qualquer responsabilidade decorrente do uso dessas informações ou das informações fornecidas por qualquer site ou serviço de terceiros.
Última atualização: 9 de dezembro de 2025
| Criada: 9 de dezembro de 2025