@@ -7,8 +7,9 @@ import { parse } from "toml"
77import { IntentFiller } from "@/core/filler"
88import { BasicFiller } from "@/strategies/basic"
99import { FXFiller } from "@/strategies/fx"
10+ import type { AerodromePoolConfig , OutputFundingConfig } from "@/funding/types"
1011import { ConfirmationPolicy , FillerBpsPolicy , FillerPricePolicy } from "@/config/interpolated-curve"
11- import { ChainConfig , FillerConfig , HexString } from "@hyperbridge/sdk"
12+ import { ChainConfig , Chains , FillerConfig , HexString , getConfigByStateMachineId } from "@hyperbridge/sdk"
1213import {
1314 FillerConfigService ,
1415 UserProvidedChainConfig ,
@@ -69,6 +70,11 @@ interface BasicStrategyConfig {
6970 confirmationPolicies : Record < string , ChainConfirmationPolicy>
7071}
7172
73+ /** TOML row for an Aerodrome pool; `chain` is the state machine id e.g. `EVM-8453`. */
74+ interface AerodromePoolToml extends AerodromePoolConfig {
75+ chain: string
76+ }
77+
7278interface FxStrategyConfig {
7379 type: "hyperfx"
7480 /**
@@ -95,6 +101,12 @@ interface FxStrategyConfig {
95101 exoticTokenAddresses: Record < string , HexString >
96102 /** Optional per-chain confirmation policies for cross-chain orders */
97103 confirmationPolicies ? : Record < string , ChainConfirmationPolicy >
104+ /** Optional Aerodrome LP funding for destination-chain outputs */
105+ outputFunding ?: {
106+ aerodrome ?: {
107+ pools ?: AerodromePoolToml [ ]
108+ }
109+ }
98110}
99111
100112type StrategyConfig = BasicStrategyConfig | FxStrategyConfig
@@ -366,6 +378,7 @@ program
366378 const configuredSigner = initializeSignerFromToml ( config . simplex . signer )
367379 const chainClientManager = new ChainClientManager ( configService , configuredSigner )
368380 const runtimeSigner : SigningAccount = chainClientManager . getSigner ( )
381+
369382 const contractService = new ContractInteractionService (
370383 chainClientManager ,
371384 configService ,
@@ -408,6 +421,24 @@ program
408421 "No confirmationPolicies configured for hyperfx strategy; cross-chain orders will be skipped" ,
409422 )
410423 }
424+ let outputFunding : OutputFundingConfig | undefined
425+ if ( strategyConfig . outputFunding ?. aerodrome ?. pools ?. length ) {
426+ const poolsByChain : Record < string , AerodromePoolConfig [ ] > = { }
427+ for ( const row of strategyConfig . outputFunding . aerodrome . pools ) {
428+ const chain = row . chain
429+ if ( ! poolsByChain [ chain ] ) poolsByChain [ chain ] = [ ]
430+ poolsByChain [ chain ] . push ( {
431+ pair : row . pair ,
432+ gauge : row . gauge ,
433+ } )
434+ }
435+
436+ outputFunding = {
437+ aerodrome : {
438+ poolsByChain,
439+ } ,
440+ }
441+ }
411442 return new FXFiller (
412443 runtimeSigner ,
413444 configService ,
@@ -418,13 +449,38 @@ program
418449 strategyConfig . maxOrderUsd ,
419450 strategyConfig . exoticTokenAddresses ,
420451 fxConfirmationPolicy ,
452+ outputFunding ,
421453 )
422454 }
423455 default :
424456 throw new Error ( `Unknown strategy type: ${ ( strategyConfig as StrategyConfig ) . type } ` )
425457 }
426458 } )
427459
460+ // Initialise FXFiller strategies
461+ for ( const strategy of strategies ) {
462+ if ( strategy instanceof FXFiller ) {
463+ logger . info ( "Hydrating Aerodrome funding state..." )
464+ await strategy . initialise ( )
465+ }
466+ }
467+
468+ // Set up periodic Aerodrome state refresh (~12s)
469+ const FUNDING_REFRESH_INTERVAL_MS = 12_000
470+ const fundingRefreshTimers : ReturnType < typeof setInterval > [] = []
471+ for (const strategy of strategies) {
472+ if ( strategy instanceof FXFiller ) {
473+ const timer = setInterval ( async ( ) => {
474+ try {
475+ await strategy . refreshFundingState ( )
476+ } catch ( err ) {
477+ logger . error ( { err } , "Aerodrome funding state refresh failed" )
478+ }
479+ } , FUNDING_REFRESH_INTERVAL_MS )
480+ fundingRefreshTimers . push ( timer )
481+ }
482+ }
483+
428484 // Initialize rebalancing service only if fully configured
429485 let rebalancingService : RebalancingService | undefined
430486 const rebalancingConfig = configService . getRebalancingConfig ( )
@@ -516,19 +572,18 @@ program
516572 )
517573
518574 // Handle graceful shutdown
519- process . on ( "SIGINT" , async ( ) => {
520- logger . warn ( "Shutting down intent filler (SIGINT)..." )
575+ const shutdown = async ( signal : string ) = > {
576+ logger . warn ( `Shutting down intent filler (${ signal } )...` )
577+ for ( const timer of fundingRefreshTimers ) {
578+ clearInterval ( timer )
579+ }
521580 metrics ?. stop ( )
522581 await intentFiller . stop ( )
523582 process . exit ( 0 )
524- } )
583+ }
525584
526- process . on ( "SIGTERM" , async ( ) => {
527- logger . warn ( "Shutting down intent filler (SIGTERM)..." )
528- metrics ?. stop ( )
529- await intentFiller . stop ( )
530- process . exit ( 0 )
531- } )
585+ process . on ( "SIGINT" , ( ) => shutdown ( "SIGINT" ) )
586+ process . on ( "SIGTERM" , ( ) => shutdown ( "SIGTERM" ) )
532587 } catch ( error ) {
533588 // Use console.error for initial startup errors since logger might not be configured yet
534589 console . error ( "Failed to start filler:" , error )
@@ -622,6 +677,29 @@ function validateConfig(config: FillerTomlConfig): void {
622677 }
623678
624679 if ( strategy . type === "hyperfx" ) {
680+ if ( strategy . outputFunding ?. aerodrome ) {
681+ if ( strategy . outputFunding . aerodrome . pools ?. length ) {
682+ for ( const pool of strategy . outputFunding . aerodrome . pools ) {
683+ if ( ! pool . chain ?. trim ( ) ) {
684+ throw new Error (
685+ "Each Aerodrome outputFunding pool must have a non-empty 'chain' (e.g. EVM-8453)" ,
686+ )
687+ }
688+ if ( ! pool . pair ) {
689+ throw new Error ( "Each Aerodrome pool must include a 'pair' address" )
690+ }
691+ const chainCfg = getConfigByStateMachineId ( pool . chain as Chains )
692+ const aerodromeRouter = chainCfg ?. addresses . AerodromeRouter
693+ const z = aerodromeRouter ?. toLowerCase ( )
694+ if ( ! z || z === "0x" || z === "0x0000000000000000000000000000000000000000" ) {
695+ throw new Error (
696+ `Aerodrome pool ${ pool . pair } uses chain ${ pool . chain } but SDK chain config has no addresses.AerodromeRouter for that chain` ,
697+ )
698+ }
699+ }
700+ }
701+ }
702+
625703 // Validate bid price curve
626704 if (
627705 ! strategy . bidPriceCurve ||
0 commit comments