When working with blockchain data, you’ll encounter numerous tokens with varying levels of liquidity and utility.
Sim APIs provide comprehensive token metadata and liquidity data to help you implement custom filtering logic that fits your specific requirements.
Our Approach to Token Data
We don’t offer direct spam filtering because definitions of spam are varying and subjective.
Instead, we provide the best objective measure that we’re aware of—liquidity data—to allow developers to filter downstream based on their specific requirements.
By grounding filtering decisions in measurable, onchain liquidity, rather than subjective labels, our method offers several advantages:
- Objective: We provide liquidity metrics rather than subjective spam classifications
- Realtime: Liquidity is checked at query time, not based on outdated lists
- Flexible: All filtering data is provided, allowing you to implement custom logic that fits your use case
- Transparent: You have full visibility into the data used for filtering decisions
- Adaptable: Your filtering criteria can evolve with your application’s needs
Supported APIs
For each token in our responses, we include comprehensive metadata that gives you the information needed to make informed filtering decisions:
- Token basics:
symbol
, name
, and decimals
properties
- Price data: Current USD pricing information using
price_usd
- Liquidity information: Real-time liquidity pool data with
pool_size
- Pool size: The total value locked in the token’s highest liquidity pool using
low_liquidity
How Sim Calculates Liquidity Data
Sim’s approach to assessing liquidity is sophisticated and real-time:
- For each token, we dynamically track the highest liquidity route to USDC
- We calculate the USD value of the liquidity along that route for each token upon each query
- This provides you with current, accurate liquidity information rather than static or outdated data
When pool_size
is very small and low_liquidity
is true, you should disregard price_usd
and value_usd
fields. While the price is technically correct based on the best liquidity pool we can find, it becomes effectively meaningless when there’s insufficient liquidity. You can’t actually exchange the token for anything else of value at that price.
Using Token Data for Custom Filtering
Let’s explore practical implementations for different filtering scenarios.
The following examples demonstrate how to use this data to create robust filtering logic that meets your app’s needs.
Liquidity Threshold Filtering
Filter tokens based on minimum liquidity requirements using the pool_size
field. This is one of the most effective ways to filter out low-quality tokens.
// Filter tokens with at least $10,000 in liquidity
const filterByLiquidity = (tokens, minLiquidity = 10000) => {
return tokens.filter(token => {
return token.pool_size && token.pool_size >= minLiquidity;
});
};
// Usage
const filteredTokens = filterByLiquidity(tokenData, 10000);
This approach ensures you only show tokens that have sufficient trading volume and market depth, reducing the likelihood of displaying illiquid or potentially problematic tokens.
Allowlisting Specific Tokens
Include certain tokens regardless of their liquidity metrics by maintaining a list of approved token addresses and chain IDs.
A secure method for allowlisting is to use a combination of the token’s unique contract address
and its chain_id
.
This guarantees you are identifying the exact token on the correct network.
// Allowlist of trusted tokens. Each entry is an object containing
// the specific chainId and the token's contract address.
const ALLOWLIST = [
// USDC on Ethereum
{ chainId: 1, address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' },
// Wrapped BTC on Ethereum
{ chainId: 1, address: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599' },
// DEGEN on Base
{ chainId: 8453, address: '0x4ed4e862860bed51a9570b96d89af5e1b0efefed' },
// Native ETH on Ethereum Mainnet
{ chainId: 1, address: 'native' },
// Native ETH on Base
{ chainId: 8453, address: 'native' },
];
const filterWithAllowlist = (tokens, minLiquidity = 10000) => {
return tokens.filter(token => {
// Check if the current token matches any in our allowlist.
const isAllowlisted = ALLOWLIST.some(allowlistItem => {
// Note: The Balances API uses `address`, while the Activity API uses `token_address`.
// We handle both possibilities here. We also convert to lowercase for a reliable match.
const tokenAddress = (token.address || token.token_address || '').toLowerCase();
return token.chain_id === allowlistItem.chainId && tokenAddress === allowlistItem.address;
});
// 1. If the token is on the allowlist, always include it.
if (isAllowlisted) {
return true;
}
// 2. For all other tokens, apply a standard liquidity filter.
return token.pool_size && token.pool_size >= minLiquidity;
});
};
Denylisting Specific Tokens
Exclude certain tokens even if they meet your liquidity criteria by maintaining a blocklist of problematic symbols, or any other criteria you choose.
// Denylist of problematic token symbols
const DENYLISTED_SYMBOLS = [
'SCAM',
'RUG',
];
const filterWithDenylist = (tokens) => {
return tokens.filter(token => {
// Exclude denylisted tokens
if (token.symbol && DENYLISTED_SYMBOLS.includes(token.symbol.toUpperCase())) {
return false;
}
// Apply other filtering criteria
return token.pool_size && token.pool_size >= 1000;
});
};
Denylisting helps you maintain control over which tokens appear in your application, even if they have sufficient liquidity.
Custom Criteria Combinations
Create sophisticated filtering logic by combining multiple criteria such as liquidity, completeness, and custom business rules.
const advancedTokenFilter = (tokens, options = {}) => {
const {
minLiquidity = 1000,
requireCompleteName = true,
minPriceUsd = 0.000001,
allowLowLiquidity = false
} = options;
return tokens.filter(token => {
// Check if token has complete metadata
if (requireCompleteName && (!token.name || !token.symbol)) {
return false;
}
// Check minimum price threshold
if (token.price_usd && token.price_usd < minPriceUsd) {
return false;
}
// Check liquidity requirements
if (!allowLowLiquidity && token.low_liquidity) {
return false;
}
if (token.pool_size && token.pool_size < minLiquidity) {
return false;
}
return true;
});
};
This approach allows you to create nuanced filtering that considers multiple factors simultaneously.
Token Completeness Filtering
Filter based on whether tokens have complete metadata, ensuring users only see tokens with proper names and symbols.
const filterCompleteTokens = (tokens) => {
return tokens.filter(token => {
// Require all basic metadata to be present
const hasBasicInfo = token.name &&
token.symbol &&
token.decimals !== undefined;
// Optionally require price data
const hasPriceData = token.price_usd !== undefined;
return hasBasicInfo && hasPriceData;
});
};
// Or create a more flexible version
const filterTokensByCompleteness = (tokens, strict = false) => {
return tokens.filter(token => {
if (strict) {
// Strict mode: require all fields
return token.name && token.symbol && token.decimals &&
token.price_usd && token.pool_size;
} else {
// Lenient mode: require only basic fields
return token.symbol && token.decimals !== undefined;
}
});
};
Completeness filtering ensures your users have meaningful information about the tokens they’re viewing.
Responses are generated using AI and may contain mistakes.