use async_trait::async_trait;
use std::sync::Arc;
use super::{
BaseBlockHeader, BlockHeader, ChaintracksInfo, HeightRange, InsertHeaderResult, LiveBlockHeader,
};
use crate::error::WalletResult;
use crate::types::Chain;
pub type HeaderCallback = Box<dyn Fn(BlockHeader) + Send + Sync>;
pub type ReorgCallback = Box<dyn Fn(ReorgEvent) + Send + Sync>;
#[derive(Debug, Clone)]
pub struct ReorgEvent {
pub depth: u32,
pub old_tip: BlockHeader,
pub new_tip: BlockHeader,
pub deactivated_headers: Vec<BlockHeader>,
}
#[derive(Debug, Clone)]
pub struct BulkSyncResult {
pub live_headers: Vec<BlockHeader>,
pub done: bool,
}
#[derive(Debug, Clone)]
pub struct ChaintracksOptions {
pub chain: Chain,
pub live_height_threshold: u32,
pub reorg_height_threshold: u32,
pub add_live_recursion_limit: u32,
pub batch_insert_limit: u32,
pub bulk_migration_chunk_size: u32,
pub require_ingestors: bool,
pub readonly: bool,
}
impl ChaintracksOptions {
pub fn default_mainnet() -> Self {
Self {
chain: Chain::Main,
live_height_threshold: 2000,
reorg_height_threshold: 400,
add_live_recursion_limit: 36,
batch_insert_limit: 400,
bulk_migration_chunk_size: 500,
require_ingestors: false,
readonly: false,
}
}
pub fn default_testnet() -> Self {
Self {
chain: Chain::Test,
live_height_threshold: 2000,
reorg_height_threshold: 400,
add_live_recursion_limit: 36,
batch_insert_limit: 400,
bulk_migration_chunk_size: 500,
require_ingestors: false,
readonly: false,
}
}
}
impl Default for ChaintracksOptions {
fn default() -> Self {
Self::default_mainnet()
}
}
#[async_trait]
pub trait ChaintracksStorageQuery: Send + Sync {
fn chain(&self) -> Chain;
fn live_height_threshold(&self) -> u32;
fn reorg_height_threshold(&self) -> u32;
async fn find_chain_tip_header(&self) -> WalletResult<Option<LiveBlockHeader>>;
async fn find_chain_tip_hash(&self) -> WalletResult<Option<String>>;
async fn find_header_for_height(&self, height: u32) -> WalletResult<Option<BlockHeader>>;
async fn find_live_header_for_block_hash(
&self,
hash: &str,
) -> WalletResult<Option<LiveBlockHeader>>;
async fn find_live_header_for_merkle_root(
&self,
merkle_root: &str,
) -> WalletResult<Option<LiveBlockHeader>>;
async fn get_headers_bytes(&self, height: u32, count: u32) -> WalletResult<Vec<u8>>;
async fn get_live_headers(&self) -> WalletResult<Vec<LiveBlockHeader>>;
async fn get_available_height_ranges(&self) -> WalletResult<Vec<HeightRange>>;
async fn find_live_height_range(&self) -> WalletResult<Option<HeightRange>>;
async fn find_common_ancestor(
&self,
h1: &LiveBlockHeader,
h2: &LiveBlockHeader,
) -> WalletResult<Option<LiveBlockHeader>>;
async fn find_reorg_depth(&self, new_header: &LiveBlockHeader) -> WalletResult<u32>;
}
#[async_trait]
pub trait ChaintracksStorageIngest: ChaintracksStorageQuery {
async fn insert_header(&self, header: LiveBlockHeader) -> WalletResult<InsertHeaderResult>;
async fn prune_live_block_headers(&self, active_tip_height: u32) -> WalletResult<u32>;
async fn migrate_live_to_bulk(&self, count: u32) -> WalletResult<u32>;
async fn delete_older_live_block_headers(&self, max_height: u32) -> WalletResult<u32>;
async fn make_available(&self) -> WalletResult<()>;
async fn migrate_latest(&self) -> WalletResult<()>;
async fn drop_all_data(&self) -> WalletResult<()>;
async fn destroy(&self) -> WalletResult<()>;
}
#[async_trait]
pub trait ChaintracksStorage: ChaintracksStorageIngest {
fn storage_type(&self) -> &str;
async fn is_available(&self) -> bool;
}
#[async_trait]
pub trait ChaintracksClient: Send + Sync {
async fn get_chain(&self) -> Chain;
async fn get_info(&self) -> WalletResult<ChaintracksInfo>;
async fn get_present_height(&self) -> WalletResult<u32>;
async fn is_listening(&self) -> bool;
async fn is_synchronized(&self) -> bool;
async fn current_height(&self) -> WalletResult<u32>;
async fn find_header_for_height(&self, height: u32) -> WalletResult<Option<BlockHeader>>;
async fn find_header_for_block_hash(&self, hash: &str) -> WalletResult<Option<BlockHeader>>;
async fn find_chain_tip_header(&self) -> WalletResult<Option<BlockHeader>>;
async fn find_chain_tip_hash(&self) -> WalletResult<Option<String>>;
async fn is_valid_root_for_height(&self, root: &str, height: u32) -> WalletResult<bool>;
async fn get_headers(&self, height: u32, count: u32) -> WalletResult<String>;
async fn add_header(&self, header: BaseBlockHeader) -> WalletResult<()>;
async fn start_listening(&self) -> WalletResult<()>;
async fn listening(&self) -> WalletResult<()>;
async fn subscribe_headers(&self, callback: HeaderCallback) -> WalletResult<String>;
async fn subscribe_reorgs(&self, callback: ReorgCallback) -> WalletResult<String>;
async fn unsubscribe(&self, subscription_id: &str) -> WalletResult<bool>;
}
#[async_trait]
pub trait ChaintracksManagement: ChaintracksClient {
async fn destroy(&self) -> WalletResult<()>;
async fn validate(&self) -> WalletResult<bool>;
async fn export_bulk_headers(
&self,
folder: &str,
headers_per_file: Option<u32>,
max_height: Option<u32>,
) -> WalletResult<()>;
}
#[async_trait]
pub trait BulkIngestor: Send + Sync {
async fn get_present_height(&self) -> WalletResult<u32>;
async fn synchronize(&self) -> WalletResult<BulkSyncResult>;
async fn fetch_headers(&self) -> WalletResult<BulkSyncResult>;
async fn set_storage(&self, storage: Arc<dyn ChaintracksStorageIngest>) -> WalletResult<()>;
async fn shutdown(&self) -> WalletResult<()>;
}
#[async_trait]
pub trait LiveIngestor: Send + Sync {
async fn get_header_by_hash(&self, hash: &str) -> WalletResult<Option<BlockHeader>>;
async fn start_listening(&self, live_headers: &mut Vec<BlockHeader>) -> WalletResult<()>;
async fn stop_listening(&self) -> WalletResult<()>;
async fn set_storage(&self, storage: Arc<dyn ChaintracksStorageIngest>) -> WalletResult<()>;
async fn shutdown(&self) -> WalletResult<()>;
}