connect('127.0.0.1', 6379, 0.15); // Optional auth: $redis->auth('yourpass'); $redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_NONE); } } catch (Throwable $e) { $redis = null; // Fail open with no cache } })(); function cache_get(string $key): ?string { global $redis; if (!$redis) return null; try { return $redis->get($key) ?: null; } catch (Throwable $e) { return null; } } function cache_set(string $key, string $val, int $ttl): void { global $redis; if (!$redis) return; try { $ttl > 0 ? $redis->setex($key, $ttl, $val) : $redis->set($key, $val); } catch (Throwable $e) {} } /* * --------------------------- * Input handling * --------------------------- */ $roundParam = $_GET['round'] ?? '0'; $modeParam = $_GET['mode'] ?? ''; $gidParam = $_GET['gid'] ?? ''; $roundNumber = (int)preg_replace('/\D+/', '', (string)$roundParam); $mode = is_string($modeParam) ? $modeParam : ''; // Base64 GID can be large; decode safely $groupID = ''; if ($gidParam !== '') { $decoded = base64_decode((string)$gidParam, true); if ($decoded !== false) { $groupID = sanitize_string($decoded); } } if ($roundNumber === 0) { $algoURL = WW_FOLDER_PATH . 'algorand/'; redirectAndDieTo($algoURL); } /* * --------------------------- * Data fetch with caching * --------------------------- * * Strategy: * - Rounds are immutable, so cache forever for older rounds. * - For very recent rounds (age < 60s), use a short TTL. * - Optional nocache=1 will bypass cache for debugging. */ $nocache = isset($_GET['nocache']) && $_GET['nocache'] !== '0'; $cachePrefix = 'ag:round:v2:' . (defined('WW_CHAINNAME') ? WW_CHAINNAME : 'algo') . ':'; $roundKey = $cachePrefix . $roundNumber . ':json'; $roundData = null; $roundJson = null; if (!$nocache && ($roundJson = cache_get($roundKey))) { $roundData = json_decode($roundJson); } if ($roundData === null) { // This function presumably calls the Indexer/Node. // Make sure inside it you set low timeouts and disable HTTP exceptions. $roundData = getAlgorandRound($roundNumber); // Cache only if we got a valid response object with minimal shape if ($roundData && is_object($roundData)) { // If timestamp is present, decide TTL from age; else default $ts = isset($roundData->timestamp) ? (int)$roundData->timestamp : 0; $age = $ts > 0 ? (time() - $ts) : 999999; // Fresh round: tiny TTL (10s). Otherwise “forever-ish” (1 year) $ttl = ($age >= 60) ? 31536000 : 10; cache_set($roundKey, json_encode($roundData, JSON_UNESCAPED_SLASHES), $ttl); } } /* * --------------------------- * Group filter (in-PHP, cheap) * --------------------------- */ $transactionList = []; if ($roundData && isset($roundData->transactions) && is_array($roundData->transactions)) { $transactionList = $roundData->transactions; if ($groupID !== '' && str_contains($mode, 'group')) { $gid = $groupID; // closure capture // Filtering is CPU-cheap; safe to do per request. $transactionList = array_values(array_filter( $transactionList, static fn($obj) => is_object($obj) && isset($obj->group) && $obj->group === $gid )); } } /* * --------------------------- * Smart HTTP caching headers * --------------------------- * * Immutable for old rounds ⇒ let CDN/browser cache. * Recent rounds ⇒ short max-age. 304 handling for free CPU savings. */ $isFound = (bool)$roundData; $roundTs = ($isFound && isset($roundData->timestamp)) ? (int)$roundData->timestamp : 0; $age = $roundTs ? max(0, time() - $roundTs) : 999999; $isFresh = ($age < 60); // If client provides If-Modified-Since and this is old, honor 304 if ($roundTs > 0) { $lastMod = gmdate('D, d M Y H:i:s', $roundTs) . ' GMT'; header('Last-Modified: ' . $lastMod); if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { $ims = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']); if ($ims !== false && $ims >= $roundTs && !$nocache) { header('Cache-Control: public, max-age=31536000, immutable, stale-while-revalidate=30, stale-if-error=86400'); http_response_code(304); exit; } } } // Cache policy if ($nocache) { header('Cache-Control: no-store, no-cache, must-revalidate'); header('Pragma: no-cache'); } else { if ($isFresh) { header('Cache-Control: public, max-age=10, stale-while-revalidate=30, stale-if-error=86400'); } else { header('Cache-Control: public, max-age=31536000, immutable, stale-while-revalidate=30, stale-if-error=86400'); } } /* * --------------------------- * HTML output (avoid flush) * --------------------------- * * Avoiding flush() keeps the FPM worker from sitting on a socket, * which can reduce run-queue pressure under load. */ ?> <?= WW_CHAINNAME ?> Round <?= htmlspecialchars((string)$roundNumber, ENT_QUOTES) ?> Details - <?= WW_APPNAME ?>

Algorand Round

Displaying Transactions from Group ID:

Transaction Group Details

Group ID:
Date:
proposer)): ?>
Block proposed by:
proposer, 5, 'account', true) ?>
{'proposer-payout'})): ?>
Block Reward:
{'proposer-payout'}) ?>
Browse:

Round Not Found

Connect a wallet or enter a search to continue...