How to Query Token Prices for Multiple Denoms Using the Osmosis SQS Client
Use the OsmosisSqsQueryClient.getPrices method to fetch USD prices for multiple token denoms in a single HTTP request by passing an array of denom strings, which returns a price map with each denom keyed to its current price.
The jonator/osmosis-agent-toolkit provides a lightweight TypeScript SDK for interacting with Osmosis. When you need to query token prices for multiple denoms efficiently, the built-in SQS (Sidecar Query Service) client offers a stateless, batch-capable interface that aggregates price data from the public Osmosis SQS endpoint.
Understanding the Osmosis SQS Client Architecture
The SQS client is implemented as a stateless HTTP wrapper around the public Osmosis Sidecar Query Service (https://sqsprod.osmosis.zone). Unlike on-chain queries, this off-chain service provides high-performance price aggregation with sub-second latency.
The core class OsmosisSqsQueryClient exposes the getPrices method, which accepts an array of token denoms (IBC hashes or native denominations) and returns a PriceMap object. According to the source code in packages/core/src/queries/sqs/client.ts, this method constructs a batch request to the /tokens/prices endpoint, encoding all denoms as comma-separated values in the base query parameter.
Querying Token Prices for Multiple Denoms
To query token prices for multiple denoms efficiently, you instantiate the client and invoke getPrices with your target denomination array. The client handles URL encoding, HTTP transport, and response normalization automatically.
URL Construction and Request Format
The getPrices method builds the request URL by appending the base parameter containing comma-separated denoms. As shown in lines 34-37 of packages/core/src/queries/sqs/client.ts:
const url = this.url('/tokens/prices')
url.searchParams.set('base', denoms.join(','))
This format allows the SQS service to process up to hundreds of denoms in a single round-trip, significantly reducing network overhead compared to individual price queries.
Response Normalization and Price Extraction
After receiving the JSON response, the client normalizes the data into a flat PriceMap object where each key is a denom and each value is the USD price as a string. Lines 41-48 of packages/core/src/queries/sqs/client.ts implement this transformation, defaulting missing prices to '0' to ensure type safety.
The helper function getPrice in packages/core/src/queries/sqs/prices.ts (lines 11-13) provides a type-safe accessor for reading individual prices from the map:
export const getPrice = (priceMap: PriceMap, denom: string) => {
return priceMap[denom] ?? '0'
}
Practical Implementation Examples
Basic Usage with OsmosisSqsQueryClient
The following example demonstrates how to query token prices for multiple denoms including native OSMO, IBC-transferred ATOM, and Noble USDC:
import { OsmosisSqsQueryClient } from '@osmosis-toolkit/core';
// Initialize client with default public endpoint
const sqs = new OsmosisSqsQueryClient();
// Define target denoms
const denoms = [
'uosmo', // Native Osmosis
'ibc/FAFA5B...', // Cosmos Hub ATOM
'ibc/498A07...', // Noble USDC (quote currency)
];
// Execute batch price query
const priceMap = await sqs.getPrices(denoms);
console.log(priceMap);
// Output:
// {
// uosmo: '0.68',
// 'ibc/FAFA5B...': '1.23',
// 'ibc/498A07...': '1.00'
// }
Batch Price Queries in AccountTool
The AccountTool implementation in packages/core/src/tools/account.ts (lines 39-78) illustrates production-grade usage. It extracts all denoms from a user's bank balances, queries prices in a single batch request, and calculates USD values:
// Inside AccountTool.call() implementation
const rawBalances = await queryBalances(accountAddress);
const denoms = rawBalances.map(b => b.denom);
// Single SQS request for all balance denoms
const priceMap = await sqsClient.getPrices(denoms);
const enrichedBalances = rawBalances.map(({ denom, amount }) => {
// Resolve asset metadata
const asset = osmosisAssets.find(a => a.base === denom);
const decimals = asset?.denom_units.find(u => u.denom === asset.display)?.exponent ?? 6;
// Convert raw amount to human-readable
const normalizedAmount = (parseInt(amount) / 10 ** decimals).toString();
// Calculate USD value using SQS price
const priceUsd = Number(priceMap[denom] ?? '0');
const valueUsd = Number(normalizedAmount) * priceUsd;
return {
amount: normalizedAmount,
ticker: asset?.symbol ?? denom,
priceUsd,
valueUsd,
};
});
Key Source Files and Implementation Details
Understanding the internal structure helps when extending the client or debugging price discrepancies.
| File | Purpose | Key Export |
|---|---|---|
packages/core/src/queries/sqs/client.ts |
HTTP client implementation with getPrices method |
OsmosisSqsQueryClient |
packages/core/src/queries/sqs/prices.ts |
Type definitions and getPrice accessor helper |
PriceMap, getPrice |
packages/core/src/tools/account.ts |
Real-world integration example | AccountTool |
The client defaults to the public endpoint https://sqsprod.osmosis.zone, but you can override this via the constructor for private SQS instances or local development.
Summary
- The
OsmosisSqsQueryClientprovides a stateless interface to query token prices for multiple denoms in a single HTTP request. - The
getPricesmethod constructs a batch request to/tokens/priceswith comma-separated denoms in thebaseparameter. - Response normalization defaults missing prices to
'0', ensuring safe downstream calculations. - Production implementations like
AccountTooldemonstrate efficient patterns: extract denoms from balances, batch query prices, then calculate USD values. - Source files are located in
packages/core/src/queries/sqs/with the main client logic inclient.ts.
Frequently Asked Questions
What is the default SQS endpoint URL used by the client?
The OsmosisSqsQueryClient defaults to the public Osmosis Sidecar Query Service at https://sqsprod.osmosis.zone. You can override this by passing a custom URL to the constructor when instantiating the client for private infrastructure or local testing environments.
How does the client handle missing price data for specific denoms?
When the SQS response lacks a price for a requested denom, the normalization logic in packages/core/src/queries/sqs/client.ts (lines 41-48) automatically defaults the value to the string '0'. This prevents undefined errors in downstream calculations and allows safe arithmetic operations when computing portfolio values.
Can I use the SQS client with custom endpoints or self-hosted SQS instances?
Yes. While the client defaults to the public Osmosis endpoint, the constructor accepts an optional base URL parameter. This allows you to point the client at private SQS deployments, staging environments, or geographically closer nodes to reduce latency when you query token prices for multiple denoms in production applications.
What format does the price map return, and how do I access individual prices?
The getPrices method returns a PriceMap object (defined in packages/core/src/queries/sqs/prices.ts) where keys are token denoms and values are price strings quoted against Noble USDC. For type-safe access, use the getPrice(priceMap, denom) helper function, which returns the price string or defaults to '0' if the denom is absent from the map.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →