Skip to content

Commit 6231d99

Browse files
committed
On NewBlock notifications, redraw the solved puzzles.
1 parent f001d09 commit 6231d99

File tree

4 files changed

+74
-4
lines changed

4 files changed

+74
-4
lines changed

frontend/src/components/puzzles/PuzzleGame.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@ import { GameHeader } from "./GameHeader";
44
import { PuzzleSelectionView } from "./PuzzleSelectionView";
55
import { GamePlayingView } from "./GamePlayingView";
66
import { useState } from "react";
7+
import { useLineraNotifications } from "@/lib/linera/hooks/useLineraNotifications";
78

89
export function PuzzleGame() {
910
const game = usePuzzleGame();
1011
const { isPuzzleCompleted, isLoadingFromBlockchain: areCompletedPuzzlesLoading} = useCompletedPuzzles();
1112
const [showTutorial, setShowTutorial] = useState(true);
1213

14+
// Set up notification handling for React Query invalidation
15+
useLineraNotifications();
16+
17+
1318
const handleCellClick = (x: number, y: number) => {
1419
game.toggleCell(x, y);
1520
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { useEffect } from "react";
2+
import { useQueryClient } from "@tanstack/react-query";
3+
import { LineraService } from "../services/LineraService";
4+
import { useLineraInitialization } from "./useLineraQueries";
5+
6+
export function useLineraNotifications() {
7+
const queryClient = useQueryClient();
8+
const { data: initialized } = useLineraInitialization();
9+
10+
useEffect(() => {
11+
if (!initialized) return;
12+
13+
const lineraService = LineraService.getInstance();
14+
15+
// Set up notification handler
16+
lineraService.onNotification((notification) => {
17+
console.log("[GOL] Received notification:", notification);
18+
19+
// When a new block is created, it might contain puzzle completions
20+
// Invalidate the completed puzzles query to refetch
21+
queryClient.invalidateQueries({ queryKey: ["completedPuzzles"] });
22+
});
23+
24+
return () => {
25+
// Cleanup is handled by LineraService disconnect
26+
};
27+
}, [initialized, queryClient]);
28+
}

frontend/src/lib/linera/lib/linera-adapter.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export class LineraAdapter {
1818
private wasmInitPromise: Promise<unknown> | null = null;
1919
private connectPromise: Promise<LineraProvider> | null = null;
2020
private onConnectionChange?: () => void;
21+
private notificationCallbacks: Set<(notification: any) => void> = new Set();
2122

2223
private constructor() {}
2324

@@ -61,6 +62,20 @@ export class LineraAdapter {
6162
const client = await new Client(wallet, signer);
6263
console.log("✅ Linera wallet created successfully!");
6364

65+
client.onNotification(notification => {
66+
let newBlock = notification.reason.NewBlock;
67+
if (!newBlock) return;
68+
69+
// Notify all registered callbacks
70+
this.notificationCallbacks.forEach(callback => {
71+
try {
72+
callback(notification);
73+
} catch (error) {
74+
console.error("Error in notification callback:", error);
75+
}
76+
});
77+
});
78+
6479
this.provider = {
6580
client,
6681
wallet,
@@ -145,12 +160,26 @@ export class LineraAdapter {
145160
this.onConnectionChange = undefined;
146161
}
147162

163+
getAddress(): string {
164+
if (!this.provider) throw new Error("Provider not set");
165+
return this.provider.address;
166+
}
167+
148168
reset(): void {
149169
this.application = null;
150170
this.provider = null;
151171
this.connectPromise = null;
152172
this.onConnectionChange?.();
153173
}
174+
175+
onNewBlockNotification(callback: (notification: any) => void): () => void {
176+
this.notificationCallbacks.add(callback);
177+
178+
// Return unsubscribe function
179+
return () => {
180+
this.notificationCallbacks.delete(callback);
181+
};
182+
}
154183
}
155184

156185
// Export singleton instance

frontend/src/lib/linera/services/LineraService.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export class LineraService {
1313
private initialized = false;
1414
private isInitializing = false;
1515
private walletInfo: WalletInfo | null = null;
16+
private notificationUnsubscribe: (() => void) | null = null;
1617

1718
private constructor() {}
1819

@@ -187,6 +188,7 @@ export class LineraService {
187188
};
188189

189190
const result = await lineraAdapter.queryApplication<any>(query);
191+
console.log("[GOL] Query sent using address: ", lineraAdapter.getAddress());
190192
console.log("[GOL] Got response from getPuzzle", result);
191193

192194
if (result.errors) {
@@ -280,7 +282,8 @@ export class LineraService {
280282
};
281283

282284
const result = await lineraAdapter.queryApplication<any>(query);
283-
console.log("[GOL] Got completed puzzle IDs", result);
285+
// console.log("[GOL] Got completed puzzle IDs", result);
286+
console.log("[GOL] Query sent using address: ", lineraAdapter.getAddress());
284287

285288
if (result.errors) {
286289
console.error("GraphQL errors:", result.errors);
@@ -295,12 +298,17 @@ export class LineraService {
295298
}
296299
}
297300

298-
onNotification(_callback: (notification: any) => void): void {
299-
// Notifications not supported with Dynamic wallet yet
300-
console.warn("Notifications not yet supported with Dynamic wallet");
301+
onNotification(callback: (notification: any) => void): void {
302+
this.notificationUnsubscribe = lineraAdapter.onNewBlockNotification(callback);
301303
}
302304

303305
async disconnect(): Promise<void> {
306+
// Unsubscribe from notifications
307+
if (this.notificationUnsubscribe) {
308+
this.notificationUnsubscribe();
309+
this.notificationUnsubscribe = null;
310+
}
311+
304312
lineraAdapter.reset();
305313
this.initialized = false;
306314
this.isInitializing = false;

0 commit comments

Comments
 (0)