wallet/triggersmartcontract
Lightning-Fast Smart Contract Calls
Dwellir's TRON endpoints execute smart contract calls in under 30ms with comprehensive error handling. Build powerful DeFi and Web3 applications with our optimized contract interaction API.
Executes smart contract functions on the TRON network. Use this method to call contract functions, read contract state, and interact with TRC20/TRC721 tokens.
When to Use This Method
wallet/triggersmartcontract
is essential for:
- TRC20 Token Operations - Transfer, approve, check balances
- DeFi Protocol Interactions - Swap, stake, lend, borrow
- NFT Operations - Mint, transfer, query TRC721 tokens
- Contract State Queries - Read public variables and view functions
- Smart Contract Execution - Call payable and non-payable functions
Parameters
-
contract_address -
string
(required)- Smart contract address in Base58 format
- Example:
"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
(USDT)
-
function_selector -
string
(required)- Function signature to call
- Example:
"balanceOf(address)"
,"transfer(address,uint256)"
-
parameter -
string
(optional)- Hex-encoded function parameters
- Example:
"0000000000000000000000004142b5e01c8c59a25d78acdbec2bfc7e89e5e863"
-
owner_address -
string
(required)- Address calling the contract
- Example:
"TJmmqjb1DK9TTZbQXzRQ2AuA94z4gKAPFh"
-
call_value -
integer
(optional)- TRX amount to send (in SUN) for payable functions
- Default:
0
-
visible -
boolean
(optional, default: false)true
- Use Base58 address formatfalse
- Use hex address format
{
"contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"function_selector": "balanceOf(address)",
"parameter": "0000000000000000000000004142b5e01c8c59a25d78acdbec2bfc7e89e5e863",
"owner_address": "TJmmqjb1DK9TTZbQXzRQ2AuA94z4gKAPFh",
"visible": true
}
Returns
Contract Result containing:
result
- Execution success/failureconstant_result
- Array of result data (for view functions)transaction
- Transaction object (for state-changing functions)energy_used
- Energy consumedenergy_penalty
- Additional energy costresult_message
- Error message (if failed)
Implementation Examples
- JavaScript
- Python
- cURL
const TRON_API = 'https://api-tron-mainnet.n.dwellir.com/YOUR_API_KEY';
// Smart contract interaction helper
class TronSmartContract {
constructor(apiKey, contractAddress) {
this.apiKey = apiKey;
this.contractAddress = contractAddress;
this.apiUrl = `${TRON_API}`;
}
async call(functionSelector, parameters = '', ownerAddress, callValue = 0) {
const response = await fetch(`${this.apiUrl}/wallet/triggersmartcontract`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
contract_address: this.contractAddress,
function_selector: functionSelector,
parameter: parameters,
owner_address: ownerAddress,
call_value: callValue,
visible: true
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
// Helper method to encode address parameter
encodeAddress(address) {
// Convert Base58 to hex and pad to 64 characters
const hexAddress = this.base58ToHex(address);
return hexAddress.toLowerCase().padStart(64, '0');
}
// Helper method to encode uint256 parameter
encodeUint256(value) {
return BigInt(value).toString(16).padStart(64, '0');
}
// Helper method to decode result
decodeResult(hexResult, type = 'uint256') {
if (!hexResult || hexResult === '0x') return null;
// Remove 0x prefix if present
const cleanHex = hexResult.replace(/^0x/, '');
switch (type) {
case 'uint256':
return BigInt('0x' + cleanHex).toString();
case 'address':
// Extract address from padded hex
const addressHex = cleanHex.slice(-40);
return this.hexToBase58(addressHex);
case 'bool':
return cleanHex === '1' || cleanHex.endsWith('1');
case 'string':
// Decode string from hex
const bytes = cleanHex.match(/.{2}/g) || [];
return bytes.map(byte => String.fromCharCode(parseInt(byte, 16))).join('');
default:
return cleanHex;
}
}
base58ToHex(base58Address) {
// Simplified conversion - use proper library in production
// This is a placeholder implementation
return base58Address; // Would need actual conversion
}
hexToBase58(hexAddress) {
// Simplified conversion - use proper library in production
return hexAddress; // Would need actual conversion
}
}
// TRC20 Token interaction class
class TRC20Token extends TronSmartContract {
async getBalance(walletAddress) {
try {
const encodedAddress = this.encodeAddress(walletAddress);
const result = await this.call('balanceOf(address)', encodedAddress, walletAddress);
if (result.result?.result && result.constant_result?.[0]) {
const balance = this.decodeResult(result.constant_result[0], 'uint256');
return balance;
}
throw new Error('Failed to get balance');
} catch (error) {
console.error('Error getting balance:', error);
throw error;
}
}
async getDecimals() {
try {
const result = await this.call('decimals()', '', this.contractAddress);
if (result.result?.result && result.constant_result?.[0]) {
return parseInt(this.decodeResult(result.constant_result[0], 'uint256'));
}
return 6; // Default for most TRC20 tokens
} catch (error) {
console.error('Error getting decimals:', error);
return 6;
}
}
async getSymbol() {
try {
const result = await this.call('symbol()', '', this.contractAddress);
if (result.result?.result && result.constant_result?.[0]) {
return this.decodeResult(result.constant_result[0], 'string');
}
throw new Error('Failed to get symbol');
} catch (error) {
console.error('Error getting symbol:', error);
throw error;
}
}
async getName() {
try {
const result = await this.call('name()', '', this.contractAddress);
if (result.result?.result && result.constant_result?.[0]) {
return this.decodeResult(result.constant_result[0], 'string');
}
throw new Error('Failed to get name');
} catch (error) {
console.error('Error getting name:', error);
throw error;
}
}
async getTotalSupply() {
try {
const result = await this.call('totalSupply()', '', this.contractAddress);
if (result.result?.result && result.constant_result?.[0]) {
return this.decodeResult(result.constant_result[0], 'uint256');
}
throw new Error('Failed to get total supply');
} catch (error) {
console.error('Error getting total supply:', error);
throw error;
}
}
// Create transfer transaction (returns unsigned transaction)
async createTransfer(fromAddress, toAddress, amount) {
try {
const encodedTo = this.encodeAddress(toAddress);
const encodedAmount = this.encodeUint256(amount);
const parameters = encodedTo + encodedAmount;
const result = await this.call(
'transfer(address,uint256)',
parameters,
fromAddress
);
if (result.result?.result) {
return result.transaction;
}
throw new Error(`Transfer creation failed: ${result.result?.message || 'Unknown error'}`);
} catch (error) {
console.error('Error creating transfer:', error);
throw error;
}
}
async getAllowance(ownerAddress, spenderAddress) {
try {
const encodedOwner = this.encodeAddress(ownerAddress);
const encodedSpender = this.encodeAddress(spenderAddress);
const parameters = encodedOwner + encodedSpender;
const result = await this.call(
'allowance(address,address)',
parameters,
ownerAddress
);
if (result.result?.result && result.constant_result?.[0]) {
return this.decodeResult(result.constant_result[0], 'uint256');
}
return '0';
} catch (error) {
console.error('Error getting allowance:', error);
throw error;
}
}
}
// DeFi protocol interaction example
class TronDeFiProtocol extends TronSmartContract {
async getPoolInfo(poolId) {
try {
const encodedPoolId = this.encodeUint256(poolId);
const result = await this.call('poolInfo(uint256)', encodedPoolId, this.contractAddress);
if (result.result?.result && result.constant_result?.[0]) {
// Decode pool info struct - simplified example
const poolData = result.constant_result[0];
return {
lpToken: this.decodeResult(poolData.slice(0, 64), 'address'),
allocPoint: this.decodeResult(poolData.slice(64, 128), 'uint256'),
lastRewardBlock: this.decodeResult(poolData.slice(128, 192), 'uint256'),
accTokenPerShare: this.decodeResult(poolData.slice(192, 256), 'uint256')
};
}
throw new Error('Failed to get pool info');
} catch (error) {
console.error('Error getting pool info:', error);
throw error;
}
}
async getUserInfo(poolId, userAddress) {
try {
const encodedPoolId = this.encodeUint256(poolId);
const encodedUser = this.encodeAddress(userAddress);
const parameters = encodedPoolId + encodedUser;
const result = await this.call('userInfo(uint256,address)', parameters, userAddress);
if (result.result?.result && result.constant_result?.[0]) {
const userData = result.constant_result[0];
return {
amount: this.decodeResult(userData.slice(0, 64), 'uint256'),
rewardDebt: this.decodeResult(userData.slice(64, 128), 'uint256')
};
}
throw new Error('Failed to get user info');
} catch (error) {
console.error('Error getting user info:', error);
throw error;
}
}
}
// Usage examples
(async () => {
try {
// USDT TRC20 token interaction
const USDT_CONTRACT = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';
const usdt = new TRC20Token('YOUR_API_KEY', USDT_CONTRACT);
const walletAddress = 'TRX6Q82wMqWNbCCmJPLz9mR8AZwqvUU2pN';
// Get token information
const [balance, decimals, symbol, name] = await Promise.all([
usdt.getBalance(walletAddress),
usdt.getDecimals(),
usdt.getSymbol(),
usdt.getName()
]);
console.log(`Token: ${name} (${symbol})`);
console.log(`Balance: ${balance / Math.pow(10, decimals)} ${symbol}`);
// Create transfer transaction
const transferTx = await usdt.createTransfer(
'TJmmqjb1DK9TTZbQXzRQ2AuA94z4gKAPFh',
'TRX6Q82wMqWNbCCmJPLz9mR8AZwqvUU2pN',
1000000 // 1 USDT (6 decimals)
);
console.log('Transfer transaction created:', transferTx.txID);
// Check allowance
const allowance = await usdt.getAllowance(
'TJmmqjb1DK9TTZbQXzRQ2AuA94z4gKAPFh',
'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'
);
console.log('Allowance:', allowance);
} catch (error) {
console.error('Error:', error);
}
})();
import requests
import json
from typing import Dict, List, Optional, Union
class TronSmartContract:
def __init__(self, api_key: str, contract_address: str):
self.api_key = api_key
self.contract_address = contract_address
self.base_url = f"https://api-tron-mainnet.n.dwellir.com/{api_key}"
self.headers = {
'Content-Type': 'application/json'
}
def call(self, function_selector: str, parameters: str = '',
owner_address: str = None, call_value: int = 0) -> Dict:
"""Call smart contract function"""
url = f"{self.base_url}/wallet/triggersmartcontract"
payload = {
"contract_address": self.contract_address,
"function_selector": function_selector,
"parameter": parameters,
"owner_address": owner_address or self.contract_address,
"call_value": call_value,
"visible": True
}
response = requests.post(url, headers=self.headers, json=payload)
response.raise_for_status()
return response.json()
def encode_address(self, address: str) -> str:
"""Encode address for contract parameters"""
# Simplified encoding - use proper library in production
# Remove 'T' prefix and convert to hex representation
return address.replace('T', '').lower().zfill(64)
def encode_uint256(self, value: Union[int, str]) -> str:
"""Encode uint256 for contract parameters"""
return format(int(value), '064x')
def decode_result(self, hex_result: str, result_type: str = 'uint256'):
"""Decode contract call result"""
if not hex_result or hex_result == '0x':
return None
# Remove 0x prefix if present
clean_hex = hex_result.replace('0x', '')
if result_type == 'uint256':
return str(int(clean_hex, 16))
elif result_type == 'bool':
return clean_hex.endswith('1')
elif result_type == 'string':
# Simplified string decoding
try:
bytes_data = bytes.fromhex(clean_hex)
return bytes_data.decode('utf-8').rstrip('\x00')
except:
return clean_hex
else:
return clean_hex
class TRC20Token(TronSmartContract):
"""TRC20 token interaction class"""
def get_balance(self, wallet_address: str) -> str:
"""Get token balance for address"""
try:
encoded_address = self.encode_address(wallet_address)
result = self.call('balanceOf(address)', encoded_address, wallet_address)
if result.get('result', {}).get('result') and result.get('constant_result'):
balance = self.decode_result(result['constant_result'][0], 'uint256')
return balance
raise Exception('Failed to get balance')
except Exception as e:
print(f"Error getting balance: {e}")
raise
def get_decimals(self) -> int:
"""Get token decimals"""
try:
result = self.call('decimals()', '', self.contract_address)
if result.get('result', {}).get('result') and result.get('constant_result'):
return int(self.decode_result(result['constant_result'][0], 'uint256'))
return 6 # Default for most TRC20 tokens
except Exception as e:
print(f"Error getting decimals: {e}")
return 6
def get_symbol(self) -> str:
"""Get token symbol"""
try:
result = self.call('symbol()', '', self.contract_address)
if result.get('result', {}).get('result') and result.get('constant_result'):
return self.decode_result(result['constant_result'][0], 'string')
raise Exception('Failed to get symbol')
except Exception as e:
print(f"Error getting symbol: {e}")
raise
def get_name(self) -> str:
"""Get token name"""
try:
result = self.call('name()', '', self.contract_address)
if result.get('result', {}).get('result') and result.get('constant_result'):
return self.decode_result(result['constant_result'][0], 'string')
raise Exception('Failed to get name')
except Exception as e:
print(f"Error getting name: {e}")
raise
def get_total_supply(self) -> str:
"""Get total token supply"""
try:
result = self.call('totalSupply()', '', self.contract_address)
if result.get('result', {}).get('result') and result.get('constant_result'):
return self.decode_result(result['constant_result'][0], 'uint256')
raise Exception('Failed to get total supply')
except Exception as e:
print(f"Error getting total supply: {e}")
raise
def create_transfer(self, from_address: str, to_address: str, amount: int) -> Dict:
"""Create transfer transaction"""
try:
encoded_to = self.encode_address(to_address)
encoded_amount = self.encode_uint256(amount)
parameters = encoded_to + encoded_amount
result = self.call('transfer(address,uint256)', parameters, from_address)
if result.get('result', {}).get('result'):
return result['transaction']
raise Exception(f"Transfer creation failed: {result.get('result', {}).get('message', 'Unknown error')}")
except Exception as e:
print(f"Error creating transfer: {e}")
raise
def get_allowance(self, owner_address: str, spender_address: str) -> str:
"""Get allowance amount"""
try:
encoded_owner = self.encode_address(owner_address)
encoded_spender = self.encode_address(spender_address)
parameters = encoded_owner + encoded_spender
result = self.call('allowance(address,address)', parameters, owner_address)
if result.get('result', {}).get('result') and result.get('constant_result'):
return self.decode_result(result['constant_result'][0], 'uint256')
return '0'
except Exception as e:
print(f"Error getting allowance: {e}")
raise
def get_formatted_balance(self, wallet_address: str) -> Dict:
"""Get formatted balance with token info"""
try:
balance_raw = self.get_balance(wallet_address)
decimals = self.get_decimals()
symbol = self.get_symbol()
balance_formatted = float(balance_raw) / (10 ** decimals)
return {
'raw': balance_raw,
'formatted': balance_formatted,
'decimals': decimals,
'symbol': symbol
}
except Exception as e:
print(f"Error getting formatted balance: {e}")
raise
class TronDeFiProtocol(TronSmartContract):
"""DeFi protocol interaction example"""
def get_pool_info(self, pool_id: int) -> Dict:
"""Get liquidity pool information"""
try:
encoded_pool_id = self.encode_uint256(pool_id)
result = self.call('poolInfo(uint256)', encoded_pool_id, self.contract_address)
if result.get('result', {}).get('result') and result.get('constant_result'):
pool_data = result['constant_result'][0]
# Decode pool info struct (simplified)
return {
'lp_token': pool_data[0:64], # Would need proper address decoding
'alloc_point': self.decode_result(pool_data[64:128], 'uint256'),
'last_reward_block': self.decode_result(pool_data[128:192], 'uint256'),
'acc_token_per_share': self.decode_result(pool_data[192:256], 'uint256')
}
raise Exception('Failed to get pool info')
except Exception as e:
print(f"Error getting pool info: {e}")
raise
def get_user_info(self, pool_id: int, user_address: str) -> Dict:
"""Get user staking information"""
try:
encoded_pool_id = self.encode_uint256(pool_id)
encoded_user = self.encode_address(user_address)
parameters = encoded_pool_id + encoded_user
result = self.call('userInfo(uint256,address)', parameters, user_address)
if result.get('result', {}).get('result') and result.get('constant_result'):
user_data = result['constant_result'][0]
return {
'amount': self.decode_result(user_data[0:64], 'uint256'),
'reward_debt': self.decode_result(user_data[64:128], 'uint256')
}
raise Exception('Failed to get user info')
except Exception as e:
print(f"Error getting user info: {e}")
raise
class TronContractManager:
"""Manage multiple contract interactions"""
def __init__(self, api_key: str):
self.api_key = api_key
self.contracts = {}
# Popular TRON contracts
self.popular_contracts = {
'USDT': 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
'USDC': 'TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8',
'WTRX': 'TNUC9Qb1rRpS5CbWLmNMxXBjyFoydXjWFR',
'JST': 'TCFLL5dx5ZJdKnWuesXxi1VPwjLVmWZZy9'
}
def get_token(self, symbol_or_address: str) -> TRC20Token:
"""Get TRC20 token instance"""
address = self.popular_contracts.get(symbol_or_address, symbol_or_address)
if address not in self.contracts:
self.contracts[address] = TRC20Token(self.api_key, address)
return self.contracts[address]
def get_portfolio_balances(self, wallet_address: str, tokens: List[str] = None) -> Dict:
"""Get balances for multiple tokens"""
if tokens is None:
tokens = list(self.popular_contracts.keys())
portfolio = {}
for token_symbol in tokens:
try:
token = self.get_token(token_symbol)
balance_info = token.get_formatted_balance(wallet_address)
portfolio[token_symbol] = balance_info
except Exception as e:
portfolio[token_symbol] = {'error': str(e)}
return portfolio
def batch_contract_calls(self, calls: List[Dict]) -> List[Dict]:
"""Execute multiple contract calls"""
results = []
for call in calls:
try:
contract = TronSmartContract(self.api_key, call['contract_address'])
result = contract.call(
call['function_selector'],
call.get('parameters', ''),
call.get('owner_address', call['contract_address'])
)
results.append({
'success': True,
'call': call,
'result': result
})
except Exception as e:
results.append({
'success': False,
'call': call,
'error': str(e)
})
return results
# Usage examples
if __name__ == "__main__":
manager = TronContractManager('YOUR_API_KEY')
try:
# Get USDT token info
usdt = manager.get_token('USDT')
wallet_address = 'TRX6Q82wMqWNbCCmJPLz9mR8AZwqvUU2pN'
# Get token information
name = usdt.get_name()
symbol = usdt.get_symbol()
decimals = usdt.get_decimals()
balance_info = usdt.get_formatted_balance(wallet_address)
print(f"Token: {name} ({symbol})")
print(f"Decimals: {decimals}")
print(f"Balance: {balance_info['formatted']} {balance_info['symbol']}")
# Get portfolio balances
portfolio = manager.get_portfolio_balances(wallet_address, ['USDT', 'USDC', 'JST'])
print("\nPortfolio:")
for token, info in portfolio.items():
if 'error' in info:
print(f"{token}: Error - {info['error']}")
else:
print(f"{token}: {info['formatted']} {info['symbol']}")
# Batch contract calls example
batch_calls = [
{
'contract_address': 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
'function_selector': 'name()',
'owner_address': wallet_address
},
{
'contract_address': 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
'function_selector': 'symbol()',
'owner_address': wallet_address
}
]
batch_results = manager.batch_contract_calls(batch_calls)
print(f"\nBatch calls completed: {len([r for r in batch_results if r['success']])}/{len(batch_results)} successful")
except Exception as e:
print(f"Error: {e}")
# Get TRC20 token balance (USDT)
curl -X POST "https://api-tron-mainnet.n.dwellir.com/YOUR_API_KEY/wallet/triggersmartcontract" \
-H "Content-Type: application/json" \
-d '{
"contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"function_selector": "balanceOf(address)",
"parameter": "0000000000000000000000004142b5e01c8c59a25d78acdbec2bfc7e89e5e863",
"owner_address": "TRX6Q82wMqWNbCCmJPLz9mR8AZwqvUU2pN",
"visible": true
}'
# Get token symbol
curl -X POST "https://api-tron-mainnet.n.dwellir.com/YOUR_API_KEY/wallet/triggersmartcontract" \
-H "Content-Type: application/json" \
-d '{
"contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"function_selector": "symbol()",
"owner_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"visible": true
}'
# Get token decimals
curl -X POST "https://api-tron-mainnet.n.dwellir.com/YOUR_API_KEY/wallet/triggersmartcontract" \
-H "Content-Type: application/json" \
-d '{
"contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"function_selector": "decimals()",
"owner_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"visible": true
}'
# Create TRC20 transfer transaction
curl -X POST "https://api-tron-mainnet.n.dwellir.com/YOUR_API_KEY/wallet/triggersmartcontract" \
-H "Content-Type: application/json" \
-d '{
"contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"function_selector": "transfer(address,uint256)",
"parameter": "0000000000000000000000004142b5e01c8c59a25d78acdbec2bfc7e89e5e86300000000000000000000000000000000000000000000000000000000000f4240",
"owner_address": "TJmmqjb1DK9TTZbQXzRQ2AuA94z4gKAPFh",
"visible": true
}'
# Parse and format token balance
curl -s -X POST "https://api-tron-mainnet.n.dwellir.com/YOUR_API_KEY/wallet/triggersmartcontract" \
-H "Content-Type: application/json" \
-d '{
"contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"function_selector": "balanceOf(address)",
"parameter": "0000000000000000000000004142b5e01c8c59a25d78acdbec2bfc7e89e5e863",
"owner_address": "TRX6Q82wMqWNbCCmJPLz9mR8AZwqvUU2pN",
"visible": true
}' | jq '{
success: .result.result,
balance_hex: .constant_result[0],
balance_decimal: (.constant_result[0] | if . then (. | tonumber) else 0 end),
energy_used: .energy_used
}'
# Batch token information script
#!/bin/bash
API_KEY="YOUR_API_KEY"
CONTRACT_ADDRESS="TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t" # USDT
WALLET_ADDRESS="TRX6Q82wMqWNbCCmJPLz9mR8AZwqvUU2pN"
echo "Fetching token information for $CONTRACT_ADDRESS..."
# Function to call smart contract
call_contract() {
local function_selector=$1
local parameters=${2:-""}
local owner_address=${3:-$CONTRACT_ADDRESS}
curl -s -X POST "https://api-tron-mainnet.n.dwellir.com/$API_KEY/wallet/triggersmartcontract" \
-H "Content-Type: application/json" \
-d "{
\"contract_address\": \"$CONTRACT_ADDRESS\",
\"function_selector\": \"$function_selector\",
\"parameter\": \"$parameters\",
\"owner_address\": \"$owner_address\",
\"visible\": true
}"
}
# Convert address to parameter format (simplified)
address_to_param() {
local address=$1
# This is a simplified conversion - use proper tools in production
echo "0000000000000000000000004142b5e01c8c59a25d78acdbec2bfc7e89e5e863"
}
# Get token name
echo "Getting token name..."
NAME_RESULT=$(call_contract "name()")
echo "Name result: $NAME_RESULT" | jq '.constant_result[0]'
# Get token symbol
echo "Getting token symbol..."
SYMBOL_RESULT=$(call_contract "symbol()")
echo "Symbol result: $SYMBOL_RESULT" | jq '.constant_result[0]'
# Get token decimals
echo "Getting token decimals..."
DECIMALS_RESULT=$(call_contract "decimals()")
DECIMALS=$(echo "$DECIMALS_RESULT" | jq -r '.constant_result[0]' | xargs printf "%d")
echo "Decimals: $DECIMALS"
# Get total supply
echo "Getting total supply..."
SUPPLY_RESULT=$(call_contract "totalSupply()")
SUPPLY_HEX=$(echo "$SUPPLY_RESULT" | jq -r '.constant_result[0]')
SUPPLY_DECIMAL=$(printf "%d" "0x$SUPPLY_HEX")
echo "Total supply: $SUPPLY_DECIMAL"
# Get balance for specific address
echo "Getting balance for $WALLET_ADDRESS..."
ADDRESS_PARAM=$(address_to_param "$WALLET_ADDRESS")
BALANCE_RESULT=$(call_contract "balanceOf(address)" "$ADDRESS_PARAM" "$WALLET_ADDRESS")
BALANCE_HEX=$(echo "$BALANCE_RESULT" | jq -r '.constant_result[0]')
BALANCE_DECIMAL=$(printf "%d" "0x$BALANCE_HEX")
echo "Balance: $BALANCE_DECIMAL"
# Calculate formatted balance
if [ "$DECIMALS" -gt 0 ]; then
FORMATTED_BALANCE=$(echo "scale=6; $BALANCE_DECIMAL / (10^$DECIMALS)" | bc -l)
echo "Formatted balance: $FORMATTED_BALANCE"
fi
# DeFi protocol interaction example
query_defi_pool() {
local defi_contract=$1
local pool_id=$2
local user_address=$3
echo "Querying DeFi pool $pool_id for user $user_address..."
# Pool info
POOL_ID_HEX=$(printf "%064x" "$pool_id")
POOL_RESULT=$(call_contract "poolInfo(uint256)" "$POOL_ID_HEX" "$defi_contract")
echo "Pool info: $POOL_RESULT" | jq '.constant_result[0]'
# User info
USER_PARAM="${POOL_ID_HEX}$(address_to_param "$user_address")"
USER_RESULT=$(call_contract "userInfo(uint256,address)" "$USER_PARAM" "$user_address")
echo "User info: $USER_RESULT" | jq '.constant_result[0]'
}
# Multi-token balance checker
check_multiple_tokens() {
local wallet_address=$1
# Define popular TRON tokens
declare -A TOKENS=(
["USDT"]="TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
["USDC"]="TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8"
["JST"]="TCFLL5dx5ZJdKnWuesXxi1VPwjLVmWZZy9"
["WTRX"]="TNUC9Qb1rRpS5CbWLmNMxXBjyFoydXjWFR"
)
echo "Checking token balances for $wallet_address..."
echo "=========================================="
for token_name in "${!TOKENS[@]}"; do
local token_address="${TOKENS[$token_name]}"
echo "Checking $token_name ($token_address)..."
# Get balance
local address_param=$(address_to_param "$wallet_address")
local balance_result=$(curl -s -X POST "https://api-tron-mainnet.n.dwellir.com/$API_KEY/wallet/triggersmartcontract" \
-H "Content-Type: application/json" \
-d "{
\"contract_address\": \"$token_address\",
\"function_selector\": \"balanceOf(address)\",
\"parameter\": \"$address_param\",
\"owner_address\": \"$wallet_address\",
\"visible\": true
}")
local balance_hex=$(echo "$balance_result" | jq -r '.constant_result[0] // "0"')
local balance_decimal=$(printf "%d" "0x$balance_hex" 2>/dev/null || echo "0")
echo "$token_name balance: $balance_decimal"
echo ""
done
}
# Usage examples
case "${1:-info}" in
"info")
# Default: show token info
;;
"balance")
check_multiple_tokens "$2"
;;
"defi")
query_defi_pool "$2" "$3" "$4"
;;
*)
echo "Usage: $0 {info|balance WALLET_ADDRESS|defi CONTRACT_ADDRESS POOL_ID USER_ADDRESS}"
;;
esac
Response Examples
Successful View Function Call (balanceOf)
{
"result": {
"result": true
},
"energy_used": 345,
"constant_result": [
"0000000000000000000000000000000000000000000000000000000005f5e100"
],
"transaction": {
"ret": [{}],
"visible": true,
"txID": "70c8e5b0b4e13a7e5a1b0e8d7c6b5a4a39291807f6e5d4c3b2a19080f0e0d0c0b0",
"raw_data": {
"contract": [
{
"parameter": {
"value": {
"data": "70a082310000000000000000000000004142b5e01c8c59a25d78acdbec2bfc7e89e5e863",
"owner_address": "TJmmqjb1DK9TTZbQXzRQ2AuA94z4gKAPFh",
"contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
},
"type_url": "type.googleapis.com/protocol.TriggerSmartContract"
},
"type": "TriggerSmartContract"
}
],
"ref_block_bytes": "4a7b",
"ref_block_hash": "e15e44aa73bd9e15",
"expiration": 1734567890000,
"timestamp": 1734567830000
}
}
}
Failed Contract Call
{
"result": {
"result": false,
"code": "REVERT",
"message": "REVERT opcode executed"
},
"energy_used": 250
}
State-Changing Function Call (Transfer)
{
"result": {
"result": true
},
"energy_used": 13326,
"energy_penalty": 0,
"transaction": {
"visible": true,
"txID": "a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890",
"raw_data": {
"contract": [
{
"parameter": {
"value": {
"data": "a9059cbb0000000000000000000000004142b5e01c8c59a25d78acdbec2bfc7e89e5e86300000000000000000000000000000000000000000000000000000000000f4240",
"owner_address": "TJmmqjb1DK9TTZbQXzRQ2AuA94z4gKAPFh",
"contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
},
"type_url": "type.googleapis.com/protocol.TriggerSmartContract"
},
"type": "TriggerSmartContract"
}
],
"ref_block_bytes": "4a7b",
"ref_block_hash": "e15e44aa73bd9e15",
"expiration": 1734567890000,
"timestamp": 1734567830000
}
}
}
Common Use Cases
1. Portfolio Tracker
class TronPortfolioTracker {
constructor(apiKey) {
this.manager = new TronContractManager(apiKey);
this.supportedTokens = {
'USDT': 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
'USDC': 'TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8',
'JST': 'TCFLL5dx5ZJdKnWuesXxi1VPwjLVmWZZy9',
'WTRX': 'TNUC9Qb1rRpS5CbWLmNMxXBjyFoydXjWFR',
'TUSD': 'TUpMhErZL2fhh4sVNULAbNKLokS4GjC1F4'
};
}
async getPortfolio(walletAddress, includeMetadata = true) {
const portfolio = {
address: walletAddress,
tokens: {},
totalValueUSD: 0,
lastUpdated: new Date().toISOString()
};
for (const [symbol, contractAddress] of Object.entries(this.supportedTokens)) {
try {
const token = this.manager.getToken(contractAddress);
const balanceInfo = await token.getFormattedBalance(walletAddress);
portfolio.tokens[symbol] = {
...balanceInfo,
contractAddress,
valueUSD: await this.getTokenValueUSD(symbol, balanceInfo.formatted)
};
if (includeMetadata) {
const [name, totalSupply] = await Promise.all([
token.getName(),
token.getTotalSupply()
]);
portfolio.tokens[symbol].name = name;
portfolio.tokens[symbol].totalSupply = totalSupply;
}
portfolio.totalValueUSD += portfolio.tokens[symbol].valueUSD;
} catch (error) {
portfolio.tokens[symbol] = {
error: error.message,
contractAddress
};
}
}
return portfolio;
}
async getTokenValueUSD(symbol, amount) {
// Simplified - would integrate with price API
const prices = {
'USDT': 1.00,
'USDC': 1.00,
'TUSD': 1.00,
'JST': 0.025,
'WTRX': 0.065
};
return (prices[symbol] || 0) * amount;
}
}
2. DeFi Yield Farming Interface
class TronYieldFarming {
constructor(apiKey, farmContractAddress) {
this.contract = new TronSmartContract(apiKey, farmContractAddress);
this.tokenManager = new TronContractManager(apiKey);
}
async getFarmInfo() {
try {
const [poolLength, rewardPerBlock, startBlock] = await Promise.all([
this.contract.call('poolLength()'),
this.contract.call('rewardPerBlock()'),
this.contract.call('startBlock()')
]);
return {
totalPools: this.contract.decodeResult(poolLength.constant_result[0], 'uint256'),
rewardPerBlock: this.contract.decodeResult(rewardPerBlock.constant_result[0], 'uint256'),
startBlock: this.contract.decodeResult(startBlock.constant_result[0], 'uint256')
};
} catch (error) {
console.error('Error getting farm info:', error);
throw error;
}
}
async getPoolInfo(poolId) {
try {
const encodedPoolId = this.contract.encodeUint256(poolId);
const result = await this.contract.call('poolInfo(uint256)', encodedPoolId);
if (result.result?.result && result.constant_result?.[0]) {
const poolData = result.constant_result[0];
return {
lpToken: poolData.slice(24, 64), // Extract address
allocPoint: this.contract.decodeResult(poolData.slice(64, 128), 'uint256'),
lastRewardBlock: this.contract.decodeResult(poolData.slice(128, 192), 'uint256'),
accRewardPerShare: this.contract.decodeResult(poolData.slice(192, 256), 'uint256')
};
}
throw new Error('Failed to get pool info');
} catch (error) {
console.error('Error getting pool info:', error);
throw error;
}
}
async getUserStakeInfo(poolId, userAddress) {
try {
const encodedPoolId = this.contract.encodeUint256(poolId);
const encodedUser = this.contract.encodeAddress(userAddress);
const parameters = encodedPoolId + encodedUser;
const result = await this.contract.call('userInfo(uint256,address)', parameters, userAddress);
if (result.result?.result && result.constant_result?.[0]) {
const userData = result.constant_result[0];
return {
amount: this.contract.decodeResult(userData.slice(0, 64), 'uint256'),
rewardDebt: this.contract.decodeResult(userData.slice(64, 128), 'uint256')
};
}
return { amount: '0', rewardDebt: '0' };
} catch (error) {
console.error('Error getting user stake info:', error);
throw error;
}
}
async getPendingRewards(poolId, userAddress) {
try {
const encodedPoolId = this.contract.encodeUint256(poolId);
const encodedUser = this.contract.encodeAddress(userAddress);
const parameters = encodedPoolId + encodedUser;
const result = await this.contract.call('pendingReward(uint256,address)', parameters, userAddress);
if (result.result?.result && result.constant_result?.[0]) {
return this.contract.decodeResult(result.constant_result[0], 'uint256');
}
return '0';
} catch (error) {
console.error('Error getting pending rewards:', error);
return '0';
}
}
async createStakeTransaction(poolId, amount, userAddress) {
try {
const encodedPoolId = this.contract.encodeUint256(poolId);
const encodedAmount = this.contract.encodeUint256(amount);
const parameters = encodedPoolId + encodedAmount;
const result = await this.contract.call('deposit(uint256,uint256)', parameters, userAddress);
if (result.result?.result) {
return result.transaction;
}
throw new Error(`Stake transaction creation failed: ${result.result?.message || 'Unknown error'}`);
} catch (error) {
console.error('Error creating stake transaction:', error);
throw error;
}
}
}
3. NFT Marketplace Integration
class TronNFTMarketplace {
constructor(apiKey, nftContractAddress) {
this.contract = new TronSmartContract(apiKey, nftContractAddress);
}
async getNFTInfo(tokenId) {
try {
const encodedTokenId = this.contract.encodeUint256(tokenId);
const [owner, tokenURI, approved] = await Promise.all([
this.contract.call('ownerOf(uint256)', encodedTokenId),
this.contract.call('tokenURI(uint256)', encodedTokenId),
this.contract.call('getApproved(uint256)', encodedTokenId)
]);
return {
tokenId: tokenId,
owner: this.contract.decodeResult(owner.constant_result[0], 'address'),
tokenURI: this.contract.decodeResult(tokenURI.constant_result[0], 'string'),
approved: this.contract.decodeResult(approved.constant_result[0], 'address')
};
} catch (error) {
console.error('Error getting NFT info:', error);
throw error;
}
}
async getTokenBalance(owner) {
try {
const encodedOwner = this.contract.encodeAddress(owner);
const result = await this.contract.call('balanceOf(address)', encodedOwner, owner);
if (result.result?.result && result.constant_result?.[0]) {
return this.contract.decodeResult(result.constant_result[0], 'uint256');
}
return '0';
} catch (error) {
console.error('Error getting token balance:', error);
return '0';
}
}
async createTransferTransaction(from, to, tokenId) {
try {
const encodedFrom = this.contract.encodeAddress(from);
const encodedTo = this.contract.encodeAddress(to);
const encodedTokenId = this.contract.encodeUint256(tokenId);
const parameters = encodedFrom + encodedTo + encodedTokenId;
const result = await this.contract.call(
'transferFrom(address,address,uint256)',
parameters,
from
);
if (result.result?.result) {
return result.transaction;
}
throw new Error(`Transfer creation failed: ${result.result?.message || 'Unknown error'}`);
} catch (error) {
console.error('Error creating transfer transaction:', error);
throw error;
}
}
}
4. Automated Trading Bot
class TronTradingBot {
constructor(apiKey, dexContractAddress) {
this.dex = new TronSmartContract(apiKey, dexContractAddress);
this.tokenManager = new TronContractManager(apiKey);
this.strategies = new Map();
}
async getTokenPrice(tokenAddress, baseTokenAddress = 'TNUC9Qb1rRpS5CbWLmNMxXBjyFoydXjWFR') {
try {
const encodedToken = this.dex.encodeAddress(tokenAddress);
const encodedBase = this.dex.encodeAddress(baseTokenAddress);
const parameters = encodedToken + encodedBase;
const result = await this.dex.call('getPrice(address,address)', parameters);
if (result.result?.result && result.constant_result?.[0]) {
return this.dex.decodeResult(result.constant_result[0], 'uint256');
}
return '0';
} catch (error) {
console.error('Error getting token price:', error);
return '0';
}
}
async createSwapTransaction(tokenA, tokenB, amountIn, minAmountOut, userAddress) {
try {
const encodedTokenA = this.dex.encodeAddress(tokenA);
const encodedTokenB = this.dex.encodeAddress(tokenB);
const encodedAmountIn = this.dex.encodeUint256(amountIn);
const encodedMinOut = this.dex.encodeUint256(minAmountOut);
const encodedUser = this.dex.encodeAddress(userAddress);
const parameters = encodedTokenA + encodedTokenB + encodedAmountIn + encodedMinOut + encodedUser;
const result = await this.dex.call(
'swapExactTokensForTokens(address,address,uint256,uint256,address)',
parameters,
userAddress
);
if (result.result?.result) {
return result.transaction;
}
throw new Error(`Swap creation failed: ${result.result?.message || 'Unknown error'}`);
} catch (error) {
console.error('Error creating swap transaction:', error);
throw error;
}
}
addStrategy(name, strategy) {
this.strategies.set(name, strategy);
}
async executeStrategy(strategyName, params) {
const strategy = this.strategies.get(strategyName);
if (!strategy) {
throw new Error(`Strategy ${strategyName} not found`);
}
return await strategy.execute(this, params);
}
}
Error Handling
Error Type | Description | Solution |
---|---|---|
REVERT | Contract execution reverted | Check function parameters and contract state |
OUT_OF_ENERGY | Insufficient energy for execution | Increase energy limit or freeze TRX for energy |
INVALID_ADDRESS | Malformed contract address | Validate contract address format |
FUNCTION_NOT_FOUND | Function doesn't exist | Verify function signature spelling |
ENCODING_ERROR | Parameter encoding failed | Check parameter format and types |
// Comprehensive error handling for smart contract calls
async function safeContractCall(contract, functionSelector, parameters, ownerAddress, options = {}) {
const { maxRetries = 3, energyLimit = 50000000 } = options;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const result = await contract.call(functionSelector, parameters, ownerAddress);
if (result.result?.result) {
return { success: true, result };
} else {
const error = result.result?.message || 'Contract call failed';
if (error.includes('REVERT')) {
throw new Error(`Contract reverted: ${error}`);
} else if (error.includes('OUT_OF_ENERGY')) {
throw new Error('Insufficient energy - consider freezing TRX for energy');
} else {
throw new Error(`Contract error: ${error}`);
}
}
} catch (error) {
console.log(`Attempt ${attempt}/${maxRetries} failed:`, error.message);
if (attempt === maxRetries) {
return {
success: false,
error: error.message,
retryable: error.message.includes('OUT_OF_ENERGY') || error.message.includes('SERVER_BUSY'),
attempts: attempt
};
}
// Exponential backoff
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
}
}
}
Performance Tips
- Batch Contract Calls - Group multiple read operations together
- Cache Results - Cache contract state that doesn't change frequently
- Optimize Parameters - Pre-encode parameters to reduce processing time
- Energy Management - Monitor energy usage and optimize contract interactions
// Optimized contract interaction with caching
class OptimizedContractClient {
constructor(apiKey, contractAddress) {
this.contract = new TronSmartContract(apiKey, contractAddress);
this.cache = new Map();
this.cacheTimeout = 60000; // 1 minute
}
async callWithCache(functionSelector, parameters, cacheKey, ttl = this.cacheTimeout) {
const cached = this.cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < ttl) {
return cached.result;
}
const result = await this.contract.call(functionSelector, parameters);
this.cache.set(cacheKey, {
result,
timestamp: Date.now()
});
return result;
}
clearCache() {
this.cache.clear();
}
}
Need help? Contact our support team or check the TRON documentation.