Создание транзакций с токенами TRC20 на TRON
Введение
Заголовок раздела «Введение»Это руководство описывает эндпоинты TRC20 API Chaingateway V2: создание адреса TRON, чтение контракта токена, проверку баланса токена и отправку перевода TRC20. Примеры приведены на Shell (cURL), PHP (Guzzle), Python (Requests) и JavaScript (Axios).
Информацию о получении API-ключа и об авторизации см. в разделе Quickstart документации Chaingateway.
Что делает API, а что нет
Заголовок раздела «Что делает API, а что нет»В API нет эндпоинта, который компилирует или деплоит смарт-контракт. Нет маршрута, публикующего новый контракт TRC20 в сети TRON, и ни один из эндпоинтов TRON не принимает байткод контракта. Каждый маршрут TRC20 принимает contractaddress токена, который уже существует в сети, — будь то USDT или любой другой токен TRC20.
Если вы ищете способ задеплоить собственный контракт токена, этот API не подходит для этого шага. Как только контракт задеплоен, эндпоинты ниже покрывают ту часть, которая нужна большинству интеграций на практике: адреса, балансы, переводы и уведомления.
| Что вы хотите сделать | Эндпоинт |
|---|---|
| Создать адрес TRON | POST /v2/tron/addresses |
| Импортировать существующий приватный ключ | POST /v2/tron/addresses/import |
| Прочитать имя, символ, decimals и supply | GET /v2/tron/trc20/{contract_address} |
| Прочитать баланс токена | GET /v2/tron/balances/{address}/trc20/{contract_address} |
| Отправить перевод TRC20 | POST /v2/tron/transactions/trc20 |
| Собрать перевод без отправки в сеть | POST /v2/tron/transactions/trc20/build |
| Отправить в сеть подписанную транзакцию | POST /v2/tron/transactions/broadcast |
| Получать уведомления о входящих токенах | POST /v2/tron/webhooks |
Шаг 1: создание адреса TRON
Заголовок раздела «Шаг 1: создание адреса TRON»Отправляющий адрес должен быть известен Chaingateway. Либо создайте его через API, либо импортируйте существующий приватный ключ через POST /v2/tron/addresses/import.
Если вы передаёте password, приватный ключ хранится в зашифрованном виде, и последующие транзакции вы подписываете этим паролем. Если пароль не указан, ответ содержит сам приватный ключ, и его нужно передавать с каждым запросом транзакции. Подход с паролем подробно описан в разделе Управление кошельками.
curl --request POST\ --url https://api.chaingateway.io/v2/tron/addresses\ --header 'Accept: application/json'\ --header 'content-type: application/json'\ --header 'Authorization: YOUR_API_TOKEN'\ --data '{"password":"test123"}'import requests
url = "https://api.chaingateway.io/v2/tron/addresses"payload = {"password": "test123"}headers = { 'Accept': 'application/json', 'content-type': 'application/json', 'Authorization': 'YOUR_API_TOKEN'}
response = requests.post(url, json=payload, headers=headers)print(response.json())const axios = require('axios');
const url = 'https://api.chaingateway.io/v2/tron/addresses';const payload = { password: 'test123' };const headers = { 'Accept': 'application/json', 'content-type': 'application/json', 'Authorization': 'YOUR_API_TOKEN'};
axios.post(url, payload, { headers }) .then(response => { console.log(response.data); }) .catch(error => { console.error(error); });<?phprequire 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client();$response = $client->post('https://api.chaingateway.io/v2/tron/addresses', [ 'headers' => [ 'Accept' => 'application/json', 'content-type' => 'application/json', 'Authorization' => 'YOUR_API_TOKEN', ], 'json' => [ 'password' => 'test123' ]]);
echo $response->getBody();?>Ответ содержит новый адрес:
{ "status": 201, "ok": true, "message": "Address created", "data": [ { "privateKey": "59f1c6200e01a2ca9471411f10198bfa63678d0e87cc2ca30f9c4a68dee78edc", "publicKey": "040fe6e677442c36f7fdd5535ba3ff1cef0110d78363420f7e24b65298990e3467aed68b9a67e1396d84753db25b32a2fa3e1fc0a673f01638e9bcfab2d8f4ceb5", "hexAddress": "41a56a6505ffbee78eb916dd44f4846874deddaebd", "address": "TR3qx91smURF3R455V1ubqtoUsZbgqikfg" } ]}Chaingateway не хранит пароли. Утерянный пароль означает утерянный кошелёк.
Шаг 2: чтение контракта токена
Заголовок раздела «Шаг 2: чтение контракта токена»Прежде чем перемещать токен, прочитайте его контракт. Значение decimals понадобится вам чаще всего, поскольку оно показывает, как сырой ончейн-баланс соотносится с суммой, которую видит пользователь.
curl --request GET\ --url https://api.chaingateway.io/v2/tron/trc20/TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t\ --header 'Accept: application/json'\ --header 'Authorization: YOUR_API_TOKEN'{ "status": 200, "ok": true, "message": "TRC20 contract fetched", "data": { "address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "symbol": "USDT", "name": "TetherUSD", "totalSupply": "61742996582033118", "decimals": "6" }}Неизвестный или не TRC20-адрес контракта отвечает статусом 400 и сообщением Error fetching TRC20 contract.
Шаг 3: проверка баланса токена
Заголовок раздела «Шаг 3: проверка баланса токена»curl --request GET\ --url https://api.chaingateway.io/v2/tron/balances/TVF2Mp9QY7FEGTnr3DBpFLobA6jguHyMvi/trc20/TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj\ --header 'Accept: application/json'\ --header 'Authorization: YOUR_API_TOKEN'{ "status": 200, "ok": true, "message": "TRC20 balance fetched", "data": { "tronaddress": "TVF2Mp9QY7FEGTnr3DBpFLobA6jguHyMvi", "decimals": 6, "balance": "1000000000000000000", "contractaddress": "TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj" }}Поле balance — это сырое целочисленное значение. Разделите его на 10 в степени decimals, чтобы получить сумму в человекочитаемом виде.
Шаг 4: отправка перевода TRC20
Заголовок раздела «Шаг 4: отправка перевода TRC20»POST /v2/tron/transactions/trc20 требует from, to, contractaddress и amount. Для подписи добавьте либо password, если адрес был создан с паролем, либо privatekey для незащищённого или импортированного адреса.
Параметры
Заголовок раздела «Параметры»- from: адрес отправителя TRON.
- to: адрес получателя TRON.
- contractaddress: адрес контракта токена.
- amount: отправляемая сумма.
- password: пароль защищённого паролем адреса Chaingateway. Обязателен, если не указан
privatekey. - privatekey: приватный ключ отправителя для адресов, созданных или импортированных без пароля.
curl --request POST\ --url https://api.chaingateway.io/v2/tron/transactions/trc20\ --header 'Accept: application/json'\ --header 'content-type: application/json'\ --header 'Authorization: YOUR_API_TOKEN'\ --data '{ "from": "TLkkCeNdJKPNUwucdro84WjswkzM62LCTH", "to": "TUwmZghA7u2GxGxKaxM1mkCmsTF4wHs4vp", "contractaddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "amount": 1, "password": "test123"}'import requests
url = "https://api.chaingateway.io/v2/tron/transactions/trc20"payload = { "from": "TLkkCeNdJKPNUwucdro84WjswkzM62LCTH", "to": "TUwmZghA7u2GxGxKaxM1mkCmsTF4wHs4vp", "contractaddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "amount": 1, "password": "test123"}headers = { 'Accept': 'application/json', 'content-type': 'application/json', 'Authorization': 'YOUR_API_TOKEN'}
response = requests.post(url, json=payload, headers=headers)print(response.json())const axios = require('axios');
const url = 'https://api.chaingateway.io/v2/tron/transactions/trc20';const payload = { from: 'TLkkCeNdJKPNUwucdro84WjswkzM62LCTH', to: 'TUwmZghA7u2GxGxKaxM1mkCmsTF4wHs4vp', contractaddress: 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t', amount: 1, password: 'test123'};const headers = { 'Accept': 'application/json', 'content-type': 'application/json', 'Authorization': 'YOUR_API_TOKEN'};
axios.post(url, payload, { headers }) .then(response => { console.log(response.data); }) .catch(error => { console.error(error); });<?phprequire 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client();$response = $client->post('https://api.chaingateway.io/v2/tron/transactions/trc20', [ 'headers' => [ 'Accept' => 'application/json', 'content-type' => 'application/json', 'Authorization' => 'YOUR_API_TOKEN', ], 'json' => [ 'from' => 'TLkkCeNdJKPNUwucdro84WjswkzM62LCTH', 'to' => 'TUwmZghA7u2GxGxKaxM1mkCmsTF4wHs4vp', 'contractaddress' => 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t', 'amount' => 1, 'password' => 'test123' ]]);
echo $response->getBody();?>Успешный вызов отвечает хешем транзакции:
{ "status": 201, "ok": true, "message": "Succesfully created transaction", "data": { "txid": "0x73344d178812d4919e9002c560781f288030edf72ece88823ef1c377dfb71f27" }}Две ошибки приходят со статусом 422, и их стоит обрабатывать отдельно. Сообщение balance is not sufficient означает, что отправляющий адрес не может оплатить транзакцию. Сообщение Validate signature error означает, что ключ или пароль не соответствуют адресу from.
Отправляющему кошельку нужен TRX
Заголовок раздела «Отправляющему кошельку нужен TRX»Перевод TRC20 — это вызов смарт-контракта, и TRON взимает за него energy и bandwidth. Адрес, держащий только токены и ничего больше, не может их отправить. Либо пополните адрес TRX, либо застейкайте ресурсы через POST /v2/tron/freeze и POST /v2/tron/delegate, либо позвольте кому-то другому спонсировать комиссию. Спонсирование комиссии описано в разделе Спонсирование комиссий TRC20.
Самостоятельная подпись транзакции
Заголовок раздела «Самостоятельная подпись транзакции»Если вы хотите не передавать приватный ключ в запросе, разделите перевод на два вызова. POST /v2/tron/transactions/trc20/build возвращает сырой hex транзакции без отправки в сеть. Вы подписываете этот hex в своём коде и передаёте подписанную транзакцию в POST /v2/tron/transactions/broadcast.
curl --request POST\ --url https://api.chaingateway.io/v2/tron/transactions/trc20/build\ --header 'Accept: application/json'\ --header 'content-type: application/json'\ --header 'Authorization: YOUR_API_TOKEN'\ --data '{ "from": "TLkkCeNdJKPNUwucdro84WjswkzM62LCTH", "to": "TUwmZghA7u2GxGxKaxM1mkCmsTF4wHs4vp", "contractaddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "amount": 1}'Ответ содержит raw_data и raw_data_hex. На этом этапе ничего ещё не отправлено в сеть.
Уведомления о входящих токенах
Заголовок раздела «Уведомления о входящих токенах»Чтобы узнать о депозите TRC20 без опроса (polling), подпишите вебхук с type, равным TRC20, и contractaddress токена. Фильтры from и to сужают отслеживание до одного адреса.
curl --request POST\ --url https://api.chaingateway.io/v2/tron/webhooks\ --header 'Accept: application/json'\ --header 'content-type: application/json'\ --header 'Authorization: YOUR_API_TOKEN'\ --data '{ "url": "https://example.com/webhook-receiver", "type": "TRC20", "contractaddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "to": "TUwmZghA7u2GxGxKaxM1mkCmsTF4wHs4vp"}'Написание приёмной стороны разбирается в разделе Создание вебхуков, а проверка того, что уведомление действительно пришло от Chaingateway, — в разделе Защита вебхуков.
Уведомление, которое ваш сервер не принял, само по себе повторно не отправляется. Неудачные уведомления перечислены в GET /v2/tron/webhooks/notifications/failed, и их можно инициировать повторно через POST /v2/tron/webhooks/notifications/{id}/retry.
Тестирование в Nile
Заголовок раздела «Тестирование в Nile»Каждый вызов выше работает и в тестовой сети TRON Nile. Добавьте заголовок X-Network: testnet и используйте тестовые токены вместо контрактов mainnet. Список сетей задокументирован в разделе Поддерживаемые сети.