Skip to content

[v10] Unify extrinsic return values by introducing an ExtrinsicResponse class#3053

Merged
basfroman merged 42 commits intoSDKv10from
feat/roman/add-extrinsic-response
Sep 9, 2025
Merged

[v10] Unify extrinsic return values by introducing an ExtrinsicResponse class#3053
basfroman merged 42 commits intoSDKv10from
feat/roman/add-extrinsic-response

Conversation

@basfroman
Copy link
Collaborator

@basfroman basfroman commented Sep 9, 2025

A new class ExtrinsicResponse has been implemented that completely inherits the behavior of extrinsic responses in previous SDK versions, but at the same time expands the capabilities, contains new data that SDK users will use for more detailed verification or checking of responses.

@dataclass
class ExtrinsicResponse:
    """
    A standardized response container for handling the extrinsic results submissions and related operations in the SDK.

    This class is designed to give developers a consistent way to represent the outcome of an extrinsic call — whether
    it succeeded or failed — along with useful metadata for debugging, logging, or higher-level business logic.

    The object also implements tuple-like behavior:
      * Iteration yields ``(success, message)``.
      * Indexing is supported: ``response[0] -> success``, ``response[1] -> message``.
      * ``len(response)`` returns 2.

    Attributes:
        success: Indicates if the extrinsic execution was successful.
        message: A status or informational message returned from the execution (e.g., "Successfully registered subnet").
        error: Captures the underlying exception if the extrinsic failed, otherwise `None`.
        data: Arbitrary data returned from the extrinsic, such as decoded events, or extra context.
        extrinsic_function: The name of the SDK extrinsic function that was executed (e.g. "register_subnet_extrinsic").
        extrinsic: The raw extrinsic object used in the call, if available.

    Example:
        import bittensor as bt

        subtensor = bt.SubtensorApi("local")
        wallet = bt.Wallet("alice")

        response = subtensor.subnets.register_subnet(alice_wallet)
        print(response)

        ExtrinsicResponse:
            success: True
            message: Successfully registered subnet
            error: None
            extrinsic_function: register_subnet_extrinsic
            extrinsic: {'account_id': '0xd43593c715fdd31c...

        success, message = response
        print(success, message)

        True Successfully registered subnet

        print(response[0])
        True
        print(response[1])
        'Successfully registered subnet'
    """

    success: bool = True
    message: str = None
    error: Optional[Exception] = None
    data: Optional[Any] = None
    extrinsic_function: Optional[str] = None
    extrinsic: Optional[GenericExtrinsic] = None

    def __iter__(self):
        yield self.success
        yield self.message

    def __str__(self):
        return str(
            f"ExtrinsicResponse:"
            f"\n\tsuccess: {self.success}"
            f"\n\tmessage: {self.message}"
            f"\n\terror: {self.error}"
            f"\n\textrinsic_function: {self.extrinsic_function}"
            f"\n\textrinsic: {self.extrinsic}"
        )

    def __repr__(self):
        return repr((self.success, self.message))

    def __eq__(self, other: Any) -> bool:
        if isinstance(other, tuple):
            return (self.success, self.message) == other
        if isinstance(other, ExtrinsicResponse):
            return (
                self.success == other.success
                and self.message == other.message
                and self.error == other.error
                and self.extrinsic_function == other.extrinsic_function
                and self.extrinsic == other.extrinsic
            )
        return super().__eq__(other)

    def __getitem__(self, index: int) -> Any:
        if index == 0:
            return self.success
        elif index == 1:
            return self.message
        else:
            raise IndexError(
                "ExtrinsicResponse only supports indices 0 (success) and 1 (message)."
            )

    def __len__(self):
        return 2

Roman added 30 commits September 5, 2025 16:34
…move_liquidity_extrinsic` + `toggle_user_liquidity_extrinsic`
…xtrinsic`, + `set_subnet_identity_extrinsic` + related subtensor calls + fixed tests
@basfroman basfroman self-assigned this Sep 9, 2025
@basfroman basfroman added the feature new feature added label Sep 9, 2025
@basfroman basfroman mentioned this pull request Sep 4, 2025
@basfroman basfroman changed the title [WIP] [v10] Unify extrinsic return values by introducing an ExtrinsicResponse class [v10] Unify extrinsic return values by introducing an ExtrinsicResponse class Sep 9, 2025
@basfroman basfroman requested a review from a team September 9, 2025 05:05
Copy link
Contributor

@ibraheem-abe ibraheem-abe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good.

One qq: Few important calls (like committing weights etc) had exception handling which we removed.

Do u think end behaviour will stay the same?

@basfroman
Copy link
Collaborator Author

Overall looks good.

One qq: Few important calls (like committing weights etc) had exception handling which we removed.

Do u think end behaviour will stay the same?

Yes. The same. But I want to add wrapper try... except... for all extrinsics and raise an error ifraise_error=True is passed and extrinsic or some logic inside (e.g. unlock wallet) raised the error.
This is in my TODO for one of the next PRs.

@basfroman basfroman merged commit 596cefa into SDKv10 Sep 9, 2025
331 checks passed
@basfroman basfroman deleted the feat/roman/add-extrinsic-response branch September 9, 2025 21:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature new feature added

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants