Background
The split between foreign-chain-rpc-interfaces and foreign-chain-inspector does not follow a consistent rule. Four symptoms:
Clients are split across both crates. foreign-chain-rpc-interfaces owns ReqwestAptosClient and GrpcSuiClient, but the third transport's constructor, build_http_client, lives in crates/foreign-chain-inspector/src/lib.rs:510.
The auth adapter is copy-pasted four times. RpcAuthentication sits in crates/foreign-chain-inspector/src/lib.rs:276, downstream of the clients, so ReqwestAptosClient::new and GrpcSuiClient::new cannot accept it and take a raw Option<(HeaderName, HeaderValue)> instead. The identical conversion match appears at crates/node/src/providers/verify_foreign_tx.rs:94 and :111, and crates/foreign-chain-health-check/src/lib.rs:157 and :336. build_http_client, the one constructor in the inspector, does take RpcAuthentication.
Fingerprint policy lives in the wire crate. ChainIdResponse::canonical_text (evm, starknet) and GetBlockHashResponse::canonical_text (bitcoin) are called only from NetworkFingerprintInspector::canonical_fingerprint, which fabricates a response type out of an operator-written config string to reach them: ChainIdResponse(fingerprint.to_owned()).canonical_text() at crates/foreign-chain-inspector/src/evm/inspector.rs:59, same shape at bitcoin/inspector.rs:48 and starknet/inspector.rs:43. Aptos already uses a free canonical_chain_id_text(&str).
Two consumers depend on the wire crate for no reason. Of 40 public items in foreign-chain-rpc-interfaces, only ReqwestAptosClient, GrpcSuiClient and SuiRpcClient are used outside foreign-chain-inspector, and only because the inspector never re-exports the clients while its public types name them (AptosInspector<ReqwestAptosClient>, SuiInspector<GrpcSuiClient> at crates/node/src/providers/verify_foreign_tx.rs:52-53). For EVM/Bitcoin/Starknet the inspector already solves this by re-exporting http_client and owning the builder.
Acceptance Criteria
foreign-chain-rpc-interfaces owns transport and wire decoding only: all three client constructors live there, RpcAuthentication moves down into it, and all three constructors take it.
- Fingerprint canonicalization is a free function over
&str per chain module, so no caller constructs an RPC response type from a config string. Receiver style is consistent across chains (evm and bitcoin take self, starknet takes &self today).
foreign-chain-inspector is the cluster's public face: it re-exports or builds the Aptos and Sui clients, and neither mpc-node nor foreign-chain-health-check depends on foreign-chain-rpc-interfaces directly.
- The four copies of the
RpcAuthentication to header-pair match are gone.
- Both crates carry a
//! stating what they own and what they deliberately do not.
Background
The split between
foreign-chain-rpc-interfacesandforeign-chain-inspectordoes not follow a consistent rule. Four symptoms:Clients are split across both crates.
foreign-chain-rpc-interfacesownsReqwestAptosClientandGrpcSuiClient, but the third transport's constructor,build_http_client, lives incrates/foreign-chain-inspector/src/lib.rs:510.The auth adapter is copy-pasted four times.
RpcAuthenticationsits incrates/foreign-chain-inspector/src/lib.rs:276, downstream of the clients, soReqwestAptosClient::newandGrpcSuiClient::newcannot accept it and take a rawOption<(HeaderName, HeaderValue)>instead. The identical conversion match appears atcrates/node/src/providers/verify_foreign_tx.rs:94and:111, andcrates/foreign-chain-health-check/src/lib.rs:157and:336.build_http_client, the one constructor in the inspector, does takeRpcAuthentication.Fingerprint policy lives in the wire crate.
ChainIdResponse::canonical_text(evm, starknet) andGetBlockHashResponse::canonical_text(bitcoin) are called only fromNetworkFingerprintInspector::canonical_fingerprint, which fabricates a response type out of an operator-written config string to reach them:ChainIdResponse(fingerprint.to_owned()).canonical_text()atcrates/foreign-chain-inspector/src/evm/inspector.rs:59, same shape atbitcoin/inspector.rs:48andstarknet/inspector.rs:43. Aptos already uses a freecanonical_chain_id_text(&str).Two consumers depend on the wire crate for no reason. Of 40 public items in
foreign-chain-rpc-interfaces, onlyReqwestAptosClient,GrpcSuiClientandSuiRpcClientare used outsideforeign-chain-inspector, and only because the inspector never re-exports the clients while its public types name them (AptosInspector<ReqwestAptosClient>,SuiInspector<GrpcSuiClient>atcrates/node/src/providers/verify_foreign_tx.rs:52-53). For EVM/Bitcoin/Starknet the inspector already solves this by re-exportinghttp_clientand owning the builder.Acceptance Criteria
foreign-chain-rpc-interfacesowns transport and wire decoding only: all three client constructors live there,RpcAuthenticationmoves down into it, and all three constructors take it.&strper chain module, so no caller constructs an RPC response type from a config string. Receiver style is consistent across chains (evmandbitcointakeself,starknettakes&selftoday).foreign-chain-inspectoris the cluster's public face: it re-exports or builds the Aptos and Sui clients, and neithermpc-nodenorforeign-chain-health-checkdepends onforeign-chain-rpc-interfacesdirectly.RpcAuthenticationto header-pair match are gone.//!stating what they own and what they deliberately do not.