diff --git a/chia/apis.py b/chia/apis.py deleted file mode 100644 index 3445b7dd15c6..000000000000 --- a/chia/apis.py +++ /dev/null @@ -1,19 +0,0 @@ -from __future__ import annotations - -from chia.farmer.farmer_api import FarmerAPI -from chia.full_node.full_node_api import FullNodeAPI -from chia.harvester.harvester_api import HarvesterAPI -from chia.introducer.introducer_api import IntroducerAPI -from chia.protocols.outbound_message import NodeType -from chia.server.api_protocol import ApiProtocol -from chia.timelord.timelord_api import TimelordAPI -from chia.wallet.wallet_node_api import WalletNodeAPI - -ApiProtocolRegistry: dict[NodeType, type[ApiProtocol]] = { - NodeType.FULL_NODE: FullNodeAPI, - NodeType.WALLET: WalletNodeAPI, - NodeType.INTRODUCER: IntroducerAPI, - NodeType.TIMELORD: TimelordAPI, - NodeType.FARMER: FarmerAPI, - NodeType.HARVESTER: HarvesterAPI, -} diff --git a/chia/apis/__init__.py b/chia/apis/__init__.py new file mode 100644 index 000000000000..c29aa300018c --- /dev/null +++ b/chia/apis/__init__.py @@ -0,0 +1,19 @@ +from __future__ import annotations + +from chia.apis.api_protocol_registry import ApiProtocolRegistry +from chia.apis.farmer_stub import FarmerApiStub +from chia.apis.full_node_stub import FullNodeApiStub +from chia.apis.harvester_stub import HarvesterApiStub +from chia.apis.introducer_stub import IntroducerApiStub +from chia.apis.timelord_stub import TimelordApiStub +from chia.apis.wallet_stub import WalletNodeApiStub + +__all__ = [ + "ApiProtocolRegistry", + "FarmerApiStub", + "FullNodeApiStub", + "HarvesterApiStub", + "IntroducerApiStub", + "TimelordApiStub", + "WalletNodeApiStub", +] diff --git a/chia/apis/api_protocol_registry.py b/chia/apis/api_protocol_registry.py new file mode 100644 index 000000000000..93cd1f890ff0 --- /dev/null +++ b/chia/apis/api_protocol_registry.py @@ -0,0 +1,19 @@ +from __future__ import annotations + +from chia.apis.farmer_stub import FarmerApiStub +from chia.apis.full_node_stub import FullNodeApiStub +from chia.apis.harvester_stub import HarvesterApiStub +from chia.apis.introducer_stub import IntroducerApiStub +from chia.apis.timelord_stub import TimelordApiStub +from chia.apis.wallet_stub import WalletNodeApiStub +from chia.protocols.outbound_message import NodeType +from chia.server.api_protocol import ApiProtocol + +ApiProtocolRegistry: dict[NodeType, type[ApiProtocol]] = { + NodeType.FULL_NODE: FullNodeApiStub, + NodeType.WALLET: WalletNodeApiStub, + NodeType.INTRODUCER: IntroducerApiStub, + NodeType.TIMELORD: TimelordApiStub, + NodeType.FARMER: FarmerApiStub, + NodeType.HARVESTER: HarvesterApiStub, +} diff --git a/chia/apis/farmer_stub.py b/chia/apis/farmer_stub.py new file mode 100644 index 000000000000..45730ca66f8a --- /dev/null +++ b/chia/apis/farmer_stub.py @@ -0,0 +1,90 @@ +from __future__ import annotations + +import logging +from typing import TYPE_CHECKING, ClassVar, Optional, cast + +if TYPE_CHECKING: + from chia.server.api_protocol import ApiProtocol + +# Minimal imports to avoid circular dependencies +from chia.protocols import farmer_protocol, harvester_protocol +from chia.protocols.harvester_protocol import ( + PlotSyncDone, + PlotSyncPathList, + PlotSyncPlotList, + PlotSyncStart, + RespondPlots, + RespondSignatures, +) +from chia.protocols.outbound_message import Message +from chia.server.api_protocol import ApiMetadata +from chia.server.ws_connection import WSChiaConnection + + +class FarmerApiStub: + """Lightweight API stub for FarmerAPI to break circular dependencies.""" + + if TYPE_CHECKING: + _protocol_check: ClassVar[ApiProtocol] = cast("FarmerApiStub", None) + + log: logging.Logger + metadata: ClassVar[ApiMetadata] = ApiMetadata() + + def ready(self) -> bool: + """Check if the farmer is ready.""" + return True + + @metadata.request(peer_required=True) + async def new_proof_of_space( + self, new_proof_of_space: harvester_protocol.NewProofOfSpace, peer: WSChiaConnection + ) -> None: + """Handle new proof of space from harvester.""" + + @metadata.request() + async def respond_signatures(self, response: RespondSignatures) -> None: + """Handle signature response from harvester.""" + + @metadata.request() + async def new_signage_point(self, new_signage_point: farmer_protocol.NewSignagePoint) -> None: + """Handle new signage point from full node.""" + + @metadata.request() + async def request_signed_values(self, full_node_request: farmer_protocol.RequestSignedValues) -> Optional[Message]: + """Handle request for signed values from full node.""" + return None + + @metadata.request(peer_required=True) + async def farming_info(self, request: farmer_protocol.FarmingInfo, peer: WSChiaConnection) -> None: + """Handle farming info from full node.""" + + @metadata.request(peer_required=True) + async def respond_plots(self, _: RespondPlots, peer: WSChiaConnection) -> None: + """Handle respond plots from harvester.""" + + @metadata.request(peer_required=True) + async def plot_sync_start(self, message: PlotSyncStart, peer: WSChiaConnection) -> None: + """Handle plot sync start.""" + + @metadata.request(peer_required=True) + async def plot_sync_loaded(self, message: PlotSyncPlotList, peer: WSChiaConnection) -> None: + """Handle plot sync loaded.""" + + @metadata.request(peer_required=True) + async def plot_sync_removed(self, message: PlotSyncPathList, peer: WSChiaConnection) -> None: + """Handle plot sync removed.""" + + @metadata.request(peer_required=True) + async def plot_sync_invalid(self, message: PlotSyncPathList, peer: WSChiaConnection) -> None: + """Handle plot sync invalid.""" + + @metadata.request(peer_required=True) + async def plot_sync_keys_missing(self, message: PlotSyncPathList, peer: WSChiaConnection) -> None: + """Handle plot sync keys missing.""" + + @metadata.request(peer_required=True) + async def plot_sync_duplicates(self, message: PlotSyncPathList, peer: WSChiaConnection) -> None: + """Handle plot sync duplicates.""" + + @metadata.request(peer_required=True) + async def plot_sync_done(self, message: PlotSyncDone, peer: WSChiaConnection) -> None: + """Handle plot sync done.""" diff --git a/chia/apis/full_node_stub.py b/chia/apis/full_node_stub.py new file mode 100644 index 000000000000..c65dace8e03d --- /dev/null +++ b/chia/apis/full_node_stub.py @@ -0,0 +1,396 @@ +from __future__ import annotations + +import logging +from typing import TYPE_CHECKING, ClassVar, Optional, cast + +if TYPE_CHECKING: + from chia.server.api_protocol import ApiProtocol + +# Minimal imports to avoid circular dependencies +from chia_rs.sized_bytes import bytes32 + +from chia.protocols import ( + farmer_protocol, + full_node_protocol, + introducer_protocol, + timelord_protocol, + wallet_protocol, +) +from chia.protocols.outbound_message import Message +from chia.protocols.protocol_message_types import ProtocolMessageTypes +from chia.server.api_protocol import ApiMetadata +from chia.server.ws_connection import WSChiaConnection + + +class FullNodeApiStub: + """Lightweight API stub for FullNodeAPI to break circular dependencies.""" + + if TYPE_CHECKING: + _protocol_check: ClassVar[ApiProtocol] = cast("FullNodeApiStub", None) + + log: logging.Logger + metadata: ClassVar[ApiMetadata] = ApiMetadata() + + def ready(self) -> bool: + """Check if the full node is ready.""" + return True + + # PEER PROTOCOL + @metadata.request(peer_required=True, reply_types=[ProtocolMessageTypes.respond_peers]) + async def request_peers( + self, _request: full_node_protocol.RequestPeers, peer: WSChiaConnection + ) -> Optional[Message]: + """Handle peer request.""" + return None + + @metadata.request(peer_required=True) + async def respond_peers( + self, request: full_node_protocol.RespondPeers, peer: WSChiaConnection + ) -> Optional[Message]: + """Handle peers response.""" + return None + + @metadata.request(peer_required=True) + async def respond_peers_introducer( + self, request: introducer_protocol.RespondPeersIntroducer, peer: WSChiaConnection + ) -> Optional[Message]: + """Handle peers response from introducer.""" + return None + + # FULL NODE PROTOCOL + @metadata.request(peer_required=True, execute_task=True) + async def new_peak(self, request: full_node_protocol.NewPeak, peer: WSChiaConnection) -> None: + """Handle new peak from peer.""" + + @metadata.request(peer_required=True) + async def new_transaction( + self, transaction: full_node_protocol.NewTransaction, peer: WSChiaConnection + ) -> Optional[Message]: + """Handle new transaction from peer.""" + return None + + @metadata.request(reply_types=[ProtocolMessageTypes.respond_transaction]) + async def request_transaction(self, request: full_node_protocol.RequestTransaction) -> Optional[Message]: + """Handle transaction request.""" + return None + + @metadata.request(peer_required=True, bytes_required=True) + async def respond_transaction( + self, + tx: full_node_protocol.RespondTransaction, + peer: WSChiaConnection, + tx_bytes: bytes = b"", + test: bool = False, + ) -> Optional[Message]: + """Handle transaction response from peer.""" + return None + + @metadata.request(reply_types=[ProtocolMessageTypes.respond_proof_of_weight]) + async def request_proof_of_weight(self, request: full_node_protocol.RequestProofOfWeight) -> Optional[Message]: + """Handle proof of weight request.""" + return None + + @metadata.request() + async def respond_proof_of_weight(self, request: full_node_protocol.RespondProofOfWeight) -> Optional[Message]: + """Handle proof of weight response.""" + return None + + @metadata.request(reply_types=[ProtocolMessageTypes.respond_block, ProtocolMessageTypes.reject_block]) + async def request_block(self, request: full_node_protocol.RequestBlock) -> Optional[Message]: + """Handle block request.""" + return None + + @metadata.request(reply_types=[ProtocolMessageTypes.respond_blocks, ProtocolMessageTypes.reject_blocks]) + async def request_blocks(self, request: full_node_protocol.RequestBlocks) -> Optional[Message]: + """Handle blocks request.""" + return None + + @metadata.request(peer_required=True) + async def reject_block( + self, + request: full_node_protocol.RejectBlock, + peer: WSChiaConnection, + ) -> None: + """Handle block rejection.""" + + @metadata.request(peer_required=True) + async def reject_blocks( + self, + request: full_node_protocol.RejectBlocks, + peer: WSChiaConnection, + ) -> None: + """Handle blocks rejection.""" + + @metadata.request(peer_required=True) + async def respond_blocks( + self, + request: full_node_protocol.RespondBlocks, + peer: WSChiaConnection, + ) -> None: + """Handle blocks response.""" + + @metadata.request(peer_required=True) + async def respond_block( + self, + respond_block: full_node_protocol.RespondBlock, + peer: WSChiaConnection, + ) -> Optional[Message]: + """Handle block response.""" + return None + + @metadata.request() + async def new_unfinished_block( + self, new_unfinished_block: full_node_protocol.NewUnfinishedBlock + ) -> Optional[Message]: + """Handle new unfinished block.""" + return None + + @metadata.request(reply_types=[ProtocolMessageTypes.respond_unfinished_block]) + async def request_unfinished_block( + self, request_unfinished_block: full_node_protocol.RequestUnfinishedBlock + ) -> Optional[Message]: + """Handle unfinished block request.""" + return None + + @metadata.request() + async def new_unfinished_block2( + self, new_unfinished_block: full_node_protocol.NewUnfinishedBlock2 + ) -> Optional[Message]: + """Handle new unfinished block v2.""" + return None + + @metadata.request(reply_types=[ProtocolMessageTypes.respond_unfinished_block]) + async def request_unfinished_block2( + self, request_unfinished_block: full_node_protocol.RequestUnfinishedBlock2 + ) -> Optional[Message]: + """Handle unfinished block v2 request.""" + return None + + @metadata.request(peer_required=True) + async def respond_unfinished_block( + self, + respond_unfinished_block: full_node_protocol.RespondUnfinishedBlock, + peer: WSChiaConnection, + ) -> Optional[Message]: + """Handle unfinished block response.""" + return None + + @metadata.request(peer_required=True) + async def new_signage_point_or_end_of_sub_slot( + self, new_sp: full_node_protocol.NewSignagePointOrEndOfSubSlot, peer: WSChiaConnection + ) -> Optional[Message]: + """Handle new signage point or end of sub slot.""" + return None + + @metadata.request( + reply_types=[ProtocolMessageTypes.respond_signage_point, ProtocolMessageTypes.respond_end_of_sub_slot] + ) + async def request_signage_point_or_end_of_sub_slot( + self, request: full_node_protocol.RequestSignagePointOrEndOfSubSlot + ) -> Optional[Message]: + """Handle signage point or end of sub slot request.""" + return None + + @metadata.request(peer_required=True) + async def respond_signage_point( + self, request: full_node_protocol.RespondSignagePoint, peer: WSChiaConnection + ) -> Optional[Message]: + """Handle signage point response.""" + return None + + @metadata.request(peer_required=True) + async def respond_end_of_sub_slot( + self, request: full_node_protocol.RespondEndOfSubSlot, peer: WSChiaConnection + ) -> Optional[Message]: + """Handle end of sub slot response.""" + return None + + @metadata.request(peer_required=True) + async def request_mempool_transactions( + self, + request: full_node_protocol.RequestMempoolTransactions, + peer: WSChiaConnection, + ) -> Optional[Message]: + """Handle mempool transactions request.""" + return None + + # FARMER PROTOCOL + @metadata.request(peer_required=True) + async def declare_proof_of_space( + self, request: farmer_protocol.DeclareProofOfSpace, peer: WSChiaConnection + ) -> Optional[Message]: + """Handle proof of space declaration from farmer.""" + return None + + @metadata.request(peer_required=True) + async def signed_values( + self, farmer_request: farmer_protocol.SignedValues, peer: WSChiaConnection + ) -> Optional[Message]: + """Handle signed values from farmer.""" + return None + + # TIMELORD PROTOCOL + @metadata.request(peer_required=True) + async def new_infusion_point_vdf( + self, request: timelord_protocol.NewInfusionPointVDF, peer: WSChiaConnection + ) -> Optional[Message]: + """Handle new infusion point VDF from timelord.""" + return None + + @metadata.request(peer_required=True) + async def new_signage_point_vdf( + self, request: timelord_protocol.NewSignagePointVDF, peer: WSChiaConnection + ) -> None: + """Handle new signage point VDF from timelord.""" + + @metadata.request(peer_required=True) + async def new_end_of_sub_slot_vdf( + self, request: timelord_protocol.NewEndOfSubSlotVDF, peer: WSChiaConnection + ) -> Optional[Message]: + """Handle new end of sub slot VDF from timelord.""" + return None + + @metadata.request(bytes_required=True, execute_task=True) + async def respond_compact_proof_of_time( + self, request: timelord_protocol.RespondCompactProofOfTime, request_bytes: bytes = b"" + ) -> None: + """Handle compact proof of time response from timelord.""" + + @metadata.request(peer_required=True, bytes_required=True, execute_task=True) + async def new_compact_vdf( + self, request: full_node_protocol.NewCompactVDF, peer: WSChiaConnection, request_bytes: bytes = b"" + ) -> None: + """Handle new compact VDF.""" + + @metadata.request(peer_required=True, reply_types=[ProtocolMessageTypes.respond_compact_vdf]) + async def request_compact_vdf(self, request: full_node_protocol.RequestCompactVDF, peer: WSChiaConnection) -> None: + """Handle compact VDF request.""" + + @metadata.request(peer_required=True) + async def respond_compact_vdf(self, request: full_node_protocol.RespondCompactVDF, peer: WSChiaConnection) -> None: + """Handle compact VDF response.""" + + # WALLET PROTOCOL + @metadata.request() + async def request_block_header(self, request: wallet_protocol.RequestBlockHeader) -> Optional[Message]: + """Handle block header request from wallet.""" + return None + + @metadata.request() + async def request_additions(self, request: wallet_protocol.RequestAdditions) -> Optional[Message]: + """Handle additions request from wallet.""" + return None + + @metadata.request() + async def request_removals(self, request: wallet_protocol.RequestRemovals) -> Optional[Message]: + """Handle removals request from wallet.""" + return None + + @metadata.request() + async def send_transaction( + self, request: wallet_protocol.SendTransaction, *, test: bool = False + ) -> Optional[Message]: + """Handle transaction send from wallet.""" + return None + + @metadata.request() + async def request_puzzle_solution(self, request: wallet_protocol.RequestPuzzleSolution) -> Optional[Message]: + """Handle puzzle solution request from wallet.""" + return None + + @metadata.request() + async def request_block_headers(self, request: wallet_protocol.RequestBlockHeaders) -> Optional[Message]: + """Handle block headers request from wallet.""" + return None + + @metadata.request() + async def request_header_blocks(self, request: wallet_protocol.RequestHeaderBlocks) -> Optional[Message]: + """Handle header blocks request from wallet (deprecated).""" + return None + + @metadata.request(peer_required=True) + async def register_for_ph_updates( + self, request: wallet_protocol.RegisterForPhUpdates, peer: WSChiaConnection + ) -> Message: + """Handle puzzle hash updates registration from wallet.""" + raise NotImplementedError("Stub method should not be called") + + @metadata.request(peer_required=True) + async def register_for_coin_updates( + self, request: wallet_protocol.RegisterForCoinUpdates, peer: WSChiaConnection + ) -> Message: + """Handle coin updates registration from wallet.""" + raise NotImplementedError("Stub method should not be called") + + @metadata.request() + async def request_children(self, request: wallet_protocol.RequestChildren) -> Optional[Message]: + """Handle children request from wallet.""" + return None + + @metadata.request() + async def request_ses_hashes(self, request: wallet_protocol.RequestSESInfo) -> Message: + """Handle SES hashes request from wallet.""" + raise NotImplementedError("Stub method should not be called") + + @metadata.request(reply_types=[ProtocolMessageTypes.respond_fee_estimates]) + async def request_fee_estimates(self, request: wallet_protocol.RequestFeeEstimates) -> Message: + """Handle fee estimates request from wallet.""" + raise NotImplementedError("Stub method should not be called") + + @metadata.request( + peer_required=True, + reply_types=[ProtocolMessageTypes.respond_remove_puzzle_subscriptions], + ) + async def request_remove_puzzle_subscriptions( + self, request: wallet_protocol.RequestRemovePuzzleSubscriptions, peer: WSChiaConnection + ) -> Message: + """Handle remove puzzle subscriptions request from wallet.""" + raise NotImplementedError("Stub method should not be called") + + @metadata.request( + peer_required=True, + reply_types=[ProtocolMessageTypes.respond_remove_coin_subscriptions], + ) + async def request_remove_coin_subscriptions( + self, request: wallet_protocol.RequestRemoveCoinSubscriptions, peer: WSChiaConnection + ) -> Message: + """Handle remove coin subscriptions request from wallet.""" + raise NotImplementedError("Stub method should not be called") + + @metadata.request(peer_required=True, reply_types=[ProtocolMessageTypes.respond_puzzle_state]) + async def request_puzzle_state( + self, request: wallet_protocol.RequestPuzzleState, peer: WSChiaConnection + ) -> Message: + """Handle puzzle state request from wallet.""" + raise NotImplementedError("Stub method should not be called") + + @metadata.request(peer_required=True, reply_types=[ProtocolMessageTypes.respond_coin_state]) + async def request_coin_state(self, request: wallet_protocol.RequestCoinState, peer: WSChiaConnection) -> Message: + """Handle coin state request from wallet.""" + raise NotImplementedError("Stub method should not be called") + + @metadata.request(reply_types=[ProtocolMessageTypes.respond_cost_info]) + async def request_cost_info(self, _request: wallet_protocol.RequestCostInfo) -> Optional[Message]: + """Handle cost info request from wallet.""" + return None + + # UTILITY METHODS + async def mempool_updates_for_puzzle_hashes( + self, peer: WSChiaConnection, puzzle_hashes: set[bytes32], include_hints: bool + ) -> None: + """Send mempool updates for puzzle hashes.""" + + async def mempool_updates_for_coin_ids(self, peer: WSChiaConnection, coin_ids: set[bytes32]) -> None: + """Send mempool updates for coin IDs.""" + + def max_subscriptions(self, peer: WSChiaConnection) -> int: + """Get maximum subscriptions for peer.""" + return 200000 + + def max_subscribe_response_items(self, peer: WSChiaConnection) -> int: + """Get maximum subscribe response items for peer.""" + return 100000 + + def is_trusted(self, peer: WSChiaConnection) -> bool: + """Check if peer is trusted.""" + return False diff --git a/chia/apis/harvester_stub.py b/chia/apis/harvester_stub.py new file mode 100644 index 000000000000..e8b277c5b69a --- /dev/null +++ b/chia/apis/harvester_stub.py @@ -0,0 +1,55 @@ +from __future__ import annotations + +import logging +from typing import TYPE_CHECKING, ClassVar, Optional, cast + +if TYPE_CHECKING: + from chia.server.api_protocol import ApiProtocol + +# Minimal imports to avoid circular dependencies +from chia.protocols import harvester_protocol +from chia.protocols.harvester_protocol import PlotSyncResponse +from chia.protocols.outbound_message import Message +from chia.protocols.protocol_message_types import ProtocolMessageTypes +from chia.server.api_protocol import ApiMetadata +from chia.server.ws_connection import WSChiaConnection + + +class HarvesterApiStub: + """Lightweight API stub for HarvesterAPI to break circular dependencies.""" + + if TYPE_CHECKING: + _protocol_check: ClassVar[ApiProtocol] = cast("HarvesterApiStub", None) + + log: logging.Logger + metadata: ClassVar[ApiMetadata] = ApiMetadata() + + def ready(self) -> bool: + """Check if the harvester is ready.""" + return True + + @metadata.request(peer_required=True) + async def harvester_handshake( + self, harvester_handshake: harvester_protocol.HarvesterHandshake, peer: WSChiaConnection + ) -> None: + """Handshake between the harvester and farmer.""" + + @metadata.request(peer_required=True) + async def new_signage_point_harvester( + self, new_challenge: harvester_protocol.NewSignagePointHarvester, peer: WSChiaConnection + ) -> None: + """Handle new signage point from farmer.""" + + @metadata.request(reply_types=[ProtocolMessageTypes.respond_signatures]) + async def request_signatures(self, request: harvester_protocol.RequestSignatures) -> Optional[Message]: + """Handle signature request from farmer.""" + return None + + @metadata.request() + async def request_plots(self, _: harvester_protocol.RequestPlots) -> Message: + """Handle request for plot information.""" + raise NotImplementedError("Stub method should not be called") + + @metadata.request() + async def plot_sync_response(self, response: PlotSyncResponse) -> None: + """Handle plot sync response.""" diff --git a/chia/apis/introducer_stub.py b/chia/apis/introducer_stub.py new file mode 100644 index 000000000000..ba86b1750b0a --- /dev/null +++ b/chia/apis/introducer_stub.py @@ -0,0 +1,36 @@ +from __future__ import annotations + +import logging +from typing import TYPE_CHECKING, ClassVar, Optional, cast + +if TYPE_CHECKING: + from chia.server.api_protocol import ApiProtocol + +# Minimal imports to avoid circular dependencies +from chia.protocols.introducer_protocol import RequestPeersIntroducer +from chia.protocols.outbound_message import Message +from chia.server.api_protocol import ApiMetadata +from chia.server.ws_connection import WSChiaConnection + + +class IntroducerApiStub: + """Lightweight API stub for IntroducerAPI to break circular dependencies.""" + + if TYPE_CHECKING: + _protocol_check: ClassVar[ApiProtocol] = cast("IntroducerApiStub", None) + + log: logging.Logger + metadata: ClassVar[ApiMetadata] = ApiMetadata() + + def ready(self) -> bool: + """Check if the introducer is ready.""" + return True + + @metadata.request(peer_required=True) + async def request_peers_introducer( + self, + request: RequestPeersIntroducer, + peer: WSChiaConnection, + ) -> Optional[Message]: + """Handle request for peers from a node.""" + return None diff --git a/chia/apis/timelord_stub.py b/chia/apis/timelord_stub.py new file mode 100644 index 000000000000..1c2a90811d6b --- /dev/null +++ b/chia/apis/timelord_stub.py @@ -0,0 +1,37 @@ +from __future__ import annotations + +import logging +from typing import TYPE_CHECKING, ClassVar, cast + +if TYPE_CHECKING: + from chia.server.api_protocol import ApiProtocol + +# Minimal imports to avoid circular dependencies +from chia.protocols.timelord_protocol import NewPeakTimelord, NewUnfinishedBlockTimelord, RequestCompactProofOfTime +from chia.server.api_protocol import ApiMetadata + + +class TimelordApiStub: + """Lightweight API stub for TimelordAPI to break circular dependencies.""" + + if TYPE_CHECKING: + _protocol_check: ClassVar[ApiProtocol] = cast("TimelordApiStub", None) + + log: logging.Logger + metadata: ClassVar[ApiMetadata] = ApiMetadata() + + def ready(self) -> bool: + """Check if the timelord is ready.""" + return True + + @metadata.request() + async def new_peak_timelord(self, new_peak: NewPeakTimelord) -> None: + """Handle new peak from full node.""" + + @metadata.request() + async def new_unfinished_block_timelord(self, new_unfinished_block: NewUnfinishedBlockTimelord) -> None: + """Handle new unfinished block from full node.""" + + @metadata.request() + async def request_compact_proof_of_time(self, vdf_info: RequestCompactProofOfTime) -> None: + """Handle request for compact proof of time.""" diff --git a/chia/apis/wallet_stub.py b/chia/apis/wallet_stub.py new file mode 100644 index 000000000000..bf098a4c5ffd --- /dev/null +++ b/chia/apis/wallet_stub.py @@ -0,0 +1,140 @@ +from __future__ import annotations + +import logging +from typing import TYPE_CHECKING, ClassVar, cast + +if TYPE_CHECKING: + from chia.server.api_protocol import ApiProtocol + +# Minimal imports to avoid circular dependencies +from chia_rs import RespondToPhUpdates + +from chia.protocols import full_node_protocol, introducer_protocol, wallet_protocol +from chia.protocols.wallet_protocol import ( + CoinStateUpdate, + RejectAdditionsRequest, + RejectBlockHeaders, + RejectHeaderBlocks, + RejectHeaderRequest, + RejectPuzzleSolution, + RejectRemovalsRequest, + RespondAdditions, + RespondBlockHeader, + RespondBlockHeaders, + RespondChildren, + RespondHeaderBlocks, + RespondPuzzleSolution, + RespondRemovals, + RespondSESInfo, + RespondToCoinUpdates, + TransactionAck, +) +from chia.server.api_protocol import ApiMetadata +from chia.server.ws_connection import WSChiaConnection + + +class WalletNodeApiStub: + """Lightweight API stub for WalletNodeAPI to break circular dependencies.""" + + if TYPE_CHECKING: + _protocol_check: ClassVar[ApiProtocol] = cast("WalletNodeApiStub", None) + + log: logging.Logger + metadata: ClassVar[ApiMetadata] = ApiMetadata() + + def ready(self) -> bool: + """Check if the wallet is ready.""" + return True + + @metadata.request(peer_required=True) + async def respond_removals(self, response: RespondRemovals, peer: WSChiaConnection) -> None: + """Handle removals response from full node.""" + + async def reject_removals_request(self, response: RejectRemovalsRequest, peer: WSChiaConnection) -> None: + """Handle reject removals request from full node.""" + + @metadata.request() + async def reject_additions_request(self, response: RejectAdditionsRequest) -> None: + """Handle reject additions request from full node.""" + + @metadata.request(peer_required=True, execute_task=True) + async def new_peak_wallet(self, peak: wallet_protocol.NewPeakWallet, peer: WSChiaConnection) -> None: + """Handle new peak from full node.""" + + @metadata.request() + async def reject_header_request(self, response: RejectHeaderRequest) -> None: + """Handle reject header request from full node.""" + + @metadata.request() + async def respond_block_header(self, response: RespondBlockHeader) -> None: + """Handle block header response from full node.""" + + @metadata.request(peer_required=True) + async def respond_additions(self, response: RespondAdditions, peer: WSChiaConnection) -> None: + """Handle additions response from full node.""" + + @metadata.request() + async def respond_proof_of_weight(self, response: full_node_protocol.RespondProofOfWeight) -> None: + """Handle proof of weight response from full node.""" + + @metadata.request(peer_required=True) + async def transaction_ack(self, ack: TransactionAck, peer: WSChiaConnection) -> None: + """Handle transaction acknowledgment from full node.""" + + @metadata.request(peer_required=True) + async def respond_peers_introducer( + self, request: introducer_protocol.RespondPeersIntroducer, peer: WSChiaConnection + ) -> None: + """Handle peers response from introducer.""" + + @metadata.request(peer_required=True) + async def respond_peers(self, request: full_node_protocol.RespondPeers, peer: WSChiaConnection) -> None: + """Handle peers response from full node.""" + + @metadata.request() + async def respond_puzzle_solution(self, request: RespondPuzzleSolution) -> None: + """Handle puzzle solution response from full node.""" + + @metadata.request() + async def reject_puzzle_solution(self, request: RejectPuzzleSolution) -> None: + """Handle reject puzzle solution from full node.""" + + @metadata.request() + async def respond_header_blocks(self, request: RespondHeaderBlocks) -> None: + """Handle header blocks response from full node.""" + + @metadata.request() + async def respond_block_headers(self, request: RespondBlockHeaders) -> None: + """Handle block headers response from full node.""" + + @metadata.request() + async def reject_header_blocks(self, request: RejectHeaderBlocks) -> None: + """Handle reject header blocks from full node.""" + + @metadata.request() + async def reject_block_headers(self, request: RejectBlockHeaders) -> None: + """Handle reject block headers from full node.""" + + @metadata.request(peer_required=True, execute_task=True) + async def coin_state_update(self, request: CoinStateUpdate, peer: WSChiaConnection) -> None: + """Handle coin state update from full node.""" + + @metadata.request() # type: ignore[type-var] + async def respond_to_ph_updates(self, request: RespondToPhUpdates) -> None: + """Handle puzzle hash updates response from full node.""" + + @metadata.request() + async def respond_to_coin_updates(self, request: RespondToCoinUpdates) -> None: + """Handle coin updates response from full node.""" + + @metadata.request() + async def respond_children(self, request: RespondChildren) -> None: + """Handle children response from full node.""" + + @metadata.request() + async def respond_ses_hashes(self, request: RespondSESInfo) -> None: + """Handle SES hashes response from full node.""" + + @metadata.request() + async def respond_blocks(self, request: full_node_protocol.RespondBlocks) -> None: + """Handle blocks response from full node.""" diff --git a/tach.toml b/tach.toml index e05edea91695..3f4f2d9d6b5d 100644 --- a/tach.toml +++ b/tach.toml @@ -88,12 +88,6 @@ depends_on = [ [[modules]] path = "chia.apis" depends_on = [ - { path = "chia.harvester", deprecated = false }, - { path = "chia.farmer", deprecated = false }, - { path = "chia.introducer", deprecated = false }, - { path = "chia.wallet", deprecated = false }, - { path = "chia.full_node", deprecated = false }, - { path = "chia.timelord", deprecated = false }, { path = "chia.protocols", deprecated = false }, { path = "chia.server", deprecated = false }, ]