
Product
Socket Threat Intel Now Shows Which Malware Campaigns Were Blocked or Detected
Socket Threat Intel now shows which malware campaigns were blocked or detected in your organization, with links to scans and Firewall events.
Decentralized price queries from DEX liquidity pools across multiple EVM chains and protocols
Decentralized price queries from DEXes across multiple chains
Installation | Quick Start | Core Concepts | API Reference | Usage Guides
Finding the best price across multiple DEXes and chains is complex. Different protocols, different APIs, different pool structures. dexap abstracts all of this complexity into a clean, type-safe interface.
viem as a peer dependency# npm
npm install dexap viem
# yarn
yarn add dexap viem
# pnpm
pnpm add dexap viem
Note:
viemis a peer dependency and must be installed alongside dexap.
import { createClient, ChainId, DexType } from "dexap";
const client = createClient({
alchemyKey: "your-api-key", // Optional
});
// Get a price quote
const result = await client.getPrice(
"WETH",
"USDC",
"1",
ChainId.ETHEREUM,
DexType.UNISWAP_V3
);
console.log(result.formatted); // "1 WETH = 3,245.67 USDC"
See Usage Guides for more examples.
dexap supports two types of concentrated liquidity protocols with different pool configurations:
Used by: Uniswap V3, SushiSwap V3, PancakeSwap V3
Pool Tiers: Based on fee percentages
100 = 0.01% fee (stablecoin pairs like USDC/USDT)500 = 0.05% fee (correlated pairs like ETH/WETH)3000 = 0.30% fee (standard pairs like ETH/USDC)10000 = 1.00% fee (volatile/exotic pairs)Available on: All 11 chains
Used by: Velodrome (Optimism), Aerodrome (Base)
Pool Tiers: Based on tick spacing
1 = Tightest spacing (stablecoin pairs)50 = Tight spacing (correlated assets)100 = Standard spacing (common pairs)200 = Wide spacing (volatile pairs)2000 = Widest spacing (exotic pairs)Key Difference: Slipstream is Velodrome's concentrated liquidity implementation optimized for OP Stack chains. It's NOT a UniswapV3 fork - it uses tick spacing parameters instead of fee tiers for pool configuration.
Available on: Optimism (Velodrome), Base (Aerodrome)
Important: dexap abstracts these protocol differences completely. You use the same API methods regardless of whether you're querying UniswapV3 or Slipstream pools. The
poolTierin results will show the appropriate tier type for each protocol.
dexap automatically handles protocol selection based on your query method:
Best Price Mode (getBestPrice)
Specific DEX Mode (getPrice)
Aggregation Mode (getAggregatedPrice)
Check availability: Use getSupportedDexTypes(chainId) to find which DEXes are available on a specific chain.
dexap includes a built-in token registry that simplifies token handling:
"WETH", "USDC" instead of addressescreateClient(config?)Creates a dexap client instance for querying DEX prices.
Parameters:
interface ClientConfig {
alchemyKey?: string; // Alchemy API key
infuraKey?: string; // Infura API key
rpcUrls?: Partial<Record<ChainKey, string>>; // Custom RPC URLs
}
Returns: Client instance
Example:
const client = createClient({
alchemyKey: "your-key",
});
client.getPrice(tokenIn, tokenOut, amount, chainId, dexType)Get a price quote from a specific DEX.
Parameters:
| Parameter | Type | Description |
|---|---|---|
tokenIn | string | TokenInfo | Input token symbol or address |
tokenOut | string | TokenInfo | Output token symbol or address |
amount | string | Amount in human-readable format (e.g., "1.5") |
chainId | ChainId | Target blockchain |
dexType | DexType | Specific DEX to query |
Returns: Promise<PriceResult>
client.getBestPrice(tokenIn, tokenOut, amount, chainId)Find the best price across all available DEXes on a chain.
Parameters: Same as getPrice except no dexType parameter
Returns: Promise<PriceResult & { dexType: DexType }>
The result includes a dexType field indicating which DEX provided the best price.
client.getPricesFromAllDexes(tokenIn, tokenOut, amount, chainId)Get price quotes from all available DEXes on a chain.
Parameters: Same as getPrice except no dexType parameter
Returns: Promise<Array<PriceResult & { dexType: DexType }>>
Returns an array of price results, one for each available DEX.
client.getAggregatedPrice(tokenIn, tokenOut, amount, chainId, filterOutliers?)Get aggregated price statistics across all DEXes with optional outlier filtering.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
tokenIn | string | TokenInfo | - | Input token |
tokenOut | string | TokenInfo | - | Output token |
amount | string | - | Amount to query |
chainId | ChainId | - | Target chain |
filterOutliers | boolean | true | Apply IQR outlier filtering |
Returns: Promise<AggregatedPrice>
Utility functions for working with tokens across chains.
resolveToken(symbol, chainId)Resolve a token symbol to chain-specific address and decimals.
function resolveToken(symbol: string, chainId: ChainId): TokenInfo;
getTokenMetadata(symbol)Get token metadata without specifying a chain.
function getTokenMetadata(symbol: string): TokenMetadata | undefined;
Returns name, symbol, and decimals (chain-agnostic).
getSupportedChains(symbol)Find which chains support a specific token.
function getSupportedChains(symbol: string): ChainId[];
getChainTokens(chainId)Get all tokens available on a specific chain.
function getChainTokens(chainId: ChainId): TokenInfo[];
getWrappedNativeToken(chainId)Get the wrapped native token for a chain (WETH, WBNB, WMATIC, etc.).
function getWrappedNativeToken(chainId: ChainId): TokenInfo | undefined;
Utility functions for discovering and checking DEX availability.
getSupportedDexTypes(chainId)Get all DEX types available on a specific chain.
function getSupportedDexTypes(chainId: ChainId): DexType[];
// Example
const baseDexes = getSupportedDexTypes(ChainId.BASE);
// => [DexType.UNISWAP_V3, DexType.SUSHISWAP_V3,
// DexType.PANCAKESWAP_V3, DexType.AERODROME]
getDexProtocol(dexType)Get protocol metadata for a DEX type.
function getDexProtocol(dexType: DexType): DexProtocol;
// Example
const protocol = getDexProtocol(DexType.VELODROME);
// => { type: "velodrome", name: "Velodrome", website: "https://velodrome.finance" }
isDexSupported(chainId, dexType)Check if a specific DEX is available on a chain.
function isDexSupported(chainId: ChainId, dexType: DexType): boolean;
// Example
const supported = isDexSupported(ChainId.BASE, DexType.VELODROME);
// => false (Velodrome is only on Optimism)
PriceResultThe result of a price query.
interface PriceResult {
tokenIn: TokenInfo; // Input token details
tokenOut: TokenInfo; // Output token details
amountIn: string; // Input amount in wei
amountOut: string; // Output amount in wei
price: number; // Numeric price (tokenOut per tokenIn)
formatted: string; // Human-readable: "1 WETH = 3,245.67 USDC"
poolTier: PoolTier; // Pool tier information
chainId: ChainId; // Chain identifier
gasEstimate: string; // Estimated gas in wei
priceImpact: number; // Price impact percentage
}
AggregatedPriceAggregated price statistics across multiple DEXes.
interface AggregatedPrice {
average: number; // Average price
median: number; // Median price
min: number; // Minimum price
max: number; // Maximum price
best: PriceResult & { dexType: DexType }; // Best price with DEX
all: Array<PriceResult & { dexType: DexType }>; // All prices
tokenIn: TokenInfo;
tokenOut: TokenInfo;
chainId: ChainId;
timestamp: number; // Query timestamp
}
PoolTierPool tier information (fee or tick spacing).
interface PoolTier {
type: "fee" | "tickSpacing"; // Tier type
value: number; // Fee (e.g., 3000) or tick spacing (e.g., 100)
display: string; // Human-readable: "0.30% fee" or "100 tick spacing"
}
TokenInfoToken information including address and decimals.
interface TokenInfo {
symbol: string; // Token symbol (e.g., "WETH")
address: `0x${string}`; // Contract address
decimals: number; // Token decimals
}
enum ChainId {
ETHEREUM = 1,
BSC = 56,
POLYGON = 137,
ARBITRUM = 42161,
AVALANCHE = 43114,
OPTIMISM = 10,
BASE = 8453,
ZORA = 7777777,
UNICHAIN = 130,
WORLD_CHAIN = 480,
SONEIUM = 1868,
}
enum DexType {
UNISWAP_V3 = "uniswap-v3",
SUSHISWAP_V3 = "sushiswap-v3",
PANCAKESWAP_V3 = "pancakeswap-v3",
VELODROME = "velodrome",
AERODROME = "aerodrome",
}
Scenario: Check the current WETH/USDC price on Ethereum.
import { createClient, ChainId, DexType } from "dexap";
const client = createClient({
alchemyKey: "your-api-key",
});
const result = await client.getPrice(
"WETH",
"USDC",
"1",
ChainId.ETHEREUM,
DexType.UNISWAP_V3
);
console.log(result.formatted); // "1 WETH = 3,245.67 USDC"
console.log(result.poolTier.display); // "0.30% fee"
console.log(result.price); // 3245.67
console.log(result.priceImpact); // 0.0234
console.log(result.gasEstimate); // "150000"
Scenario: Find which DEX offers the best WETH price on Ethereum.
import { createClient, ChainId } from "dexap";
const client = createClient({ alchemyKey: "your-api-key" });
// Option 1: Get best price directly
const best = await client.getBestPrice("WETH", "USDC", "1", ChainId.ETHEREUM);
console.log(`Best: ${best.formatted}`);
console.log(`DEX: ${best.dexType}`);
console.log(`Pool: ${best.poolTier.display}`);
// Option 2: Compare all DEXes manually
const allPrices = await client.getPricesFromAllDexes(
"WETH",
"USDC",
"1",
ChainId.ETHEREUM
);
allPrices.forEach((quote) => {
console.log(
`${quote.dexType}: ${quote.formatted} (impact: ${quote.priceImpact.toFixed(
4
)}%)`
);
});
Scenario: Check WETH/USDC price across multiple chains.
import { createClient, ChainId, DexType } from "dexap";
const client = createClient({ alchemyKey: "your-api-key" });
const chains = [
ChainId.ETHEREUM,
ChainId.BASE,
ChainId.ARBITRUM,
ChainId.OPTIMISM,
ChainId.POLYGON,
];
const prices = await Promise.allSettled(
chains.map((chainId) =>
client.getPrice("WETH", "USDC", "1", chainId, DexType.UNISWAP_V3)
)
);
prices.forEach((result, i) => {
if (result.status === "fulfilled") {
const chainName = ChainId[chains[i]];
console.log(`${chainName}: $${result.value.price.toFixed(2)}`);
} else {
console.log(`${ChainId[chains[i]]}: Error - ${result.reason}`);
}
});
Scenario: Get statistical analysis of WETH price across all DEXes on Base.
import { createClient, ChainId } from "dexap";
const client = createClient({ alchemyKey: "your-api-key" });
const agg = await client.getAggregatedPrice(
"WETH",
"USDC",
"1",
ChainId.BASE,
true // Filter outliers
);
console.log(`Average: $${agg.average.toFixed(2)}`);
console.log(`Median: $${agg.median.toFixed(2)}`);
console.log(`Range: $${agg.min.toFixed(2)} - $${agg.max.toFixed(2)}`);
console.log(`Best: ${agg.best.formatted} (${agg.best.dexType})`);
console.log(`Spread: ${(((agg.max - agg.min) / agg.min) * 100).toFixed(2)}%`);
// Analyze individual DEX prices
agg.all.forEach((quote) => {
const spread = ((quote.price - agg.min) / agg.min) * 100;
console.log(
`${quote.dexType}: $${quote.price.toFixed(2)} (+${spread.toFixed(
2
)}% above min)`
);
});
Scenario: Discover token availability and resolve addresses.
import {
resolveToken,
getTokenMetadata,
getSupportedChains,
getChainTokens,
getWrappedNativeToken,
ChainId,
} from "dexap";
// Get token metadata (chain-agnostic)
const meta = getTokenMetadata("WETH");
console.log(`${meta.name} - ${meta.decimals} decimals`);
// Find which chains support USDC
const usdcChains = getSupportedChains("USDC");
console.log(`USDC available on ${usdcChains.length} chains`);
// Get token address for specific chain
const weth = resolveToken("WETH", ChainId.BASE);
console.log(`WETH on Base: ${weth.address}`);
// Get wrapped native token
const wrapped = getWrappedNativeToken(ChainId.BSC);
console.log(`BSC wrapped native: ${wrapped.symbol}`); // "WBNB"
// List all tokens on a chain
const baseTokens = getChainTokens(ChainId.BASE);
console.log(`Tokens on Base: ${baseTokens.map((t) => t.symbol).join(", ")}`);
Scenario: Configure RPC providers for optimal performance.
import { createClient } from "dexap";
// Use Alchemy
const alchemyClient = createClient({
alchemyKey: "your-alchemy-key",
});
// Use Infura
const infuraClient = createClient({
infuraKey: "your-infura-key",
});
// Mix custom RPCs with API keys
const customClient = createClient({
alchemyKey: "your-key", // Use Alchemy for most chains
rpcUrls: {
mainnet: "https://your-private-eth-rpc.com", // Override Ethereum
base: "https://your-private-base-rpc.com", // Override Base
},
});
// Public RPCs only (rate limited, not recommended for production)
const publicClient = createClient();
Scenario: Handle common errors gracefully.
import { createClient, ChainId, DexType } from "dexap";
const client = createClient({ alchemyKey: "your-api-key" });
try {
const result = await client.getPrice(
"WETH",
"USDC",
"1",
ChainId.ETHEREUM,
DexType.UNISWAP_V3
);
console.log("Price:", result.formatted);
} catch (error) {
if (error instanceof Error) {
if (
error.message.includes("Token") &&
error.message.includes("not found")
) {
console.log("Token not supported on this chain");
} else if (error.message.includes("not configured")) {
console.log("DEX not available on this chain");
} else if (error.message.includes("No liquidity found")) {
console.log("No liquidity available for this pair");
} else {
console.error("Unexpected error:", error.message);
}
}
}
Common error patterns:
Token "${symbol}" not found on chain ${chainId} - Token not deployed on this chainDEX ${dexType} not configured for chain ${chainId} - DEX not available on this chainNo liquidity found for ${tokenIn}/${tokenOut} on ${dexType} - Insufficient liquidity| Chain | Chain ID | DEXes Available |
|---|---|---|
| Ethereum | 1 | UniswapV3, SushiSwapV3, PancakeSwapV3 |
| Base | 8453 | UniswapV3, SushiSwapV3, PancakeSwapV3, Aerodrome |
| Optimism | 10 | UniswapV3, SushiSwapV3, Velodrome |
| Arbitrum | 42161 | UniswapV3, SushiSwapV3, PancakeSwapV3 |
| Polygon | 137 | UniswapV3, SushiSwapV3 |
| BNB Smart Chain | 56 | UniswapV3, SushiSwapV3, PancakeSwapV3 |
| Avalanche | 43114 | UniswapV3, SushiSwapV3 |
| Zora | 7777777 | UniswapV3 |
| Unichain | 130 | UniswapV3 |
| World Chain | 480 | UniswapV3 |
| Soneium | 1868 | UniswapV3 |
| DEX | Protocol | Pool Tiers | Chains |
|---|---|---|---|
| Uniswap V3 | UniswapV3 | Fee-based (0.01% - 1.00%) | All 11 chains |
| SushiSwap V3 | UniswapV3 | Fee-based (0.01% - 1.00%) | Ethereum, Base, Optimism, Arbitrum, Polygon, BSC, Avalanche |
| PancakeSwap V3 | UniswapV3 | Fee-based (0.01% - 1.00%) | Ethereum, Base, Arbitrum, BSC |
| Velodrome | Slipstream | Tick Spacing (1 - 2000) | Optimism |
| Aerodrome | Slipstream | Tick Spacing (1 - 2000) | Base |
FAQs
Decentralized price queries from DEX liquidity pools across multiple EVM chains and protocols
The npm package dexap receives a total of 0 weekly downloads. As such, dexap popularity was classified as not popular.
We found that dexap demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Product
Socket Threat Intel now shows which malware campaigns were blocked or detected in your organization, with links to scans and Firewall events.

Security News
Fixes for eMudhra and Brotli are out. Getting them everywhere they’re needed means tracking down bundled libraries, runtimes, and certificate stores.

Threat Research
/Security News
Socket uncovered secret-stealing workflows that ran in LiteLLM’s GitHub repository 11 days before the supply chain attack on PyPI and Docker.