@@ -105,6 +105,19 @@ function getDeltaColor(percent: number): string {
105105 return 'text-muted' ;
106106}
107107
108+ /** Detect backend syncing errors (503 from the proxy). */
109+ function isSyncingError ( error : unknown ) : boolean {
110+ if ( error instanceof Error ) {
111+ return error . message . includes ( 'currently syncing' ) ;
112+ }
113+
114+ if ( typeof error === 'string' ) {
115+ return error . includes ( 'currently syncing' ) ;
116+ }
117+
118+ return false ;
119+ }
120+
108121function calculateAggregateStats ( results : BlockSimulationResult [ ] ) : AggregateStats {
109122 const stats = results . reduce (
110123 ( acc , result ) => {
@@ -824,14 +837,37 @@ export function SimulatePage(): JSX.Element {
824837 Loading gas parameters...
825838 </ div >
826839 ) }
827- { defaultsError && (
828- < Alert
829- variant = "error"
830- description = { `Error loading gas schedule: ${ defaultsError . message } ` }
831- accentBorder
832- className = "mt-3"
833- />
834- ) }
840+ { defaultsError &&
841+ ( isSyncingError ( defaultsError ) ? (
842+ < div
843+ className = "mt-3 overflow-hidden rounded-sm border border-amber-400/30 dark:border-amber-500/20"
844+ role = "status"
845+ aria-live = "polite"
846+ >
847+ < div className = "flex items-start gap-3 bg-amber-50/80 p-3.5 dark:bg-amber-500/5" >
848+ < div className = "flex size-8 shrink-0 items-center justify-center rounded-xs bg-amber-100 dark:bg-amber-500/15" >
849+ < ArrowPathIcon
850+ className = "size-4 animate-spin text-amber-600 dark:text-amber-400"
851+ style = { { animationDuration : '2s' } }
852+ />
853+ </ div >
854+ < div className = "min-w-0 flex-1" >
855+ < p className = "text-sm/5 font-medium text-amber-800 dark:text-amber-200" > Backend nodes are syncing</ p >
856+ < p className = "mt-0.5 text-xs/4 text-amber-700/70 dark:text-amber-300/60" >
857+ The nodes serving this network are catching up with the chain. Check back shortly and try again.
858+ </ p >
859+ </ div >
860+ </ div >
861+ < div className = "h-px animate-pulse bg-linear-to-r from-transparent via-amber-400/50 to-transparent" />
862+ </ div >
863+ ) : (
864+ < Alert
865+ variant = "error"
866+ description = { `Error loading gas schedule: ${ defaultsError . message } ` }
867+ accentBorder
868+ className = "mt-3"
869+ />
870+ ) ) }
835871 { gasWarning && modifiedCount === 0 && (
836872 < Alert
837873 variant = "warning"
@@ -946,7 +982,37 @@ export function SimulatePage(): JSX.Element {
946982 { /* Error */ }
947983 { simState . status === 'error' && (
948984 < div className = "mb-4" >
949- < Alert variant = "error" title = "Simulation failed" description = { simState . error ?? 'Unknown error' } />
985+ { isSyncingError ( simState . error ) ? (
986+ < Card className = "overflow-hidden" >
987+ < div className = "flex items-start gap-4 p-5" role = "status" aria-live = "polite" >
988+ < div className = "relative flex size-10 shrink-0 items-center justify-center" >
989+ < div
990+ className = "absolute inset-0 animate-ping rounded-full bg-amber-400/15"
991+ style = { { animationDuration : '3s' } }
992+ />
993+ < div className = "flex size-10 items-center justify-center rounded-full bg-amber-100 dark:bg-amber-500/10" >
994+ < ArrowPathIcon
995+ className = "size-5 animate-spin text-amber-500 dark:text-amber-400"
996+ style = { { animationDuration : '2s' } }
997+ />
998+ </ div >
999+ </ div >
1000+ < div className = "min-w-0 flex-1" >
1001+ < h3 className = "text-sm font-semibold text-foreground" > Backend Syncing</ h3 >
1002+ < p className = "mt-1 text-sm/5 text-muted" >
1003+ The simulation was interrupted because all backend nodes for this network are currently syncing with
1004+ the chain.
1005+ { simState . completedBlocks > 0 &&
1006+ ` ${ simState . completedBlocks } of ${ simState . totalBlocks } blocks completed before the interruption.` } { ' ' }
1007+ Check back shortly and try again.
1008+ </ p >
1009+ </ div >
1010+ </ div >
1011+ < div className = "h-px animate-pulse bg-linear-to-r from-transparent via-amber-400/40 to-transparent" />
1012+ </ Card >
1013+ ) : (
1014+ < Alert variant = "error" title = "Simulation failed" description = { simState . error ?? 'Unknown error' } />
1015+ ) }
9501016 </ div >
9511017 ) }
9521018
0 commit comments