@@ -105,144 +105,127 @@ pub async fn run() -> anyhow::Result<()> {
105105 // V2 escrow accounts are in the network subgraph
106106 let escrow_v2_query_url_for_dips = Some ( config. subgraphs . network . config . query_url . clone ( ) ) ;
107107
108- // Configure router with escrow watchers based on Horizon mode
109- use indexer_config:: HorizonMode ;
110- let router = match config. horizon . mode {
111- HorizonMode :: Legacy => {
112- tracing:: info!( "Horizon mode: Legacy - using escrow accounts v1 only" ) ;
113- // Only create v1 watcher for legacy mode
114- let escrow_subgraph_v1 = create_subgraph_client (
115- http_client. clone ( ) ,
116- & config. graph_node ,
117- & config. subgraphs . escrow . config ,
118- )
119- . await ;
120-
121- let v1_watcher = indexer_monitor:: escrow_accounts_v1 (
122- escrow_subgraph_v1,
123- indexer_address,
124- config. subgraphs . escrow . config . syncing_interval_secs ,
125- true , // Reject thawing signers eagerly
126- )
127- . await
128- . expect ( "Error creating escrow_accounts_v1 channel" ) ;
129-
130- ServiceRouter :: builder ( )
131- . database ( database. clone ( ) )
132- . domain_separator ( domain_separator. clone ( ) )
133- . graph_node ( config. graph_node )
134- . http_client ( http_client)
135- . release ( release)
136- . indexer ( config. indexer )
137- . service ( config. service )
138- . blockchain ( config. blockchain )
139- . timestamp_buffer_secs ( config. tap . rav_request . timestamp_buffer_secs )
140- . network_subgraph ( network_subgraph, config. subgraphs . network )
141- . escrow_accounts_v1 ( v1_watcher)
142- . build ( )
108+ // Determine if we should check for Horizon contracts and potentially enable hybrid mode:
109+ // - If horizon.enabled = false: Pure legacy mode, no Horizon detection
110+ // - If horizon.enabled = true: Check if Horizon contracts are active in the network
111+ let is_horizon_active = if config. horizon . enabled {
112+ tracing:: info!( "Horizon migration support enabled - checking if Horizon contracts are active in the network" ) ;
113+ match indexer_monitor:: is_horizon_active ( network_subgraph) . await {
114+ Ok ( active) => {
115+ if active {
116+ tracing:: info!( "Horizon contracts detected in network subgraph - enabling hybrid migration mode" ) ;
117+ tracing:: info!( "Mode: Accept new V2 receipts only, continue processing existing V1 receipts for RAVs" ) ;
118+ } else {
119+ tracing:: info!( "Horizon contracts not yet active in network subgraph - remaining in legacy mode" ) ;
120+ }
121+ active
122+ }
123+ Err ( e) => {
124+ tracing:: warn!(
125+ "Failed to detect Horizon contracts: {}. Remaining in legacy mode." ,
126+ e
127+ ) ;
128+ false
129+ }
143130 }
144- HorizonMode :: Transition => {
145- tracing:: info!( "Horizon mode: Transition - using both escrow accounts v1 and v2" ) ;
146- // Create both watchers for transition mode
147- let escrow_subgraph_v1 = create_subgraph_client (
148- http_client. clone ( ) ,
149- & config. graph_node ,
150- & config. subgraphs . escrow . config ,
151- )
152- . await ;
131+ } else {
132+ tracing:: info!(
133+ "Horizon migration support disabled in configuration - using pure legacy mode"
134+ ) ;
135+ false
136+ } ;
153137
154- let v1_watcher = indexer_monitor:: escrow_accounts_v1 (
155- escrow_subgraph_v1,
156- indexer_address,
157- config. subgraphs . escrow . config . syncing_interval_secs ,
158- true , // Reject thawing signers eagerly
159- )
160- . await
161- . expect ( "Error creating escrow_accounts_v1 channel" ) ;
138+ // Configure router with escrow watchers based on automatic Horizon detection
139+ let router = if is_horizon_active {
140+ tracing:: info!( "Horizon contracts detected - using Horizon migration mode: V2 receipts only, but processing existing V1 receipts" ) ;
162141
163- // V2 escrow accounts are in the network subgraph
164- let v2_watcher = match indexer_monitor:: escrow_accounts_v2 (
165- network_subgraph,
166- indexer_address,
167- config. subgraphs . network . config . syncing_interval_secs ,
168- true , // Reject thawing signers eagerly
169- )
170- . await
171- {
172- Ok ( watcher) => {
173- tracing:: info!(
174- "V2 escrow accounts successfully initialized from network subgraph"
175- ) ;
176- watcher
177- }
178- Err ( e) => {
179- tracing:: warn!(
180- "V2 escrow accounts temporarily disabled - network subgraph query failed: {}. \
181- Indexer will only process V1 TAP receipts until this is fixed.",
182- e
183- ) ;
184- // Create empty watcher as fallback
185- indexer_monitor:: empty_escrow_accounts_watcher ( )
186- }
187- } ;
188-
189- ServiceRouter :: builder ( )
190- . database ( database. clone ( ) )
191- . domain_separator ( domain_separator. clone ( ) )
192- . graph_node ( config. graph_node )
193- . http_client ( http_client)
194- . release ( release)
195- . indexer ( config. indexer )
196- . service ( config. service )
197- . blockchain ( config. blockchain )
198- . timestamp_buffer_secs ( config. tap . rav_request . timestamp_buffer_secs )
199- . network_subgraph ( network_subgraph, config. subgraphs . network )
200- . escrow_accounts_v1 ( v1_watcher)
201- . escrow_accounts_v2 ( v2_watcher)
202- . build ( )
203- }
204- HorizonMode :: Full => {
205- tracing:: info!( "Horizon mode: Full - using escrow accounts v2 only" ) ;
206- // V2 escrow accounts are in the network subgraph
207- let v2_watcher = match indexer_monitor:: escrow_accounts_v2 (
208- network_subgraph,
209- indexer_address,
210- config. subgraphs . network . config . syncing_interval_secs ,
211- true , // Reject thawing signers eagerly
212- )
213- . await
214- {
215- Ok ( watcher) => {
216- tracing:: info!(
217- "V2 escrow accounts successfully initialized from network subgraph"
218- ) ;
219- watcher
220- }
221- Err ( e) => {
222- tracing:: warn!(
223- "V2 escrow accounts temporarily disabled - network subgraph query failed: {}. \
224- Indexer will only process V1 TAP receipts until this is fixed.",
225- e
226- ) ;
227- // Create empty watcher as fallback
228- indexer_monitor:: empty_escrow_accounts_watcher ( )
229- }
230- } ;
231-
232- ServiceRouter :: builder ( )
233- . database ( database. clone ( ) )
234- . domain_separator ( domain_separator. clone ( ) )
235- . graph_node ( config. graph_node )
236- . http_client ( http_client)
237- . release ( release)
238- . indexer ( config. indexer )
239- . service ( config. service )
240- . blockchain ( config. blockchain )
241- . timestamp_buffer_secs ( config. tap . rav_request . timestamp_buffer_secs )
242- . network_subgraph ( network_subgraph, config. subgraphs . network )
243- . escrow_accounts_v2 ( v2_watcher)
244- . build ( )
245- }
142+ // Create V1 escrow watcher for processing existing receipts
143+ let escrow_subgraph_v1 = create_subgraph_client (
144+ http_client. clone ( ) ,
145+ & config. graph_node ,
146+ & config. subgraphs . escrow . config ,
147+ )
148+ . await ;
149+
150+ let v1_watcher = indexer_monitor:: escrow_accounts_v1 (
151+ escrow_subgraph_v1,
152+ indexer_address,
153+ config. subgraphs . escrow . config . syncing_interval_secs ,
154+ true , // Reject thawing signers eagerly
155+ )
156+ . await
157+ . expect ( "Error creating escrow_accounts_v1 channel" ) ;
158+
159+ // Create V2 escrow watcher for new receipts (V2 escrow accounts are in the network subgraph)
160+ let v2_watcher = match indexer_monitor:: escrow_accounts_v2 (
161+ network_subgraph,
162+ indexer_address,
163+ config. subgraphs . network . config . syncing_interval_secs ,
164+ true , // Reject thawing signers eagerly
165+ )
166+ . await
167+ {
168+ Ok ( watcher) => {
169+ tracing:: info!( "V2 escrow accounts successfully initialized from network subgraph" ) ;
170+ watcher
171+ }
172+ Err ( e) => {
173+ tracing:: error!(
174+ "Failed to initialize V2 escrow accounts: {}. Service cannot continue." ,
175+ e
176+ ) ;
177+ std:: process:: exit ( 1 ) ;
178+ }
179+ } ;
180+
181+ ServiceRouter :: builder ( )
182+ . database ( database. clone ( ) )
183+ . domain_separator ( domain_separator. clone ( ) )
184+ . graph_node ( config. graph_node )
185+ . http_client ( http_client)
186+ . release ( release)
187+ . indexer ( config. indexer )
188+ . service ( config. service )
189+ . blockchain ( config. blockchain )
190+ . timestamp_buffer_secs ( config. tap . rav_request . timestamp_buffer_secs )
191+ . network_subgraph ( network_subgraph, config. subgraphs . network )
192+ . escrow_accounts_v1 ( v1_watcher)
193+ . escrow_accounts_v2 ( v2_watcher)
194+ . build ( )
195+ } else {
196+ tracing:: info!(
197+ "No Horizon contracts detected - using Legacy (V1) mode with escrow accounts v1 only"
198+ ) ;
199+ // Only create v1 watcher for legacy mode
200+ let escrow_subgraph_v1 = create_subgraph_client (
201+ http_client. clone ( ) ,
202+ & config. graph_node ,
203+ & config. subgraphs . escrow . config ,
204+ )
205+ . await ;
206+
207+ let v1_watcher = indexer_monitor:: escrow_accounts_v1 (
208+ escrow_subgraph_v1,
209+ indexer_address,
210+ config. subgraphs . escrow . config . syncing_interval_secs ,
211+ true , // Reject thawing signers eagerly
212+ )
213+ . await
214+ . expect ( "Error creating escrow_accounts_v1 channel" ) ;
215+
216+ ServiceRouter :: builder ( )
217+ . database ( database. clone ( ) )
218+ . domain_separator ( domain_separator. clone ( ) )
219+ . graph_node ( config. graph_node )
220+ . http_client ( http_client)
221+ . release ( release)
222+ . indexer ( config. indexer )
223+ . service ( config. service )
224+ . blockchain ( config. blockchain )
225+ . timestamp_buffer_secs ( config. tap . rav_request . timestamp_buffer_secs )
226+ . network_subgraph ( network_subgraph, config. subgraphs . network )
227+ . escrow_accounts_v1 ( v1_watcher)
228+ . build ( )
246229 } ;
247230
248231 serve_metrics ( config. metrics . get_socket_addr ( ) ) ;
0 commit comments