The Factory

The factory is the central place for discovering information about the Levana Perps protocol. The first thing you'll likely want to do is discover which markets are available:

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 markets: { markets: string[] } = await client.queryContractSmart(
    factoryAddress,
    { markets: {} }
  )
  for (const marketId of markets.markets) {
    console.log(marketId)
  }
}

runAll()

This program uses the queryContractSmart to make a query against the factory smart contract. CosmWasm queries are JSON objects, where the key represents the request we want to make. In this case, we're making a request to the markets query. Running this prints out all the markets available on our factory:

$ yarn tutorial
ATOM_USD
BTC_USD

We can now use another query to get more information about the ATOM_USD market:

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 marketInfo = await client.queryContractSmart(factoryAddress, {
    market_info: { market_id: "ATOM_USD" }
  })
  console.log(JSON.stringify(marketInfo))
}

runAll()

We're now querying the market_info query, and providing the market_id parameter with the input ATOM_USD. This results in the output:

$ yarn tutorial
{
  "market_addr":"osmo1kus6tmx9ggmvgg5tf88ukgxcz0ynakx38hyjy0sjgahvp7d3ut2qqtfhf4",
  "position_token":"osmo1kqw7lkemyqdvyfqv5lt05rfgdj72qq8lh2rwpwk8p646twlpwpsqc54m9w",
  "liquidity_token_lp":"osmo142cthpwtqgsdhq9ex55fp0ya4w45a2mhff3qhg5092hauhf22f4q98x2uw",
  "liquidity_token_xlp":"osmo16gg2ehrl7jz43w08vvxyq8nf933vkcsae5xuzk8hc5jvdnml672s2svsy6"
}

This query provides some information on the ATOM_USD market. For now, all we care about is the market_addr, which gives the address of the market contract we will want to interact with going forward.

Reading the API docs

It's useful to be able to look at the query message API docs and see how the Rust representation matches up with the JSON representation. For example, the factory query message looks like the following (though redacted a bit):

#![allow(unused)]
fn main() {
pub enum QueryMsg {
    Markets {},
    MarketInfo {
        market_id: MarketId,
    },
}
}

You can see that the Markets and MarketInfo names--known in Rust as variants--turn into the snake case versions markets and market_info in the queries above. This will be a pattern you'll see repeated throughout all queries.

The vast majority of work within Levana Perps happens with the market contract. Now that we know the basics of querying a contract and have a market contract address, it's time to start playing with the market.

If you look at the specific variant documentation, such as MarketInfo you will see the return type too, which in this case is MarketInfoResponse