Cara Mengotomatiskan Penyewaan TRON Energy dengan API

2026-05-13

Mengapa Mengotomatiskan Penyewaan Energi

Jika Anda menjalankan hot wallet, mesin penarikan exchange, atau kontrak yang memicu transfer TRC-20 atas nama pengguna, Anda sudah tahu rasa sakitnya: Anda membutuhkan TRON energy siap pada detik transaksi dijalankan. Mengisi energi secara manual melalui UI tidak dapat ditingkatkan melewati beberapa transfer per hari. Lewatkan jendela waktunya dan transaksi justru akan membakar TRX dari alamat pengirim, sering kali dengan biaya jauh lebih tinggi daripada energi yang disewa terlebih dahulu.

Solusinya adalah memanggil API penyewaan saat backend Anda akan menyiarkan transaksi, sehingga energi disediakan secara terprogram tanpa keterlibatan manusia. Artikel ini menjelaskan secara persis bagaimana melakukan itu terhadap tronenergyrent.com: bentuk permintaan yang sebenarnya, siklus hidup pesanan asinkron, pertimbangan durasi yang masuk akal, dan contoh Python yang berfungsi yang dapat Anda masukkan ke layanan Anda.

Apa yang Sebenarnya Dilakukan API di On-Chain

Sebelum menulis kode, ada baiknya memahami mekanik on-chain agar Anda tidak melakukan debug dengan buta.

Model sumber daya TRON memisahkan komputasi (energi) dari ukuran transaksi (bandwidth). Transfer USDT TRC-20 standar mengonsumsi sekitar 65,000 energi ketika penerima sudah memiliki USDT, dan sekitar 130,000 ketika saldo USDT penerima adalah nol. Transfer masuk pertama membayar biaya penyimpanan untuk membuat entri saldo, itulah sebabnya biaya sepenuhnya bergantung pada penerima, bukan pengirim. Penggunaan bandwidth untuk satu transfer sekitar 345 byte, yang cukup kecil sehingga sebagian besar akun menutupinya dari kuota gratis harian mereka.

Saat Anda memanggil API penyewaan, layanan melakukan stake TRX miliknya sendiri dan mendelegasikan energi yang dihasilkan ke alamat yang Anda tentukan, menggunakan DelegateResourceContract dari Stake 2.0. Delegasi bersifat spesifik per alamat dan dibatasi waktu. Setelah periode sewa berakhir, energi diambil kembali oleh penyedia secara otomatis.

Satu detail penting: penyewaan bersifat asinkron. Pemanggilan API segera mengembalikan orderId dan state PAID_BY_USER, namun transaksi delegasi on-chain disiarkan di latar belakang dan biasanya selesai dalam beberapa detik. Integrasi Anda harus memperlakukan respons awal sebagai konfirmasi bahwa pesanan telah diterima dan dibayar, kemudian melakukan polling pada endpoint detail pesanan hingga state berpindah ke ENERGY_DELEGATED.

Memilih Durasi Sewa yang Tepat

API menerima parameter period dengan empat nilai yang diizinkan: 1h, 1d, 3d, 30d. Harga berfluktuasi mengikuti pasar energi on-chain dan berubah sepanjang hari, jadi angka aktual selalu tersedia di halaman harga. Urutan relatifnya stabil: 1h paling murah per panggilan, 30d paling murah jika diamortisasi pada banyak transfer dari alamat yang sama.

Untuk sistem berbasis event di mana Anda memicu satu penyewaan per transfer keluar, tingkat 1h hampir selalu menjadi pilihan yang tepat. Anda membayar biaya absolut terendah dan energi dikonsumsi dalam hitungan detik setelah didelegasikan. Tingkat 1d dan yang lebih panjang masuk akal saat Anda menjalankan beban kerja batch yang dapat diprediksi, misalnya pekerjaan pembayaran malam hari, dan ingin menyewa satu blok energi besar sekali alih-alih memanggil API puluhan kali.

Jika sistem Anda secara konsisten menjalankan lebih dari 20-30 transfer per jam dari alamat yang sama, menyewa blok 1d dengan ukuran yang menutupi volume yang Anda harapkan lebih bersih daripada pemanggilan per-transfer. Biaya awal naik tetapi overhead API dan latensi konfirmasi on-chain hilang dari hot path.

Autentikasi dan Struktur Permintaan

Endpoint penyewaan berada di:

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

Ini adalah permintaan GET biasa dengan parameter query. Autentikasi adalah parameter query apiKey, yang Anda buat dari dasbor Anda setelah mendaftar dan mendanai akun Anda. Tidak ada autentikasi berbasis header dan tidak ada body permintaan JSON untuk endpoint ini.

Parameternya adalah:

  • apiKey (wajib): kunci API Anda dari dasbor.
  • period (wajib): durasi sewa, salah satu dari 1h, 1d, 3d, 30d.
  • energyAmount (wajib): seberapa banyak energi yang akan didelegasikan. Minimum adalah 15000. Untuk satu transfer USDT standar ke penerima yang sudah memiliki USDT, 65000 adalah angka aman; untuk transfer pertama ke pemilik USDT baru, gunakan 130000.
  • destinationAddress (wajib): alamat TRON (base58check, diawali dengan T) yang akan menerima energi yang didelegasikan.
  • preActivateDestinationAddress (opsional, default 0): atur ke 1 jika alamat tujuan belum pernah menerima TRX dan karena itu belum diaktifkan on-chain. Layanan kemudian akan mengirim 1.5 TRX dari saldo prabayar Anda untuk mengaktifkan alamat sebelum mendelegasikan energi. Jika alamat sudah aktif, biarkan ini pada 0 untuk menghindari biaya tambahan.

Respons selalu dikembalikan dengan status HTTP 200, terlepas dari apakah pesanan berhasil atau gagal. Cabangkan logika berdasarkan field status pada body JSON, bukan status HTTP. Body sukses terlihat seperti ini:

{
  "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"
  }
}

Body error memiliki status: "ERROR", errorCode yang dapat dibaca mesin, dan errorDescription yang dapat dibaca manusia:

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

Selalu catat requestId di kedua cabang. Jika Anda perlu meminta dukungan untuk melacak penyewaan tertentu, ID itulah yang mereka cari.

Siklus Hidup Pesanan

Field state di payload berjalan melalui urutan tetap yang kecil:

  • PAID_BY_USER: state awal, pesanan telah dibayar dari saldo Anda namun belum ada aksi on-chain yang terjadi.
  • WAITING_DELEGATION: layanan telah mengambil pesanan dan sedang menyiapkan transaksi delegasi.
  • ENERGY_DELEGATED: transaksi delegasi telah masuk ke on-chain. Alamat tujuan sekarang memiliki energi yang disewa dan dapat menggunakannya untuk transaksi keluar berikutnya.
  • ERROR_DELEGATION: delegasi gagal karena suatu alasan. Jarang, tetapi mungkin terjadi selama kemacetan jaringan yang berat.
  • CANCELLED: pesanan dibatalkan dan dana dikembalikan ke saldo Anda.

Untuk memeriksa state saat ini, panggil:

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

Respons menggunakan envelope status / errorCode / payload yang sama, dengan state saat ini di dalam payload. Lakukan polling setiap satu atau dua detik setelah menempatkan pesanan dan lanjutkan transfer TRC-20 Anda hanya setelah Anda melihat ENERGY_DELEGATED. Dalam praktiknya biasanya cukup satu atau dua polling.

Integrasi Python yang Berfungsi

Berikut adalah pola minimal namun siap produksi. Ia menempatkan penyewaan, melakukan polling sampai delegasi masuk ke on-chain, dan memunculkan error yang jelas jika ada yang salah.

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

Beberapa hal yang perlu disoroti. Pemeriksaan eksplisit status == "SUCCESS" penting karena status HTTP selalu 200, jadi resp.raise_for_status() saja tidak memberi tahu apa pun tentang hasil sebenarnya. Loop polling memiliki timeout keras sehingga pesanan yang macet tidak dapat memblokir pipeline transfer Anda tanpa batas. Percabangan pada state menangani tiga hasil terminal (ENERGY_DELEGATED, ERROR_DELEGATION, CANCELLED) secara eksplisit, bukan mengandalkan "not success" yang generik.

Dalam alur kerja transfer Anda, panggil rent_energy() terlebih dahulu, lalu siarkan transfer TRC-20. Urutan operasi penting: siarkan terlebih dahulu dan transaksi akan membakar TRX dari pengirim karena delegasi belum masuk.

Menentukan Ukuran Saldo Prabayar Anda

Biaya sewa dipotong dari saldo prabayar yang Anda pertahankan di akun tronenergyrent.com Anda. Siapkan peringatan atau pengisian otomatis saat saldo turun di bawah ambang batas. Batas bawah yang masuk akal adalah apa pun yang menutupi dua jam volume puncak.

Untuk membaca saldo saat ini secara terprogram:

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

Payload mencakup saldo dan state akun Anda saat ini. Hubungkan itu ke stack pemantauan Anda dan Anda tidak akan pernah dikejutkan oleh saldo yang habis pada jam 2 pagi. Perhatikan bahwa pengisian minimum ke saldo tronenergyrent.com Anda adalah 10 TRX.

Penanganan Error dalam Praktik

Tiga mode kegagalan paling sering muncul di produksi. Kode error di bawah ini berasal dari API yang sebenarnya dan Anda dapat mencabangkan logika atasnya dengan aman.

  1. INSUFFICIENT_BALANCE: saldo prabayar Anda terlalu rendah untuk menutupi penyewaan yang diminta ditambah pra-aktivasi apa pun. Jangan mencoba lagi, mencoba ulang tidak akan memperbaikinya. Tangkap ini secara spesifik dan picu alur peringatan atau pengisian. Tambahkan requestId ke payload peringatan Anda.
  2. INVALID_ADDRESS: destinationAddress gagal pada decode base58check di server. Jika sistem Anda membangun alamat secara dinamis, misalnya dari input yang diberikan pengguna, validasikan secara lokal sebelum memanggil API. Library Python tronpy memiliki is_address() untuk ini; menolak input buruk di sisi klien lebih cepat daripada menunggu round trip.
  3. INACTIVE_DESTINATION_ADDRESS_ERROR: alamat tujuan belum pernah diaktifkan on-chain dan Anda tidak meminta layanan untuk mengaktifkannya. Perbaiki dengan mendanai alamat terlebih dahulu dengan sedikit TRX dari tempat lain, atau dengan meneruskan preActivateDestinationAddress=1 pada pemanggilan berikutnya sehingga layanan mengaktifkannya seharga 1.5 TRX.

Kasus yang lebih halus: ORDER_IS_ALREADY_IN_PROGRESS dapat kembali jika Anda memiliki beberapa worker yang menempatkan penyewaan untuk tujuan yang sama pada saat yang sama. Perbaikannya ada di sisi proses, bukan sisi API. Ambil distributed lock (Redis bekerja dengan baik) yang berkunci pada alamat tujuan dan ditahan sampai delegasi selesai.

Verifikasi On-Chain

Untuk sebagian besar integrasi, polling /single-order-details sampai ENERGY_DELEGATED sudah cukup. Jika Anda ingin verifikasi sabuk dan tali pengaman, Anda juga dapat melakukan query ke full node TRON secara langsung setelah delegasi masuk:

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

Respons berisi state sumber daya alamat saat ini, termasuk energi yang didelegasikan kepadanya dari alamat eksternal. Nama field yang tepat bergantung pada tampilan Stake 2.0 saat ini, jadi konsultasikan dokumen API HTTP TRON yang aktif saat memasangnya. Sebagai pemeriksaan lunak yang mencatat peringatan alih-alih memblokir transfer, ini adalah kenari yang berguna untuk kasus langka ketika ada yang salah di hilir dari API penyewaan itu sendiri.

Pemeriksaan ekstra itu akan menghemat berjam-jam debugging pada satu kali ketika penyewaan terlihat berhasil di API tetapi ada hal lain yang salah di on-chain.

Ingin hemat biaya transaksi TRON? Cek harga energi sekarang. Estimasi Harga
Kembali ke Blog