Getting Started

Get started with using Aver's SDKs
This guide is intended to follow along with the example scripts included in the Python and Typescript SDKs.
If you're building your own bindings/interface with Aver, the steps will be similar, but your implementation may vary.
This guide will still be very helpful in demonstrating the sequence of events and steps involved in the interaction.

Install one of the Aver SDKs

The best way to interact with our API is to use one of the open source SDKs. You can install these files as follows:
pip install pyaver
npm install aver-ts
You will find example files below- which you can use to follow along with the remainder of this guide.
Python SDK documentation is available here:
import asyncio
from datetime import datetime
import base58
from solana.rpc.async_api import AsyncClient
from solana.keypair import Keypair
from pyaver.enums import SolanaNetwork
from pyaver.aver_client import AverClient
from pyaver.constants import get_solana_endpoint, AVER_PROGRAM_IDS
from solana.rpc.types import TxOpts
from solana.rpc.commitment import Confirmed
import base58
from pyaver.enums import Side, SizeFormat, MarketStatus
from pyaver.refresh import refresh_user_market
from solana.publickey import PublicKey
from import AverMarket
from pyaver.user_market import UserMarket
from requests import get
from token_airdrop import request_token_airdrop, api_endpoint
# ----------------------------------------------------
# ----------------------------------------------------
# This example is intended to demonstrate an end-to-end interaction where
# - A wallet is created or reloaded from a secret key
# - The wallet is funded with SOL and Tokens
# - A request is made to the Aver API to obtain a list of markets
# - A market is loaded using the market's identifying public key
# -
async def main():
# ----------------------------------------------------
# ----------------------------------------------------
# Generate or reload an existing keypair ('wallet') - for example from storage in your system or environment files.
# - New keypairs can be generated by calling Kaypair()
secret_key = base58.b58decode('zSaKmpRbsJQQjmMRQsADRQ1vss8P2SQLbxGiiL8LFf9rJ8bFT8S1jAqj8Fkwg9hyq6vb97rR8EDkyu5EFD2tFbj')
owner_keypair = Keypair.from_secret_key(secret_key)
print(f'Keypair loaded with public key {owner_keypair.public_key}')
# ----------------------------------------------------
# ----------------------------------------------------
# Here we us default transaction options
# - You can learn more about these configuration points in the Solana documentation
# - Generally, it relates to the trade-off of speed vs certainty in confirmation by the network
opts = TxOpts(
connection = AsyncClient(
endpoint = get_solana_endpoint(SolanaNetwork.DEVNET),
commitment = 'confirmed',
timeout = 30
client: AverClient = await AverClient.load(
# ----------------------------------------------------
# ----------------------------------------------------
# Fund the wallet with Lamports/SOL if required
# - On mainnet, this would require a purchase/transfer of Lamports/SOL from another wallet or an exchange
# - On devnet, you can simulate this using an 'airdrop'
# Gets Solana Airdrop
print('Topping up SOL/Lamports...')
lamport_balance = await client.request_lamport_balance(owner_keypair.public_key)
print(f' - Old SOL/Lamports balance: {lamport_balance}')
if lamport_balance < 500000:
await client.request_lamport_airdrop(1_000_000, owner_keypair.public_key)
print(f' - New SOL/Lamports balance: {lamport_balance}')
print('Topping up USDC Tokens...')
# Creates (or loads if one already exists) an Associated Token Account - where tokens will be stored for this wallet
ata = await client.get_or_create_associated_token_account(
token_balance = await client.request_token_balance(client.quote_token, owner_keypair.public_key)
print(f' - Token balance: {token_balance}')
if token_balance < 50000:
txn_signature = request_token_airdrop('', client.quote_token, owner_keypair.public_key, 1_000_000_000)['signature']
# Wait to ensure transaction has been confirmed before moving on
await client.provider.connection.confirm_transaction(txn_signature, Confirmed)
token_balance = await client.request_token_balance(client.quote_token, owner_keypair.public_key)
print(f' - New token balance: {token_balance}')
# ----------------------------------------------------
# ----------------------------------------------------
# We can query the Aver API to provide a list of markets
# Filters can be applied to load specific categories, status, etc
# Here we simply load all markets and will select the first one in the section below
# To find out more, query in your browser
all_markets = get(api_endpoint(client.solana_network) + 'v3/markets?active_only=true')
results = all_markets.json()['results']
#Load all active markets from endpoint
market_pubkeys = [PublicKey(m['pubkey']) for m in results if m['internal_status'] == 'active']
# ----------------------------------------------------
# ----------------------------------------------------
# An AverMarket object can be initialized using only an AverClient and the PublicKey of a valid market
# This must be awaited, as the class will autopopulate state from all of the related
# on-chain accounts which make up this market.
if len(market_pubkeys) == 0:
print('There are currently no active markets, returning.')
#Loads market data from onchain
loaded_markets = await AverMarket.load_multiple(client, market_pubkeys)
#Ensure market is in ACTIVE_PRE_EVENT status so we can place orders on it
active_pre_event_markets = list(filter(lambda market: market.market_state.market_status == MarketStatus.ACTIVE_PRE_EVENT and market.market_state.trading_cease_time > datetime.utcnow().timestamp() if market is not None else False, loaded_markets))
#Let's just pick the first market in the list
market = active_pre_event_markets[0]
# Print market data or specific properties
print(f'Market {market.market_pubkey} loaded...')
print(f'Market name: {market.market_state.market_name}')
for idx, outcome_name in enumerate(market.market_state.outcome_names):
print(f' - {idx} - {outcome_name}')
print('Market state:')
# Print one or more of the orderbooks or orderbook properties from memory
outcome_1_orderbook = market.orderbooks[0]
print('Best Ask Price', outcome_1_orderbook.get_best_ask_price(True))
print('Best Bid Price', outcome_1_orderbook.get_best_bid_price(True))
# ----------------------------------------------------
# ----------------------------------------------------
# A User-Market Account (UMA) stores a given wallets matched and
# unmatched orders on-chain
# A UMA must be initialized before a user can interact with a
# market, so that their bets and orders can be stored.
# If required, this method will also initialized a User-Host-Lifetime
# account (UHLA) if necessary automatically.
# There are some optional parameters to consider when initializing
# a UMA - for example, allocating a particular number of slots
# for how many unmatched orders can remain open in this market
# at the same time. (e.g. a typical user may only need a few,
# while a market maker may wish to have capacity to place
# several orders per outcome and side.)
uma = await UserMarket.get_or_create_user_market_account(
client = client,
owner = owner_keypair,
market = market,
number_of_orders = (3 * market.market_state.number_of_outcomes) # Optional argument
print(f'UMA created at pubkey {uma.pubkey}')
# ----------------------------------------------------
# ----------------------------------------------------
# The UMA object can now be used to interact with the market.
# Actions like placing and order can be called on the UMA object
# Familiarize yourself with the list and format arguments
# for the place_order() method can accomodate.
# Some additional example of different formats are provided
# and have been commmented out.
# This order a BUY side on outcome 1 at a price of 0.5 and size 10
txn_signature = await uma.place_order(
owner = owner_keypair, # Required in keypair format, as the owned needs to 'sign' this transaction to approve it
outcome_id = 0, # Specifies which outcome/selection in the market to trade. Outcomes in a given market are indexed 0,1,..,n.
side = Side.BUY, # Whether we wish to buy/back or sell/lay
limit_price = 0.5, # Limit price (in probability format - range (0,1))
size = 10, # The trade size - specified in size_format (units of payout here)
size_format = SizeFormat.PAYOUT # The format to specify the trade size. Payout units are the number of dollars that would be returned in a back-win. Stake = Payout * Price (Probability)
#Wait to ensure transaction has been confirmed before moving on
await client.provider.connection.confirm_transaction(txn_signature['result'], Confirmed)
# Another order example - in Decimal Odds and Stake Size
decimal_price = 3.0
desired_stake = 10.0
txn_signature = await uma.place_order(
owner = owner_keypair,
outcome_id = 1,
side = Side.SELL, # Laying/selling
limit_price = (1/decimal_price), # limit_price must be provided as a probability price, but it is easy to convert from decimal or other odds formats
size = desired_stake, # Size here is provided as a STAKE, as the size_format is set to STAKE
size_format = SizeFormat.STAKE,
# --- Optional arguments ----
# send_options = TxOpts(), # Additional control could be exercised in terms of how the transaction is sent or confirmed
# order_type = OrderType.POST_ONLY, # Additional control to specify a particular order_type (i.e. post only in this case)
# self_trade_behavior = SelfTradeBehavior.CANCEL_PROVIDE, # Additional control to specify self-trade behavior
# active_pre_flight_check = True, # You can turn off client-side checks if you'd prefer to perform your own validations / attempt transactions which may fail on-chain due to invalid inputs or conditions
# Another order example - Placing a 'Market Order' - fill up to the size specified at best available price
target_payout_units = 50
txn_signature = await uma.place_order(
owner = owner_keypair,
outcome_id = 1,
side = Side.BUY, # Buying/backing
limit_price = 1, # Setting limit_price = 1 for a BUY/BACK or to 0 for a SELL/LAY for a market order
size = target_payout_units, # Size here is provided as a PAYOUT, as market orders cannot currently be supported in STAKE format
size_format = SizeFormat.PAYOUT,
order_type = OrderType.IOC, # A 'market order' (i.e. limit_price or 0 or 1) will only be accpeted if the order_type is IOC of KILL_OR_FILL (to prevent users from inadvertently putting exposed orders on the book)
# ----------------------------------------------------
# ----------------------------------------------------
# The UMA object needs to be refreshed to ensure it
# reflects the latest on-chain state.
# Depending on the configuration (speed vs confirmations
# trade-off) it may take some time before some state
# changes show-up. If using 'Confirmed' Commitment, it
# should show up almost immediately.
# Refreshing a User Market also automatically refreshes
# the data for the corresponding AverMarket object.
# There are a number of tools for efficiently refreshing
# data within the file. In particular this
# should be used where a script is trading on multiple
# markets at a time.
uma = await refresh_user_market(client, uma)
market =
print('UMA after placing order...')
print('- Unmatched Bets / Open Orders')
for order in uma.user_market_state.orders:
print('- Matched exposures')
for outcome_position in uma.user_market_state.outcome_positions:
# ----------------------------------------------------
# ----------------------------------------------------
# The UMA object needs to be refreshed to ensure it
# reflects the latest on-chain state.
# There are other methods available for cancelling orders
# in a group. For example, all orders for a market, or
# all orders for an outcome within a market.
# NOTE: If the earlier order resulted in a complete fill/match
# there may be no residual posted order, and therefore no
# order to cancel. Try adjusting the price to one that won't
# fill/match to demonstrate.
if uma.user_market_state.number_of_orders > 0:
my_order = uma.user_market_state.orders[0]
signature = await uma.cancel_order(
fee_payer = owner_keypair,
order_id = my_order.order_id,
outcome_id = my_order.outcome_id,
#Wait to ensure transaction has been confirmed before moving on
await client.provider.connection.confirm_transaction(signature['result'], Confirmed)
# Reload the UMA and print it out
uma = await refresh_user_market(client, uma)
market =
print('UMA after canceling order...')
print('- Unmatched Bets / Open Orders')
for order in uma.user_market_state.orders:
print('- Matched exposures')
for outcome_position in uma.user_market_state.outcome_positions:
print('No orders to cancel.')
# ----------------------------------------------------
# ----------------------------------------------------
#Finally close the client
await client.close()
from solana.publickey import PublicKey
from requests import post, get
from pyaver.constants import SolanaNetwork
def request_token_airdrop(
aver_api_endpoint: str,
quote_token: PublicKey,
owner: PublicKey,
amount: int = 1_000_000_000,
url = aver_api_endpoint + '/airdrop'
body = {
'wallet': owner.to_base58(),
'mint': quote_token.__str__(),
'amount': amount
response = post(url, body)
return response.json()
def api_endpoint(network: SolanaNetwork):
if(network == SolanaNetwork.DEVNET):
return ''
return ''
Typescript SDK documentation will be available very soon.

Overview of Steps

A simple overview of the steps involved is set out here (with more details on each step set out in the following pages):
  1. 1.
    Create or recall Solana wallet from storage.
  2. 2.
    Ensure that wallet is sufficiently funded with SOL and USDC, or ensure there are processes to transfer (or airdrop) sufficient funds to the wallet.
  3. 3.
    Establish a connection for your client with (a) the Solana network, and (b) the corresponding Aver API (the SDKs provide a Client object to enable this).
  4. 4.
    Retrieve (from the Aver API) and list available markets (for example, by category, date, or other query parameters).
  5. 5.
    Use the public key (unique identifier) for a market and load information about that market from the blockchain into client-side memory. From here, you can access descriptive information, price and orderbook information, etc.
  6. 6.
    Initialize a 'UserMarket' account to interact with a given market - this enables orders and positions specific to a given wallet and market to be stored and updated.
  7. 7.
    Create a client-side object which represents the initialized UserMarket account and which can be used to assemble instructions/transactions - such as to place, cancel and manage matched and unmatched orders.
  8. 8.
    Send instructions to the on-chain program to place orders - these instructions must contain the necessary parameters to describe your desired order.
  9. 9.
    Canceling orders can be performed for a specific order (specifying the market, outcome and order id) or be sending bulk transaction requests (for example to cancel all orders for a particular outcome or market). These too require transactions to be sent to the on-chain program with the required parameters.
  10. 10.
    Getting an up-to-date view of positions, trades and orders requires synchronizing client-side state with on-chain state - at regular intervals or when triggered by a change. The SDKs contain many helpful objects which abstract much of this and enable easy and optimized refreshing of information from the data stored on-chain.

Asynchronous Scripting

For more information on asynchronous scripting see the primer section.

Creating a Loop

When using asynchronous scripting in Python you will need to execute the logic using asyncio.
The simplest way (single loop) is to create an aysnc def (as show below) and execute it by calling<your_async_def>)
async def main():
# Will need to include 'await' before any sequential steps
# For example:
# await uma.place_order(...)
//You can run this with ts-node or in a browser
async function main() {

Closing the Client

It's recommended to close the client with the following processing logic once it is no longer required:
await client.close()
// Not required in TS