Como Automatizar o Aluguel de Energia TRON com a API

2026-05-13

Por Que Automatizar o Aluguel de Energia

Se você opera uma carteira quente, um motor de saques de exchange ou um contrato que dispara transferências TRC-20 em nome dos usuários, já conhece a dor: você precisa de energia TRON pronta no exato segundo em que uma transação é disparada. Recarregar energia manualmente por uma interface não escala além de algumas transferências por dia. Perca a janela e a transação queima TRX do endereço remetente, frequentemente a um custo muito mais alto do que a energia pré-alugada.

A solução é chamar a API de aluguel no momento em que seu backend está prestes a transmitir uma transação, de modo que a energia seja provisionada programaticamente, sem nenhum humano no circuito. Este artigo mostra exatamente como fazer isso contra o tronenergyrent.com: o formato real da requisição, o ciclo de vida assíncrono do pedido, escolhas sensatas de duração e um exemplo Python funcional que você pode plugar no seu serviço.

O Que a API Realmente Faz On-Chain

Antes de escrever código, vale a pena entender a mecânica on-chain para não depurar às cegas.

O modelo de recursos da TRON separa computação (energia) do tamanho da transação (bandwidth). Uma transferência USDT TRC-20 padrão consome aproximadamente 65,000 de energia quando o destinatário já possui USDT, e cerca de 130,000 quando o saldo USDT do destinatário é zero. A primeira transferência recebida paga o custo de armazenamento da criação do registro de saldo, e é por isso que o custo depende inteiramente do destinatário, não do remetente. O uso de bandwidth para uma transferência é de cerca de 345 bytes, pequeno o suficiente para que a maioria das contas cubra esse valor com sua cota gratuita diária.

Quando você chama a API de aluguel, o serviço faz o stake do próprio TRX e delega a energia resultante ao endereço que você especificar, usando DelegateResourceContract do Stake 2.0. A delegação é específica por endereço e tem prazo limitado. Quando o período de aluguel expira, a energia é recuperada automaticamente pelo provedor.

Um detalhe importante: o aluguel é assíncrono. A chamada da API retorna imediatamente com um orderId e um estado PAID_BY_USER, mas a transação de delegação on-chain é transmitida em segundo plano e normalmente é confirmada em poucos segundos. Sua integração deve tratar a resposta inicial como confirmação de que o pedido foi aceito e pago, e então fazer polling no endpoint de detalhes do pedido até o estado mudar para ENERGY_DELEGATED.

Escolhendo a Duração Certa do Aluguel

A API aceita um parâmetro period com quatro valores permitidos: 1h, 1d, 3d, 30d. Os preços flutuam com o mercado de energia on-chain e mudam ao longo do dia, então os valores ao vivo ficam sempre na página de preços. A ordem relativa é estável: 1h é a mais barata por chamada, 30d é a mais barata quando amortizada entre muitas transferências do mesmo endereço.

Para um sistema orientado a eventos, no qual você dispara um aluguel por transferência de saída, o nível 1h é quase sempre a escolha correta. Você paga o menor custo absoluto e a energia é consumida em segundos após ser delegada. Os níveis 1d e mais longos fazem sentido quando você roda cargas em lote previsíveis, por exemplo um job noturno de pagamentos, e quer alugar um grande bloco de energia de uma vez em vez de chamar a API dezenas de vezes.

Se seu sistema dispara consistentemente mais de 20-30 transferências por hora a partir do mesmo endereço, alugar um bloco 1d dimensionado para cobrir seu volume esperado é mais limpo do que chamadas por transferência. O custo inicial sobe, mas o overhead da API e a latência de confirmação on-chain saem do caminho crítico.

Autenticação e Estrutura da Requisição

O endpoint de aluguel fica em:

GET https://api.tronenergyrent.com/place-energy-order

É uma requisição GET simples com parâmetros de query. A autenticação é o parâmetro de query apiKey, que você gera no seu painel depois de se registrar e adicionar saldo à conta. Não há autenticação por header e não há corpo JSON de requisição para este endpoint.

Os parâmetros são:

  • apiKey (obrigatório): sua chave de API obtida no painel.
  • period (obrigatório): duração do aluguel, um dentre 1h, 1d, 3d, 30d.
  • energyAmount (obrigatório): quanta energia delegar. O mínimo é 15000. Para uma transferência USDT padrão a um destinatário que já possui USDT, 65000 é o número seguro; para uma primeira transferência a um novo holder de USDT, use 130000.
  • destinationAddress (obrigatório): o endereço TRON (base58check, começa com T) que receberá a energia delegada.
  • preActivateDestinationAddress (opcional, padrão 0): defina como 1 se o endereço de destino nunca recebeu TRX e portanto não está ativado on-chain. O serviço então envia 1.5 TRX do seu saldo pré-pago para ativar o endereço antes de delegar energia. Se o endereço já estiver ativo, deixe em 0 para evitar o custo extra.

A resposta é sempre retornada com status HTTP 200, independentemente de o pedido ter tido sucesso ou falhado. Faça o branching pelo campo status do corpo JSON em vez do status HTTP. Um corpo de sucesso fica assim:

{
  "status": "SUCCESS",
  "errorCode": null,
  "errorDescription": null,
  "requestId": "2651eacd-2428",
  "payload": {
    "orderId": "128de799-501e-44b2-8d6f-1fa825c2deed",
    "totalPriceSun": 5662800,
    "totalPriceTrx": 5.6628,
    "state": "PAID_BY_USER"
  }
}

Um corpo de erro tem status: "ERROR", um errorCode legível por máquina e um errorDescription legível por humanos:

{
  "status": "ERROR",
  "errorCode": "INVALID_ENERGY_AMOUNT",
  "errorDescription": "energyAmount is less than 15000",
  "requestId": "71431087-4",
  "payload": null
}

Sempre registre o requestId em ambos os ramos. Se você um dia precisar pedir ao suporte para rastrear um aluguel específico, é por esse ID que eles fazem a busca.

O Ciclo de Vida do Pedido

O campo state no payload avança por uma pequena sequência fixa:

  • PAID_BY_USER: estado inicial, o pedido foi pago a partir do seu saldo, mas nenhuma ação on-chain aconteceu ainda.
  • WAITING_DELEGATION: o serviço pegou o pedido e está preparando a transação de delegação.
  • ENERGY_DELEGATED: a transação de delegação foi confirmada on-chain. O endereço de destino agora possui a energia alugada e pode gastá-la na próxima transação de saída.
  • ERROR_DELEGATION: a delegação falhou por algum motivo. Raro, mas possível durante congestionamento intenso da rede.
  • CANCELLED: o pedido foi cancelado e os fundos devolvidos ao seu saldo.

Para checar o estado atual, chame:

GET https://api.tronenergyrent.com/single-order-details?apiKey=YOUR_API_KEY&orderId=ORDER_ID

A resposta usa o mesmo envelope status / errorCode / payload, com o state atual dentro de payload. Faça polling a cada um ou dois segundos após colocar o pedido e prossiga com sua transferência TRC-20 somente depois de ver ENERGY_DELEGATED. Na prática, normalmente isso são uma ou duas consultas.

Uma Integração Python Funcional

Aqui está um padrão mínimo, mas com cara de produção. Ele coloca o aluguel, faz polling até a delegação estar on-chain e expõe um erro claro se algo der errado.

import logging
import time
import requests

API_BASE = "https://api.tronenergyrent.com"
API_KEY = "your_api_key_here"
ENERGY_FOR_TRANSFER = 65_000   # use 130_000 if recipient has zero USDT balance
HTTP_TIMEOUT_SECS = 10
POLL_INTERVAL_SECS = 1
POLL_TIMEOUT_SECS = 30


def place_order(destination_address: str, period: str = "1h",
                energy_amount: int = ENERGY_FOR_TRANSFER) -> dict:
    resp = requests.get(
        f"{API_BASE}/place-energy-order",
        params={
            "apiKey": API_KEY,
            "period": period,
            "energyAmount": energy_amount,
            "destinationAddress": destination_address,
            "preActivateDestinationAddress": 0,
        },
        timeout=HTTP_TIMEOUT_SECS,
    )
    resp.raise_for_status()
    body = resp.json()
    if body.get("status") != "SUCCESS":
        raise RuntimeError(
            f"place-energy-order failed: {body.get('errorCode')} "
            f"({body.get('errorDescription')}) requestId={body.get('requestId')}"
        )
    return body["payload"]


def wait_for_delegation(order_id: str) -> dict:
    deadline = time.monotonic() + POLL_TIMEOUT_SECS
    while time.monotonic() < deadline:
        resp = requests.get(
            f"{API_BASE}/single-order-details",
            params={"apiKey": API_KEY, "orderId": order_id},
            timeout=HTTP_TIMEOUT_SECS,
        )
        resp.raise_for_status()
        body = resp.json()
        if body.get("status") != "SUCCESS":
            raise RuntimeError(
                f"single-order-details failed: {body.get('errorCode')} "
                f"({body.get('errorDescription')})"
            )
        state = body["payload"]["state"]
        if state == "ENERGY_DELEGATED":
            return body["payload"]
        if state == "ERROR_DELEGATION":
            raise RuntimeError(f"Delegation failed for order {order_id}")
        if state == "CANCELLED":
            raise RuntimeError(f"Order {order_id} was cancelled")
        time.sleep(POLL_INTERVAL_SECS)
    raise TimeoutError(f"Order {order_id} did not reach ENERGY_DELEGATED in {POLL_TIMEOUT_SECS}s")


def rent_energy(destination_address: str) -> dict:
    placed = place_order(destination_address)
    logging.info(
        "Order placed: id=%s priceSun=%s priceTrx=%s",
        placed["orderId"], placed["totalPriceSun"], placed["totalPriceTrx"],
    )
    delegated = wait_for_delegation(placed["orderId"])
    logging.info("Order delegated: id=%s", delegated["orderId"])
    return delegated

Vale destacar alguns pontos. A checagem explícita de status == "SUCCESS" é importante porque o status HTTP é sempre 200, então o resp.raise_for_status() sozinho não diz nada sobre o resultado real. O laço de polling tem um timeout rígido, de modo que um pedido travado não pode bloquear seu pipeline de transferências indefinidamente. O branching por state trata os três desfechos terminais (ENERGY_DELEGATED, ERROR_DELEGATION, CANCELLED) de forma explícita, em vez de depender de um genérico "não foi sucesso".

No seu fluxo de transferência, chame rent_energy() primeiro e depois transmita a transferência TRC-20. A ordem das operações importa: transmitir primeiro fará a transação queimar TRX do remetente, porque a delegação ainda não foi confirmada.

Dimensionando Seu Saldo Pré-Pago

O custo do aluguel é debitado de um saldo pré-pago que você mantém na sua conta do tronenergyrent.com. Configure um alerta ou uma recarga automática quando o saldo cair abaixo de um limite. Um piso razoável é o que cobrir duas horas de volume de pico.

Para ler o saldo atual programaticamente:

GET https://api.tronenergyrent.com/account-info?apiKey=YOUR_API_KEY

O payload inclui seu saldo atual e o estado da conta. Plugue isso no seu stack de monitoramento e você nunca mais será pego de surpresa por um saldo zerado às 2h da manhã. Observe que a recarga mínima do seu saldo no tronenergyrent.com é 10 TRX.

Tratamento de Erros na Prática

Três modos de falha aparecem com mais frequência em produção. Os códigos de erro abaixo vêm da API real e você pode fazer branching neles com segurança.

  1. INSUFFICIENT_BALANCE: seu saldo pré-pago é baixo demais para cobrir o aluguel solicitado mais qualquer pré-ativação. Não tente de novo, repetir não vai resolver. Capture esse caso especificamente e dispare um alerta ou um fluxo de recarga. Inclua o requestId no payload do alerta.
  2. INVALID_ADDRESS: o destinationAddress falhou no decode base58check no servidor. Se seu sistema constrói endereços dinamicamente, por exemplo a partir de input fornecido pelo usuário, valide-os localmente antes de chamar a API. A biblioteca Python tronpy tem is_address() para isso; rejeitar input ruim no client é mais rápido do que esperar pela ida e volta.
  3. INACTIVE_DESTINATION_ADDRESS_ERROR: o endereço de destino nunca foi ativado on-chain e você não pediu ao serviço para ativá-lo. Corrija pré-financiando o endereço com uma pequena quantidade de TRX de outra fonte, ou passando preActivateDestinationAddress=1 na próxima chamada para que o serviço o ative por 1.5 TRX.

Um caso mais sutil: ORDER_IS_ALREADY_IN_PROGRESS pode voltar se você tiver múltiplos workers colocando aluguéis para o mesmo destino ao mesmo tempo. A correção é no lado do processo, não da API. Pegue um lock distribuído (Redis funciona bem) com chave no endereço de destino e mantido até a delegação ser concluída.

Verificando On-Chain

Para a maioria das integrações, fazer polling em /single-order-details até ENERGY_DELEGATED já basta. Se você quiser uma verificação com cinto e suspensórios, também pode consultar o nó completo da TRON diretamente após a delegação ser confirmada:

GET https://api.trongrid.io/v1/accounts/{destinationAddress}

A resposta contém o estado atual de recursos do endereço, incluindo a energia delegada a ele a partir de endereços externos. O nome exato do campo depende da visão atual do Stake 2.0, então consulte a documentação ao vivo da TRON HTTP API ao integrar isso. Como uma checagem leve, que apenas registra um aviso em vez de bloquear a transferência, ela é um canário útil para o raro caso em que algo dá errado downstream da própria API de aluguel.

Essa checagem extra vai te salvar horas de depuração na única vez em que o aluguel parecer bem-sucedido na API, mas algo mais sair errado on-chain.

Quer economizar nas taxas de transacao TRON? Confira os precos de energia agora. Estimativa de Preço
Voltar ao Blog