Async Usage
Kraken clients are async-first and support two usage styles:
- construct a client and call methods directly for quick one-off requests
- use
async withwhen you want explicit lifecycle management
Quick Usage
For short request-response flows, plain construction is fine -- the underlying transport(s) open lazily on first use.
from typed_kraken import Kraken
client = Kraken.new(public=True)
ticker = await client.spot.market_data.ticker(pair='XBTUSD')
print(ticker)That works because the REST client opens its underlying httpx.AsyncClient when the first
request is sent -- there's no separate connect step to forget.
Context Manager Usage
Use async with when you want the client to open up front and close cleanly at the end of
the block.
from typed_kraken import Kraken
async with Kraken.new(public=True) as client:
ticker = await client.spot.market_data.ticker(pair='XBTUSD')
book = await client.spot.market_data.pre_trade(symbol='BTC/USD')Kraken.new(...) builds all three top-level surfaces -- spot (REST), streams
(WebSocket subscriptions), and trading_ws (WebSocket trading RPCs) -- and its
__aenter__ enters them concurrently (asyncio.gather), so async with Kraken.new(...)
is the only thing you need: every sub-surface underneath (spot.account, spot.trading,
streams.market_data, trading_ws.add_order, ...) bottoms out lazily on first use, the
same as direct construction. You never enter a sub-client separately.
This is the recommended style for:
- multiple requests in the same flow
- long-lived sessions
- any streaming workflow
- code where explicit cleanup matters
Streams
streams.market_data and streams.private methods are channel subscriptions: each returns
a StreamManager, not a stream directly. Use async with on it so the subscription is
unsubscribed automatically when the block exits:
from typed_kraken import Kraken
async with Kraken.new(public=True) as client:
async with client.streams.market_data.ticker(symbol=['BTC/USD']) as ticker:
async for msg in ticker:
for entry in msg['data']:
print(entry['symbol'], entry['last'])awaiting the manager directly also works, but leaves the subscription open until you call
unsubscribe() yourself:
from typed_kraken import Kraken
async with Kraken.new(public=True) as client:
ticker = await client.streams.market_data.ticker(symbol=['BTC/USD'])
async for msg in ticker:
print(msg['data'][0]['last'])
break
await ticker.unsubscribe()Trading (WebSocket)
trading_ws is a separate top-level surface, not part of streams: its methods
(add_order, cancel_order, edit_order, ...) are plain WebSocket RPC calls, not
subscriptions -- await them directly, the same as an HTTP call:
from typed_kraken import Kraken
async with Kraken.new() as client:
result = await client.trading_ws.add_order({
'order_type': 'limit', 'side': 'buy', 'order_qty': 0.001,
'symbol': 'BTC/USD', 'limit_price': 10_000,
})
print(result.get('order_id'))Composite/Multi-Surface Client
Kraken.new() bundles three independent top-level surfaces:
spot-- REST, underhttps://api.kraken.com. OneHttpRpcClientshared across five product groups exposed ascached_propertys:account,earn,funding,market_data,trading. Public methods (likemarket_data.ticker) work with no credentials; private ones sign each request.streams-- WebSocket v2 channel subscriptions, over two separate connections.market_clientconnects to the publicwss://ws.kraken.com/v2and backsstreams.market_data.private_clientconnects to the authenticatedwss://ws-auth.kraken.com/v2and backsstreams.private(account channel subscriptions).trading_ws-- WebSocket v2 trading RPCs (order placement/cancellation), request/reply rather than subscriptions. Reaches Kraken over the sameprivate_clientconnectionstreams.privateuses -- Kraken serves both over one authenticated socket -- but is its own top-level surface, kept out ofstreamssince its calls areawaited directly rather than iterated.
Pass public=True to build a client with no credentials, usable only for
spot.market_data and streams.market_data.
from typed_kraken import Kraken
async with Kraken.new() as client:
ticker = await client.spot.market_data.ticker(pair='XBTUSD')
result = await client.trading_ws.add_order({
'order_type': 'market', 'side': 'buy', 'order_qty': 0.001, 'symbol': 'BTC/USD',
})Each subscription's StreamManager also supports .map(f)/.filter(f) to transform or
filter pushes before you iterate them, if you want a narrower or reshaped stream.
Guidance
Use direct construction for quick reads. Use async with by default when doing more than
one call, opening streams, or wanting predictable cleanup.