Async Usage
The Lighter client is async-first and supports two usage styles:
- build a client and call methods directly, for quick one-off scripts
- use
async with, to close every connection cleanly when you are done
Quick Usage
Lighter.new() resolves credentials and builds the client without connecting to anything.
Connections open on first use:
from typed_lighter import Lighter
client = Lighter.new(public=True)
status = await client.api.system.status()Context Manager Usage
async with on the top-level client is the only lifecycle call you make. It opens nothing
up front: the REST connection pool, the WebSocket connection, the explorer and the deposit
bridge each connect lazily on first use, and on exit the client closes whichever of them
were opened. Every one of them is closed even if closing another fails, or if the task
leaving the block is cancelled.
If another task is still opening the WebSocket connection when the block exits, the exit
doesn't wait for it. That connect closes what it opened and raises NetworkError, so no
connection outlives the block. Work that starts after the exit gets a fresh connection.
Exiting does not retire the client. Using it after the block silently opens new
connections (the REST connection pool, or the WebSocket connection with its background
keepalive), and only another exit of the top-level client closes them. Don't use a client
after its block ends; if you do, enter it again with async with.
from typed_lighter import Lighter
async with Lighter.new() as client:
books = await client.api.markets.order_books()
await client.tx.cancel_all_orders({'mode': 'immediate'}, transport='ws')Enter only the top-level client. client.api, client.tx, client.streams,
client.explorer and client.deposit_bridge share its connections, so they never close
them: async with client.tx: (or any of those five) is allowed but does nothing, and a
live stream keeps receiving after such a block ends. client.signer and Scaler hold no
connection and don't support async with at all.
from typed_lighter import Lighter
async with Lighter.new() as client:
async with client.streams.trades(0) as trades:
async with client.tx: # does nothing: the WebSocket stays open
await client.tx.cancel_all_orders({'mode': 'immediate'}, transport='ws')
async for frame in trades:
print(frame['trades'])
break
# the connections close hereStreams
Every subscription can be used two ways. With async with, leaving the block unsubscribes:
from typed_lighter import Lighter
async with Lighter.new(public=True) as client:
async with client.streams.trades(0) as trades:
async for frame in trades:
print(frame['trades'])With await, the subscription stays open until you unsubscribe:
from typed_lighter import Lighter
async with Lighter.new(public=True) as client:
trades = await client.streams.trades(0)
async for frame in trades:
print(frame['trades'])
break
await trades.unsubscribe()Shared Connections
The client's surfaces share their transports:
client.apiandclient.tx(over HTTP) use one REST connection pool.client.streamsandclient.tx(withtransport='ws') use one WebSocket connection: subscriptions and transactions are multiplexed over it.client.explorerandclient.deposit_bridgehave hosts of their own.
Independent calls can run concurrently:
import asyncio
from typed_lighter import Lighter
async with Lighter.new() as client:
account = client.signer.account_index
books, orders = await asyncio.gather(
client.api.markets.order_books(),
client.api.account.orders.active(account_index=account),
)Concurrent transactions are safe too. Each API key's nonces are handed out under a per-key lock held from signing through submission, so transactions on one key reach Lighter in nonce order; with several keys configured, transactions rotate across them and run in parallel.
Guidance
Use async with on the top-level client by default: it is the only way to close the
connections deterministically, and a WebSocket connection left open keeps a background
keepalive running. Without it, connections still open on first use and stay open until the
process ends. Plain construction is fine for short scripts and for signing offline, which
opens no connection at all.