diff --git a/CHANGELOG.md b/CHANGELOG.md
index 092f85424a..ce3bac95da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
+- **Frontend**: Fixed a bug where user could reach a non-existent page
+ with a non-existent block height on the scan state page
+ ([#1966](https://github.com/o1-labs/mina-rust/pull/1966))
- **Frontend**: Fixed a bug where text was overlapping in the view.
([#1957](https://github.com/o1-labs/mina-rust/pull/1957))
- **CI**: fix version regex in build verification workflows to accept
diff --git a/frontend/src/app/features/snarks/scan-state/scan-state-toolbar/scan-state-toolbar.component.html b/frontend/src/app/features/snarks/scan-state/scan-state-toolbar/scan-state-toolbar.component.html
index 4588be19ed..24caf15b19 100644
--- a/frontend/src/app/features/snarks/scan-state/scan-state-toolbar/scan-state-toolbar.component.html
+++ b/frontend/src/app/features/snarks/scan-state/scan-state-toolbar/scan-state-toolbar.component.html
@@ -39,7 +39,9 @@
class="h-sm w-sm fx-row-full-cent"
[tooltip]="'Next block'"
[showDelay]="500"
- [disabled]="block?.trees.length === 0"
+ [disabled]="
+ block?.trees.length === 0 || block?.height >= maxBlockHeight
+ "
(click)="clearForm(); getHeight(block?.height + 1)"
>
navigate_next
diff --git a/frontend/src/app/features/snarks/scan-state/scan-state-toolbar/scan-state-toolbar.component.ts b/frontend/src/app/features/snarks/scan-state/scan-state-toolbar/scan-state-toolbar.component.ts
index 8bb3bd9492..8d0e191570 100644
--- a/frontend/src/app/features/snarks/scan-state/scan-state-toolbar/scan-state-toolbar.component.ts
+++ b/frontend/src/app/features/snarks/scan-state/scan-state-toolbar/scan-state-toolbar.component.ts
@@ -35,6 +35,8 @@ import {
import { FormBuilder, FormGroup } from '@angular/forms';
import { untilDestroyed } from '@ngneat/until-destroy';
import { NumberInput } from '@angular/cdk/coercion';
+import { AppSelectors } from '@app/app.state';
+import { AppNodeDetails } from '@shared/types/app/app-node-details.type';
@Component({
selector: 'mina-scan-state-toolbar',
@@ -54,6 +56,7 @@ export class ScanStateToolbarComponent
openSidePanel: boolean;
treeView: boolean;
highlightSnarkPool: boolean;
+ maxBlockHeight: number;
private inputRef: ElementRef;
private gotHeightFromForm: boolean;
@@ -76,6 +79,7 @@ export class ScanStateToolbarComponent
this.listenToSidePanelChange();
this.listenToTreeViewChange();
this.listenToHighlightSnarkPoolChange();
+ this.listenToActiveNodeDetailsChanges();
}
getHeight(height: NumberInput): void {
@@ -196,4 +200,11 @@ export class ScanStateToolbarComponent
toggleHighlightSnarkPool(): void {
this.dispatch(ScanStateHighlightSnarkPool);
}
+
+ private listenToActiveNodeDetailsChanges(): void {
+ this.select(AppSelectors.activeNodeDetails, (details: AppNodeDetails) => {
+ this.maxBlockHeight = details?.blockHeight;
+ this.detect();
+ });
+ }
}
diff --git a/frontend/src/app/features/snarks/scan-state/scan-state.service.ts b/frontend/src/app/features/snarks/scan-state/scan-state.service.ts
index 7b974a6b43..62b1a08c64 100644
--- a/frontend/src/app/features/snarks/scan-state/scan-state.service.ts
+++ b/frontend/src/app/features/snarks/scan-state/scan-state.service.ts
@@ -10,7 +10,7 @@ import {
tap,
} from 'rxjs';
import { ScanStateBlock } from '@shared/types/snarks/scan-state/scan-state-block.type';
-import { HttpClient } from '@angular/common/http';
+import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import {
ScanStateLeaf,
ScanStateLeafStatus,
@@ -32,7 +32,7 @@ export class ScanStateService {
) {}
getScanState(heightOrHash?: string | number): Observable {
- const url = this.rust.URL + '/scan-state/summary/' + (heightOrHash ?? '');
+ const url = `${this.rust.URL}/scan-state/summary/${heightOrHash ?? ''}`;
return this.http.get(url).pipe(
switchMap((response: any[]) => {
@@ -84,8 +84,22 @@ export class ScanStateService {
map(() => response),
);
}),
-
map((response: any) => this.mapScanState(response)),
+ catchError((err: HttpErrorResponse) => {
+ const response = err.error;
+ if (response === 'target block not found') {
+ return of({
+ hash: '',
+ height: 0,
+ globalSlot: 0,
+ transactions: [],
+ completedWorks: [],
+ workingSnarkers: [],
+ trees: [],
+ });
+ }
+ throw new Error(response);
+ }),
);
}