Querying the Market
It's time to get familiar with the market contract itself. The market QueryMsg
provides a number of different queries. But we're going to start off by looking at two queries that provide protocol-wide information:
status
provides information on the current status of the market: configuration values, available liquidity, notional interest, and more.spot_price
gives the price at a given timestamp or, if no timestamp is provided, at the current time.
import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";
// Testnet factory address
const factoryAddress =
"osmo1ymuvx9nydujjghgxxug28w48ptzcu9ysvnynqdw78qgteafj0syq247w5u"
// Osmosis testnet RPC endpoint
// retrieved from https://github.com/cosmos/chain-registry/blob/aecb225b17d1cb5a3826887735cafeb7e62934d0/testnets/osmosistestnet/chain.json#L123
const rpcEndpoint = "https://rpc.osmotest5.osmosis.zone"
const runAll = async () => {
const client = await CosmWasmClient.connect(rpcEndpoint);
const { market_addr: marketAddress } = await client.queryContractSmart(
factoryAddress,
{
market_info: { market_id: "ATOM_USD" },
}
);
const price = await client.queryContractSmart(marketAddress, {
spot_price: {},
});
console.log(JSON.stringify(price));
const status = await client.queryContractSmart(marketAddress, { status: {} });
console.log(JSON.stringify(status));
};
runAll();
This demonstrates a common theme you'll have in your own code: use the factory to get the market address, and then proceed to query that market. For brevity in the rest of the tutorial, we'll simply hard-code the market address.
Spot price
Let's look at the price data, prettied up a bit:
{
"price_notional":"0.080100999350080516",
"price_usd":"12.48423875",
"price_base":"12.48423875",
"timestamp":"1709569578000000000",
"is_notional_usd":true,
"market_type":"collateral_is_base",
}
Let's start with the market_type
. Our ATOM_USD
market is a collateral-is-base market, meaning that we use ATOM as the collateral asset. We'll see in later sections how to get some ATOM to experiment with and how to use it with the market contract.
The timestamp
field is given in nanoseconds since the epoch. You can use any epoch converter to translate into human-readable dates; epochconverter.com is a good choice. The above timestamp comes out to Monday, March 4, 2024 16:39:51 GMT
.
price_base
gives the price of the base asset (ATOM) in terms of the quote asset (USD). This is the standard price you're used to seeing. price_usd
gives the price of the collateral asset in terms of USD. In this market, price_usd
will always give the same value, since ATOM is both the base and collateral assets, and USD is the quote asset. price_notional
is the price used internally by the system. For more information on how Levana Perps handles collateral-is-base markets internally, see our collateral is base slide deck.
Status
The status
response provides a lot of information, and we aren't going to look at it all right now. Let's instead start with a subset of the data:
{
"market_id":"ATOM_USD",
"base":"ATOM",
"quote":"USD",
"market_type":"collateral_is_base",
"collateral": {
"cw20": {
"addr":"osmo1g68w56vq9q0vr2mdlzp2l80j0lelnffkn7y3zhek5pavtxzznuks8wkv6k",
"decimal_places": 6
}
},
"liquidity": {
"locked":"297436.161968789588197153",
"unlocked":"90564.995625182297950879",
"total_lp":"261441.162273575907212688",
"total_xlp":"130064.659093487869092113"
},
"borrow_fee":"0.01",
"borrow_fee_lp":"0.005465354312584584",
"borrow_fee_xlp":"0.004534645687415416",
"long_funding":"-0.069789280603992498",
"short_funding":"0.067865306914332403",
"long_notional":"2659830.714669499436727636",
"short_notional":"2735236.611240979886379068",
"long_usd":"2659830.714669499436727636",
"short_usd":"2735236.611240979886379068",
}
We start off with an overview of the market metadata itself: the market ID, base and quote assets, and whether market_type
is collateral_is_base
or collateral_is_quote
. Next we get to the collateral itself. The above data says that we're using a CW20 token contract with the given address. Levana Perps supports both CW20s and native coins as collateral assets.
Next we see the liquidity
section, which provides an overview of liquidity provided to the platform. The values locked
and unlocked
give the total amount of collateral available in the system. locked
is the total collateral currently locked in positions to guarantee solvency if a trader takes profits. unlocked
represents liquidity available for traders to lock up in new positions. total_lp
and total_xlp
give the total number of LP and xLP tokens.
borrow_fee
, long_funding
, and short_funding
are all ratios giving annualized rates for these values. For example, above, a trader would pay approximately 12.8% APR on any funds they borrow in a position.
long_notional
and short_notional
represent the long and short notional interest, or the sum of all long and short position sizes currently open. An overall goal of Levana Perps is to keep the net notional, which is net_notional = long_notional - short_notional
, as close to 0 as possible. And finally, long_usd
and short_usd
represent the same values, but converted to USD. In our ATOM_USD
market, the notional interest is already expressed in USD, so the values are the same as long_notional
and short_notional
. But in other markets, like stablecoin-denominated markets, this won't be the case.
We could continue querying the market, but it's much more interesting to begin interacting with it. To do that, we'll need a wallet with some funds. Let's take a detour from the code and get that set up.