Step 1 - Setup Gas wallet Allowance
To initiate an TRC-20 approve transaction, replace the token, source wallet, gas wallet, bearer token, vault ID and run the following code:
from tronpy import Tron
from tronpy.keys import to_hex_address
from eth_abi.abi import encode as encode_abi
from eth_utils import keccak
import requests
# Tron Shasta network connection
client = Tron(network='shasta')
# Define relevant addresses
token_address = 'TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs' # USDT on Shasta
source_wallet = 'TN2QSXwq4jvuvjXyWdGX1Kve3gaGUM7eEW' # Token holder
gas_wallet = 'TQQ52wvmP159cPR2PwUAncJzhh9icdhuRH' # Sponsor (spender)
# Encode function call: approve(address spender, uint256 amount)
amount = 1 * 10**6 # 1 USDT in smallest units
Prepare the TRC-20 call data:
spender_hex = to_hex_address(gas_wallet)
spender_bytes = bytes.fromhex(spender_hex[2:])
selector = keccak(text="approve(address,uint256)")[:4].hex()
args_encoded = encode_abi(['address', 'uint256'], [spender_bytes, amount]).hex()
calldata = "0x" + selector + args_encoded
Initiate a tronTriggerSmartContract transaction:
# Construct Utila-compatible payload
vault_id = "YOUR_VAULT_ID"
url = f"https://api.utila.io/v2/vaults/{vault_id}/transactions:initiate"
payload = {
"details": {
"tronTriggerSmartContract": {
"network": "networks/tron-testnet-shasta",
"ownerAddress": source_wallet,
"contractAddress": token_address,
"callValue": "0",
"data": calldata
}
},
"note": "Token Approval - Tron Shasta",
"includeReferencedResources": True
}
# Submit to Utila
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_BEARER_TOKEN"
}
response = requests.post(url, json=payload, headers=headers)
print(response.status_code)
print(response.json())
After internal approval and signing, the transaction will appear in the console as:
Step 2 - Initiate transferFrom by the Gas wallet
Similarly, set a destination wallet address and initiate an ERC20 transferFrom transaction:
destination_wallet = "TE14iNUCWfGegXjEgMffEQVC1fGi3WJB3U"
amount = int(0.05 * (10 ** 6)) # Amount to approve (1 USDC = 1 * 10^6 because USDT has 6 decimals)
source_bytes = bytes.fromhex(to_hex_address(source_wallet)[2:])
destination_bytes = bytes.fromhex(to_hex_address(destination_wallet)[2:])
selector = keccak(text="transferFrom(address,address,uint256)")[:4].hex()
args_encoded = encode_abi(['address', 'address', 'uint256'], [source_bytes, destination_bytes, amount]).hex()
calldata = "0x" + selector + args_encoded
# Prepare payload
vault_id = "YOUR_VAULT_ID"
url = f"https://api.utila.io/v2/vaults/{vault_id}/transactions:initiate"
payload = {
"details": {
"tronTriggerSmartContract": {
"network": "networks/tron-testnet-shasta",
"ownerAddress": gas_wallet,
"contractAddress": token_address,
"callValue": "0",
"data": calldata
}
},
"note": "Token TransferFrom - Tron Shasta",
"includeReferencedResources": True
}
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_BEARER_TOKEN"
}
response = requests.post(url, json=payload, headers=headers)
print(response.status_code)
print(response.json())
After internal approval and signing, the transaction will appear in the console as: