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.
- {helius_python-0.1.1 → helius_python-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +1 -1
- {helius_python-0.1.1 → helius_python-0.3.0}/AGENTS.md +10 -92
- {helius_python-0.1.1 → helius_python-0.3.0}/CONTRIBUTING.md +2 -1
- {helius_python-0.1.1 → helius_python-0.3.0}/PKG-INFO +93 -64
- {helius_python-0.1.1 → helius_python-0.3.0}/README.md +91 -63
- helius_python-0.3.0/TODO.md +3 -0
- {helius_python-0.1.1 → helius_python-0.3.0}/examples/block_explorer.py +9 -6
- {helius_python-0.1.1 → helius_python-0.3.0}/examples/devnet_airdrop.py +2 -2
- {helius_python-0.1.1 → helius_python-0.3.0}/examples/network_status.py +2 -2
- {helius_python-0.1.1 → helius_python-0.3.0}/examples/priority_fees.py +2 -2
- {helius_python-0.1.1 → helius_python-0.3.0}/examples/stake_overview.py +22 -14
- {helius_python-0.1.1 → helius_python-0.3.0}/examples/token_inspector.py +2 -2
- {helius_python-0.1.1 → helius_python-0.3.0}/examples/transaction_inspector.py +5 -4
- {helius_python-0.1.1 → helius_python-0.3.0}/examples/wallet_tracker.py +9 -6
- {helius_python-0.1.1 → helius_python-0.3.0}/pyproject.toml +5 -1
- {helius_python-0.1.1 → helius_python-0.3.0}/requirements.txt +1 -0
- helius_python-0.3.0/src/helius/admin/admin.py +95 -0
- helius_python-0.3.0/src/helius/laserstream/websockets.py +398 -0
- helius_python-0.3.0/src/helius/rpc/__init__.py +3 -0
- helius_python-0.3.0/src/helius/rpc/json_rpc_request.py +52 -0
- helius_python-0.3.0/src/helius/solana_rpc/__init__.py +5 -0
- {helius_python-0.1.1/src/helius → helius_python-0.3.0/src/helius/solana_rpc}/client.py +100 -113
- {helius_python-0.1.1/src/helius → helius_python-0.3.0/src/helius/solana_rpc}/models.py +7 -0
- helius_python-0.3.0/tests/unit/admin/test_admin.py +73 -0
- helius_python-0.3.0/tests/unit/lasterstream/test_websockets.py +871 -0
- helius_python-0.3.0/tests/unit/rpc/test_json_rpc_request.py +50 -0
- 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
- {helius_python-0.1.1/tests/unit → helius_python-0.3.0/tests/unit/solana_rpc}/test_models.py +30 -2
- helius_python-0.1.1/tests/unit/test_rpc_request.py +0 -46
- {helius_python-0.1.1 → helius_python-0.3.0}/.editorconfig +0 -0
- {helius_python-0.1.1 → helius_python-0.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {helius_python-0.1.1 → helius_python-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {helius_python-0.1.1 → helius_python-0.3.0}/.github/workflows/python-package.yml +0 -0
- {helius_python-0.1.1 → helius_python-0.3.0}/.github/workflows/python-publish.yml +0 -0
- {helius_python-0.1.1 → helius_python-0.3.0}/.gitignore +0 -0
- {helius_python-0.1.1 → helius_python-0.3.0}/CLAUDE.md +0 -0
- {helius_python-0.1.1 → helius_python-0.3.0}/LICENSE +0 -0
- {helius_python-0.1.1 → helius_python-0.3.0}/src/helius/__init__.py +0 -0
- {helius_python-0.1.1 → helius_python-0.3.0}/tests/fixtures/account.json +0 -0
- {helius_python-0.1.1 → helius_python-0.3.0}/tests/fixtures/supply.json +0 -0
|
@@ -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
|
|
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
|
|
104
|
-
4. Add
|
|
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
|
-
|
|
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 `
|
|
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.
|
|
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
|
|
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 `
|
|
201
|
-
- Use the context-manager form (`with
|
|
202
|
-
- Group tests in `tests/unit/
|
|
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/
|
|
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.
|
|
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.
|
|
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:**
|
|
192
|
-
>
|
|
193
|
-
>
|
|
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.
|
|
171
|
+
from helius.solana_rpc import SolanaRpcClient
|
|
210
172
|
|
|
211
|
-
client =
|
|
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.
|
|
190
|
+
from helius.solana_rpc import SolanaRpcClient
|
|
229
191
|
|
|
230
|
-
client =
|
|
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.
|
|
200
|
+
from helius.solana_rpc import SolanaRpcClient
|
|
239
201
|
|
|
240
|
-
with
|
|
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
|
-
`
|
|
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.
|
|
220
|
+
from helius.solana_rpc import SolanaRpcClient
|
|
259
221
|
|
|
260
|
-
client =
|
|
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/
|
|
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.
|
|
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:**
|
|
172
|
-
>
|
|
173
|
-
>
|
|
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.
|
|
150
|
+
from helius.solana_rpc import SolanaRpcClient
|
|
190
151
|
|
|
191
|
-
client =
|
|
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.
|
|
169
|
+
from helius.solana_rpc import SolanaRpcClient
|
|
209
170
|
|
|
210
|
-
client =
|
|
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.
|
|
179
|
+
from helius.solana_rpc import SolanaRpcClient
|
|
219
180
|
|
|
220
|
-
with
|
|
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
|
-
`
|
|
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.
|
|
199
|
+
from helius.solana_rpc import SolanaRpcClient
|
|
239
200
|
|
|
240
|
-
client =
|
|
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/
|
|
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
|
|