<YOUR_KEY> with the key of one of your endpoints and
TXYZ… with a real address. The WU in the comments are what Node API charges for exactly these calls.
Connect
The first call reads account data — 1 WU..proto files and takes addresses as base64 bytes — see gRPC.
Send USDT
Build the transaction through the node, sign it on your side, broadcast it through the node. Your private key never leaves your server. One transfer costs 2 WU; with tronpy 3 WU, plus 2 WU once to load the contract. In these examplesfrom (sender) and to are the sender’s and the recipient’s addresses, amount
is in the token’s smallest unit (USDT has 6 decimals: 1 USDT = 1000000), and PRIVATE_KEY is the
sender’s private key. fee_limit is the most TRX, in sun, the transfer may burn: 30000000 is 30 TRX.
parameter is the ABI-encoded arguments of transfer(address,uint256) in hex: the
recipient’s 20-byte address (its hex form without the leading 41) left-padded with zeros to 64 hex
characters, then the amount, also padded to 64. The node answers with an unsigned transaction and
its txID. Sign txID with the sender’s private key, add the signature to the transaction as
"signature": ["<hex>"], and send that transaction object as signed.json.
With grpcurl, call.json is a TriggerSmartContract message: owner_address, contract_address
and data (the 4-byte function selector followed by the ABI-encoded arguments), all as base64 bytes.
The message has no fee limit field: set raw_data.fee_limit on the returned transaction, then sign
the SHA-256 of the new raw_data — the txid that came back no longer matches after that change. See
gRPC.
Watch USDT transfers
Read the newest block header, then the receipts of that block, and keep the USDT ones. The header is 1 WU and the receipts of a fresh block 2 WU — 3 WU per block. Following every block of the chain this way is about 2.6M WU a month.Transfer events in log. In an event, topics[0]
is ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, topics[1] and topics[2] are
the sender and the recipient (the last 40 hex characters are the address without its 41 prefix), and
data is the amount. receipt.result is SUCCESS for a transfer that went through. The filter above
keeps direct calls to the USDT contract; to also catch USDT moved by other contracts, check the
address of every log entry instead — a614f803b6fd780986a42c78ec9c7f77e6ded13c for USDT.
A new block arrives about every 3 seconds. Remember the last block you processed and fetch receipts for
every number after it, so a slow poll never skips a block. Receipts of a block deeper than 20 below the
head are no longer fresh and are charged by their size — see Quota units.