@@ -2,7 +2,11 @@ import { LRUCache } from 'lru-cache'
22import { Observer , Subscription } from 'rxjs'
33import { ago } from '@/common/time.js'
44import { createTypedEventEmitter , deepCamelize } from '@/common/util.js'
5- import { WormholeIds , WormholeSupportedNetworks } from '@/services/agents/wormhole/types/chain.js'
5+ import {
6+ urnToChainId ,
7+ WormholeIds ,
8+ WormholeSupportedNetworks ,
9+ } from '@/services/agents/wormhole/types/chain.js'
610import { WormholescanClient } from '@/services/networking/apis/wormhole/client.js'
711import { makeWormholeLevelStorage } from '@/services/networking/apis/wormhole/storage.js'
812import {
@@ -26,6 +30,8 @@ import { mapOperationToJourney, NewJourneyWithAssets } from './mappers/index.js'
2630import { TelemetryWormholeEventEmitter } from './telemetry/events.js'
2731import { collectWormholeStats , wormholeAgentMetrics } from './telemetry/metrics.js'
2832
33+ const OPERATION_LOOKUP_WINDOW_MS = 5 * 60_000
34+
2935function isChainSupported ( chainId ?: number ) : boolean {
3036 return chainId === undefined || WormholeSupportedNetworks . includes ( chainId )
3137}
@@ -157,25 +163,57 @@ export class WormholeAgent implements Agent {
157163
158164 this . #log. info ( '[agent:%s] rechecking pending journeys...' , this . id )
159165
160- const pendings = await this . #repository. getJourneysByStatus ( 'sent' , [ ...WormholeProtocols ] )
166+ const pendings = await this . #repository. getJourneysByStatus ( [ 'sent' , 'waiting' ] , [ ...WormholeProtocols ] )
161167
162168 for ( const journey of pendings ) {
163- try {
169+ await this . #recheckJourney( journey )
170+ }
171+
172+ this . #log. info ( '[agent:%s] pending recheck complete (%s items)' , this . id , pendings . length )
173+ }
174+
175+ async #recheckJourney( journey : Journey ) {
176+ try {
177+ if ( this . #watcher. isWormholeId ( journey . correlation_id ) ) {
164178 const op = await this . #watcher. fetchOperationById ( journey . correlation_id )
165179 if ( op ) {
166180 await this . #onOperation( op )
167181 }
168- } catch ( err ) {
169- this . #log. warn (
170- err ,
171- '[agent:%s] failed to recheck pending journey %s' ,
172- this . id ,
173- journey . correlation_id ,
174- )
182+ return
175183 }
184+
185+ await this . #recheckBySearch( journey )
186+ } catch ( err ) {
187+ this . #log. warn ( err , '[agent:%s] failed to recheck pending journey %s' , this . id , journey . correlation_id )
176188 }
189+ }
177190
178- this . #log. info ( '[agent:%s] pending recheck complete (%s items)' , this . id , pendings . length )
191+ async #recheckBySearch( journey : Journey ) {
192+ const isOriginLeg = isWormholeProtocol ( journey . origin_protocol )
193+ const address = isOriginLeg ? journey . from : journey . to
194+
195+ const stop = journey . stops . find ( ( s : any ) => s . type === 'wormhole' || isWormholeProtocol ( s . type ) )
196+ if ( ! stop ) {
197+ return
198+ }
199+
200+ const sourceChain = urnToChainId ( stop . from . chainId )
201+ const targetChain = urnToChainId ( stop . to . chainId )
202+
203+ const from = new Date ( journey . sent_at - OPERATION_LOOKUP_WINDOW_MS ) . toISOString ( )
204+ const to = new Date ( journey . sent_at + OPERATION_LOOKUP_WINDOW_MS ) . toISOString ( )
205+
206+ const { operations } = await this . #watcher. fetchOperations ( {
207+ address,
208+ sourceChain,
209+ targetChain,
210+ from,
211+ to,
212+ } )
213+
214+ for ( const op of operations ) {
215+ await this . #onOperation( op )
216+ }
179217 }
180218
181219 #onOperation = async ( op : WormholeOperation ) => {
@@ -192,8 +230,13 @@ export class WormholeAgent implements Agent {
192230 const journey = mapOperationToJourney ( op , this . #repository. generateTripId . bind ( this ) )
193231 if ( this . #replacedJourneysCache. has ( journey . correlation_id ) ) {
194232 this . #log. info ( '[agent:%s] Journey replaced for correlationId: %s' , this . id , journey . correlation_id )
233+ return
195234 }
196235 const existingTrips = await this . #repository. getJourneyByTripId ( journey . trip_id )
236+ if ( existingTrips . every ( ( t ) => t . status === 'received' ) ) {
237+ this . #log. info ( '[agent:%s] Existing trips already completed: %s' , this . id , journey . trip_id )
238+ return
239+ }
197240 const existingJourney = await this . #repository. getJourneyByCorrelationId ( journey . correlation_id )
198241 if ( ! existingJourney ) {
199242 const { assets, ...journeyWithoutAssets } = journey
@@ -213,7 +256,7 @@ export class WormholeAgent implements Agent {
213256 return
214257 }
215258
216- if ( existingJourney . status !== journey . status ) {
259+ if ( existingJourney . status !== 'received' && existingJourney . status !== journey . status ) {
217260 const update : JourneyUpdate = { }
218261 if ( isWormholeProtocol ( journey . destination_protocol ) || journey . status !== 'received' ) {
219262 update . status = journey . status
0 commit comments