Skip to content

Commit 47d7335

Browse files
committed
0.11.0.1
1 parent c5d6b02 commit 47d7335

14 files changed

Lines changed: 297 additions & 537 deletions

File tree

README.md

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The Somnia Data Streams Python SDK enables streaming data on-chain, integrated w
1313
- Type-safe API with comprehensive type definitions
1414
- Asynchronized architecture for better CPU utilization on high load
1515
- Extensive unit tests and integration tests
16+
- Example code snippets for all functionalities
1617

1718

1819
## Installation
@@ -39,6 +40,8 @@ sdk = SDK.create_for_chain(SOMNIA_TESTNET["id"], private_key="0x...")
3940
### Get All Registered Schemas
4041

4142
```python
43+
import asyncio
44+
4245
schemas = await sdk.streams.get_all_schemas()
4346
for i, schema in enumerate(schemas):
4447
print(f"{i+1}. {schema}")
@@ -67,7 +70,7 @@ from somnia_data_streams_sdk import SchemaEncoder, SchemaItem
6770
encoder = SchemaEncoder("uint256 balance, address owner")
6871
encoded = encoder.encode_data([
6972
SchemaItem(name="balance", type="uint256", value=666),
70-
SchemaItem(name="owner", type="address", value="0x7e5f4552091a69125d5dfcb7b8c2659029395bdf"),
73+
SchemaItem(name="owner", type="address", value="0x..."),
7174
])
7275
print(f"Encoded Schema: {encoded}")
7376

@@ -77,7 +80,7 @@ for item in decoded:
7780
print(f" {item.name} ({item.type}): {item.value.value}")
7881
```
7982

80-
### Register a Schema (Consumes Gas)
83+
### Register a Data Schema (Consumes Gas)
8184

8285
```python
8386
from somnia_data_streams_sdk import DataSchemaRegistration
@@ -136,59 +139,96 @@ if data:
136139
print("Raw data (schema not public):", data)
137140
```
138141

139-
### Register and Emit Events (Consumes Gas)
142+
### Register Events (Consumes Gas)
140143

141144
```python
142-
from somnia_data_streams_sdk import EventSchema, EventParameter, EventStream
145+
from somnia_data_streams_sdk import EventSchema, EventParameter
143146
from eth_utils import to_hex, keccak
144147

145-
# First, register an event schema
146-
event_signature = "Transfer(address,uint256,uint256)"
147-
event_topic = to_hex(keccak(text=event_signature)) # Compute keccak256 hash
148+
event_signature = "TestV1(uint256 indexed x)"
149+
event_id = "TestV1"
148150

149151
event_schemas = [
150152
EventSchema(
151153
params=[
152-
EventParameter(name="user", param_type="address", is_indexed=True),
153-
EventParameter(name="amount", param_type="uint256", is_indexed=False),
154-
EventParameter(name="timestamp", param_type="uint256", is_indexed=False),
154+
EventParameter(name="x", param_type="uint256", is_indexed=True)
155155
],
156-
event_topic=event_topic # HexStr: keccak256 hash of event signature
156+
event_topic=to_hex(keccak(text=event_signature))
157157
)
158158
]
159159

160160
tx_hash = await sdk.streams.register_event_schemas(
161-
ids=["my-transfer-event"],
161+
ids=[event_id],
162162
schemas=event_schemas
163163
)
164+
164165
if tx_hash and isinstance(tx_hash, str):
165-
print(f"Event schema registered! TX: {tx_hash}")
166+
print(f"Event schema registered! TX: 0x{tx_hash}")
166167
else:
167168
print("Event schema registration failed or already registered")
168169

169-
# Then emit events
170+
time.sleep(5) # gives Somnia's blockchain a short time to register the event
171+
172+
tx_hash = await sdk.streams.manage_event_emitters_for_registered_streams_event(
173+
event_id, "0x...", True) # Replace 0x... with your public key
174+
print(f"Event permission added! TX: 0x{tx_hash}")
175+
```
176+
177+
### Emit Events (Consumes Gas)
178+
179+
```python
170180
from eth_abi import encode
181+
from somnia_data_streams_sdk import EventStream
171182

172183
event_data = encode(
173-
["uint256", "uint256"],
174-
[1000, 1234567890] # amount, timestamp
184+
["uint256"],
185+
[13] # Replace 13 with any unsigned int value you want to emit
175186
)
176187

177188
events = [
178189
EventStream(
179-
id="my-transfer-event",
180-
argument_topics=[to_hex(keccak(hexstr="0x" + "1234567890123456789012345678901234567890"))], # indexed user address
181-
data=to_hex(event_data)
190+
id=event_id,
191+
argument_topics=[to_hex(keccak(text=event_signature))],
192+
data=event_data
182193
)
183194
]
184195

185196
tx_hash = await sdk.streams.emit_events(events)
186197
if tx_hash and isinstance(tx_hash, str):
187-
print(f"Events emitted! TX: {tx_hash}")
198+
print(f"Events emitted! TX: 0x{tx_hash}")
188199
else:
189200
print("Event emission failed")
190201
```
191202

203+
### Subscribe to Events
204+
205+
```python
206+
from somnia_data_streams_sdk import SubscriptionInitParams
207+
208+
def on_data(data):
209+
print(data)
210+
211+
def on_error(error):
212+
print(error)
213+
214+
subscription = await sdk.streams.subscribe(
215+
SubscriptionInitParams(
216+
somnia_streams_event_id="TestV1",
217+
eth_calls=[],
218+
on_data=on_data,
219+
on_error=on_error,
220+
only_push_changes=True
221+
)
222+
)
223+
224+
print("Subscribed to TestV1. Press Ctrl+C to stop.")
225+
226+
try:
227+
await asyncio.Future()
228+
except:
229+
await subscription.get("unsubscribe")
230+
```
231+
192232

193233
## API Reference
194234

@@ -220,4 +260,4 @@ If it's bug fix or code improvement (i.e. not a new feature), please make sure y
220260
pytest -v -s
221261
```
222262

223-
If it's a new feature, don't forget to write unit tests and integration tests for it.
263+
If it's a new feature, don't forget to write examples, unit tests, and integration tests for it.

examples/example_emit_events.py

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,21 @@
11
import asyncio
2-
from eth_typing import HexStr
32
from eth_utils import to_hex, keccak
43
from eth_abi import encode
5-
from web3 import Web3
6-
import time
7-
from somnia_data_streams_sdk import SDK, SOMNIA_TESTNET, EventSchema, EventParameter, EventStream
4+
from somnia_data_streams_sdk import SDK, SOMNIA_TESTNET, EventStream
85

96

107
async def main():
118
sdk = SDK.create_for_chain(SOMNIA_TESTNET["id"],
129
private_key="0x0000000000000000000000000000000000000000000000000000000000000001")
1310

14-
event_signature = "TesterV1(uint256 indexed x)"
15-
event_id = "TesterY1"
16-
17-
event_schemas = [
18-
EventSchema(
19-
params=[
20-
EventParameter(name="x", param_type="uint256", is_indexed=True)
21-
],
22-
event_topic=to_hex(keccak(text=event_signature))
23-
)
24-
]
25-
26-
tx_hash = await sdk.streams.register_event_schemas(
27-
ids=[event_id],
28-
schemas=event_schemas
29-
)
30-
31-
if tx_hash and isinstance(tx_hash, str):
32-
print(f"Event schema registered! TX: 0x{tx_hash}")
33-
else:
34-
print("Event schema registration failed or already registered")
11+
event_signature = "TestV1(uint256 indexed x)"
12+
event_id = "TestV1"
3513

3614
event_data = encode(
3715
["uint256"],
3816
[13]
3917
)
4018

41-
time.sleep(5)
42-
43-
tx_hash = await sdk.streams.manage_event_emitters_for_registered_streams_event(
44-
event_id, "0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf", True)
45-
print(f"Event permission added! TX: 0x{tx_hash}")
46-
4719
events = [
4820
EventStream(
4921
id=event_id,
@@ -52,8 +24,6 @@ async def main():
5224
)
5325
]
5426

55-
time.sleep(5)
56-
5727
tx_hash = await sdk.streams.emit_events(events)
5828
if tx_hash and isinstance(tx_hash, str):
5929
print(f"Events emitted! TX: 0x{tx_hash}")
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import asyncio
2+
from eth_utils import to_hex, keccak
3+
import time
4+
from somnia_data_streams_sdk import SDK, SOMNIA_TESTNET, EventSchema, EventParameter
5+
6+
7+
async def main():
8+
sdk = SDK.create_for_chain(SOMNIA_TESTNET["id"],
9+
private_key="0x0000000000000000000000000000000000000000000000000000000000000001")
10+
11+
event_signature = "TestV1(uint256 indexed x)"
12+
event_id = "TestV1"
13+
14+
event_schemas = [
15+
EventSchema(
16+
params=[
17+
EventParameter(name="x", param_type="uint256", is_indexed=True)
18+
],
19+
event_topic=to_hex(keccak(text=event_signature))
20+
)
21+
]
22+
23+
tx_hash = await sdk.streams.register_event_schemas(
24+
ids=[event_id],
25+
schemas=event_schemas
26+
)
27+
if tx_hash and isinstance(tx_hash, str):
28+
print(f"Event schema registered! TX: 0x{tx_hash}")
29+
else:
30+
print("Event schema registration failed or already registered")
31+
32+
time.sleep(5)
33+
34+
tx_hash = await sdk.streams.manage_event_emitters_for_registered_streams_event(
35+
event_id, "0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf", True)
36+
print(f"Event permission added! TX: 0x{tx_hash}")
37+
38+
if __name__ == "__main__":
39+
asyncio.run(main())

examples/example_subscribe.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import asyncio
2+
import traceback
3+
from pprint import pprint
4+
from somnia_data_streams_sdk import SDK, SOMNIA_TESTNET, SubscriptionInitParams
5+
6+
7+
def on_data(data):
8+
print("Full event data:")
9+
pprint(data)
10+
print("Decoded event data value:")
11+
print(int(data.get("result").get("data").hex(), 16))
12+
13+
14+
def on_error(error):
15+
print(f"Subscription error: {error}")
16+
17+
18+
async def main():
19+
sdk = SDK.create_for_chain(SOMNIA_TESTNET["id"],
20+
private_key="0x0000000000000000000000000000000000000000000000000000000000000001")
21+
22+
try:
23+
subscription = await sdk.streams.subscribe(
24+
SubscriptionInitParams(
25+
somnia_streams_event_id="TestV1",
26+
eth_calls=[],
27+
on_data=on_data,
28+
on_error=on_error,
29+
only_push_changes=True,
30+
context=None # Optional context for filtering
31+
)
32+
)
33+
34+
if subscription:
35+
print(f"Subscription ID: {subscription.get('subscriptionId')}")
36+
print("Run example_emit_events.py to emit a new TestV1 event")
37+
print("Waiting for events... (Press Ctrl+C to stop)")
38+
39+
await asyncio.sleep(60) # Listen for 60 seconds
40+
41+
print("Unsubscribing...")
42+
unsubscribe_fn = subscription.get("unsubscribe")
43+
if unsubscribe_fn:
44+
await unsubscribe_fn()
45+
print("Unsubscribed successfully!")
46+
else:
47+
print("Failed to subscribe")
48+
49+
except KeyboardInterrupt:
50+
print("Interrupted by user")
51+
except Exception as e:
52+
print(f"Error: {e}")
53+
traceback.print_exc()
54+
55+
56+
if __name__ == "__main__":
57+
asyncio.run(main())

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "somnia-data-streams-sdk"
7-
version = "0.11.0"
7+
version = "0.11.0.1"
88
description = "A Python SDK for Somnia data streams with first class reactivity support"
99
readme = "README.md"
1010
requires-python = ">=3.8"

src/somnia_data_streams_sdk/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
RpcResponse
2525
)
2626

27-
__version__ = "0.11.0"
27+
__version__ = "0.11.0.1"
2828

2929
__all__ = [
3030
"SDK",

src/somnia_data_streams_sdk/chains.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,17 @@ def get_default_rpc_url(chain_id: int) -> str:
9494
"""
9595
chain = get_chain_config(chain_id)
9696
return chain["rpcUrls"]["default"]["http"][0]
97+
98+
99+
def get_default_web_socket_url(chain_id: int) -> str:
100+
"""
101+
Get default RPC URL for a chain.
102+
103+
Args:
104+
chain_id: Chain ID
105+
106+
Returns:
107+
Default RPC URL
108+
"""
109+
chain = get_chain_config(chain_id)
110+
return chain["rpcUrls"]["default"]["webSocket"][0]

src/somnia_data_streams_sdk/modules/encoder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Schema encoder for ABI encoding/decoding."""
22

33
import re
4-
from typing import List, Any, Dict, Tuple, Optional
4+
from typing import List, Any, Dict, Tuple
55
from eth_abi import encode, decode
66
from eth_utils import to_bytes, to_hex
77
from eth_typing import HexStr

0 commit comments

Comments
 (0)