yellowstone-fumarole-client 0.1.0rc2__py3-none-any.whl → 0.2.0__py3-none-any.whl

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.
@@ -1,11 +1,11 @@
1
- from typing import Optional, List, Dict, Set, Deque, Tuple, Any
1
+ from typing import Optional, Set, Deque, Sequence
2
2
  from collections import deque, defaultdict
3
- from yellowstone_fumarole_proto.fumarole_v2_pb2 import (
3
+ from yellowstone_fumarole_proto.fumarole_pb2 import (
4
4
  CommitmentLevel,
5
5
  BlockchainEvent,
6
6
  )
7
+ from yellowstone_fumarole_client.utils.collections import OrderedSet
7
8
  import heapq
8
- import uuid
9
9
  from enum import Enum
10
10
 
11
11
  __all__ = [
@@ -107,7 +107,7 @@ class FumaroleSM:
107
107
  def __init__(self, last_committed_offset: FumeOffset, slot_memory_retention: int):
108
108
  self.last_committed_offset = last_committed_offset
109
109
  self.slot_commitment_progression = dict() # Slot -> SlotCommitmentProgression
110
- self.downloaded_slot = set() # Set of downloaded slots
110
+ self.downloaded_slot = OrderedSet() # Set of downloaded slots
111
111
  self.inflight_slot_shard_download = {} # Slot -> SlotDownloadProgress
112
112
  self.blocked_slot_status_update = defaultdict(
113
113
  deque
@@ -121,7 +121,9 @@ class FumaroleSM:
121
121
  ] = deque()
122
122
  self.sequence = 1
123
123
  self.last_processed_fume_sequence = 0
124
- self.sequence_to_offset = {} # FumeSessionSequence -> FumeOffset
124
+ self.sequence_to_offset: dict[FumeSessionSequence, FumeOffset] = (
125
+ {}
126
+ ) # FumeSessionSequence -> FumeOffset
125
127
  self.slot_memory_retention = slot_memory_retention
126
128
 
127
129
  def update_committed_offset(self, offset: FumeOffset) -> None:
@@ -138,14 +140,14 @@ class FumaroleSM:
138
140
  def gc(self) -> None:
139
141
  """Garbage collect old slots to respect memory retention limit."""
140
142
  while len(self.downloaded_slot) > self.slot_memory_retention:
141
- slot = self.downloaded_slot.pop(0) if self.downloaded_slot else None
143
+ slot = self.downloaded_slot.popfirst() if self.downloaded_slot else None
142
144
  if slot is None:
143
145
  break
144
146
  self.slot_commitment_progression.pop(slot, None)
145
147
  self.inflight_slot_shard_download.pop(slot, None)
146
148
  self.blocked_slot_status_update.pop(slot, None)
147
149
 
148
- def queue_blockchain_event(self, events: List[BlockchainEvent]) -> None:
150
+ def queue_blockchain_event(self, events: Sequence[BlockchainEvent]) -> None:
149
151
  """Queue blockchain events for processing."""
150
152
  for event in events:
151
153
 
@@ -232,7 +234,7 @@ class FumaroleSM:
232
234
  blockchain_event: BlockchainEvent = blockchain_event
233
235
  event_cl = blockchain_event.commitment_level
234
236
 
235
- if event_cl < min_commitment:
237
+ if event_cl != min_commitment:
236
238
  self.slot_status_update_queue.append(
237
239
  FumeSlotStatus(
238
240
  session_sequence=session_sequence,
@@ -266,6 +268,18 @@ class FumaroleSM:
266
268
  else:
267
269
  blockchain_id = bytes(blockchain_event.blockchain_id)
268
270
  block_uid = bytes(blockchain_event.block_uid)
271
+
272
+ self.blocked_slot_status_update[blockchain_event.slot].append(
273
+ FumeSlotStatus(
274
+ session_sequence=session_sequence,
275
+ offset=blockchain_event.offset,
276
+ slot=blockchain_event.slot,
277
+ parent_slot=blockchain_event.parent_slot,
278
+ commitment_level=event_cl,
279
+ dead_error=blockchain_event.dead_error,
280
+ )
281
+ )
282
+
269
283
  if blockchain_event.slot not in self.inflight_slot_shard_download:
270
284
  download_request = FumeDownloadRequest(
271
285
  slot=blockchain_event.slot,
@@ -280,16 +294,6 @@ class FumaroleSM:
280
294
  self.inflight_slot_shard_download[blockchain_event.slot] = (
281
295
  download_progress
282
296
  )
283
- self.blocked_slot_status_update[blockchain_event.slot].append(
284
- FumeSlotStatus(
285
- session_sequence=session_sequence,
286
- offset=blockchain_event.offset,
287
- slot=blockchain_event.slot,
288
- parent_slot=blockchain_event.parent_slot,
289
- commitment_level=event_cl,
290
- dead_error=blockchain_event.dead_error,
291
- )
292
- )
293
297
  return download_request
294
298
  return None
295
299
 
@@ -298,13 +302,10 @@ class FumaroleSM:
298
302
  fume_offset = self.sequence_to_offset.pop(event_seq_number, None)
299
303
  if fume_offset is None:
300
304
  raise ValueError("Event sequence number not found")
301
- heapq.heappush(
302
- self.processed_offset, (-event_seq_number, -fume_offset)
303
- ) # Negate for min-heap
305
+ heapq.heappush(self.processed_offset, (event_seq_number, fume_offset))
304
306
 
305
307
  while self.processed_offset:
306
308
  seq, offset = self.processed_offset[0]
307
- seq, offset = -seq, -offset # Convert back to positive
308
309
  if seq != self.last_processed_fume_sequence + 1:
309
310
  break
310
311
  heapq.heappop(self.processed_offset)
@@ -1,6 +1,5 @@
1
1
  import asyncio
2
2
  import logging
3
- from typing import Any, Coroutine
4
3
 
5
4
  LOGGER = logging.getLogger(__name__)
6
5
 
@@ -22,7 +21,6 @@ class Interval:
22
21
 
23
22
  Args:
24
23
  interval: The interval in seconds.
25
- factory: A factory that returns a coroutine to be run at the interval.
26
24
  """
27
25
  self.interval = interval
28
26
 
@@ -0,0 +1,37 @@
1
+ from collections import OrderedDict
2
+
3
+
4
+ class OrderedSet:
5
+ """
6
+ A simple ordered set implementation that maintains the order of elements.
7
+ """
8
+
9
+ def __init__(self, iterable=None):
10
+ self._data = []
11
+ self.inner: OrderedDict = OrderedDict()
12
+ if iterable is not None:
13
+ for item in iterable:
14
+ self.inner[item] = None
15
+
16
+ def add(self, item):
17
+ self.inner[item] = None
18
+ # Make sure the item is at the end to maintain order
19
+ self.inner.move_to_end(item, last=True)
20
+
21
+ def popfirst(self):
22
+ try:
23
+ self.inner.popitem(last=False)
24
+ except KeyError as e:
25
+ raise KeyError(f"{OrderedDict.__name__} is empty") from e
26
+
27
+ def __contains__(self, item):
28
+ return item in self.inner
29
+
30
+ def __iter__(self):
31
+ return iter(self.inner.keys())
32
+
33
+ def __len__(self):
34
+ return len(self.inner)
35
+
36
+ def __repr__(self):
37
+ return f"OrderedSet({list(self._data)})"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: yellowstone-fumarole-client
3
- Version: 0.1.0rc2
3
+ Version: 0.2.0
4
4
  Summary: Yellowstone Fumarole Python Client
5
5
  Home-page: https://github.com/rpcpool/yellowstone-fumarole
6
6
  Author: Louis-Vincent
@@ -8,14 +8,9 @@ Author-email: louis-vincent@triton.one
8
8
  Requires-Python: >=3.13,<4.0
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Programming Language :: Python :: 3.13
11
- Requires-Dist: asyncio (>=3.4.3,<4.0.0)
12
- Requires-Dist: base58 (>=2.1.1,<3.0.0)
13
- Requires-Dist: click (>=8.1.7,<9.0.0)
14
11
  Requires-Dist: grpcio (>=1.71.1,<2.0.0)
15
- Requires-Dist: protobuf (>=5.29.1,<6.0.0)
12
+ Requires-Dist: protobuf (>=6.32.0,<7.0.0)
16
13
  Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
17
- Requires-Dist: tabulate (>=0.9.0,<0.10.0)
18
- Requires-Dist: toml (>=0.10.2,<0.11.0)
19
14
  Project-URL: Repository, https://github.com/rpcpool/yellowstone-fumarole
20
15
  Description-Content-Type: text/markdown
21
16
 
@@ -83,33 +78,43 @@ async def dragonsmouth_like_session(fumarole_config):
83
78
  session = await client.dragonsmouth_subscribe(
84
79
  consumer_group_name="test",
85
80
  request=SubscribeRequest(
86
- # accounts={"fumarole": SubscribeRequestFilterAccounts()},
81
+ accounts={"fumarole": SubscribeRequestFilterAccounts()},
87
82
  transactions={"fumarole": SubscribeRequestFilterTransactions()},
88
83
  blocks_meta={"fumarole": SubscribeRequestFilterBlocksMeta()},
89
84
  entry={"fumarole": SubscribeRequestFilterEntry()},
90
85
  slots={"fumarole": SubscribeRequestFilterSlots()},
91
86
  ),
92
87
  )
93
- dragonsmouth_source = session.source
94
- handle = session.fumarole_handle
95
- block_map = defaultdict(BlockConstruction)
96
- while True:
97
- tasks = [asyncio.create_task(dragonsmouth_source.get()), handle]
98
- done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
99
- for t in done:
100
- if tasks[0] == t:
101
- result: SubscribeUpdate = t.result()
102
- if result.HasField("block_meta"):
103
- block_meta: SubscribeUpdateBlockMeta = result.block_meta
104
- elif result.HasField("transaction"):
105
- tx: SubscribeUpdateTransaction = result.transaction
106
- elif result.HasField("account"):
107
- account: SubscribeUpdateAccount = result.account
108
- elif result.HasField("entry"):
109
- entry: SubscribeUpdateEntry = result.entry
110
- elif result.HasField("slot"):
111
- result: SubscribeUpdateSlot = result.slot
112
- else:
113
- result = t.result()
114
- raise RuntimeError("failed to get dragonsmouth source: %s" % result)
88
+ async with session:
89
+ dragonsmouth_like_source = session.source
90
+ # result: SubscribeUpdate
91
+ async for result in dragonsmouth_like_source:
92
+ if result.HasField("block_meta"):
93
+ block_meta: SubscribeUpdateBlockMeta = result.block_meta
94
+ elif result.HasField("transaction"):
95
+ tx: SubscribeUpdateTransaction = result.transaction
96
+ elif result.HasField("account"):
97
+ account: SubscribeUpdateAccount = result.account
98
+ elif result.HasField("entry"):
99
+ entry: SubscribeUpdateEntry = result.entry
100
+ elif result.HasField("slot"):
101
+ result: SubscribeUpdateSlot = result.slot
102
+
103
+ # OUTSIDE THE SCOPE, YOU SHOULD NEVER USE `session` again.
104
+ ```
105
+
106
+
107
+ At any point you can get a rough estimate if you are progression through the slot using `DragonsmouthAdapterSession.stats()` call:
108
+
109
+ ```python
110
+
111
+ async with session:
112
+ stats: FumaroleSubscribeStats = session.stats()
113
+ print(f"{stats.log_committed_offset}, {stats.log_committable_offset}, {stats.max_slot_seen}")
115
114
  ```
115
+
116
+ `log_committed_offset` : what have been ACK so for to fumarole remote service.
117
+ `log_committable_offset` : what can be ACK to next commit call.
118
+ `max_slot_seen` : maximum slot seen in the inner fumarole client state -- not yet processed by your code.
119
+
120
+
@@ -0,0 +1,22 @@
1
+ yellowstone_fumarole_client/__init__.py,sha256=-UQcnKGG7D7cTcMMXE98y8nIqc-Xqm0qXA3R0iQ6uks,13381
2
+ yellowstone_fumarole_client/config.py,sha256=aclhCPUy6RO-xtXR9w8otmt1RzFZyFnbF28jk115C2g,1394
3
+ yellowstone_fumarole_client/grpc_connectivity.py,sha256=Sex_x6_Bha0wGD7rRqr-V_slsohX1tDFeiHdqahLJ4Q,6639
4
+ yellowstone_fumarole_client/runtime/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ yellowstone_fumarole_client/runtime/aio.py,sha256=ydcfIP-FpQ4Cgd5drd35Zm9fd_g6qEhpKkdPQHO7gJM,21364
6
+ yellowstone_fumarole_client/runtime/state_machine.py,sha256=d4blPv62UcqZ0HigRK2IXTd_8MeRrRjhclDVpE0PMnQ,12634
7
+ yellowstone_fumarole_client/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ yellowstone_fumarole_client/utils/aio.py,sha256=lm_BNkPiw5CJ6FjDlQUPoCKAqY3eYFAedAJB8mhNbzE,639
9
+ yellowstone_fumarole_client/utils/collections.py,sha256=BO0kADUKIRkpQ-fRpBtmn5rA7Xu4P4MkJ2rsU2FxfBc,979
10
+ yellowstone_fumarole_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ yellowstone_fumarole_proto/fumarole_pb2.py,sha256=aF869yXAjiTE5hqpKatzql42N1saAO0ayVQOJJ8sxVs,14315
12
+ yellowstone_fumarole_proto/fumarole_pb2.pyi,sha256=eJgwihIU5wzJVlEZvYlG_F0vaW-z-axONwOoCQtnI-s,20092
13
+ yellowstone_fumarole_proto/fumarole_pb2_grpc.py,sha256=t-d3wKHd8xbHjct7h0IVmeFN3PTP7WPinYwxgDs6mO0,19117
14
+ yellowstone_fumarole_proto/geyser_pb2.py,sha256=95QrgJGuWll2t7XQiLunY20a9prhK4F1tclzXIQS0I0,20169
15
+ yellowstone_fumarole_proto/geyser_pb2.pyi,sha256=7P9cFmkhK05NhTBlPtzPitzXZeAS_kGBbt6teu2PyGk,27187
16
+ yellowstone_fumarole_proto/geyser_pb2_grpc.py,sha256=JCEz0KM_jg_610HyQI_F1K4kJlRGkGsP192XEDTCoYM,15342
17
+ yellowstone_fumarole_proto/solana_storage_pb2.py,sha256=LS-P5EPyS0n1pO9_U73rA6SPlbGSTEC2qYhuS3skzA8,8443
18
+ yellowstone_fumarole_proto/solana_storage_pb2.pyi,sha256=HivhoN4VEe_W7kB4lc2Un5AeTAv3xiKR_HLI096qmyA,13040
19
+ yellowstone_fumarole_proto/solana_storage_pb2_grpc.py,sha256=-rb9Dr0HXohIrHrnxukYrmUYl6OCVbkQYh2-pCO6740,895
20
+ yellowstone_fumarole_client-0.2.0.dist-info/METADATA,sha256=P90eNzQ2clW8LALfQZfvye9h5YtxZYB1sEdwIo-7uQk,4156
21
+ yellowstone_fumarole_client-0.2.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
22
+ yellowstone_fumarole_client-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,134 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # NO CHECKED-IN PROTOBUF GENCODE
4
+ # source: fumarole.proto
5
+ # Protobuf Python Version: 6.31.1
6
+ """Generated protocol buffer code."""
7
+ from google.protobuf import descriptor as _descriptor
8
+ from google.protobuf import descriptor_pool as _descriptor_pool
9
+ from google.protobuf import runtime_version as _runtime_version
10
+ from google.protobuf import symbol_database as _symbol_database
11
+ from google.protobuf.internal import builder as _builder
12
+ _runtime_version.ValidateProtobufRuntimeVersion(
13
+ _runtime_version.Domain.PUBLIC,
14
+ 6,
15
+ 31,
16
+ 1,
17
+ '',
18
+ 'fumarole.proto'
19
+ )
20
+ # @@protoc_insertion_point(imports)
21
+
22
+ _sym_db = _symbol_database.Default()
23
+
24
+
25
+ import yellowstone_fumarole_proto.geyser_pb2 as geyser__pb2
26
+ try:
27
+ solana__storage__pb2 = geyser__pb2.solana__storage__pb2
28
+ except AttributeError:
29
+ solana__storage__pb2 = geyser__pb2.solana_storage_pb2
30
+
31
+ from yellowstone_fumarole_proto.geyser_pb2 import *
32
+
33
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x66umarole.proto\x12\x08\x66umarole\x1a\x0cgeyser.proto\",\n\x13GetSlotRangeRequest\x12\x15\n\rblockchain_id\x18\x01 \x01(\x0c\"Q\n\x14GetSlotRangeResponse\x12\x15\n\rblockchain_id\x18\x01 \x01(\x0c\x12\x10\n\x08min_slot\x18\x02 \x01(\x03\x12\x10\n\x08max_slot\x18\x03 \x01(\x03\"+\n\x12GetChainTipRequest\x12\x15\n\rblockchain_id\x18\x01 \x01(\x0c\"\xc1\x01\n\x13GetChainTipResponse\x12\x15\n\rblockchain_id\x18\x01 \x01(\x0c\x12W\n\x17shard_to_max_offset_map\x18\x02 \x03(\x0b\x32\x36.fumarole.GetChainTipResponse.ShardToMaxOffsetMapEntry\x1a:\n\x18ShardToMaxOffsetMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x03:\x02\x38\x01\"\x10\n\x0eVersionRequest\"\"\n\x0fVersionResponse\x12\x0f\n\x07version\x18\x01 \x01(\t\":\n\x1bGetConsumerGroupInfoRequest\x12\x1b\n\x13\x63onsumer_group_name\x18\x01 \x01(\t\"9\n\x1a\x44\x65leteConsumerGroupRequest\x12\x1b\n\x13\x63onsumer_group_name\x18\x01 \x01(\t\".\n\x1b\x44\x65leteConsumerGroupResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"\x1b\n\x19ListConsumerGroupsRequest\"R\n\x1aListConsumerGroupsResponse\x12\x34\n\x0f\x63onsumer_groups\x18\x01 \x03(\x0b\x32\x1b.fumarole.ConsumerGroupInfo\"e\n\x11\x43onsumerGroupInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x1b\n\x13\x63onsumer_group_name\x18\x02 \x01(\t\x12\x10\n\x08is_stale\x18\x03 \x01(\x08\x12\x15\n\rblockchain_id\x18\x04 \x01(\x0c\"4\n\x15GetSlotLagInfoRequest\x12\x1b\n\x13\x63onsumer_group_name\x18\x01 \x01(\t\"\xe5\x04\n\x0c\x42lockFilters\x12\x36\n\x08\x61\x63\x63ounts\x18\x01 \x03(\x0b\x32$.fumarole.BlockFilters.AccountsEntry\x12>\n\x0ctransactions\x18\x02 \x03(\x0b\x32(.fumarole.BlockFilters.TransactionsEntry\x12\x34\n\x07\x65ntries\x18\x03 \x03(\x0b\x32#.fumarole.BlockFilters.EntriesEntry\x12;\n\x0b\x62locks_meta\x18\x04 \x03(\x0b\x32&.fumarole.BlockFilters.BlocksMetaEntry\x1aW\n\rAccountsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x35\n\x05value\x18\x02 \x01(\x0b\x32&.geyser.SubscribeRequestFilterAccounts:\x02\x38\x01\x1a_\n\x11TransactionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.geyser.SubscribeRequestFilterTransactions:\x02\x38\x01\x1aS\n\x0c\x45ntriesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x32\n\x05value\x18\x02 \x01(\x0b\x32#.geyser.SubscribeRequestFilterEntry:\x02\x38\x01\x1a[\n\x0f\x42locksMetaEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.geyser.SubscribeRequestFilterBlocksMeta:\x02\x38\x01\"\x95\x01\n\x12\x44ownloadBlockShard\x12\x15\n\rblockchain_id\x18\x01 \x01(\x0c\x12\x11\n\tblock_uid\x18\x02 \x01(\x0c\x12\x11\n\tshard_idx\x18\x03 \x01(\x05\x12\x31\n\x0c\x62lockFilters\x18\x04 \x01(\x0b\x32\x16.fumarole.BlockFiltersH\x00\x88\x01\x01\x42\x0f\n\r_blockFilters\"\x17\n\x04Ping\x12\x0f\n\x07ping_id\x18\x01 \x01(\r\"\x17\n\x04Pong\x12\x0f\n\x07ping_id\x18\x01 \x01(\r\"\x87\x01\n\x0b\x44\x61taCommand\x12<\n\x14\x64ownload_block_shard\x18\x01 \x01(\x0b\x32\x1c.fumarole.DownloadBlockShardH\x00\x12/\n\rfilter_update\x18\x02 \x01(\x0b\x32\x16.fumarole.BlockFiltersH\x00\x42\t\n\x07\x63ommand\"\x1a\n\x18\x42lockShardDownloadFinish\"L\n\rBlockNotFound\x12\x15\n\rblockchain_id\x18\x01 \x01(\x0c\x12\x11\n\tblock_uid\x18\x02 \x01(\x0c\x12\x11\n\tshard_idx\x18\x03 \x01(\x05\"B\n\tDataError\x12,\n\tnot_found\x18\x01 \x01(\x0b\x32\x17.fumarole.BlockNotFoundH\x00\x42\x07\n\x05\x65rror\"\x90\x01\n\x0c\x44\x61taResponse\x12)\n\x06update\x18\x01 \x01(\x0b\x32\x17.geyser.SubscribeUpdateH\x00\x12I\n\x1b\x62lock_shard_download_finish\x18\x02 \x01(\x0b\x32\".fumarole.BlockShardDownloadFinishH\x00\x42\n\n\x08response\"0\n\x0c\x43ommitOffset\x12\x0e\n\x06offset\x18\x01 \x01(\x03\x12\x10\n\x08shard_id\x18\x02 \x01(\x05\"c\n\x15PollBlockchainHistory\x12\x10\n\x08shard_id\x18\x01 \x01(\x05\x12\x11\n\x04\x66rom\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\x03H\x01\x88\x01\x01\x42\x07\n\x05_fromB\x08\n\x06_limit\"\x8f\x02\n\x0f\x42lockchainEvent\x12\x0e\n\x06offset\x18\x01 \x01(\x03\x12\x15\n\rblockchain_id\x18\x02 \x01(\x0c\x12\x11\n\tblock_uid\x18\x03 \x01(\x0c\x12\x12\n\nnum_shards\x18\x04 \x01(\r\x12\x0c\n\x04slot\x18\x05 \x01(\x04\x12\x18\n\x0bparent_slot\x18\x06 \x01(\x04H\x00\x88\x01\x01\x12\x31\n\x10\x63ommitment_level\x18\x07 \x01(\x0e\x32\x17.geyser.CommitmentLevel\x12\x1b\n\x13\x62lockchain_shard_id\x18\x08 \x01(\x05\x12\x17\n\ndead_error\x18\t \x01(\tH\x01\x88\x01\x01\x42\x0e\n\x0c_parent_slotB\r\n\x0b_dead_error\">\n\x11\x42lockchainHistory\x12)\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x19.fumarole.BlockchainEvent\"L\n\x10JoinControlPlane\x12 \n\x13\x63onsumer_group_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x16\n\x14_consumer_group_name\"\xd6\x01\n\x0e\x43ontrolCommand\x12\x32\n\x0cinitial_join\x18\x01 \x01(\x0b\x32\x1a.fumarole.JoinControlPlaneH\x00\x12/\n\rcommit_offset\x18\x02 \x01(\x0b\x32\x16.fumarole.CommitOffsetH\x00\x12\x34\n\tpoll_hist\x18\x03 \x01(\x0b\x32\x1f.fumarole.PollBlockchainHistoryH\x00\x12\x1e\n\x04ping\x18\x04 \x01(\x0b\x32\x0e.fumarole.PingH\x00\x42\t\n\x07\x63ommand\"\xdb\x01\n\x0f\x43ontrolResponse\x12\x33\n\x04init\x18\x01 \x01(\x0b\x32#.fumarole.InitialConsumerGroupStateH\x00\x12\x35\n\rcommit_offset\x18\x02 \x01(\x0b\x32\x1c.fumarole.CommitOffsetResultH\x00\x12\x30\n\tpoll_hist\x18\x03 \x01(\x0b\x32\x1b.fumarole.BlockchainHistoryH\x00\x12\x1e\n\x04pong\x18\x04 \x01(\x0b\x32\x0e.fumarole.PongH\x00\x42\n\n\x08response\"6\n\x12\x43ommitOffsetResult\x12\x0e\n\x06offset\x18\x01 \x01(\x03\x12\x10\n\x08shard_id\x18\x02 \x01(\x05\"\xce\x01\n\x19InitialConsumerGroupState\x12\x15\n\rblockchain_id\x18\x01 \x01(\x0c\x12]\n\x16last_committed_offsets\x18\x02 \x03(\x0b\x32=.fumarole.InitialConsumerGroupState.LastCommittedOffsetsEntry\x1a;\n\x19LastCommittedOffsetsEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x03:\x02\x38\x01\"8\n\x1b\x43reateConsumerGroupResponse\x12\x19\n\x11\x63onsumer_group_id\x18\x01 \x01(\t\"\x9d\x01\n\x1a\x43reateConsumerGroupRequest\x12\x1b\n\x13\x63onsumer_group_name\x18\x01 \x01(\t\x12<\n\x15initial_offset_policy\x18\x02 \x01(\x0e\x32\x1d.fumarole.InitialOffsetPolicy\x12\x16\n\tfrom_slot\x18\x03 \x01(\x04H\x00\x88\x01\x01\x42\x0c\n\n_from_slot*0\n\x13InitialOffsetPolicy\x12\n\n\x06LATEST\x10\x00\x12\r\n\tFROM_SLOT\x10\x01\x32\xd1\x06\n\x08\x46umarole\x12\\\n\x14GetConsumerGroupInfo\x12%.fumarole.GetConsumerGroupInfoRequest\x1a\x1b.fumarole.ConsumerGroupInfo\"\x00\x12\x61\n\x12ListConsumerGroups\x12#.fumarole.ListConsumerGroupsRequest\x1a$.fumarole.ListConsumerGroupsResponse\"\x00\x12\x64\n\x13\x44\x65leteConsumerGroup\x12$.fumarole.DeleteConsumerGroupRequest\x1a%.fumarole.DeleteConsumerGroupResponse\"\x00\x12\x64\n\x13\x43reateConsumerGroup\x12$.fumarole.CreateConsumerGroupRequest\x1a%.fumarole.CreateConsumerGroupResponse\"\x00\x12I\n\rDownloadBlock\x12\x1c.fumarole.DownloadBlockShard\x1a\x16.fumarole.DataResponse\"\x00\x30\x01\x12\x44\n\rSubscribeData\x12\x15.fumarole.DataCommand\x1a\x16.fumarole.DataResponse\"\x00(\x01\x30\x01\x12L\n\x0bGetChainTip\x12\x1c.fumarole.GetChainTipRequest\x1a\x1d.fumarole.GetChainTipResponse\"\x00\x12\x46\n\tSubscribe\x12\x18.fumarole.ControlCommand\x1a\x19.fumarole.ControlResponse\"\x00(\x01\x30\x01\x12@\n\x07Version\x12\x18.fumarole.VersionRequest\x1a\x19.fumarole.VersionResponse\"\x00\x12O\n\x0cGetSlotRange\x12\x1d.fumarole.GetSlotRangeRequest\x1a\x1e.fumarole.GetSlotRangeResponse\"\x00P\x00\x62\x06proto3')
34
+
35
+ _globals = globals()
36
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
37
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'fumarole_pb2', _globals)
38
+ if not _descriptor._USE_C_DESCRIPTORS:
39
+ DESCRIPTOR._loaded_options = None
40
+ _globals['_GETCHAINTIPRESPONSE_SHARDTOMAXOFFSETMAPENTRY']._loaded_options = None
41
+ _globals['_GETCHAINTIPRESPONSE_SHARDTOMAXOFFSETMAPENTRY']._serialized_options = b'8\001'
42
+ _globals['_BLOCKFILTERS_ACCOUNTSENTRY']._loaded_options = None
43
+ _globals['_BLOCKFILTERS_ACCOUNTSENTRY']._serialized_options = b'8\001'
44
+ _globals['_BLOCKFILTERS_TRANSACTIONSENTRY']._loaded_options = None
45
+ _globals['_BLOCKFILTERS_TRANSACTIONSENTRY']._serialized_options = b'8\001'
46
+ _globals['_BLOCKFILTERS_ENTRIESENTRY']._loaded_options = None
47
+ _globals['_BLOCKFILTERS_ENTRIESENTRY']._serialized_options = b'8\001'
48
+ _globals['_BLOCKFILTERS_BLOCKSMETAENTRY']._loaded_options = None
49
+ _globals['_BLOCKFILTERS_BLOCKSMETAENTRY']._serialized_options = b'8\001'
50
+ _globals['_INITIALCONSUMERGROUPSTATE_LASTCOMMITTEDOFFSETSENTRY']._loaded_options = None
51
+ _globals['_INITIALCONSUMERGROUPSTATE_LASTCOMMITTEDOFFSETSENTRY']._serialized_options = b'8\001'
52
+ _globals['_INITIALOFFSETPOLICY']._serialized_start=3669
53
+ _globals['_INITIALOFFSETPOLICY']._serialized_end=3717
54
+ _globals['_GETSLOTRANGEREQUEST']._serialized_start=42
55
+ _globals['_GETSLOTRANGEREQUEST']._serialized_end=86
56
+ _globals['_GETSLOTRANGERESPONSE']._serialized_start=88
57
+ _globals['_GETSLOTRANGERESPONSE']._serialized_end=169
58
+ _globals['_GETCHAINTIPREQUEST']._serialized_start=171
59
+ _globals['_GETCHAINTIPREQUEST']._serialized_end=214
60
+ _globals['_GETCHAINTIPRESPONSE']._serialized_start=217
61
+ _globals['_GETCHAINTIPRESPONSE']._serialized_end=410
62
+ _globals['_GETCHAINTIPRESPONSE_SHARDTOMAXOFFSETMAPENTRY']._serialized_start=352
63
+ _globals['_GETCHAINTIPRESPONSE_SHARDTOMAXOFFSETMAPENTRY']._serialized_end=410
64
+ _globals['_VERSIONREQUEST']._serialized_start=412
65
+ _globals['_VERSIONREQUEST']._serialized_end=428
66
+ _globals['_VERSIONRESPONSE']._serialized_start=430
67
+ _globals['_VERSIONRESPONSE']._serialized_end=464
68
+ _globals['_GETCONSUMERGROUPINFOREQUEST']._serialized_start=466
69
+ _globals['_GETCONSUMERGROUPINFOREQUEST']._serialized_end=524
70
+ _globals['_DELETECONSUMERGROUPREQUEST']._serialized_start=526
71
+ _globals['_DELETECONSUMERGROUPREQUEST']._serialized_end=583
72
+ _globals['_DELETECONSUMERGROUPRESPONSE']._serialized_start=585
73
+ _globals['_DELETECONSUMERGROUPRESPONSE']._serialized_end=631
74
+ _globals['_LISTCONSUMERGROUPSREQUEST']._serialized_start=633
75
+ _globals['_LISTCONSUMERGROUPSREQUEST']._serialized_end=660
76
+ _globals['_LISTCONSUMERGROUPSRESPONSE']._serialized_start=662
77
+ _globals['_LISTCONSUMERGROUPSRESPONSE']._serialized_end=744
78
+ _globals['_CONSUMERGROUPINFO']._serialized_start=746
79
+ _globals['_CONSUMERGROUPINFO']._serialized_end=847
80
+ _globals['_GETSLOTLAGINFOREQUEST']._serialized_start=849
81
+ _globals['_GETSLOTLAGINFOREQUEST']._serialized_end=901
82
+ _globals['_BLOCKFILTERS']._serialized_start=904
83
+ _globals['_BLOCKFILTERS']._serialized_end=1517
84
+ _globals['_BLOCKFILTERS_ACCOUNTSENTRY']._serialized_start=1155
85
+ _globals['_BLOCKFILTERS_ACCOUNTSENTRY']._serialized_end=1242
86
+ _globals['_BLOCKFILTERS_TRANSACTIONSENTRY']._serialized_start=1244
87
+ _globals['_BLOCKFILTERS_TRANSACTIONSENTRY']._serialized_end=1339
88
+ _globals['_BLOCKFILTERS_ENTRIESENTRY']._serialized_start=1341
89
+ _globals['_BLOCKFILTERS_ENTRIESENTRY']._serialized_end=1424
90
+ _globals['_BLOCKFILTERS_BLOCKSMETAENTRY']._serialized_start=1426
91
+ _globals['_BLOCKFILTERS_BLOCKSMETAENTRY']._serialized_end=1517
92
+ _globals['_DOWNLOADBLOCKSHARD']._serialized_start=1520
93
+ _globals['_DOWNLOADBLOCKSHARD']._serialized_end=1669
94
+ _globals['_PING']._serialized_start=1671
95
+ _globals['_PING']._serialized_end=1694
96
+ _globals['_PONG']._serialized_start=1696
97
+ _globals['_PONG']._serialized_end=1719
98
+ _globals['_DATACOMMAND']._serialized_start=1722
99
+ _globals['_DATACOMMAND']._serialized_end=1857
100
+ _globals['_BLOCKSHARDDOWNLOADFINISH']._serialized_start=1859
101
+ _globals['_BLOCKSHARDDOWNLOADFINISH']._serialized_end=1885
102
+ _globals['_BLOCKNOTFOUND']._serialized_start=1887
103
+ _globals['_BLOCKNOTFOUND']._serialized_end=1963
104
+ _globals['_DATAERROR']._serialized_start=1965
105
+ _globals['_DATAERROR']._serialized_end=2031
106
+ _globals['_DATARESPONSE']._serialized_start=2034
107
+ _globals['_DATARESPONSE']._serialized_end=2178
108
+ _globals['_COMMITOFFSET']._serialized_start=2180
109
+ _globals['_COMMITOFFSET']._serialized_end=2228
110
+ _globals['_POLLBLOCKCHAINHISTORY']._serialized_start=2230
111
+ _globals['_POLLBLOCKCHAINHISTORY']._serialized_end=2329
112
+ _globals['_BLOCKCHAINEVENT']._serialized_start=2332
113
+ _globals['_BLOCKCHAINEVENT']._serialized_end=2603
114
+ _globals['_BLOCKCHAINHISTORY']._serialized_start=2605
115
+ _globals['_BLOCKCHAINHISTORY']._serialized_end=2667
116
+ _globals['_JOINCONTROLPLANE']._serialized_start=2669
117
+ _globals['_JOINCONTROLPLANE']._serialized_end=2745
118
+ _globals['_CONTROLCOMMAND']._serialized_start=2748
119
+ _globals['_CONTROLCOMMAND']._serialized_end=2962
120
+ _globals['_CONTROLRESPONSE']._serialized_start=2965
121
+ _globals['_CONTROLRESPONSE']._serialized_end=3184
122
+ _globals['_COMMITOFFSETRESULT']._serialized_start=3186
123
+ _globals['_COMMITOFFSETRESULT']._serialized_end=3240
124
+ _globals['_INITIALCONSUMERGROUPSTATE']._serialized_start=3243
125
+ _globals['_INITIALCONSUMERGROUPSTATE']._serialized_end=3449
126
+ _globals['_INITIALCONSUMERGROUPSTATE_LASTCOMMITTEDOFFSETSENTRY']._serialized_start=3390
127
+ _globals['_INITIALCONSUMERGROUPSTATE_LASTCOMMITTEDOFFSETSENTRY']._serialized_end=3449
128
+ _globals['_CREATECONSUMERGROUPRESPONSE']._serialized_start=3451
129
+ _globals['_CREATECONSUMERGROUPRESPONSE']._serialized_end=3507
130
+ _globals['_CREATECONSUMERGROUPREQUEST']._serialized_start=3510
131
+ _globals['_CREATECONSUMERGROUPREQUEST']._serialized_end=3667
132
+ _globals['_FUMAROLE']._serialized_start=3720
133
+ _globals['_FUMAROLE']._serialized_end=4569
134
+ # @@protoc_insertion_point(module_scope)
@@ -4,7 +4,8 @@ from google.protobuf.internal import containers as _containers
4
4
  from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
5
5
  from google.protobuf import descriptor as _descriptor
6
6
  from google.protobuf import message as _message
7
- from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
7
+ from collections.abc import Iterable as _Iterable, Mapping as _Mapping
8
+ from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union
8
9
  from yellowstone_fumarole_proto.geyser_pb2 import SubscribeRequest as SubscribeRequest
9
10
  from yellowstone_fumarole_proto.geyser_pb2 import SubscribeRequestFilterAccounts as SubscribeRequestFilterAccounts
10
11
  from yellowstone_fumarole_proto.geyser_pb2 import SubscribeRequestFilterAccountsFilter as SubscribeRequestFilterAccountsFilter
@@ -29,6 +30,8 @@ from yellowstone_fumarole_proto.geyser_pb2 import SubscribeUpdateBlockMeta as Su
29
30
  from yellowstone_fumarole_proto.geyser_pb2 import SubscribeUpdateEntry as SubscribeUpdateEntry
30
31
  from yellowstone_fumarole_proto.geyser_pb2 import SubscribeUpdatePing as SubscribeUpdatePing
31
32
  from yellowstone_fumarole_proto.geyser_pb2 import SubscribeUpdatePong as SubscribeUpdatePong
33
+ from yellowstone_fumarole_proto.geyser_pb2 import SubscribeReplayInfoRequest as SubscribeReplayInfoRequest
34
+ from yellowstone_fumarole_proto.geyser_pb2 import SubscribeReplayInfoResponse as SubscribeReplayInfoResponse
32
35
  from yellowstone_fumarole_proto.geyser_pb2 import PingRequest as PingRequest
33
36
  from yellowstone_fumarole_proto.geyser_pb2 import PongResponse as PongResponse
34
37
  from yellowstone_fumarole_proto.geyser_pb2 import GetLatestBlockhashRequest as GetLatestBlockhashRequest
@@ -59,7 +62,46 @@ SLOT_DEAD: _geyser_pb2.SlotStatus
59
62
  class InitialOffsetPolicy(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
60
63
  __slots__ = ()
61
64
  LATEST: _ClassVar[InitialOffsetPolicy]
65
+ FROM_SLOT: _ClassVar[InitialOffsetPolicy]
62
66
  LATEST: InitialOffsetPolicy
67
+ FROM_SLOT: InitialOffsetPolicy
68
+
69
+ class GetSlotRangeRequest(_message.Message):
70
+ __slots__ = ("blockchain_id",)
71
+ BLOCKCHAIN_ID_FIELD_NUMBER: _ClassVar[int]
72
+ blockchain_id: bytes
73
+ def __init__(self, blockchain_id: _Optional[bytes] = ...) -> None: ...
74
+
75
+ class GetSlotRangeResponse(_message.Message):
76
+ __slots__ = ("blockchain_id", "min_slot", "max_slot")
77
+ BLOCKCHAIN_ID_FIELD_NUMBER: _ClassVar[int]
78
+ MIN_SLOT_FIELD_NUMBER: _ClassVar[int]
79
+ MAX_SLOT_FIELD_NUMBER: _ClassVar[int]
80
+ blockchain_id: bytes
81
+ min_slot: int
82
+ max_slot: int
83
+ def __init__(self, blockchain_id: _Optional[bytes] = ..., min_slot: _Optional[int] = ..., max_slot: _Optional[int] = ...) -> None: ...
84
+
85
+ class GetChainTipRequest(_message.Message):
86
+ __slots__ = ("blockchain_id",)
87
+ BLOCKCHAIN_ID_FIELD_NUMBER: _ClassVar[int]
88
+ blockchain_id: bytes
89
+ def __init__(self, blockchain_id: _Optional[bytes] = ...) -> None: ...
90
+
91
+ class GetChainTipResponse(_message.Message):
92
+ __slots__ = ("blockchain_id", "shard_to_max_offset_map")
93
+ class ShardToMaxOffsetMapEntry(_message.Message):
94
+ __slots__ = ("key", "value")
95
+ KEY_FIELD_NUMBER: _ClassVar[int]
96
+ VALUE_FIELD_NUMBER: _ClassVar[int]
97
+ key: int
98
+ value: int
99
+ def __init__(self, key: _Optional[int] = ..., value: _Optional[int] = ...) -> None: ...
100
+ BLOCKCHAIN_ID_FIELD_NUMBER: _ClassVar[int]
101
+ SHARD_TO_MAX_OFFSET_MAP_FIELD_NUMBER: _ClassVar[int]
102
+ blockchain_id: bytes
103
+ shard_to_max_offset_map: _containers.ScalarMap[int, int]
104
+ def __init__(self, blockchain_id: _Optional[bytes] = ..., shard_to_max_offset_map: _Optional[_Mapping[int, int]] = ...) -> None: ...
63
105
 
64
106
  class VersionRequest(_message.Message):
65
107
  __slots__ = ()
@@ -100,14 +142,16 @@ class ListConsumerGroupsResponse(_message.Message):
100
142
  def __init__(self, consumer_groups: _Optional[_Iterable[_Union[ConsumerGroupInfo, _Mapping]]] = ...) -> None: ...
101
143
 
102
144
  class ConsumerGroupInfo(_message.Message):
103
- __slots__ = ("id", "consumer_group_name", "is_stale")
145
+ __slots__ = ("id", "consumer_group_name", "is_stale", "blockchain_id")
104
146
  ID_FIELD_NUMBER: _ClassVar[int]
105
147
  CONSUMER_GROUP_NAME_FIELD_NUMBER: _ClassVar[int]
106
148
  IS_STALE_FIELD_NUMBER: _ClassVar[int]
149
+ BLOCKCHAIN_ID_FIELD_NUMBER: _ClassVar[int]
107
150
  id: str
108
151
  consumer_group_name: str
109
152
  is_stale: bool
110
- def __init__(self, id: _Optional[str] = ..., consumer_group_name: _Optional[str] = ..., is_stale: bool = ...) -> None: ...
153
+ blockchain_id: bytes
154
+ def __init__(self, id: _Optional[str] = ..., consumer_group_name: _Optional[str] = ..., is_stale: bool = ..., blockchain_id: _Optional[bytes] = ...) -> None: ...
111
155
 
112
156
  class GetSlotLagInfoRequest(_message.Message):
113
157
  __slots__ = ("consumer_group_name",)
@@ -320,9 +364,11 @@ class CreateConsumerGroupResponse(_message.Message):
320
364
  def __init__(self, consumer_group_id: _Optional[str] = ...) -> None: ...
321
365
 
322
366
  class CreateConsumerGroupRequest(_message.Message):
323
- __slots__ = ("consumer_group_name", "initial_offset_policy")
367
+ __slots__ = ("consumer_group_name", "initial_offset_policy", "from_slot")
324
368
  CONSUMER_GROUP_NAME_FIELD_NUMBER: _ClassVar[int]
325
369
  INITIAL_OFFSET_POLICY_FIELD_NUMBER: _ClassVar[int]
370
+ FROM_SLOT_FIELD_NUMBER: _ClassVar[int]
326
371
  consumer_group_name: str
327
372
  initial_offset_policy: InitialOffsetPolicy
328
- def __init__(self, consumer_group_name: _Optional[str] = ..., initial_offset_policy: _Optional[_Union[InitialOffsetPolicy, str]] = ...) -> None: ...
373
+ from_slot: int
374
+ def __init__(self, consumer_group_name: _Optional[str] = ..., initial_offset_policy: _Optional[_Union[InitialOffsetPolicy, str]] = ..., from_slot: _Optional[int] = ...) -> None: ...