Skip to content

Commit fd22870

Browse files
authored
Merge pull request #2862 from opentensor/feat/roman/subtensor-api
Introduce `SubtensorApi` interface for SDK
2 parents 8f01580 + ff9c533 commit fd22870

File tree

17 files changed

+813
-22
lines changed

17 files changed

+813
-22
lines changed

bittensor/core/async_subtensor.py

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import numpy as np
1010
import scalecodec
1111
from async_substrate_interface import AsyncSubstrateInterface
12+
from async_substrate_interface.substrate_addons import RetryAsyncSubstrate
1213
from bittensor_drand import get_encrypted_commitment
1314
from bittensor_wallet.utils import SS58_FORMAT
1415
from numpy.typing import NDArray
@@ -114,17 +115,21 @@ def __init__(
114115
self,
115116
network: Optional[str] = None,
116117
config: Optional["Config"] = None,
117-
_mock: bool = False,
118118
log_verbose: bool = False,
119+
fallback_chains: Optional[list[str]] = None,
120+
retry_forever: bool = False,
121+
_mock: bool = False,
119122
):
120123
"""
121124
Initializes an instance of the AsyncSubtensor class.
122125
123126
Arguments:
124127
network (str): The network name or type to connect to.
125128
config (Optional[Config]): Configuration object for the AsyncSubtensor instance.
126-
_mock: Whether this is a mock instance. Mainly just for use in testing.
127129
log_verbose (bool): Enables or disables verbose logging.
130+
fallback_chains (list): List of fallback chains endpoints to use if no network is specified. Defaults to `None`.
131+
retry_forever (bool): Whether to retry forever on connection errors. Defaults to `False`.
132+
_mock: Whether this is a mock instance. Mainly just for use in testing.
128133
129134
Raises:
130135
Any exceptions raised during the setup, configuration, or connection process.
@@ -143,13 +148,8 @@ def __init__(
143148
f"Connecting to network: [blue]{self.network}[/blue], "
144149
f"chain_endpoint: [blue]{self.chain_endpoint}[/blue]..."
145150
)
146-
self.substrate = AsyncSubstrateInterface(
147-
url=self.chain_endpoint,
148-
ss58_format=SS58_FORMAT,
149-
type_registry=TYPE_REGISTRY,
150-
use_remote_preset=True,
151-
chain_name="Bittensor",
152-
_mock=_mock,
151+
self.substrate = self._get_substrate(
152+
fallback_chains=fallback_chains, retry_forever=retry_forever, _mock=_mock
153153
)
154154
if self.log_verbose:
155155
logging.info(
@@ -283,6 +283,42 @@ async def get_hyperparameter(
283283

284284
return getattr(result, "value", result)
285285

286+
def _get_substrate(
287+
self,
288+
fallback_chains: Optional[list[str]] = None,
289+
retry_forever: bool = False,
290+
_mock: bool = False,
291+
) -> Union[AsyncSubstrateInterface, RetryAsyncSubstrate]:
292+
"""Creates the Substrate instance based on provided arguments.
293+
294+
Arguments:
295+
fallback_chains (list): List of fallback chains endpoints to use if no network is specified. Defaults to `None`.
296+
retry_forever (bool): Whether to retry forever on connection errors. Defaults to `False`.
297+
_mock: Whether this is a mock instance. Mainly just for use in testing.
298+
299+
Returns:
300+
the instance of the SubstrateInterface or RetrySyncSubstrate class.
301+
"""
302+
if fallback_chains or retry_forever:
303+
return RetryAsyncSubstrate(
304+
url=self.chain_endpoint,
305+
fallback_chains=fallback_chains,
306+
ss58_format=SS58_FORMAT,
307+
type_registry=TYPE_REGISTRY,
308+
retry_forever=retry_forever,
309+
use_remote_preset=True,
310+
chain_name="Bittensor",
311+
_mock=_mock,
312+
)
313+
return AsyncSubstrateInterface(
314+
url=self.chain_endpoint,
315+
ss58_format=SS58_FORMAT,
316+
type_registry=TYPE_REGISTRY,
317+
use_remote_preset=True,
318+
chain_name="Bittensor",
319+
_mock=_mock,
320+
)
321+
286322
# Subtensor queries ===========================================================================================
287323

288324
async def query_constant(

bittensor/core/subtensor.py

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import numpy as np
77
import scalecodec
88
from async_substrate_interface.errors import SubstrateRequestException
9+
from async_substrate_interface.substrate_addons import RetrySyncSubstrate
910
from async_substrate_interface.sync_substrate import SubstrateInterface
1011
from async_substrate_interface.types import ScaleObj
1112
from bittensor_drand import get_encrypted_commitment
@@ -116,17 +117,21 @@ def __init__(
116117
self,
117118
network: Optional[str] = None,
118119
config: Optional["Config"] = None,
119-
_mock: bool = False,
120120
log_verbose: bool = False,
121+
fallback_chains: Optional[list[str]] = None,
122+
retry_forever: bool = False,
123+
_mock: bool = False,
121124
):
122125
"""
123126
Initializes an instance of the Subtensor class.
124127
125128
Arguments:
126129
network (str): The network name or type to connect to.
127130
config (Optional[Config]): Configuration object for the AsyncSubtensor instance.
128-
_mock: Whether this is a mock instance. Mainly just for use in testing.
129131
log_verbose (bool): Enables or disables verbose logging.
132+
fallback_chains (list): List of fallback chains endpoints to use if no network is specified. Defaults to `None`.
133+
retry_forever (bool): Whether to retry forever on connection errors. Defaults to `False`.
134+
_mock: Whether this is a mock instance. Mainly just for use in testing.
130135
131136
Raises:
132137
Any exceptions raised during the setup, configuration, or connection process.
@@ -143,13 +148,8 @@ def __init__(
143148
f"Connecting to network: [blue]{self.network}[/blue], "
144149
f"chain_endpoint: [blue]{self.chain_endpoint}[/blue]> ..."
145150
)
146-
self.substrate = SubstrateInterface(
147-
url=self.chain_endpoint,
148-
ss58_format=SS58_FORMAT,
149-
type_registry=TYPE_REGISTRY,
150-
use_remote_preset=True,
151-
chain_name="Bittensor",
152-
_mock=_mock,
151+
self.substrate = self._get_substrate(
152+
fallback_chains=fallback_chains, retry_forever=retry_forever, _mock=_mock
153153
)
154154
if self.log_verbose:
155155
logging.info(
@@ -163,11 +163,45 @@ def __exit__(self, exc_type, exc_val, exc_tb):
163163
self.close()
164164

165165
def close(self):
166-
"""
167-
Closes the websocket connection
168-
"""
166+
"""Closes the websocket connection."""
169167
self.substrate.close()
170168

169+
def _get_substrate(
170+
self,
171+
fallback_chains: Optional[list[str]] = None,
172+
retry_forever: bool = False,
173+
_mock: bool = False,
174+
) -> Union[SubstrateInterface, RetrySyncSubstrate]:
175+
"""Creates the Substrate instance based on provided arguments.
176+
177+
Arguments:
178+
fallback_chains (list): List of fallback chains endpoints to use if no network is specified. Defaults to `None`.
179+
retry_forever (bool): Whether to retry forever on connection errors. Defaults to `False`.
180+
_mock: Whether this is a mock instance. Mainly just for use in testing.
181+
182+
Returns:
183+
the instance of the SubstrateInterface or RetrySyncSubstrate class.
184+
"""
185+
if fallback_chains or retry_forever:
186+
return RetrySyncSubstrate(
187+
url=self.chain_endpoint,
188+
ss58_format=SS58_FORMAT,
189+
type_registry=TYPE_REGISTRY,
190+
use_remote_preset=True,
191+
chain_name="Bittensor",
192+
fallback_chains=fallback_chains,
193+
retry_forever=retry_forever,
194+
_mock=_mock,
195+
)
196+
return SubstrateInterface(
197+
url=self.chain_endpoint,
198+
ss58_format=SS58_FORMAT,
199+
type_registry=TYPE_REGISTRY,
200+
use_remote_preset=True,
201+
chain_name="Bittensor",
202+
_mock=_mock,
203+
)
204+
171205
# Subtensor queries ===========================================================================================
172206

173207
def query_constant(

0 commit comments

Comments
 (0)