pyaver.utils
1from .aver_client import AverClient 2from spl.token.instructions import get_associated_token_address 3from spl.token._layouts import ACCOUNT_LAYOUT 4from spl.token.constants import ACCOUNT_LEN 5from .data_classes import UserBalanceState, MarketStatus 6from solana.publickey import PublicKey 7from .errors import parse_error 8from .slab import Slab 9from solana.keypair import Keypair 10from solana.rpc.types import RPCResponse, TxOpts 11import base64 12from anchorpy.error import ProgramError 13from solana.publickey import PublicKey 14from solana.rpc.async_api import AsyncClient 15from solana.transaction import TransactionInstruction, Transaction 16 17def parse_bytes_data(res: RPCResponse) -> bytes: 18 """ 19 Parses bytes from an RPC response 20 21 Args: 22 res (RPCResponse): Response 23 24 Raises: 25 Exception: Cannot load byte data 26 27 Returns: 28 bytes: Parsed data 29 """ 30 if ("result" not in res) or ("value" not in res["result"]) or ("data" not in res["result"]["value"]): 31 raise Exception(f"Cannot load byte data. {res['error']}") 32 data = res["result"]["value"]["data"][0] 33 return base64.decodebytes(data.encode("ascii")) 34 35def parse_multiple_bytes_data(res: RPCResponse, is_only_getting_data: bool = True) -> list[bytes]: 36 """ 37 Parses bytes from an RPC response for multiple accounts 38 39 Args: 40 res (RPCResponse): Response 41 is_only_getting_data (bool, optional): Only returns account data if true; gets all information otherwise. Defaults to True. 42 43 Raises: 44 Exception: Cannot load byte data 45 46 Returns: 47 list[bytes]: List of parsed byte data 48 """ 49 if ("result" not in res) or ("value" not in res["result"]): 50 raise Exception(f"Cannot load byte data. {res['error']}") 51 data_list = [] 52 raw_data_list = res['result']['value'] 53 for r in raw_data_list: 54 if(r is None): 55 data_list.append(None) 56 continue 57 if(is_only_getting_data): 58 data_list.append(base64.decodebytes(r['data'][0].encode('ascii'))) 59 else: 60 datum = r 61 datum['data'] = base64.decodebytes(r['data'][0].encode('ascii')) 62 data_list.append(datum) 63 return data_list 64 65async def load_bytes_data(conn: AsyncClient, address: PublicKey) -> bytes: 66 """ 67 Fetch account data from AsyncClient 68 69 Args: 70 conn (AsyncClient): Solana AsyncClient object 71 address (PublicKey): Public key of account to be loaded 72 73 Returns: 74 bytes: bytes 75 """ 76 res = await conn.get_account_info(address) 77 return parse_bytes_data(res) 78 79#This function chunks requests into max size of 100 accounts 80async def load_multiple_bytes_data( 81 conn: AsyncClient, 82 addresses_remaining: list[PublicKey], 83 loaded_data_so_far: list[bytes] = [], 84 is_only_getting_data: bool = True): 85 """ 86 Fetch account data from AsyncClient for multiple accounts 87 88 Args: 89 conn (AsyncClient): Solana AsyncClient object 90 addresses_remaining (list[PublicKey]): Public keys of accounts to be loaded 91 loaded_data_so_far (list[bytes], optional): Parameter for recursive use of function. Defaults to []. 92 is_only_getting_data (bool, optional): Only returns account data if true; gets all information otherwise. Defaults to True. 93 94 Returns: 95 list[bytes]: _description_ 96 """ 97 if(len(addresses_remaining) == 0): 98 return loaded_data_so_far 99 100 addresses_to_load = addresses_remaining[:100] 101 res = await conn.get_multiple_accounts(addresses_to_load) 102 return await load_multiple_bytes_data( 103 conn, 104 addresses_remaining[100:], 105 loaded_data_so_far + parse_multiple_bytes_data(res, is_only_getting_data), 106 is_only_getting_data 107 ) 108 109#TODO - calculate lamports required for transaction 110async def sign_and_send_transaction_instructions( 111 client: AverClient, 112 signers: list[Keypair], 113 fee_payer: Keypair, 114 tx_instructions: list[TransactionInstruction], 115 send_options: TxOpts = None, 116 manual_max_retry: int = 0 117): 118 """ 119 Cryptographically signs transaction and sends onchain 120 121 Args: 122 client (AverClient): AverClient object 123 signers (list[Keypair]): List of signing keypairs 124 fee_payer (Keypair): Keypair to pay fee for transaction 125 tx_instructions (list[TransactionInstruction]): List of transaction instructions to pack into transaction to be sent 126 send_options (TxOpts, optional): Options to specify when broadcasting a transaction. Defaults to None. 127 128 Raises: 129 error: COMING SOON 130 131 Returns: 132 RPCResponse: Response 133 """ 134 tx = Transaction() 135 if(not fee_payer in signers): 136 signers = [fee_payer] + signers 137 tx.add(*tx_instructions) 138 if(send_options == None): 139 send_options = client.provider.opts 140 141 142 attempts = 0 143 while attempts <= manual_max_retry: 144 try: 145 return await client.provider.connection.send_transaction(tx, *signers, opts=send_options) 146 except Exception as e: 147 error = parse_error(e, client.program) 148 if(isinstance(error, ProgramError)): 149 raise error 150 else: 151 attempts = attempts + 1 152 153 154 155def calculate_tick_size_for_price(limit_price: float): 156 """ 157 Calculates tick size for specific price 158 159 Args: 160 limit_price (float): Limit price 161 162 Raises: 163 Exception: Limit price too low 164 Exception: Limit price too high 165 166 Returns: 167 int: Tick size 168 """ 169 if(limit_price < 1_000): 170 raise Exception('Limit price too low') 171 if(limit_price <= 2_000): 172 return 100 173 if(limit_price <= 5_000): 174 return 250 175 if(limit_price <= 10_000): 176 return 500 177 if(limit_price <= 20_000): 178 return 1_000 179 if(limit_price <= 50_000): 180 return 2_500 181 if(limit_price <= 100_000): 182 return 5_000 183 if(limit_price <= 990_000): 184 return 10_000 185 if(limit_price > 990_000): 186 raise Exception('Limit price too high') 187 return limit_price 188 189def round_price_to_nearest_tick_size(limit_price: float): 190 """ 191 Rounds price to the nearest tick size available 192 193 Args: 194 limit_price (float): Limit price 195 196 Returns: 197 float: Rounded limit price 198 """ 199 limit_price_to_6dp = limit_price * (10 ** 6) 200 tick_size = calculate_tick_size_for_price(limit_price_to_6dp) 201 rounded_limit_price_to_6dp = round(limit_price_to_6dp/tick_size) * tick_size 202 rounded_limit_price = rounded_limit_price_to_6dp / (10 ** 6) 203 204 return rounded_limit_price 205 206def parse_user_market_state(buffer: bytes, aver_client: AverClient): 207 """ 208 Parses raw onchain data to UserMarketState object 209 Args: 210 buffer (bytes): Raw bytes coming from onchain 211 aver_client (AverClient): AverClient object 212 213 Returns: 214 UserMarket: UserMarketState object 215 """ 216 #uma_parsed = USER_MARKET_STATE_LAYOUT.parse(buffer) 217 uma_parsed = aver_client.program.account['UserMarket'].coder.accounts.decode(buffer) 218 return uma_parsed 219 220def parse_market_state(buffer: bytes, aver_client: AverClient): 221 """ 222 Parses raw onchain data to MarketState object 223 Args: 224 buffer (bytes): Raw bytes coming from onchain 225 aver_client (AverClient): AverClient object 226 227 Returns: 228 MarketState: MarketState object 229 """ 230 231 market_account_info = aver_client.program.account['Market'].coder.accounts.decode(buffer) 232 return market_account_info 233 234def parse_market_store(buffer: bytes, aver_client: AverClient): 235 """ 236 Parses onchain data for a MarketStore State 237 238 Args: 239 buffer (bytes): Raw bytes coming from onchain 240 aver_client (AverClient): AverClient 241 242 Returns: 243 MarketStore: MarketStore object 244 """ 245 market_store_account_info = aver_client.program.account['MarketStore'].coder.accounts.decode(buffer) 246 return market_store_account_info 247 248 249def parse_user_host_lifetime_state(aver_client: AverClient, buffer): 250 """ 251 Parses raw onchain data to UserHostLifetime object 252 253 Args: 254 aver_client (AverClient): AverClient object 255 buffer (bytes): Raw bytes coming from onchain 256 257 Returns: 258 UserHostLifetime: UserHostLifetime object 259 """ 260 user_host_lifetime_info = aver_client.program.account['UserHostLifetime'].coder.accounts.decode(buffer) 261 return user_host_lifetime_info 262 263async def load_multiple_account_states( 264 aver_client: AverClient, 265 market_pubkeys: list[PublicKey], 266 market_store_pubkeys: list[PublicKey], 267 slab_pubkeys: list[PublicKey], 268 user_market_pubkeys: list[PublicKey] = [], 269 user_pubkeys: list[PublicKey] = [], 270 uhl_pubkeys: list[PublicKey] = [] 271 ): 272 """ 273 Fetchs account data for multiple account types at once 274 275 Used in refresh.py to quckly and efficiently pull all account data at once 276 277 Args: 278 aver_client (AverClient): AverClient object 279 market_pubkeys (list[PublicKey]): List of MarketState object public keys 280 market_store_pubkeys (list[PublicKey]): List of MarketStoreStore object public keys 281 slab_pubkeys (list[PublicKey]): List of Slab public keys for orderbooks 282 user_market_pubkeys (list[PublicKey], optional): List of UserMarketState object public keys. Defaults to []. 283 user_pubkeys (list[PublicKey], optional): List of UserMarket owners' public keys. Defaults to []. 284 uhl_pubkeuys(list[PublicKey], optional): List of UserHostLifetime public keys. Defaults to [] 285 286 Returns: 287 dict[str, list]: Dictionary containing `market_states`, `market_stores`, `slabs`, `user_market_states`, `user_balance_sheets` 288 """ 289 all_ata_pubkeys = [get_associated_token_address(u, aver_client.quote_token) for u in user_pubkeys] 290 291 all_pubkeys = market_pubkeys + market_store_pubkeys + slab_pubkeys + user_market_pubkeys + user_pubkeys + all_ata_pubkeys + uhl_pubkeys 292 data = await load_multiple_bytes_data(aver_client.provider.connection, all_pubkeys, [], False) 293 294 deserialized_market_state = [] 295 for index, m in enumerate(market_pubkeys): 296 buffer = data[index] 297 deserialized_market_state.append(parse_market_state(buffer['data'], aver_client)) 298 299 deserialized_market_store = [] 300 for index, m in enumerate(market_pubkeys): 301 buffer = data[index + len(market_pubkeys)] 302 if(buffer is None): 303 deserialized_market_store.append(None) 304 continue 305 deserialized_market_store.append(parse_market_store(buffer['data'], aver_client)) 306 307 deserialized_slab_data = [] 308 for index, s in enumerate(slab_pubkeys): 309 buffer = data[index + len(market_pubkeys) + len(market_store_pubkeys)] 310 if(buffer is None): 311 deserialized_slab_data.append(None) 312 continue 313 deserialized_slab_data.append(Slab.from_bytes(buffer['data'])) 314 315 deserialized_uma_data = [] 316 if(user_market_pubkeys is not None): 317 for index, u in enumerate(user_market_pubkeys): 318 buffer = data[index + len(market_pubkeys) + len(market_store_pubkeys) + len(slab_pubkeys)] 319 if(buffer is None): 320 deserialized_uma_data.append(None) 321 continue 322 deserialized_uma_data.append(parse_user_market_state(buffer['data'], aver_client)) 323 324 lamport_balances = [] 325 if(user_pubkeys is not None): 326 for index, pubkey in enumerate(user_pubkeys): 327 balance = data[index + len(market_pubkeys) + len(market_store_pubkeys) + len(slab_pubkeys) + len(user_market_pubkeys)] 328 lamport_balances.append(balance['lamports'] if balance and balance['lamports'] is not None else 0) 329 330 token_balances = [] 331 if(all_ata_pubkeys is not None): 332 for index, pubkey in enumerate(all_ata_pubkeys): 333 buffer = data[index + len(market_pubkeys) + len(market_store_pubkeys) + len(slab_pubkeys) + len(user_market_pubkeys) + len(user_pubkeys)] 334 if(len(buffer['data']) == ACCOUNT_LEN): 335 token_balances.append(ACCOUNT_LAYOUT.parse(buffer['data'])['amount']) 336 else: 337 token_balances.append(0) 338 339 user_balance_states = [] 340 for index, x in enumerate(lamport_balances): 341 user_balance_state = UserBalanceState(lamport_balances[index], token_balances[index]) 342 user_balance_states.append(user_balance_state) 343 344 uhl_states = [] 345 for index, pubkey in enumerate(uhl_pubkeys): 346 buffer = data[index + len(market_pubkeys) + len(market_store_pubkeys) + len(slab_pubkeys) + len(user_market_pubkeys) + len(user_pubkeys) + len(all_ata_pubkeys)] 347 if(buffer is None): 348 uhl_states.append(None) 349 continue 350 uhl_state = parse_user_host_lifetime_state(aver_client, buffer['data']) 351 uhl_states.append(uhl_state) 352 353 return { 354 'market_states': deserialized_market_state, 355 'market_stores': deserialized_market_store, 356 'slabs': deserialized_slab_data, 357 'user_market_states': deserialized_uma_data, 358 'user_balance_states': user_balance_states, 359 'user_host_lifetime_states': uhl_states 360 } 361 362def is_market_tradeable(market_status: MarketStatus): 363 """ 364 Returns if it is possible to place an order on a market 365 366 Args: 367 market_status (MarketStatus): Market Status (found in MarketState) 368 369 Returns: 370 bool: Trade possible is true 371 """ 372 return market_status in [MarketStatus.ACTIVE_IN_PLAY, MarketStatus.ACTIVE_PRE_EVENT] 373 374def can_cancel_order_in_market(market_status: MarketStatus): 375 """ 376 Returns if it is possible to cancel an order on a market 377 378 Args: 379 market_status (MarketStatus): Market Status (found in MarketState) 380 381 Returns: 382 _type_: Order cancellable if true 383 """ 384 return market_status in [ 385 MarketStatus.ACTIVE_PRE_EVENT, 386 MarketStatus.ACTIVE_IN_PLAY, 387 MarketStatus.HALTED_IN_PLAY, 388 MarketStatus.HALTED_PRE_EVENT 389 ]
18def parse_bytes_data(res: RPCResponse) -> bytes: 19 """ 20 Parses bytes from an RPC response 21 22 Args: 23 res (RPCResponse): Response 24 25 Raises: 26 Exception: Cannot load byte data 27 28 Returns: 29 bytes: Parsed data 30 """ 31 if ("result" not in res) or ("value" not in res["result"]) or ("data" not in res["result"]["value"]): 32 raise Exception(f"Cannot load byte data. {res['error']}") 33 data = res["result"]["value"]["data"][0] 34 return base64.decodebytes(data.encode("ascii"))
Parses bytes from an RPC response
Args
- res (RPCResponse): Response
Raises
- Exception: Cannot load byte data
Returns
bytes: Parsed data
36def parse_multiple_bytes_data(res: RPCResponse, is_only_getting_data: bool = True) -> list[bytes]: 37 """ 38 Parses bytes from an RPC response for multiple accounts 39 40 Args: 41 res (RPCResponse): Response 42 is_only_getting_data (bool, optional): Only returns account data if true; gets all information otherwise. Defaults to True. 43 44 Raises: 45 Exception: Cannot load byte data 46 47 Returns: 48 list[bytes]: List of parsed byte data 49 """ 50 if ("result" not in res) or ("value" not in res["result"]): 51 raise Exception(f"Cannot load byte data. {res['error']}") 52 data_list = [] 53 raw_data_list = res['result']['value'] 54 for r in raw_data_list: 55 if(r is None): 56 data_list.append(None) 57 continue 58 if(is_only_getting_data): 59 data_list.append(base64.decodebytes(r['data'][0].encode('ascii'))) 60 else: 61 datum = r 62 datum['data'] = base64.decodebytes(r['data'][0].encode('ascii')) 63 data_list.append(datum) 64 return data_list
Parses bytes from an RPC response for multiple accounts
Args
- res (RPCResponse): Response
- is_only_getting_data (bool, optional): Only returns account data if true; gets all information otherwise. Defaults to True.
Raises
- Exception: Cannot load byte data
Returns
list[bytes]: List of parsed byte data
66async def load_bytes_data(conn: AsyncClient, address: PublicKey) -> bytes: 67 """ 68 Fetch account data from AsyncClient 69 70 Args: 71 conn (AsyncClient): Solana AsyncClient object 72 address (PublicKey): Public key of account to be loaded 73 74 Returns: 75 bytes: bytes 76 """ 77 res = await conn.get_account_info(address) 78 return parse_bytes_data(res)
Fetch account data from AsyncClient
Args
- conn (AsyncClient): Solana AsyncClient object
- address (PublicKey): Public key of account to be loaded
Returns
bytes: bytes
81async def load_multiple_bytes_data( 82 conn: AsyncClient, 83 addresses_remaining: list[PublicKey], 84 loaded_data_so_far: list[bytes] = [], 85 is_only_getting_data: bool = True): 86 """ 87 Fetch account data from AsyncClient for multiple accounts 88 89 Args: 90 conn (AsyncClient): Solana AsyncClient object 91 addresses_remaining (list[PublicKey]): Public keys of accounts to be loaded 92 loaded_data_so_far (list[bytes], optional): Parameter for recursive use of function. Defaults to []. 93 is_only_getting_data (bool, optional): Only returns account data if true; gets all information otherwise. Defaults to True. 94 95 Returns: 96 list[bytes]: _description_ 97 """ 98 if(len(addresses_remaining) == 0): 99 return loaded_data_so_far 100 101 addresses_to_load = addresses_remaining[:100] 102 res = await conn.get_multiple_accounts(addresses_to_load) 103 return await load_multiple_bytes_data( 104 conn, 105 addresses_remaining[100:], 106 loaded_data_so_far + parse_multiple_bytes_data(res, is_only_getting_data), 107 is_only_getting_data 108 )
Fetch account data from AsyncClient for multiple accounts
Args
- conn (AsyncClient): Solana AsyncClient object
- addresses_remaining (list[PublicKey]): Public keys of accounts to be loaded
- loaded_data_so_far (list[bytes], optional): Parameter for recursive use of function. Defaults to [].
- is_only_getting_data (bool, optional): Only returns account data if true; gets all information otherwise. Defaults to True.
Returns
list[bytes]: _description_
111async def sign_and_send_transaction_instructions( 112 client: AverClient, 113 signers: list[Keypair], 114 fee_payer: Keypair, 115 tx_instructions: list[TransactionInstruction], 116 send_options: TxOpts = None, 117 manual_max_retry: int = 0 118): 119 """ 120 Cryptographically signs transaction and sends onchain 121 122 Args: 123 client (AverClient): AverClient object 124 signers (list[Keypair]): List of signing keypairs 125 fee_payer (Keypair): Keypair to pay fee for transaction 126 tx_instructions (list[TransactionInstruction]): List of transaction instructions to pack into transaction to be sent 127 send_options (TxOpts, optional): Options to specify when broadcasting a transaction. Defaults to None. 128 129 Raises: 130 error: COMING SOON 131 132 Returns: 133 RPCResponse: Response 134 """ 135 tx = Transaction() 136 if(not fee_payer in signers): 137 signers = [fee_payer] + signers 138 tx.add(*tx_instructions) 139 if(send_options == None): 140 send_options = client.provider.opts 141 142 143 attempts = 0 144 while attempts <= manual_max_retry: 145 try: 146 return await client.provider.connection.send_transaction(tx, *signers, opts=send_options) 147 except Exception as e: 148 error = parse_error(e, client.program) 149 if(isinstance(error, ProgramError)): 150 raise error 151 else: 152 attempts = attempts + 1
Cryptographically signs transaction and sends onchain
Args
- client (AverClient): AverClient object
- signers (list[Keypair]): List of signing keypairs
- fee_payer (Keypair): Keypair to pay fee for transaction
- tx_instructions (list[TransactionInstruction]): List of transaction instructions to pack into transaction to be sent
- send_options (TxOpts, optional): Options to specify when broadcasting a transaction. Defaults to None.
Raises
- error: COMING SOON
Returns
RPCResponse: Response
156def calculate_tick_size_for_price(limit_price: float): 157 """ 158 Calculates tick size for specific price 159 160 Args: 161 limit_price (float): Limit price 162 163 Raises: 164 Exception: Limit price too low 165 Exception: Limit price too high 166 167 Returns: 168 int: Tick size 169 """ 170 if(limit_price < 1_000): 171 raise Exception('Limit price too low') 172 if(limit_price <= 2_000): 173 return 100 174 if(limit_price <= 5_000): 175 return 250 176 if(limit_price <= 10_000): 177 return 500 178 if(limit_price <= 20_000): 179 return 1_000 180 if(limit_price <= 50_000): 181 return 2_500 182 if(limit_price <= 100_000): 183 return 5_000 184 if(limit_price <= 990_000): 185 return 10_000 186 if(limit_price > 990_000): 187 raise Exception('Limit price too high') 188 return limit_price
Calculates tick size for specific price
Args
- limit_price (float): Limit price
Raises
- Exception: Limit price too low
- Exception: Limit price too high
Returns
int: Tick size
190def round_price_to_nearest_tick_size(limit_price: float): 191 """ 192 Rounds price to the nearest tick size available 193 194 Args: 195 limit_price (float): Limit price 196 197 Returns: 198 float: Rounded limit price 199 """ 200 limit_price_to_6dp = limit_price * (10 ** 6) 201 tick_size = calculate_tick_size_for_price(limit_price_to_6dp) 202 rounded_limit_price_to_6dp = round(limit_price_to_6dp/tick_size) * tick_size 203 rounded_limit_price = rounded_limit_price_to_6dp / (10 ** 6) 204 205 return rounded_limit_price
Rounds price to the nearest tick size available
Args
- limit_price (float): Limit price
Returns
float: Rounded limit price
207def parse_user_market_state(buffer: bytes, aver_client: AverClient): 208 """ 209 Parses raw onchain data to UserMarketState object 210 Args: 211 buffer (bytes): Raw bytes coming from onchain 212 aver_client (AverClient): AverClient object 213 214 Returns: 215 UserMarket: UserMarketState object 216 """ 217 #uma_parsed = USER_MARKET_STATE_LAYOUT.parse(buffer) 218 uma_parsed = aver_client.program.account['UserMarket'].coder.accounts.decode(buffer) 219 return uma_parsed
Parses raw onchain data to UserMarketState object
Args
- buffer (bytes): Raw bytes coming from onchain
- aver_client (AverClient): AverClient object
Returns
UserMarket: UserMarketState object
221def parse_market_state(buffer: bytes, aver_client: AverClient): 222 """ 223 Parses raw onchain data to MarketState object 224 Args: 225 buffer (bytes): Raw bytes coming from onchain 226 aver_client (AverClient): AverClient object 227 228 Returns: 229 MarketState: MarketState object 230 """ 231 232 market_account_info = aver_client.program.account['Market'].coder.accounts.decode(buffer) 233 return market_account_info
Parses raw onchain data to MarketState object
Args
- buffer (bytes): Raw bytes coming from onchain
- aver_client (AverClient): AverClient object
Returns
MarketState: MarketState object
235def parse_market_store(buffer: bytes, aver_client: AverClient): 236 """ 237 Parses onchain data for a MarketStore State 238 239 Args: 240 buffer (bytes): Raw bytes coming from onchain 241 aver_client (AverClient): AverClient 242 243 Returns: 244 MarketStore: MarketStore object 245 """ 246 market_store_account_info = aver_client.program.account['MarketStore'].coder.accounts.decode(buffer) 247 return market_store_account_info
Parses onchain data for a MarketStore State
Args
- buffer (bytes): Raw bytes coming from onchain
- aver_client (AverClient): AverClient
Returns
MarketStore: MarketStore object
250def parse_user_host_lifetime_state(aver_client: AverClient, buffer): 251 """ 252 Parses raw onchain data to UserHostLifetime object 253 254 Args: 255 aver_client (AverClient): AverClient object 256 buffer (bytes): Raw bytes coming from onchain 257 258 Returns: 259 UserHostLifetime: UserHostLifetime object 260 """ 261 user_host_lifetime_info = aver_client.program.account['UserHostLifetime'].coder.accounts.decode(buffer) 262 return user_host_lifetime_info
Parses raw onchain data to UserHostLifetime object
Args
- aver_client (AverClient): AverClient object
- buffer (bytes): Raw bytes coming from onchain
Returns
UserHostLifetime: UserHostLifetime object
264async def load_multiple_account_states( 265 aver_client: AverClient, 266 market_pubkeys: list[PublicKey], 267 market_store_pubkeys: list[PublicKey], 268 slab_pubkeys: list[PublicKey], 269 user_market_pubkeys: list[PublicKey] = [], 270 user_pubkeys: list[PublicKey] = [], 271 uhl_pubkeys: list[PublicKey] = [] 272 ): 273 """ 274 Fetchs account data for multiple account types at once 275 276 Used in refresh.py to quckly and efficiently pull all account data at once 277 278 Args: 279 aver_client (AverClient): AverClient object 280 market_pubkeys (list[PublicKey]): List of MarketState object public keys 281 market_store_pubkeys (list[PublicKey]): List of MarketStoreStore object public keys 282 slab_pubkeys (list[PublicKey]): List of Slab public keys for orderbooks 283 user_market_pubkeys (list[PublicKey], optional): List of UserMarketState object public keys. Defaults to []. 284 user_pubkeys (list[PublicKey], optional): List of UserMarket owners' public keys. Defaults to []. 285 uhl_pubkeuys(list[PublicKey], optional): List of UserHostLifetime public keys. Defaults to [] 286 287 Returns: 288 dict[str, list]: Dictionary containing `market_states`, `market_stores`, `slabs`, `user_market_states`, `user_balance_sheets` 289 """ 290 all_ata_pubkeys = [get_associated_token_address(u, aver_client.quote_token) for u in user_pubkeys] 291 292 all_pubkeys = market_pubkeys + market_store_pubkeys + slab_pubkeys + user_market_pubkeys + user_pubkeys + all_ata_pubkeys + uhl_pubkeys 293 data = await load_multiple_bytes_data(aver_client.provider.connection, all_pubkeys, [], False) 294 295 deserialized_market_state = [] 296 for index, m in enumerate(market_pubkeys): 297 buffer = data[index] 298 deserialized_market_state.append(parse_market_state(buffer['data'], aver_client)) 299 300 deserialized_market_store = [] 301 for index, m in enumerate(market_pubkeys): 302 buffer = data[index + len(market_pubkeys)] 303 if(buffer is None): 304 deserialized_market_store.append(None) 305 continue 306 deserialized_market_store.append(parse_market_store(buffer['data'], aver_client)) 307 308 deserialized_slab_data = [] 309 for index, s in enumerate(slab_pubkeys): 310 buffer = data[index + len(market_pubkeys) + len(market_store_pubkeys)] 311 if(buffer is None): 312 deserialized_slab_data.append(None) 313 continue 314 deserialized_slab_data.append(Slab.from_bytes(buffer['data'])) 315 316 deserialized_uma_data = [] 317 if(user_market_pubkeys is not None): 318 for index, u in enumerate(user_market_pubkeys): 319 buffer = data[index + len(market_pubkeys) + len(market_store_pubkeys) + len(slab_pubkeys)] 320 if(buffer is None): 321 deserialized_uma_data.append(None) 322 continue 323 deserialized_uma_data.append(parse_user_market_state(buffer['data'], aver_client)) 324 325 lamport_balances = [] 326 if(user_pubkeys is not None): 327 for index, pubkey in enumerate(user_pubkeys): 328 balance = data[index + len(market_pubkeys) + len(market_store_pubkeys) + len(slab_pubkeys) + len(user_market_pubkeys)] 329 lamport_balances.append(balance['lamports'] if balance and balance['lamports'] is not None else 0) 330 331 token_balances = [] 332 if(all_ata_pubkeys is not None): 333 for index, pubkey in enumerate(all_ata_pubkeys): 334 buffer = data[index + len(market_pubkeys) + len(market_store_pubkeys) + len(slab_pubkeys) + len(user_market_pubkeys) + len(user_pubkeys)] 335 if(len(buffer['data']) == ACCOUNT_LEN): 336 token_balances.append(ACCOUNT_LAYOUT.parse(buffer['data'])['amount']) 337 else: 338 token_balances.append(0) 339 340 user_balance_states = [] 341 for index, x in enumerate(lamport_balances): 342 user_balance_state = UserBalanceState(lamport_balances[index], token_balances[index]) 343 user_balance_states.append(user_balance_state) 344 345 uhl_states = [] 346 for index, pubkey in enumerate(uhl_pubkeys): 347 buffer = data[index + len(market_pubkeys) + len(market_store_pubkeys) + len(slab_pubkeys) + len(user_market_pubkeys) + len(user_pubkeys) + len(all_ata_pubkeys)] 348 if(buffer is None): 349 uhl_states.append(None) 350 continue 351 uhl_state = parse_user_host_lifetime_state(aver_client, buffer['data']) 352 uhl_states.append(uhl_state) 353 354 return { 355 'market_states': deserialized_market_state, 356 'market_stores': deserialized_market_store, 357 'slabs': deserialized_slab_data, 358 'user_market_states': deserialized_uma_data, 359 'user_balance_states': user_balance_states, 360 'user_host_lifetime_states': uhl_states 361 }
Fetchs account data for multiple account types at once
Used in refresh.py to quckly and efficiently pull all account data at once
Args
- aver_client (AverClient): AverClient object
- market_pubkeys (list[PublicKey]): List of MarketState object public keys
- market_store_pubkeys (list[PublicKey]): List of MarketStoreStore object public keys
- slab_pubkeys (list[PublicKey]): List of Slab public keys for orderbooks
- user_market_pubkeys (list[PublicKey], optional): List of UserMarketState object public keys. Defaults to [].
- user_pubkeys (list[PublicKey], optional): List of UserMarket owners' public keys. Defaults to [].
- uhl_pubkeuys(list[PublicKey], optional): List of UserHostLifetime public keys. Defaults to []
Returns
dict[str, list]: Dictionary containing
market_states
,market_stores
,slabs
,user_market_states
,user_balance_sheets
363def is_market_tradeable(market_status: MarketStatus): 364 """ 365 Returns if it is possible to place an order on a market 366 367 Args: 368 market_status (MarketStatus): Market Status (found in MarketState) 369 370 Returns: 371 bool: Trade possible is true 372 """ 373 return market_status in [MarketStatus.ACTIVE_IN_PLAY, MarketStatus.ACTIVE_PRE_EVENT]
Returns if it is possible to place an order on a market
Args
- market_status (MarketStatus): Market Status (found in MarketState)
Returns
bool: Trade possible is true
375def can_cancel_order_in_market(market_status: MarketStatus): 376 """ 377 Returns if it is possible to cancel an order on a market 378 379 Args: 380 market_status (MarketStatus): Market Status (found in MarketState) 381 382 Returns: 383 _type_: Order cancellable if true 384 """ 385 return market_status in [ 386 MarketStatus.ACTIVE_PRE_EVENT, 387 MarketStatus.ACTIVE_IN_PLAY, 388 MarketStatus.HALTED_IN_PLAY, 389 MarketStatus.HALTED_PRE_EVENT 390 ]
Returns if it is possible to cancel an order on a market
Args
- market_status (MarketStatus): Market Status (found in MarketState)
Returns
_type_: Order cancellable if true