Ir para o conteúdo

Usando o Substrate API Sidecar

Introdução

O Substrate API Sidecar permite que aplicações acessem blocos, saldo 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 saldo e mudanças de estado em uma rede powered by Tanssi. Esta página descreve como instalar e executar o Substrate API Sidecar para uma rede Tanssi e os endpoints mais usados.

Instalando e Executando o Substrate API Sidecar

Existem várias formas de instalar e executar o Substrate API Sidecar. Este guia descreve os passos para instalá-lo e executá-lo localmente via NPM. Para uso via Docker ou build e execução a partir do código-fonte, consulte o repositório oficial do Substrate API Sidecar.

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

Note

Se a pasta não tiver um projeto Node.js, crie manualmente node_modules com mkdir node_modules.

O Substrate API Sidecar v20.2.2 é a versão estável atual 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 WS da rede que deseja usar. Exemplos:

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=INSERIR_ENDPOINT_WSS_DA_REDE

Depois de definir, confirme com:

echo $SAS_SUBSTRATE_URL

Ele deve exibir o endpoint configurado.

Executando o Substrate API Sidecar

Com a variável de ambiente configurada e 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:

Saída bem-sucedida

Endpoints do Substrate API Sidecar

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 informações da conta
  • GET /node/version — implementação e versão do nó Substrate
  • GET /runtime/metadata — metadata do runtime em JSON decodificado

Para a lista completa, consulte a documentação oficial.

Mapeamento de Campos no Objeto JSON do Bloco

O Sidecar retorna blocos em JSON. Parte do objeto é a estrutura aninhada das extrínsecas processadas em um bloco específico. Cada extrínseca chama um método de um módulo. Em linhas gerais, a estrutura é:

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
    ...

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 da Tanssi, 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 da 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, veja 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 em que:

{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/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
Assinatura 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 de execução 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
Valor extrinsics[extrinsic_number].args.transaction.legacy.value
Assinatura extrinsics[extrinsic_number].args.transaction.legacy.signature
Remetente EVM extrinsics[extrinsic_number].events[event_number].data[0]
Destinatário EVM 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
Valor extrinsics[extrinsic_number].args.transaction.eip2930.value
Access list extrinsics[extrinsic_number].args.transaction.eip2930.accessList
Assinatura extrinsics[extrinsic_number].args.transaction.eip2930.oddYParity/r/s
Remetente EVM extrinsics[extrinsic_number].events[event_number].data[0]
Destinatário EVM 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, campos como “Nonce” e “Signature” ficam em:

extrinsics[extrinsic_number].args.transaction[transaction_type]

Assim, “Nonce” e “Signature” no nível Substrate (extrinsics[extrinsic_number]) ficam null.

Uma transação EVM bem-sucedida retorna succeed: "Stopped" ou succeed: "Returned" no campo de status de execução EVM.

Monitorar Transferências de Tokens

Os trechos a seguir mostram como escutar transferências do token nativo enviadas via Substrate ou Ethereum API, e transferências de tokens ERC-20 via Ethereum API, usando o Substrate API Sidecar. Transferências pela Ethereum API se aplicam apenas a redes EVM da Tanssi.

Transferências de Token Nativo

Redes Tanssi EVM e não-EVM podem fazer transferências de saldo nativas baseadas em Substrate.

O snippet abaixo usa Axios para consultar o endpoint /blocks/head para o último bloco finalizado, e decodifica from, to, value, tx hash e transaction 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 smart contracts (como um contrato ERC-20 implantado em redes EVM da Tanssi) podem ser decodificados a partir do JSON do bloco. A 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
\t\t\t\t        |-- data
            ...
    ...

Transferências ERC-20 emitem o evento Transfer, que pode ser decodificado assim:

Informação da tx Campo JSON do bloco
Endereço do contrato extrinsics[extrinsic_number].events[event_number].data[0].address
Hash da assinatura extrinsics[extrinsic_number].events[event_number].data[0].topics[0]
Endereço remetente extrinsics[extrinsic_number].events[event_number].data[0].topics[1]
Endereço destinatário extrinsics[extrinsic_number].events[event_number].data[0].topics[2]
Quantia extrinsics[extrinsic_number].events[event_number].data[0].data

Outros eventos de contratos EVM podem ser decodificados de modo semelhante; o conteúdo de topics e data muda conforme a definição do evento.

Note

A quantia transferida leva em conta as casas decimais e vem em hexadecimal.

Taxas de Transação na Substrate API

Para redes Tanssi EVM e não-EVM, todas as informações sobre taxas de transações enviadas via Substrate API podem ser extraídas do endpoint:

GET /blocks/{blockId}

Os endpoints de bloco retornam dados de um ou mais blocos. Saiba mais na documentação oficial do Sidecar.

Lendo como JSON, para um pallet (módulo) e method, a taxa da transação vem de um evento com:

{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 do bloco
Conta que paga extrinsics[extrinsic_number].events[event_number].data[0]
Taxas totais extrinsics[extrinsic_number].events[event_number].data[1]
Gorjeta (tip) extrinsics[extrinsic_number].events[event_number].data[2]

A taxa total paga para a extrínseca está em:

extrinsics[extrinsic_number].events[event_number].data[1]

Taxas de Transação na Ethereum API

Para redes EVM da Tanssi, usuários também podem enviar fundos via Ethereum API. Para calcular a taxa de uma transação Ethereum, use:

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 e é definida pela rede. Foi introduzida na EIP-1559. Redes EVM da Tanssi usam um mecanismo dinâmico semelhante ao da EIP-1559, ajustando a base fee conforme congestionamento.

No template EVM da 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 define o gas price em transações legacy (pré‑EIP-1559). MaxFeePerGas e MaxPriorityFeePerGas foram introduzidos com a EIP-1559 junto da BaseFee. MaxFeePerGas define a taxa máxima por unidade de gas (BaseFee + MaxPriorityFeePerGas). MaxPriorityFeePerGas é a gorjeta máxima configurada para priorizar a transação.

Embora redes EVM da Tanssi sejam compatíveis com Ethereum, são cadeias Substrate, e prioridades funcionam de forma diferente: no Substrate 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 descrito 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 Runtime de uma transação no bloco. Para todos os tipos, pode ser obtido no evento da extrínseca em que:

pallet: "system", method: "ExtrinsicSuccess"

E entã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: 23 de dezembro de 2025
| Criada: 27 de novembro de 2025