// GET /api/status?sigs=[,…]&until=: pending, confirmed, // failed or expired for each (expired: the blockhash ran out before it landed, so it never will). import { blockHeight, txStatuses, type Ctx } from '../../server/card.ts' import { ConfigError, configFailure, contextFor, gate, type CardEnv } from '../../server/env.ts' import { allowInMemory, clientIp, failure, json } from '../../server/http.ts' // Near expiry every pending poll needs the block height; one reading serves this isolate for two // seconds (a height two seconds old only delays "expired" by as much). Only the finished value is // shared, never the pending read: Workers cancel a request's work when its client leaves, which // would leave every other request waiting on that read hanging. const HEIGHT_TTL_MS = 2000 let height: { at: number; value: number } | null = null const sharedHeight = (ctx: Ctx) => async (): Promise => { if (height && Date.now() - height.at < HEIGHT_TTL_MS) return height.value const value = await blockHeight(ctx) height = { at: Date.now(), value } return value } export const onRequestGet: PagesFunction = async ({ request, env }) => { const params = new URL(request.url).searchParams if ([...params.keys()].some((k) => k !== 'sigs' && k !== 'until')) return json({ error: 'Expected ?sigs=&until=.', code: 'bad-request' }, 400) // The app polls every 2 s per purchase (30 a minute); phone carriers put many people behind one IP. const refused = await gate(request, env, 'status', 240, 'memory') if (refused) return refused try { // Statuses never depend on the pause flags, so polls skip reading them. const ctx = await contextFor(env, { flags: false }) // The history search is the costly call; a buyer needs about one per purchase, so a client // gets 20 a minute (beyond that, "pending" until the next minute). const mayDeepSearch = () => allowInMemory('status-deep', clientIp(request), 20, env.RATE_SALT) return json(await txStatuses(ctx, params.get('sigs'), params.get('until'), sharedHeight(ctx), mayDeepSearch)) } catch (err) { return err instanceof ConfigError ? configFailure(err) : failure(err, 'status') } }