Query Guide
Introduction
This guide covers common query patterns, optimization techniques, and best practices for retrieving data from the Panda Protocol subgraph.
Basic Queries
Pool Data
# Get basic pool information
{
pandaPool(id: "0x123...") {
id
price
volumeUSD
swapsCount
graduated
}
}
# List active pools with high volume
{
pandaPools(
where: {
volumeUSD_gt: "100000",
graduated: false
}
orderBy: volumeUSD
orderDirection: desc
first: 10
) {
id
price
volumeUSD
}
}
Trading Activity
# Recent swaps for a pool
{
pandaPoolSwaps(
where: { pool: "0x123..." }
orderBy: timestamp
orderDirection: desc
first: 100
) {
timestamp
amountPandaIn
amountPandaOut
volumeUSD
averagePrice
}
}
Advanced Queries
Time-Based Queries
# Get pools with recent activity
{
pandaPools(
where: {
lastSwapTimestamp_gt: "1634567890"
}
) {
id
price
lastSwapTimestamp
}
}
# Get hourly price data
{
priceSnapshots(
where: {
pool: "0x123...",
timeframe: HOUR,
timestamp_gt: "1634567890"
}
orderBy: timestamp
orderDirection: asc
) {
timestamp
open
high
low
close
}
}
Market Analysis
# Top pools by volume
{
pandaPools(
orderBy: volumeUSD
orderDirection: desc
first: 5
) {
id
volumeUSD
marketCapUSD
swapsCount
}
}
# Token holder distribution
{
token(id: "0x123...") {
symbol
holdersCount
holders(
orderBy: balance
orderDirection: desc
first: 10
) {
address
balance
sharePercentage
}
}
}
Query Optimization
Pagination
# Using skip/first for pagination
{
pandaPoolSwaps(
skip: 100 # Skip first 100 results
first: 50 # Get next 50 results
orderBy: timestamp
orderDirection: desc
) {
id
timestamp
}
}
Field Selection
# Good: Specific fields
{
pandaPools {
id
price
volumeUSD
}
}
# Bad: Overfetching
{
pandaPools {
id
price
volumeUSD
swapsCount
lastSwapTimestamp
graduated
raised
# ... unnecessary fields
}
}
Using Fragments
# Define reusable fragments
fragment PoolBasics on PandaPool {
id
price
volumeUSD
swapsCount
}
# Use in queries
{
activePools: pandaPools(
where: { graduated: false }
) {
...PoolBasics
}
graduatedPools: pandaPools(
where: { graduated: true }
) {
...PoolBasics
}
}
Common Use Cases
Trading Interface Data
# Get pool trading data
{
pandaPool(id: "0x123...") {
price
pandaReserve
baseReserve
swapsCount
lastSwapTimestamp
recentSwaps: swaps(
first: 50
orderBy: timestamp
orderDirection: desc
) {
timestamp
amountPandaIn
amountPandaOut
averagePrice
}
}
}
Analytics Dashboard
# Get market overview
{
statistics(id: "global") {
totalVolumeUSD
totalMarketCapUSD
totalPandaPoolsCount
totalGraduatedPandaPoolsCount
}
topPools: pandaPools(
first: 5
orderBy: volumeUSD
orderDirection: desc
) {
id
volumeUSD
marketCapUSD
swapsCount
}
}
Real-time Data Updates
Polling Strategy
# Efficient polling query
{
pandaPool(id: "0x123...") {
price
lastSwapTimestamp
pandaReserve
baseReserve
}
}
Using Block Numbers
# Query at specific block
{
pandaPool(id: "0x123...", block: { number: 15000000 }) {
price
volumeUSD
}
}
Error Handling
Null Checks
# Handle potential null values
{
pandaPool(id: "0x123...") {
id # Will be null if pool doesn't exist
price
# Always check optional relationships
swaps(first: 1) {
id
}
}
}
Block Timestamps
# Use block timestamps for time ranges
{
pandaPoolSwaps(
where: {
timestamp_gt: "1634567890",
timestamp_lt: "1634567990"
}
) {
timestamp
averagePrice
}
}
Best Practices
Query Performance
Use pagination for large datasets
Select only needed fields
Optimize sorting and filtering
Data Freshness
Consider indexing delays
Implement proper polling intervals
Use block numbers for consistency
Error Recovery
Handle null entities gracefully
Validate data ranges
Implement retry logic
Next Steps
Continue to Advanced Usage for:
Complex query patterns
Performance optimization
Edge case handling
Last updated