2025-11-06 03:08:43 -05:00
|
|
|
use std::{sync::Arc, ops::Deref, collections::HashSet};
|
|
|
|
|
|
|
|
|
|
use rand_core::{RngCore, OsRng};
|
|
|
|
|
|
|
|
|
|
use sp_core::Encode;
|
|
|
|
|
use sp_blockchain::{Error as BlockchainError, HeaderMetadata, HeaderBackend};
|
2025-11-06 20:12:37 -05:00
|
|
|
use sp_consensus::BlockStatus;
|
2025-11-06 03:08:43 -05:00
|
|
|
use sp_block_builder::BlockBuilder;
|
|
|
|
|
use sp_api::ProvideRuntimeApi;
|
2025-11-06 20:12:37 -05:00
|
|
|
use sc_client_api::BlockBackend;
|
2025-11-06 03:08:43 -05:00
|
|
|
|
|
|
|
|
use serai_abi::{primitives::prelude::*, SubstrateBlock as Block};
|
|
|
|
|
|
2025-11-13 04:50:54 -05:00
|
|
|
use serai_runtime::SeraiApi;
|
|
|
|
|
|
2025-11-06 03:08:43 -05:00
|
|
|
use jsonrpsee::RpcModule;
|
|
|
|
|
|
2025-11-14 03:35:38 -05:00
|
|
|
use super::utils::block_hash;
|
2025-11-13 04:50:54 -05:00
|
|
|
|
2025-11-06 03:08:43 -05:00
|
|
|
pub(crate) fn module<
|
|
|
|
|
C: 'static
|
|
|
|
|
+ Send
|
|
|
|
|
+ Sync
|
|
|
|
|
+ HeaderMetadata<Block, Error = BlockchainError>
|
|
|
|
|
+ HeaderBackend<Block>
|
|
|
|
|
+ BlockBackend<Block>
|
2025-11-13 04:50:54 -05:00
|
|
|
+ ProvideRuntimeApi<Block, Api: SeraiApi<Block>>,
|
2025-11-06 03:08:43 -05:00
|
|
|
>(
|
|
|
|
|
client: Arc<C>,
|
|
|
|
|
) -> Result<RpcModule<impl 'static + Send + Sync>, Box<dyn std::error::Error + Send + Sync>> {
|
|
|
|
|
let mut module = RpcModule::new(client);
|
2025-11-06 20:12:37 -05:00
|
|
|
|
2025-11-14 03:35:38 -05:00
|
|
|
module.register_method("blockchain/latest_finalized_block_number", |_params, client, _ext| {
|
2025-11-08 05:06:28 -05:00
|
|
|
client.info().finalized_number
|
|
|
|
|
});
|
|
|
|
|
|
2025-11-14 03:35:38 -05:00
|
|
|
module.register_method("blockchain/is_finalized", |params, client, _ext| {
|
2025-11-13 04:50:54 -05:00
|
|
|
let block_hash = block_hash(&**client, ¶ms)?;
|
2025-11-06 20:12:37 -05:00
|
|
|
let finalized = client.info().finalized_number;
|
|
|
|
|
let Ok(Some(number)) = client.number(block_hash) else {
|
|
|
|
|
return Err(jsonrpsee::types::error::ErrorObjectOwned::owned(
|
|
|
|
|
-2,
|
|
|
|
|
"failed to fetch block's number",
|
|
|
|
|
Option::<()>::None,
|
|
|
|
|
));
|
|
|
|
|
};
|
|
|
|
|
let Ok(status) = client.block_status(block_hash) else {
|
|
|
|
|
return Err(jsonrpsee::types::error::ErrorObjectOwned::owned(
|
|
|
|
|
-3,
|
|
|
|
|
"failed to fetch block's status",
|
|
|
|
|
Option::<()>::None,
|
|
|
|
|
));
|
|
|
|
|
};
|
|
|
|
|
Ok(
|
|
|
|
|
matches!(status, BlockStatus::InChainWithState | BlockStatus::InChainPruned) &&
|
|
|
|
|
(number <= finalized),
|
|
|
|
|
)
|
|
|
|
|
})?;
|
|
|
|
|
|
2025-11-14 03:35:38 -05:00
|
|
|
module.register_method("blockchain/block", |params, client, _ext| {
|
2025-11-13 04:50:54 -05:00
|
|
|
let block_hash = block_hash(&**client, ¶ms)?;
|
2025-11-06 20:12:37 -05:00
|
|
|
let Ok(Some(block)) = client.block(block_hash) else {
|
2025-11-06 03:08:43 -05:00
|
|
|
return Err(jsonrpsee::types::error::ErrorObjectOwned::owned(
|
|
|
|
|
-2,
|
|
|
|
|
"couldn't find requested block",
|
|
|
|
|
Option::<()>::None,
|
|
|
|
|
));
|
|
|
|
|
};
|
2025-11-06 20:12:37 -05:00
|
|
|
|
|
|
|
|
Ok(hex::encode(borsh::to_vec(&serai_abi::Block::from(block.block)).unwrap()))
|
2025-11-06 03:08:43 -05:00
|
|
|
})?;
|
2025-11-06 20:12:37 -05:00
|
|
|
|
2025-11-14 03:35:38 -05:00
|
|
|
module.register_method("blockchain/events", |params, client, _ext| {
|
2025-11-13 04:50:54 -05:00
|
|
|
let block_hash = block_hash(&**client, ¶ms)?;
|
|
|
|
|
let Ok(events) = client.runtime_api().events(block_hash) else {
|
|
|
|
|
return Err(jsonrpsee::types::error::ErrorObjectOwned::owned(
|
|
|
|
|
-2,
|
|
|
|
|
"couldn't fetch the events for the requested block",
|
|
|
|
|
Option::<()>::None,
|
|
|
|
|
));
|
|
|
|
|
};
|
|
|
|
|
Ok(events.into_iter().map(hex::encode).collect::<Vec<String>>())
|
|
|
|
|
})?;
|
|
|
|
|
|
2025-11-06 03:08:43 -05:00
|
|
|
Ok(module)
|
|
|
|
|
}
|