Oracle Integration Guide
A guide to using the builtin oracles to simplify and secure feeding price data into your smart contracts.
In this article, we will discuss how to use Kujira’s builtin oracle for obtaining price data and perform calculations with normalized prices in your smart contracts. We will cover how to query exchange rates, normalize prices, and use them in calculations.
Querying Exchange Rates
To query exchange rates, you need to use the KujiraQuerier
struct provided by the Kujira crate. First, create a new KujiraQuerier
instance by passing a querier
to its constructor. Then, you can use the query_exchange_rate
method to get the exchange rate for a specific token denomination.
Here’s an example of how to query the exchange rate for a given denomination:
use kujira::{KujiraQuery, KujiraQuerier, HumanPrice};
// ...
pub fn execute(
deps: DepsMut<KujiraQuery>,
// ...
) {
let querier = KujiraQuerier::new(deps.querier);
let human_price = querier.query_exchange_rate(config.denom)?;
// ...
}
In this example, human_price
is of type HumanPrice
, which represents the exchange rate without normalization. It’s important to note that you should not use HumanPrice
directly in calculations, but rather convert it to NormalizedPrice
first.
Normalizing Prices
To convert a HumanPrice
to a NormalizedPrice
, you can use the normalize
method, passing the number of decimal places for the token as an argument. Normalized prices should be used in all calculations involving the value of coins given the oracle price.
Here’s an example of how to convert a HumanPrice
to a NormalizedPrice
:
use kujira::{HumanPrice, NormalizedPrice};
// ...
pub fn deposit(
deps: DepsMut<KujiraQuery>,
// ...
) {
// ...
let normalized_price = human_price.normalize(config.token_decimals);
// use normalized price for calculating the value, etc
}
Using Normalized Prices in Calculations
A NormalizedPrice
can be used as a standin for the Decimal
type for many arithmetic operations. For example, you can use it to multiply a Uint128
value by the exchange rate to get the value of the coins in the oracle’s denomination. If you need to extract the underlying Decimal
value, you can use the inner()
method. Be sure to see the kujirastd
crate’s documentation for more information on the specific trait implementations of NormalizedPrice
.
Dangers of Using NonNormalized Prices
Using nonnormalized prices when calculating values can lead to incorrect results, especially when comparing values of tokens with different decimal places. It’s essential to always normalize prices before performing calculations to avoid these issues.
Here are some potential dangers of using nonnormalized prices:

Incorrect comparisons: When comparing the values of two tokens with different decimal places, using nonnormalized prices might lead to incorrect results. For example, comparing a token with 6 decimal places to another with 18 decimal places without normalization could result in a wrong relative value.

Inaccurate calculations: Performing calculations with nonnormalized prices can lead to incorrect outcomes, as the underlying arithmetic might not account for the different decimal places of the tokens involved. This can cause issues when calculating the value of a trade, converting tokens, or performing any operation that relies on accurate price data.
To mitigate these risks, you should always use the NormalizedPrice
type for calculations. However, if you know what you’re doing and are confident that you’re handling normalization correctly, you can use the unsafe_unchecked
function to obtain a NormalizedPrice
directly. This should be done with caution, as it does not check that the price is normalized to the reference decimal places.
let normalized_price = NormalizedPrice::unsafe_unchecked(price);
Using NormalizedPrice
in function signatures helps ensure normalization across function boundaries. By leveraging Rust’s type system, you can depend on the type system to help guarantee that the prices used in your functions are normalized, avoiding potential issues caused by nonnormalized prices.
If you need to extract the underlying Decimal
value from a NormalizedPrice
, you can use the inner()
method:
let decimal_value = normalized_price.inner();
This allows you to access the raw decimal value for further processing or conversion if needed.