Major upgrades to Jupiter’s price API — introducing Jupiter Price V2.
Jupiter Price V1 is a powerful method of getting precise & real time pricing for all SPL tokens, but there are some shortfalls with how price is derived. Currently Price V1 derives price via /quote on the buy side. This does not factor in the sell side. In the event of single-sided liquidity or extreme price volatility, price blips occur causing temporary price spikes & mispricing for the token.
There were a few inaccuracies in Price V1, namely:
- Only factoring in
buyPrice
can lead to large blips, especially when there’s skewed buy side liquidity - No price smoothing measures
An example of a huge price blip in Price V1 (SOL)
Also, we believe that factoring just buyPrice
or lastTradedPrice
is not the most accurate measure of price.
If only lastTradedPrice is factored in, tokens that have not been traded for some time will have a stale or inaccurate price, not reflecting the true price based on the liquidity of the token.
What can you look forward to with Price V2
PriceV2 aims to address these issues by smoothing out the price by factoring the sell side liquidity along with the buy side liquidity to derive the average price of the two. We are also introducing extraInfo
& confidenceLevel
.
Ultimately, Price V2 aims to give users more enriched data on the price that is served to them and give users the option to choose which price best fits their needs & use-case.
What is within extraInfo
?
lastJupiterSellAt |
Epoch seconds of the lastJupiterSellPrice . |
---|---|
lastJupiterSellPrice |
Price of last Jupiter sell |
lastJupiterBuyAt |
Epoch seconds of the lastJupiterBuyPrice . |
lastJupiterBuyPrice |
Price of last Jupiter buy |
buyPrice |
An Option<String> representing the quoted buy price. |
buyAt |
Epoch seconds of when the buy quote was retrieved. |
sellPrice |
An Option<String> representing the quoted sell price. |
sellAt |
Epoch seconds of when the sell quote was retrieved. |
confidenceLevel |
A String indicating the confidence level (High, Medium, or Low). |
If you don’t need to extraInfo
, simply set showExtraInfo
to false
!
Caching Mechanism
Price data from both buy side and sell side is cached for up to 15 seconds - it is not meaningful to spam this endpoint
Another point to note is that when the price is revalidated, the revalidated price will be cached so that all users get as fresh data as possible.
Price Revalidation Criteria
In the Price V2 API, we implement a process called price revalidation to deliver the freshest and most accurate data to users with every request. Price revalidation involves refreshing the cached price data before serving it, and it is triggered when the following criteria are met:
- The token is among the top 200 most traded tokens of the day.
- The price discrepancy between buy and sell prices exceeds 2% (
| buyPrice - sellPrice | > 2%
).
By revalidating, we ensure users receive the most current data, improving freshness and ensuring that previously covered arbitrage opportunities are updated accordingly.
How we retrieve last swapped price
For last swapped price, we will cache the previous 3 days’ swap data for USDC routes and update our cache with new Jupiter swaps (that are against USDC). This means that last swapped price will only show if the token has been swapped to and from USDC in the past 3 days on Jupiter’s platform.
An example:
- User A swaps 1 JUP for 0.8 USDC
- User B swaps 1 USDC for 1.25 JUP
In this scenario, since there was a swap from the token to and from USDC, we will have JUP’s last swapped price
- User A swaps 1 JUP for 0.006 SOL
- User B swaps 1 SOL for 166 JUP
For this scenario, we won’t have the last swapped price of JUP (assuming that there were no other swaps in the past 3 days)
We understand that this can be limited and we’ll be working on improving on supporting more tokens other than USDC as the base.
What is confidenceLevel
and how is it derived?
One of the main reasons for introducing the confidenceLevel
in this release is to address the challenges posed by low liquidity and volatile tokens. Accurately determining execution prices for these tokens is difficult due to constantly fluctuating liquidity. In such cases, spreads can be extremely large, making it challenging to provide precise pricing based on rapidly changing buy and sell prices.
Yes, these might be arbitrary thresholds, but these thresholds are backed by our benchmarks.
To derive these numbers, we benchmarked all of Jupiter’s tradable tokens over a full trading day. Our analysis revealed that the majority of tokens consistently fall within the 0% ≤ x ≤ 5%
spread threshold, even for those with lower liquidity. This data-driven approach allows us to set realistic and practical thresholds that reflect the actual trading environment.
By implementing confidenceLevel
, users can better understand the reliability of the pricing information, particularly when dealing with tokens that are more susceptible to large fluctuations.
(Price spread plot that shows the buy & sell spread of all JUP tradable tokens)
This is something that we’ll continue to refine over the next few iterations.
For any ideas how we can further improve on our confidenceLevel, do join our discord.
Confidence Level Thresholds
- High Confidence: Tokens with
buyPrice
andsellPrice
spreads that are within0% < x ≤ 2%
. - Medium Confidence: Tokens with spreads in the range
2% < x ≤ 5%
. - Low Confidence: Tokens with spreads in the range
5% < x < ∞
.
For tokens that return low
confidence, it is recommended that users use extraInfo
to review the data and make a decision for what price to use.
Price comparison between Birdeye, Price V1 & Price V2
We benchmarked Birdeye, V1 and V2 together to test for accuracy against buyPrice & Birdeye’s lastTradedPrice
Benchmark with $SOL
While the prices we provide are generally similar, they can differ at times due to the different methods used by the three parties to derive prices. The advantage of V2 is that you can now access all three prices with just a single call.
Benchmark with $WIF
What is depth
and how do we derive it?
The Liquidity Depth feature provides users with insights into the available liquidity for a specific token. It displays how many tokens can be purchased with SOL at various price levels, helping users understand the price impact of larger trades.
By showcasing the token availability at different price points, users will be able to assess how liquidity changes as they increase their order size. As larger buys or sells are made, users will encounter higher price impact, meaning they will receive fewer tokens (or get less value) compared to the quoted base price (the derivedPrice).
This feature helps users make informed decisions by visualising how much liquidity exists for a token and how impact increases with larger trades. The Liquidity Depth feature highlights the impact of low liquidity, where larger buy or sell orders cause the price to deviate from the derivedPrice.
E.g. While a small buy might be filled close to the quoted price, larger purchases will tap into higher-priced orders, resulting in fewer tokens received per unit of SOL. By showing the increasing price impact, this feature enables users to see the cost of making larger trades and understand how liquidity constraints will affect their returns. This gives users a clear view of how bigger buys or sells will impact the value they are getting back.
How it is derived
The way this is derived is by retrieving the quotes for different buy and sell amounts, specifically 10 SOL, 100 SOL and a 1000 SOL. We used SOL over USDC as the base as we used a buy amount of 0.1 SOL to derive price of tokens for derivedPrice above. For consistency, we used SOL amounts for the different buys/sells as well.
The amounts used are 0.1 SOL (base), 10 SOL, 100 SOL & 1000 SOL.
The price impact for these buys will be displayed as follows:
{
"data": {
"So11111111111111111111111111111111111111112": {
"id": "So11111111111111111111111111111111111111112",
"type": "derivedPrice",
"price": "133.710850000",
"extraInfo": {
"lastSwappedPrice": {
"lastJupiterSellAt": 1726223630,
"lastJupiterSellPrice": "133.50768150684598",
"lastJupiterBuyAt": 1726223631,
"lastJupiterBuyPrice": "133.51524275498682"
},
"quotedPrice": {
"buyPrice": "133.475690000",
"buyAt": 1726223632,
"sellPrice": "133.946010000",
"sellAt": 1726223632
},
"confidenceLevel": "high",
"depth": {
"buyPriceImpactRatio": {
"depth": {
"10": 0.010960969555868325,
"100": 0.0459120200389435,
"1000": 0.11200035034584616
},
"timestamp": 1726223631
},
"sellPriceImpactRatio": {
"depth": {
"10": 0.0019479490281157845,
"100": 0.01959692565682939,
"1000": 0.41393755588539766
},
"timestamp": 1726223631
}
}
}
}
},
"timeTaken": 0.0041872
}
In this JSON, the depth property includes both buyDepth and sellDepth, representing the price impact for different buy and sell amounts of the token compared to the derivedPrice (based on a 0.1 SOL trade):
- buyDepth: Shows how much the price increases for larger buys compared to the derivedPrice.
- At 10 tokens, slippage is 0.02%.
- At 100 tokens, slippage is 0.14%.
- At 1000 tokens, slippage is 0.81%.
- sellDepth: Shows how much the price decreases for larger sells compared to the derivedPrice.
- At 10 SOL worth, slippage is 0.019%.
- At 100 SOL worth, slippage is 0.11%.
- At 1000 SOL worth, slippage is 0.8%.
This comparison helps users see how the token price changes when making larger buys or sells, indicating the liquidity available for the token at each level.
In this example, $SOL has deep liquidity given that increasing buys/sells don’t affect the amount of tokens the user will receive on swap.
An example of a less liquid market:
{
"data": {
"6ogzHhzdrQr9Pgv6hZ2MNze7UrzBMAFyBBWUYp1Fhitx": {
"id": "6ogzHhzdrQr9Pgv6hZ2MNze7UrzBMAFyBBWUYp1Fhitx",
"type": "derivedPrice",
"price": "0.038359",
"extraInfo": {
"lastSwappedPrice": {
"lastJupiterSellAt": 1726220723,
"lastJupiterSellPrice": "0.04141940318450596",
"lastJupiterBuyAt": 1726219853,
"lastJupiterBuyPrice": "0.04076191011857915"
},
"quotedPrice": {
"buyPrice": "0.036359",
"buyAt": 1726223719,
"sellPrice": "0.040358",
"sellAt": 1726223719
},
"confidenceLevel": "low",
"depth": {
"buyPriceImpactRatio": {
"depth": {
"10": 11.788194099694987,
"100": 13.840967924271794,
"1000": 34.09976218567382
},
"timestamp": 1726223713
},
"sellPriceImpactRatio": {
"depth": {
"10": 0.19701194576444417,
"100": 2.0307197199500737,
"1000": 20.490705047966696
},
"timestamp": 1726223719
}
}
}
}
},
"timeTaken": 0.0067155
}
Limitations
If price for a token cannot be found, it is either because:
- The token is not tradable on Jupiter - it does not fit into Jupiter’s routing criteria.
- There is no route for this token to SOL.
sellPrice
, sellAt
& lastSwappedPrice
might be null
in cases:
sellPrice
&sellAt
cannot be retrieved within 2 seconds.lastSwappedPrice
might be null if the token has not been traded recently or cannot be retrieved within 1 second.
a. Usually meme coins that have lost steam.
b. Note that this is only for swaps done via Jupiter, it will not be done for swaps done for e.g. directly on Raydium’s platform.
Closing
In conclusion, Price V2 is a step forward towards getting real time on-chain price by providing enriched price data that provides users the option to choose which price best fits their needs & use-case.
For any suggestion or ideas on how we can further improve our services, do let us know on discord.