Skip to main content

Token Data

Learn how to fetch and manage token metadata for building UI components like token selectors, dropdowns, and list views. This guide shows you how to work with token information efficiently.

Overview

This page covers:

  • Fetching the complete token list
  • Getting individual token details
  • Finding associated pairs for tokens
  • Building token selection components
  • Caching and updating token data

Getting All Tokens

Fetch Complete Token List

import requests
import json

def get_all_tokens():
"""Fetch all available tokens"""
url = "https://api.hoops.finance/tokens"
response = requests.get(url)
response.raise_for_status()
return response.json()

def get_token_details(token_address):
"""Fetch detailed information for a specific token"""
url = f"https://api.hoops.finance/tokens/{token_address}"
response = requests.get(url)
response.raise_for_status()
return response.json()

# Usage
tokens = get_all_tokens()
print(f"Total tokens: {len(tokens['tokens'])}")

# Display first 5 tokens
for token in tokens['tokens'][:5]:
print(f"Symbol: {token['symbol']}")
print(f"Name: {token['name']}")
print(f"Address: {token['address']}")
print(f"Decimals: {token['decimals']}")
print("---")
Use Case

Great for: Token dropdowns, search functionality, and token list displays

Response Fields Explained

FieldDescriptionExample
symbolToken symbol/tickerXLM, USDC, BTC
nameFull token nameStellar Lumens, USD Coin
addressToken contract addressCAB6MICC2WKRT372U3FRPKGGVB5R3FDJSMWJL5XK6R3XWMJUCA4RJMXU
decimalsNumber of decimal places7, 6, 8
totalSupplyTotal token supply1000000000000000
imageUrlToken logo URLhttps://example.com/token.png

Individual Token Details

Get Specific Token Information

def get_token_with_pairs(token_address):
"""Get token details and its associated pairs"""
# Get token details
token_details = get_token_details(token_address)

# Get pairs for this token
pairs_url = f"https://api.hoops.finance/tokens/{token_address}/pairs"
pairs_response = requests.get(pairs_url)
pairs_response.raise_for_status()
pairs_data = pairs_response.json()

return {
'token': token_details,
'pairs': pairs_data['pairs']
}

# Usage
token_address = "CAB6MICC2WKRT372U3FRPKGGVB5R3FDJSMWJL5XK6R3XWMJUCA4RJMXU"
token_data = get_token_with_pairs(token_address)

print(f"Token: {token_data['token']['name']} ({token_data['token']['symbol']})")
print(f"Address: {token_data['token']['address']}")
print(f"Decimals: {token_data['token']['decimals']}")
print(f"Total Supply: {token_data['token']['totalSupply']}")
print(f"Associated Pairs: {len(token_data['pairs'])}")

# Show some pairs
for pair in token_data['pairs'][:3]:
print(f" - {pair['token0Symbol']}/{pair['token1Symbol']} (TVL: ${float(pair['tvl']):,.2f})")
async function getTokenWithPairs(tokenAddress) {
try {
const [tokenResponse, pairsResponse] = await Promise.all([
fetch(`https://api.hoops.finance/tokens/${tokenAddress}`),
fetch(`https://api.hoops.finance/tokens/${tokenAddress}/pairs`)
]);

if (!tokenResponse.ok || !pairsResponse.ok) {
throw new Error(`HTTP error! status: ${tokenResponse.status} or ${pairsResponse.status}`);
}

const [tokenData, pairsData] = await Promise.all([
tokenResponse.json(),
pairsResponse.json()
]);

return {
token: tokenData,
pairs: pairsData.pairs
};
} catch (error) {
console.error('Error fetching token data:', error.message);
throw error;
}
}

// Usage
const tokenAddress = "CAB6MICC2WKRT372U3FRPKGGVB5R3FDJSMWJL5XK6R3XWMJUCA4RJMXU";

getTokenWithPairs(tokenAddress).then(data => {
console.log(`Token: ${data.token.name} (${data.token.symbol})`);
console.log(`Address: ${data.token.address}`);
console.log(`Decimals: ${data.token.decimals}`);
console.log(`Total Supply: ${data.token.totalSupply}`);
console.log(`Associated Pairs: ${data.pairs.length}`);

// Show some pairs
data.pairs.slice(0, 3).forEach(pair => {
console.log(` - ${pair.token0Symbol}/${pair.token1Symbol} (TVL: $${parseFloat(pair.tvl).toLocaleString()})`);
});
});
Use Case

Great for: Token detail pages, pair discovery, and token analysis

Building Token Selection Components

Python Token Selector

class TokenSelector:
def __init__(self):
self.tokens = {}
self.load_tokens()

def load_tokens(self):
"""Load all tokens into memory"""
try:
response = requests.get("https://api.hoops.finance/tokens")
data = response.json()

# Create lookup dictionaries
for token in data['tokens']:
self.tokens[token['address']] = token
self.tokens[token['symbol'].lower()] = token
self.tokens[token['name'].lower()] = token

print(f"Loaded {len(data['tokens'])} tokens")
except Exception as e:
print(f"Error loading tokens: {e}")

def search_tokens(self, query, limit=10):
"""Search tokens by symbol, name, or address"""
query = query.lower()
results = []

for token in self.tokens.values():
if (query in token['symbol'].lower() or
query in token['name'].lower() or
query in token['address'].lower()):
results.append(token)
if len(results) >= limit:
break

return results

def get_token_by_symbol(self, symbol):
"""Get token by symbol"""
return self.tokens.get(symbol.lower())

def get_token_by_address(self, address):
"""Get token by address"""
return self.tokens.get(address)

def get_popular_tokens(self, limit=10):
"""Get popular tokens (XLM, USDC, etc.)"""
popular_symbols = ['XLM', 'USDC', 'BTC', 'ETH', 'USDT']
popular_tokens = []

for symbol in popular_symbols:
token = self.get_token_by_symbol(symbol)
if token:
popular_tokens.append(token)

return popular_tokens[:limit]

# Usage
selector = TokenSelector()

# Search for tokens
results = selector.search_tokens("USDC")
for token in results:
print(f"{token['symbol']} - {token['name']}")

# Get popular tokens
popular = selector.get_popular_tokens()
print("\nPopular tokens:")
for token in popular:
print(f" {token['symbol']}: {token['name']}")

JavaScript Token Selector

class TokenSelector {
constructor() {
this.tokens = {};
this.loadTokens();
}

async loadTokens() {
try {
const response = await fetch('https://api.hoops.finance/tokens');

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data = await response.json();

// Create lookup objects
data.tokens.forEach(token => {
this.tokens[token.address] = token;
this.tokens[token.symbol.toLowerCase()] = token;
this.tokens[token.name.toLowerCase()] = token;
});

console.log(`Loaded ${data.tokens.length} tokens`);
} catch (error) {
console.error('Error loading tokens:', error.message);
}
}

searchTokens(query, limit = 10) {
const queryLower = query.toLowerCase();
const results = [];

Object.values(this.tokens).forEach(token => {
if (token.symbol.toLowerCase().includes(queryLower) ||
token.name.toLowerCase().includes(queryLower) ||
token.address.toLowerCase().includes(queryLower)) {
results.push(token);
}
});

return results.slice(0, limit);
}

getTokenBySymbol(symbol) {
return this.tokens[symbol.toLowerCase()];
}

getTokenByAddress(address) {
return this.tokens[address];
}

getPopularTokens(limit = 10) {
const popularSymbols = ['XLM', 'USDC', 'BTC', 'ETH', 'USDT'];
const popularTokens = [];

popularSymbols.forEach(symbol => {
const token = this.getTokenBySymbol(symbol);
if (token) {
popularTokens.push(token);
}
});

return popularTokens.slice(0, limit);
}
}

// Usage
const selector = new TokenSelector();

// Wait for tokens to load, then search
setTimeout(() => {
const results = selector.searchTokens('USDC');
results.forEach(token => {
console.log(`${token.symbol} - ${token.name}`);
});

const popular = selector.getPopularTokens();
console.log('\nPopular tokens:');
popular.forEach(token => {
console.log(` ${token.symbol}: ${token.name}`);
});
}, 1000);
Use Case

Great for: Token search interfaces, autocomplete components, and token selection dropdowns

Token Data Caching

Python Caching Implementation

import time
import json
from datetime import datetime, timedelta

class TokenCache:
def __init__(self, cache_duration=3600): # 1 hour default
self.cache_duration = cache_duration
self.cache = {}
self.last_update = None

def is_cache_valid(self):
"""Check if cache is still valid"""
if not self.last_update:
return False

return datetime.now() - self.last_update < timedelta(seconds=self.cache_duration)

def update_cache(self):
"""Update the token cache"""
try:
response = requests.get("https://api.hoops.finance/tokens")
data = response.json()

self.cache = {
'tokens': data['tokens'],
'timestamp': datetime.now().isoformat()
}
self.last_update = datetime.now()

print(f"Cache updated with {len(data['tokens'])} tokens")
return True
except Exception as e:
print(f"Error updating cache: {e}")
return False

def get_tokens(self, force_update=False):
"""Get tokens, updating cache if necessary"""
if force_update or not self.is_cache_valid():
self.update_cache()

return self.cache.get('tokens', [])

def save_cache_to_file(self, filename='token_cache.json'):
"""Save cache to file"""
with open(filename, 'w') as f:
json.dump(self.cache, f)

def load_cache_from_file(self, filename='token_cache.json'):
"""Load cache from file"""
try:
with open(filename, 'r') as f:
self.cache = json.load(f)
self.last_update = datetime.fromisoformat(self.cache['timestamp'])
print(f"Loaded {len(self.cache['tokens'])} tokens from cache")
except FileNotFoundError:
print("No cache file found")
except Exception as e:
print(f"Error loading cache: {e}")

# Usage
cache = TokenCache(cache_duration=1800) # 30 minutes
cache.load_cache_from_file()

# Get tokens (will use cache if valid)
tokens = cache.get_tokens()
print(f"Available tokens: {len(tokens)}")

# Force update
tokens = cache.get_tokens(force_update=True)

# Save cache
cache.save_cache_to_file()

JavaScript Caching Implementation

class TokenCache {
constructor(cacheDuration = 3600) { // 1 hour default
this.cacheDuration = cacheDuration;
this.cache = {};
this.lastUpdate = null;
}

isCacheValid() {
if (!this.lastUpdate) return false;

const now = new Date();
const timeDiff = (now - this.lastUpdate) / 1000; // seconds
return timeDiff < this.cacheDuration;
}

async updateCache() {
try {
const response = await fetch('https://api.hoops.finance/tokens');

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data = await response.json();

this.cache = {
tokens: data.tokens,
timestamp: new Date().toISOString()
};
this.lastUpdate = new Date();

console.log(`Cache updated with ${data.tokens.length} tokens`);
return true;
} catch (error) {
console.error('Error updating cache:', error.message);
return false;
}
}

async getTokens(forceUpdate = false) {
if (forceUpdate || !this.isCacheValid()) {
await this.updateCache();
}

return this.cache.tokens || [];
}

saveCacheToLocalStorage() {
try {
localStorage.setItem('tokenCache', JSON.stringify(this.cache));
console.log('Cache saved to localStorage');
} catch (error) {
console.error('Error saving cache:', error.message);
}
}

loadCacheFromLocalStorage() {
try {
const cached = localStorage.getItem('tokenCache');
if (cached) {
this.cache = JSON.parse(cached);
this.lastUpdate = new Date(this.cache.timestamp);
console.log(`Loaded ${this.cache.tokens.length} tokens from cache`);
}
} catch (error) {
console.error('Error loading cache:', error.message);
}
}
}

// Usage
const cache = new TokenCache(1800); // 30 minutes
cache.loadCacheFromLocalStorage();

// Get tokens (will use cache if valid)
cache.getTokens().then(tokens => {
console.log(`Available tokens: ${tokens.length}`);
});

// Force update
cache.getTokens(true).then(tokens => {
console.log(`Updated tokens: ${tokens.length}`);
cache.saveCacheToLocalStorage();
});

Token Image URLs

Working with Token Images

def get_token_image_url(token_address):
"""Get token image URL if available"""
token_details = get_token_details(token_address)
return token_details.get('imageUrl')

def display_token_with_image(token_address):
"""Display token info with image URL"""
token = get_token_details(token_address)

print(f"Token: {token['name']} ({token['symbol']})")
print(f"Address: {token['address']}")

if token.get('imageUrl'):
print(f"Image: {token['imageUrl']}")
else:
print("No image available")

# For web applications, you might use:
# <img src="{token['imageUrl']}" alt="{token['name']}" />

# Usage
token_address = "CAB6MICC2WKRT372U3FRPKGGVB5R3FDJSMWJL5XK6R3XWMJUCA4RJMXU"
display_token_with_image(token_address)
async function getTokenImageUrl(tokenAddress) {
try {
const response = await fetch(`https://api.hoops.finance/tokens/${tokenAddress}`);

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const token = await response.json();
return token.imageUrl;
} catch (error) {
console.error('Error fetching token image:', error.message);
return null;
}
}

async function displayTokenWithImage(tokenAddress) {
try {
const response = await fetch(`https://api.hoops.finance/tokens/${tokenAddress}`);

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const token = await response.json();

console.log(`Token: ${token.name} (${token.symbol})`);
console.log(`Address: ${token.address}`);

if (token.imageUrl) {
console.log(`Image: ${token.imageUrl}`);
} else {
console.log('No image available');
}

// For web applications:
// <img src={token.imageUrl} alt={token.name} />
} catch (error) {
console.error('Error:', error.message);
}
}

// Usage
const tokenAddress = "CAB6MICC2WKRT372U3FRPKGGVB5R3FDJSMWJL5XK6R3XWMJUCA4RJMXU";
displayTokenWithImage(tokenAddress);

Next Steps

Rate Limiting

Remember to implement proper rate limiting in production applications. The API allows 120 requests per minute.

Caching Best Practices
  • Cache token data for 30-60 minutes to reduce API calls
  • Implement fallback mechanisms for when cache is stale
  • Consider using localStorage (browser) or file system (server) for persistence