helius-python 0.1.1__tar.gz → 0.3.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.
Files changed (40) hide show
  1. {helius_python-0.1.1 → helius_python-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +1 -1
  2. {helius_python-0.1.1 → helius_python-0.3.0}/AGENTS.md +10 -92
  3. {helius_python-0.1.1 → helius_python-0.3.0}/CONTRIBUTING.md +2 -1
  4. {helius_python-0.1.1 → helius_python-0.3.0}/PKG-INFO +93 -64
  5. {helius_python-0.1.1 → helius_python-0.3.0}/README.md +91 -63
  6. helius_python-0.3.0/TODO.md +3 -0
  7. {helius_python-0.1.1 → helius_python-0.3.0}/examples/block_explorer.py +9 -6
  8. {helius_python-0.1.1 → helius_python-0.3.0}/examples/devnet_airdrop.py +2 -2
  9. {helius_python-0.1.1 → helius_python-0.3.0}/examples/network_status.py +2 -2
  10. {helius_python-0.1.1 → helius_python-0.3.0}/examples/priority_fees.py +2 -2
  11. {helius_python-0.1.1 → helius_python-0.3.0}/examples/stake_overview.py +22 -14
  12. {helius_python-0.1.1 → helius_python-0.3.0}/examples/token_inspector.py +2 -2
  13. {helius_python-0.1.1 → helius_python-0.3.0}/examples/transaction_inspector.py +5 -4
  14. {helius_python-0.1.1 → helius_python-0.3.0}/examples/wallet_tracker.py +9 -6
  15. {helius_python-0.1.1 → helius_python-0.3.0}/pyproject.toml +5 -1
  16. {helius_python-0.1.1 → helius_python-0.3.0}/requirements.txt +1 -0
  17. helius_python-0.3.0/src/helius/admin/admin.py +95 -0
  18. helius_python-0.3.0/src/helius/laserstream/websockets.py +398 -0
  19. helius_python-0.3.0/src/helius/rpc/__init__.py +3 -0
  20. helius_python-0.3.0/src/helius/rpc/json_rpc_request.py +52 -0
  21. helius_python-0.3.0/src/helius/solana_rpc/__init__.py +5 -0
  22. {helius_python-0.1.1/src/helius → helius_python-0.3.0/src/helius/solana_rpc}/client.py +100 -113
  23. {helius_python-0.1.1/src/helius → helius_python-0.3.0/src/helius/solana_rpc}/models.py +7 -0
  24. helius_python-0.3.0/tests/unit/admin/test_admin.py +73 -0
  25. helius_python-0.3.0/tests/unit/lasterstream/test_websockets.py +871 -0
  26. helius_python-0.3.0/tests/unit/rpc/test_json_rpc_request.py +50 -0
  27. helius_python-0.1.1/tests/unit/test_helius_client.py → helius_python-0.3.0/tests/unit/solana_rpc/test_client.py +194 -94
  28. {helius_python-0.1.1/tests/unit → helius_python-0.3.0/tests/unit/solana_rpc}/test_models.py +30 -2
  29. helius_python-0.1.1/tests/unit/test_rpc_request.py +0 -46
  30. {helius_python-0.1.1 → helius_python-0.3.0}/.editorconfig +0 -0
  31. {helius_python-0.1.1 → helius_python-0.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  32. {helius_python-0.1.1 → helius_python-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  33. {helius_python-0.1.1 → helius_python-0.3.0}/.github/workflows/python-package.yml +0 -0
  34. {helius_python-0.1.1 → helius_python-0.3.0}/.github/workflows/python-publish.yml +0 -0
  35. {helius_python-0.1.1 → helius_python-0.3.0}/.gitignore +0 -0
  36. {helius_python-0.1.1 → helius_python-0.3.0}/CLAUDE.md +0 -0
  37. {helius_python-0.1.1 → helius_python-0.3.0}/LICENSE +0 -0
  38. {helius_python-0.1.1 → helius_python-0.3.0}/src/helius/__init__.py +0 -0
  39. {helius_python-0.1.1 → helius_python-0.3.0}/tests/fixtures/account.json +0 -0
  40. {helius_python-0.1.1 → helius_python-0.3.0}/tests/fixtures/supply.json +0 -0
@@ -24,7 +24,7 @@ body:
24
24
  your API key.
25
25
  render: python
26
26
  placeholder: |
27
- from helius.client import HeliusClient
27
+ from helius.solana_rpc import HeliusClient
28
28
 
29
29
  with HeliusClient(api_key="...") as c:
30
30
  c.get_balance(public_key="...")
@@ -1,84 +1,3 @@
1
- When implementing a function for a RPC method in the HeliusClient class, read the docs for the specific RPC method. For example, for the get_supply function (getSupply RPC method) you should read https://www.helius.dev/docs/rpc/guides/getsupply and https://www.helius.dev/docs/api-reference/rpc/http/getsupply.
2
-
3
- # API Reference
4
-
5
- The API reference is generated from **Google-style docstrings** on every public symbol in `src/helius/`. Whenever you add or modify a public method, model, or class, you MUST write or update its docstring following the rules below. The README's "Supported methods" table is a quick index only — the docstring is the source of truth.
6
-
7
- ## Where docstrings live
8
-
9
- - **Client methods** (`HeliusClient.get_*`, `is_*`, `request_*`, etc.) — every public method gets a docstring. Private methods (`_send`, dunders) do not need one.
10
- - **Models** (`src/helius/models.py`) — every public model class gets a docstring describing what it represents. Individual fields don't need per-field docstrings if their names and types are self-explanatory; only document fields where the meaning, units, or nullability isn't obvious from the type alone.
11
- - **Builders / helpers** (`RpcRequest`) — class docstring describing purpose, plus one-line docstrings on each public method.
12
-
13
- ## Client method docstring format
14
-
15
- Use Google-style sections. Order matters; omit any section that doesn't apply.
16
-
17
- ```python
18
- def method_name(self, ...) -> ReturnType:
19
- """One-line summary in the imperative mood, ending with a period.
20
-
21
- Optional longer description: a paragraph or two on what the method does,
22
- when to use it, and any non-obvious behavior. Keep this short — link to
23
- the upstream Helius docs rather than restating them.
24
-
25
- Args:
26
- param_one: Description of the first parameter, including units
27
- (lamports vs. SOL, slot vs. block height) when relevant. Mention
28
- the upstream JSON field name only if it differs in a non-obvious
29
- way from the snake_case Python name.
30
- param_two: Description. Note constraints like "must be base-58
31
- encoded" or "max 500_000 slots from `start_slot`".
32
- commitment: Optional commitment level. Defaults to the node's default
33
- when omitted.
34
-
35
- Returns:
36
- Describe the return shape. For tuples, describe each element in
37
- order. For models, name the model and what it represents. For
38
- primitives, name the unit (e.g. "Balance in lamports.").
39
-
40
- Raises:
41
- ValueError: When the arguments violate the documented constraints
42
- (e.g. mutually exclusive params, mismatched pairs).
43
-
44
- Note:
45
- Only available on Devnet and Testnet, not Mainnet Beta.
46
-
47
- See Also:
48
- - Helius guide: https://www.helius.dev/docs/rpc/guides/<method>
49
- - Helius API reference: https://www.helius.dev/docs/api-reference/rpc/http/<method>
50
- """
51
- ```
52
-
53
- Rules:
54
-
55
- - **Summary line** is one sentence, imperative mood, ≤ 88 chars, ends with a period. Example: `"Return the SOL balance of an account in lamports."`
56
- - **`Args:`** documents every parameter, even `commitment` and `min_context_slot`. One entry per param. Don't re-state the type — basedpyright already shows it.
57
- - **`Returns:`** is mandatory unless the method returns `None`.
58
- - **`Raises:`** is required if the method calls `raise` directly. Don't document exceptions that bubble up from `httpx` — those are covered by the library-wide error-handling docs.
59
- - **`Note:`** for network restrictions, version requirements, pagination limits, deprecation warnings, etc. One section per concern.
60
- - **`See Also:`** ALWAYS includes the Helius guide and API reference URLs for the underlying RPC method. This is the contract for an RPC wrapper — the docstring tells you what we do, the upstream docs tell you what the network does.
61
- - Keep prose tight. The docstring should be readable in `help(client.method)` without scrolling forever.
62
-
63
- ## Model docstring format
64
-
65
- ```python
66
- class Supply(BaseModel):
67
- """Total, circulating, and non-circulating SOL supply, in lamports.
68
-
69
- Returned as the `value` field of `getSupply`. All amounts are in
70
- lamports (1 SOL = 1_000_000_000 lamports).
71
-
72
- See Also:
73
- - Helius API reference: https://www.helius.dev/docs/api-reference/rpc/http/getsupply
74
- """
75
- ...
76
- ```
77
-
78
- Rules:
79
-
80
- - One-line summary + optional paragraph + `See Also:` linking the upstream docs that define the shape.
81
- - If a field has surprising semantics (e.g. `ui_amount` can be `None` when the mint has too many decimals, `non_circulating_accounts` is only populated when not excluded), document it inline with `Field(..., description="...")` or in the class docstring.
82
1
 
83
2
  ## Conventions
84
3
 
@@ -98,11 +17,10 @@ Rules:
98
17
 
99
18
  ## Checklist for adding a new client method
100
19
 
101
- 1. Read both Helius doc URLs for the RPC method (see the top of this file).
20
+ 1. Read the docs. The user should provide the relevant URLs. If they don't, ask them to do so.
102
21
  2. Implement the method, following the **Implementation conventions** above — in particular, return `(context, value)` if the upstream response is wrapped.
103
- 3. Add a docstring with `Args`, `Returns`, `Raises` (if any), `Note` (if any), and `See Also` with both Helius URLs.
104
- 4. Add the method to the "Supported methods" table in `README.md`.
105
- 5. Add tests per the Testing section.
22
+ 3. Add the method to the "Supported methods" table in `README.md`.
23
+ 4. Add tests per the Testing section.
106
24
 
107
25
  # Testing
108
26
 
@@ -123,7 +41,7 @@ tests/
123
41
  unit/
124
42
  test_rpc_request.py # RpcRequest builder
125
43
  test_models.py # pydantic model validation against fixtures
126
- test_client.py # one test (or small group) per client method
44
+ test_solana_rpc.py # one test (or small group) per client method
127
45
  ```
128
46
 
129
47
  ## Three Layers
@@ -154,7 +72,7 @@ One fixture per model is enough. The goal is to catch schema mismatches (missing
154
72
 
155
73
  ### 3. Client methods — `respx`-mocked tests
156
74
 
157
- For each method on `HeliusClient`, write at least one test that asserts **both** sides of the wire:
75
+ For each method on `SolanaRpcClient`, write at least one test that asserts **both** sides of the wire:
158
76
 
159
77
  - **Outgoing request:** the JSON body sent to Helius matches the JSON-RPC payload you expect — correct `method`, correct positional `params`, correct config object with snake → camel mapping, and optional arguments omitted when `None`.
160
78
  - **Return value:** the method correctly parses a canned response into the documented return shape (model, tuple, primitive, etc.).
@@ -169,7 +87,7 @@ Skeleton:
169
87
  import json
170
88
  import httpx
171
89
  import respx
172
- from helius.client import HeliusClient
90
+ from helius.solana_rpc import SolanaRpcClient
173
91
 
174
92
  @respx.mock
175
93
  def test_get_balance():
@@ -183,7 +101,7 @@ def test_get_balance():
183
101
  },
184
102
  )
185
103
  )
186
- with HeliusClient(api_key="test") as c:
104
+ with SolanaRpcClient(api_key="test") as c:
187
105
  assert c.get_balance("So11...112", commitment="finalized") == 42
188
106
 
189
107
  sent = route.calls.last.request
@@ -197,9 +115,9 @@ For methods with branching logic (e.g. `get_block_production`, `get_token_accoun
197
115
 
198
116
  ## Conventions
199
117
 
200
- - Construct `HeliusClient` in tests with an explicit `api_key="test"` (or similar). Never rely on a real `.env` file.
201
- - Use the context-manager form (`with HeliusClient(...) as c:`) in tests so the `httpx.Client` is closed cleanly.
202
- - Group tests in `tests/unit/test_client.py` by method, but a single file is fine until it grows unwieldy.
118
+ - Construct `SolanaRpcClient` in tests with an explicit `api_key="test"` (or similar). Never rely on a real `.env` file.
119
+ - Use the context-manager form (`with SolanaRpcClient(...) as c:`) in tests so the `httpx.Client` is closed cleanly.
120
+ - Group tests in `tests/unit/test_solana_rpc.py` by method, but a single file is fine until it grows unwieldy.
203
121
  - Test names should describe the behavior, not the implementation: `test_get_balance_includes_commitment_in_config`, not `test_get_balance_calls_set`.
204
122
  - When adding a new client method, the PR must include: (a) a `respx` test asserting the request payload, and (b) a fixture-based model test if the method introduces or uses a model. This is enforced in `CONTRIBUTING.md`.
205
123
 
@@ -44,6 +44,7 @@ easiest to most involved:
44
44
  - **Improve docs and examples.** Clearer docstrings, better README snippets,
45
45
  more realistic examples.
46
46
  - **Create an example or refine an existing one.** Examples make it easier for developers to get started.
47
+ - **Improve test coverage** Write a missing test or improve an existing one.
47
48
 
48
49
  If you're not sure where to start, browse the
49
50
  [open issues](https://github.com/markosnarinian/helius-python/issues).
@@ -66,7 +67,7 @@ prior discussion; just send them.
66
67
  ## Codebase Conventions
67
68
 
68
69
  Please match the existing style of the codebase. Skim
69
- [`src/helius/client.py`](src/helius/client.py) and
70
+ [`src/helius/solana_rpc.py`](src/helius/solana_rpc.py) and
70
71
  [`src/helius/models.py`](src/helius/models.py) before writing new code. In
71
72
  particular:
72
73
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: helius-python
3
- Version: 0.1.1
3
+ Version: 0.3.0
4
4
  Summary: Typed Python client for the Helius API
5
5
  Project-URL: Homepage, https://github.com/markosnarinian/helius-python
6
6
  Project-URL: Issues, https://github.com/markosnarinian/helius-python/issues
@@ -13,6 +13,7 @@ Requires-Python: >=3.10
13
13
  Requires-Dist: httpx
14
14
  Requires-Dist: pydantic
15
15
  Requires-Dist: python-dotenv
16
+ Requires-Dist: websockets
16
17
  Provides-Extra: dev
17
18
  Requires-Dist: pytest; extra == 'dev'
18
19
  Requires-Dist: respx; extra == 'dev'
@@ -118,55 +119,6 @@ Description-Content-Type: text/markdown
118
119
  </p>
119
120
 
120
121
  **A complete, typed Python client for [Helius](https://helius.dev) — the Solana developer platform.**
121
- <br />
122
-
123
- ## TL;DR
124
-
125
- ```bash
126
- pip install helius-python
127
- ```
128
-
129
- ```python
130
- # export HELIUS_API_KEY=your_key (or put it in .env)
131
-
132
- from helius.client import HeliusClient
133
-
134
- with HeliusClient() as helius:
135
- _ctx, lamports = helius.get_balance("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU")
136
- print(f"{lamports / 1_000_000_000:.4f} SOL")
137
-
138
- for sig in helius.get_signatures_for_address(
139
- "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", limit=5
140
- ):
141
- print(sig.slot, "ERR" if sig.err else "OK ", sig.signature)
142
- ```
143
-
144
- `HELIUS_API_KEY` is read from the environment (or `.env`), the
145
- client is a context manager, and every return value is fully typed.
146
-
147
- ## Why this over `solana-py` / `solders`?
148
-
149
- `solders` is for building and signing transactions. `solana-py` is a generic Solana RPC client. Use them for that.
150
-
151
- This library is for talking to **Helius** specifically — typed `pydantic` responses, snake_case, and (eventually) the Helius-only endpoints (DAS, Enhanced Transactions, Webhooks, priority fees) the others don't cover. Plays nicely alongside `solders`: sign with `solders`, read with `helius-python`.
152
-
153
- ## Example: wallet tracker
154
-
155
- See [`examples/wallet_tracker.py`](examples/wallet_tracker.py) for a
156
- runnable script that takes a wallet address and prints:
157
-
158
- - SOL balance
159
- - All non-empty SPL token accounts (mint, balance, account)
160
- - The last N transactions (timestamp, slot, success/error, signature)
161
-
162
- ```bash
163
- export HELIUS_API_KEY=your_helius_api_key
164
- python examples/wallet_tracker.py 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU --limit 20
165
- ```
166
-
167
- It uses `get_balance`, `get_token_accounts_by_owner` (with
168
- `encoding="jsonParsed"`), and `get_signatures_for_address` — pure
169
- stdlib plus this library, no `solana-py` or `solders` needed.
170
122
 
171
123
  ## Coverage
172
124
 
@@ -186,11 +138,16 @@ wraps it.
186
138
  Webhooks API, Mint API, token metadata, address lookups, and beyond.
187
139
  **(in progress)**
188
140
  - 🚧 **Platform features** — streaming, websockets, and any new
189
- capability Helius adds to its API. **(in progress)**
141
+ capability Helius adds to its API. The full WebSocket subscription
142
+ surface (`accountSubscribe`, `transactionSubscribe`, `logsSubscribe`,
143
+ `programSubscribe`, and the rest) is **supported today**; other
144
+ platform features are **in progress**.
190
145
 
191
- > **Current status:** only the standard Solana JSON-RPC surface is
192
- > implemented today. Support for Helius RPC extensions, REST endpoints,
193
- > and platform features is actively being worked on.
146
+ > **Current status:** the standard Solana JSON-RPC surface, the
147
+ > WebSocket subscription surface, and the Admin (account management)
148
+ > usage endpoint are implemented today. Support for Helius RPC
149
+ > extensions and the remaining REST endpoints is actively being worked
150
+ > on.
194
151
 
195
152
  ## Goals
196
153
 
@@ -201,14 +158,19 @@ wraps it.
201
158
  4. **Zero magic** — thin, predictable wrappers that map directly to the
202
159
  documented Helius API.
203
160
 
161
+ ## Installation via PyPI
162
+ ```bash
163
+ pip install helius-python
164
+ ```
165
+
204
166
  ## Authentication
205
167
 
206
168
  Pass your Helius API key explicitly:
207
169
 
208
170
  ```python
209
- from helius.client import HeliusClient
171
+ from helius.solana_rpc import SolanaRpcClient
210
172
 
211
- client = HeliusClient(api_key="YOUR_HELIUS_API_KEY")
173
+ client = SolanaRpcClient(api_key="YOUR_HELIUS_API_KEY")
212
174
  ```
213
175
 
214
176
  or set `HELIUS_API_KEY` as an environment variable:
@@ -225,9 +187,9 @@ HELIUS_API_KEY=your_helius_api_key
225
187
  ```
226
188
 
227
189
  ```python
228
- from helius.client import HeliusClient
190
+ from helius.solana_rpc import SolanaRpcClient
229
191
 
230
- client = HeliusClient() # reads HELIUS_API_KEY from the environment or .env
192
+ client = SolanaRpcClient() # reads HELIUS_API_KEY from the environment or .env
231
193
  ```
232
194
 
233
195
  ## Usage
@@ -235,9 +197,9 @@ client = HeliusClient() # reads HELIUS_API_KEY from the environment or .env
235
197
  ### As a context manager (recommended)
236
198
 
237
199
  ```python
238
- from helius.client import HeliusClient
200
+ from helius.solana_rpc import SolanaRpcClient
239
201
 
240
- with HeliusClient(api_key="YOUR_HELIUS_API_KEY") as client:
202
+ with SolanaRpcClient(api_key="YOUR_HELIUS_API_KEY") as client:
241
203
  _ctx, balance = client.get_balance("So11111111111111111111111111111111111111112")
242
204
  _ctx, supply = client.get_supply()
243
205
  nodes = client.get_cluster_nodes()
@@ -245,7 +207,7 @@ with HeliusClient(api_key="YOUR_HELIUS_API_KEY") as client:
245
207
  tx = client.get_transaction("5j7s...signature...")
246
208
  ```
247
209
 
248
- `HeliusClient` implements the context-manager protocol via `__enter__` /
210
+ `SolanaRpcClient` implements the context-manager protocol via `__enter__` /
249
211
  `__exit__`, so the underlying `httpx.Client` is closed cleanly when the
250
212
  `with` block exits.
251
213
 
@@ -255,9 +217,9 @@ If a `with` block doesn't fit your code structure (e.g. the client lives
255
217
  on a long-lived object), call `close()` yourself when you're done:
256
218
 
257
219
  ```python
258
- from helius.client import HeliusClient
220
+ from helius.solana_rpc import SolanaRpcClient
259
221
 
260
- client = HeliusClient(api_key="YOUR_HELIUS_API_KEY")
222
+ client = SolanaRpcClient(api_key="YOUR_HELIUS_API_KEY")
261
223
  try:
262
224
  _ctx, balance = client.get_balance("So11111111111111111111111111111111111111112")
263
225
  _ctx, supply = client.get_supply()
@@ -303,7 +265,7 @@ The method names map 1:1 to the Solana JSON-RPC spec, just converted to
303
265
  ## Status
304
266
 
305
267
  Actively expanding toward full coverage of the Helius API. See
306
- [`src/helius/client.py`](src/helius/client.py) for the current list of
268
+ [`src/helius/solana_rpc.py`](src/helius/solana_rpc.py) for the current list of
307
269
  implemented methods; missing endpoints are tracked as issues and added
308
270
  continuously.
309
271
 
@@ -359,6 +321,73 @@ continuously.
359
321
  | `isBlockhashValid` | `is_blockhash_valid(...)` | [guide](https://www.helius.dev/docs/rpc/guides/isblockhashvalid), [reference](https://www.helius.dev/docs/api-reference/rpc/http/isblockhashvalid) |
360
322
  | `minimumLedgerSlot` | `minimum_ledger_slot()` | [guide](https://www.helius.dev/docs/rpc/guides/minimumledgerslot), [reference](https://www.helius.dev/docs/api-reference/rpc/http/minimumledgerslot) |
361
323
  | `requestAirdrop` | `request_airdrop(...)` | [guide](https://www.helius.dev/docs/rpc/guides/requestairdrop), [reference](https://www.helius.dev/docs/api-reference/rpc/http/requestairdrop) |
324
+ | `sendTransaction` | `send_transaction(...)` | [guide](https://www.helius.dev/docs/rpc/guides/sendtransaction), [reference](https://www.helius.dev/docs/api-reference/rpc/http/sendtransaction) |
325
+
326
+ ## WebSocket subscriptions
327
+
328
+ `WebSocketClient` wraps the Solana/Helius WebSocket subscription surface.
329
+ It connects over `wss://` on construction, exposes one `*_subscribe` /
330
+ `*_unsubscribe` pair per subscription type, and parses incoming
331
+ notifications into typed pydantic models.
332
+
333
+ ```python
334
+ from helius.laserstream.websockets import WebSocketClient
335
+
336
+ with WebSocketClient(api_key="YOUR_HELIUS_API_KEY") as ws:
337
+ subscription = ws.account_subscribe(
338
+ pubkey="So11111111111111111111111111111111111111112",
339
+ commitment="confirmed",
340
+ )
341
+
342
+ for context, notification, sub in ws.listen():
343
+ print(notification) # typed AccountNotification
344
+
345
+ ws.account_unsubscribe(subscription)
346
+ ```
347
+
348
+ Like `SolanaRpcClient`, it supports the context-manager protocol and a
349
+ manual `close()`. The constructor defaults to
350
+ `wss://mainnet.helius-rpc.com` and reads `HELIUS_API_KEY` from the
351
+ environment or `.env` when `api_key` is omitted; an optional `proxy` is
352
+ also accepted.
353
+
354
+ Each `*_subscribe` call returns the integer subscription id. Use
355
+ `receive()` to read a single notification or `listen()` to iterate over
356
+ them; both yield a `(context, notification, subscription)` tuple where
357
+ `notification` is the model below.
358
+
359
+ | Subscribe method | Unsubscribe method | Notification model | Helius docs |
360
+ | ------------------------------- | --------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
361
+ | `account_subscribe(...)` | `account_unsubscribe(...)` | `AccountNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/accountsubscribe) |
362
+ | `block_subscribe(...)` | `block_unsubscribe(...)` | `BlockNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/blocksubscribe) |
363
+ | `logs_subscribe(...)` | `logs_unsubscribe(...)` | `LogsNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/logssubscribe) |
364
+ | `program_subscribe(...)` | `program_unsubscribe(...)` | `ProgramNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/programsubscribe) |
365
+ | `root_subscribe()` | `root_unsubscribe(...)` | `RootNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/rootsubscribe) |
366
+ | `signature_subscribe(...)` | `signature_unsubscribe(...)` | `SignatureNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/signaturesubscribe) |
367
+ | `slot_subscribe()` | `slot_unsubscribe(...)` | `SlotNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/slotsubscribe) |
368
+ | `slots_updates_subscribe()` | `slots_updates_unsubscribe(...)` | `SlotsUpdatesNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/slotsupdatessubscribe) |
369
+ | `vote_subscribe()` | `vote_unsubscribe(...)` | `VoteNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/votesubscribe) |
370
+ | `transaction_subscribe(...)` | `transaction_unsubscribe(...)` | `TransactionNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/slotunsubscribe) |
371
+
372
+ ## Admin API
373
+
374
+ `AccountManagementClient` wraps the Helius admin API. Today it exposes
375
+ project credit usage via `get_project_usage(...)`, which returns a typed
376
+ `ProjectUsage` model.
377
+
378
+ ```python
379
+ from helius.admin.admin import AccountManagementClient
380
+
381
+ with AccountManagementClient(api_key="YOUR_HELIUS_API_KEY") as admin:
382
+ usage = admin.get_project_usage(project_id="YOUR_PROJECT_ID")
383
+ print(usage.credits_remaining, usage.usage.rpc)
384
+ ```
385
+
386
+ The `project_id` can be passed per call or set once on the constructor;
387
+ if neither is provided, `get_project_usage` raises `ValueError`. The
388
+ client defaults to `https://admin-api.helius.xyz` and, like the others,
389
+ supports the context-manager protocol, a manual `close()`, and reads
390
+ `HELIUS_API_KEY` from the environment or `.env`.
362
391
 
363
392
  ## License
364
393
 
@@ -98,55 +98,6 @@
98
98
  </p>
99
99
 
100
100
  **A complete, typed Python client for [Helius](https://helius.dev) — the Solana developer platform.**
101
- <br />
102
-
103
- ## TL;DR
104
-
105
- ```bash
106
- pip install helius-python
107
- ```
108
-
109
- ```python
110
- # export HELIUS_API_KEY=your_key (or put it in .env)
111
-
112
- from helius.client import HeliusClient
113
-
114
- with HeliusClient() as helius:
115
- _ctx, lamports = helius.get_balance("7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU")
116
- print(f"{lamports / 1_000_000_000:.4f} SOL")
117
-
118
- for sig in helius.get_signatures_for_address(
119
- "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", limit=5
120
- ):
121
- print(sig.slot, "ERR" if sig.err else "OK ", sig.signature)
122
- ```
123
-
124
- `HELIUS_API_KEY` is read from the environment (or `.env`), the
125
- client is a context manager, and every return value is fully typed.
126
-
127
- ## Why this over `solana-py` / `solders`?
128
-
129
- `solders` is for building and signing transactions. `solana-py` is a generic Solana RPC client. Use them for that.
130
-
131
- This library is for talking to **Helius** specifically — typed `pydantic` responses, snake_case, and (eventually) the Helius-only endpoints (DAS, Enhanced Transactions, Webhooks, priority fees) the others don't cover. Plays nicely alongside `solders`: sign with `solders`, read with `helius-python`.
132
-
133
- ## Example: wallet tracker
134
-
135
- See [`examples/wallet_tracker.py`](examples/wallet_tracker.py) for a
136
- runnable script that takes a wallet address and prints:
137
-
138
- - SOL balance
139
- - All non-empty SPL token accounts (mint, balance, account)
140
- - The last N transactions (timestamp, slot, success/error, signature)
141
-
142
- ```bash
143
- export HELIUS_API_KEY=your_helius_api_key
144
- python examples/wallet_tracker.py 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU --limit 20
145
- ```
146
-
147
- It uses `get_balance`, `get_token_accounts_by_owner` (with
148
- `encoding="jsonParsed"`), and `get_signatures_for_address` — pure
149
- stdlib plus this library, no `solana-py` or `solders` needed.
150
101
 
151
102
  ## Coverage
152
103
 
@@ -166,11 +117,16 @@ wraps it.
166
117
  Webhooks API, Mint API, token metadata, address lookups, and beyond.
167
118
  **(in progress)**
168
119
  - 🚧 **Platform features** — streaming, websockets, and any new
169
- capability Helius adds to its API. **(in progress)**
120
+ capability Helius adds to its API. The full WebSocket subscription
121
+ surface (`accountSubscribe`, `transactionSubscribe`, `logsSubscribe`,
122
+ `programSubscribe`, and the rest) is **supported today**; other
123
+ platform features are **in progress**.
170
124
 
171
- > **Current status:** only the standard Solana JSON-RPC surface is
172
- > implemented today. Support for Helius RPC extensions, REST endpoints,
173
- > and platform features is actively being worked on.
125
+ > **Current status:** the standard Solana JSON-RPC surface, the
126
+ > WebSocket subscription surface, and the Admin (account management)
127
+ > usage endpoint are implemented today. Support for Helius RPC
128
+ > extensions and the remaining REST endpoints is actively being worked
129
+ > on.
174
130
 
175
131
  ## Goals
176
132
 
@@ -181,14 +137,19 @@ wraps it.
181
137
  4. **Zero magic** — thin, predictable wrappers that map directly to the
182
138
  documented Helius API.
183
139
 
140
+ ## Installation via PyPI
141
+ ```bash
142
+ pip install helius-python
143
+ ```
144
+
184
145
  ## Authentication
185
146
 
186
147
  Pass your Helius API key explicitly:
187
148
 
188
149
  ```python
189
- from helius.client import HeliusClient
150
+ from helius.solana_rpc import SolanaRpcClient
190
151
 
191
- client = HeliusClient(api_key="YOUR_HELIUS_API_KEY")
152
+ client = SolanaRpcClient(api_key="YOUR_HELIUS_API_KEY")
192
153
  ```
193
154
 
194
155
  or set `HELIUS_API_KEY` as an environment variable:
@@ -205,9 +166,9 @@ HELIUS_API_KEY=your_helius_api_key
205
166
  ```
206
167
 
207
168
  ```python
208
- from helius.client import HeliusClient
169
+ from helius.solana_rpc import SolanaRpcClient
209
170
 
210
- client = HeliusClient() # reads HELIUS_API_KEY from the environment or .env
171
+ client = SolanaRpcClient() # reads HELIUS_API_KEY from the environment or .env
211
172
  ```
212
173
 
213
174
  ## Usage
@@ -215,9 +176,9 @@ client = HeliusClient() # reads HELIUS_API_KEY from the environment or .env
215
176
  ### As a context manager (recommended)
216
177
 
217
178
  ```python
218
- from helius.client import HeliusClient
179
+ from helius.solana_rpc import SolanaRpcClient
219
180
 
220
- with HeliusClient(api_key="YOUR_HELIUS_API_KEY") as client:
181
+ with SolanaRpcClient(api_key="YOUR_HELIUS_API_KEY") as client:
221
182
  _ctx, balance = client.get_balance("So11111111111111111111111111111111111111112")
222
183
  _ctx, supply = client.get_supply()
223
184
  nodes = client.get_cluster_nodes()
@@ -225,7 +186,7 @@ with HeliusClient(api_key="YOUR_HELIUS_API_KEY") as client:
225
186
  tx = client.get_transaction("5j7s...signature...")
226
187
  ```
227
188
 
228
- `HeliusClient` implements the context-manager protocol via `__enter__` /
189
+ `SolanaRpcClient` implements the context-manager protocol via `__enter__` /
229
190
  `__exit__`, so the underlying `httpx.Client` is closed cleanly when the
230
191
  `with` block exits.
231
192
 
@@ -235,9 +196,9 @@ If a `with` block doesn't fit your code structure (e.g. the client lives
235
196
  on a long-lived object), call `close()` yourself when you're done:
236
197
 
237
198
  ```python
238
- from helius.client import HeliusClient
199
+ from helius.solana_rpc import SolanaRpcClient
239
200
 
240
- client = HeliusClient(api_key="YOUR_HELIUS_API_KEY")
201
+ client = SolanaRpcClient(api_key="YOUR_HELIUS_API_KEY")
241
202
  try:
242
203
  _ctx, balance = client.get_balance("So11111111111111111111111111111111111111112")
243
204
  _ctx, supply = client.get_supply()
@@ -283,7 +244,7 @@ The method names map 1:1 to the Solana JSON-RPC spec, just converted to
283
244
  ## Status
284
245
 
285
246
  Actively expanding toward full coverage of the Helius API. See
286
- [`src/helius/client.py`](src/helius/client.py) for the current list of
247
+ [`src/helius/solana_rpc.py`](src/helius/solana_rpc.py) for the current list of
287
248
  implemented methods; missing endpoints are tracked as issues and added
288
249
  continuously.
289
250
 
@@ -339,6 +300,73 @@ continuously.
339
300
  | `isBlockhashValid` | `is_blockhash_valid(...)` | [guide](https://www.helius.dev/docs/rpc/guides/isblockhashvalid), [reference](https://www.helius.dev/docs/api-reference/rpc/http/isblockhashvalid) |
340
301
  | `minimumLedgerSlot` | `minimum_ledger_slot()` | [guide](https://www.helius.dev/docs/rpc/guides/minimumledgerslot), [reference](https://www.helius.dev/docs/api-reference/rpc/http/minimumledgerslot) |
341
302
  | `requestAirdrop` | `request_airdrop(...)` | [guide](https://www.helius.dev/docs/rpc/guides/requestairdrop), [reference](https://www.helius.dev/docs/api-reference/rpc/http/requestairdrop) |
303
+ | `sendTransaction` | `send_transaction(...)` | [guide](https://www.helius.dev/docs/rpc/guides/sendtransaction), [reference](https://www.helius.dev/docs/api-reference/rpc/http/sendtransaction) |
304
+
305
+ ## WebSocket subscriptions
306
+
307
+ `WebSocketClient` wraps the Solana/Helius WebSocket subscription surface.
308
+ It connects over `wss://` on construction, exposes one `*_subscribe` /
309
+ `*_unsubscribe` pair per subscription type, and parses incoming
310
+ notifications into typed pydantic models.
311
+
312
+ ```python
313
+ from helius.laserstream.websockets import WebSocketClient
314
+
315
+ with WebSocketClient(api_key="YOUR_HELIUS_API_KEY") as ws:
316
+ subscription = ws.account_subscribe(
317
+ pubkey="So11111111111111111111111111111111111111112",
318
+ commitment="confirmed",
319
+ )
320
+
321
+ for context, notification, sub in ws.listen():
322
+ print(notification) # typed AccountNotification
323
+
324
+ ws.account_unsubscribe(subscription)
325
+ ```
326
+
327
+ Like `SolanaRpcClient`, it supports the context-manager protocol and a
328
+ manual `close()`. The constructor defaults to
329
+ `wss://mainnet.helius-rpc.com` and reads `HELIUS_API_KEY` from the
330
+ environment or `.env` when `api_key` is omitted; an optional `proxy` is
331
+ also accepted.
332
+
333
+ Each `*_subscribe` call returns the integer subscription id. Use
334
+ `receive()` to read a single notification or `listen()` to iterate over
335
+ them; both yield a `(context, notification, subscription)` tuple where
336
+ `notification` is the model below.
337
+
338
+ | Subscribe method | Unsubscribe method | Notification model | Helius docs |
339
+ | ------------------------------- | --------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
340
+ | `account_subscribe(...)` | `account_unsubscribe(...)` | `AccountNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/accountsubscribe) |
341
+ | `block_subscribe(...)` | `block_unsubscribe(...)` | `BlockNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/blocksubscribe) |
342
+ | `logs_subscribe(...)` | `logs_unsubscribe(...)` | `LogsNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/logssubscribe) |
343
+ | `program_subscribe(...)` | `program_unsubscribe(...)` | `ProgramNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/programsubscribe) |
344
+ | `root_subscribe()` | `root_unsubscribe(...)` | `RootNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/rootsubscribe) |
345
+ | `signature_subscribe(...)` | `signature_unsubscribe(...)` | `SignatureNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/signaturesubscribe) |
346
+ | `slot_subscribe()` | `slot_unsubscribe(...)` | `SlotNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/slotsubscribe) |
347
+ | `slots_updates_subscribe()` | `slots_updates_unsubscribe(...)` | `SlotsUpdatesNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/slotsupdatessubscribe) |
348
+ | `vote_subscribe()` | `vote_unsubscribe(...)` | `VoteNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/votesubscribe) |
349
+ | `transaction_subscribe(...)` | `transaction_unsubscribe(...)` | `TransactionNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/slotunsubscribe) |
350
+
351
+ ## Admin API
352
+
353
+ `AccountManagementClient` wraps the Helius admin API. Today it exposes
354
+ project credit usage via `get_project_usage(...)`, which returns a typed
355
+ `ProjectUsage` model.
356
+
357
+ ```python
358
+ from helius.admin.admin import AccountManagementClient
359
+
360
+ with AccountManagementClient(api_key="YOUR_HELIUS_API_KEY") as admin:
361
+ usage = admin.get_project_usage(project_id="YOUR_PROJECT_ID")
362
+ print(usage.credits_remaining, usage.usage.rpc)
363
+ ```
364
+
365
+ The `project_id` can be passed per call or set once on the constructor;
366
+ if neither is provided, `get_project_usage` raises `ValueError`. The
367
+ client defaults to `https://admin-api.helius.xyz` and, like the others,
368
+ supports the context-manager protocol, a manual `close()`, and reads
369
+ `HELIUS_API_KEY` from the environment or `.env`.
342
370
 
343
371
  ## License
344
372
 
@@ -0,0 +1,3 @@
1
+ - Mangling __
2
+ - WebSocket subscription manager
3
+ - Use typeddicts where useful