helius-python 0.3.3__tar.gz → 0.4.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 (51) hide show
  1. {helius_python-0.3.3 → helius_python-0.4.0}/PKG-INFO +50 -11
  2. {helius_python-0.3.3 → helius_python-0.4.0}/README.md +49 -10
  3. {helius_python-0.3.3 → helius_python-0.4.0}/TODO.md +2 -0
  4. helius_python-0.4.0/examples/laserstream/websocket_logs.py +76 -0
  5. helius_python-0.4.0/examples/solana_rpc/address_transactions.py +125 -0
  6. helius_python-0.4.0/examples/solana_rpc/address_transfers.py +118 -0
  7. {helius_python-0.3.3/examples → helius_python-0.4.0/examples/solana_rpc}/block_explorer.py +4 -3
  8. {helius_python-0.3.3/examples → helius_python-0.4.0/examples/solana_rpc}/devnet_airdrop.py +26 -4
  9. {helius_python-0.3.3/examples → helius_python-0.4.0/examples/solana_rpc}/network_status.py +1 -1
  10. {helius_python-0.3.3/examples → helius_python-0.4.0/examples/solana_rpc}/priority_fees.py +2 -2
  11. {helius_python-0.3.3/examples → helius_python-0.4.0/examples/solana_rpc}/stake_overview.py +5 -2
  12. {helius_python-0.3.3/examples → helius_python-0.4.0/examples/solana_rpc}/token_inspector.py +12 -5
  13. {helius_python-0.3.3/examples → helius_python-0.4.0/examples/solana_rpc}/transaction_inspector.py +2 -2
  14. {helius_python-0.3.3/examples → helius_python-0.4.0/examples/solana_rpc}/wallet_tracker.py +4 -4
  15. helius_python-0.4.0/examples/webhooks/webhook_crud.py +190 -0
  16. helius_python-0.4.0/examples/webhooks/webhook_receiver.py +109 -0
  17. {helius_python-0.3.3 → helius_python-0.4.0}/pyproject.toml +1 -1
  18. {helius_python-0.3.3 → helius_python-0.4.0}/src/helius/laserstream/websockets.py +1 -1
  19. {helius_python-0.3.3 → helius_python-0.4.0}/src/helius/solana_rpc/client.py +1 -1
  20. {helius_python-0.3.3 → helius_python-0.4.0}/src/helius/solana_rpc/models.py +0 -2
  21. helius_python-0.4.0/src/helius/utils/__init__.py +3 -0
  22. helius_python-0.4.0/src/helius/webhooks/__init__.py +0 -0
  23. helius_python-0.4.0/src/helius/webhooks/webhooks.py +722 -0
  24. helius_python-0.4.0/test_examples.py +226 -0
  25. {helius_python-0.3.3/tests/unit/rpc → helius_python-0.4.0/tests/unit/utils}/test_json_rpc_request.py +1 -1
  26. helius_python-0.4.0/tests/unit/webhooks/test_webhook.py +26 -0
  27. helius_python-0.4.0/tests/unit/webhooks/test_webhooks_api_client.py +168 -0
  28. helius_python-0.3.3/src/helius/rpc/__init__.py +0 -3
  29. {helius_python-0.3.3 → helius_python-0.4.0}/.editorconfig +0 -0
  30. {helius_python-0.3.3 → helius_python-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  31. {helius_python-0.3.3 → helius_python-0.4.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  32. {helius_python-0.3.3 → helius_python-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  33. {helius_python-0.3.3 → helius_python-0.4.0}/.github/workflows/python-package.yml +0 -0
  34. {helius_python-0.3.3 → helius_python-0.4.0}/.github/workflows/python-publish.yml +0 -0
  35. {helius_python-0.3.3 → helius_python-0.4.0}/.gitignore +0 -0
  36. {helius_python-0.3.3 → helius_python-0.4.0}/AGENTS.md +0 -0
  37. {helius_python-0.3.3 → helius_python-0.4.0}/CLAUDE.md +0 -0
  38. {helius_python-0.3.3 → helius_python-0.4.0}/CONTRIBUTING.md +0 -0
  39. {helius_python-0.3.3 → helius_python-0.4.0}/LICENSE +0 -0
  40. {helius_python-0.3.3 → helius_python-0.4.0}/requirements.txt +0 -0
  41. {helius_python-0.3.3 → helius_python-0.4.0}/src/helius/__init__.py +0 -0
  42. {helius_python-0.3.3 → helius_python-0.4.0}/src/helius/admin/__init__.py +0 -0
  43. {helius_python-0.3.3 → helius_python-0.4.0}/src/helius/admin/admin.py +0 -0
  44. {helius_python-0.3.3 → helius_python-0.4.0}/src/helius/solana_rpc/__init__.py +0 -0
  45. {helius_python-0.3.3/src/helius/rpc → helius_python-0.4.0/src/helius/utils}/json_rpc_request.py +0 -0
  46. {helius_python-0.3.3 → helius_python-0.4.0}/tests/fixtures/account.json +0 -0
  47. {helius_python-0.3.3 → helius_python-0.4.0}/tests/fixtures/supply.json +0 -0
  48. {helius_python-0.3.3 → helius_python-0.4.0}/tests/unit/admin/test_admin.py +0 -0
  49. {helius_python-0.3.3 → helius_python-0.4.0}/tests/unit/lasterstream/test_websockets.py +0 -0
  50. {helius_python-0.3.3 → helius_python-0.4.0}/tests/unit/solana_rpc/test_client.py +0 -0
  51. {helius_python-0.3.3 → helius_python-0.4.0}/tests/unit/solana_rpc/test_models.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: helius-python
3
- Version: 0.3.3
3
+ Version: 0.4.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
@@ -135,9 +135,10 @@ wraps it.
135
135
  - 🚧 **All Helius-specific RPC extensions** — enhanced transactions, DAS
136
136
  (Digital Asset Standard) methods, priority fee estimation, and the
137
137
  rest of the Helius-only RPC namespace. **(in progress)**
138
- - 🚧 **Every Helius REST endpoint** — Enhanced Transactions API,
139
- Webhooks API, Mint API, token metadata, address lookups, and beyond.
140
- **(in progress)**
138
+ - **Webhooks API** — create, fetch, update, enable/disable, and delete
139
+ Helius webhooks. **(supported today)**
140
+ - 🚧 **Remaining Helius REST endpoints** — Enhanced Transactions API,
141
+ Mint API, token metadata, address lookups, and beyond. **(in progress)**
141
142
  - 🚧 **Platform features** — streaming, websockets, and any new
142
143
  capability Helius adds to its API. The full WebSocket subscription
143
144
  surface (`accountSubscribe`, `transactionSubscribe`, `logsSubscribe`,
@@ -145,10 +146,10 @@ wraps it.
145
146
  platform features are **in progress**.
146
147
 
147
148
  **Current status:** the standard Solana JSON-RPC surface, the
148
- WebSocket subscription surface, and the Admin (account management)
149
- usage endpoint are implemented today. Support for Helius RPC
150
- extensions and the remaining REST endpoints is actively being worked
151
- on.
149
+ WebSocket subscription surface, the Webhooks API, and the Admin
150
+ (account management) usage endpoint are implemented today. Support for
151
+ Helius RPC extensions and the remaining REST endpoints is actively
152
+ being worked on.
152
153
 
153
154
  ## Goals
154
155
 
@@ -266,9 +267,9 @@ The method names map 1:1 to the Solana JSON-RPC spec, just converted to
266
267
  ## Status
267
268
 
268
269
  Actively expanding toward full coverage of the Helius API. See
269
- [`src/helius/solana_rpc.py`](src/helius/solana_rpc.py) for the current list of
270
- implemented methods; missing endpoints are tracked as issues and added
271
- continuously.
270
+ [`src/helius/solana_rpc/client.py`](src/helius/solana_rpc/client.py) for the
271
+ current Solana JSON-RPC implementation; supported surfaces are listed below,
272
+ and missing endpoints are tracked as issues and added continuously.
272
273
 
273
274
  | Solana JSON-RPC method | Python method | Helius docs |
274
275
  | ----------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
@@ -372,6 +373,44 @@ them; both yield a `(context, notification, subscription)` tuple where
372
373
  | `vote_subscribe()` | `vote_unsubscribe(...)` | `VoteNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/votesubscribe) |
373
374
  | `transaction_subscribe(...)` | `transaction_unsubscribe(...)` | `TransactionNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/slotunsubscribe) |
374
375
 
376
+ ## Webhooks API
377
+
378
+ `WebhooksApiClient` wraps the Helius Webhooks REST API. It can create,
379
+ fetch, list, update, enable/disable, and delete webhook subscriptions,
380
+ returning typed `Webhook` models where the endpoint returns a webhook.
381
+
382
+ ```python
383
+ from helius.webhooks.webhooks import WebhooksApiClient
384
+
385
+ with WebhooksApiClient(api_key="YOUR_HELIUS_API_KEY") as webhooks:
386
+ webhook = webhooks.create_webhook(
387
+ webhook_url="https://example.com/helius-webhook",
388
+ transaction_types=["TRANSFER"],
389
+ account_addresses=["So11111111111111111111111111111111111111112"],
390
+ webhook_type="enhanced",
391
+ auth_header="Bearer your-shared-secret",
392
+ encoding="jsonParsed",
393
+ txn_status="all",
394
+ )
395
+
396
+ webhooks.toggle_webhook(webhook.webhook_id, active=False)
397
+ ```
398
+
399
+ Like the other clients, it supports the context-manager protocol and a
400
+ manual `close()`. The constructor defaults to
401
+ `https://mainnet.helius-rpc.com/v0/webhooks` and reads `HELIUS_API_KEY`
402
+ from the environment or `.env` when `api_key` is omitted; optional
403
+ `headers` and `proxy` arguments are also accepted.
404
+
405
+ | REST operation | Python method | Helius docs |
406
+ | -------------- | -------------------------- | ------------------------------------------------------------------------------------------------- |
407
+ | Create webhook | `create_webhook(...)` | [reference](https://www.helius.dev/docs/api-reference/webhooks/create-webhook) |
408
+ | Get webhook | `get_webhook(...)` | [reference](https://www.helius.dev/docs/api-reference/webhooks/get-webhook) |
409
+ | List webhooks | `get_all_webhooks()` | [reference](https://www.helius.dev/docs/api-reference/webhooks/get-all-webhooks) |
410
+ | Update webhook | `update_webhook(...)` | [reference](https://www.helius.dev/docs/api-reference/webhooks/update-webhook) |
411
+ | Toggle webhook | `toggle_webhook(...)` | [reference](https://www.helius.dev/docs/api-reference/webhooks/toggle-webhook) |
412
+ | Delete webhook | `delete_webhook(...)` | [reference](https://www.helius.dev/docs/api-reference/webhooks/delete-webhook) |
413
+
375
414
  ## Admin API
376
415
 
377
416
  `AccountManagementClient` wraps the Helius admin API. Today it exposes
@@ -113,9 +113,10 @@ wraps it.
113
113
  - 🚧 **All Helius-specific RPC extensions** — enhanced transactions, DAS
114
114
  (Digital Asset Standard) methods, priority fee estimation, and the
115
115
  rest of the Helius-only RPC namespace. **(in progress)**
116
- - 🚧 **Every Helius REST endpoint** — Enhanced Transactions API,
117
- Webhooks API, Mint API, token metadata, address lookups, and beyond.
118
- **(in progress)**
116
+ - **Webhooks API** — create, fetch, update, enable/disable, and delete
117
+ Helius webhooks. **(supported today)**
118
+ - 🚧 **Remaining Helius REST endpoints** — Enhanced Transactions API,
119
+ Mint API, token metadata, address lookups, and beyond. **(in progress)**
119
120
  - 🚧 **Platform features** — streaming, websockets, and any new
120
121
  capability Helius adds to its API. The full WebSocket subscription
121
122
  surface (`accountSubscribe`, `transactionSubscribe`, `logsSubscribe`,
@@ -123,10 +124,10 @@ wraps it.
123
124
  platform features are **in progress**.
124
125
 
125
126
  **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.
127
+ WebSocket subscription surface, the Webhooks API, and the Admin
128
+ (account management) usage endpoint are implemented today. Support for
129
+ Helius RPC extensions and the remaining REST endpoints is actively
130
+ being worked on.
130
131
 
131
132
  ## Goals
132
133
 
@@ -244,9 +245,9 @@ The method names map 1:1 to the Solana JSON-RPC spec, just converted to
244
245
  ## Status
245
246
 
246
247
  Actively expanding toward full coverage of the Helius API. See
247
- [`src/helius/solana_rpc.py`](src/helius/solana_rpc.py) for the current list of
248
- implemented methods; missing endpoints are tracked as issues and added
249
- continuously.
248
+ [`src/helius/solana_rpc/client.py`](src/helius/solana_rpc/client.py) for the
249
+ current Solana JSON-RPC implementation; supported surfaces are listed below,
250
+ and missing endpoints are tracked as issues and added continuously.
250
251
 
251
252
  | Solana JSON-RPC method | Python method | Helius docs |
252
253
  | ----------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
@@ -350,6 +351,44 @@ them; both yield a `(context, notification, subscription)` tuple where
350
351
  | `vote_subscribe()` | `vote_unsubscribe(...)` | `VoteNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/votesubscribe) |
351
352
  | `transaction_subscribe(...)` | `transaction_unsubscribe(...)` | `TransactionNotification` | [reference](https://www.helius.dev/docs/api-reference/rpc/websocket/slotunsubscribe) |
352
353
 
354
+ ## Webhooks API
355
+
356
+ `WebhooksApiClient` wraps the Helius Webhooks REST API. It can create,
357
+ fetch, list, update, enable/disable, and delete webhook subscriptions,
358
+ returning typed `Webhook` models where the endpoint returns a webhook.
359
+
360
+ ```python
361
+ from helius.webhooks.webhooks import WebhooksApiClient
362
+
363
+ with WebhooksApiClient(api_key="YOUR_HELIUS_API_KEY") as webhooks:
364
+ webhook = webhooks.create_webhook(
365
+ webhook_url="https://example.com/helius-webhook",
366
+ transaction_types=["TRANSFER"],
367
+ account_addresses=["So11111111111111111111111111111111111111112"],
368
+ webhook_type="enhanced",
369
+ auth_header="Bearer your-shared-secret",
370
+ encoding="jsonParsed",
371
+ txn_status="all",
372
+ )
373
+
374
+ webhooks.toggle_webhook(webhook.webhook_id, active=False)
375
+ ```
376
+
377
+ Like the other clients, it supports the context-manager protocol and a
378
+ manual `close()`. The constructor defaults to
379
+ `https://mainnet.helius-rpc.com/v0/webhooks` and reads `HELIUS_API_KEY`
380
+ from the environment or `.env` when `api_key` is omitted; optional
381
+ `headers` and `proxy` arguments are also accepted.
382
+
383
+ | REST operation | Python method | Helius docs |
384
+ | -------------- | -------------------------- | ------------------------------------------------------------------------------------------------- |
385
+ | Create webhook | `create_webhook(...)` | [reference](https://www.helius.dev/docs/api-reference/webhooks/create-webhook) |
386
+ | Get webhook | `get_webhook(...)` | [reference](https://www.helius.dev/docs/api-reference/webhooks/get-webhook) |
387
+ | List webhooks | `get_all_webhooks()` | [reference](https://www.helius.dev/docs/api-reference/webhooks/get-all-webhooks) |
388
+ | Update webhook | `update_webhook(...)` | [reference](https://www.helius.dev/docs/api-reference/webhooks/update-webhook) |
389
+ | Toggle webhook | `toggle_webhook(...)` | [reference](https://www.helius.dev/docs/api-reference/webhooks/toggle-webhook) |
390
+ | Delete webhook | `delete_webhook(...)` | [reference](https://www.helius.dev/docs/api-reference/webhooks/delete-webhook) |
391
+
353
392
  ## Admin API
354
393
 
355
394
  `AccountManagementClient` wraps the Helius admin API. Today it exposes
@@ -2,3 +2,5 @@
2
2
  - WebSocket subscription manager
3
3
  - Use typeddicts where useful
4
4
  - When Python 3.10 and 3.11 go out of support we should use TypedDict from typing instead of typing_extensions
5
+ - Improve camelCase <-> snake_case in typing
6
+ - Handle HTTP response codes and idiomatic error messages in responses
@@ -0,0 +1,76 @@
1
+ """Listen for Solana log notifications over Helius WebSockets.
2
+
3
+ Subscribes with `logsSubscribe`, prints a small number of notifications,
4
+ then unsubscribes cleanly. Use `--mentions <ADDRESS>` to filter logs to a
5
+ single account or program; otherwise the example listens to all logs.
6
+
7
+ Usage:
8
+
9
+ export HELIUS_API_KEY=your_helius_api_key
10
+ python examples/laserstream/websocket_logs.py --mentions <ADDRESS>
11
+ python examples/laserstream/websocket_logs.py --count 3
12
+
13
+ Docs:
14
+ https://www.helius.dev/docs/api-reference/rpc/websocket/logssubscribe
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import argparse
20
+ from contextlib import suppress
21
+ import sys
22
+
23
+ from helius.laserstream.websockets import WebSocketClient
24
+
25
+
26
+ def main() -> int:
27
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
28
+ parser.add_argument(
29
+ "--mentions",
30
+ help="Only receive logs mentioning this account or program address",
31
+ )
32
+ parser.add_argument(
33
+ "--count",
34
+ type=int,
35
+ default=5,
36
+ help="Number of notifications to print before exiting (default 5)",
37
+ )
38
+ args = parser.parse_args()
39
+
40
+ log_filter = {"mentions": [args.mentions]} if args.mentions else "all"
41
+
42
+ with WebSocketClient() as client:
43
+ subscription = client.logs_subscribe(
44
+ filter=log_filter,
45
+ commitment="confirmed",
46
+ )
47
+ print(f"Subscribed to logs with id {subscription}. Waiting...\n")
48
+
49
+ try:
50
+ for index, (context, notification, _subscription) in enumerate(
51
+ client.listen(), start=1
52
+ ):
53
+ slot = context.get("slot") if context else "unknown"
54
+ status = "ERR" if notification.err else "OK "
55
+ print(f"[{index}/{args.count}] slot={slot} {status} {notification.signature}")
56
+ for line in notification.logs[:5]:
57
+ print(f" {line}")
58
+ if len(notification.logs) > 5:
59
+ print(f" ... {len(notification.logs) - 5} more log lines")
60
+ print()
61
+ if index >= args.count:
62
+ break
63
+ finally:
64
+ # A busy `logsSubscribe` stream can deliver another notification
65
+ # between our unsubscribe request and the unsubscribe response. The
66
+ # client helper currently expects the very next frame to be the RPC
67
+ # response, so ignore that race here and let the context manager
68
+ # close the socket cleanly.
69
+ with suppress(KeyError):
70
+ client.logs_unsubscribe(subscription)
71
+
72
+ return 0
73
+
74
+
75
+ if __name__ == "__main__":
76
+ sys.exit(main())
@@ -0,0 +1,125 @@
1
+ """List Helius enhanced transactions for an address.
2
+
3
+ Uses Helius's `getTransactionsForAddress` RPC method, which can return
4
+ either compact signature rows or full transaction payloads with pagination.
5
+
6
+ Usage:
7
+
8
+ export HELIUS_API_KEY=your_helius_api_key
9
+ python examples/solana_rpc/address_transactions.py <ADDRESS> [--limit 10]
10
+ python examples/solana_rpc/address_transactions.py <ADDRESS> --full --limit 5
11
+
12
+ Docs:
13
+ https://www.helius.dev/docs/getting-data/get-transactions-for-address
14
+
15
+ Note:
16
+ Helius documents this exclusive RPC method as requiring a Developer plan
17
+ or higher.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import argparse
23
+ import datetime as dt
24
+ import sys
25
+
26
+ import httpx
27
+
28
+ from helius.solana_rpc import SolanaRpcClient
29
+
30
+
31
+ def format_time(block_time: int | None) -> str:
32
+ if block_time is None:
33
+ return "(no time)"
34
+ return dt.datetime.fromtimestamp(block_time, tz=dt.timezone.utc).strftime(
35
+ "%Y-%m-%d %H:%M:%SZ"
36
+ )
37
+
38
+
39
+ def main() -> int:
40
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
41
+ parser.add_argument("address", help="Wallet, account, or program address")
42
+ parser.add_argument(
43
+ "--limit",
44
+ type=int,
45
+ default=10,
46
+ help="Number of rows to fetch (1-1000, default 10)",
47
+ )
48
+ parser.add_argument(
49
+ "--pagination-token",
50
+ help="Token returned by a previous page of results",
51
+ )
52
+ parser.add_argument(
53
+ "--full",
54
+ action="store_true",
55
+ help="Fetch full transaction details instead of signature rows",
56
+ )
57
+ parser.add_argument(
58
+ "--dry-run",
59
+ action="store_true",
60
+ help="Validate arguments and print the planned request without sending it",
61
+ )
62
+ args = parser.parse_args()
63
+
64
+ details = "full" if args.full else "signatures"
65
+ if args.dry_run:
66
+ print("Would call get_transactions_for_address with:")
67
+ print(f" address={args.address}")
68
+ print(f" transaction_details={details}")
69
+ print(f" limit={args.limit}")
70
+ print(f" pagination_token={args.pagination_token}")
71
+ print(f" encoding={'jsonParsed' if args.full else None}")
72
+ return 0
73
+
74
+ try:
75
+ with SolanaRpcClient() as client:
76
+ transactions, next_token = client.get_transactions_for_address(
77
+ address=args.address,
78
+ transaction_details=details,
79
+ sort_order="desc",
80
+ commitment="finalized",
81
+ limit=args.limit,
82
+ pagination_token=args.pagination_token,
83
+ encoding="jsonParsed" if args.full else None,
84
+ max_supported_transaction_version=0 if args.full else None,
85
+ )
86
+ except httpx.HTTPStatusError as exc:
87
+ print(
88
+ f"HTTP {exc.response.status_code}: getTransactionsForAddress was rejected. "
89
+ "This Helius-exclusive method may require a Developer plan or higher.",
90
+ file=sys.stderr,
91
+ )
92
+ return 2
93
+
94
+ print(f"\n=== Transactions for {args.address} ===\n")
95
+ if not transactions:
96
+ print("No transactions returned.")
97
+ return 0
98
+
99
+ for tx in transactions:
100
+ if details == "signatures":
101
+ status = "ERR" if tx.err else "OK "
102
+ print(
103
+ f"{format_time(tx.block_time)} slot={tx.slot:<12} "
104
+ f"idx={tx.transaction_index:<4} {status} {tx.signature}"
105
+ )
106
+ else:
107
+ signature = "(signature unavailable)"
108
+ signatures = tx.transaction.get("signatures")
109
+ if isinstance(signatures, list) and signatures:
110
+ signature = signatures[0]
111
+ err = tx.meta.get("err") if isinstance(tx.meta, dict) else None
112
+ status = "ERR" if err else "OK "
113
+ print(
114
+ f"{format_time(tx.block_time)} slot={tx.slot:<12} "
115
+ f"idx={tx.transaction_index:<4} {status} {signature}"
116
+ )
117
+
118
+ if next_token:
119
+ print(f"\nNext page token: {next_token}")
120
+
121
+ return 0
122
+
123
+
124
+ if __name__ == "__main__":
125
+ sys.exit(main())
@@ -0,0 +1,118 @@
1
+ """List token and SOL transfers for an address.
2
+
3
+ Uses Helius's `getTransfersByAddress` RPC method exposed by this client as
4
+ `get_transfers_by_address`.
5
+
6
+ Usage:
7
+
8
+ export HELIUS_API_KEY=your_helius_api_key
9
+ python examples/solana_rpc/address_transfers.py <ADDRESS> [--limit 20]
10
+ python examples/solana_rpc/address_transfers.py <ADDRESS> --direction in --mint <MINT>
11
+
12
+ Docs:
13
+ https://www.helius.dev/docs/getting-data/get-transfers-by-address
14
+
15
+ Note:
16
+ Helius documents this exclusive RPC method as requiring a Developer plan
17
+ or higher.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import argparse
23
+ import datetime as dt
24
+ import sys
25
+
26
+ import httpx
27
+
28
+ from helius.solana_rpc import SolanaRpcClient
29
+
30
+
31
+ def format_time(block_time: int) -> str:
32
+ return dt.datetime.fromtimestamp(block_time, tz=dt.timezone.utc).strftime(
33
+ "%Y-%m-%d %H:%M:%SZ"
34
+ )
35
+
36
+
37
+ def main() -> int:
38
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
39
+ parser.add_argument("address", help="Wallet, token account, or owner address")
40
+ parser.add_argument(
41
+ "--limit",
42
+ type=int,
43
+ default=20,
44
+ help="Number of transfers to fetch (1-100, default 20)",
45
+ )
46
+ parser.add_argument(
47
+ "--direction",
48
+ choices=("in", "out", "any"),
49
+ default="any",
50
+ help="Transfer direction relative to address (default any)",
51
+ )
52
+ parser.add_argument("--with-address", help="Counterparty address filter")
53
+ parser.add_argument("--mint", help="Mint address filter")
54
+ parser.add_argument(
55
+ "--pagination-token",
56
+ help="Token returned by a previous page of results",
57
+ )
58
+ parser.add_argument(
59
+ "--dry-run",
60
+ action="store_true",
61
+ help="Validate arguments and print the planned request without sending it",
62
+ )
63
+ args = parser.parse_args()
64
+
65
+ if args.dry_run:
66
+ print("Would call get_transfers_by_address with:")
67
+ print(f" address={args.address}")
68
+ print(f" with_address={args.with_address}")
69
+ print(f" direction={args.direction}")
70
+ print(f" mint={args.mint}")
71
+ print(f" limit={args.limit}")
72
+ print(f" pagination_token={args.pagination_token}")
73
+ return 0
74
+
75
+ try:
76
+ with SolanaRpcClient() as client:
77
+ transfers, next_token = client.get_transfers_by_address(
78
+ address=args.address,
79
+ with_address=args.with_address,
80
+ direction=args.direction,
81
+ mint=args.mint,
82
+ limit=args.limit,
83
+ pagination_token=args.pagination_token,
84
+ commitment="finalized",
85
+ sort_order="desc",
86
+ )
87
+ except httpx.HTTPStatusError as exc:
88
+ print(
89
+ f"HTTP {exc.response.status_code}: getTransfersByAddress was rejected. "
90
+ "This Helius-exclusive method may require a Developer plan or higher.",
91
+ file=sys.stderr,
92
+ )
93
+ return 2
94
+
95
+ print(f"\n=== Transfers for {args.address} ===\n")
96
+ if not transfers:
97
+ print("No transfers returned.")
98
+ return 0
99
+
100
+ for transfer in transfers:
101
+ from_acct = transfer.from_user_account or transfer.from_token_account or "-"
102
+ to_acct = transfer.to_user_account or transfer.to_token_account or "-"
103
+ print(
104
+ f"{format_time(transfer.block_time)} slot={transfer.slot:<12} "
105
+ f"{transfer.type:<11} {transfer.ui_amount:>18} mint={transfer.mint}"
106
+ )
107
+ print(f" from={from_acct}")
108
+ print(f" to ={to_acct}")
109
+ print(f" sig ={transfer.signature}")
110
+
111
+ if next_token:
112
+ print(f"\nNext page token: {next_token}")
113
+
114
+ return 0
115
+
116
+
117
+ if __name__ == "__main__":
118
+ sys.exit(main())
@@ -8,8 +8,8 @@ breakdown of successful vs. failed transactions plus total fees paid.
8
8
  Usage:
9
9
 
10
10
  export HELIUS_API_KEY=your_helius_api_key
11
- python examples/block_explorer.py
12
- python examples/block_explorer.py --slot 250000000
11
+ python examples/solana_rpc/block_explorer.py
12
+ python examples/solana_rpc/block_explorer.py --slot 250000000
13
13
 
14
14
  Uses (with `with`):
15
15
  get_slot, get_block.
@@ -43,9 +43,10 @@ def main() -> int:
43
43
  else helius.get_slot(commitment="finalized")
44
44
  )
45
45
  block = helius.get_block(
46
- slot,
46
+ slot=slot,
47
47
  commitment="finalized",
48
48
  encoding="jsonParsed",
49
+ rewards=False,
49
50
  max_supported_transcation_version=0,
50
51
  )
51
52
 
@@ -7,7 +7,7 @@ polls `getSignatureStatuses` until the airdrop transaction reaches a
7
7
  Usage:
8
8
 
9
9
  export HELIUS_API_KEY=your_helius_api_key
10
- python examples/devnet_airdrop.py <WALLET_ADDRESS> [--sol 1.0]
10
+ python examples/solana_rpc/devnet_airdrop.py <WALLET_ADDRESS> [--sol 1.0]
11
11
 
12
12
  Note:
13
13
  `requestAirdrop` is only available on Devnet and Testnet — never on
@@ -24,6 +24,8 @@ import argparse
24
24
  import sys
25
25
  import time
26
26
 
27
+ import httpx
28
+
27
29
  from helius.solana_rpc import SolanaRpcClient
28
30
 
29
31
  LAMPORTS_PER_SOL = 1_000_000_000
@@ -45,20 +47,40 @@ def main() -> int:
45
47
  default=30.0,
46
48
  help="Seconds to wait for confirmation (default: 30)",
47
49
  )
50
+ parser.add_argument(
51
+ "--dry-run",
52
+ action="store_true",
53
+ help="Validate arguments and print the planned airdrop without sending it",
54
+ )
48
55
  args = parser.parse_args()
49
56
  lamports = int(args.sol * LAMPORTS_PER_SOL)
50
57
 
58
+ if args.dry_run:
59
+ print("Would request devnet airdrop with:")
60
+ print(f" address={args.address}")
61
+ print(f" sol={args.sol}")
62
+ print(f" lamports={lamports}")
63
+ print(f" timeout={args.timeout}")
64
+ return 0
65
+
51
66
  client = SolanaRpcClient(base_url=DEVNET_URL)
52
67
  try:
53
68
  print(f"Requesting {args.sol} SOL airdrop to {args.address} on devnet...")
54
- signature = client.request_airdrop(args.address, lamports)
69
+ try:
70
+ signature = client.request_airdrop(public_key=args.address, lamports=lamports)
71
+ except httpx.HTTPStatusError as exc:
72
+ print(
73
+ f"HTTP {exc.response.status_code}: devnet airdrop request was rejected.",
74
+ file=sys.stderr,
75
+ )
76
+ return 2
55
77
  print(f" signature: {signature}")
56
78
 
57
79
  deadline = time.monotonic() + args.timeout
58
80
  status = None
59
81
  while time.monotonic() < deadline:
60
82
  _ctx, statuses = client.get_signature_statuses(
61
- [signature], search_transaction_history=True
83
+ signatures=[signature], search_transaction_history=True
62
84
  )
63
85
  status = statuses[0]
64
86
  if status is not None and status.confirmation_status in (
@@ -79,7 +101,7 @@ def main() -> int:
79
101
  return 1
80
102
  print(f" status: {status.confirmation_status} at slot {status.slot}")
81
103
 
82
- _ctx, balance = client.get_balance(args.address)
104
+ _ctx, balance = client.get_balance(public_key=args.address)
83
105
  print(f"Post-airdrop balance: {balance / LAMPORTS_PER_SOL:.9f} SOL")
84
106
  finally:
85
107
  client.close()
@@ -7,7 +7,7 @@ recent-performance summary (avg TPS over the last samples).
7
7
  Usage:
8
8
 
9
9
  export HELIUS_API_KEY=your_helius_api_key
10
- python examples/network_status.py
10
+ python examples/solana_rpc/network_status.py
11
11
 
12
12
  Uses (with `with`):
13
13
  get_health, get_version, get_slot, get_block_height, get_epoch_info,
@@ -12,8 +12,8 @@ sample only counts transactions that locked those accounts as writable
12
12
  Usage:
13
13
 
14
14
  export HELIUS_API_KEY=your_helius_api_key
15
- python examples/priority_fees.py
16
- python examples/priority_fees.py --account <PUBKEY> --account <PUBKEY>
15
+ python examples/solana_rpc/priority_fees.py
16
+ python examples/solana_rpc/priority_fees.py --account <PUBKEY> --account <PUBKEY>
17
17
 
18
18
  Uses (with `with`):
19
19
  get_recent_prioritization_fees.
@@ -7,7 +7,7 @@ validator set (top 10 by stake).
7
7
  Usage:
8
8
 
9
9
  export HELIUS_API_KEY=your_helius_api_key
10
- python examples/stake_overview.py
10
+ python examples/solana_rpc/stake_overview.py
11
11
 
12
12
  Uses (with `try/finally`):
13
13
  get_inflation_rate, get_inflation_governor, get_supply,
@@ -18,6 +18,8 @@ from __future__ import annotations
18
18
 
19
19
  import sys
20
20
 
21
+ import httpx
22
+
21
23
  from helius.solana_rpc import SolanaRpcClient
22
24
 
23
25
  LAMPORTS_PER_SOL = 1_000_000_000
@@ -25,10 +27,11 @@ LAMPORTS_PER_SOL = 1_000_000_000
25
27
 
26
28
  def main() -> int:
27
29
  client = SolanaRpcClient()
30
+ client._client.timeout = httpx.Timeout(30.0)
28
31
  try:
29
32
  rate = client.get_inflation_rate()
30
33
  gov = client.get_inflation_governor()
31
- _ctx, supply = client.get_supply(exclude_non_circulating_accounts_list=True)
34
+ _ctx, supply = client.get_supply(exclude_non_circulating_accounts_list=False)
32
35
  _ctx, min_stake = client.get_stake_minimum_delegation()
33
36
  current, delinquent = client.get_vote_accounts()
34
37
  finally: