Overview
TRON's blockchain ecosystem includes both native and EVM-compatible token standards, making it challenging to consistently retrieve token metadata across different address formats. This Function simplifies the process by enabling developers to query TRC20 token information using either TRON native or EVM-compatible addresses.
In this Function example, we will convert TRON addresses to their EVM-compatible format when necessary, and use Web3.js to fetch essential token metadata like name, symbol, decimals, and total supply from the TRON blockchain.
Sample Function
The following is the code for the Function to retrieve TRC20 token metadata using the Node.js v20
runtime, supporting both TRON native and EVM-compatible addresses:
const { Web3 } = require('web3');
const bs58 = require('bs58');
// Replace with the TRON QuickNode endpoint
const tronEvmNodeUrl = '';
const web3 = new Web3(tronEvmNodeUrl);
// ERC20/TRC20 ABI
const tokenABI = [
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [{"name": "", "type": "string"}],
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [{"name": "", "type": "string"}],
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [{"name": "", "type": "uint8"}],
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [{"name": "", "type": "uint256"}],
"type": "function"
}
];
// Function to convert TRON address to EVM address
function convertTronToEvmAddress(tronAddress) {
if (tronAddress.startsWith('T')) {
// Decode the base58 address
const decoded = bs58.decode(tronAddress);
// Remove the first byte (address type) and the last 4 bytes (checksum)
const addressHex = decoded.slice(1, -4).toString('hex');
// Add '0x' prefix to make it a valid Ethereum-style address
return '0x' + addressHex;
}
// If it's already an EVM address, return as is
return tronAddress;
}
async function fetchTokenMetadata(contractAddress) {
try {
// Convert address if it's in TRON format
const evmAddress = convertTronToEvmAddress(contractAddress);
// Create contract instance
const contract = new web3.eth.Contract(tokenABI, evmAddress);
// Fetch token metadata
const [name, symbol, decimals, totalSupply] = await Promise.all([
contract.methods.name().call(),
contract.methods.symbol().call(),
contract.methods.decimals().call(),
contract.methods.totalSupply().call()
]);
// Return the results
return {
address: {
original: contractAddress,
evm: evmAddress
},
name,
symbol,
decimals: parseInt(decimals),
totalSupply: totalSupply.toString()
};
} catch (error) {
console.error("Error fetching token metadata:", error);
throw error;
}
}
async function main(params) {
try {
const contractAddress = params.user_data.contractAddress;
if (!contractAddress) {
throw new Error("Contract address is required");
}
const metadata = await fetchTokenMetadata(contractAddress);
return {
statusCode: 200,
metadata,
};
} catch (error) {
console.error("Error in main function:", error);
return {
statusCode: 500,
body: JSON.stringify({ error: error.message }),
};
}
}
module.exports = { main };
Request
We will invoke the function with the following cURL command. Be sure to replace the YOUR_API_KEY with your own QuickNode API key and the POST URL with the URL of your Function.
curl -X POST "https://api.quicknode.com/functions/rest/v1/functions/{functionId}/call?result_only=true" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"user_data": {
"contractAddress": "TUEYcyPAqc4hTg1fSuBCPc18vGWcJDECVw"
}
}'
Response
Resulting in the following response:
{
"metadata": {
"address": {
"evm": "0xc858e17d9c51e729cf4e357a798814cdd1262eaa",
"original": "TUEYcyPAqc4hTg1fSuBCPc18vGWcJDECVw"
},
"decimals": 6,
"name": "Justswap V1",
"symbol": "JUSTSWAP-V1",
"totalSupply": "480633872315709"
},
"statusCode": 200
}
Learn more about QuickNode Functions.
We ❤️ Feedback!
Let us know if you have any feedback or requests for new topics. We'd love to hear from you.