1use std::{marker::PhantomData, sync::Arc};
20
21use ethereum_types::H256;
22use jsonrpsee::core::RpcResult;
23use sp_api::{Core, ProvideRuntimeApi};
25use sp_blockchain::HeaderBackend;
26use sp_core::keccak_256;
27use sp_runtime::traits::Block as BlockT;
28use fc_rpc_core::{types::Bytes, Web3ApiServer};
30use fp_rpc::EthereumRuntimeRPCApi;
31
32use crate::internal_err;
33
34pub struct Web3<B, C> {
36 client: Arc<C>,
37 _marker: PhantomData<B>,
38}
39
40impl<B, C> Web3<B, C> {
41 pub fn new(client: Arc<C>) -> Self {
42 Self {
43 client,
44 _marker: PhantomData,
45 }
46 }
47}
48
49impl<B, C> Web3ApiServer for Web3<B, C>
50where
51 B: BlockT,
52 C: ProvideRuntimeApi<B>,
53 C::Api: EthereumRuntimeRPCApi<B>,
54 C: HeaderBackend<B> + 'static,
55{
56 fn client_version(&self) -> RpcResult<String> {
57 let hash = self.client.info().best_hash;
58 let version = self
59 .client
60 .runtime_api()
61 .version(hash)
62 .map_err(|err| internal_err(format!("fetch runtime version failed: {err:?}")))?;
63 Ok(format!(
64 "{spec_name}/v{spec_version}.{impl_version}/{pkg_name}-{pkg_version}",
65 spec_name = version.spec_name,
66 spec_version = version.spec_version,
67 impl_version = version.impl_version,
68 pkg_name = env!("CARGO_PKG_NAME"),
69 pkg_version = env!("CARGO_PKG_VERSION")
70 ))
71 }
72
73 fn sha3(&self, input: Bytes) -> RpcResult<H256> {
74 Ok(H256::from(keccak_256(&input.into_vec())))
75 }
76}