Querying DEX Pool Reserves
Query liquidity pool reserves from Cardano DEXes like Minswap, SundaeSwap, and WingRiders
Query real-time liquidity pool reserves from Cardano decentralized exchanges. This guide covers Minswap V2, with patterns that extend to other DEXes.
Use Cases
- Price feeds: Get current token prices from DEX liquidity pools
- Arbitrage bots: Monitor price differences across pools
- Portfolio trackers: Display real-time token valuations
- Trading interfaces: Show available liquidity and expected slippage
Choose Your Approach
| Method | Speed | Best For |
|---|---|---|
| Ogmios + Asset Filter | Instant (~20ms) | Single pool queries, trading bots |
| GraphQL | ~2-5 sec | Price checks, dashboards, most use cases |
| Ogmios (unfiltered) | ~30-60 sec | Building swap transactions, guaranteed accuracy |
Use Ogmios + Asset Filter for single pool queries - it's instant from the prewarmed cache. Use GraphQL for multi-pool dashboards. Use unfiltered Ogmios only when you need ALL pools.
Minswap V2 Pools
Minswap is Cardano's largest DEX by TVL. Here's how to query their pool reserves.
Contract Information
| Property | Value |
|---|---|
| Pool Address | addr1z84q0denmyep98ph3tmzwsmw0j7zau9ljmsqx6a4rvaau66j2c79gy9l76sdg0xwhd7r0c0kna0tycz4y5s6mlenh8pq777e2a |
| LP Policy ID | f5808c2c990d86da54bfc97d89cee6efa20cd8461616359478d96b4c |
| Source | github.com/minswap/minswap-dex-v2 |
Ogmios + Asset Filter (Fastest)
Query a specific pool instantly using server-side filtering. This is ideal for trading bots that need one pool's data in real-time.
const MINSWAP_V2_ADDRESS = 'addr1z84q0denmyep98ph3tmzwsmw0j7zau9ljmsqx6a4rvaau66j2c79gy9l76sdg0xwhd7r0c0kna0tycz4y5s6mlenh8pq777e2a';
const MIN_POLICY = '29d222ce763455e3d7a09a665ce554f00ac89d2e99a1a83d267170c6';
async function getMinAdaPool() {
const response = await fetch('https://api.nacho.builders/v1/ogmios', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': process.env.NACHO_API_KEY
},
body: JSON.stringify({
jsonrpc: '2.0',
method: 'queryLedgerState/utxo',
params: {
addresses: [MINSWAP_V2_ADDRESS],
assets: [{ policyId: MIN_POLICY }] // Server-side filter!
},
id: 1
})
});
const { result: utxos } = await response.json();
if (utxos.length === 0) {
throw new Error('MIN/ADA pool not found');
}
const pool = utxos[0];
const adaReserve = pool.value.ada.lovelace;
const minReserve = Object.values(pool.value[MIN_POLICY])[0];
const price = (adaReserve / 1e6) / (minReserve / 1e6);
return {
txHash: pool.transaction.id,
index: pool.index,
adaReserve,
minReserve,
price
};
}
// Usage - instant response from prewarmed cache
const pool = await getMinAdaPool();
console.log(`MIN/ADA price: ${pool.price.toFixed(8)} ADA per MIN`);Performance: Without filtering, this query returns ~3MB (3000+ pools) and takes 30-60 seconds. With the assets filter, it returns ~5KB (1-2 UTxOs) instantly from the prewarmed cache.
GraphQL Method (Recommended for Dashboards)
Query pool data from the indexed DB-Sync database via GraphQL.
const MINSWAP_V2_ADDRESS = 'addr1z84q0denmyep98ph3tmzwsmw0j7zau9ljmsqx6a4rvaau66j2c79gy9l76sdg0xwhd7r0c0kna0tycz4y5s6mlenh8pq777e2a';
const LP_POLICY = 'f5808c2c990d86da54bfc97d89cee6efa20cd8461616359478d96b4c';
async function getMinswapPools() {
const query = `
query MinswapPools($address: String!) {
tx_out(
where: { address: { _eq: $address } }
order_by: { id: desc }
limit: 100
) {
id
value
multi_assets {
quantity
asset {
policy
name
fingerprint
}
}
}
}
`;
const response = await fetch('https://api.nacho.builders/v1/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': process.env.NACHO_API_KEY
},
body: JSON.stringify({
query,
variables: { address: MINSWAP_V2_ADDRESS }
})
});
const { data } = await response.json();
return parsePoolOutputs(data.tx_out);
}
function parsePoolOutputs(outputs) {
const pools = new Map();
for (const output of outputs) {
const adaAmount = BigInt(output.value);
const tokens = [];
for (const ma of output.multi_assets || []) {
const policy = ma.asset.policy.replace('\\x', '');
const name = ma.asset.name.replace('\\x', '');
// Skip LP tokens
if (policy === LP_POLICY) continue;
tokens.push({
policy,
name,
quantity: BigInt(ma.quantity),
ticker: decodeAssetName(name)
});
}
if (tokens.length === 1) {
const token = tokens[0];
const poolKey = token.policy + token.name;
// Keep most recent output per token pair
if (!pools.has(poolKey)) {
pools.set(poolKey, {
adaReserve: adaAmount,
tokenReserve: token.quantity,
tokenTicker: token.ticker,
price: Number(adaAmount) / 1e6 / (Number(token.quantity) / 1e6)
});
}
}
}
return Array.from(pools.values())
.sort((a, b) => Number(b.adaReserve - a.adaReserve));
}
function decodeAssetName(hex) {
try {
const decoded = Buffer.from(hex, 'hex').toString('utf8');
return /^[a-zA-Z0-9]+$/.test(decoded) ? decoded : hex.slice(0, 8);
} catch {
return hex.slice(0, 8);
}
}
// Usage
const pools = await getMinswapPools();
pools.slice(0, 10).forEach(pool => {
console.log(`ADA/${pool.tokenTicker}: 1 ${pool.tokenTicker} = ${pool.price.toFixed(6)} ADA`);
});Ogmios Method (Real-time)
Query the node's live ledger state for guaranteed real-time UTxO data.
const MINSWAP_V2_ADDRESS = 'addr1z84q0denmyep98ph3tmzwsmw0j7zau9ljmsqx6a4rvaau66j2c79gy9l76sdg0xwhd7r0c0kna0tycz4y5s6mlenh8pq777e2a';
const LP_POLICY = 'f5808c2c990d86da54bfc97d89cee6efa20cd8461616359478d96b4c';
async function getMinswapPoolsRealtime() {
const response = await fetch('https://api.nacho.builders/v1/ogmios', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': process.env.NACHO_API_KEY
},
body: JSON.stringify({
jsonrpc: '2.0',
method: 'queryLedgerState/utxo',
params: { addresses: [MINSWAP_V2_ADDRESS] },
id: 1
})
});
const { result: utxos } = await response.json();
return parsePoolUtxos(utxos);
}
function parsePoolUtxos(utxos) {
const pools = [];
for (const utxo of utxos) {
const txHash = utxo.transaction.id;
const index = utxo.index;
const adaAmount = BigInt(utxo.value.ada.lovelace);
const tokens = [];
for (const [policyId, assets] of Object.entries(utxo.value)) {
if (policyId === 'ada') continue;
if (policyId === LP_POLICY) continue; // Skip LP tokens
for (const [assetName, quantity] of Object.entries(assets)) {
tokens.push({
policyId,
assetName,
quantity: BigInt(quantity),
ticker: decodeAssetName(assetName)
});
}
}
if (tokens.length === 1) {
const token = tokens[0];
pools.push({
txHash,
index,
adaReserve: adaAmount,
tokenReserve: token.quantity,
tokenTicker: token.ticker,
price: Number(adaAmount) / 1e6 / (Number(token.quantity) / 1e6)
});
}
}
return pools.sort((a, b) => Number(b.adaReserve - a.adaReserve));
}
// Usage
console.log('Querying pools (this may take 30-60 seconds)...');
const pools = await getMinswapPoolsRealtime();
console.log(`Found ${pools.length} pools`);
pools.slice(0, 10).forEach(pool => {
console.log(`ADA/${pool.tokenTicker}: ${pool.price.toFixed(6)} ADA`);
});The Ogmios query returns ~3MB of data containing all Minswap pools. Set a timeout of at least 60 seconds.
Calculating Swap Prices
Pool reserves give you the spot price (the ratio of reserves). For actual swap prices, account for:
- Swap Fee: Minswap charges 0.3% on swaps
- Price Impact: Large swaps move the price
function calculateSwapOutput(inputAmount, inputReserve, outputReserve, feePercent = 0.3) {
// Apply fee to input
const inputWithFee = inputAmount * (1 - feePercent / 100);
// Constant product formula: x * y = k
// outputAmount = outputReserve - (inputReserve * outputReserve) / (inputReserve + inputWithFee)
const outputAmount = (inputWithFee * outputReserve) / (inputReserve + inputWithFee);
// Price impact
const spotPrice = outputReserve / inputReserve;
const executionPrice = outputAmount / inputAmount;
const priceImpact = Math.abs(1 - executionPrice / spotPrice) * 100;
return {
outputAmount,
executionPrice,
priceImpact
};
}
// Example: Swap 1000 ADA for MIN
const result = calculateSwapOutput(
1000_000000, // 1000 ADA in lovelace
4479978_000000, // ADA reserve
206376044_000000 // MIN reserve
);
console.log(`Output: ${(result.outputAmount / 1e6).toFixed(2)} MIN`);
console.log(`Price Impact: ${result.priceImpact.toFixed(2)}%`);Other Cardano DEXes
The same patterns work for other DEXes - just change the contract address:
| DEX | Pool Address Pattern |
|---|---|
| Minswap V2 | addr1z84q0denm... (single address) |
| SundaeSwap | addr1w9qzpelu9... (single address) |
| WingRiders | Multiple pool addresses by token pair |
Each DEX has different pool structures and fee mechanisms. Check their documentation for accurate swap calculations.
Filtering by Token
Query specific token pairs by filtering results:
// Filter pools to find ADA/MIN
const pools = await getMinswapPools();
const minPool = pools.find(p => p.tokenTicker === 'MIN');
if (minPool) {
console.log(`ADA/MIN Price: ${minPool.price.toFixed(6)} ADA per MIN`);
console.log(`Liquidity: ${(Number(minPool.adaReserve) / 1e6).toLocaleString()} ADA`);
}Well-Known Token Registry
Common Cardano tokens and their identifiers:
| Token | Policy ID | Asset Name (hex) |
|---|---|---|
| MIN | 29d222ce763455e3d7a09a665ce554f00ac89d2e99a1a83d267170c6 | 4d494e |
| SNEK | 279c909f348e533da5808898f87f9a14bb2c3dfbbacccd631d927a3f | 534e454b |
| SUNDAE | 9a9693a9a37912a5097918f97918d15240c92ab729a0b7c4aa144d77 | 53554e444145 |
| iUSD | f66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b69880 | 69555344 |
| DJED | 8db269c3ec630e06ae29f74bc39edd1f87c819f1056206e879a1cd61 | 446a65644d6963726f555344 |
| WMT | 1d7f33bd23d85e1a25d87d86fac4f199c3197a2f7afeb662a0f34e1e | 776f726c646d6f62696c65746f6b656e |
Performance Tips
Cache Pool Data
Prices don't change every second. Cache results for a reasonable period:
const poolCache = new Map();
const CACHE_TTL = 30000; // 30 seconds
async function getCachedPools() {
const cached = poolCache.get('minswap');
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.pools;
}
const pools = await getMinswapPools();
poolCache.set('minswap', { pools, timestamp: Date.now() });
return pools;
}Use WebSocket for Live Updates
For real-time price feeds, combine with chain synchronization:
// Subscribe to new blocks
const ws = new WebSocket(`wss://api.nacho.builders/v1/ogmios?apikey=${API_KEY}`);
ws.onopen = () => {
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'findIntersection',
params: { points: ['origin'] }
}));
};
ws.onmessage = async (event) => {
const data = JSON.parse(event.data);
if (data.method === 'rollForward') {
// New block - refresh pool data
const pools = await getMinswapPools();
updatePriceDisplay(pools);
}
};Example Output
Querying Minswap V2 pools via GraphQL...
Found 500 outputs at pool address
Pool Reserves (top 10 by TVL):
----------------------------------------------------------------------
ADA/MIN
ADA: 4,479,978.81
MIN: 206,376,044.19
Price: 1 MIN = 0.021708 ADA
ADA/SNEK
ADA: 2,529,367.16
SNEK: 1,320,472,521
Price: 1 SNEK = 0.001916 ADA
ADA/DJED
ADA: 681,607.00
DJED: 221,304.14
Price: 1 DJED = 3.079956 ADA
ADA/iUSD
ADA: 614,302.94
iUSD: 204,509.61
Price: 1 iUSD = 3.003785 ADANext Steps
- Submitting Transactions: Build and submit swap transactions
- WebSocket Connections: Real-time price monitoring
- Chain Synchronization: Track pool state changes
Was this page helpful?