diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 01b7da6b4d62..0195abf7ddeb 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -13,6 +13,13 @@ repos:
entry: ./activated.py python chia/_tests/build-init-files.py -v --root .
language: system
pass_filenames: false
+ - repo: local
+ hooks:
+ - id: generate-service-peer-schemas
+ name: Generate service peer schemas
+ entry: ./activated.py chia dev generate-service-peer-schemas
+ language: system
+ pass_filenames: false
- repo: local
hooks:
- id: ruff_format
diff --git a/chia/apis.py b/chia/apis.py
deleted file mode 100644
index f30eac27fafb..000000000000
--- a/chia/apis.py
+++ /dev/null
@@ -1,21 +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.solver.solver_api import SolverAPI
-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,
- NodeType.SOLVER: SolverAPI,
-}
diff --git a/chia/apis/__init__.py b/chia/apis/__init__.py
new file mode 100644
index 000000000000..2c2700020901
--- /dev/null
+++ b/chia/apis/__init__.py
@@ -0,0 +1,23 @@
+from __future__ import annotations
+
+from chia.apis.data_layer_api_schema import DataLayerApiSchema
+from chia.apis.farmer_api_schema import FarmerApiSchema
+from chia.apis.full_node_api_schema import FullNodeApiSchema
+from chia.apis.harvester_api_schema import HarvesterApiSchema
+from chia.apis.introducer_api_schema import IntroducerApiSchema
+from chia.apis.solver_api_schema import SolverApiSchema
+from chia.apis.timelord_api_schema import TimelordApiSchema
+from chia.apis.wallet_api_schema import WalletNodeApiSchema
+from chia.protocols.outbound_message import NodeType
+from chia.server.api_protocol import ApiSchemaProtocol
+
+ApiProtocolRegistry: dict[NodeType, type[ApiSchemaProtocol]] = {
+ NodeType.DATA_LAYER: DataLayerApiSchema,
+ NodeType.FARMER: FarmerApiSchema,
+ NodeType.FULL_NODE: FullNodeApiSchema,
+ NodeType.HARVESTER: HarvesterApiSchema,
+ NodeType.INTRODUCER: IntroducerApiSchema,
+ NodeType.SOLVER: SolverApiSchema,
+ NodeType.TIMELORD: TimelordApiSchema,
+ NodeType.WALLET: WalletNodeApiSchema,
+}
diff --git a/chia/apis/data_layer_api_schema.py b/chia/apis/data_layer_api_schema.py
new file mode 100644
index 000000000000..71e8b7086e4e
--- /dev/null
+++ b/chia/apis/data_layer_api_schema.py
@@ -0,0 +1,12 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, ClassVar, cast
+
+from chia.server.api_protocol import ApiMetadata, ApiSchemaProtocol
+
+
+class DataLayerApiSchema:
+ if TYPE_CHECKING:
+ _protocol_check: ApiSchemaProtocol = cast("DataLayerApiSchema", None)
+
+ metadata: ClassVar[ApiMetadata] = ApiMetadata()
diff --git a/chia/apis/farmer_api_schema.py b/chia/apis/farmer_api_schema.py
new file mode 100644
index 000000000000..5bf5b284baac
--- /dev/null
+++ b/chia/apis/farmer_api_schema.py
@@ -0,0 +1,72 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, ClassVar, Optional, cast
+
+from chia.protocols import farmer_protocol, harvester_protocol
+from chia.protocols.harvester_protocol import (
+ PartialProofsData,
+ PlotSyncDone,
+ PlotSyncPathList,
+ PlotSyncPlotList,
+ PlotSyncStart,
+)
+from chia.protocols.outbound_message import Message
+from chia.protocols.solver_protocol import SolverResponse
+from chia.server.api_protocol import ApiMetadata, ApiSchemaProtocol
+from chia.server.ws_connection import WSChiaConnection
+
+
+class FarmerApiSchema:
+ if TYPE_CHECKING:
+ _protocol_check: ApiSchemaProtocol = cast("FarmerApiSchema", None)
+
+ metadata: ClassVar[ApiMetadata] = ApiMetadata()
+
+ @metadata.request(peer_required=True)
+ async def new_proof_of_space(
+ self, new_proof_of_space: harvester_protocol.NewProofOfSpace, peer: WSChiaConnection
+ ) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def partial_proofs(self, partial_proof_data: PartialProofsData, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request()
+ async def solution_response(self, response: SolverResponse, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request()
+ async def respond_signatures(self, response: harvester_protocol.RespondSignatures) -> None: ...
+
+ @metadata.request()
+ async def new_signage_point(self, new_signage_point: farmer_protocol.NewSignagePoint) -> None: ...
+
+ @metadata.request()
+ async def request_signed_values(
+ self, full_node_request: farmer_protocol.RequestSignedValues
+ ) -> Optional[Message]: ...
+
+ @metadata.request(peer_required=True)
+ async def farming_info(self, request: farmer_protocol.FarmingInfo, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def respond_plots(self, _: harvester_protocol.RespondPlots, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def plot_sync_start(self, message: PlotSyncStart, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def plot_sync_loaded(self, message: PlotSyncPlotList, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def plot_sync_removed(self, message: PlotSyncPathList, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def plot_sync_invalid(self, message: PlotSyncPathList, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def plot_sync_keys_missing(self, message: PlotSyncPathList, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def plot_sync_duplicates(self, message: PlotSyncPathList, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def plot_sync_done(self, message: PlotSyncDone, peer: WSChiaConnection) -> None: ...
diff --git a/chia/apis/full_node_api_schema.py b/chia/apis/full_node_api_schema.py
new file mode 100644
index 000000000000..7eed70b330a0
--- /dev/null
+++ b/chia/apis/full_node_api_schema.py
@@ -0,0 +1,264 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, ClassVar, Optional, cast
+
+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, ApiSchemaProtocol
+from chia.server.ws_connection import WSChiaConnection
+
+
+class FullNodeApiSchema:
+ if TYPE_CHECKING:
+ _protocol_check: ApiSchemaProtocol = cast("FullNodeApiSchema", None)
+
+ metadata: ClassVar[ApiMetadata] = ApiMetadata()
+
+ @metadata.request(peer_required=True, reply_types=[ProtocolMessageTypes.respond_peers])
+ async def request_peers(
+ self, _request: full_node_protocol.RequestPeers, peer: WSChiaConnection
+ ) -> Optional[Message]: ...
+
+ @metadata.request(peer_required=True)
+ async def respond_peers(
+ self, request: full_node_protocol.RespondPeers, peer: WSChiaConnection
+ ) -> Optional[Message]: ...
+
+ @metadata.request(peer_required=True)
+ async def respond_peers_introducer(
+ self, request: introducer_protocol.RespondPeersIntroducer, peer: WSChiaConnection
+ ) -> Optional[Message]: ...
+
+ @metadata.request(peer_required=True, execute_task=True)
+ async def new_peak(self, request: full_node_protocol.NewPeak, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def new_transaction(
+ self, transaction: full_node_protocol.NewTransaction, peer: WSChiaConnection
+ ) -> Optional[Message]: ...
+
+ @metadata.request(reply_types=[ProtocolMessageTypes.respond_transaction])
+ async def request_transaction(self, request: full_node_protocol.RequestTransaction) -> Optional[Message]: ...
+
+ @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]: ...
+
+ @metadata.request(reply_types=[ProtocolMessageTypes.respond_proof_of_weight])
+ async def request_proof_of_weight(self, request: full_node_protocol.RequestProofOfWeight) -> Optional[Message]: ...
+
+ @metadata.request()
+ async def respond_proof_of_weight(self, request: full_node_protocol.RespondProofOfWeight) -> Optional[Message]: ...
+
+ @metadata.request(reply_types=[ProtocolMessageTypes.respond_block, ProtocolMessageTypes.reject_block])
+ async def request_block(self, request: full_node_protocol.RequestBlock) -> Optional[Message]: ...
+
+ @metadata.request(reply_types=[ProtocolMessageTypes.respond_blocks, ProtocolMessageTypes.reject_blocks])
+ async def request_blocks(self, request: full_node_protocol.RequestBlocks) -> Optional[Message]: ...
+
+ @metadata.request(peer_required=True)
+ async def reject_block(
+ self,
+ request: full_node_protocol.RejectBlock,
+ peer: WSChiaConnection,
+ ) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def reject_blocks(
+ self,
+ request: full_node_protocol.RejectBlocks,
+ peer: WSChiaConnection,
+ ) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def respond_blocks(
+ self,
+ request: full_node_protocol.RespondBlocks,
+ peer: WSChiaConnection,
+ ) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def respond_block(
+ self,
+ respond_block: full_node_protocol.RespondBlock,
+ peer: WSChiaConnection,
+ ) -> Optional[Message]: ...
+
+ @metadata.request()
+ async def new_unfinished_block(
+ self, new_unfinished_block: full_node_protocol.NewUnfinishedBlock
+ ) -> Optional[Message]: ...
+
+ @metadata.request(reply_types=[ProtocolMessageTypes.respond_unfinished_block])
+ async def request_unfinished_block(
+ self, request_unfinished_block: full_node_protocol.RequestUnfinishedBlock
+ ) -> Optional[Message]: ...
+
+ @metadata.request()
+ async def new_unfinished_block2(
+ self, new_unfinished_block: full_node_protocol.NewUnfinishedBlock2
+ ) -> Optional[Message]: ...
+
+ @metadata.request(reply_types=[ProtocolMessageTypes.respond_unfinished_block])
+ async def request_unfinished_block2(
+ self, request_unfinished_block: full_node_protocol.RequestUnfinishedBlock2
+ ) -> Optional[Message]: ...
+
+ @metadata.request(peer_required=True)
+ async def respond_unfinished_block(
+ self,
+ respond_unfinished_block: full_node_protocol.RespondUnfinishedBlock,
+ peer: WSChiaConnection,
+ ) -> Optional[Message]: ...
+
+ @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]: ...
+
+ @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]: ...
+
+ @metadata.request(peer_required=True)
+ async def respond_signage_point(
+ self, request: full_node_protocol.RespondSignagePoint, peer: WSChiaConnection
+ ) -> Optional[Message]: ...
+
+ @metadata.request(peer_required=True)
+ async def respond_end_of_sub_slot(
+ self, request: full_node_protocol.RespondEndOfSubSlot, peer: WSChiaConnection
+ ) -> Optional[Message]: ...
+
+ @metadata.request(peer_required=True)
+ async def request_mempool_transactions(
+ self,
+ request: full_node_protocol.RequestMempoolTransactions,
+ peer: WSChiaConnection,
+ ) -> Optional[Message]: ...
+
+ @metadata.request(peer_required=True)
+ async def declare_proof_of_space(
+ self, request: farmer_protocol.DeclareProofOfSpace, peer: WSChiaConnection
+ ) -> Optional[Message]: ...
+
+ @metadata.request(peer_required=True)
+ async def signed_values(
+ self, farmer_request: farmer_protocol.SignedValues, peer: WSChiaConnection
+ ) -> Optional[Message]: ...
+
+ @metadata.request(peer_required=True)
+ async def new_infusion_point_vdf(
+ self, request: timelord_protocol.NewInfusionPointVDF, peer: WSChiaConnection
+ ) -> Optional[Message]: ...
+
+ @metadata.request(peer_required=True)
+ async def new_signage_point_vdf(
+ self, request: timelord_protocol.NewSignagePointVDF, peer: WSChiaConnection
+ ) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def new_end_of_sub_slot_vdf(
+ self, request: timelord_protocol.NewEndOfSubSlotVDF, peer: WSChiaConnection
+ ) -> Optional[Message]: ...
+
+ @metadata.request()
+ async def request_block_header(self, request: wallet_protocol.RequestBlockHeader) -> Optional[Message]: ...
+
+ @metadata.request()
+ async def request_additions(self, request: wallet_protocol.RequestAdditions) -> Optional[Message]: ...
+
+ @metadata.request()
+ async def request_removals(self, request: wallet_protocol.RequestRemovals) -> Optional[Message]: ...
+
+ @metadata.request()
+ async def send_transaction(
+ self, request: wallet_protocol.SendTransaction, *, test: bool = False
+ ) -> Optional[Message]: ...
+
+ @metadata.request()
+ async def request_puzzle_solution(self, request: wallet_protocol.RequestPuzzleSolution) -> Optional[Message]: ...
+
+ @metadata.request()
+ async def request_block_headers(self, request: wallet_protocol.RequestBlockHeaders) -> Optional[Message]: ...
+
+ @metadata.request()
+ async def request_header_blocks(self, request: wallet_protocol.RequestHeaderBlocks) -> Optional[Message]: ...
+
+ @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: ...
+
+ @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: ...
+
+ @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: ...
+
+ @metadata.request(peer_required=True)
+ async def respond_compact_vdf(
+ self, request: full_node_protocol.RespondCompactVDF, peer: WSChiaConnection
+ ) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def register_for_ph_updates( # type: ignore[empty-body]
+ self, request: wallet_protocol.RegisterForPhUpdates, peer: WSChiaConnection
+ ) -> Message: ...
+
+ @metadata.request(peer_required=True)
+ async def register_for_coin_updates( # type: ignore[empty-body]
+ self, request: wallet_protocol.RegisterForCoinUpdates, peer: WSChiaConnection
+ ) -> Message: ...
+
+ @metadata.request()
+ async def request_children(self, request: wallet_protocol.RequestChildren) -> Optional[Message]: ...
+
+ @metadata.request()
+ async def request_ses_hashes(self, request: wallet_protocol.RequestSESInfo) -> Message: # type: ignore[empty-body]
+ ...
+
+ @metadata.request(reply_types=[ProtocolMessageTypes.respond_fee_estimates])
+ async def request_fee_estimates(self, request: wallet_protocol.RequestFeeEstimates) -> Message: # type: ignore[empty-body]
+ ...
+
+ @metadata.request(
+ peer_required=True,
+ reply_types=[ProtocolMessageTypes.respond_remove_puzzle_subscriptions],
+ )
+ async def request_remove_puzzle_subscriptions( # type: ignore[empty-body]
+ self, request: wallet_protocol.RequestRemovePuzzleSubscriptions, peer: WSChiaConnection
+ ) -> Message: ...
+
+ @metadata.request(
+ peer_required=True,
+ reply_types=[ProtocolMessageTypes.respond_remove_coin_subscriptions],
+ )
+ async def request_remove_coin_subscriptions( # type: ignore[empty-body]
+ self, request: wallet_protocol.RequestRemoveCoinSubscriptions, peer: WSChiaConnection
+ ) -> Message: ...
+
+ @metadata.request(peer_required=True, reply_types=[ProtocolMessageTypes.respond_puzzle_state])
+ async def request_puzzle_state( # type: ignore[empty-body]
+ self, request: wallet_protocol.RequestPuzzleState, peer: WSChiaConnection
+ ) -> Message: ...
+
+ @metadata.request(peer_required=True, reply_types=[ProtocolMessageTypes.respond_coin_state])
+ async def request_coin_state(self, request: wallet_protocol.RequestCoinState, peer: WSChiaConnection) -> Message: # type: ignore[empty-body]
+ ...
+
+ @metadata.request(reply_types=[ProtocolMessageTypes.respond_cost_info])
+ async def request_cost_info(self, _request: wallet_protocol.RequestCostInfo) -> Optional[Message]: ...
diff --git a/chia/apis/harvester_api_schema.py b/chia/apis/harvester_api_schema.py
new file mode 100644
index 000000000000..7c37852382bf
--- /dev/null
+++ b/chia/apis/harvester_api_schema.py
@@ -0,0 +1,37 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, ClassVar, Optional, cast
+
+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, ApiSchemaProtocol
+from chia.server.ws_connection import WSChiaConnection
+
+
+class HarvesterApiSchema:
+ if TYPE_CHECKING:
+ _protocol_check: ApiSchemaProtocol = cast("HarvesterApiSchema", None)
+
+ metadata: ClassVar[ApiMetadata] = ApiMetadata()
+
+ @metadata.request(peer_required=True)
+ async def harvester_handshake(
+ self, harvester_handshake: harvester_protocol.HarvesterHandshake, peer: WSChiaConnection
+ ) -> None: ...
+
+ @metadata.request(peer_required=True, request_type=ProtocolMessageTypes.new_signage_point_harvester)
+ async def new_signage_point_harvester(
+ self, new_challenge: harvester_protocol.NewSignagePointHarvester2, peer: WSChiaConnection
+ ) -> None: ...
+
+ @metadata.request(reply_types=[ProtocolMessageTypes.respond_signatures])
+ async def request_signatures(self, request: harvester_protocol.RequestSignatures) -> Optional[Message]: ...
+
+ @metadata.request()
+ async def request_plots(self, _: harvester_protocol.RequestPlots) -> Message: # type: ignore[empty-body]
+ ...
+
+ @metadata.request()
+ async def plot_sync_response(self, response: PlotSyncResponse) -> None: ...
diff --git a/chia/apis/introducer_api_schema.py b/chia/apis/introducer_api_schema.py
new file mode 100644
index 000000000000..4e5ad08b0e29
--- /dev/null
+++ b/chia/apis/introducer_api_schema.py
@@ -0,0 +1,22 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, ClassVar, Optional, cast
+
+from chia.protocols.introducer_protocol import RequestPeersIntroducer
+from chia.protocols.outbound_message import Message
+from chia.server.api_protocol import ApiMetadata, ApiSchemaProtocol
+from chia.server.ws_connection import WSChiaConnection
+
+
+class IntroducerApiSchema:
+ if TYPE_CHECKING:
+ _protocol_check: ApiSchemaProtocol = cast("IntroducerApiSchema", None)
+
+ metadata: ClassVar[ApiMetadata] = ApiMetadata()
+
+ @metadata.request(peer_required=True)
+ async def request_peers_introducer(
+ self,
+ request: RequestPeersIntroducer,
+ peer: WSChiaConnection,
+ ) -> Optional[Message]: ...
diff --git a/chia/apis/solver_api_schema.py b/chia/apis/solver_api_schema.py
new file mode 100644
index 000000000000..a45ccdf8b887
--- /dev/null
+++ b/chia/apis/solver_api_schema.py
@@ -0,0 +1,21 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, ClassVar, Optional, cast
+
+from chia.protocols.outbound_message import Message
+from chia.protocols.protocol_message_types import ProtocolMessageTypes
+from chia.protocols.solver_protocol import SolverInfo
+from chia.server.api_protocol import ApiMetadata, ApiSchemaProtocol
+
+
+class SolverApiSchema:
+ if TYPE_CHECKING:
+ _protocol_check: ApiSchemaProtocol = cast("SolverApiSchema", None)
+
+ metadata: ClassVar[ApiMetadata] = ApiMetadata()
+
+ @metadata.request(peer_required=False, reply_types=[ProtocolMessageTypes.solution_response])
+ async def solve(
+ self,
+ request: SolverInfo,
+ ) -> Optional[Message]: ...
diff --git a/chia/apis/timelord_api_schema.py b/chia/apis/timelord_api_schema.py
new file mode 100644
index 000000000000..d67d08e2a8c9
--- /dev/null
+++ b/chia/apis/timelord_api_schema.py
@@ -0,0 +1,25 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, ClassVar, cast
+
+from chia.protocols import timelord_protocol
+from chia.protocols.timelord_protocol import NewPeakTimelord
+from chia.server.api_protocol import ApiMetadata, ApiSchemaProtocol
+
+
+class TimelordApiSchema:
+ if TYPE_CHECKING:
+ _protocol_check: ApiSchemaProtocol = cast("TimelordApiSchema", None)
+
+ metadata: ClassVar[ApiMetadata] = ApiMetadata()
+
+ @metadata.request()
+ async def new_peak_timelord(self, new_peak: NewPeakTimelord) -> None: ...
+
+ @metadata.request()
+ async def new_unfinished_block_timelord(
+ self, new_unfinished_block: timelord_protocol.NewUnfinishedBlockTimelord
+ ) -> None: ...
+
+ @metadata.request()
+ async def request_compact_proof_of_time(self, vdf_info: timelord_protocol.RequestCompactProofOfTime) -> None: ...
diff --git a/chia/apis/wallet_api_schema.py b/chia/apis/wallet_api_schema.py
new file mode 100644
index 000000000000..ee4779d6dead
--- /dev/null
+++ b/chia/apis/wallet_api_schema.py
@@ -0,0 +1,84 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, ClassVar, cast
+
+from chia_rs import RespondToPhUpdates
+
+from chia.protocols import full_node_protocol, introducer_protocol, wallet_protocol
+from chia.server.api_protocol import ApiMetadata, ApiSchemaProtocol
+from chia.server.ws_connection import WSChiaConnection
+
+
+class WalletNodeApiSchema:
+ if TYPE_CHECKING:
+ _protocol_check: ApiSchemaProtocol = cast("WalletNodeApiSchema", None)
+
+ metadata: ClassVar[ApiMetadata] = ApiMetadata()
+
+ @metadata.request(peer_required=True)
+ async def respond_removals(self, response: wallet_protocol.RespondRemovals, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request()
+ async def reject_additions_request(self, response: wallet_protocol.RejectAdditionsRequest) -> None: ...
+
+ @metadata.request(peer_required=True, execute_task=True)
+ async def new_peak_wallet(self, peak: wallet_protocol.NewPeakWallet, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request()
+ async def reject_header_request(self, response: wallet_protocol.RejectHeaderRequest) -> None: ...
+
+ @metadata.request()
+ async def respond_block_header(self, response: wallet_protocol.RespondBlockHeader) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def respond_additions(self, response: wallet_protocol.RespondAdditions, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request()
+ async def respond_proof_of_weight(self, response: full_node_protocol.RespondProofOfWeight) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def transaction_ack(self, ack: wallet_protocol.TransactionAck, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def respond_peers_introducer(
+ self, request: introducer_protocol.RespondPeersIntroducer, peer: WSChiaConnection
+ ) -> None: ...
+
+ @metadata.request(peer_required=True)
+ async def respond_peers(self, request: full_node_protocol.RespondPeers, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request()
+ async def respond_puzzle_solution(self, request: wallet_protocol.RespondPuzzleSolution) -> None: ...
+
+ @metadata.request()
+ async def reject_puzzle_solution(self, request: wallet_protocol.RejectPuzzleSolution) -> None: ...
+
+ @metadata.request()
+ async def respond_header_blocks(self, request: wallet_protocol.RespondHeaderBlocks) -> None: ...
+
+ @metadata.request()
+ async def respond_block_headers(self, request: wallet_protocol.RespondBlockHeaders) -> None: ...
+
+ @metadata.request()
+ async def reject_header_blocks(self, request: wallet_protocol.RejectHeaderBlocks) -> None: ...
+
+ @metadata.request()
+ async def reject_block_headers(self, request: wallet_protocol.RejectBlockHeaders) -> None: ...
+
+ @metadata.request(peer_required=True, execute_task=True)
+ async def coin_state_update(self, request: wallet_protocol.CoinStateUpdate, peer: WSChiaConnection) -> None: ...
+
+ @metadata.request() # type: ignore[type-var]
+ async def respond_to_ph_updates(self, request: RespondToPhUpdates) -> None: ...
+
+ @metadata.request()
+ async def respond_to_coin_updates(self, request: wallet_protocol.RespondToCoinUpdates) -> None: ...
+
+ @metadata.request()
+ async def respond_children(self, request: wallet_protocol.RespondChildren) -> None: ...
+
+ @metadata.request()
+ async def respond_ses_hashes(self, request: wallet_protocol.RespondSESInfo) -> None: ...
+
+ @metadata.request()
+ async def respond_blocks(self, request: full_node_protocol.RespondBlocks) -> None: ...
diff --git a/chia/cmds/dev/generate_schemas.py b/chia/cmds/dev/generate_schemas.py
new file mode 100644
index 000000000000..b7d43e92d99a
--- /dev/null
+++ b/chia/cmds/dev/generate_schemas.py
@@ -0,0 +1,271 @@
+from __future__ import annotations
+
+import subprocess
+import sys
+from pathlib import Path
+
+import click
+
+import chia
+from chia.data_layer.data_layer_api import DataLayerAPI
+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.solver.solver_api import SolverAPI
+from chia.timelord.timelord_api import TimelordAPI
+from chia.wallet.wallet_node_api import WalletNodeAPI
+
+
+class SchemaGenerationError(Exception):
+ """Base exception for schema generation errors."""
+
+
+class GitTrackingError(SchemaGenerationError):
+ """Exception raised when git tracking validation fails."""
+
+
+class FormattingError(SchemaGenerationError):
+ """Exception raised when file formatting fails."""
+
+
+class RegistryGenerationError(SchemaGenerationError):
+ """Exception raised when registry file generation fails."""
+
+
+# Registry of original implementation APIs for schema generation
+source_api_registry: dict[NodeType, type[ApiProtocol]] = {
+ NodeType.FULL_NODE: FullNodeAPI,
+ NodeType.WALLET: WalletNodeAPI,
+ NodeType.INTRODUCER: IntroducerAPI,
+ NodeType.TIMELORD: TimelordAPI,
+ NodeType.FARMER: FarmerAPI,
+ NodeType.HARVESTER: HarvesterAPI,
+ NodeType.SOLVER: SolverAPI,
+ NodeType.DATA_LAYER: DataLayerAPI,
+}
+
+d = set(source_api_registry.keys()).symmetric_difference(NodeType)
+if len(d) != 0:
+ raise Exception(f"NodeType and source_api_registry out of sync: {d}")
+
+api_class_names: dict[NodeType, str] = {
+ **{node_type: node_type.name.title().replace("_", "") for node_type in source_api_registry.keys()},
+ NodeType.WALLET: "WalletNode",
+ NodeType.FULL_NODE: "FullNode",
+}
+
+
+@click.command("generate-service-peer-schemas")
+@click.option(
+ "--output-dir",
+ "-o",
+ type=click.Path(exists=False, path_type=Path),
+ # avoiding chia.apis.__file__ directly can help with overwriting broken output files
+ default=Path(chia.__file__).parent.joinpath("apis"),
+ help="Output directory for generated schema files",
+)
+@click.option(
+ "--service",
+ "-s",
+ type=click.Choice([node_type.name.lower() for node_type in NodeType]),
+ multiple=True,
+ help="""Generate schema for specific service(s). Can be used multiple times.
+ If not specified, generates for all services.""",
+)
+@click.option(
+ "--format-output/--no-format",
+ default=True,
+ help="Run ruff format and check --fix on generated files",
+)
+@click.option(
+ "--generate-registry/--no-registry",
+ default=True,
+ help="Generate ApiProtocolRegistry file",
+)
+def generate_service_peer_schemas_cmd(
+ output_dir: Path,
+ service: tuple[str, ...],
+ format_output: bool,
+ generate_registry: bool,
+) -> None:
+ """Generate service peer API schemas from registered API protocols."""
+ output_dir.mkdir(parents=True, exist_ok=True)
+
+ # Determine which services to generate
+ if service:
+ selected_services = [NodeType[name.upper()] for name in service]
+ else:
+ selected_services = list(source_api_registry.keys())
+
+ generated_files = []
+ has_errors = False
+
+ for node_type in selected_services:
+ if node_type not in source_api_registry:
+ click.echo(f"Warning: No API registered for {node_type.name}", err=True)
+ has_errors = True
+ continue
+
+ api_class = source_api_registry[node_type]
+ output_file = output_dir.joinpath(f"{node_type.name.lower()}_api_schema.py")
+
+ # Generate schema content
+ try:
+ schema_content = api_class.metadata.create_schema(api_class)
+
+ # Write to file
+ with output_file.open("w", encoding="utf-8", newline="\n") as file:
+ file.write(schema_content)
+
+ generated_files.append(output_file)
+ click.echo(f"Generated {output_file} ({len(schema_content)} characters)")
+
+ except Exception as e:
+ click.echo(f"Error generating schema for {node_type.name}: {type(e).__name__} -> {e}", err=True)
+ has_errors = True
+ continue
+
+ # Generate ApiProtocolRegistry if requested
+ if generate_registry:
+ try:
+ registry_file = _generate_registry_file(output_dir, selected_services)
+ generated_files.append(registry_file)
+ except RegistryGenerationError as e:
+ click.echo(f"Registry generation failed: {e}", err=True)
+ has_errors = True
+
+ try:
+ # Verify all generated files are tracked by git
+ if generated_files:
+ _verify_git_tracking(generated_files)
+
+ # Format generated files if requested
+ if format_output and generated_files:
+ _format_files(generated_files)
+
+ except (GitTrackingError, FormattingError) as e:
+ click.echo(f"Error: {e}", err=True)
+ has_errors = True
+
+ if generated_files:
+ if has_errors:
+ click.echo(f"Generated {len(generated_files)} schema file(s) with errors", err=True)
+ sys.exit(1)
+ else:
+ click.echo(f"Successfully generated {len(generated_files)} schema file(s)")
+ else:
+ click.echo("No schema files were generated", err=True)
+ sys.exit(1)
+
+
+def _format_files(files: list[Path]) -> None:
+ """Format files, raising FormattingError if any errors occurred."""
+ formatting_errors = []
+
+ for file_path in files:
+ try:
+ # Run ruff format
+ subprocess.run(
+ [sys.executable, "-m", "ruff", "format", file_path], check=True, capture_output=True, text=True
+ )
+ click.echo(f" [OK] Formatted {file_path.name}")
+
+ except Exception as e:
+ error_msg = f"Failed to format {file_path.name}: {e}"
+ click.echo(f" [FAIL] {error_msg}", err=True)
+ formatting_errors.append(error_msg)
+ continue
+
+ try:
+ # Run ruff check --fix
+ subprocess.run(
+ [sys.executable, "-m", "ruff", "check", "--fix", file_path],
+ check=True,
+ capture_output=True,
+ text=True,
+ )
+ click.echo(f" [OK] No ruff check issues for {file_path.name}")
+
+ except Exception as e:
+ error_msg = f"Failed to run ruff check on {file_path.name}: {e}"
+ click.echo(f" [FAIL] {error_msg}", err=True)
+ formatting_errors.append(error_msg)
+
+ if formatting_errors:
+ raise FormattingError(f"Formatting failed for {len(formatting_errors)} file(s)")
+
+
+def _verify_git_tracking(files: list[Path]) -> None:
+ """Verify all generated files are tracked by git. Raises GitTrackingError if issues found."""
+ try:
+ # Get list of tracked files from git
+ result = subprocess.run(
+ ["git", "rev-parse", "--show-toplevel"], check=True, capture_output=True, text=True, cwd=Path.cwd()
+ )
+ repo_root = Path(result.stdout.strip())
+ result = subprocess.run(["git", "ls-files"], check=True, capture_output=True, text=True, cwd=repo_root)
+ tracked_files = {Path(line) for line in result.stdout.strip().splitlines()}
+
+ # Check each generated file
+ untracked_files = [file_path for file_path in files if file_path.relative_to(repo_root) not in tracked_files]
+
+ if len(untracked_files) == 0:
+ click.echo("All generated files are tracked by git")
+ else:
+ click.echo("ERROR: The following generated files are not tracked by git:", err=True)
+ for file_path in untracked_files:
+ click.echo(f" {file_path}", err=True)
+ click.echo("Please add these files to git before proceeding.", err=True)
+ raise GitTrackingError(f"Found {len(untracked_files)} untracked generated files")
+
+ except subprocess.CalledProcessError as e:
+ error_msg = f"Error checking git status: {e}"
+ click.echo(error_msg, err=True)
+ raise GitTrackingError(error_msg) from e
+
+
+def _generate_registry_file(output_dir: Path, selected_services: list[NodeType]) -> Path:
+ """Generate the ApiProtocolRegistry __init__.py file. Raises RegistryGenerationError on failure."""
+ registry_file = output_dir.joinpath("__init__.py")
+
+ try:
+ # Generate imports for each service
+ imports = []
+ registry_entries = []
+
+ for node_type in sorted(selected_services, key=lambda x: x.name):
+ schema_module = f"{node_type.name.lower()}_api_schema"
+
+ # Convert FARMER -> FarmerApiSchema, HARVESTER -> HarvesterApiSchema, etc.
+ schema_class = f"{api_class_names[node_type]}ApiSchema"
+
+ imports.append(f"from chia.apis.{schema_module} import {schema_class}")
+ registry_entries.append(f" NodeType.{node_type.name}: {schema_class},")
+
+ joined_imports = "\n".join(imports)
+ joined_registry_entries = "\n".join(registry_entries)
+ # Generate the complete file content
+ content = f"""from __future__ import annotations
+
+{joined_imports}
+from chia.protocols.outbound_message import NodeType
+from chia.server.api_protocol import ApiSchemaProtocol
+
+ApiProtocolRegistry: dict[NodeType, type[ApiSchemaProtocol]] = {{
+{joined_registry_entries}
+}}
+"""
+
+ with registry_file.open("w", encoding="utf-8", newline="\n") as file:
+ file.write(content)
+
+ click.echo(f"Generated {registry_file} ({len(content)} characters)")
+ return registry_file
+
+ except Exception as e:
+ error_msg = f"Error generating registry file: {e}"
+ click.echo(error_msg, err=True)
+ raise RegistryGenerationError(error_msg) from e
diff --git a/chia/cmds/dev/main.py b/chia/cmds/dev/main.py
index 1436096cf21d..8afcbeeecdb2 100644
--- a/chia/cmds/dev/main.py
+++ b/chia/cmds/dev/main.py
@@ -3,6 +3,7 @@
import click
from chia.cmds.dev.data import data_group
+from chia.cmds.dev.generate_schemas import generate_service_peer_schemas_cmd
from chia.cmds.dev.gh import gh_group
from chia.cmds.dev.installers import installers_group
from chia.cmds.dev.mempool import mempool_cmd
@@ -20,3 +21,4 @@ def dev_cmd(ctx: click.Context) -> None:
dev_cmd.add_command(gh_group)
dev_cmd.add_command(mempool_cmd)
dev_cmd.add_command(data_group)
+dev_cmd.add_command(generate_service_peer_schemas_cmd)
diff --git a/chia/server/api_protocol.py b/chia/server/api_protocol.py
index f12ac7c64eb5..b55de87ccd4a 100644
--- a/chia/server/api_protocol.py
+++ b/chia/server/api_protocol.py
@@ -1,7 +1,10 @@
from __future__ import annotations
import functools
+import inspect
import logging
+import re
+import textwrap
from collections.abc import Awaitable
from dataclasses import dataclass, field
from logging import Logger
@@ -14,10 +17,13 @@
from chia.util.streamable import Streamable
-class ApiProtocol(Protocol):
- log: Logger
+class ApiSchemaProtocol(Protocol):
metadata: ClassVar[ApiMetadata]
+
+class ApiProtocol(ApiSchemaProtocol, Protocol):
+ log: Logger
+
def ready(self) -> bool: ...
@@ -114,3 +120,98 @@ def wrapper(self: Self, original: Union[bytes, S], *args: P.args, **kwargs: P.kw
return wrapper
return inner
+
+ def create_schema(self, api: type[ApiProtocol]) -> str:
+ # ruff will fixup imports
+ import_lines = [
+ "from __future__ import annotations",
+ "from typing import TYPE_CHECKING, ClassVar, Optional, cast",
+ "from chia.protocols.outbound_message import Message",
+ "from chia.protocols.protocol_message_types import ProtocolMessageTypes",
+ "from chia.server.api_protocol import ApiMetadata, ApiSchemaProtocol",
+ "from chia.server.ws_connection import WSChiaConnection",
+ ]
+
+ schema_class_name = api.__name__.replace("API", "ApiSchema")
+ class_lines = (
+ textwrap.dedent(
+ f"""
+ class {schema_class_name}:
+ if TYPE_CHECKING:
+ _protocol_check: ApiSchemaProtocol = cast("{schema_class_name}", None)
+
+ metadata: ClassVar[ApiMetadata] = ApiMetadata()
+ """
+ )
+ .strip()
+ .splitlines()
+ )
+
+ method_lines = []
+
+ # First pass: collect method signatures and track usage
+ for request in self.message_type_to_request.values():
+ type_hints = get_type_hints(request.method)
+ source = inspect.getsource(request.method).splitlines()
+
+ # Collect the method signature lines
+ method_source = []
+ for line in source:
+ method_source.append(line)
+ if line.rstrip().endswith(":"):
+ break
+
+ this_method_schema_source = "\n".join(method_source)
+
+ # Check for types used in parameters that appear in the signature
+ for param_name, hint in type_hints.items():
+ if param_name in {"self", "return"}:
+ continue
+
+ module = hint.__module__
+ name = hint.__name__
+ protocol_match = re.match(r"(?Pchia\.protocols)\.(?P[^. ]+_protocol)", module)
+ # Import from chia.protocols.*
+ if protocol_match is not None:
+ base = protocol_match.group("base")
+ protocol = protocol_match.group("protocol")
+ if re.search(rf"(? ChiaServer:
log = logging.getLogger(name)
diff --git a/chia/server/start_service.py b/chia/server/start_service.py
index 2a23019f390d..154ab9bc64cb 100644
--- a/chia/server/start_service.py
+++ b/chia/server/start_service.py
@@ -17,7 +17,7 @@
from chia.protocols.outbound_message import NodeType
from chia.protocols.shared_protocol import default_capabilities
from chia.rpc.rpc_server import RpcApiProtocol, RpcServer, RpcServiceProtocol, start_rpc_server
-from chia.server.api_protocol import ApiProtocol
+from chia.server.api_protocol import ApiProtocol, ApiSchemaProtocol
from chia.server.chia_policy import set_chia_policy
from chia.server.server import ChiaServer
from chia.server.signal_handlers import SignalHandlers
@@ -62,7 +62,7 @@ def __init__(
network_id: str,
*,
config: dict[str, Any],
- class_for_type: dict[NodeType, type[ApiProtocol]],
+ class_for_type: dict[NodeType, type[ApiSchemaProtocol]],
upnp_ports: Optional[list[int]] = None,
connect_peers: Optional[set[UnresolvedPeerInfo]] = None,
on_connect_callback: Optional[Callable[[WSChiaConnection], Awaitable[None]]] = None,
diff --git a/chia/server/ws_connection.py b/chia/server/ws_connection.py
index 5950a06044cc..e80b2dbf8f91 100644
--- a/chia/server/ws_connection.py
+++ b/chia/server/ws_connection.py
@@ -28,7 +28,7 @@
RATE_LIMITER_BAN_SECONDS,
)
from chia.protocols.shared_protocol import Capability, Error, Handshake, protocol_version
-from chia.server.api_protocol import ApiMetadata, ApiProtocol
+from chia.server.api_protocol import ApiMetadata, ApiProtocol, ApiSchemaProtocol
from chia.server.capabilities import known_active_capabilities
from chia.server.rate_limits import RateLimiter
from chia.types.peer_info import PeerInfo
@@ -84,7 +84,7 @@ class WSChiaConnection:
close_callback: Optional[ConnectionClosedCallbackProtocol] = field(repr=False)
outbound_rate_limiter: RateLimiter
inbound_rate_limiter: RateLimiter
- class_for_type: dict[NodeType, type[ApiProtocol]] = field(repr=False)
+ class_for_type: dict[NodeType, type[ApiSchemaProtocol]] = field(repr=False)
# connection properties
is_outbound: bool
@@ -140,7 +140,7 @@ def create(
inbound_rate_limit_percent: int,
outbound_rate_limit_percent: int,
local_capabilities_for_handshake: list[tuple[uint16, str]],
- class_for_type: dict[NodeType, type[ApiProtocol]],
+ class_for_type: dict[NodeType, type[ApiSchemaProtocol]],
session: Optional[ClientSession] = None,
) -> WSChiaConnection:
assert ws._writer is not None
diff --git a/chia/timelord/timelord_api.py b/chia/timelord/timelord_api.py
index 956953ca5c99..9892df349992 100644
--- a/chia/timelord/timelord_api.py
+++ b/chia/timelord/timelord_api.py
@@ -121,7 +121,9 @@ def check_orphaned_unfinished_block(self, new_peak: NewPeakTimelord):
return False
@metadata.request()
- async def new_unfinished_block_timelord(self, new_unfinished_block: timelord_protocol.NewUnfinishedBlockTimelord):
+ async def new_unfinished_block_timelord(
+ self, new_unfinished_block: timelord_protocol.NewUnfinishedBlockTimelord
+ ) -> None:
if self.timelord.last_state is None:
return None
async with self.timelord.lock:
@@ -155,7 +157,7 @@ async def new_unfinished_block_timelord(self, new_unfinished_block: timelord_pro
log.debug(f"Non-overflow unfinished block, total {self.timelord.total_unfinished}")
@metadata.request()
- async def request_compact_proof_of_time(self, vdf_info: timelord_protocol.RequestCompactProofOfTime):
+ async def request_compact_proof_of_time(self, vdf_info: timelord_protocol.RequestCompactProofOfTime) -> None:
async with self.timelord.lock:
if not self.timelord.bluebox_mode:
return None
diff --git a/chia/wallet/wallet_node_api.py b/chia/wallet/wallet_node_api.py
index 5bfbbe7c3e4d..11462964347d 100644
--- a/chia/wallet/wallet_node_api.py
+++ b/chia/wallet/wallet_node_api.py
@@ -32,22 +32,24 @@ def ready(self) -> bool:
return self.wallet_node.logged_in
@metadata.request(peer_required=True)
- async def respond_removals(self, response: wallet_protocol.RespondRemovals, peer: WSChiaConnection):
+ async def respond_removals(self, response: wallet_protocol.RespondRemovals, peer: WSChiaConnection) -> None:
pass
- async def reject_removals_request(self, response: wallet_protocol.RejectRemovalsRequest, peer: WSChiaConnection):
+ async def reject_removals_request(
+ self, response: wallet_protocol.RejectRemovalsRequest, peer: WSChiaConnection
+ ) -> None:
"""
The full node has rejected our request for removals.
"""
@metadata.request()
- async def reject_additions_request(self, response: wallet_protocol.RejectAdditionsRequest):
+ async def reject_additions_request(self, response: wallet_protocol.RejectAdditionsRequest) -> None:
"""
The full node has rejected our request for additions.
"""
@metadata.request(peer_required=True, execute_task=True)
- async def new_peak_wallet(self, peak: wallet_protocol.NewPeakWallet, peer: WSChiaConnection):
+ async def new_peak_wallet(self, peak: wallet_protocol.NewPeakWallet, peer: WSChiaConnection) -> None:
"""
The full node sent as a new peak
"""
@@ -77,25 +79,25 @@ async def new_peak_wallet(self, peak: wallet_protocol.NewPeakWallet, peer: WSChi
await self.wallet_node.new_peak_queue.new_peak_wallet(peak, peer)
@metadata.request()
- async def reject_header_request(self, response: wallet_protocol.RejectHeaderRequest):
+ async def reject_header_request(self, response: wallet_protocol.RejectHeaderRequest) -> None:
"""
The full node has rejected our request for a header.
"""
@metadata.request()
- async def respond_block_header(self, response: wallet_protocol.RespondBlockHeader):
+ async def respond_block_header(self, response: wallet_protocol.RespondBlockHeader) -> None:
pass
@metadata.request(peer_required=True)
- async def respond_additions(self, response: wallet_protocol.RespondAdditions, peer: WSChiaConnection):
+ async def respond_additions(self, response: wallet_protocol.RespondAdditions, peer: WSChiaConnection) -> None:
pass
@metadata.request()
- async def respond_proof_of_weight(self, response: full_node_protocol.RespondProofOfWeight):
+ async def respond_proof_of_weight(self, response: full_node_protocol.RespondProofOfWeight) -> None:
pass
@metadata.request(peer_required=True)
- async def transaction_ack(self, ack: wallet_protocol.TransactionAck, peer: WSChiaConnection):
+ async def transaction_ack(self, ack: wallet_protocol.TransactionAck, peer: WSChiaConnection) -> None:
"""
This is an ack for our previous SendTransaction call. This removes the transaction from
the send queue if we have sent it to enough nodes.
@@ -137,7 +139,7 @@ async def transaction_ack(self, ack: wallet_protocol.TransactionAck, peer: WSChi
@metadata.request(peer_required=True)
async def respond_peers_introducer(
self, request: introducer_protocol.RespondPeersIntroducer, peer: WSChiaConnection
- ):
+ ) -> None:
if self.wallet_node.wallet_peers is not None:
await self.wallet_node.wallet_peers.add_peers(request.peer_list, peer.get_peer_info(), False)
@@ -145,7 +147,7 @@ async def respond_peers_introducer(
await peer.close()
@metadata.request(peer_required=True)
- async def respond_peers(self, request: full_node_protocol.RespondPeers, peer: WSChiaConnection):
+ async def respond_peers(self, request: full_node_protocol.RespondPeers, peer: WSChiaConnection) -> None:
if self.wallet_node.wallet_peers is None:
return None
@@ -155,50 +157,50 @@ async def respond_peers(self, request: full_node_protocol.RespondPeers, peer: WS
return None
@metadata.request()
- async def respond_puzzle_solution(self, request: wallet_protocol.RespondPuzzleSolution):
+ async def respond_puzzle_solution(self, request: wallet_protocol.RespondPuzzleSolution) -> None:
self.log.error("Unexpected message `respond_puzzle_solution`. Peer might be slow to respond")
@metadata.request()
- async def reject_puzzle_solution(self, request: wallet_protocol.RejectPuzzleSolution):
+ async def reject_puzzle_solution(self, request: wallet_protocol.RejectPuzzleSolution) -> None:
self.log.warning(f"Reject puzzle solution: {request}")
@metadata.request()
- async def respond_header_blocks(self, request: wallet_protocol.RespondHeaderBlocks):
+ async def respond_header_blocks(self, request: wallet_protocol.RespondHeaderBlocks) -> None:
pass
@metadata.request()
- async def respond_block_headers(self, request: wallet_protocol.RespondBlockHeaders):
+ async def respond_block_headers(self, request: wallet_protocol.RespondBlockHeaders) -> None:
pass
@metadata.request()
- async def reject_header_blocks(self, request: wallet_protocol.RejectHeaderBlocks):
+ async def reject_header_blocks(self, request: wallet_protocol.RejectHeaderBlocks) -> None:
self.log.warning(f"Reject header blocks: {request}")
@metadata.request()
- async def reject_block_headers(self, request: wallet_protocol.RejectBlockHeaders):
+ async def reject_block_headers(self, request: wallet_protocol.RejectBlockHeaders) -> None:
pass
@metadata.request(peer_required=True, execute_task=True)
- async def coin_state_update(self, request: wallet_protocol.CoinStateUpdate, peer: WSChiaConnection):
+ async def coin_state_update(self, request: wallet_protocol.CoinStateUpdate, peer: WSChiaConnection) -> None:
await self.wallet_node.new_peak_queue.full_node_state_updated(request, peer)
# TODO: Review this hinting issue around this rust type not being a Streamable
# subclass, as you might expect it wouldn't be. Maybe we can get the
# protocol working right back at the api.request definition.
@metadata.request() # type: ignore[type-var]
- async def respond_to_ph_updates(self, request: RespondToPhUpdates):
+ async def respond_to_ph_updates(self, request: RespondToPhUpdates) -> None:
pass
@metadata.request()
- async def respond_to_coin_updates(self, request: wallet_protocol.RespondToCoinUpdates):
+ async def respond_to_coin_updates(self, request: wallet_protocol.RespondToCoinUpdates) -> None:
pass
@metadata.request()
- async def respond_children(self, request: wallet_protocol.RespondChildren):
+ async def respond_children(self, request: wallet_protocol.RespondChildren) -> None:
pass
@metadata.request()
- async def respond_ses_hashes(self, request: wallet_protocol.RespondSESInfo):
+ async def respond_ses_hashes(self, request: wallet_protocol.RespondSESInfo) -> None:
pass
@metadata.request()
diff --git a/tach.toml b/tach.toml
index e05edea91695..30127d6d216c 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 },
]
@@ -212,6 +206,8 @@ depends_on = [
{ path = "chia.simulator", deprecated = false },
{ path = "chia.protocols", deprecated = false },
{ path = "chia.data_layer", deprecated = false },
+ { path = "chia.introducer", deprecated = false },
+ { path = "chia.timelord", deprecated = false },
]
[[modules]]