pool_sync_mantle/
pool_sync.rs1use alloy::providers::Provider;
8use alloy::providers::ProviderBuilder;
9use std::collections::HashMap;
10use std::sync::Arc;
11
12use crate::builder::PoolSyncBuilder;
13use crate::cache::{read_cache_file, write_cache_file, PoolCache};
14use crate::chain::Chain;
15use crate::errors::*;
16use crate::pools::*;
17use crate::rpc::Rpc;
18
19pub struct PoolSync {
21 pub fetchers: HashMap<PoolType, Arc<dyn PoolFetcher>>,
23 pub chain: Chain,
25 pub rate_limit: u64,
27 pub start_block: Option<u64>,
29 pub end_block: Option<u64>,
31}
32
33impl PoolSync {
34 pub fn builder() -> PoolSyncBuilder {
36 PoolSyncBuilder::default()
37 }
38
39 pub async fn sync_pools(&self) -> Result<(Vec<Pool>, u64), PoolSyncError> {
41 dotenv::dotenv().ok();
43
44 let archive = Arc::new(
46 ProviderBuilder::new()
47 .network::<alloy::network::AnyNetwork>()
48 .on_http(std::env::var("ARCHIVE").unwrap().parse().unwrap()),
49 );
50
51 let full = Arc::new(
53 ProviderBuilder::new()
54 .network::<alloy::network::AnyNetwork>()
55 .on_http(std::env::var("FULL").unwrap().parse().unwrap()),
56 );
57
58 std::fs::create_dir_all("cache").unwrap();
60
61 let mut pool_caches: Vec<PoolCache> = self
63 .fetchers
64 .keys()
65 .map(|pool_type| read_cache_file(pool_type, self.chain).unwrap())
66 .collect();
67
68 let mut fully_synced = false;
69 let mut last_synced_block = 0;
70
71 while !fully_synced {
72 fully_synced = true;
73
74 let end_block = match self.end_block {
76 Some(end_block) => end_block,
77 None => full.get_block_number().await.unwrap(),
78 };
79
80 println!("\n🔄 开始同步轮次 - 目标区块: {}, 上次同步: {}", end_block, last_synced_block);
81 println!("📊 协议状态:");
82 for cache in &pool_caches {
83 println!(" {} - 缓存池数: {}, 上次同步区块: {}",
84 cache.pool_type, cache.pools.len(), cache.last_synced_block);
85 }
86 println!("");
87
88 for cache in &mut pool_caches {
89 let start_block = match self.start_block {
91 Some(start_block) => {
92 if cache.last_synced_block < start_block {
94 start_block
95 } else {
96 cache.last_synced_block + 1
97 }
98 },
99 None => cache.last_synced_block + 1,
100 };
101
102 if start_block <= end_block {
103 fully_synced = false;
104
105 println!("🔗 正在同步 {} 协议 (区块 {} → {})", cache.pool_type, start_block, end_block);
106
107 let fetcher = self.fetchers[&cache.pool_type].clone();
108
109 let pool_addrs = Rpc::fetch_pool_addrs(
111 start_block,
112 end_block,
113 archive.clone(),
114 fetcher.clone(),
115 self.chain,
116 self.rate_limit,
117 )
118 .await
119 .expect(
120 "Failed to fetch pool addresses. Exiting due to having inconclusive state",
121 );
122
123 let mut new_pools = Rpc::populate_pools(
125 pool_addrs,
126 full.clone(),
127 cache.pool_type,
128 fetcher.clone(),
129 self.rate_limit,
130 self.chain,
131 )
132 .await
133 .expect("Failed to sync pool data, Exiting due to haveing inconclusive state");
134
135
136 Rpc::populate_liquidity(
138 start_block,
139 end_block,
140 &mut cache.pools,
141 archive.clone(),
142 cache.pool_type,
143 self.rate_limit,
144 cache.is_initial_sync,
145 )
146 .await
147 .expect("Failed to populate liquidity information, Exiting due to having inconclusive state");
148
149 if !new_pools.is_empty() {
151 Rpc::populate_liquidity(
152 start_block,
153 end_block,
154 &mut new_pools,
155 archive.clone(),
156 cache.pool_type,
157 self.rate_limit,
158 true,
159 )
160 .await
161 .expect("Failed to populate liquidity information, Exiting due to having inconclusive state");
162 }
163
164
165 let new_pools_count = new_pools.len();
167 cache.pools.extend(new_pools);
168
169
170 cache.last_synced_block = end_block;
172 last_synced_block = end_block;
173 cache.is_initial_sync = false;
174
175 println!("✅ {} 协议同步完成 - 总池数: {}, 新增池: {}, 同步至区块: {}",
176 cache.pool_type, cache.pools.len(), new_pools_count, end_block);
177 } else {
178 println!("⏭️ {} 协议已为最新状态 (区块 {})", cache.pool_type, cache.last_synced_block);
179 }
180 }
181
182 if let Some(target_end_block) = self.end_block {
184 let all_synced_to_target = pool_caches.iter().all(|cache| cache.last_synced_block >= target_end_block);
185 if all_synced_to_target {
186 println!("🎯 所有协议已同步至目标区块 {}, 同步完成!", target_end_block);
187 break;
188 }
189 }
190 }
191
192 println!("\n🎉 所有协议同步完成! 最终状态:");
193 for cache in &pool_caches {
194 println!(" {} - 总池数: {}, 最新区块: {}",
195 cache.pool_type, cache.pools.len(), cache.last_synced_block);
196 }
197 println!("💾 正在保存缓存文件...\n");
198
199 pool_caches
201 .iter()
202 .for_each(|cache| write_cache_file(cache, self.chain).unwrap());
203
204 Ok((
206 pool_caches
207 .into_iter()
208 .flat_map(|cache| cache.pools)
209 .collect(),
210 last_synced_block,
211 ))
212 }
213}
214