radion-sdk 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches:
7
+ - main
8
+
9
+ jobs:
10
+ check:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v5
15
+ with:
16
+ enable-cache: true
17
+ - run: uv sync --extra dev
18
+ - run: uv run ruff check
19
+ - run: uv run ty check
@@ -0,0 +1,9 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ dist/
5
+ build/
6
+ *.egg-info/
7
+ .ruff_cache/
8
+ .DS_Store
9
+ .env
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Radion
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,210 @@
1
+ Metadata-Version: 2.4
2
+ Name: radion-sdk
3
+ Version: 0.2.0
4
+ Summary: Official async SDK for the Radion platform
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Keywords: async,polymarket,radion,realtime,sdk,websocket
8
+ Requires-Python: >=3.10
9
+ Requires-Dist: msgspec>=0.18.0
10
+ Requires-Dist: websockets>=13.0
11
+ Provides-Extra: dev
12
+ Requires-Dist: ruff>=0.8.0; extra == 'dev'
13
+ Requires-Dist: ty>=0.0.1a1; extra == 'dev'
14
+ Description-Content-Type: text/markdown
15
+
16
+ # radion-sdk
17
+
18
+ [![PyPI version](https://img.shields.io/pypi/v/radion-sdk.svg)](https://pypi.org/project/radion-sdk/)
19
+ [![Python versions](https://img.shields.io/pypi/pyversions/radion-sdk.svg)](https://pypi.org/project/radion-sdk/)
20
+ [![license](https://img.shields.io/pypi/l/radion-sdk.svg)](./LICENSE)
21
+
22
+ Official, async-first, fully-typed SDK for the [Radion](https://radion.app) platform.
23
+
24
+ One client, one API key, every Radion product surface. Install `radion-sdk`; import it as `radion`.
25
+
26
+ ```python
27
+ radion = Radion(api_key=os.getenv("RADION_API_KEY"))
28
+ await radion.realtime.connect()
29
+ await radion.realtime.subscribe(Subscription(id="trades", channel="trades"))
30
+
31
+ @radion.realtime.on("trades")
32
+ async def handle_trade(event):
33
+ print(event.id, event.data)
34
+ ```
35
+
36
+ ## Features
37
+
38
+ - **Unified client** — `Radion(api_key=...)` is the single entry point for every product surface
39
+ - **Auto-reconnect** — exponential backoff with jitter; stops on graceful shutdown
40
+ - **Subscription restore** — active channels are re-subscribed after every reconnect
41
+ - **Heartbeats** — ping/pong keep-alive that detects stale connections and reconnects
42
+ - **Typed end-to-end** — channel names, frame models, and errors
43
+ - **Async-first** — built on `asyncio`; handlers may be sync or async
44
+
45
+ ## Requirements
46
+
47
+ - Python >= 3.10
48
+
49
+ ## Install
50
+
51
+ ```bash
52
+ uv add radion-sdk
53
+ # or: pip install radion-sdk
54
+ ```
55
+
56
+ ## Quick start
57
+
58
+ ```python
59
+ import asyncio
60
+ import os
61
+
62
+ from radion import Radion, Subscription
63
+
64
+
65
+ async def main() -> None:
66
+ radion = Radion(api_key=os.getenv("RADION_API_KEY"))
67
+
68
+ await radion.realtime.connect()
69
+ await radion.realtime.subscribe(Subscription(id="trades", channel="trades"))
70
+
71
+ @radion.realtime.on("trades")
72
+ async def handle_trade(event):
73
+ print(event.id, event.channel, event.data)
74
+
75
+ await asyncio.sleep(60)
76
+ await radion.realtime.close()
77
+
78
+
79
+ asyncio.run(main())
80
+ ```
81
+
82
+ ## Usage
83
+
84
+ ### Configuration
85
+
86
+ ```python
87
+ Radion(api_key, *, base_url=..., ws_url=..., reconnect=True, heartbeat=True,
88
+ heartbeat_interval=15.0, heartbeat_timeout=10.0)
89
+ ```
90
+
91
+ | Argument | Type | Default | Description |
92
+ | -------------------- | ------- | ------------------------- | ------------------------------------------------- |
93
+ | `api_key` | `str` | — | **Required.** Sent as the `X-API-Key` header. |
94
+ | `base_url` | `str` | `https://api.radion.app` | Base URL for the Radion API. |
95
+ | `ws_url` | `str` | `wss://api.radion.app/ws` | Override the realtime endpoint. |
96
+ | `reconnect` | `bool` | `True` | Auto-reconnect on unexpected disconnect. |
97
+ | `heartbeat` | `bool` | `True` | Enable heartbeats / stale detection. |
98
+ | `heartbeat_interval` | `float` | `15.0` | Seconds between pings. |
99
+ | `heartbeat_timeout` | `float` | `10.0` | Extra grace before a quiet connection is stale. |
100
+
101
+ Extra keyword arguments are forwarded to the realtime client.
102
+
103
+ ### Realtime client
104
+
105
+ `radion.realtime` is a `RealtimeClient`. It can also be imported and
106
+ constructed standalone:
107
+
108
+ ```python
109
+ from radion import RealtimeClient
110
+
111
+ client = RealtimeClient(api_key=os.getenv("RADION_API_KEY"))
112
+ ```
113
+
114
+ | Method | Description |
115
+ | ------------------------------- | ------------------------------------------------------------ |
116
+ | `await connect()` | Open the connection. Resolves once established. |
117
+ | `await subscribe(subscription)` | Subscribe with `Subscription(id, channel, filters)`. Replayed on reconnect.|
118
+ | `await unsubscribe(id)` | Unsubscribe by subscription id. |
119
+ | `on(event)` | Decorator for a channel, `"event"` (all), or lifecycle handler. |
120
+ | `off(event, handler=None)` | Remove a handler (or all for that event). |
121
+ | `await close(code=1000, ...)` | Graceful shutdown. Stops reconnect attempts. |
122
+ | `connected` | Property — whether the socket is currently open. |
123
+
124
+ ### Subscriptions & filters
125
+
126
+ A subscription is `Subscription(id, channel, filters=None)`. The `id` is your
127
+ own string, echoed back on every event so you can tell subscriptions apart;
128
+ `channel` may carry a `mempool.` prefix. Some channels require a filter:
129
+
130
+ ```python
131
+ from radion import ChannelFilters, Subscription
132
+
133
+ await radion.realtime.subscribe(
134
+ Subscription(id="whales", channel="large_trades", filters=ChannelFilters(min_usd=10_000))
135
+ )
136
+
137
+ # "event" fires for every channel; the event carries id + channel + data.
138
+ @radion.realtime.on("event")
139
+ async def on_any(event):
140
+ print(event.id, event.channel, event.data)
141
+ ```
142
+
143
+ `ChannelFilters`: `wallets`, `market_ids`, `token_ids`, `min_usd`.
144
+
145
+ ### Channels
146
+
147
+ ```
148
+ global · trades · activity · lifecycle · oracle · collateral
149
+ combos · prices · wallets · markets · large_trades
150
+ ```
151
+
152
+ Available as the `CHANNELS` tuple and the `Channel` type.
153
+
154
+ ```python
155
+ from radion import CHANNELS, Subscription
156
+
157
+ for channel in CHANNELS:
158
+ await radion.realtime.subscribe(Subscription(id=channel, channel=channel))
159
+ ```
160
+
161
+ ### Lifecycle events
162
+
163
+ ```python
164
+ @radion.realtime.on("open")
165
+ async def opened(_):
166
+ print("connected")
167
+
168
+ @radion.realtime.on("close")
169
+ async def closed(info):
170
+ print(info["code"], info["reason"])
171
+
172
+ @radion.realtime.on("reconnect")
173
+ async def reconnecting(info):
174
+ print(info["attempt"], info["delay"])
175
+
176
+ @radion.realtime.on("error")
177
+ async def errored(err):
178
+ print(err)
179
+ ```
180
+
181
+ ### Reconnect & subscription restore
182
+
183
+ On an unexpected disconnect the client reconnects with exponential backoff and
184
+ re-sends every active subscription once the socket reopens. After `close()` no
185
+ further attempts run.
186
+
187
+ ### Heartbeats
188
+
189
+ A ping is sent every `heartbeat_interval` seconds. Any inbound frame counts as
190
+ liveness; if the connection goes quiet past the timeout window it is terminated
191
+ and reconnected.
192
+
193
+ ### Error handling
194
+
195
+ ```python
196
+ from radion import RadionConnectionError, RadionServerError
197
+
198
+ @radion.realtime.on("error")
199
+ async def errored(err):
200
+ if isinstance(err, RadionServerError):
201
+ print("server error", err.code, err.channel)
202
+ elif isinstance(err, RadionConnectionError):
203
+ print("connection error", err)
204
+ ```
205
+
206
+ A throwing consumer handler is reported via the `error` event and never retried.
207
+
208
+ ## License
209
+
210
+ MIT
@@ -0,0 +1,195 @@
1
+ # radion-sdk
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/radion-sdk.svg)](https://pypi.org/project/radion-sdk/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/radion-sdk.svg)](https://pypi.org/project/radion-sdk/)
5
+ [![license](https://img.shields.io/pypi/l/radion-sdk.svg)](./LICENSE)
6
+
7
+ Official, async-first, fully-typed SDK for the [Radion](https://radion.app) platform.
8
+
9
+ One client, one API key, every Radion product surface. Install `radion-sdk`; import it as `radion`.
10
+
11
+ ```python
12
+ radion = Radion(api_key=os.getenv("RADION_API_KEY"))
13
+ await radion.realtime.connect()
14
+ await radion.realtime.subscribe(Subscription(id="trades", channel="trades"))
15
+
16
+ @radion.realtime.on("trades")
17
+ async def handle_trade(event):
18
+ print(event.id, event.data)
19
+ ```
20
+
21
+ ## Features
22
+
23
+ - **Unified client** — `Radion(api_key=...)` is the single entry point for every product surface
24
+ - **Auto-reconnect** — exponential backoff with jitter; stops on graceful shutdown
25
+ - **Subscription restore** — active channels are re-subscribed after every reconnect
26
+ - **Heartbeats** — ping/pong keep-alive that detects stale connections and reconnects
27
+ - **Typed end-to-end** — channel names, frame models, and errors
28
+ - **Async-first** — built on `asyncio`; handlers may be sync or async
29
+
30
+ ## Requirements
31
+
32
+ - Python >= 3.10
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ uv add radion-sdk
38
+ # or: pip install radion-sdk
39
+ ```
40
+
41
+ ## Quick start
42
+
43
+ ```python
44
+ import asyncio
45
+ import os
46
+
47
+ from radion import Radion, Subscription
48
+
49
+
50
+ async def main() -> None:
51
+ radion = Radion(api_key=os.getenv("RADION_API_KEY"))
52
+
53
+ await radion.realtime.connect()
54
+ await radion.realtime.subscribe(Subscription(id="trades", channel="trades"))
55
+
56
+ @radion.realtime.on("trades")
57
+ async def handle_trade(event):
58
+ print(event.id, event.channel, event.data)
59
+
60
+ await asyncio.sleep(60)
61
+ await radion.realtime.close()
62
+
63
+
64
+ asyncio.run(main())
65
+ ```
66
+
67
+ ## Usage
68
+
69
+ ### Configuration
70
+
71
+ ```python
72
+ Radion(api_key, *, base_url=..., ws_url=..., reconnect=True, heartbeat=True,
73
+ heartbeat_interval=15.0, heartbeat_timeout=10.0)
74
+ ```
75
+
76
+ | Argument | Type | Default | Description |
77
+ | -------------------- | ------- | ------------------------- | ------------------------------------------------- |
78
+ | `api_key` | `str` | — | **Required.** Sent as the `X-API-Key` header. |
79
+ | `base_url` | `str` | `https://api.radion.app` | Base URL for the Radion API. |
80
+ | `ws_url` | `str` | `wss://api.radion.app/ws` | Override the realtime endpoint. |
81
+ | `reconnect` | `bool` | `True` | Auto-reconnect on unexpected disconnect. |
82
+ | `heartbeat` | `bool` | `True` | Enable heartbeats / stale detection. |
83
+ | `heartbeat_interval` | `float` | `15.0` | Seconds between pings. |
84
+ | `heartbeat_timeout` | `float` | `10.0` | Extra grace before a quiet connection is stale. |
85
+
86
+ Extra keyword arguments are forwarded to the realtime client.
87
+
88
+ ### Realtime client
89
+
90
+ `radion.realtime` is a `RealtimeClient`. It can also be imported and
91
+ constructed standalone:
92
+
93
+ ```python
94
+ from radion import RealtimeClient
95
+
96
+ client = RealtimeClient(api_key=os.getenv("RADION_API_KEY"))
97
+ ```
98
+
99
+ | Method | Description |
100
+ | ------------------------------- | ------------------------------------------------------------ |
101
+ | `await connect()` | Open the connection. Resolves once established. |
102
+ | `await subscribe(subscription)` | Subscribe with `Subscription(id, channel, filters)`. Replayed on reconnect.|
103
+ | `await unsubscribe(id)` | Unsubscribe by subscription id. |
104
+ | `on(event)` | Decorator for a channel, `"event"` (all), or lifecycle handler. |
105
+ | `off(event, handler=None)` | Remove a handler (or all for that event). |
106
+ | `await close(code=1000, ...)` | Graceful shutdown. Stops reconnect attempts. |
107
+ | `connected` | Property — whether the socket is currently open. |
108
+
109
+ ### Subscriptions & filters
110
+
111
+ A subscription is `Subscription(id, channel, filters=None)`. The `id` is your
112
+ own string, echoed back on every event so you can tell subscriptions apart;
113
+ `channel` may carry a `mempool.` prefix. Some channels require a filter:
114
+
115
+ ```python
116
+ from radion import ChannelFilters, Subscription
117
+
118
+ await radion.realtime.subscribe(
119
+ Subscription(id="whales", channel="large_trades", filters=ChannelFilters(min_usd=10_000))
120
+ )
121
+
122
+ # "event" fires for every channel; the event carries id + channel + data.
123
+ @radion.realtime.on("event")
124
+ async def on_any(event):
125
+ print(event.id, event.channel, event.data)
126
+ ```
127
+
128
+ `ChannelFilters`: `wallets`, `market_ids`, `token_ids`, `min_usd`.
129
+
130
+ ### Channels
131
+
132
+ ```
133
+ global · trades · activity · lifecycle · oracle · collateral
134
+ combos · prices · wallets · markets · large_trades
135
+ ```
136
+
137
+ Available as the `CHANNELS` tuple and the `Channel` type.
138
+
139
+ ```python
140
+ from radion import CHANNELS, Subscription
141
+
142
+ for channel in CHANNELS:
143
+ await radion.realtime.subscribe(Subscription(id=channel, channel=channel))
144
+ ```
145
+
146
+ ### Lifecycle events
147
+
148
+ ```python
149
+ @radion.realtime.on("open")
150
+ async def opened(_):
151
+ print("connected")
152
+
153
+ @radion.realtime.on("close")
154
+ async def closed(info):
155
+ print(info["code"], info["reason"])
156
+
157
+ @radion.realtime.on("reconnect")
158
+ async def reconnecting(info):
159
+ print(info["attempt"], info["delay"])
160
+
161
+ @radion.realtime.on("error")
162
+ async def errored(err):
163
+ print(err)
164
+ ```
165
+
166
+ ### Reconnect & subscription restore
167
+
168
+ On an unexpected disconnect the client reconnects with exponential backoff and
169
+ re-sends every active subscription once the socket reopens. After `close()` no
170
+ further attempts run.
171
+
172
+ ### Heartbeats
173
+
174
+ A ping is sent every `heartbeat_interval` seconds. Any inbound frame counts as
175
+ liveness; if the connection goes quiet past the timeout window it is terminated
176
+ and reconnected.
177
+
178
+ ### Error handling
179
+
180
+ ```python
181
+ from radion import RadionConnectionError, RadionServerError
182
+
183
+ @radion.realtime.on("error")
184
+ async def errored(err):
185
+ if isinstance(err, RadionServerError):
186
+ print("server error", err.code, err.channel)
187
+ elif isinstance(err, RadionConnectionError):
188
+ print("connection error", err)
189
+ ```
190
+
191
+ A throwing consumer handler is reported via the `error` event and never retried.
192
+
193
+ ## License
194
+
195
+ MIT
@@ -0,0 +1,30 @@
1
+ [project]
2
+ name = "radion-sdk"
3
+ version = "0.2.0"
4
+ description = "Official async SDK for the Radion platform"
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ license = { text = "MIT" }
8
+ keywords = ["radion", "sdk", "realtime", "websocket", "async", "polymarket"]
9
+ dependencies = ["websockets>=13.0", "msgspec>=0.18.0"]
10
+
11
+ [project.optional-dependencies]
12
+ dev = ["ruff>=0.8.0", "ty>=0.0.1a1"]
13
+
14
+ [build-system]
15
+ requires = ["hatchling"]
16
+ build-backend = "hatchling.build"
17
+
18
+ [tool.hatch.build.targets.wheel]
19
+ packages = ["src/radion"]
20
+
21
+ [tool.ruff]
22
+ line-length = 88
23
+ target-version = "py310"
24
+ src = ["src"]
25
+
26
+ [tool.ruff.lint]
27
+ select = ["E", "F", "I", "UP", "B", "ASYNC", "SIM", "RUF"]
28
+
29
+ [tool.ty.environment]
30
+ root = ["./src"]
@@ -0,0 +1,85 @@
1
+ """Official async SDK for the Radion platform."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from ._config import DEFAULT_BASE_URL, DEFAULT_WS_URL, RadionConfig
6
+ from .client import Radion
7
+ from .errors import RadionConnectionError, RadionError, RadionServerError
8
+ from .realtime import (
9
+ CHANNELS,
10
+ FILTER_REQUIREMENTS,
11
+ ActivityPayload,
12
+ AnyChannelPayload,
13
+ AnyConfirmedPayload,
14
+ Channel,
15
+ ChannelEvent,
16
+ ChannelFilters,
17
+ CollateralPayload,
18
+ CombosPayload,
19
+ ErrorFrame,
20
+ EventDispatcher,
21
+ EventFrame,
22
+ FilterKey,
23
+ InboundFrame,
24
+ LifecyclePayload,
25
+ MempoolChannel,
26
+ OraclePayload,
27
+ PongFrame,
28
+ PricesPayload,
29
+ RealtimeClient,
30
+ ReconnectManager,
31
+ SubscribableChannel,
32
+ SubscribedFrame,
33
+ Subscription,
34
+ SubscriptionManager,
35
+ TradesPayload,
36
+ UnsubscribedFrame,
37
+ is_channel,
38
+ is_mempool_channel,
39
+ is_subscribable_channel,
40
+ validate_subscription_filters,
41
+ )
42
+
43
+ __all__ = [
44
+ "CHANNELS",
45
+ "DEFAULT_BASE_URL",
46
+ "DEFAULT_WS_URL",
47
+ "FILTER_REQUIREMENTS",
48
+ "ActivityPayload",
49
+ "AnyChannelPayload",
50
+ "AnyConfirmedPayload",
51
+ "Channel",
52
+ "ChannelEvent",
53
+ "ChannelFilters",
54
+ "CollateralPayload",
55
+ "CombosPayload",
56
+ "ErrorFrame",
57
+ "EventDispatcher",
58
+ "EventFrame",
59
+ "FilterKey",
60
+ "InboundFrame",
61
+ "LifecyclePayload",
62
+ "MempoolChannel",
63
+ "OraclePayload",
64
+ "PongFrame",
65
+ "PricesPayload",
66
+ "Radion",
67
+ "RadionConfig",
68
+ "RadionConnectionError",
69
+ "RadionError",
70
+ "RadionServerError",
71
+ "RealtimeClient",
72
+ "ReconnectManager",
73
+ "SubscribableChannel",
74
+ "SubscribedFrame",
75
+ "Subscription",
76
+ "SubscriptionManager",
77
+ "TradesPayload",
78
+ "UnsubscribedFrame",
79
+ "is_channel",
80
+ "is_mempool_channel",
81
+ "is_subscribable_channel",
82
+ "validate_subscription_filters",
83
+ ]
84
+
85
+ __version__ = "0.2.0"
@@ -0,0 +1,25 @@
1
+ """Shared configuration for the Radion SDK."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+
7
+ DEFAULT_BASE_URL = "https://api.radion.app"
8
+ """Default base URL for the Radion REST API."""
9
+
10
+ DEFAULT_WS_URL = "wss://api.radion.app/ws"
11
+ """Default endpoint for the Radion realtime (WebSocket) API."""
12
+
13
+
14
+ @dataclass(frozen=True, slots=True)
15
+ class RadionConfig:
16
+ """Shared configuration for every Radion product surface.
17
+
18
+ ``base_url`` is reserved for the forthcoming REST resource namespaces
19
+ (``markets``, ``traders``, ``backtests``, …); the realtime client uses
20
+ ``ws_url``.
21
+ """
22
+
23
+ api_key: str
24
+ base_url: str = DEFAULT_BASE_URL
25
+ ws_url: str = DEFAULT_WS_URL
@@ -0,0 +1,50 @@
1
+ """The unified :class:`Radion` platform client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from ._config import DEFAULT_BASE_URL, DEFAULT_WS_URL
8
+ from .errors import RadionConnectionError
9
+ from .realtime import RealtimeClient
10
+
11
+
12
+ class Radion:
13
+ """Unified async entry point for the Radion platform.
14
+
15
+ Holds shared configuration and exposes each product surface as an
16
+ attribute. Today that is :attr:`realtime`; REST resource namespaces
17
+ (``markets``, ``traders``, ``backtests``, ``auth``, ``health``) attach here
18
+ as they ship, built from ``base_url`` over a shared HTTP transport — the
19
+ constructor shape stays stable so adding them is purely additive.
20
+
21
+ Extra keyword arguments are forwarded to the realtime client (for example
22
+ ``reconnect``, ``heartbeat``, ``heartbeat_interval``).
23
+
24
+ Example::
25
+
26
+ radion = Radion(api_key=os.getenv("RADION_API_KEY"))
27
+ await radion.realtime.connect()
28
+ await radion.realtime.subscribe("trades")
29
+
30
+ @radion.realtime.on("trades")
31
+ async def handle_trade(event):
32
+ print(event.data)
33
+ """
34
+
35
+ def __init__(
36
+ self,
37
+ *,
38
+ api_key: str,
39
+ base_url: str = DEFAULT_BASE_URL,
40
+ ws_url: str = DEFAULT_WS_URL,
41
+ **realtime_options: Any,
42
+ ) -> None:
43
+ if not api_key:
44
+ raise RadionConnectionError("api_key is required")
45
+ self._base_url = base_url
46
+ self.realtime = RealtimeClient(
47
+ api_key=api_key,
48
+ url=ws_url,
49
+ **realtime_options,
50
+ )
@@ -0,0 +1,28 @@
1
+ """Error types raised by the SDK."""
2
+
3
+ from __future__ import annotations
4
+
5
+
6
+ class RadionError(Exception):
7
+ """Base class for every error surfaced by the SDK."""
8
+
9
+
10
+ class RadionConnectionError(RadionError):
11
+ """Raised when the SDK is used against an invalid connection state."""
12
+
13
+
14
+ class RadionServerError(RadionError):
15
+ """Raised when the server reports an ``error`` frame."""
16
+
17
+ def __init__(
18
+ self,
19
+ message: str,
20
+ *,
21
+ code: str | None = None,
22
+ channel: str | None = None,
23
+ id: str | None = None,
24
+ ) -> None:
25
+ super().__init__(message)
26
+ self.code = code
27
+ self.channel = channel
28
+ self.id = id
File without changes